Author: wmb
Date: 2008-08-29 11:22:06 +0200 (Fri, 29 Aug 2008)
New Revision: 906
Modified:
cpu/x86/pc/neptune/addrs.fth
cpu/x86/pc/neptune/config.fth
cpu/x86/pc/neptune/romreset.bth
Log:
Neptune - memory autoconfiguration.
Modified: cpu/x86/pc/neptune/addrs.fth
===================================================================
--- cpu/x86/pc/neptune/addrs.fth 2008-08-29 09:21:31 UTC (rev 905)
+++ cpu/x86/pc/neptune/addrs.fth 2008-08-29 09:22:06 UTC (rev 906)
@@ -38,6 +38,8 @@
h# f.…
[View More]0008 constant resume-entry
h# f.0800 constant resume-data
+h# 80.0000 constant fb-size
+
\ If you change these, also change {g/l}xmsrs.fth and {g/l}xearly.fth
h# fd00.0000 constant fw-map-base
h# ffc0.0000 constant fw-map-limit
Modified: cpu/x86/pc/neptune/config.fth
===================================================================
--- cpu/x86/pc/neptune/config.fth 2008-08-29 09:21:31 UTC (rev 905)
+++ cpu/x86/pc/neptune/config.fth 2008-08-29 09:22:06 UTC (rev 906)
@@ -34,6 +34,7 @@
create use-elf
create lx-pll-autoconfig \ enable pll autoconfiguration from bootstrap pin
+create mem-autoconfig \ autoconfigure different memory sizes
create use-memtest86
\ create use-timestamp-counter \ Use CPU's timestamp counter for timing ...
Modified: cpu/x86/pc/neptune/romreset.bth
===================================================================
--- cpu/x86/pc/neptune/romreset.bth 2008-08-29 09:21:31 UTC (rev 905)
+++ cpu/x86/pc/neptune/romreset.bth 2008-08-29 09:22:06 UTC (rev 906)
@@ -46,7 +46,79 @@
fload ${BP}/cpu/x86/pc/romfind.fth \ find-dropin
+label dramtry
+ char b 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+ h# 12 # al mov al h# 80 # out
+
+ \ Unmask CKE1 and CKE0
+ 1000. 2000001d set-msr \ MC_CFCLK_DBG Clear 300 bits, don't tristate in IDLE
+
+ \ Reset memory controller
+ 20000018 rmsr \ MC_CF07_DATA
+ 2 bitset 20000018 wmsr
+ 2 bitclr 20000018 wmsr
+
+ \ Enable DLL, load Extended Mode Register by set and clear PROG_DRAM
+ 10000001 bitset 20000018 wmsr
+ 10000001 bitclr 20000018 wmsr
+
+ \ Reset DLL (bit 27 is undocumented in GX datasheet, but is in the LX one)
+ 08000001 bitset 20000018 wmsr
+ 08000001 bitclr 20000018 wmsr
+
+ \ Here we are supposed to wait 200 SDCLK cycles to let the DLL settle.
+ \ That is approximately 2 uS. The ROM instruction access is so slow that
+ \ anything we do will take quite a bit longer than that, so we just let the
+ \ "rmsr, bitset" sequence take care of the time delay for us.
+
+ \ In the following sequence of writes the 2000.0018 MSR, we
+ \ take advantage of the fact that the existing value stays
+ \ in EAX/EDX, so we don't have to re-read the value.
+
+ \ Generate 2 refresh requests. The refresh queue is 8 deep, and we
+ \ need to make sure 2 refreshes hit the chips, so we have to issue
+ \ 10 requests to the queue. According to the GX datasheet, we don't
+ \ have to clear the REF_TST bit (8) explicitly between writes
+ 20000018 rmsr 8 bitset
+ wrmsr wrmsr wrmsr wrmsr wrmsr wrmsr wrmsr wrmsr wrmsr wrmsr
+ 8 bitclr
+
+ \ Load Mode Register
+ 1 bitset 20000018 wmsr
+ 1 bitclr 20000018 wmsr
+
+ \ Earlier code has set up an MSR so the fxxxx address range hits memory
+
+ \ The RAM DLL needs a write to lock on
+ ax h# ffff0 #) mov
+
+ \ The following simple test determines how much memory is present.
+
+ \ Set locations just below power-of-two boundaries to the boundary value
+ h# 4000.0000 # si mov \ Start address
+ h# 400.0000 # di mov \ End address
+ si ax mov
+ begin
+ ax -4 [ax] mov \ Set e.g. loc 3ffffffc to 40000000
+ 1 # ax shr \ Step down to the next power of two
+ di ax cmp \ Stop at 64 MiB; can't buy RAMs that small
+ <= until
+
+ \ Look for a location that contains the expected data
+ si ax mov
+ begin
+ -4 [ax] bx mov
+ bx ax cmp = if esp jmp then \ Exit if found
+ 1 # ax shr
+ di ax cmp
+ <= until
+
+ \ Not found, return 0
+ ax ax xor
+ esp jmp
+
label startup
+ long-offsets on
h# 10 # al mov al h# 80 # out
\ The next few MSRs allow us to access the 5536
@@ -102,6 +174,208 @@
\ sdram_initialize,generic_sdram.c
\ sdram_set_spdregisters(),auto.c
+[ifdef] mem-autoconfig
+ 20000000.000fff00. 10000020 set-msr \ memory - 0..fffff
+
+ \ We start with address map settings for the largest possible memory configuration,
+ \ probe and test the memory, then reduce the values as necessary
+ \ We'll deal with DMA and the frame buffer after memory has been sized.
+
+ 25ffe002.14000000. 1808 set-msr \ 2M ROM at ffe0.0000, system RAM limit at 4000.0000
+ 2000003f.fff00100. 10000028 set-msr \ Top of memory at 3fff.ffff
+
+ 00000000.2814d352. 00001981 set-msr \ Memory delay values
+ 00000000.1068334d. 00001982 set-msr \ Memory delay values
+ 00000106.83104104. 00001983 set-msr \ Memory delay values
+ 00000000.00000001. 00001980 set-msr \ Enable memory delays
+
+ \ Init the SDRAMs
+ \ sdram_enable,src/northbridge/amd/gx2/raminit.c
+
+ \ Clock gating for PMode
+ \ Clocks always on in mode 1, hardware gating in mode 0
+\ 20002004 rmsr 4 bitclr 1 bitset 20002004 wmsr \ GX p 199
+ 1. 20002004 set-msr \ GX p 199
+
+ 00000200.00000000. 20000020 set-msr \ Power mode entry and exit delays
+
+[ifdef] support-1g-drams
+ \ Try 1-Gbit chip, 1 GiB total config
+
+ 1300. 2000001d set-msr \ Mask CKE1,0 while setting new config
+ 10078113.00005040. 20000018 set-msr \ DIMM1 off, DIMM0 1024 MB, 2 module banks, 8K pages
+ 18000100.364221a3. 20000019 set-msr
+ 140dd101. 2000001a set-msr \ MC_CF1017_DATA LX p 231
+
+ here d# 10 + asm-base - ResetBase + # esp mov \ Return address (no stack)
+ dramtry #) jmp h# 4000.0000 # ax cmp 1 F: je
+
+ \ Try 1-Gbit chip, 512 MiB total config
+
+ 1300. 2000001d set-msr \ Mask CKE1,0 while setting new config
+ 10077013.00005040. 20000018 set-msr \ DIMM1 off, DIMM0 512 MB, 1 module bank, 8K pages
+ 18000100.364221a3. 20000019 set-msr
+ 140dd101. 2000001a set-msr \ MC_CF1017_DATA LX p 231
+
+ here d# 10 + asm-base - ResetBase + # esp mov \ Return address (no stack)
+ dramtry #) jmp h# 2000.0000 # ax cmp 1 F: je
+[then]
+
+ \ Try 512-Mbit chip, 512 MiB total config
+
+ 1300. 2000001d set-msr \ Mask CKE1,0 while setting new config
+ 10077113.00005040. 20000018 set-msr \ DIMM1 off, DIMM0 512 MB, 2 module banks, 8K pages
+ 18000100.364221a3. 20000019 set-msr
+ 140dd101. 2000001a set-msr \ MC_CF1017_DATA LX p 231
+ here d# 10 + asm-base - ResetBase + # esp mov \ Return address (no stack)
+ dramtry #) jmp h# 2000.0000 # ax cmp 1 F: je
+
+
+ \ Try 512-Mbit chip, 256 MiB total config
+ 1300. 2000001d set-msr \ Mask CKE1,0 while setting new config
+ 10076013.00005040. 20000018 set-msr \ DIMM1 off, DIMM0 256 MB, 1 module bank, 8K pages
+ 18000100.364221a3. 20000019 set-msr
+ 140dd101. 2000001a set-msr \ MC_CF1017_DATA LX p 231
+
+ here d# 10 + asm-base - ResetBase + # esp mov \ Return address (no stack)
+ dramtry #) jmp h# 1000.0000 # ax cmp 1 F: je
+
+
+ \ Can't find a working RAM configuration - emit a message and POST code
+ char * 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+ char R 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+ char A 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+ char M 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+ char * 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+ h# 1e # al mov al h# 80 # out
+ begin hlt again
+
+1 L: \ DRAM is okay; size in EAX
+ ax bp mov \ Move DRAM size to EBP so we can use EAX for MSR ops
+ fb-size # bp sub \ Subtract off frame buffer size
+
+ \ Shrink system RAM limit in RCONF_DEFAULT MSR
+ 00001808 rmsr
+ bp ax mov 4 # ax shr \ Move DRAM size to SYSTOP field
+ h# 1000.0000 # ax or \ Set DEVRP (high nibble) and SYSRP (low byte)
+ 00001808 wmsr
+
+ \ Map frame buffer (see page 83 of LX manual)
+ \ This is tricky because we have to compute several field values and distribute
+ \ them across two registers.
+
+ bp dx mov \ EDX: Frame buffer address in RAM array
+ fb-pci-base # bx mov \ EBX: Frame buffer address in CPU address space
+ bx dx sub \ EDX: Offset from FB CPU address to RAM array address
+ d# 4 # dx shr \ Move offset to OFFSET field of P2D_RO high word
+ h# 2000.0000 # dx or \ Merge in PDID1 field
+
+ bx ax mov \ EAX: Frame buffer CPU address
+ fb-size # ax add \ EAX: Frame buffer limit
+ h# 1000 # ax sub \ EAX: Frame buffer top page
+ ax si mov \ Save a copy in ESI
+ d# 24 # ax shr \ Top 8 bits of frame buffer top page to PMAX field
+ ax dx or \ EDX: completed high word of MSR value EAX: dead
+
+ bx ax mov \ EAX: Frame buffer CPU address
+ d# 12 # ax shr \ Move to PMIN field
+ d# 8 # si shl \ Move low bits of frame buffer limit to PMAX low
+ si ax add \ EAX: completed high word of MSR value ESI: dead EBX: dead
+ 10000029 wmsr \ P2D_RO0 - Frame buffer at PA fd00.0000 maps to RAM at 0f80.0000
+
+ \ The remaining fields use the top page instead of the limit
+ h# 1000 # bp sub \ EBP: RAM top page address
+
+ \ Set above-1M memory address map - P2D_R descriptors
+ bp dx mov d# 24 # dx shr \ Top 8 bits to PMAX field in high word
+ bp ax mov d# 8 # ax shl \ Low bits to PMAX field in low word
+ h# 2000.0000 # dx or \ Merge in PDID1 field
+ h# 0000.0100 # ax or \ Merge in PMIN field (1 MiB)
+ 10000028 wmsr \ Write P2D_R descriptor for GLIU0 (outgoing)
+ 4000002c wmsr \ Write P2D_R descriptor for GLIU1 (incoming)
+
+ \ Set PCI DMA to memory descriptor to map incoming DMA from 1M to RAM limit
+ bp dx mov \ TOP field in high word
+ h# 00100130 # ax mov \ BASE field (1 MiB), EN (100), PF(20), WC(10)
+ 50002019 wmsr \ Write GLPCI_R1 MSR
+
+\ This is the tail of ${BP}/dev/geode/draminit.fth
+
+ h# 19 # al mov al h# 80 # out
+ h# 1430 # dx mov dx ax in h# 9999 # ax cmp = if
+ h# 34 # al mov al h# 70 # out \ Write to CMOS 0x34
+ h# 19 # al mov al h# 71 # out \ Write value 01
+ then
+
+ \ Turn on the cache
+ cr0 ax mov
+ 6000.0000 bitclr \ Cache-disable off, coherent
+ ax cr0 mov
+ invd
+
+ h# 1a # al mov al h# 80 # out
+ h# 1430 # dx mov dx ax in h# 9999 # ax cmp = if
+ h# 34 # al mov al h# 70 # out \ Write to CMOS 0x34
+ h# 1a # al mov al h# 71 # out \ Write value 01
+ then
+
+ 0000f001.00001400. 5140000f set-msr \ PMS BAR
+
+ \ It is tempting to test bit 0 of PM register 5c, but a 5536 erratum
+ \ prevents that bit from working. Bit 1 works, but LX errata 34
+ \ sometimes requires that we reset the system to fix the memory DLL,
+ \ which destroys all the bits of PM register 5c. So we put a breadcrumb
+ \ in a PM register that we don't otherwise use.
+ 1430 port-rl h# 9999 # ax cmp = if \ Wakeup event flag
+ 0 1430 port-wl
+ h# 1b # al mov al h# 80 # out
+ h# 34 # al mov al h# 70 # out \ Write to CMOS 0x34
+ h# 1b # al mov al h# 71 # out \ Write value 01
+
+ char r 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+
+ resume-data # sp mov
+ resume-entry # ax mov ax call \ This might return if checksumming fails
+ char x 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+ then
+
+ h# 1c # al mov al h# 80 # out
+ h# 1808 rmsr \ Default region configuration properties MSR
+ h# 0fffff00 # ax and \ Top of System Memory field
+ 4 # ax shl \ Shift into place
+ ax mem-info-pa 4 + #) mov \ Put it where resetend.fth can find it
+
+ \ char D 3f8 port-wb begin 3fd port-rb 40 bitand 0<> until
+
+ \ Memory is now on
+ h# 8.0000 # sp mov \ Setup a stack pointer for later code
+
+ h# 1d # al mov al h# 80 # out
+\ Some optional debugging stuff ...
+[ifdef] debug-startup
+init-com1
+
+carret report
+linefeed report
+ascii F report
+ascii o report
+ascii r report
+[then]
+
+\ fload ${BP}/cpu/x86/pc/ramtest.fth
+
+0 [if]
+ax ax xor
+h# 12345678 # bx mov
+bx 0 [ax] mov
+h# 5555aaaa # 4 [ax] mov
+0 [ax] dx mov
+dx bx cmp <> if ascii B report ascii A report ascii D report begin again then
+[then]
+
+[else]
+ \ This is the single-configuration DRAM startup code
+
25ffe002.10f80000. 1808 set-msr \ 2M ROM at ffe0.0000, system RAM limit at 0f80.0000
20000000.000fff00. 10000020 set-msr \ memory - 0..fffff
2000000f.7ff00100. 10000028 set-msr \ Top of memory at 0f7f.ffff
@@ -150,6 +424,7 @@
fload ${BP}/dev/geode/draminit.fth
+[then]
\ Last-minute check for LX erratum 34 - reset if the DLL didn't start correctly
h# 4c000017 rmsr h# 10 bitand 0<> if \ LX branch
h# 4c00000f rmsr h# 7ff bitclr h# 4 bitset h# 4c00000f wmsr \ Set DLL_OV
[View Less]
Author: wmb
Date: 2008-08-29 11:21:31 +0200 (Fri, 29 Aug 2008)
New Revision: 905
Modified:
cpu/x86/assem.fth
cpu/x86/build/builder.dic
Log:
The assembler needs to pay attention to "long-offsets" in the
implementation of direct branching words like "je".
Modified: cpu/x86/assem.fth
===================================================================
--- cpu/x86/assem.fth 2008-08-29 05:54:16 UTC (rev 904)
+++ cpu/x86/assem.fth 2008-08-29 09:21:31 UTC (rev 905)
@@ -335,12 +335,14 @@
: …
[View More]prefix-0f h# 0f asm8, ;
+variable long-offsets long-offsets off
+
\ 3MI define branch instructions, with one or two bytes of offset.
: 3MI \ conditional branches
( op -- ) create c,
( dest -- ) does> c@ ( dest op )
swap here 2+ - ( op disp )
- dup small? if ( op disp8 )
+ dup small? long-offsets @ 0= and if ( op disp8 )
swap asm8, asm8,
else ( op disp )
prefix-0f swap h# 10 + asm8,
@@ -704,8 +706,6 @@
\ Assembler version of forward/backward mark/resolve.
-variable long-offsets long-offsets off
-
: >MARK (S -- addr ) HERE ; \ Address of opcode, not offset byte
: >RESOLVE (S addr -- )
long-offsets @ if
[View Less]
Author: wmb
Date: 2008-08-29 00:25:57 +0200 (Fri, 29 Aug 2008)
New Revision: 897
Added:
clients/emacs/ansi.c
clients/emacs/basic.c
clients/emacs/bind.c
clients/emacs/buffer.c
clients/emacs/dg10.c
clients/emacs/display.c
clients/emacs/ebind.h
clients/emacs/edef.h
clients/emacs/efunc.h
clients/emacs/emacs.hlp
clients/emacs/emacs.key
clients/emacs/emacs.rc
clients/emacs/emacs.tut
clients/emacs/emacs2.mss
clients/emacs/emacsfm.rc
clients/emacs/…
[View More]emacsobp.rc
clients/emacs/epath.h
clients/emacs/estruct.h
clients/emacs/estructp.h
clients/emacs/exec.c
clients/emacs/file.c
clients/emacs/fileio.c
clients/emacs/hp150.c
clients/emacs/ibmpc.c
clients/emacs/input.c
clients/emacs/isearch.c
clients/emacs/line.c
clients/emacs/lock.c
clients/emacs/main.c
clients/emacs/makefile
clients/emacs/makefile.obp
clients/emacs/me.man
clients/emacs/menu.cmd
clients/emacs/menu1
clients/emacs/ofwtermio.c
clients/emacs/random.c
clients/emacs/readme
clients/emacs/readme.dl
clients/emacs/region.c
clients/emacs/search.c
clients/emacs/spawn.c
clients/emacs/tags
clients/emacs/tcap.c
clients/emacs/termio.c
clients/emacs/vmsvt.c
clients/emacs/vt52.c
clients/emacs/window.c
clients/emacs/word.c
clients/emacs/x86/Makefile
clients/emacs/x86/config.h
clients/emacs/x86/emacs.lds
clients/emacs/x86/emacs.rc
Log:
Checked in EMACS client program files.
Added: clients/emacs/ansi.c
===================================================================
--- clients/emacs/ansi.c (rev 0)
+++ clients/emacs/ansi.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,227 @@
+/*
+ * The routines in this file provide support for ANSI style terminals
+ * over a serial line. The serial I/O services are provided by routines in
+ * "termio.c". It compiles into nothing if not an ANSI device.
+ */
+
+#define termdef 1 /* don't define "term" external */
+
+#include "estruct.h"
+#include "edef.h"
+
+#if ANSI
+
+#if AMIGA
+#define NROW 23 /* Screen size. */
+#define NCOL 77 /* Edit if you want to. */
+#else
+/*
+ * PCs really have 25 lines, but the VT100 terminal emulator in the
+ * MS Windows "Terminal" accessory does really bad things if you tell
+ * it to go to line 25
+ */
+#define NROW 24 /* Screen size. */
+#define NCOL 80 /* Edit if you want to. */
+#endif
+#define NPAUSE 100 /* # times thru update to pause */
+#define MARGIN 8 /* size of minimim margin and */
+#define SCRSIZ 64 /* scroll size for extended lines */
+#define BEL 0x07 /* BEL character. */
+#define ESC 0x1B /* ESC character. */
+
+extern int ttopen(); /* Forward references. */
+extern int ttgetc();
+extern int ttputc();
+extern int ttflush();
+extern int ttclose();
+extern int ansimove();
+extern int ansieeol();
+extern int ansieeop();
+extern int ansibeep();
+extern int ansiopen();
+extern int ansirev();
+extern int ansiclose();
+
+#if COLOR
+extern int ansifcol();
+extern int ansibcol();
+
+int cfcolor = -1; /* current forground color */
+int cbcolor = -1; /* current background color */
+#endif
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM term = {
+ NROW-1,
+ NCOL,
+ MARGIN,
+ SCRSIZ,
+ NPAUSE,
+ ansiopen,
+ ansiclose,
+ ttgetc,
+ ttputc,
+ ttflush,
+ ansimove,
+ ansieeol,
+ ansieeop,
+ ansibeep,
+ ansirev
+#if COLOR
+ , ansifcol,
+ ansibcol
+#endif
+};
+
+#if COLOR
+ansifcol(color) /* set the current output color */
+
+int color; /* color to set */
+
+{
+ if (color == cfcolor)
+ return;
+ ttputc(ESC);
+ ttputc('[');
+ ansiparm(color+30);
+ ttputc('m');
+ cfcolor = color;
+}
+
+ansibold()
+{
+ ttputc(ESC);
+ ttputc('[');
+ ttputc('1');
+ ttputc('m');
+}
+
+ansibcol(color) /* set the current background color */
+
+int color; /* color to set */
+
+{
+ if (color == cbcolor)
+ return;
+ ttputc(ESC);
+ ttputc('[');
+ ansiparm(color+40);
+ ttputc('m');
+ cbcolor = color;
+}
+#endif
+
+ansimove(row, col)
+{
+ ttputc(ESC);
+ ttputc('[');
+ ansiparm(row+1);
+ ttputc(';');
+ ansiparm(col+1);
+ ttputc('H');
+}
+
+ansieeol()
+{
+ ttputc(ESC);
+ ttputc('[');
+ ttputc('K');
+}
+
+ansieeop()
+{
+#if COLOR
+ ansifcol(gfcolor);
+ ansibcol(gbcolor);
+#endif
+ ttputc(ESC);
+ ttputc('[');
+ ttputc('J');
+}
+
+ansirev(state) /* change reverse video state */
+
+int state; /* TRUE = reverse, FALSE = normal */
+
+{
+#if COLOR
+ int ftmp, btmp; /* temporaries for colors */
+
+ if (state == FALSE) {
+ ftmp = cfcolor;
+ btmp = cbcolor;
+ cfcolor = -1;
+ cbcolor = -1;
+ ansifcol(ftmp);
+ ansibcol(btmp);
+ }
+#else
+ ttputc(ESC);
+ ttputc('[');
+ ttputc(state ? '7': '0');
+ ttputc('m');
+#endif
+}
+
+ansibeep()
+{
+ ttputc(BEL);
+ ttflush();
+}
+
+ansiparm(n)
+register int n;
+{
+ register int q,r;
+
+ q = n/10;
+ if (q != 0) {
+ r = q/10;
+ if (r != 0) {
+ ttputc((r%10)+'0');
+ }
+ ttputc((q%10) + '0');
+ }
+ ttputc((n%10) + '0');
+}
+
+ansiopen()
+{
+#if V7 | USG | BSD
+ register char *cp;
+ char *getenv();
+
+ if ((cp = getenv("TERM")) == NULL) {
+ puts("Shell variable TERM not defined!");
+ exit(1);
+ }
+ if (strcmp(cp, "vt100") != 0) {
+ puts("Terminal type not 'vt100'!");
+ exit(1);
+ }
+#endif
+#if OFW
+ term.t_nrow = stdout_rows() - 1;
+ term.t_ncol = stdout_columns();
+#endif
+ revexist = TRUE;
+ ttopen();
+}
+
+ansiclose()
+
+{
+#if COLOR
+ ansifcol(7);
+ ansibcol(0);
+#endif
+ ttclose();
+}
+#else
+ansihello()
+{
+}
+#endif
Added: clients/emacs/basic.c
===================================================================
--- clients/emacs/basic.c (rev 0)
+++ clients/emacs/basic.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,382 @@
+/*
+ * The routines in this file move the cursor around on the screen. They
+ * compute a new value for the cursor, then adjust ".". The display code
+ * always updates the cursor location, so only moves between lines, or
+ * functions that adjust the top line in the window and invalidate the
+ * framing, are hard.
+ */
+#include "estruct.h"
+#include "edef.h"
+
+/*
+ * Move the cursor to the
+ * beginning of the current line.
+ * Trivial.
+ */
+gotobol(f, n)
+{
+ curwp->w_doto = 0;
+ return (TRUE);
+}
+
+/*
+ * Move the cursor backwards by "n" characters. If "n" is less than zero call
+ * "forwchar" to actually do the move. Otherwise compute the new cursor
+ * location. Error if you try and move out of the buffer. Set the flag if the
+ * line pointer for dot changes.
+ */
+backchar(f, n)
+register int n;
+{
+ register LINE *lp;
+
+ if (n < 0)
+ return (forwchar(f, -n));
+ while (n--) {
+ if (curwp->w_doto == 0) {
+ if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
+ return (FALSE);
+ curwp->w_dotp = lp;
+ curwp->w_doto = llength(lp);
+ curwp->w_flag |= WFMOVE;
+ } else
+ curwp->w_doto--;
+ }
+ return (TRUE);
+}
+
+/*
+ * Move the cursor to the end of the current line. Trivial. No errors.
+ */
+gotoeol(f, n)
+{
+ curwp->w_doto = llength(curwp->w_dotp);
+ return (TRUE);
+}
+
+/*
+ * Move the cursor forwwards by "n" characters. If "n" is less than zero call
+ * "backchar" to actually do the move. Otherwise compute the new cursor
+ * location, and move ".". Error if you try and move off the end of the
+ * buffer. Set the flag if the line pointer for dot changes.
+ */
+forwchar(f, n)
+register int n;
+{
+ if (n < 0)
+ return (backchar(f, -n));
+ while (n--) {
+ if (curwp->w_doto == llength(curwp->w_dotp)) {
+ if (curwp->w_dotp == curbp->b_linep)
+ return (FALSE);
+ curwp->w_dotp = lforw(curwp->w_dotp);
+ curwp->w_doto = 0;
+ curwp->w_flag |= WFMOVE;
+ } else
+ curwp->w_doto++;
+ }
+ return (TRUE);
+}
+
+gotoline(f, n) /* move to a particular line.
+ argument (n) must be a positive integer for
+ this to actually do anything */
+
+{
+ if (n < 1) /* if a bogus argument...then leave */
+ return(FALSE);
+
+ /* first, we go to the start of the buffer */
+ curwp->w_dotp = lforw(curbp->b_linep);
+ curwp->w_doto = 0;
+ return(forwline(f, n-1));
+}
+
+/*
+ * Goto the beginning of the buffer. Massive adjustment of dot. This is
+ * considered to be hard motion; it really isn't if the original value of dot
+ * is the same as the new value of dot. Normally bound to "M-<".
+ */
+gotobob(f, n)
+{
+ curwp->w_dotp = lforw(curbp->b_linep);
+ curwp->w_doto = 0;
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/*
+ * Move to the end of the buffer. Dot is always put at the end of the file
+ * (ZJ). The standard screen code does most of the hard parts of update.
+ * Bound to "M->".
+ */
+gotoeob(f, n)
+{
+ curwp->w_dotp = curbp->b_linep;
+ curwp->w_doto = 0;
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/*
+ * Move forward by full lines. If the number of lines to move is less than
+ * zero, call the backward line function to actually do it. The last command
+ * controls how the goal column is set. Bound to "C-N". No errors are
+ * possible.
+ */
+forwline(f, n)
+{
+ register LINE *dlp;
+
+ if (n < 0)
+ return (backline(f, -n));
+ if ((lastflag&CFCPCN) == 0) /* Reset goal if last */
+ curgoal = getccol(FALSE); /* not C-P or C-N */
+ thisflag |= CFCPCN;
+ dlp = curwp->w_dotp;
+ while (n-- && dlp!=curbp->b_linep)
+ dlp = lforw(dlp);
+ curwp->w_dotp = dlp;
+ curwp->w_doto = getgoal(dlp);
+ curwp->w_flag |= WFMOVE;
+ return (TRUE);
+}
+
+/*
+ * This function is like "forwline", but goes backwards. The scheme is exactly
+ * the same. Check for arguments that are less than zero and call your
+ * alternate. Figure out the new line and call "movedot" to perform the
+ * motion. No errors are possible. Bound to "C-P".
+ */
+backline(f, n)
+{
+ register LINE *dlp;
+
+ if (n < 0)
+ return (forwline(f, -n));
+ if ((lastflag&CFCPCN) == 0) /* Reset goal if the */
+ curgoal = getccol(FALSE); /* last isn't C-P, C-N */
+ thisflag |= CFCPCN;
+ dlp = curwp->w_dotp;
+ while (n-- && lback(dlp)!=curbp->b_linep)
+ dlp = lback(dlp);
+ curwp->w_dotp = dlp;
+ curwp->w_doto = getgoal(dlp);
+ curwp->w_flag |= WFMOVE;
+ return (TRUE);
+}
+
+#if WORDPRO
+gotobop(f, n) /* go back to the begining of the current paragraph
+ here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
+ combination to delimit the begining of a paragraph */
+
+int f, n; /* default Flag & Numeric argument */
+
+{
+ register int suc; /* success of last backchar */
+
+ if (n < 0) /* the other way...*/
+ return(gotoeop(f, -n));
+
+ while (n-- > 0) { /* for each one asked for */
+
+ /* first scan back until we are in a word */
+ suc = backchar(FALSE, 1);
+ while (!inword() && suc)
+ suc = backchar(FALSE, 1);
+ curwp->w_doto = 0; /* and go to the B-O-Line */
+
+ /* and scan back until we hit a <NL><NL> or <NL><TAB>
+ or a <NL><SPACE> */
+ while (lback(curwp->w_dotp) != curbp->b_linep)
+ if (llength(curwp->w_dotp) != 0 &&
+ lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
+ lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
+ curwp->w_dotp = lback(curwp->w_dotp);
+ else
+ break;
+
+ /* and then forward until we are in a word */
+ suc = forwchar(FALSE, 1);
+ while (suc && !inword())
+ suc = forwchar(FALSE, 1);
+ }
+ curwp->w_flag |= WFMOVE; /* force screen update */
+ return(TRUE);
+}
+
+gotoeop(f, n) /* go forword to the end of the current paragraph
+ here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
+ combination to delimit the begining of a paragraph */
+
+int f, n; /* default Flag & Numeric argument */
+
+{
+ register int suc; /* success of last backchar */
+
+ if (n < 0) /* the other way...*/
+ return(gotobop(f, -n));
+
+ while (n-- > 0) { /* for each one asked for */
+
+ /* first scan forward until we are in a word */
+ suc = forwchar(FALSE, 1);
+ while (!inword() && suc)
+ suc = forwchar(FALSE, 1);
+ curwp->w_doto = 0; /* and go to the B-O-Line */
+ if (suc) /* of next line if not at EOF */
+ curwp->w_dotp = lforw(curwp->w_dotp);
+
+ /* and scan forword until we hit a <NL><NL> or <NL><TAB>
+ or a <NL><SPACE> */
+ while (curwp->w_dotp != curbp->b_linep) {
+ if (llength(curwp->w_dotp) != 0 &&
+ lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
+ lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
+ curwp->w_dotp = lforw(curwp->w_dotp);
+ else
+ break;
+ }
+
+ /* and then backward until we are in a word */
+ suc = backchar(FALSE, 1);
+ while (suc && !inword()) {
+ suc = backchar(FALSE, 1);
+ }
+ curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */
+ }
+ curwp->w_flag |= WFMOVE; /* force screen update */
+ return(TRUE);
+}
+#endif
+
+/*
+ * This routine, given a pointer to a LINE, and the current cursor goal
+ * column, return the best choice for the offset. The offset is returned.
+ * Used by "C-N" and "C-P".
+ */
+getgoal(dlp)
+register LINE *dlp;
+{
+ register int c;
+ register int col;
+ register int newcol;
+ register int dbo;
+
+ col = 0;
+ dbo = 0;
+ while (dbo != llength(dlp)) {
+ c = lgetc(dlp, dbo);
+ newcol = col;
+ if (c == '\t')
+ newcol |= 0x07;
+ else if (c<0x20 || c==0x7F)
+ ++newcol;
+ ++newcol;
+ if (newcol > curgoal)
+ break;
+ col = newcol;
+ ++dbo;
+ }
+ return (dbo);
+}
+
+/*
+ * Scroll forward by a specified number of lines, or by a full page if no
+ * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
+ * the overlap; this value is the default overlap value in ITS EMACS. Because
+ * this zaps the top line in the display window, we have to do a hard update.
+ */
+forwpage(f, n)
+register int n;
+{
+ register LINE *lp;
+
+ if (f == FALSE) {
+ n = curwp->w_ntrows - 2; /* Default scroll. */
+ if (n <= 0) /* Forget the overlap */
+ n = 1; /* if tiny window. */
+ } else if (n < 0)
+ return (backpage(f, -n));
+#if CVMVAS
+ else /* Convert from pages */
+ n *= curwp->w_ntrows; /* to lines. */
+#endif
+ lp = curwp->w_linep;
+ while (n-- && lp!=curbp->b_linep)
+ lp = lforw(lp);
+ curwp->w_linep = lp;
+ curwp->w_dotp = lp;
+ curwp->w_doto = 0;
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/*
+ * This command is like "forwpage", but it goes backwards. The "2", like
+ * above, is the overlap between the two windows. The value is from the ITS
+ * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
+ * reason.
+ */
+backpage(f, n)
+register int n;
+{
+ register LINE *lp;
+
+ if (f == FALSE) {
+ n = curwp->w_ntrows - 2; /* Default scroll. */
+ if (n <= 0) /* Don't blow up if the */
+ n = 1; /* window is tiny. */
+ } else if (n < 0)
+ return (forwpage(f, -n));
+#if CVMVAS
+ else /* Convert from pages */
+ n *= curwp->w_ntrows; /* to lines. */
+#endif
+ lp = curwp->w_linep;
+ while (n-- && lback(lp)!=curbp->b_linep)
+ lp = lback(lp);
+ curwp->w_linep = lp;
+ curwp->w_dotp = lp;
+ curwp->w_doto = 0;
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/*
+ * Set the mark in the current window to the value of "." in the window. No
+ * errors are possible. Bound to "M-.".
+ */
+setmark(f, n)
+{
+ curwp->w_markp = curwp->w_dotp;
+ curwp->w_marko = curwp->w_doto;
+ mlwrite("[Mark set]");
+ return (TRUE);
+}
+
+/*
+ * Swap the values of "." and "mark" in the current window. This is pretty
+ * easy, bacause all of the hard work gets done by the standard routine
+ * that moves the mark about. The only possible error is "no mark". Bound to
+ * "C-X C-X".
+ */
+swapmark(f, n)
+{
+ register LINE *odotp;
+ register int odoto;
+
+ if (curwp->w_markp == NULL) {
+ mlwrite("No mark in this window");
+ return (FALSE);
+ }
+ odotp = curwp->w_dotp;
+ odoto = curwp->w_doto;
+ curwp->w_dotp = curwp->w_markp;
+ curwp->w_doto = curwp->w_marko;
+ curwp->w_markp = odotp;
+ curwp->w_marko = odoto;
+ curwp->w_flag |= WFMOVE;
+ return (TRUE);
+}
Added: clients/emacs/bind.c
===================================================================
--- clients/emacs/bind.c (rev 0)
+++ clients/emacs/bind.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,609 @@
+/* This file is for functions having to do with key bindings,
+ descriptions, help commands and startup file.
+
+ written 11-feb-86 by Daniel Lawrence
+ */
+
+#include "estruct.h"
+#include "edef.h"
+#include "epath.h"
+
+extern int foo;
+extern int meta(), cex(); /* dummy prefix binding functions */
+
+deskey(f, n) /* describe the command for a certain key */
+
+{
+ register int c; /* command character to describe */
+ register char *ptr; /* string pointer to scan output strings */
+ register KEYTAB *ktp; /* pointer into the command table */
+ register int found; /* matched command flag */
+ register NBIND *nptr; /* pointer into the name binding table */
+ char outseq[80]; /* output buffer for command sequence */
+
+ /* prompt the user to type us a key to describe */
+ mlwrite(": describe-key ");
+
+ /* get the command sequence to describe */
+ c = getckey(FALSE); /* get a command sequence */
+
+ /* change it to something we can print as well */
+ cmdstr(c, &outseq[0]);
+
+ /* and dump it out */
+ ptr = &outseq[0];
+ while (*ptr)
+ (*term.t_putchar)(*ptr++);
+ (*term.t_putchar)(' '); /* space it out */
+
+ /* find the right ->function */
+ ktp = &keytab[0];
+ found = FALSE;
+ while (ktp->k_fp != NULL) {
+ if (ktp->k_code == c) {
+ found = TRUE;
+ break;
+ }
+ ++ktp;
+ }
+
+ if (!found)
+ strcpy(outseq,"Not Bound");
+ else {
+ /* match it against the name binding table */
+ nptr = &names[0];
+ strcpy(outseq,"[Bad binding]");
+ while (nptr->n_func != NULL) {
+ if (nptr->n_func == ktp->k_fp) {
+ strcpy(outseq, nptr->n_name);
+ break;
+ }
+ ++nptr;
+ }
+ }
+
+ /* output the command sequence */
+ ptr = &outseq[0];
+ while (*ptr)
+ (*term.t_putchar)(*ptr++);
+}
+
+cmdstr(c, seq) /* change a key command to a string we can print out */
+
+int c; /* sequence to translate */
+char *seq; /* destination string for sequence */
+
+{
+ char *ptr; /* pointer into current position in sequence */
+
+ ptr = seq;
+
+ /* apply meta sequence if needed */
+ if (c & META) {
+ *ptr++ = 'M';
+ *ptr++ = '-';
+ }
+
+ /* apply ^X sequence if needed */
+ if (c & CTLX) {
+ *ptr++ = '^';
+ *ptr++ = 'X';
+ }
+
+ /* apply SPEC sequence if needed */
+ if (c & SPEC) {
+ *ptr++ = 'F';
+ *ptr++ = 'N';
+ }
+
+ /* apply control sequence if needed */
+ if (c & CTRL) {
+ *ptr++ = '^';
+ }
+
+ c = c & 255; /* strip the prefixes */
+
+ /* and output the final sequence */
+
+ *ptr++ = c;
+ *ptr = 0; /* terminate the string */
+}
+
+#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+char *homedir; /* pointer to your home directory */
+char *getenv();
+char *gethomedir(void);
+#endif
+
+help(f, n) /* give me some help!!!!
+ bring up a fake buffer and read the help file
+ into it with view mode */
+{
+ register int status; /* status of I/O operations */
+ register WINDOW *wp; /* scaning pointer to windows */
+ register BUFFER *bp; /* buffer pointer to help */
+ register int i; /* index into help file names */
+ char fname[NSTRING]; /* buffer to construct file name in */
+
+ /* first check if we are already here */
+ bp = bfind("emacs.hlp", FALSE, BFINVS);
+
+ if (bp == NULL) {
+#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+ /* Look in the Emacs home directory */
+#if OFW
+ if ((homedir = getenv("EMACSHOME")) != NULL
+ ||(homedir = gethomedir()) != NULL) {
+#else
+ if ((homedir = getenv("EMACSHOME")) != NULL) {
+#endif
+ /* build the file name */
+ strcpy(fname, homedir);
+#if ! OFW
+ if ( *homedir
+ && homedir[strlen(homedir)-1] != '/'
+ && homedir[strlen(homedir)-1] != '\\'
+ )
+ strcat(fname, "/");
+#endif
+ strcat(fname, pathname[1]);
+
+ /* and test it */
+ status = ffropen(fname);
+ if (status == FIOSUC)
+ goto okay;
+ }
+#endif
+
+ /* search through the list of help files */
+ for (i=2; i < NPNAMES; i++) {
+ strcpy(fname, pathname[i]);
+ strcat(fname, pathname[1]);
+ status = ffropen(fname);
+ if (status == FIOSUC)
+ goto okay;
+ }
+
+ if (status == FIOFNF) {
+ mlwrite("[Help file is not online]");
+ return(FALSE);
+ }
+
+okay:
+ /* close the file to prepare for to read it in */
+ ffclose();
+ }
+
+ /* split the current window to make room for the help stuff */
+ if (splitwind(FALSE, 1) == FALSE)
+ return(FALSE);
+
+ if (bp == NULL) {
+ /* and read the stuff in */
+ if (getfile(fname, FALSE) == FALSE)
+ return(FALSE);
+ } else
+ swbuffer(bp);
+
+ /* make this window in VIEW mode, update all mode lines */
+ curwp->w_bufp->b_mode |= MDVIEW;
+ curwp->w_bufp->b_flag |= BFINVS;
+ wp = wheadp;
+ while (wp != NULL) {
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ return(TRUE);
+}
+
+int (*fncmatch(fname))() /* match fname to a function in the names table
+ and return any match or NULL if none */
+
+char *fname; /* name to attempt to match */
+
+{
+ register NBIND *ffp; /* pointer to entry in name binding table */
+
+ /* scan through the table, returning any match */
+ ffp = &names[0];
+ while (ffp->n_func != NULL) {
+ if (strcmp(fname, ffp->n_name) == 0)
+ return(ffp->n_func);
+ ++ffp;
+ }
+ return(NULL);
+}
+
+/* bindtokey: add a new key to the key binding table
+*/
+
+bindtokey(f, n)
+
+int f, n; /* command arguments [IGNORED] */
+
+{
+ register int c; /* command key to bind */
+ register (*kfunc)(); /* ptr to the requexted function to bind to */
+ register char *ptr; /* ptr to dump out input key string */
+ register KEYTAB *ktp; /* pointer into the command table */
+ register int found; /* matched command flag */
+ char outseq[80]; /* output buffer for keystroke sequence */
+ int (*getname())();
+
+ /* prompt the user to type in a key to bind */
+ mlwrite(": bind-to-key ");
+
+ /* get the function name to bind it to */
+ kfunc = getname();
+ if (kfunc == NULL) {
+ mlwrite("[No such function]");
+ return(FALSE);
+ }
+ (*term.t_putchar)(' '); /* space it out */
+ (*term.t_flush)();
+
+ /* get the command sequence to bind */
+ c = getckey((kfunc == meta) || (kfunc == cex));
+
+ /* change it to something we can print as well */
+ cmdstr(c, &outseq[0]);
+
+ /* and dump it out */
+ ptr = &outseq[0];
+ while (*ptr)
+ (*term.t_putchar)(*ptr++);
+
+ /* if the function is a prefix key */
+ if (kfunc == meta || kfunc == cex) {
+
+ /* search for an existing binding for the prefix key */
+ ktp = &keytab[0];
+ found = FALSE;
+ while (ktp->k_fp != NULL) {
+ if (ktp->k_fp == kfunc) {
+ found = TRUE;
+ break;
+ }
+ ++ktp;
+ }
+
+ /* reset the appropriate global prefix variable */
+ if (kfunc == meta)
+ metac = c;
+ if (kfunc == cex)
+ ctlxc = c;
+
+ /* if we found it, just reset it
+ otherwise, let it fall through and be added to the end */
+ if (found) {
+ ktp->k_code = c;
+ return(TRUE);
+ }
+ } else {
+
+ /* search the table to see if it exists */
+ ktp = &keytab[0];
+ found = FALSE;
+ while (ktp->k_fp != NULL) {
+ if (ktp->k_code == c) {
+ found = TRUE;
+ break;
+ }
+ ++ktp;
+ }
+ }
+
+ if (found) { /* it exists, just change it then */
+ ktp->k_fp = kfunc;
+ } else { /* otherwise we need to add it to the end */
+ /* if we run out of binding room, bitch */
+ if (ktp >= &keytab[NBINDS]) {
+ mlwrite("Binding table FULL!");
+ return(FALSE);
+ }
+
+ ktp->k_code = c; /* add keycode */
+ ktp->k_fp = kfunc; /* and the function pointer */
+ ++ktp; /* and make sure the next is null */
+ ktp->k_code = 0;
+ ktp->k_fp = NULL;
+ }
+ return(TRUE);
+}
+
+/* unbindkey: delete a key from the key binding table
+*/
+
+unbindkey(f, n)
+
+int f, n; /* command arguments [IGNORED] */
+
+{
+ register int c; /* command key to unbind */
+ register char *ptr; /* ptr to dump out input key string */
+ register KEYTAB *ktp; /* pointer into the command table */
+ register KEYTAB *sktp; /* saved pointer into the command table */
+ register int found; /* matched command flag */
+ char outseq[80]; /* output buffer for keystroke sequence */
+
+ /* prompt the user to type in a key to unbind */
+ mlwrite(": unbind-key ");
+
+ /* get the command sequence to unbind */
+ c = getckey(FALSE); /* get a command sequence */
+
+ /* change it to something we can print as well */
+ cmdstr(c, &outseq[0]);
+
+ /* and dump it out */
+ ptr = &outseq[0];
+ while (*ptr)
+ (*term.t_putchar)(*ptr++);
+
+ /* search the table to see if the key exists */
+ ktp = &keytab[0];
+ found = FALSE;
+ while (ktp->k_fp != NULL) {
+ if (ktp->k_code == c) {
+ found = TRUE;
+ break;
+ }
+ ++ktp;
+ }
+
+ /* if it isn't bound, bitch */
+ if (!found) {
+ mlwrite("[Key not bound]");
+ return(FALSE);
+ }
+
+ /* save the pointer and scan to the end of the table */
+ sktp = ktp;
+ while (ktp->k_fp != NULL)
+ ++ktp;
+ --ktp; /* backup to the last legit entry */
+
+ /* copy the last entry to the current one */
+ sktp->k_code = ktp->k_code;
+ sktp->k_fp = ktp->k_fp;
+
+ /* null out the last one */
+ ktp->k_code = 0;
+ ktp->k_fp = NULL;
+ return(TRUE);
+}
+
+desbind(f, n) /* describe bindings
+ bring up a fake buffer and list the key bindings
+ into it with view mode */
+{
+ register WINDOW *wp; /* scnaning pointer to windows */
+ register KEYTAB *ktp; /* pointer into the command table */
+ register NBIND *nptr; /* pointer into the name binding table */
+ register BUFFER *bp; /* buffer to put binding list into */
+ char *strp; /* pointer int string to send */
+ int cpos; /* current position to use in outseq */
+ char outseq[80]; /* output buffer for keystroke sequence */
+
+ /* split the current window to make room for the binding list */
+ if (splitwind(FALSE, 1) == FALSE)
+ return(FALSE);
+
+ /* and get a buffer for it */
+ bp = bfind("Binding list", TRUE, 0);
+ if (bp == NULL || bclear(bp) == FALSE) {
+ mlwrite("Can not display binding list");
+ return(FALSE);
+ }
+
+ /* let us know this is in progress */
+ mlwrite("[Building buffer list]");
+
+ /* disconect the current buffer */
+ if (--curbp->b_nwnd == 0) { /* Last use. */
+ curbp->b_dotp = curwp->w_dotp;
+ curbp->b_doto = curwp->w_doto;
+ curbp->b_markp = curwp->w_markp;
+ curbp->b_marko = curwp->w_marko;
+ }
+
+ /* connect the current window to this buffer */
+ curbp = bp; /* make this buffer current in current window */
+ bp->b_mode = 0; /* no modes active in binding list */
+ bp->b_nwnd++; /* mark us as more in use */
+ wp = curwp;
+ wp->w_bufp = bp;
+ wp->w_linep = bp->b_linep;
+ wp->w_flag = WFHARD|WFFORCE;
+ wp->w_dotp = bp->b_dotp;
+ wp->w_doto = bp->b_doto;
+ wp->w_markp = NULL;
+ wp->w_marko = 0;
+
+ /* build the contents of this window, inserting it line by line */
+ nptr = &names[0];
+ while (nptr->n_func != NULL) {
+
+ /* add in the command name */
+ strcpy(outseq, nptr->n_name);
+ cpos = strlen(outseq);
+
+ /* search down any keys bound to this */
+ ktp = &keytab[0];
+ while (ktp->k_fp != NULL) {
+ if (ktp->k_fp == nptr->n_func) {
+ /* padd out some spaces */
+ while (cpos < 25)
+ outseq[cpos++] = ' ';
+
+ /* add in the command sequence */
+ cmdstr(ktp->k_code, &outseq[cpos]);
+ while (outseq[cpos] != 0)
+ ++cpos;
+
+ /* and add it as a line into the buffer */
+ strp = &outseq[0];
+ while (*strp != 0)
+ linsert(1, *strp++);
+ lnewline();
+
+ cpos = 0; /* and clear the line */
+ }
+ ++ktp;
+ }
+
+ /* if no key was bound, we need to dump it anyway */
+ if (cpos > 0) {
+ outseq[cpos] = 0;
+ strp = &outseq[0];
+ while (*strp != 0)
+ linsert(1, *strp++);
+ lnewline();
+ }
+
+ /* and on to the next name */
+ ++nptr;
+ }
+
+ curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
+ curbp->b_flag &= ~BFCHG; /* don't flag this as a change */
+ wp->w_dotp = lforw(bp->b_linep);/* back to the begining */
+ wp->w_doto = 0;
+ wp = wheadp; /* and update ALL mode lines */
+ while (wp != NULL) {
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ mlwrite(""); /* clear the mode line */
+ return(TRUE);
+}
+
+getckey(mflag) /* get a command key sequence from the keyboard */
+
+int mflag; /* going for a meta sequence? */
+
+{
+ register int c; /* character fetched */
+ register char *tp; /* pointer into the token */
+ char tok[NSTRING]; /* command incoming */
+
+ /* check to see if we are executing a command line */
+ if (clexec) {
+ nxtarg(tok); /* get the next token */
+
+ /* parse it up */
+ tp = &tok[0];
+ c = 0;
+
+ /* first, the META prefix */
+ if (*tp == 'M' && *(tp+1) == '-') {
+ c = META;
+ tp += 2;
+ } else
+
+ /* next the function prefix */
+ if (*tp == 'F' && *(tp+1) == 'N') {
+ c |= SPEC;
+ tp += 2;
+ } else
+
+ /* control-x as well... */
+ if (*tp == '^' && *(tp+1) == 'X') {
+ c |= CTLX;
+ tp += 2;
+ }
+
+ /* a control char? */
+ if (*tp == '^' & *(tp+1) != 0) {
+ c |= CTRL;
+ ++tp;
+ }
+
+ /* make sure we are not lower case */
+ if (c >= 'a' && c <= 'z')
+ c -= 32;
+
+ /* the final sequence... */
+ c |= *tp;
+
+ return(c);
+ }
+
+ /* or the normal way */
+ if (mflag)
+ c = get1key();
+ else
+ c = getcmd();
+ return(c);
+}
+
+/* execute the startup file */
+
+startup(sfname)
+
+char *sfname; /* name of startup file (null if default) */
+
+{
+ register int status; /* status of I/O operations */
+ register int i; /* index into help file names */
+ char fname[NSTRING]; /* buffer to construct file name in */
+ char *sfroot; /* root of startup file name */
+
+#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+ char *getenv();
+ char *homedir; /* pointer to your home directory */
+#endif
+
+ if (sfname[0] == 0)
+ sfroot = pathname[0];
+ else
+ sfroot = sfname;
+
+#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+ /* get the HOME from the environment */
+#if OFW
+ if ((homedir = getenv("HOME") ) != NULL
+ || (homedir = getenv("EMACSHOME")) != NULL
+ || (homedir = gethomedir() ) != NULL) {
+#else
+ if ((homedir = getenv("HOME") ) != NULL
+ || (homedir = getenv("EMACSHOME")) != NULL) {
+#endif
+ /* build the file name */
+ strcpy(fname, homedir);
+#if ! OFW
+ if ( *homedir
+ && homedir[strlen(homedir)-1] != '/'
+ && homedir[strlen(homedir)-1] != '\\'
+ )
+ strcat(fname, "/");
+#endif
+ strcat(fname, sfroot);
+
+ /* and test it */
+ status = ffropen(fname);
+ if (status == FIOSUC) {
+ ffclose();
+ return(dofile(fname));
+ }
+ }
+#endif
+
+ /* search through the list of startup files */
+ for (i=2; i < NPNAMES; i++) {
+ strcpy(fname, pathname[i]);
+ strcat(fname, sfroot);
+ status = ffropen(fname);
+ if (status == FIOSUC)
+ break;
+ }
+
+ /* if it isn't around, don't sweat it */
+ if (status == FIOFNF)
+ return(TRUE);
+
+ ffclose(); /* close the file to prepare to read it in */
+
+ return(dofile(fname));
+}
+
Added: clients/emacs/buffer.c
===================================================================
--- clients/emacs/buffer.c (rev 0)
+++ clients/emacs/buffer.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,495 @@
+/*
+ * Buffer management.
+ * Some of the functions are internal,
+ * and some are actually attached to user
+ * keys. Like everyone else, they set hints
+ * for the display system.
+ */
+#include "estruct.h"
+#include "edef.h"
+
+/*
+ * Attach a buffer to a window. The
+ * values of dot and mark come from the buffer
+ * if the use count is 0. Otherwise, they come
+ * from some other window.
+ */
+usebuffer(f, n)
+{
+ register BUFFER *bp;
+ register int s;
+ char bufn[NBUFN];
+
+ if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
+ return (s);
+ if ((bp=bfind(bufn, TRUE, 0)) == NULL)
+ return (FALSE);
+ return(swbuffer(bp));
+}
+
+nextbuffer(f, n) /* switch to the next buffer in the buffer list */
+
+{
+ register BUFFER *bp;
+
+ bp = curbp->b_bufp;
+ /* cycle through the buffers to find an eligable one */
+ while (bp == NULL || bp->b_flag & BFINVS) {
+ if (bp == NULL)
+ bp = bheadp;
+ else
+ bp = bp->b_bufp;
+ }
+ return(swbuffer(bp));
+}
+
+swbuffer(bp) /* make buffer BP current */
+
+BUFFER *bp;
+
+{
+ register WINDOW *wp;
+
+ if (--curbp->b_nwnd == 0) { /* Last use. */
+ curbp->b_dotp = curwp->w_dotp;
+ curbp->b_doto = curwp->w_doto;
+ curbp->b_markp = curwp->w_markp;
+ curbp->b_marko = curwp->w_marko;
+ }
+ curbp = bp; /* Switch. */
+ if (curbp->b_active != TRUE) { /* buffer not active yet*/
+ /* read it in and activate it */
+ readin(curbp->b_fname, TRUE);
+ curbp->b_dotp = lforw(curbp->b_linep);
+ curbp->b_doto = 0;
+ curbp->b_active = TRUE;
+ }
+ curwp->w_bufp = bp;
+ curwp->w_linep = bp->b_linep; /* For macros, ignored. */
+ curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */
+ if (bp->b_nwnd++ == 0) { /* First use. */
+ curwp->w_dotp = bp->b_dotp;
+ curwp->w_doto = bp->b_doto;
+ curwp->w_markp = bp->b_markp;
+ curwp->w_marko = bp->b_marko;
+ return (TRUE);
+ }
+ wp = wheadp; /* Look for old. */
+ while (wp != NULL) {
+ if (wp!=curwp && wp->w_bufp==bp) {
+ curwp->w_dotp = wp->w_dotp;
+ curwp->w_doto = wp->w_doto;
+ curwp->w_markp = wp->w_markp;
+ curwp->w_marko = wp->w_marko;
+ break;
+ }
+ wp = wp->w_wndp;
+ }
+ return (TRUE);
+}
+
+/*
+ * Dispose of a buffer, by name.
+ * Ask for the name. Look it up (don't get too
+ * upset if it isn't there at all!). Get quite upset
+ * if the buffer is being displayed. Clear the buffer (ask
+ * if the buffer has been changed). Then free the header
+ * line and the buffer header. Bound to "C-X K".
+ */
+killbuffer(f, n)
+
+{
+ register BUFFER *bp;
+ register int s;
+ char bufn[NBUFN];
+
+ if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
+ return(s);
+ if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */
+ return (TRUE);
+ return(zotbuf(bp));
+}
+
+zotbuf(bp) /* kill the buffer pointed to by bp */
+
+register BUFFER *bp;
+
+{
+ register BUFFER *bp1;
+ register BUFFER *bp2;
+ register int s;
+
+ if (bp->b_nwnd != 0) { /* Error if on screen. */
+ mlwrite("Buffer is being displayed");
+ return (FALSE);
+ }
+ if ((s=bclear(bp)) != TRUE) /* Blow text away. */
+ return (s);
+ free((char *) bp->b_linep); /* Release header line. */
+ bp1 = NULL; /* Find the header. */
+ bp2 = bheadp;
+ while (bp2 != bp) {
+ bp1 = bp2;
+ bp2 = bp2->b_bufp;
+ }
+ bp2 = bp2->b_bufp; /* Next one in chain. */
+ if (bp1 == NULL) /* Unlink it. */
+ bheadp = bp2;
+ else
+ bp1->b_bufp = bp2;
+ free((char *) bp); /* Release buffer block */
+ return (TRUE);
+}
+
+namebuffer(f,n) /* Rename the current buffer */
+
+int f, n; /* default Flag & Numeric arg */
+
+{
+ register BUFFER *bp; /* pointer to scan through all buffers */
+ char bufn[NBUFN]; /* buffer to hold buffer name */
+
+ /* prompt for and get the new buffer name */
+ask: if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
+ return(FALSE);
+
+ /* and check for duplicates */
+ bp = bheadp;
+ while (bp != NULL) {
+ if (bp != curbp) {
+ /* if the names the same */
+ if (strcmp(bufn, bp->b_bname) == 0)
+ goto ask; /* try again */
+ }
+ bp = bp->b_bufp; /* onward */
+ }
+
+ strcpy(curbp->b_bname, bufn); /* copy buffer name to structure */
+ curwp->w_flag |= WFMODE; /* make mode line replot */
+ mlerase();
+ return(TRUE);
+}
+
+/*
+ * List all of the active
+ * buffers. First update the special
+ * buffer that holds the list. Next make
+ * sure at least 1 window is displaying the
+ * buffer list, splitting the screen if this
+ * is what it takes. Lastly, repaint all of
+ * the windows that are displaying the
+ * list. Bound to "C-X C-B".
+ */
+listbuffers(f, n)
+{
+ register WINDOW *wp;
+ register BUFFER *bp;
+ register int s;
+
+ if ((s=makelist()) != TRUE)
+ return (s);
+ if (blistp->b_nwnd == 0) { /* Not on screen yet. */
+ if ((wp=wpopup()) == NULL)
+ return (FALSE);
+ bp = wp->w_bufp;
+ if (--bp->b_nwnd == 0) {
+ bp->b_dotp = wp->w_dotp;
+ bp->b_doto = wp->w_doto;
+ bp->b_markp = wp->w_markp;
+ bp->b_marko = wp->w_marko;
+ }
+ wp->w_bufp = blistp;
+ ++blistp->b_nwnd;
+ }
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_bufp == blistp) {
+ wp->w_linep = lforw(blistp->b_linep);
+ wp->w_dotp = lforw(blistp->b_linep);
+ wp->w_doto = 0;
+ wp->w_markp = NULL;
+ wp->w_marko = 0;
+ wp->w_flag |= WFMODE|WFHARD;
+ }
+ wp = wp->w_wndp;
+ }
+ return (TRUE);
+}
+
+/*
+ * This routine rebuilds the
+ * text in the special secret buffer
+ * that holds the buffer list. It is called
+ * by the list buffers command. Return TRUE
+ * if everything works. Return FALSE if there
+ * is an error (if there is no memory).
+ */
+makelist()
+{
+ register char *cp1;
+ register char *cp2;
+ register int c;
+ register BUFFER *bp;
+ register LINE *lp;
+ register int s;
+ register int i;
+ long nbytes; /* # of bytes in current buffer */
+ char b[7+1];
+ char line[128];
+
+ blistp->b_flag &= ~BFCHG; /* Don't complain! */
+ if ((s=bclear(blistp)) != TRUE) /* Blow old text away */
+ return (s);
+ strcpy(blistp->b_fname, "");
+ if (addline("AC MODES Size Buffer File") == FALSE
+ || addline("-- ----- ---- ------ ----") == FALSE)
+ return (FALSE);
+ bp = bheadp; /* For all buffers */
+
+ /* build line to report global mode settings */
+ cp1 = &line[0];
+ *cp1++ = ' ';
+ *cp1++ = ' ';
+ *cp1++ = ' ';
+
+ /* output the mode codes */
+ for (i = 0; i < NUMMODES; i++)
+ if (gmode & (1 << i))
+ *cp1++ = modecode[i];
+ else
+ *cp1++ = '.';
+ strcpy(cp1, " Global Modes");
+ if (addline(line) == FALSE)
+ return(FALSE);
+
+ /* output the list of buffers */
+ while (bp != NULL) {
+ if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones. */
+ bp = bp->b_bufp;
+ continue;
+ }
+ cp1 = &line[0]; /* Start at left edge */
+
+ /* output status of ACTIVE flag (has the file been read in? */
+ if (bp->b_active == TRUE) /* "@" if activated */
+ *cp1++ = '@';
+ else
+ *cp1++ = ' ';
+
+ /* output status of changed flag */
+ if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */
+ *cp1++ = '*';
+ else
+ *cp1++ = ' ';
+ *cp1++ = ' '; /* Gap. */
+
+ /* output the mode codes */
+ for (i = 0; i < NUMMODES; i++) {
+ if (bp->b_mode & (1 << i))
+ *cp1++ = modecode[i];
+ else
+ *cp1++ = '.';
+ }
+ *cp1++ = ' '; /* Gap. */
+ nbytes = 0L; /* Count bytes in buf. */
+ lp = lforw(bp->b_linep);
+ while (lp != bp->b_linep) {
+ nbytes += (long)llength(lp)+1L;
+ lp = lforw(lp);
+ }
+ eltoa(b, 7, nbytes); /* 6 digit buffer size. */
+ cp2 = &b[0];
+ while ((c = *cp2++) != 0)
+ *cp1++ = c;
+ *cp1++ = ' '; /* Gap. */
+ cp2 = &bp->b_bname[0]; /* Buffer name */
+ while ((c = *cp2++) != 0)
+ *cp1++ = c;
+ cp2 = &bp->b_fname[0]; /* File name */
+ if (*cp2 != 0) {
+ while (cp1 < &line[2+1+5+1+6+1+NBUFN])
+ *cp1++ = ' ';
+ while ((c = *cp2++) != 0) {
+ if (cp1 < &line[128-1])
+ *cp1++ = c;
+ }
+ }
+ *cp1 = 0; /* Add to the buffer. */
+ if (addline(line) == FALSE)
+ return (FALSE);
+ bp = bp->b_bufp;
+ }
+ return (TRUE); /* All done */
+}
+
+eltoa(buf, width, num)
+
+char buf[];
+int width;
+long num;
+
+{
+ buf[width] = 0; /* End of string. */
+ while (num >= 10) { /* Conditional digits. */
+ buf[--width] = (int)(num%10L) + '0';
+ num /= 10L;
+ }
+ buf[--width] = (int)num + '0'; /* Always 1 digit. */
+ while (width != 0) /* Pad with blanks. */
+ buf[--width] = ' ';
+}
+
+/*
+ * The argument "text" points to
+ * a string. Append this line to the
+ * buffer list buffer. Handcraft the EOL
+ * on the end. Return TRUE if it worked and
+ * FALSE if you ran out of room.
+ */
+addline(text)
+char *text;
+{
+ register LINE *lp;
+ register int i;
+ register int ntext;
+
+ ntext = strlen(text);
+ if ((lp=lalloc(ntext)) == NULL)
+ return (FALSE);
+ for (i=0; i<ntext; ++i)
+ lputc(lp, i, text[i]);
+ blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */
+ lp->l_bp = blistp->b_linep->l_bp;
+ blistp->b_linep->l_bp = lp;
+ lp->l_fp = blistp->b_linep;
+ if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */
+ blistp->b_dotp = lp; /* move it to new line */
+ return (TRUE);
+}
+
+/*
+ * Look through the list of
+ * buffers. Return TRUE if there
+ * are any changed buffers. Buffers
+ * that hold magic internal stuff are
+ * not considered; who cares if the
+ * list of buffer names is hacked.
+ * Return FALSE if no buffers
+ * have been changed.
+ */
+anycb()
+{
+ register BUFFER *bp;
+
+ bp = bheadp;
+ while (bp != NULL) {
+ if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
+ return (TRUE);
+ bp = bp->b_bufp;
+ }
+ return (FALSE);
+}
+
+/*
+ * Find a buffer, by name. Return a pointer
+ * to the BUFFER structure associated with it.
+ * If the buffer is not found
+ * and the "cflag" is TRUE, create it. The "bflag" is
+ * the settings for the flags in in buffer.
+ */
+BUFFER *
+bfind(bname, cflag, bflag)
+register char *bname;
+{
+ register BUFFER *bp;
+ register BUFFER *sb; /* buffer to insert after */
+ register LINE *lp;
+
+ bp = bheadp;
+ while (bp != NULL) {
+ if (strcmp(bname, bp->b_bname) == 0)
+ return (bp);
+ bp = bp->b_bufp;
+ }
+ if (cflag != FALSE) {
+ if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
+ return (NULL);
+ if ((lp=lalloc(0)) == NULL) {
+ free((char *) bp);
+ return (NULL);
+ }
+ /* find the place in the list to insert this buffer */
+ if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
+ /* insert at the begining */
+ bp->b_bufp = bheadp;
+ bheadp = bp;
+ } else {
+ sb = bheadp;
+ while (sb->b_bufp != NULL) {
+ if (strcmp(sb->b_bufp->b_bname, bname) > 0)
+ break;
+ sb = sb->b_bufp;
+ }
+
+ /* and insert it */
+ bp->b_bufp = sb->b_bufp;
+ sb->b_bufp = bp;
+ }
+
+ /* and set up the other buffer fields */
+ bp->b_active = TRUE;
+ bp->b_dotp = lp;
+ bp->b_doto = 0;
+ bp->b_markp = NULL;
+ bp->b_marko = 0;
+ bp->b_flag = bflag;
+ bp->b_mode = gmode;
+ bp->b_nwnd = 0;
+ bp->b_linep = lp;
+ strcpy(bp->b_fname, "");
+ strcpy(bp->b_bname, bname);
+ lp->l_fp = lp;
+ lp->l_bp = lp;
+ }
+ return (bp);
+}
+
+/*
+ * This routine blows away all of the text
+ * in a buffer. If the buffer is marked as changed
+ * then we ask if it is ok to blow it away; this is
+ * to save the user the grief of losing text. The
+ * window chain is nearly always wrong if this gets
+ * called; the caller must arrange for the updates
+ * that are required. Return TRUE if everything
+ * looks good.
+ */
+bclear(bp)
+register BUFFER *bp;
+{
+ register LINE *lp;
+ register int s;
+
+ if ((bp->b_flag&BFINVS) == 0 /* Not scratch buffer. */
+ && (bp->b_flag&BFCHG) != 0 /* Something changed */
+ && (s=mlyesno("Discard changes")) != TRUE)
+ return (s);
+ bp->b_flag &= ~BFCHG; /* Not changed */
+ while ((lp=lforw(bp->b_linep)) != bp->b_linep)
+ lfree(lp);
+ bp->b_dotp = bp->b_linep; /* Fix "." */
+ bp->b_doto = 0;
+ bp->b_markp = NULL; /* Invalidate "mark" */
+ bp->b_marko = 0;
+ return (TRUE);
+}
+
+unmark(f, n) /* unmark the current buffers change flag */
+
+int f, n; /* unused command arguments */
+
+{
+ curbp->b_flag &= ~BFCHG;
+ curwp->w_flag |= WFMODE;
+ return(TRUE);
+}
Added: clients/emacs/dg10.c
===================================================================
--- clients/emacs/dg10.c (rev 0)
+++ clients/emacs/dg10.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,162 @@
+/*
+ * The routines in this file provide support for the Data General Model 10
+ * Microcomputer.
+ */
+
+#define termdef 1 /* don't define "term" external */
+
+#include "estruct.h"
+#include "edef.h"
+
+#if DG10
+
+#define NROW 24 /* Screen size. */
+#define NCOL 80 /* Edit if you want to. */
+#define NPAUSE 100 /* # times thru update to pause */
+#define MARGIN 8 /* size of minimim margin and */
+#define SCRSIZ 64 /* scroll size for extended lines */
+#define BEL 0x07 /* BEL character. */
+#define ESC 30 /* DG10 ESC character. */
+
+extern int ttopen(); /* Forward references. */
+extern int ttgetc();
+extern int ttputc();
+extern int ttflush();
+extern int ttclose();
+extern int dg10move();
+extern int dg10eeol();
+extern int dg10eeop();
+extern int dg10beep();
+extern int dg10open();
+extern int dg10rev();
+extern int dg10close();
+
+#if COLOR
+extern int dg10fcol();
+extern int dg10bcol();
+
+int cfcolor = -1; /* current forground color */
+int cbcolor = -1; /* current background color */
+int ctrans[] = { /* emacs -> DG10 color translation table */
+ 0, 4, 2, 6, 1, 5, 3, 7};
+#endif
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM term = {
+ NROW-1,
+ NCOL,
+ MARGIN,
+ SCRSIZ,
+ NPAUSE,
+ dg10open,
+ dg10close,
+ ttgetc,
+ ttputc,
+ ttflush,
+ dg10move,
+ dg10eeol,
+ dg10eeop,
+ dg10beep,
+ dg10rev
+#if COLOR
+ , dg10fcol,
+ dg10bcol
+#endif
+};
+
+#if COLOR
+dg10fcol(color) /* set the current output color */
+
+int color; /* color to set */
+
+{
+ if (color == cfcolor)
+ return;
+ ttputc(ESC);
+ ttputc(0101);
+ ttputc(ctrans[color]);
+ cfcolor = color;
+}
+
+dg10bcol(color) /* set the current background color */
+
+int color; /* color to set */
+
+{
+ if (color == cbcolor)
+ return;
+ ttputc(ESC);
+ ttputc(0102);
+ ttputc(ctrans[color]);
+ cbcolor = color;
+}
+#endif
+
+dg10move(row, col)
+{
+ ttputc(16);
+ ttputc(col);
+ ttputc(row);
+}
+
+dg10eeol()
+{
+ ttputc(11);
+}
+
+dg10eeop()
+{
+#if COLOR
+ dg10fcol(gfcolor);
+ dg10bcol(gbcolor);
+#endif
+ ttputc(ESC);
+ ttputc(0106);
+ ttputc(0106);
+}
+
+dg10rev(state) /* change reverse video state */
+
+int state; /* TRUE = reverse, FALSE = normal */
+
+{
+#if COLOR
+ if (state == TRUE) {
+ dg10fcol(0);
+ dg10bcol(7);
+ }
+#else
+ ttputc(ESC);
+ ttputc(state ? 0104: 0105);
+#endif
+}
+
+dg10beep()
+{
+ ttputc(BEL);
+ ttflush();
+}
+
+dg10open()
+{
+ revexist = TRUE;
+ ttopen();
+}
+
+dg10close()
+
+{
+#if COLOR
+ dg10fcol(7);
+ dg10bcol(0);
+#endif
+ ttclose();
+}
+#else
+dg10hello()
+{
+}
+#endif
Added: clients/emacs/display.c
===================================================================
--- clients/emacs/display.c (rev 0)
+++ clients/emacs/display.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,1119 @@
+/*
+ * The functions in this file handle redisplay. There are two halves, the
+ * ones that update the virtual display screen, and the ones that make the
+ * physical display screen the same as the virtual display screen. These
+ * functions use hints that are left in the windows by the commands.
+ *
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+#define WFDEBUG 0 /* Window flag debug. */
+
+typedef struct VIDEO {
+ int v_flag; /* Flags */
+#if COLOR
+ int v_fcolor; /* current forground color */
+ int v_bcolor; /* current background color */
+ int v_rfcolor; /* requested forground color */
+ int v_rbcolor; /* requested background color */
+#endif
+ char v_text[1]; /* Screen data. */
+} VIDEO;
+
+#define VFCHG 0x0001 /* Changed flag */
+#define VFEXT 0x0002 /* extended (beyond column 80) */
+#define VFREV 0x0004 /* reverse video status */
+#define VFREQ 0x0008 /* reverse video request */
+#define VFCOL 0x0010 /* color change requested */
+
+VIDEO **vscreen; /* Virtual screen. */
+#if IBMPC == 0
+VIDEO **pscreen; /* Physical screen. */
+#endif
+
+/*
+ * Initialize the data structures used by the display code. The edge vectors
+ * used to access the screens are set up. The operating system's terminal I/O
+ * channel is set up. All the other things get initialized at compile time.
+ * The original window has "WFCHG" set, so that it will get completely
+ * redrawn on the first call to "update".
+ */
+vtinit()
+{
+ register int i;
+ register VIDEO *vp;
+
+ (*term.t_open)();
+ (*term.t_rev)(FALSE);
+ vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
+
+ if (vscreen == NULL)
+ errexit();
+
+#if IBMPC == 0
+ pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
+
+ if (pscreen == NULL)
+ errexit();
+#endif
+
+ for (i = 0; i < term.t_nrow; ++i)
+ {
+ vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
+
+ if (vp == NULL)
+ errexit();
+
+ vp->v_flag = 0;
+#if COLOR
+ vp->v_rfcolor = 7;
+ vp->v_rbcolor = 0;
+#endif
+ vscreen[i] = vp;
+#if IBMPC == 0
+ vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
+
+ if (vp == NULL)
+ errexit();
+
+ vp->v_flag = 0;
+ pscreen[i] = vp;
+#endif
+ }
+}
+
+/*
+ * Clean up the virtual terminal system, in anticipation for a return to the
+ * operating system. Move down to the last line and clear it out (the next
+ * system prompt will be written in the line). Shut down the channel to the
+ * terminal.
+ */
+vttidy()
+{
+ mlerase();
+ movecursor(term.t_nrow, 0);
+ (*term.t_flush)();
+ (*term.t_close)();
+}
+
+/*
+ * Set the virtual cursor to the specified row and column on the virtual
+ * screen. There is no checking for nonsense values; this might be a good
+ * idea during the early stages.
+ */
+vtmove(row, col)
+{
+ vtrow = row;
+ vtcol = col;
+}
+
+/*
+ * Write a character to the virtual screen. The virtual row and column are
+ * updated. If the line is too long put a "$" in the last column. This routine
+ * only puts printing characters into the virtual terminal buffers. Only
+ * column overflow is checked.
+ */
+vtputc(c)
+ int c;
+{
+ register VIDEO *vp;
+
+ vp = vscreen[vtrow];
+
+ if (vtcol >= term.t_ncol) {
+ vtcol = (vtcol + 0x07) & ~0x07;
+ vp->v_text[term.t_ncol - 1] = '$';
+ } else if (c == '\t')
+ {
+ do
+ {
+ vtputc(' ');
+ }
+ while ((vtcol&0x07) != 0);
+ }
+ else if (c < 0x20 || c == 0x7F)
+ {
+ vtputc('^');
+ vtputc(c ^ 0x40);
+ }
+ else
+ vp->v_text[vtcol++] = c;
+}
+
+/* put a character to the virtual screen in an extended line. If we are
+ not yet on left edge, don't print it yet. check for overflow on
+ the right margin */
+
+vtpute(c)
+
+int c;
+
+{
+ register VIDEO *vp;
+
+ vp = vscreen[vtrow];
+
+ if (vtcol >= term.t_ncol) {
+ vtcol = (vtcol + 0x07) & ~0x07;
+ vp->v_text[term.t_ncol - 1] = '$';
+ } else if (c == '\t')
+ {
+ do
+ {
+ vtpute(' ');
+ }
+ while (((vtcol + lbound)&0x07) != 0);
+ }
+ else if (c < 0x20 || c == 0x7F)
+ {
+ vtpute('^');
+ vtpute(c ^ 0x40);
+ }
+ else {
+ if (vtcol >= 0)
+ vp->v_text[vtcol] = c;
+ ++vtcol;
+ }
+}
+
+/*
+ * Erase from the end of the software cursor to the end of the line on which
+ * the software cursor is located.
+ */
+vteeol()
+{
+ register VIDEO *vp;
+
+ vp = vscreen[vtrow];
+ while (vtcol < term.t_ncol)
+ vp->v_text[vtcol++] = ' ';
+}
+
+/* upscreen: user routine to force a screen update
+ always finishes complete update */
+
+upscreen(f, n)
+
+{
+ update(TRUE);
+ return(TRUE);
+}
+
+/*
+ * Make sure that the display is right. This is a three part process. First,
+ * scan through all of the windows looking for dirty ones. Check the framing,
+ * and refresh the screen. Second, make sure that "currow" and "curcol" are
+ * correct for the current window. Third, make the virtual and physical
+ * screens the same.
+ */
+update(force)
+
+int force; /* force update past type ahead? */
+
+{
+ register WINDOW *wp;
+
+#if TYPEAH
+ if (force == FALSE && typahead())
+ return(TRUE);
+#endif
+
+ /* update any windows that need refreshing */
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_flag) {
+ /* if the window has changed, service it */
+ reframe(wp); /* check the framing */
+ if ((wp->w_flag & ~WFMODE) == WFEDIT)
+ updone(wp); /* update EDITed line */
+ else if (wp->w_flag & ~WFMOVE)
+ updall(wp); /* update all lines */
+#if ~WFDEBUG
+ if (wp->w_flag & WFMODE)
+ modeline(wp); /* update modeline */
+#endif
+ wp->w_flag = 0;
+ wp->w_force = 0;
+ }
+#if WFDEBUG
+ modeline();
+#endif
+ /* on to the next window */
+ wp = wp->w_wndp;
+ }
+
+ /* recalc the current hardware cursor location */
+ updpos();
+
+#if IBMPC
+ /* update the cursor and flush the buffers */
+ movecursor(currow, curcol - lbound);
+#endif
+
+ /* check for lines to de-extend */
+ upddex();
+
+ /* if screen is garbage, re-plot it */
+ if (sgarbf != FALSE)
+ updgar();
+
+ /* update the virtual screen to the physical screen */
+ updupd(force);
+
+ /* update the cursor and flush the buffers */
+ movecursor(currow, curcol - lbound);
+ (*term.t_flush)();
+ return(TRUE);
+}
+
+/* reframe: check to see if the cursor is on in the window
+ and re-frame it if needed or wanted */
+
+reframe(wp)
+
+WINDOW *wp;
+
+{
+ register LINE *lp;
+ register int i;
+
+ /* if not a requested reframe, check for a needed one */
+ if ((wp->w_flag & WFFORCE) == 0) {
+ lp = wp->w_linep;
+ for (i = 0; i < wp->w_ntrows; i++) {
+
+ /* if the line is in the window, no reframe */
+ if (lp == wp->w_dotp)
+ return(TRUE);
+
+ /* if we are at the end of the file, reframe */
+ if (lp == wp->w_bufp->b_linep)
+ break;
+
+ /* on to the next line */
+ lp = lforw(lp);
+ }
+ }
+
+ /* reaching here, we need a window refresh */
+ i = wp->w_force;
+
+ /* how far back to reframe? */
+ if (i > 0) { /* only one screen worth of lines max */
+ if (--i >= wp->w_ntrows)
+ i = wp->w_ntrows - 1;
+ } else if (i < 0) { /* negative update???? */
+ i += wp->w_ntrows;
+ if (i < 0)
+ i = 0;
+ } else
+ i = wp->w_ntrows / 2;
+
+ /* backup to new line at top of window */
+ lp = wp->w_dotp;
+ while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
+ --i;
+ lp = lback(lp);
+ }
+
+ /* and reset the current line at top of window */
+ wp->w_linep = lp;
+ wp->w_flag |= WFHARD;
+ wp->w_flag &= ~WFFORCE;
+ return(TRUE);
+}
+
+/* updone: update the current line to the virtual screen */
+
+updone(wp)
+
+WINDOW *wp; /* window to update current line in */
+
+{
+ register LINE *lp; /* line to update */
+ register int sline; /* physical screen line to update */
+ register int i;
+
+ /* search down the line we want */
+ lp = wp->w_linep;
+ sline = wp->w_toprow;
+ while (lp != wp->w_dotp) {
+ ++sline;
+ lp = lforw(lp);
+ }
+
+ /* and update the virtual line */
+ vscreen[sline]->v_flag |= VFCHG;
+ vscreen[sline]->v_flag &= ~VFREQ;
+ vtmove(sline, 0);
+ for (i=0; i < llength(lp); ++i)
+ vtputc(lgetc(lp, i));
+#if COLOR
+ vscreen[sline]->v_rfcolor = wp->w_fcolor;
+ vscreen[sline]->v_rbcolor = wp->w_bcolor;
+#endif
+ vteeol();
+}
+
+/* updall: update all the lines in a window on the virtual screen */
+
+updall(wp)
+
+WINDOW *wp; /* window to update lines in */
+
+{
+ register LINE *lp; /* line to update */
+ register int sline; /* physical screen line to update */
+ register int i;
+
+ /* search down the lines, updating them */
+ lp = wp->w_linep;
+ sline = wp->w_toprow;
+ while (sline < wp->w_toprow + wp->w_ntrows) {
+
+ /* and update the virtual line */
+ vscreen[sline]->v_flag |= VFCHG;
+ vscreen[sline]->v_flag &= ~VFREQ;
+ vtmove(sline, 0);
+ if (lp != wp->w_bufp->b_linep) {
+ /* if we are not at the end */
+ for (i=0; i < llength(lp); ++i)
+ vtputc(lgetc(lp, i));
+ lp = lforw(lp);
+ }
+
+ /* on to the next one */
+#if COLOR
+ vscreen[sline]->v_rfcolor = wp->w_fcolor;
+ vscreen[sline]->v_rbcolor = wp->w_bcolor;
+#endif
+ vteeol();
+ ++sline;
+ }
+
+}
+
+/* updpos: update the position of the hardware cursor and handle extended
+ lines. This is the only update for simple moves. */
+
+updpos()
+
+{
+ register LINE *lp;
+ register int c;
+ register int i;
+
+ /* find the current row */
+ lp = curwp->w_linep;
+ currow = curwp->w_toprow;
+ while (lp != curwp->w_dotp) {
+ ++currow;
+ lp = lforw(lp);
+ }
+
+ /* find the current column */
+ curcol = 0;
+ i = 0;
+ while (i < curwp->w_doto) {
+ c = lgetc(lp, i++);
+ if (c == '\t')
+ curcol |= 0x07;
+ else
+ if (c < 0x20 || c == 0x7f)
+ ++curcol;
+
+ ++curcol;
+ }
+
+ /* if extended, flag so and update the virtual line image */
+ if (curcol >= term.t_ncol - 1) {
+ vscreen[currow]->v_flag |= (VFEXT | VFCHG);
+ updext();
+ } else
+ lbound = 0;
+}
+
+/* upddex: de-extend any line that derserves it */
+
+upddex()
+
+{
+ register WINDOW *wp;
+ register LINE *lp;
+ register int i,j;
+
+ wp = wheadp;
+
+ while (wp != NULL) {
+ lp = wp->w_linep;
+ i = wp->w_toprow;
+
+ while (i < wp->w_toprow + wp->w_ntrows) {
+ if (vscreen[i]->v_flag & VFEXT) {
+ if ((wp != curwp) || (lp != wp->w_dotp) ||
+ (curcol < term.t_ncol - 1)) {
+ vtmove(i, 0);
+ for (j = 0; j < llength(lp); ++j)
+ vtputc(lgetc(lp, j));
+ vteeol();
+
+ /* this line no longer is extended */
+ vscreen[i]->v_flag &= ~VFEXT;
+ vscreen[i]->v_flag |= VFCHG;
+ }
+ }
+ lp = lforw(lp);
+ ++i;
+ }
+ /* and onward to the next window */
+ wp = wp->w_wndp;
+ }
+}
+
+/* updgar: if the screen is garbage, clear the physical screen and
+ the virtual screen and force a full update */
+
+updgar()
+
+{
+ register char *txt;
+ register int i,j;
+
+ for (i = 0; i < term.t_nrow; ++i) {
+ vscreen[i]->v_flag |= VFCHG;
+#if REVSTA
+ vscreen[i]->v_flag &= ~VFREV;
+#endif
+#if COLOR
+ vscreen[i]->v_fcolor = gfcolor;
+ vscreen[i]->v_bcolor = gbcolor;
+#endif
+#if IBMPC == 0
+ txt = pscreen[i]->v_text;
+ for (j = 0; j < term.t_ncol; ++j)
+ txt[j] = ' ';
+#endif
+ }
+
+ movecursor(0, 0); /* Erase the screen. */
+ (*term.t_eeop)();
+ sgarbf = FALSE; /* Erase-page clears */
+ mpresf = FALSE; /* the message area. */
+#if COLOR
+ mlerase(); /* needs to be cleared if colored */
+#endif
+}
+
+/* updupd: update the physical screen from the virtual screen */
+
+updupd(force)
+
+int force; /* forced update flag */
+
+{
+ register VIDEO *vp1;
+ register int i;
+
+ for (i = 0; i < term.t_nrow; ++i) {
+ vp1 = vscreen[i];
+
+ /* for each line that needs to be updated*/
+ if ((vp1->v_flag & VFCHG) != 0) {
+#if TYPEAH
+ if (force == FALSE && typahead())
+ return(TRUE);
+#endif
+#if IBMPC
+ updateline(i, vp1);
+#else
+ updateline(i, vp1, pscreen[i]);
+#endif
+ }
+ }
+
+#if OFW
+ /* Restore the colors to those for the current line */
+ (*term.t_setfor)(vscreen[currow]->v_rfcolor);
+ (*term.t_setback)(vscreen[currow]->v_rbcolor);
+#endif
+
+ return(TRUE);
+}
+
+/* updext: update the extended line which the cursor is currently
+ on at a column greater than the terminal width. The line
+ will be scrolled right or left to let the user see where
+ the cursor is
+ */
+
+updext()
+
+{
+ register int rcursor; /* real cursor location */
+ register LINE *lp; /* pointer to current line */
+ register int j; /* index into line */
+
+ /* calculate what column the real cursor will end up in */
+ rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
+ lbound = curcol - rcursor + 1;
+
+ /* scan through the line outputing characters to the virtual screen */
+ /* once we reach the left edge */
+ vtmove(currow, -lbound); /* start scanning offscreen */
+ lp = curwp->w_dotp; /* line to output */
+ for (j=0; j<llength(lp); ++j) /* until the end-of-line */
+ vtpute(lgetc(lp, j));
+
+ /* truncate the virtual line */
+ vteeol();
+
+ /* and put a '$' in column 1 */
+ vscreen[currow]->v_text[0] = '$';
+}
+
+/*
+ * Update a single line. This does not know how to use insert or delete
+ * character sequences; we are using VT52 functionality. Update the physical
+ * row and column variables. It does try an exploit erase to end of line. The
+ * RAINBOW version of this routine uses fast video.
+ */
+#if IBMPC
+/* UPDATELINE specific code for the IBM-PC and other compatables */
+
+updateline(row, vp1)
+
+int row; /* row of screen to update */
+struct VIDEO *vp1; /* virtual screen image */
+
+{
+#if COLOR
+ scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
+ vp1->v_fcolor = vp1->v_rfcolor;
+ vp1->v_bcolor = vp1->v_rbcolor;
+#else
+ if (vp1->v_flag & VFREQ)
+ scwrite(row, vp1->v_text, 0, 7);
+ else
+ scwrite(row, vp1->v_text, 7, 0);
+#endif
+ vp1->v_flag &= ~(VFCHG | VFCOL); /* flag this line as changed */
+
+}
+
+#else
+
+updateline(row, vp1, vp2)
+
+int row; /* row of screen to update */
+struct VIDEO *vp1; /* virtual screen image */
+struct VIDEO *vp2; /* physical screen image */
+
+{
+#if RAINBOW
+/* UPDATELINE specific code for the DEC rainbow 100 micro */
+
+ register char *cp1;
+ register char *cp2;
+ register int nch;
+
+ /* since we don't know how to make the rainbow do this, turn it off */
+ flags &= (~VFREV & ~VFREQ);
+
+ cp1 = &vp1->v_text[0]; /* Use fast video. */
+ cp2 = &vp2->v_text[0];
+ putline(row+1, 1, cp1);
+ nch = term.t_ncol;
+
+ do
+ {
+ *cp2 = *cp1;
+ ++cp2;
+ ++cp1;
+ }
+ while (--nch);
+ *flags &= ~VFCHG;
+#else
+/* UPDATELINE code for all other versions */
+
+ register char *cp1;
+ register char *cp2;
+ register char *cp3;
+ register char *cp4;
+ register char *cp5;
+ register int nbflag; /* non-blanks to the right flag? */
+ int rev; /* reverse video flag */
+ int req; /* reverse video request flag */
+
+
+ /* set up pointers to virtual and physical lines */
+ cp1 = &vp1->v_text[0];
+ cp2 = &vp2->v_text[0];
+
+#if COLOR
+ (*term.t_setfor)(vp1->v_rfcolor);
+ (*term.t_setback)(vp1->v_rbcolor);
+#endif
+
+#if REVSTA | COLOR
+ /* if we need to change the reverse video status of the
+ current line, we need to re-write the entire line */
+ rev = (vp1->v_flag & VFREV) == VFREV;
+ req = (vp1->v_flag & VFREQ) == VFREQ;
+ if ((rev != req)
+#if COLOR
+ || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
+#endif
+ ) {
+ movecursor(row, 0); /* Go to start of line. */
+ /* set rev video if needed */
+ if (rev != req)
+ (*term.t_rev)(req);
+
+ /* scan through the line and dump it to the screen and
+ the virtual screen array */
+ cp3 = &vp1->v_text[term.t_ncol];
+ while (cp1 < cp3) {
+ (*term.t_putchar)(*cp1);
+ ++ttcol;
+ *cp2++ = *cp1++;
+ }
+ /* turn rev video off */
+ if (rev != req)
+ (*term.t_rev)(FALSE);
+
+ /* update the needed flags */
+ vp1->v_flag &= ~VFCHG;
+ if (req)
+ vp1->v_flag |= VFREV;
+ else
+ vp1->v_flag &= ~VFREV;
+#if COLOR
+ vp1->v_fcolor = vp1->v_rfcolor;
+ vp1->v_bcolor = vp1->v_rbcolor;
+#endif
+ return(TRUE);
+ }
+#endif
+
+ /* advance past any common chars at the left */
+ while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
+ ++cp1;
+ ++cp2;
+ }
+
+/* This can still happen, even though we only call this routine on changed
+ * lines. A hard update is always done when a line splits, a massive
+ * change is done, or a buffer is displayed twice. This optimizes out most
+ * of the excess updating. A lot of computes are used, but these tend to
+ * be hard operations that do a lot of update, so I don't really care.
+ */
+ /* if both lines are the same, no update needs to be done */
+ if (cp1 == &vp1->v_text[term.t_ncol])
+ return(TRUE);
+
+ /* find out if there is a match on the right */
+ nbflag = FALSE;
+ cp3 = &vp1->v_text[term.t_ncol];
+ cp4 = &vp2->v_text[term.t_ncol];
+
+ while (cp3[-1] == cp4[-1]) {
+ --cp3;
+ --cp4;
+ if (cp3[0] != ' ') /* Note if any nonblank */
+ nbflag = TRUE; /* in right match. */
+ }
+
+ cp5 = cp3;
+
+ /* Erase to EOL ? */
+ if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
+ while (cp5!=cp1 && cp5[-1]==' ')
+ --cp5;
+
+ if (cp3-cp5 <= 3) /* Use only if erase is */
+ cp5 = cp3; /* fewer characters. */
+ }
+
+ movecursor(row, cp1 - &vp1->v_text[0]); /* Go to start of line. */
+#if REVSTA
+ (*term.t_rev)((vp1->v_flag & VFREV) == VFREV);
+#endif
+
+ while (cp1 != cp5) { /* Ordinary. */
+ (*term.t_putchar)(*cp1);
+ ++ttcol;
+ *cp2++ = *cp1++;
+ }
+
+ if (cp5 != cp3) { /* Erase. */
+ (*term.t_eeol)();
+ while (cp1 != cp3)
+ *cp2++ = *cp1++;
+ }
+#if REVSTA
+ (*term.t_rev)(FALSE);
+#endif
+ vp1->v_flag &= ~VFCHG; /* flag this line is changed */
+ return(TRUE);
+#endif
+}
+#endif
+
+/*
+ * Redisplay the mode line for the window pointed to by the "wp". This is the
+ * only routine that has any idea of how the modeline is formatted. You can
+ * change the modeline format by hacking at this routine. Called by "update"
+ * any time there is a dirty window.
+ */
+modeline(wp)
+ WINDOW *wp;
+{
+ register char *cp;
+ register int c;
+ register int n; /* cursor position count */
+ register BUFFER *bp;
+ register i; /* loop index */
+ register lchar; /* character to draw line in buffer with */
+ register firstm; /* is this the first mode? */
+ char tline[NLINE]; /* buffer for part of mode line */
+
+ n = wp->w_toprow+wp->w_ntrows; /* Location. */
+ vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
+#if COLOR
+ vscreen[n]->v_rfcolor = 0; /* black on */
+ vscreen[n]->v_rbcolor = 7; /* white.....*/
+#endif
+ vtmove(n, 0); /* Seek to right line. */
+ if (wp == curwp) /* mark the current buffer */
+ lchar = '=';
+ else
+#if REVSTA
+ if (revexist)
+ lchar = ' ';
+ else
+#endif
+ lchar = '-';
+
+ vtputc(lchar);
+ bp = wp->w_bufp;
+
+ if ((bp->b_flag&BFCHG) != 0) /* "*" if changed. */
+ vtputc('*');
+ else
+ vtputc(lchar);
+
+ n = 2;
+ strcpy(tline, " MicroEMACS 3.7 ("); /* Buffer name. */
+
+ /* display the modes */
+
+ firstm = TRUE;
+ for (i = 0; i < NUMMODES; i++) /* add in the mode flags */
+ if (wp->w_bufp->b_mode & (1 << i)) {
+ if (firstm != TRUE)
+ strcat(tline, " ");
+ firstm = FALSE;
+ strcat(tline, modename[i]);
+ }
+ strcat(tline,") ");
+
+ cp = &tline[0];
+ while ((c = *cp++) != 0)
+ {
+ vtputc(c);
+ ++n;
+ }
+
+#if WFDEBUG
+ vtputc(lchar);
+ vtputc((wp->w_flag&WFCOLR) != 0 ? 'C' : lchar);
+ vtputc((wp->w_flag&WFMODE) != 0 ? 'M' : lchar);
+ vtputc((wp->w_flag&WFHARD) != 0 ? 'H' : lchar);
+ vtputc((wp->w_flag&WFEDIT) != 0 ? 'E' : lchar);
+ vtputc((wp->w_flag&WFMOVE) != 0 ? 'V' : lchar);
+ vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar);
+ vtputc(lchar);
+ n += 8;
+#endif
+
+ vtputc(lchar);
+ vtputc(lchar);
+ vtputc(' ');
+ n += 3;
+ cp = &bp->b_bname[0];
+
+ while ((c = *cp++) != 0)
+ {
+ vtputc(c);
+ ++n;
+ }
+
+ vtputc(' ');
+ vtputc(lchar);
+ vtputc(lchar);
+ n += 3;
+
+ if (bp->b_fname[0] != 0) /* File name. */
+ {
+ vtputc(' ');
+ ++n;
+ cp = "File: ";
+
+ while ((c = *cp++) != 0)
+ {
+ vtputc(c);
+ ++n;
+ }
+
+ cp = &bp->b_fname[0];
+
+ while ((c = *cp++) != 0)
+ {
+ vtputc(c);
+ ++n;
+ }
+
+ vtputc(' ');
+ ++n;
+ }
+
+ while (n < term.t_ncol) /* Pad to full width. */
+ {
+ vtputc(lchar);
+ ++n;
+ }
+}
+
+upmode() /* update all the mode lines */
+
+{
+ register WINDOW *wp;
+
+ wp = wheadp;
+ while (wp != NULL) {
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+}
+
+/*
+ * Send a command to the terminal to move the hardware cursor to row "row"
+ * and column "col". The row and column arguments are origin 0. Optimize out
+ * random calls. Update "ttrow" and "ttcol".
+ */
+movecursor(row, col)
+ {
+ if (row!=ttrow || col!=ttcol)
+ {
+ ttrow = row;
+ ttcol = col;
+ (*term.t_move)(row, col);
+ }
+ }
+
+/*
+ * Erase the message line. This is a special routine because the message line
+ * is not considered to be part of the virtual screen. It always works
+ * immediately; the terminal buffer is flushed via a call to the flusher.
+ */
+mlerase()
+ {
+ int i;
+
+ movecursor(term.t_nrow, 0);
+#if COLOR
+ (*term.t_setfor)(7);
+ (*term.t_setback)(0);
+#endif
+ if (eolexist == TRUE)
+ (*term.t_eeol)();
+ else {
+ for (i = 0; i < term.t_ncol - 1; i++)
+ (*term.t_putchar)(' ');
+ movecursor(term.t_nrow, 1); /* force the move! */
+ movecursor(term.t_nrow, 0);
+ }
+ (*term.t_flush)();
+ mpresf = FALSE;
+ }
+
+/*
+ * Write a message into the message line. Keep track of the physical cursor
+ * position. A small class of printf like format items is handled. Assumes the
+ * stack grows down; this assumption is made by the "++" in the argument scan
+ * loop. Set the "message line" flag TRUE.
+ */
+
+mlwrite(fmt, arg)
+ char *fmt;
+ {
+ register int c;
+ register char *ap;
+
+#if COLOR
+ (*term.t_setfor)(7);
+ (*term.t_setback)(0);
+#endif
+ if (eolexist == FALSE) {
+ mlerase();
+ (*term.t_flush)();
+ }
+
+ movecursor(term.t_nrow, 0);
+ ap = (char *) &arg;
+ while ((c = *fmt++) != 0) {
+ if (c != '%') {
+ (*term.t_putchar)(c);
+ ++ttcol;
+ }
+ else
+ {
+ c = *fmt++;
+ switch (c) {
+ case 'd':
+ mlputi(*(int *)ap, 10);
+ ap += sizeof(int);
+ break;
+
+ case 'o':
+ mlputi(*(int *)ap, 8);
+ ap += sizeof(int);
+ break;
+
+ case 'x':
+ mlputi(*(int *)ap, 16);
+ ap += sizeof(int);
+ break;
+
+ case 'D':
+ mlputli(*(long *)ap, 10);
+ ap += sizeof(long);
+ break;
+
+ case 's':
+ mlputs(*(char **)ap);
+ ap += sizeof(char *);
+ break;
+
+ case 'f':
+ mlputf(*(int *)ap);
+ ap += sizeof(int);
+ break;
+
+ default:
+ (*term.t_putchar)(c);
+ ++ttcol;
+ }
+ }
+ }
+ if (eolexist == TRUE)
+ (*term.t_eeol)();
+ (*term.t_flush)();
+ mpresf = TRUE;
+ }
+
+/*
+ * Write out a string. Update the physical cursor position. This assumes that
+ * the characters in the string all have width "1"; if this is not the case
+ * things will get screwed up a little.
+ */
+mlputs(s)
+ char *s;
+ {
+ register int c;
+
+ while ((c = *s++) != 0)
+ {
+ (*term.t_putchar)(c);
+ ++ttcol;
+ }
+ }
+
+/*
+ * Write out an integer, in the specified radix. Update the physical cursor
+ * position.
+ */
+mlputi(i, r)
+ {
+ register int q;
+ static char hexdigits[] = "0123456789ABCDEF";
+
+ if (i < 0)
+ {
+ i = -i;
+ (*term.t_putchar)('-');
+ }
+
+ q = i/r;
+
+ if (q != 0)
+ mlputi(q, r);
+
+ (*term.t_putchar)(hexdigits[i%r]);
+ ++ttcol;
+ }
+
+/*
+ * do the same except as a long integer.
+ */
+mlputli(l, r)
+ long l;
+ {
+ register long q;
+
+ if (l < 0)
+ {
+ l = -l;
+ (*term.t_putchar)('-');
+ }
+
+ q = l/r;
+
+ if (q != 0)
+ mlputli(q, r);
+
+ (*term.t_putchar)((int)(l%r)+'0');
+ ++ttcol;
+ }
+
+/*
+ * write out a scaled integer with two decimal places
+ */
+
+mlputf(s)
+
+int s; /* scaled integer to output */
+
+{
+ int i; /* integer portion of number */
+ int f; /* fractional portion of number */
+
+ /* break it up */
+ i = s / 100;
+ f = s % 100;
+
+ /* send out the integer portion */
+ mlputi(i, 10);
+ (*term.t_putchar)('.');
+ (*term.t_putchar)((f / 10) + '0');
+ (*term.t_putchar)((f % 10) + '0');
+ ttcol += 3;
+}
+
+#if RAINBOW
+
+putline(row, col, buf)
+ int row, col;
+ char buf[];
+ {
+ int n;
+
+ n = strlen(buf);
+ if (col + n - 1 > term.t_ncol)
+ n = term.t_ncol - col + 1;
+ Put_Data(row, col, n, buf);
+ }
+#endif
+
Added: clients/emacs/ebind.h
===================================================================
--- clients/emacs/ebind.h (rev 0)
+++ clients/emacs/ebind.h 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,357 @@
+/* EBIND: Initial default key to function bindings for
+ MicroEMACS 3.7
+*/
+
+/*
+ * Command table.
+ * This table is *roughly* in ASCII order, left to right across the
+ * characters of the command. This expains the funny location of the
+ * control-X commands.
+ */
+KEYTAB keytab[NBINDS] = {
+ {CTRL|'A', gotobol},
+ {CTRL|'B', backchar},
+ {CTRL|'C', insspace},
+ {CTRL|'D', forwdel},
+ {CTRL|'E', gotoeol},
+ {CTRL|'F', forwchar},
+ {CTRL|'G', ctrlg},
+ {CTRL|'H', backdel},
+ {CTRL|'I', tab},
+ {CTRL|'J', indent},
+ {CTRL|'K', killtext},
+ {CTRL|'L', refresh},
+ {CTRL|'M', newline},
+ {CTRL|'N', forwline},
+ {CTRL|'O', openline},
+ {CTRL|'P', backline},
+ {CTRL|'Q', quote},
+ {CTRL|'R', backsearch},
+ {CTRL|'S', forwsearch},
+ {CTRL|'T', twiddle},
+ {CTRL|'V', forwpage},
+ {CTRL|'W', killregion},
+ {CTRL|'X', cex},
+ {CTRL|'Y', yank},
+ {CTRL|'Z', backpage},
+ {CTRL|']', meta},
+ {CTLX|CTRL|'B', listbuffers},
+ {CTLX|CTRL|'C', quit}, /* Hard quit. */
+ {CTLX|CTRL|'F', filefind},
+ {CTLX|CTRL|'I', insfile},
+ {CTLX|CTRL|'L', lowerregion},
+ {CTLX|CTRL|'M', delmode},
+ {CTLX|CTRL|'N', mvdnwind},
+ {CTLX|CTRL|'O', deblank},
+ {CTLX|CTRL|'P', mvupwind},
+ {CTLX|CTRL|'R', fileread},
+ {CTLX|CTRL|'S', filesave},
+ {CTLX|CTRL|'U', upperregion},
+ {CTLX|CTRL|'V', viewfile},
+ {CTLX|CTRL|'W', filewrite},
+ {CTLX|CTRL|'X', swapmark},
+ {CTLX|CTRL|'Z', shrinkwind},
+ {CTLX|'?', deskey},
+ {CTLX|'!', spawn},
+ {CTLX|'@', pipe},
+ {CTLX|'#', filter},
+ {CTLX|'=', showcpos},
+ {CTLX|'(', ctlxlp},
+ {CTLX|')', ctlxrp},
+ {CTLX|'^', enlargewind},
+ {CTLX|'0', delwind},
+ {CTLX|'1', onlywind},
+ {CTLX|'2', splitwind},
+ {CTLX|'B', usebuffer},
+ {CTLX|'C', spawncli},
+#if BSD
+ {CTLX|'D', bktoshell},
+#endif
+ {CTLX|'E', ctlxe},
+ {CTLX|'F', setfillcol},
+ {CTLX|'K', killbuffer},
+ {CTLX|'M', setmode},
+ {CTLX|'N', filename},
+ {CTLX|'O', nextwind},
+ {CTLX|'P', prevwind},
+#if ISRCH
+ {CTLX|'R', risearch},
+ {CTLX|'S', fisearch},
+#endif
+ {CTLX|'W', resize},
+ {CTLX|'X', nextbuffer},
+ {CTLX|'Z', enlargewind},
+#if WORDPRO
+ {META|CTRL|'C', wordcount},
+#endif
+ {META|CTRL|'H', delbword},
+ {META|CTRL|'K', unbindkey},
+ {META|CTRL|'L', reposition},
+ {META|CTRL|'M', delgmode},
+ {META|CTRL|'N', namebuffer},
+ {META|CTRL|'R', qreplace},
+ {META|CTRL|'V', scrnextdw},
+#if WORDPRO
+ {META|CTRL|'W', killpara},
+#endif
+ {META|CTRL|'Z', scrnextup},
+ {META|' ', setmark},
+ {META|'?', help},
+ {META|'!', reposition},
+ {META|'.', setmark},
+ {META|'>', gotoeob},
+ {META|'<', gotobob},
+ {META|'~', unmark},
+ {META|'B', backword},
+ {META|'C', capword},
+ {META|'D', delfword},
+ {META|'F', forwword},
+ {META|'G', gotoline},
+ {META|'K', bindtokey},
+ {META|'L', lowerword},
+ {META|'M', setgmode},
+#if WORDPRO
+ {META|'N', gotoeop},
+ {META|'P', gotobop},
+ {META|'Q', fillpara},
+#endif
+ {META|'R', sreplace},
+#if BSD
+ {META|'S', bktoshell},
+#endif
+ {META|'U', upperword},
+ {META|'V', backpage},
+ {META|'W', copyregion},
+ {META|'X', namedcmd},
+ {META|'Z', quickexit},
+ {META|0x7F, delbword},
+
+#if OFW
+ {SPEC|0x48, gotobob},
+ {SPEC|0x41, backline},
+ {SPEC|0x3f, backpage},
+ {SPEC|0x44, backchar},
+ {SPEC|0x43, forwchar},
+ {SPEC|0x4b, gotoeob},
+ {SPEC|0x42, forwline},
+ {SPEC|0x2f, forwpage},
+ {SPEC|0x40, insspace},
+/* {SPEC|83, forwdel},
+ {SPEC|115, backword},
+ {SPEC|116, forwword},
+ {SPEC|132, gotobop},
+ {SPEC|118, gotoeop}, */
+ {SPEC|0x50, cbuf1},
+ {SPEC|0x51, cbuf2},
+ {SPEC|0x77, cbuf3},
+ {SPEC|0x78, cbuf4},
+ {SPEC|0x74, cbuf5},
+ {SPEC|0x75, cbuf6},
+ {SPEC|0x71, cbuf7},
+ {SPEC|0x72, cbuf8},
+ {SPEC|0x70, cbuf9},
+ {SPEC|0x4d, cbuf10},
+#endif
+
+#if MSDOS & (HP150 == 0) & (WANGPC == 0)
+ {SPEC|CTRL|'_', forwhunt},
+ {SPEC|CTRL|'S', backhunt},
+ {SPEC|71, gotobob},
+ {SPEC|72, backline},
+ {SPEC|73, backpage},
+ {SPEC|75, backchar},
+ {SPEC|77, forwchar},
+ {SPEC|79, gotoeob},
+ {SPEC|80, forwline},
+ {SPEC|81, forwpage},
+ {SPEC|82, insspace},
+ {SPEC|83, forwdel},
+ {SPEC|115, backword},
+ {SPEC|116, forwword},
+ {SPEC|132, gotobop},
+ {SPEC|118, gotoeop},
+ {SPEC|84, cbuf1},
+ {SPEC|85, cbuf2},
+ {SPEC|86, cbuf3},
+ {SPEC|87, cbuf4},
+ {SPEC|88, cbuf5},
+ {SPEC|89, cbuf6},
+ {SPEC|90, cbuf7},
+ {SPEC|91, cbuf8},
+ {SPEC|92, cbuf9},
+ {SPEC|93, cbuf10},
+#endif
+
+#if HP150
+ {SPEC|32, backline},
+ {SPEC|33, forwline},
+ {SPEC|35, backchar},
+ {SPEC|34, forwchar},
+ {SPEC|44, gotobob},
+ {SPEC|46, forwpage},
+ {SPEC|47, backpage},
+ {SPEC|82, nextwind},
+ {SPEC|68, openline},
+ {SPEC|69, killtext},
+ {SPEC|65, forwdel},
+ {SPEC|64, ctlxe},
+ {SPEC|67, refresh},
+ {SPEC|66, reposition},
+ {SPEC|83, help},
+ {SPEC|81, deskey},
+#endif
+
+#if AMIGA
+ {SPEC|'?', help},
+ {SPEC|'A', backline},
+ {SPEC|'B', forwline},
+ {SPEC|'C', forwchar},
+ {SPEC|'D', backchar},
+ {SPEC|'T', backpage},
+ {SPEC|'S', forwpage},
+ {SPEC|'a', backword},
+ {SPEC|'`', forwword},
+ {SPEC|'P', cbuf1},
+ {SPEC|'Q', cbuf2},
+ {SPEC|'R', cbuf3},
+ {SPEC|'S', cbuf4},
+ {SPEC|'T', cbuf5},
+ {SPEC|'U', cbuf6},
+ {SPEC|'V', cbuf7},
+ {SPEC|'W', cbuf8},
+ {SPEC|'X', cbuf9},
+ {SPEC|'Y', cbuf10},
+
+#endif
+
+#if WANGPC
+ SPEC|0xE0, quit, /* Cancel */
+ SPEC|0xE1, help, /* Help */
+ SPEC|0xF1, help, /* ^Help */
+ SPEC|0xE3, ctrlg, /* Print */
+ SPEC|0xF3, ctrlg, /* ^Print */
+ SPEC|0xC0, backline, /* North */
+ SPEC|0xD0, gotobob, /* ^North */
+ SPEC|0xC1, forwchar, /* East */
+ SPEC|0xD1, gotoeol, /* ^East */
+ SPEC|0xC2, forwline, /* South */
+ SPEC|0xD2, gotobop, /* ^South */
+ SPEC|0xC3, backchar, /* West */
+ SPEC|0xD3, gotobol, /* ^West */
+ SPEC|0xC4, ctrlg, /* Home */
+ SPEC|0xD4, gotobob, /* ^Home */
+ SPEC|0xC5, filesave, /* Execute */
+ SPEC|0xD5, ctrlg, /* ^Execute */
+ SPEC|0xC6, insfile, /* Insert */
+ SPEC|0xD6, ctrlg, /* ^Insert */
+ SPEC|0xC7, forwdel, /* Delete */
+ SPEC|0xD7, killregion, /* ^Delete */
+ SPEC|0xC8, backpage, /* Previous */
+ SPEC|0xD8, prevwind, /* ^Previous */
+ SPEC|0xC9, forwpage, /* Next */
+ SPEC|0xD9, nextwind, /* ^Next */
+ SPEC|0xCB, ctrlg, /* Erase */
+ SPEC|0xDB, ctrlg, /* ^Erase */
+ SPEC|0xDC, ctrlg, /* ^Tab */
+ SPEC|0xCD, ctrlg, /* BackTab */
+ SPEC|0xDD, ctrlg, /* ^BackTab */
+ SPEC|0x80, ctrlg, /* Indent */
+ SPEC|0x90, ctrlg, /* ^Indent */
+ SPEC|0x81, ctrlg, /* Page */
+ SPEC|0x91, ctrlg, /* ^Page */
+ SPEC|0x82, ctrlg, /* Center */
+ SPEC|0x92, ctrlg, /* ^Center */
+ SPEC|0x83, ctrlg, /* DecTab */
+ SPEC|0x93, ctrlg, /* ^DecTab */
+ SPEC|0x84, ctrlg, /* Format */
+ SPEC|0x94, ctrlg, /* ^Format */
+ SPEC|0x85, ctrlg, /* Merge */
+ SPEC|0x95, ctrlg, /* ^Merge */
+ SPEC|0x86, setmark, /* Note */
+ SPEC|0x96, ctrlg, /* ^Note */
+ SPEC|0x87, ctrlg, /* Stop */
+ SPEC|0x97, ctrlg, /* ^Stop */
+ SPEC|0x88, forwsearch, /* Srch */
+ SPEC|0x98, backsearch, /* ^Srch */
+ SPEC|0x89, sreplace, /* Replac */
+ SPEC|0x99, qreplace, /* ^Replac */
+ SPEC|0x8A, ctrlg, /* Copy */
+ SPEC|0x9A, ctrlg, /* ^Copy */
+ SPEC|0x8B, ctrlg, /* Move */
+ SPEC|0x9B, ctrlg, /* ^Move */
+ SPEC|0x8C, namedcmd, /* Command */
+ SPEC|0x9C, spawn, /* ^Command */
+ SPEC|0x8D, ctrlg, /* ^ */
+ SPEC|0x9D, ctrlg, /* ^^ */
+ SPEC|0x8E, ctrlg, /* Blank */
+ SPEC|0x9E, ctrlg, /* ^Blank */
+ SPEC|0x8F, gotoline, /* GoTo */
+ SPEC|0x9F, usebuffer, /* ^GoTo */
+#endif
+
+ {0x7F, backdel},
+ {0, NULL}
+};
+
+#if RAINBOW
+
+#include "rainbow.h"
+
+/*
+ * Mapping table from the LK201 function keys to the internal EMACS character.
+ */
+
+short lk_map[][2] = {
+ Up_Key, CTRL+'P',
+ Down_Key, CTRL+'N',
+ Left_Key, CTRL+'B',
+ Right_Key, CTRL+'F',
+ Shift+Left_Key, META+'B',
+ Shift+Right_Key, META+'F',
+ Control+Left_Key, CTRL+'A',
+ Control+Right_Key, CTRL+'E',
+ Prev_Scr_Key, META+'V',
+ Next_Scr_Key, CTRL+'V',
+ Shift+Up_Key, META+'<',
+ Shift+Down_Key, META+'>',
+ Cancel_Key, CTRL+'G',
+ Find_Key, CTRL+'S',
+ Shift+Find_Key, CTRL+'R',
+ Insert_Key, CTRL+'Y',
+ Options_Key, CTRL+'D',
+ Shift+Options_Key, META+'D',
+ Remove_Key, CTRL+'W',
+ Shift+Remove_Key, META+'W',
+ Select_Key, CTRL+'@',
+ Shift+Select_Key, CTLX+CTRL+'X',
+ Interrupt_Key, CTRL+'U',
+ Keypad_PF2, META+'L',
+ Keypad_PF3, META+'C',
+ Keypad_PF4, META+'U',
+ Shift+Keypad_PF2, CTLX+CTRL+'L',
+ Shift+Keypad_PF4, CTLX+CTRL+'U',
+ Keypad_1, CTLX+'1',
+ Keypad_2, CTLX+'2',
+ Do_Key, CTLX+'E',
+ Keypad_4, CTLX+CTRL+'B',
+ Keypad_5, CTLX+'B',
+ Keypad_6, CTLX+'K',
+ Resume_Key, META+'!',
+ Control+Next_Scr_Key, CTLX+'N',
+ Control+Prev_Scr_Key, CTLX+'P',
+ Control+Up_Key, CTLX+CTRL+'P',
+ Control+Down_Key, CTLX+CTRL+'N',
+ Help_Key, CTLX+'=',
+ Shift+Do_Key, CTLX+'(',
+ Control+Do_Key, CTLX+')',
+ Keypad_0, CTLX+'Z',
+ Shift+Keypad_0, CTLX+CTRL+'Z',
+ Main_Scr_Key, CTRL+'C',
+ Keypad_Enter, CTLX+'!',
+ Exit_Key, CTLX+CTRL+'C',
+ Shift+Exit_Key, CTRL+'Z'
+};
+
+#define lk_map_size (sizeof(lk_map)/2)
+#endif
+
Added: clients/emacs/edef.h
===================================================================
--- clients/emacs/edef.h (rev 0)
+++ clients/emacs/edef.h 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,140 @@
+/* EDEF: Global variable definitions for
+ MicroEMACS 3.2
+
+ written by Dave G. Conroy
+ modified by Steve Wilhite, George Jones
+ greatly modified by Daniel Lawrence
+*/
+
+/* some global fuction declarations */
+
+/* char *malloc(); */
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef maindef
+
+/* for MAIN.C */
+
+/* initialized global definitions */
+
+int fillcol = 72; /* Current fill column */
+short kbdm[NKBDM] = {CTLX|')'}; /* Macro */
+char pat[NPAT]; /* Search pattern */
+char rpat[NPAT]; /* replacement pattern */
+char sarg[NSTRING] = ""; /* string argument for line exec*/
+int eolexist = TRUE; /* does clear to EOL exist */
+int revexist = FALSE; /* does reverse video exist? */
+char *modename[] = { /* name of modes */
+ "WRAP", "CMODE", "SPELL", "EXACT", "VIEW", "OVER", "MAGIC"};
+char modecode[] = "WCSEVOM"; /* letters to represent modes */
+int gmode = 0; /* global editor mode */
+int gfcolor = 7; /* global forgrnd color (white) */
+int gbcolor = 0; /* global backgrnd color (black)*/
+int sgarbf = TRUE; /* TRUE if screen is garbage */
+int mpresf = FALSE; /* TRUE if message in last line */
+int clexec = FALSE; /* command line execution flag */
+int mstore = FALSE; /* storing text to macro flag */
+struct BUFFER *bstore = NULL; /* buffer to store macro text to*/
+int vtrow = 0; /* Row location of SW cursor */
+int vtcol = 0; /* Column location of SW cursor */
+int ttrow = HUGE; /* Row location of HW cursor */
+int ttcol = HUGE; /* Column location of HW cursor */
+int lbound = 0; /* leftmost column of current line
+ being displayed */
+int metac = CTRL | '['; /* current meta character */
+int ctlxc = CTRL | 'X'; /* current control X prefix char */
+int quotec = 0x11; /* quote char during mlreply() */
+char *cname[] = { /* names of colors */
+ "BLACK", "RED", "GREEN", "YELLOW", "BLUE",
+ "MAGENTA", "CYAN", "WHITE"};
+KILL *kbufp = NULL; /* current kill buffer chunk pointer */
+KILL *kbufh = NULL; /* kill buffer header pointer */
+int kused = KBLOCK; /* # of bytes used in kill buffer */
+WINDOW *swindow = NULL; /* saved window pointer */
+
+/* uninitialized global definitions */
+
+int currow; /* Cursor row */
+int curcol; /* Cursor column */
+int thisflag; /* Flags, this command */
+int lastflag; /* Flags, last command */
+int curgoal; /* Goal for C-P, C-N */
+WINDOW *curwp; /* Current window */
+BUFFER *curbp; /* Current buffer */
+WINDOW *wheadp; /* Head of list of windows */
+BUFFER *bheadp; /* Head of list of buffers */
+BUFFER *blistp; /* Buffer for C-X C-B */
+short *kbdmip; /* Input pointer for above */
+short *kbdmop; /* Output pointer for above */
+
+BUFFER *bfind(); /* Lookup a buffer by name */
+WINDOW *wpopup(); /* Pop up window creation */
+LINE *lalloc(); /* Allocate a line */
+
+#else
+
+/* for all the other .C files */
+
+/* initialized global external declarations */
+
+extern int fillcol; /* Fill column */
+extern short kbdm[]; /* Holds kayboard macro data */
+extern char pat[]; /* Search pattern */
+extern char rpat[]; /* Replacement pattern */
+extern char sarg[]; /* string argument for line exec*/
+extern int eolexist; /* does clear to EOL exist? */
+extern int revexist; /* does reverse video exist? */
+extern char *modename[]; /* text names of modes */
+extern char modecode[]; /* letters to represent modes */
+extern KEYTAB keytab[]; /* key bind to functions table */
+extern NBIND names[]; /* name to function table */
+extern int gmode; /* global editor mode */
+extern int gfcolor; /* global forgrnd color (white) */
+extern int gbcolor; /* global backgrnd color (black)*/
+extern int sgarbf; /* State of screen unknown */
+extern int mpresf; /* Stuff in message line */
+extern int clexec; /* command line execution flag */
+extern int mstore; /* storing text to macro flag */
+extern struct BUFFER *bstore; /* buffer to store macro text to*/
+extern int vtrow; /* Row location of SW cursor */
+extern int vtcol; /* Column location of SW cursor */
+extern int ttrow; /* Row location of HW cursor */
+extern int ttcol; /* Column location of HW cursor */
+extern int lbound; /* leftmost column of current line
+ being displayed */
+extern int metac; /* current meta character */
+extern int ctlxc; /* current control X prefix char */
+extern int quotec; /* quote char during mlreply() */
+extern char *cname[]; /* names of colors */
+extern KILL *kbufp; /* current kill buffer chunk pointer */
+extern KILL *kbufh; /* kill buffer header pointer */
+extern int kused; /* # of bytes used in KB */
+extern WINDOW *swindow; /* saved window pointer */
+
+/* initialized global external declarations */
+
+extern int currow; /* Cursor row */
+extern int curcol; /* Cursor column */
+extern int thisflag; /* Flags, this command */
+extern int lastflag; /* Flags, last command */
+extern int curgoal; /* Goal for C-P, C-N */
+extern WINDOW *curwp; /* Current window */
+extern BUFFER *curbp; /* Current buffer */
+extern WINDOW *wheadp; /* Head of list of windows */
+extern BUFFER *bheadp; /* Head of list of buffers */
+extern BUFFER *blistp; /* Buffer for C-X C-B */
+extern short *kbdmip; /* Input pointer for above */
+extern short *kbdmop; /* Output pointer for above */
+
+extern BUFFER *bfind(); /* Lookup a buffer by name */
+extern WINDOW *wpopup(); /* Pop up window creation */
+extern LINE *lalloc(); /* Allocate a line */
+
+#endif
+
+/* terminal table defined only in TERM.C */
+
+#ifndef termdef
+extern TERM term; /* Terminal information. */
+#endif
Added: clients/emacs/efunc.h
===================================================================
--- clients/emacs/efunc.h (rev 0)
+++ clients/emacs/efunc.h 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,352 @@
+/* EFUNC.H: MicroEMACS function declarations and names
+
+ This file list all the C code functions used by MicroEMACS
+ and the names to use to bind keys to them. To add functions,
+ declare it here in both the extern function list and the name
+ binding table.
+
+*/
+
+/* External function declarations */
+
+extern int ctrlg(); /* Abort out of things */
+extern int quit(); /* Quit */
+extern int ctlxlp(); /* Begin macro */
+extern int ctlxrp(); /* End macro */
+extern int ctlxe(); /* Execute macro */
+extern int fileread(); /* Get a file, read only */
+extern int filefind(); /* Get a file, read write */
+extern int filewrite(); /* Write a file */
+extern int filesave(); /* Save current file */
+extern int filename(); /* Adjust file name */
+extern int getccol(); /* Get current column */
+extern int gotobol(); /* Move to start of line */
+extern int forwchar(); /* Move forward by characters */
+extern int gotoeol(); /* Move to end of line */
+extern int backchar(); /* Move backward by characters */
+extern int forwline(); /* Move forward by lines */
+extern int backline(); /* Move backward by lines */
+extern int forwpage(); /* Move forward by pages */
+extern int backpage(); /* Move backward by pages */
+extern int gotobob(); /* Move to start of buffer */
+extern int gotoeob(); /* Move to end of buffer */
+extern int setfillcol(); /* Set fill column. */
+extern int setmark(); /* Set mark */
+extern int swapmark(); /* Swap "." and mark */
+extern int forwsearch(); /* Search forward */
+extern int backsearch(); /* Search backwards */
+extern int sreplace(); /* search and replace */
+extern int qreplace(); /* search and replace w/query */
+extern int showcpos(); /* Show the cursor position */
+extern int nextwind(); /* Move to the next window */
+extern int prevwind(); /* Move to the previous window */
+extern int onlywind(); /* Make current window only one */
+extern int splitwind(); /* Split current window */
+extern int mvdnwind(); /* Move window down */
+extern int mvupwind(); /* Move window up */
+extern int enlargewind(); /* Enlarge display window. */
+extern int shrinkwind(); /* Shrink window. */
+extern int listbuffers(); /* Display list of buffers */
+extern int usebuffer(); /* Switch a window to a buffer */
+extern int killbuffer(); /* Make a buffer go away. */
+extern int reposition(); /* Reposition window */
+extern int refresh(); /* Refresh the screen */
+extern int twiddle(); /* Twiddle characters */
+extern int tab(); /* Insert tab */
+extern int newline(); /* Insert CR-LF */
+extern int indent(); /* Insert CR-LF, then indent */
+extern int openline(); /* Open up a blank line */
+extern int deblank(); /* Delete blank lines */
+extern int quote(); /* Insert literal */
+extern int backword(); /* Backup by words */
+extern int forwword(); /* Advance by words */
+extern int forwdel(); /* Forward delete */
+extern int backdel(); /* Backward delete */
+extern int killtext(); /* Kill forward */
+extern int yank(); /* Yank back from killbuffer. */
+extern int upperword(); /* Upper case word. */
+extern int lowerword(); /* Lower case word. */
+extern int upperregion(); /* Upper case region. */
+extern int lowerregion(); /* Lower case region. */
+extern int capword(); /* Initial capitalize word. */
+extern int delfword(); /* Delete forward word. */
+extern int delbword(); /* Delete backward word. */
+extern int killregion(); /* Kill region. */
+extern int copyregion(); /* Copy region to kill buffer. */
+extern int spawncli(); /* Run CLI in a subjob. */
+extern int spawn(); /* Run a command in a subjob. */
+#if BSD
+extern int bktoshell(); /* suspend emacs to parent shell*/
+extern int rtfrmshell(); /* return from a suspended state*/
+#endif
+extern int quickexit(); /* low keystroke style exit. */
+extern int setmode(); /* set an editor mode */
+extern int delmode(); /* delete a mode */
+extern int gotoline(); /* go to a numbered line */
+extern int namebuffer(); /* rename the current buffer */
+#if WORDPRO
+extern int gotobop(); /* go to begining/paragraph */
+extern int gotoeop(); /* go to end/paragraph */
+extern int fillpara(); /* fill current paragraph */
+#endif
+extern int help(); /* get the help file here */
+extern int deskey(); /* describe a key's binding */
+extern int viewfile(); /* find a file in view mode */
+extern int insfile(); /* insert a file */
+extern int scrnextup(); /* scroll next window back */
+extern int scrnextdw(); /* scroll next window down */
+extern int bindtokey(); /* bind a function to a key */
+extern int unbindkey(); /* unbind a key's function */
+extern int namedcmd(); /* execute named command */
+extern int desbind(); /* describe bindings */
+extern int execcmd(); /* execute a command line */
+extern int execbuf(); /* exec commands from a buffer */
+extern int execfile(); /* exec commands from a file */
+extern int nextbuffer(); /* switch to the next buffer */
+#if WORDPRO
+extern int killpara(); /* kill the current paragraph */
+#endif
+extern int setgmode(); /* set a global mode */
+extern int delgmode(); /* delete a global mode */
+extern int insspace(); /* insert a space forword */
+extern int forwhunt(); /* hunt forward for next match */
+extern int backhunt(); /* hunt backwards for next match*/
+extern int pipe(); /* pipe command into buffer */
+extern int filter(); /* filter buffer through dos */
+extern int delwind(); /* delete the current window */
+extern int cbuf1(); /* execute numbered comd buffer */
+extern int cbuf2();
+extern int cbuf3();
+extern int cbuf4();
+extern int cbuf5();
+extern int cbuf6();
+extern int cbuf7();
+extern int cbuf8();
+extern int cbuf9();
+extern int cbuf10();
+extern int cbuf11();
+extern int cbuf12();
+extern int cbuf13();
+extern int cbuf14();
+extern int cbuf15();
+extern int cbuf16();
+extern int cbuf17();
+extern int cbuf18();
+extern int cbuf19();
+extern int cbuf20();
+extern int cbuf21();
+extern int cbuf22();
+extern int cbuf23();
+extern int cbuf24();
+extern int cbuf25();
+extern int cbuf26();
+extern int cbuf27();
+extern int cbuf28();
+extern int cbuf29();
+extern int cbuf30();
+extern int cbuf31();
+extern int cbuf32();
+extern int cbuf33();
+extern int cbuf34();
+extern int cbuf35();
+extern int cbuf36();
+extern int cbuf37();
+extern int cbuf38();
+extern int cbuf39();
+extern int cbuf40();
+extern int storemac(); /* store text for macro */
+extern int resize(); /* resize current window */
+extern int clrmes(); /* clear the message line */
+extern int meta(); /* meta prefix dummy function */
+extern int cex(); /* ^X prefix dummy function */
+extern int istring(); /* insert string in text */
+extern int unmark(); /* unmark current buffer */
+#if ISRCH
+extern int fisearch(); /* forward incremental search */
+extern int risearch(); /* reverse incremental search */
+#endif
+#if WORDPRO
+extern int wordcount(); /* count words in region */
+#endif
+extern int savewnd(); /* save current window */
+extern int restwnd(); /* restore current window */
+extern int upscreen(); /* force screen update */
+extern int writemsg(); /* write text on message line */
+
+/* Name to function binding table
+
+ This table gives the names of all the bindable functions
+ end their C function address. These are used for the bind-to-key
+ function.
+*/
+
+NBIND names[] = {
+ {"add-mode", setmode},
+ {"add-global-mode", setgmode},
+ {"backward-character", backchar},
+ {"begin-macro", ctlxlp},
+ {"begining-of-file", gotobob},
+ {"begining-of-line", gotobol},
+ {"bind-to-key", bindtokey},
+ {"buffer-position", showcpos},
+ {"case-region-lower", lowerregion},
+ {"case-region-upper", upperregion},
+ {"case-word-capitalize", capword},
+ {"case-word-lower", lowerword},
+ {"case-word-upper", upperword},
+ {"change-file-name", filename},
+ {"clear-and-redraw", refresh},
+ {"clear-message-line", clrmes},
+ {"copy-region", copyregion},
+#if WORDPRO
+ {"count-words", wordcount},
+#endif
+ {"ctlx-prefix", cex},
+ {"delete-blank-lines", deblank},
+ {"delete-buffer", killbuffer},
+ {"delete-mode", delmode},
+ {"delete-global-mode", delgmode},
+ {"delete-next-character", forwdel},
+ {"delete-next-word", delfword},
+ {"delete-other-windows", onlywind},
+ {"delete-previous-character", backdel},
+ {"delete-previous-word", delbword},
+ {"delete-window", delwind},
+ {"describe-bindings", desbind},
+ {"describe-key", deskey},
+ {"end-macro", ctlxrp},
+ {"end-of-file", gotoeob},
+ {"end-of-line", gotoeol},
+ {"exchange-point-and-mark", swapmark},
+ {"execute-buffer", execbuf},
+ {"execute-command-line", execcmd},
+ {"execute-file", execfile},
+ {"execute-macro", ctlxe},
+ {"execute-macro-1", cbuf1},
+ {"execute-macro-2", cbuf2},
+ {"execute-macro-3", cbuf3},
+ {"execute-macro-4", cbuf4},
+ {"execute-macro-5", cbuf5},
+ {"execute-macro-6", cbuf6},
+ {"execute-macro-7", cbuf7},
+ {"execute-macro-8", cbuf8},
+ {"execute-macro-9", cbuf9},
+ {"execute-macro-10", cbuf10},
+ {"execute-macro-11", cbuf11},
+ {"execute-macro-12", cbuf12},
+ {"execute-macro-13", cbuf13},
+ {"execute-macro-14", cbuf14},
+ {"execute-macro-15", cbuf15},
+ {"execute-macro-16", cbuf16},
+ {"execute-macro-17", cbuf17},
+ {"execute-macro-18", cbuf18},
+ {"execute-macro-19", cbuf19},
+ {"execute-macro-20", cbuf20},
+ {"execute-macro-21", cbuf21},
+ {"execute-macro-22", cbuf22},
+ {"execute-macro-23", cbuf23},
+ {"execute-macro-24", cbuf24},
+ {"execute-macro-25", cbuf25},
+ {"execute-macro-26", cbuf26},
+ {"execute-macro-27", cbuf27},
+ {"execute-macro-28", cbuf28},
+ {"execute-macro-29", cbuf29},
+ {"execute-macro-30", cbuf30},
+ {"execute-macro-31", cbuf31},
+ {"execute-macro-32", cbuf32},
+ {"execute-macro-33", cbuf33},
+ {"execute-macro-34", cbuf34},
+ {"execute-macro-35", cbuf35},
+ {"execute-macro-36", cbuf36},
+ {"execute-macro-37", cbuf37},
+ {"execute-macro-38", cbuf38},
+ {"execute-macro-39", cbuf39},
+ {"execute-macro-40", cbuf40},
+ {"execute-named-command", namedcmd},
+ {"exit-emacs", quit},
+#if WORDPRO
+ {"fill-paragraph", fillpara},
+#endif
+ {"filter-buffer", filter},
+ {"find-file", filefind},
+ {"forward-character", forwchar},
+ {"goto-line", gotoline},
+ {"grow-window", enlargewind},
+ {"handle-tab", tab},
+ {"hunt-forward", forwhunt},
+ {"hunt-backward", backhunt},
+ {"help", help},
+ {"i-shell", spawncli},
+#if ISRCH
+ {"incremental-search", fisearch},
+#endif
+ {"insert-file", insfile},
+ {"insert-space", insspace},
+ {"insert-string", istring},
+#if WORDPRO
+ {"kill-paragraph", killpara},
+#endif
+ {"kill-region", killregion},
+ {"kill-to-end-of-line", killtext},
+ {"list-buffers", listbuffers},
+ {"meta-prefix", meta},
+ {"move-window-down", mvdnwind},
+ {"move-window-up", mvupwind},
+ {"name-buffer", namebuffer},
+ {"newline", newline},
+ {"newline-and-indent", indent},
+ {"next-buffer", nextbuffer},
+ {"next-line", forwline},
+ {"next-page", forwpage},
+#if WORDPRO
+ {"next-paragraph", gotoeop},
+#endif
+ {"next-window", nextwind},
+ {"next-word", forwword},
+ {"open-line", openline},
+ {"pipe-command", pipe},
+ {"previous-line", backline},
+ {"previous-page", backpage},
+#if WORDPRO
+ {"previous-paragraph", gotobop},
+#endif
+ {"previous-window", prevwind},
+ {"previous-word", backword},
+ {"query-replace-string", qreplace},
+ {"quick-exit", quickexit},
+ {"quote-character", quote},
+ {"read-file", fileread},
+ {"redraw-display", reposition},
+ {"resize-window", resize},
+ {"restore-window", restwnd},
+ {"replace-string", sreplace},
+#if ISRCH
+ {"reverse-incremental-search", risearch},
+#endif
+ {"save-file", filesave},
+ {"save-window", savewnd},
+ {"scroll-next-up", scrnextup},
+ {"scroll-next-down", scrnextdw},
+ {"search-forward", forwsearch},
+ {"search-reverse", backsearch},
+ {"select-buffer", usebuffer},
+ {"set-fill-column", setfillcol},
+ {"set-mark", setmark},
+ {"shell-command", spawn},
+ {"shrink-window", shrinkwind},
+ {"split-current-window", splitwind},
+ {"store-macro", storemac},
+#if BSD
+ {"suspend-emacs", bktoshell},
+#endif
+ {"transpose-characters", twiddle},
+ {"unbind-key", unbindkey},
+ {"unmark-buffer", unmark},
+ {"update-screen", upscreen},
+ {"view-file", viewfile},
+ {"write-file", filewrite},
+ {"write-message", writemsg},
+ {"yank", yank},
+
+ {"", NULL}
+};
Added: clients/emacs/emacs.hlp
===================================================================
--- clients/emacs/emacs.hlp (rev 0)
+++ clients/emacs/emacs.hlp 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,195 @@
+=> MicroEMACS 3.7 Help screens (07/02/86)
+
+ M- means to use the <ESC> key prior to using another key
+ ^A means to use the control key at the same time as the A key
+
+^V or [Pg Dn] Scroll down M-< or <HOME> Begining of file
+^Z or [Pg Up] Scroll up M-> or <END> End of file
+
+-----------------------------------------------------------------------
+=> (1) MOVING THE CURSOR
+
+^F Forward character M-F Forward word Keypad arrows
+^B Backward character M-B Backward word are active!
+^A Front of line M-G Goto a line
+^E End of line
+^N Next line M-N Front of paragraph
+^P Previous line M-P End of paragraph
+-----------------------------------------------------------------------
+=> (2) DELETING & INSERTING
+
+<-- Delete previous character
+^D or <DELETE> Delete next character
+^C or <INSERT> Insert a space
+M-<-- Delete previous word
+M-D Delete next word
+^K Close (delete) to end of line
+-----------------------------------------------------------------------
+=> (2a) MORE DELETING & INSERTING
+
+<RETURN> Insert a newline <TAB> Advance to next tab stop
+^J Insert a newline and indent M-^W Delete paragraph
+^O Open (insert) line
+^W Delete region between mark (set using M-<spacebar>) and cursor
+M-W Copy region to kill buffer
+^X ^O Delete blank lines around cursor
+-----------------------------------------------------------------------
+=> (3) SEARCHING
+
+^S Search forward from cursor position.
+^R Reverse search from cursor position.
+^X S Forward incremental search
+^X R Reverse incremental search
+-----------------------------------------------------------------------
+=> (4) REPLACING
+
+M-R Replace all instances of first typed-in string with second
+ typed-in string. End each string with ESC.
+M-^R Replace with query. Answer with:
+ ^G cancel . exit to entry point
+ ! replace the rest Y replace & continue
+ ? Get a list of options N no replacement & continue
+-----------------------------------------------------------------------
+=> (5) CAPITALIZING & TRANSPOSING
+
+M-U UPPERCASE word
+M-C Capitalize word ^T Transpose characters
+M-L lowercase word
+^X ^L lowercase region
+^X ^U uppercase region
+^Q Quote next entry, so that control codes may be entered into text
+-----------------------------------------------------------------------
+=> (6) REGIONS & THE KILL BUFFER
+
+M-<spacebar> set MARK at current position
+^X ^X eXchange mark and cursor
+
+A REGION will then be continuously-defined as the area between the mark and
+the current cursor position. The KILL BUFFER is the text which has been
+most recently saved or deleted.
+-----------------------------------------------------------------------
+=> (7) COPYING AND MOVING
+
+^W Delete (Wipe) region M-W copy region to KILL buffer
+^Y Yankback save buffer at cursor
+Generally, the procedure for copying or moving text is:
+ 1) Mark a REGION using M-<spacebar> at beginning and cursor at end.
+ 2) Delete it (with ^W) or copy it (with M-W) into the KILL buffer.
+ 3) Move the cursor to the desired location and yank it back (with ^Y).
+-----------------------------------------------------------------------
+=> (8) MODES OF OPERATION
+^X M Add mode in buffer M-M Add global mode
+^X ^M Delete mode in buffer M-^M Delete global mode
+OVER Replaces (overwrites) rather than inserts characters
+WRAP Turns on word wrap (automatic carraige return).
+VIEW Allows viewing file without insertion and deletion.
+CMODE Automatic indenting for C program entry
+EXACT/MAGIC Changes how search and replace commands work (see next page)
+-----------------------------------------------------------------------
+=> (9) SEARCH AND REPLACE MODES
+
+EXACT Uppper/lower case is not ignored in searches
+MAGIC Regular pattern matching characters are active
+ ? Matches any one character
+ * Matches any sequence of characters
+ [EXACT MODE NOT READY YET ---- 6/5/86]
+
+-----------------------------------------------------------------------
+=> (10) ON-SCREEN FORMATTING
+
+^X F Set fill column
+Mn-<tab> Set tab spacing to n charecters between tabs stops
+M-Q Format paragraph so that text lies between margins
+^X = Position report -- displays line number, char count,
+ file size and character under cursor
+M-^C Count words/lines/chars in marked region
+-----------------------------------------------------------------------
+=> (11) MULTIPLE WINDOWS
+
+Many WINDOWS may be active at once on the screen. All windows may show
+different parts of the same buffer, or each may display a different one.
+^X 2 Split the current window in two ^X O Change to next window
+^X 0 delete current window ^X P Change to previous window
+^X 1 delete all other windows M-^V Page down next window
+ M-^Z Page up other window
+-----------------------------------------------------------------------
+=> (12) CONTROLLING WINDOWS
+
+^X ^ Enlarge current window M-<n> ^X W Resize window to <n> lines
+^X ^Z Shrink current window
+^X ^N Move window down
+^X ^P Move window up
+M-^L Reposition window
+^L Refresh the screen
+-----------------------------------------------------------------------
+=> (13) MULTIPLE BUFFERS
+A BUFFER is a named area containing a document being edited. Many buffers
+may be activated at once.
+^X B Switch to another buffer. <CR> = use just-previous buffer
+^X X Switch to next buffer in buffer list
+M-^N Change name of current buffer
+^X K Delete a non-displayed buffer.
+^X ^B Display buffer directory in a window
+-----------------------------------------------------------------------
+=> (14) READING FROM DISK
+
+^X ^F Find file; read into a new buffer created from filename.
+ (This is the usual way to begin editing a new file.)
+^X ^R Read file into current buffer, erasing its previous contents.
+ No new buffer will be created.
+^X ^I Insert file into current buffer at cursor's location.
+^X ^V Find a file to make current in VIEW mode
+-----------------------------------------------------------------------
+=> (15) SAVING TO DISK
+
+^X ^S Save current buffer to disk
+^X ^W Write current buffer to disk
+^X N Change file name of current buffer
+M-Z Write out all changed buffers and exit MicroEMACS
+
+
+-----------------------------------------------------------------------
+=> (16) ACCESSING THE OPERATING SYSTEM
+
+^X ! Send one command to the operating system and return
+^X @ Pipe DOS command results to buffer
+^X # Filter buffer through DOS filter program
+^X C Start a new command processor under MicroEMACS
+^X D Suspend MicroEMACS into the background (UNIX BSD4.2 only)
+^X ^C Exit MicroEMACS
+-----------------------------------------------------------------------
+=> (17) KEY BINDINGS AND COMMANDS
+
+M-K Bind a key to a command
+M-^K Unbind a key from a command
+^X ? Describe command bound to a key
+M-X Execute a named (and possibly unbound) command
+{Describe-bindings}
+ Display a list of all commands and key bindings to a buffer
+-----------------------------------------------------------------------
+=> (18) COMMAND EXECUTION
+Commands can be specified as command lines in the form:
+ <optional repeat count> {command-name} <optional arguments>
+{Execute-command-line} execute a typed in command line
+{Execute-buffer} executes commands lines in a buffer
+{Execute-file} executes command lines from a file
+{clear-message-line} clears the message line during execution
+ M-~ clears the change flag for a buffer
+-----------------------------------------------------------------------
+=> (19) MACRO EXECUTION
+
+^X ( Start recording keyboard macro
+^X ) Stop recording keyboard macro
+^X E Execute keyboard macro
+M-<n> {store-macro} Start recording named macro
+ [end] Stop recording named macro
+{execute-macro-n} Execute macro n (where n is from 1 to 20)
+-----------------------------------------------------------------------
+=> (20) SPECIAL KEYS
+
+^G Cancel current command and return to top level of processing.
+^U or Universal repeat. May be followed by an integer (default = 4)
+M-<digit> and repeats the next command that many times.
+M-X Execute a named (and possibly unbound) command
+
+
Added: clients/emacs/emacs.key
===================================================================
--- clients/emacs/emacs.key (rev 0)
+++ clients/emacs/emacs.key 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,94 @@
+ Default Key Bindings for MicroEmacs 3.7 (06/05/86)
+ ========================================
+
+ ^A Move to start of line
+ ^B Move backward by characters ESC B Backup by words
+ ^C Insert space ESC C Initial capitalize word
+ ^D Forward delete ESC D Delete forward word
+ ^E Goto end of line
+ ^F Move forward by characters ESC F Advance by words
+ ^G Abort out of things ESC G Go to a line
+ ^H Backward delete
+ ^I Insert tab/Set tab stops
+ ^J Insert CR-LF, then indent
+ ^K Kill forward ESC K Bind Key to function
+ ^L Refresh the screen ESC L Lower case word
+ ^M Insert CR-LF ESC M Add global mode
+ ^N Move forward by lines ESC N Goto End paragraph
+ ^O Open up a blank line
+ ^P Move backward by lines ESC P Goto Begining of paragraph
+ ^Q Insert literal ESC Q Fill current paragraph
+ ^R Search backwards ESC R Search and replace
+ ^S Search forward
+ ^T Transpose characters
+ ^U Repeat command four times ESC U Upper case word
+ ^V Move forward by pages ESC V Move backward by pages
+ ^W Kill region ESC W Copy region to kill buffer
+ ^Y Yank back from killbuffer ESC X Execute named command
+ ^Z Move backward by pages ESC Z Save all buffers and exit
+
+ ESC ^C Count words in region ESC ~ Unmark current buffer
+ ESC ^H Delete backward word ESC ! Reposition window
+ ESC ^K Unbind Key from function ESC < Move to start of buffer
+ ESC ^L Reposition window ESC > Move to end of buffer
+ ESC ^M Delete global mode ESC . Set mark
+ ESC ^N Rename current buffer ESC space Set mark
+ ESC ^R Search & replace w/query ESC rubout Delete backward word
+ ESC ^V Scroll next window down rubout Backward delete
+ ESC ^W Delete Paragraph
+ ESC ^Z Scroll next window up
+
+ ^X ? Describe a key ^X ! Run 1 command in a subjob
+ ^X = Show the cursor position ^X @ Pipe DOS command to buffer
+ ^X ^ Enlarge display window ^X # Filter buffer thru DOS filter
+ ^X 0 Delete current window ^X ( Begin macro
+ ^X 1 Delete other windows ^X ) End macro
+ ^X 2 Split current window
+
+ ^X ^B Display buffer list ^X B Switch a window to a buffer
+ ^X ^C Exit MicroEMACS ^X C Start a new command processer
+ ^X D Suspend MicroEMACS (BSD4.2 only)
+ ^X E Execute macro
+ ^X ^F Find file ^X F Set fill column
+ ^X ^I Insert file
+ ^X K Delete buffer
+ ^X ^L Lower case region
+ ^X ^M Delete Mode ^X M Add a mode
+ ^X ^N Move window down ^X N Rename current filename
+ ^X ^O Delete blank lines ^X O Move to the next window
+ ^X ^P Move window up ^X P Move to the previous window
+ ^X ^R Get a file from disk ^X R Incremental reverse search
+ ^X ^S Save current file ^X S Incremental forward search
+ ^X ^U Upper case region
+ ^X ^V View file
+ ^X ^W Write a file to disk ^X W resize Window
+ ^X ^X Swap "." and mark ^X X Use next buffer
+ ^X ^Z Shrink window ^X Z Enlarge display window
+
+Only under PCDOS:
+ <ALT>-S Hunt forward SHIFT <F1> - <F10>
+ <ALT>-R Hunt backward Execute macroes 1 - 10
+
+Unbound commands:
+=================
+describe-bindings pull the list of current bindings into a window
+clear-message-line clears the message line (for in macroes)
+execute-buffer execute a buffer od command lines
+execute-command-line execute a command line (n <command> <args>)
+execute-file execute a file of command lines
+execute-named-command execute a command by name (w/command completion)
+execute-macro-[1-20] execute macroes 1 thru 20
+hunt-forward find next occurance of search string
+hunt-backward find last occurance of search string
+
+Usable Modes
+============
+WRAP Lines going past right margin "wrap" to a new line
+VIEW Read-Only mode where no modifications are allowed
+CMODE Change behavior of some commands to work with C better
+EXACT Exact case matching on search strings
+OVER Overwrite typed characters instead of inserting them
+MAGIC Use regular expresion matching in searches [NOT READY YET]
+
+WHITE/CYAN/MAGENTA/YELLOW/BLUE/RED/GREEN/BLACK Sets foreground color
+white/cyan/magenta/yellow/blue/red/green/black Sets background color
Added: clients/emacs/emacs.rc
===================================================================
--- clients/emacs/emacs.rc (rev 0)
+++ clients/emacs/emacs.rc 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,97 @@
+; EMACS.RC: Startup file for MicroEMACS 3.4
+;
+; This file is executed everytime the
+; editor is entered
+
+; ***** Rebind the Function key group
+
+bind-to-key execute-macro-11 FN;
+bind-to-key execute-named-command FN<
+bind-to-key hunt-forward FN=
+bind-to-key hunt-backward FN>
+bind-to-key next-window FN?
+bind-to-key execute-macro FN@
+bind-to-key find-file FNA
+bind-to-key view-file FNB
+bind-to-key save-file FNC
+bind-to-key exit-emacs FND
+
+; set screen colors
+add-global-mode "blue"
+
+; Enter Help
+11 store-macro
+ help
+ 8 resize-window
+ bind-to-key execute-macro-12 FNI
+ bind-to-key execute-macro-13 FNQ
+ bind-to-key execute-macro-14 FN;
+ add-mode "red"
+ begining-of-file
+ 2 forward-character
+ clear-message-line
+[end]
+
+; bring up the function key window
+1 store-macro
+ 2 split-current-window
+ select-buffer "Function Keys"
+ add-mode "red"
+ begining-of-file
+ 2 resize-window
+ insert-string "F1 help on/off F2 exec cmd F3 hunt F4 back hunt F5 next window"
+ newline
+ insert-string "F6 exec macro F7 find file F8 view file F9 save file F10 exit emacs"
+ begining-of-file
+ unmark-buffer
+ bind-to-key execute-macro-15 FNT
+ next-window
+[end]
+
+; reselect function key window
+15 store-macro
+ 2 split-current-window
+ select-buffer "Function Keys"
+ begining-of-file
+ 2 resize-window
+ add-mode "red"
+ next-window
+[end]
+
+; consult file
+3 store-macro
+ 2 split-current-window
+ previous-window
+ view-file "@File to Consult: "
+ 8 resize-window
+ add-mode "green"
+ add-mode "Black"
+ next-window
+[end]
+
+; Exit Help
+14 store-macro
+ bind-to-key previous-page FNI
+ bind-to-key next-page FNQ
+ bind-to-key execute-macro-11 FN;
+ delete-window
+ clear-message-line
+[end]
+
+; last help page
+12 store-macro
+ begining-of-line
+ search-reverse "=>"
+ 1 redraw-display
+[end]
+
+; next help page
+13 store-macro
+ begining-of-line
+ 2 forward-character
+ search-forward "=>"
+ 1 redraw-display
+[end]
+
+execute-macro-1
+
Added: clients/emacs/emacs.tut
===================================================================
--- clients/emacs/emacs.tut (rev 0)
+++ clients/emacs/emacs.tut 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,636 @@
+You are looking at the MICRO-EMACS tutorial. Comments on this document
+may be refered to Dana Hoggatt or Dan Lawrance.
+
+EMACS commands generally involve the CONTROL key (sometimes labelled CTRL or
+CTL) or the META key (generally labelled ESCAPE). Rather than write out META
+or CONTROL each time we want you to prefix a character, we'll use the following
+abbreviations:
+
+ ^<chr> means hold the CONTROL key while typing the character <chr>
+ Thus, ^F would be: hold the CONTROL key and type F.
+
+ ESC-<chr> means type the ESCAPE key and release it, then type the
+ character <chr>. The <chr> can be upper or lower case
+ and it will have the same meaning.
+
+Important note: if you must exit at some point, type ^X ^C.
+
+This tutorial attempts to help you "learn by doing". The characters ">>"
+at the left margin of your screen indicate directions for you to try using
+a command. For instance:
+
+>> Now type ^V (View next screen) to move to the next screen.
+ (go ahead, do it by depressing the control key and V together).
+
+From now on, you'll be expected to type ^V whenever you finish reading the
+current screen.
+
+Note that there is an overlap when going from screen to screen; this
+provides some continuity when moving through the file.
+
+The first thing that you need to know is how to move around from place to
+place in the file. You already know how to move forward a screen, with ^V.
+To move backwards a screen, type ^Z. (depress the CTRL key and type Z).
+
+>> Try typing ^Z and then ^V to move back and forth a few times.
+
+
+SUMMARY
+-------
+
+The following commands are useful for viewing screenfuls:
+
+ ^V Move forward one screenful
+ ^Z Move backward one screenful
+ <ESC>^L Clear screen and redisplay everything
+ putting the text near the cursor at the center.
+
+>> find the cursor and remember what text is near it.
+ Then type a <ESC>^L.
+ Find the cursor again and see what text is near it now.
+
+
+BASIC CURSOR CONTROL
+--------------------
+
+Getting from screenful to screenful is useful, but how do you reposition
+yourself within a given screen to a specific place? There are several ways
+you can do this. One way (not the best, but the most basic) is to use the
+commands previous, backward, forward and next. As you can imagine these
+commands (which are given to EMACS as ^P, ^B, ^F, and ^N respectively) move
+the cursor from where it currently is to a new place in the given direction.
+Here, in a more graphical form are the commands:
+
+ Previous line, ^P
+ :
+ :
+ Backward, ^B .... Current cursor position .... Forward, ^F
+ :
+ :
+ Next line, ^N
+
+You'll probably find it easy to think of these by letter. P for
+previous, N for next, B for backward and F for forward. These are
+the basic cursor positioning commands and you'll be using them ALL
+the time so it would be of great benefit if you learn them now.
+
+>> Do a few ^N's to bring the cursor down to this line.
+
+>> Move into the line with ^F's and then up with several ^P's.
+ See what ^P does when the cursor is in the middle of the line.
+
+Lines are separated by a single Linefeed character, which is what
+Unix calls a Newline.
+
+>> Try to ^B at the beginning of a line. Do a few more ^B's.
+ Then do ^F's back to the end of the line and beyond.
+
+When you go off the top or bottom of the screen, the text beyond
+the edge is shifted onto the screen so that your instructions can
+be carried out while keeping the cursor on the screen.
+
+>> Try to move the cursor off the bottom of the screen with ^N and
+ see what happens.
+
+If moving by characters is too slow, you can move by words. ESC-F
+(Meta-F) moves forward a word and ESC-B moves back a word.
+
+>> Type a few ESC-F's and ESC-B's. Intersperse them with ^F's and ^B's.
+
+Notice the parallel between ^F and ^B on the one hand, and ESC-F and ESC-B on
+the other hand. Very often Meta characters are used for operations related
+to English text whereas Control characters operate on the basic textual units
+that are independent of what you are editing (characters, lines, etc). There
+is a similar parallel between lines and sentences: ^A and ^E move to the
+beginning or end of a line. and ESC-A and ESC-E move to the beginning or end
+of a sentence.
+
+### Note: ESC-A and ESC-E are not implimented yet (DLH - 1/22/86) ###
+
+>> Try a couple of ^A's, and then a couple of ^E's.
+ Try a couple of ESC-A's, and then a couple of ESC-E's.
+
+See how repeated ^A's do nothing, but repeated ESC-A's
+keep moving farther. Do you think that this is right?
+
+Two other simple cursor motion commands are ESC-< (Meta Less-than),
+which moves to the beginning of the file, and ESC-> (Meta Greater-than),
+which moves to the end of the file. You probably don't need to try
+them, since finding this spot again will be boring. If you need the
+shift key to type a "<", then you must also use the shift key to type
+ESC-<. Otherwise, you would be typing ESC-, .
+
+The location of the cursor within the text is also called "point". To
+paraphrase, the cursor shows on the screen where point is located in the text.
+
+Here is a summary of simple moving operations including
+the word and sentence moving commands:
+
+ ^F Move forward a character
+ ^B Move backward a character
+
+ ESC-F Move forward a word
+ ESC-B Move backward a word
+
+ ^N Move to next line
+ ^P Move to previous line
+
+ ESC-N Move to next paragraph
+ ESC-P Move to previous paragraph
+
+ ^A Move to beginning of line
+ ^E Move to end of line
+
+ ESC-A Move back to beginning of sentence (not functional)
+ ESC-E Move forward to end of sentence (not functional)
+
+ ESC-< Go to beginning of file
+ ESC-> Go to end of file
+
+>> Try all of these commands now a few times for practice.
+ Since the last two will take you away from this screen,
+ you can come back here with ^Z's and ^V's. These are
+ the most often used commands.
+
+Like all other commands in EMACS, these commands can be given
+arguments which cause them to be executed repeatedly. The way you
+give a command a repeat count is by typing META and then the digits
+before you type the command. (Remember META is ususally called ESCAPE)
+
+For instance, META 8 ^F moves forward eight characters.
+
+>> Try giving a suitable argument to ^N or ^P to come as close
+ as you can to this line in one jump.
+
+This also applies to the screen moving commands, ^V and ^Z. When
+given an argument, they scroll the screen up or down by that many
+screenfuls. As a special case, typing just ^U is equivalent to ESC-4.
+
+>> Try typing ESC-3 ^V now.
+
+If you would like to scroll it down, you can give an argument to ^Z.
+
+
+QUITTING FROM COMMANDS
+----------------------
+
+The character in EMACS used to quit out of all commands which request
+input is ^G. For example, you can use ^G to discard a numeric argument
+or the beginning of a command that you don't want to finish.
+
+>> Type ESC-100 to make a numeric arg of 100, then type ^G.
+ Now type ^F. How many characters does it move?
+ If you have typed an <ESC> by mistake, you can get rid of it
+ with a ^G.
+
+
+IBM CURSOR KEYS
+---------------
+
+On the IBM-PC version, the cursor keypad has been bound to some of the
+more useful screen movement commands. The mappings are as follows:
+
+ Cursor-Right ^F Move forward a character
+ Cursor-Left ^B Move backward a character
+
+ ^Cursor-Right ESC-F Move forward a word
+ ^Cursor-Left ESC-B Move backward a word
+
+ Cursor-Down ^N Move to next line
+ Cursor-UP ^P Move to previous line
+
+ Pg-Dn ^V Move to next screen
+ Pg-Up ^Z Move to previous screen
+
+ Home ESC-< Go to beginning of file
+ End ESC-> Go to end of file
+
+ Insert ^O Open up a new line
+ Delete ^K Kill to end of line
+
+Usage of the ^O and ^K commands is described later in the tutorial. A
+map of the key layout looks something like this:
+
+ -------------------------------------------------
+ | 7 | 8 | 9 |
+ | Home | ^ | Pg Up |
+ | | | | |
+ | ESC-< | ^P | ^Z |
+ -------------------------------------------------
+ | 4 | 5 | 6 |
+ | <-- | | --> |
+ | | | |
+ | ^B | | ^F |
+ -------------------------------------------------
+ | 1 | 2 | 3 |
+ | End | | | Pg Dn |
+ | | v | |
+ | ESC-> | ^N | ^V |
+ -------------------------------------------------------------
+ | 0 | . |
+ | Insert | Delete |
+ | | |
+ | ^O | ^K |
+ -------------------------------------------------------------
+
+>> if you have an IBM-PC, practice using the cursor keypad.
+
+
+
+ERRORS
+------
+
+Sometimes you may do something which EMACS doesn't allow. If it is
+something simple, such as typing a control key sequence which is not
+associated with any command, EMACS will just beep at you. Otherwise,
+EMACS will also display an informative error message at the bottom of
+the screen.
+
+Some versions of EMACS do not have all the features described in this
+tutorial implemented yet. If you come across such an unimplemented
+feature, you may get an error message when you try to use it. Just
+type a space and proceed on to the next section of the tutorial.
+
+
+INSERTING AND DELETING
+----------------------
+
+If you want to type text, just do it. Characters which you can see, such
+as A, 7, *, etc. are taken by EMACS as text and are immediately inserted.
+Type <Return> (the carriage-return key) to insert a line separator.
+
+You can delete the last character you typed by typing either <Delete> or ^H.
+On some keyboards, there is a dedicated key for creating a ^H. If so, it is
+usually labeled as either "Backspace" or "<--". <Delete> is a key on the
+keyboard, which may be labeled "Rubout" instead of "Delete" on some terminals.
+More generally, <Delete> deletes the character immediately before the current
+cursor position.
+
+>> Do this now, type a few characters and then delete them by typing
+ <Delete> a few times. Don't worry about this file being changed;
+ you won't affect the master tutorial. This is just a copy of it.
+
+>> Now start typing text until you reach the right margin, and keep
+ typing. When a line of text gets too big for one line on the
+ screen, the line of text is "continued" off the edge of the screen
+ The dollar sign at the right margin indicates a line which has
+ been continued. EMACS scrolls the line over so you can see what you
+ are editing. The '$' at the left or right edge of the screen indicates
+ that the current line extends off in that direction.
+
+>> The following line actually goes off the edge. Trying typing enough ^F's
+ so that you move off the right hand end of this line. This is a long line of text. Note the "$"s at each edge. Keep typing ^F's and watch where EMACS decides to scroll the line. Now, type ^B's until EMACS decides to scroll the line again.
+
+This is one of those gizmos which is easier to understand by playing with it
+than by reading about it.
+
+>> Use ^D's or <Delete>s to delete the text until the text line fits on
+ one screen line again. The continuation "$" will go away.
+
+>> Move the cursor to the beginning of a line and type <Delete>. This
+ deletes the line separator before the line and merges the line onto
+ the previous line. The resulting line may be too long to fit, in
+ which case it has a continuation indication.
+
+>> Type <Return> to insert the separator again.
+
+Internally, EMACS will allow you to have lines of nearly any length, limited
+only by the amount of memory available. Externally, however, EMACS can only
+read or write lines, to or from a file, which are less than or equal to 255
+characters.
+
+Remember that most EMACS commands can be given a repeat count; Note
+that this includes characters which insert themselves.
+
+>> Try that now -- type META 8 * and see what happens.
+
+If you want to create a blank line in between two lines, move to the
+second of the two lines and type ^O.
+
+>> Try moving to a line and typing ^O now.
+
+You've now learned the most basic way of typing something in
+EMACS and correcting errors. You can delete by words or lines
+as well. Here is a summary of the delete operations:
+
+ <Delete> delete the character just before the cursor
+ ^H delete the character just before the cursor
+ ^D delete the next character after the cursor
+
+ ESC-<Delete> kill the word immediately before the cursor
+ ESC-^H kill the word immediately before the cursor
+ ESC-D kill the next word after the cursor
+
+ ^K kill from the cursor position to end of line
+
+Notice that <Delete> and ^D vs ESC-<Delete> and ESC-D extend the parallel
+started by ^F and ESC-F (well, <Delete> isn't really a control
+character, but let's not worry about that).
+
+Now suppose you kill something, and then you decide that you want to get
+it back? Well, whenever you kill something bigger than a character, EMACS
+saves it for you. To yank it back, use ^Y. Note that you don't have to
+be in the same place to do ^Y; This is a good way to move text around.
+Also note that the difference between "Killing" and "Deleting" something
+is that "Killed" things can be yanked back, and "Deleted" things cannot.
+Generally, the commands that can destroy a lot of text save it, while the
+ones that attack only one character, or nothing but blank lines and spaces,
+do not save.
+
+For instance, type ^N a couple times to postion the cursor
+at some line on this screen.
+
+>> Do this now, move the cursor and kill that line with ^K.
+
+Note that a single ^K kills the contents of the line, and a second
+^K kills the line itself, and make all the other lines move up. If
+you give ^K a repeat count, it kills that many lines AND their contents.
+
+The text that has just disappeared is saved so that you can
+retrieve it. To retrieve the last killed text and put it where
+the cursor currently is, type ^Y.
+
+>> Try it; type ^Y to yank the text back.
+
+Think of ^Y as if you were yanking something back that someone took away
+from you. Notice that if you do several ^K's in a row the text that is
+killed is all saved together so that one ^Y will yank all of the lines.
+
+>> Do this now, type ^K several times.
+
+Now to retrieve that killed text:
+
+>> Type ^Y. Then move the cursor down a few lines and type ^Y
+ again. You now see how to copy some text.
+
+What do you do if you have some text you want to yank back, and then
+you kill something else? ^Y would yank the more recent kill.
+
+>> Kill a line, move around, kill another line.
+ Then do ^Y to get back the second killed line.
+
+
+FILES
+-----
+
+In order to make the text you edit permanent, you must put it in a file.
+Otherwise, it will go away when you leave EMACS. While you are editing a
+file in EMACS, your changes are actually being made to a private
+"scratch" copy of the file. However, the changes still don't become
+permanent until you "save" the file. This is so you can have control to
+avoid leaving a half-changed file around when you don't want to.
+
+If you look near the botton of the screen you will see a line that
+looks like this:
+
+ =* MicroEMACS 3.1 (NORMAL) == emacs.tut == File: emacs.tut ==========
+ ---------------
+
+Note that EMACS indicates the name of the file you are currently editing.
+This is the name of your own temporary copy of the text of the EMACS
+tutorial; the file you are now editing. Whatever file you edit, that
+file's name will appear in that precise spot.
+
+The commands for finding and saving files are unlike the other commands you
+have learned in that they consist of two characters. They both start with the
+character Control-X. There is a whole series of commands that start with
+Control-X; many of them have to do with files, buffers, and related things,
+and all of them consist of Control-X followed by some other character. As
+with ESC, the character is interpreted the same regardless of case.
+
+Another thing about the command for finding a file is that you have to say
+what file name you want. We say the command "reads an argument from the
+terminal" (in this case, the argument is the name of the file). After you
+type the command
+
+ ^X ^F Find a file
+
+EMACS will ask you for the file name. You should end the name with
+the Return key. After this command, you will see the contents of the
+file in your EMACS. You can edit the contents. When you wish to make
+the changes permanent, issue the command
+
+ ^X ^S Save the file
+
+A new version of the file will be created. When the operation is
+finished, EMACS prints the name and number of lines saved.
+
+If you forget to save and edit a different file and then decide to quit,
+EMACS will remind you that you made changes that have not been save and
+then ask you whether you really want to quit. (If you don't save them,
+they will be thrown away. That might be what you want!) You should
+answer with a "N" to save them or a "Y" to throw the changes away.
+
+To make a new file, just edit it "as if" it already existed. Then start
+typing in the text. When you ask to "save" the file, EMACS will really
+create the file with the text that you have inserted. From then on, you
+can consider yourself to be editing an already existing file.
+
+It is not easy for you to try out editing a file and continue with the
+tutorial. But you can always come back into the tutorial by starting it
+over and skipping forward. So, when you feel ready, you should try editing
+a file named "FOO", putting some text in it, and saving it; then exit from
+EMACS and look at the file to be sure that it worked.
+
+
+EXTENDING THE COMMAND SET
+-------------------------
+
+### The mechanisms for extending the command set and setting ###
+### the key bindings has not been installed yet. Skip forward ###
+### to the next section (TEXT REPLACEMENT). DLH (1/22/86) ###
+
+There are many, many more EMACS commands than could possibly be put
+on all the control and meta characters. EMACS gets around this with
+the X (eXtend) command. This comes in two flavors:
+
+ ^X Character eXtend. Followed by one character.
+ ESC-X Named command eXtend. Followed by a long name.
+
+These are commands that are generally useful but used less than the commands
+you have already learned about. You have already seen two of them: the file
+commands ^X ^F to Find and ^X ^S to Save. Another example is the command to
+tell EMACS that you'd like to stop editing. The command to do this is ^X ^C.
+
+There are many ^X commands. The ones you need immediately are:
+
+ ^X ^F Find file.
+ ^X ^S Save file.
+ ^X ^C Quit EMACS. This does not save your files auto-
+ matically, though if your files have been modi-
+ fied, EMACS asks if you really want to quit. The
+ standard way to save and exit is ^X ^S ^X ^C.
+
+Named eXtended commands are commands which are used even less
+frequently, or commands which are used only in certain modes. These
+commands are usually called "functions". An example is the function
+"apropos", which prompts for a keyword and then gives the names of all
+the functions that apropos for that keyword. When you type ESC-X, EMACS
+prompts you at the bottom of the screen with ":" and you should type the
+name of the function you wish to call; in this case, "apropos". Just
+type "apr<Space>" and EMACS will complete the name. EMACS will ask you
+for a keyword or phrase and you type the string that you want ask about.
+
+>> Try typing ESC-X, followed by "apropos" or "apr" and then Return.
+ Then try typing "file" followed by a Return.
+
+
+TEXT REPLACEMENT
+---- -----------
+
+>> Move the cursor to the blank line two lines below this one.
+ Then type ESC-r changed<Escape>altered<Escape>.
+
+ Notice how this line has changed: you've replaced
+ the word c-h-a-n-g-e-d with "altered" wherever it occurs
+ after the cursor.
+
+The more customary command for replacing strings is the interactive
+command query-replace-search, which has several options. In essence, it
+shows each occurance of the first string and asks you if you want to
+replace it or not. You can also choose to edit around the string, or go
+on and replace all occurances without asking further. It is described in
+detail in the EMACS manual. Also, typing a '?' when it asks you if you
+wish to replace will list out the various options.
+
+
+MODE LINE
+---------
+
+The bottom line of the screen is known as the communications line. This
+is where EMACS interactively communicates with you. You have already
+seen how emacs prompts you for information (like when searching). EMACS
+can also report things to you as well.
+
+>> Type ^X = and see what you get in the communications line.
+
+The line immediately above the communications line is called the MODE
+LINE. The mode line says something like
+
+ =* MicroEMACS 3.1 (NORMAL) == emacs.tut == File: emacs.tut ==========
+
+This is a very useful "information" line.
+
+The star means that you have made changes to the text. Right after
+you visit or save a file, there is no star.
+
+The buffername is the name EMACS gave to the buffer, and it is usually
+related to the filename. You already know what the filename means -- it
+is the file you have edited.
+
+The part of the mode line inside the parentheses is to tell you what
+modes you are in. The default mode is NORMAL which is what you are in
+now. It is an example of a "major mode". There are several major modes
+in EMACS for editing different languages and text, such as C mode, Text
+mode, etc. At any time one and only one major mode is active, and its
+name can always be found in the mode line just where "NORMAL" is now.
+
+Each major mode makes a few commands behave differently. For example,
+there are commands for creating comments in a program, and since each
+programming language has a different idea of what a should look like,
+each major mode has to insert comments differently. Each major mode is
+controlled by a EMACS variable which can be manipulated and queried with
+the "set" and "print" extended commands.
+
+Major modes are called major because there are also minor modes. They
+are called minor because they aren't alternatives to the major modes,
+just minor modifications of them. Each minor mode can be turned on or
+off by itself, regardless of what major mode you are in, and regardless
+of the other minor modes. So you can use no minor modes, or one minor
+mode, or any combination of several minor modes.
+
+One minor mode which is very useful, especially for editing English
+text, is WRAP mode. When this mode is on, EMACS breaks the line in
+between words automatically whenever the line gets too long. You can
+turn this mode on by doing ^X M wrap <return>. When the mode is on, you
+can turn it off by doing ^X ^M wrap <Return>.
+
+>> Type "^X ^M wrap <Return>" now. Then insert a line of "asdf " over
+ again until you see it divide into two lines. You must put in spaces
+ between them because Auto Fill breaks lines only at spaces. Note that
+ "WRAP" appears in the mode line, indicating that you are in WRAP mode.
+
+The margin is usually set at 72 characters, but it can be shanged.
+Simply type ESC nn ^X F, where "nn" is the column number for the right
+hand margin.
+
+
+SEARCHING
+---------
+
+EMACS can do searches for strings (these are groups of contiguous
+characters or words) either forward through the file or backward
+through it.
+
+>> Now type ^S to start a search. Type the word 'cursor', then ESCAPE.
+
+>> Type ^S ESCAPE to find the next occurrence of "cursor".
+
+The ^S starts a search that looks for any occurrence of the search
+string AFTER the current cursor position. But what if you want to
+search for something earlier in the text? To do this one should
+type ^R for Reverse search. Everything that applies to ^S applies
+to ^R except that the direction of the search is reversed.
+
+
+GETTING MORE HELP
+-----------------
+
+In this tutorial we have tried to supply just enough information to
+get you started using EMACS. There is so much available in EMACS that
+it would be impossible to explain it all here. However, you may want
+to learn more about EMACS since it has numerous desirable features
+that you don't know about yet.
+
+### The on-line help features have not been implimented yet. DLH ###
+
+The most basic HELP feature is the describe-key function which is
+available by typing ^X ? and then a command character. EMACS prints one
+line line on the bottom of the screen tell what function is bound to
+that key.
+
+The describe-command function ESC-? will prompt for the name of a function
+and print out the section from the manual about that command. When you
+are finished reading it, type a Space or a ^G (quit) to bring your text
+back on the screen.
+
+>> Type ^X ? Control-P. The message at the bottom of the screen should
+ be something like "^P is bound to previous-line".
+
+Multi-character commands such as ^X ^Z and <ESC>V are also allowed
+after ^X ?.
+
+Now lets get more information about the previous-line command.
+
+>> Type ESC-? previous-line. When you are finished reading the
+ output, type a Space.
+
+The "name of the function" is important for people who are customizing
+EMACS. It is what appears in the EMACS CHART as the documentation for
+the command character.
+
+
+CONCLUSION
+----------
+
+Remember, to exit use ^X ^C.
+
+This tutorial is meant to be understandable to all new users, so if
+you found something unclear, don't sit and blame yourself - complain!
+
+You'll probably find that if you use EMACS for a few days you won't
+be able to give it up. Initially it may give you trouble. But remember
+that this is the case with any editor, especially one that can do many,
+many things. And EMACS can do practically everything.
+
+
+Acknowledgements
+----------------
+
+This is a modified version of the "JOVE Tutorial" by Jonathan Payne
+(19 January 86). That document was in turn a modified version of the
+tutorial "Teach-Emacs" from MIT as modified by Steve Zimmerman at
+CCA-UNIX (31 October 85).
+
+This document was last updated on 2-7-86 by Dana Hoggatt.
+
Added: clients/emacs/emacs2.mss
===================================================================
--- clients/emacs/emacs2.mss (rev 0)
+++ clients/emacs/emacs2.mss 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,790 @@
+
+@style(indent 8 chars, spacing 1 lines)
+@begin(center)
+@b(MicroEMACS 3.7)
+
+@i(Screen Editor)
+written by Dave Conroy
+and Daniel Lawrence
+@end(center)
+
+
+@begin(quotation)
+ This software is in the public domain and may be freely copied
+and used by one and all. We would ask that if it is incorporated into
+other software that proper credit be given to its authors.
+@end(quotation)
+
+@flushleft(@b[Introduction])
+
+ MicroEMACS 3.7 is a screen editor for programming and word
+processing. It is availible for the IBM-PC and its clones, UNIX V7,
+UNIX BSD4.2, UNIX V5, VMS, the HP150, the Wang-PC and the Commodore
+AMIGA. It requires between 40 to 70K of space to run on these machines.
+Some of its capabilities include:
+
+@begin(verbatim)
+ Multiple windows on screen at one time
+
+ Multiple files in the editor at once
+
+ Limited on screen formating of text
+
+ User changable command set
+
+ User written editing macroes
+
+ Compatability across all supported environments
+@end(verbatim)
+
+ This manual is designed as a reference manual. All the commands
+in MicroEMACS are listed, in functional groups, along with detailed
+descriptions of what each commands does.
+@newpage
+@flushleft(@b[How to Start])
+
+ MicroEMACS is invoked from the operating system command level
+with a command of the form:
+
+@begin(verbatim)
+ emacs {options} <filelist>
+
+where options may be:
+
+-v all the following files are in view mode (read only)
+-e all the following files can be edited
+-g<n> go directly to line <n> of the first file
+-s<string> go to the end of the first occurance of <string>
+ in the first file
+
+@@<sfile> execute macro file <sfile> instead of the
+ standard startup file
+
+and <filelist> is a list of files to be edited.
+
+for example:
+
+ emacs @@start1.cmd -g56 test.c -v head.h def.h
+
+@end(verbatim)
+
+ means to first execute macro file start1.cmd instead of the
+standard startup file, emacs.rc and then read in test.c, position the
+cursor to line 56, and be ready to read in files head.h and def.h in
+view (read-only) mode. In the simple case, MicroEMACS is usually run by
+typing:
+
+@flushleft( emacs <file>)
+
+ where <file> is the name of the file to be edited.
+@newpage
+@flushleft(@b[How to type in commands])
+
+ Most commands in MicroEMACS are a single keystroke, or a
+keystroke preceded by a command prefix. Control commands appear in the
+documentation like ^A which means to depress the <Ctrl> key and while
+holding down it down, type the A character. Meta-commands appear as
+M-A which means to strike the Meta key (<ESC> on most computers) and
+then after realeasing it, type the A character. Control-X commands
+usually appear as ^X-A which means to hold down the control key and type
+the X character then type the A character. Both meta commands and
+control-x commands can be control characters as well, for example,
+^X-^O (the delete-blank-lines command) means to hold down <Ctrl>, type
+X, keep holding down <Ctrl> and type the O character.
+
+ Many commands in MicroEMACS can be executed a number of times.
+In order to make one command repeat many times, type Meta (<ESC>)
+followed by a number, and then the command. for example:
+
+@verbatim( M 12 ^K)
+
+ will delete 12 lines starting at the cursor and going down.
+Sometimes, the repeat count is used as an argument to the command as in
+the set-tab command where the repeat count is used to set the spacing of
+the tab stops.
+
+@flushleft(@b[The Command List])
+
+ The following is a list of all the commands in MicroEMACS.
+Listed is the command name, the default (normal) keystrokes used to
+invoke it, and alternative keys for the IBM-PC, and a description of
+what the command does.
+
+@begin(verbatim)
+@b[(1) MOVING THE CURSOR]
+
+@i(previous-page) ^Z <Pg Up>
+
+ Move one screen towards the begining of the file.
+
+@i(next-page) ^V <Pg Dn>
+
+ Move one screen towards the end of the file.
+
+@i(begining-of-file) M-< <Home>
+
+ Place the cursor at the begining of the file.
+
+@i(end-of-file) M-> <End>
+
+ Place the cursor at the end of the file.
+
+@i(forward-character) ^F (6 on the keypad)
+
+ Move the cursor one character to the right. Go down to
+the begining of the next line if the cursor was already at the
+end of the current line.
+
+@i(backward-character) ^B (4 on the keypad)
+
+ Move the cursor one character to the left. Go to the
+end of the previous line if the cursor was at the begining of
+the current line.
+
+@i(next-word) M-F (^6 on the keypad)
+
+ Place the cursor at the begining of the next word.
+
+@i(previous-word) M-B (^4 on the keypad)
+
+ Place the cursor at the begining of the previous word.
+
+@i(begining-of-line) ^A
+
+ Move cursor to the begining of the current line.
+
+@i(end-of-line) ^E
+
+ Move the cursor to the end of the current line.
+
+@i(next-line) ^N (2 on the keypad)
+
+ Move the cursor down one line.
+
+@i(previous-line) ^P (8 on the keypad)
+
+ Move the cursor up one line.
+
+@i(goto-line) M-G
+
+ Goto a specific line in the file. IE M 65 M-G would
+put the cursor on the 65th line of the current buffer.
+
+@i(next-paragraph) M-N
+
+ Put the cursor at the first end of paragraph after the cursor.
+
+@i(previous-paragraph) M-P
+
+ Put the cursor at the first begining of paragraph before the
+cursor.
+
+@b[(2) DELETING & INSERTING]
+
+@i(delete-previous-character) ^H <--
+
+ Delete the character immedietly to the left of the
+cursor. If the cursor is at the begining of a line, this will
+join the current line on the end of the previous one.
+
+@i(delete-next-character) ^D <Del>
+
+ Delete the character the cursor is on. If the cursor is
+at the end of a line, the next line is put at the end of the
+current one.
+
+@i(delete-previous word) M-^H M- <--
+
+ Delete the word before the cursor.
+
+@i(delete-next-word) M-^D
+
+ Delete the word starting at the cursor.
+
+@i(kill-to-end-of-line)
+
+ When used with no argument, this command deletes all
+text from the cursor to the end of a line. When used on a blank
+line, it deletes the blank line. When used with an argument, it
+deletes the specified number of lines.
+
+@i(insert-space) ^C <Ins>
+
+ Insert a space before the character the cursor is on.
+
+@i(newline) <return>
+
+ Insert a newline into the text, move the cursor down to the
+begining of the next physical line, carrying any text that was after
+it with it.
+
+@i(newline-and-indent) ^J
+
+ Insert a newline into the text, and indent the new line the
+same as the previous line.
+
+@i(handle-tab) ^I -->
+
+ With no argument, move the cursor to the begining of the
+next tab stop. With an argument of zero, use real tab
+characters when tabbing. With a non-zero argument, use spaces
+to tab every argument positions.
+
+@i(delete-blank-lines) ^X-^O
+
+ Delete all the blank lines before and after the current cursor
+position.
+
+@i(kill-paragraph) M-^W
+
+ Delete the paragraph that the cursor is currently in.
+
+@i(kill-region) ^W
+
+ Delete all the characters from the cursor to the mark set with
+the set-mark command.
+
+@i(copy-region)
+
+ Copy all the characters between the cursor and the mark
+set with the set-mark command into the kill buffer (so they can
+later be yanked elsewhere).
+
+@i(open-line) ^O
+
+ Insert a newline at the cursor, but do not move the cursor.
+
+@b[(3) SEARCHING]
+
+@i(search-forward) ^S
+
+ Seearch for a string from the current cursor position to
+the end of the file. The string is typed on on the bottom line of
+the screen, and terminated with the <ESC> key. Special characters
+can be typed in by preceeding them with a ^Q. A single ^Q
+indicates a null string. On successive searches, hitting <ESC>
+alone causes the last search string to be reused.
+
+@i(search-reverse) ^R
+
+ This command searches backwards in the file. In all other ways
+it is like search-forward.
+
+@i(incremental-search) ^X-S
+
+ This command is similar to forward-search, but it processes the
+search as each character of the input string is typed in. This allows
+the user to only use as many keystrokes as are needed to uniquely
+specify the string being searched. Several control characters are active
+while isearching:
+
+ ^S or ^X Skip to the next occurence of the current string
+ ^R skip to the last occurence of the current string
+ ^H back up to the last match (posibly deleting
+ the last character on the search string)
+ ^G abort the search, return to start
+ <ESC> end the search, stay here
+
+@i(reverse-incremental-search) ^X-R
+
+ This command is the same as incremental-search, but it starts in
+the reverse direction.
+
+@i(hunt-forward) unbound (<ALT>S on the IBM PC)
+
+ This command repeats the last search with the last search string
+
+@i(hunt-backward) unbound (<ALT>R on the IBM PC)
+
+ THe last search string is looked for starting at the cursor and
+going backwards.
+
+@b[(4) REPLACING]
+
+@i(replace-string) M-R
+
+ This command allows you to replace all occurences of one string
+with another string. The replacement starts at the current location of
+the cursor and goes to the end of the current buffer. A numeric argument
+will limit the number of strings replaced.
+
+@i(query-replace-string) M-^R
+
+ Like the replace-string command, this command will replace one
+string with another. However, it allows you to step through each string
+and ask you if you wish to make the replacement. When the computer asks
+if you wish to make the replacement, the following answers are allowed:
+
+ Y Make the replacement and continue on to the next string
+ N Don't make the replacement, then continue
+ ! Replace the rest of the strings without asking
+ ^G Stop the command
+ . Go back to place the command started
+ ? get a list of options
+
+
+@b[(5) CAPITALIZING & TRANSPOSING]
+
+@i(case-word-upper) M-U
+
+ Change the following word into upper case.
+
+@i(case-word-capitalize) M-C
+
+ Capitolize the following word.
+
+@i(case-word-lower) M-L
+
+ Change the following word to lower case.
+
+@i(case-region-upper) ^X-^U
+
+ Change all the alphabetic characters in a marked region to upper
+case.
+
+@i(case-region-lower) ^X-^L
+
+ Change all the alphabetic characters in a marked region to lower
+case.
+
+@i(transpose-characters) ^T
+
+ Swap the last and second last characters behind the cursor.
+
+@i(quote-character) ^Q
+
+ Insert the next typed character, ignoring the fact that it may
+be a command character.
+
+@b[(6) REGIONS & THE KILL BUFFER]
+
+@i(set-mark) M-<SPACE>
+
+ This command is used to delimit the begining of a marked region.
+Many commands are effective for a region of text. A region is defined
+as the text between the mark and the current cursor position. To delete
+a section of text, for example, one moves the cursor to the begining of
+the text to be deleted, issues the set-mark command by typing M-<SPACE>,
+moves the cursor to the end of the text to be deleted, and then deletes
+it by using the kill-region (^W) command. Only one mark can be set in
+one window or one buffer at a time, and MicroEMACS will try to remember
+a mark set in an offscreen buffer when it is called back on screen.
+
+@i(exchange-point-and-mark) ^X-^X
+
+ This command moves the cursor to the current marked position in
+the current window and moves the mark to where the cursor was. This is
+very usefull in finding where a mark was, or in returning to a position
+previously marked.
+
+@b[(7) COPYING AND MOVING]
+
+@i(kill-region) ^W
+
+ This command is used to copy the current region (as defined by
+the current mark and the cursor) into the kill buffer.
+
+@i(yank) ^Y
+
+ This copies the contents of the kill buffer into the text at the
+current cursor position. This does not clear the kill buffer, and thus
+may be used to make multiple copies of a section of text.
+
+@i(copy-region) M-W
+
+ This command copies the contents of the current region into the
+kill buffer without deleting it from the current buffer.
+
+@b(8) MODES OF OPERATION]
+
+@i(add-mode) ^X-M
+
+ Add a mode to the current buffer
+
+@i(delete-mode) ^X-^M
+
+ Delete a mode from the current buffer
+
+@i(add-global-mode) M-M
+
+ Add a mode to the global modes which get inherited by any new
+buffers that are created while editing.
+
+@i(delete-global-mode) M-^M
+
+ Delete a mode from the global mode list. This mode list is
+displayed as the first line in the output produced by the list-buffers
+command.
+
+@b( MODES)
+
+ Modes are assigned to all buffers that exist during an editing
+session. These modes effect the way text is inserted, and the operation
+of some commands. Legal modes are:
+
+
+@i(OVER) Overwrite Mode
+
+ In this mode, typed characters replace existing characters
+rather than being inserted into existing lines. Newlines still insert
+themselves, but all other characters will write over existing characters
+on the current line being edited. This mode is very usefull for editing
+charts, figures, and tables.
+
+@i(WRAP) Word Wrap Mode
+
+ In this mode, when the cursor crosses the current fill column
+(which defaults to 72) it will, at the next wordbreak, automatically
+insert a newline, dragging the last word down with it. This makes
+typing prose much easier since the newline (<RETURN>) only needs to be
+used between paragraphs.
+
+@i(VIEW) File Viewing Mode
+
+ In this mode, no commands which can change the text are allowed.
+
+@i(CMODE) C Program Editing Mode
+
+ This mode is for editing programs written in the 'C' programming
+language. When the newline is used, the editor will attempt to place
+the cursor at the proper indentation level on the next line. Close
+braces are automatically undented for the user, and also pre-processor
+commands are automatically set flush with the left margin. When a close
+parenthesis or brace is typed, if the matching open is on screen, the
+cursor briefly moves to it, and then back. (Typing any key will abort
+this fence matching, executing the next command immediatly)
+
+@i(EXACT) Exact Case Matching on Searching MODE
+
+ Normally case is insignificant during the various search
+commands. This forces all matching to take character case into account.
+
+@i(MAGIC) Regular expresion pattern matching Mode
+
+ This feature is not yet implimented. While it may be set as a
+mode, it will have no effect at the moment. When it is ready, it will
+cause all search commands to accept various pattern characters to allow
+regular exspression search and replaces.
+
+@b[(10) ON-SCREEN FORMATTING]
+
+@i(set-fill-column) ^X-F
+
+ Sets the column used by WRAP mode and the fill-paragraph command.
+
+@i(handle-tab) <TAB>
+
+ Given a numeric argument, the tab key resets the normal behavior
+of the tab key. An argument of zero causes the tab key to generate
+hardware tabs (at each 8 columns). A non-zero argument will cause the
+tab key to generate enough spaces to reach a culumn of a multiple of the
+argument given. This also resets the spacing used while in CMODE.
+
+@i(fill-paragraph) M-Q
+
+ This takes all the text in the current paragraph (as defined by
+surrounding blank lines, or a leading indent) and attempt to fill it
+from the left margin to the current fill column.
+
+@i(buffer-position)
+
+ This command reports on the current and total lines and
+characters of the current buffer. It also gives the hexidecimal code of
+the character currently under the cursor.
+
+@b[(11) MULTIPLE WINDOWS]
+
+@i(split-current-window) ^X-2
+
+ If possible, this command splits the current window into two
+near equal windows, each displaying the buffer displayed by the original
+window. A numeric argument of 1 forces the upper window to be the new
+current window, and an argument of 2 forces the lower window to be the
+new current window.
+
+@i(delete-window) ^X-0
+
+ this command attempts to delete the current window, retrieving
+the lines for use in the window above or below it.
+
+@i(delete-other-windows) ^X-1
+
+ All other windows are deleted by this command. The current
+window becomes the only window, using the entire availible screen.
+
+@i(next-window) ^X-O
+
+ Make the next window down the current window. With an argument,
+this makes the nth window from the top current.
+
+@i(previous-window) ^X-P
+
+ Make the next window up the current window. With an argument,
+this makes tghe nth window from the bottom the current window.
+
+@i(scroll-next-down) M-^V
+
+ Scroll the next window down a page.
+
+@i(scroll-next-up) M-^Z
+
+ Scroll the next window up a page.
+
+@b[(12) CONTROLLING WINDOWS]
+
+@i(grow-window) ^X-^
+
+ Enlarge the current window by the argument number of lines (1 by
+default).
+
+@i(shrink-window) ^X-^Z
+
+ Shrink the current window by the argument number of lines (1 by
+default).
+
+@i(resize-window) ^X-W
+
+ CHnage the size of the current window to the number of lines
+specified by the argument, if possible.
+
+@i(move-window-down) ^X-^N
+
+ Move the window into the current buffer down by one line.
+
+@i(move-window-up) ^X-^P
+
+ Move the window into the current buffer up by one line.
+
+@i(redraw-display) M-^L
+
+ Redraw the current window with the current line in the middle of
+the window, of with an argument, with the current line on the nth line
+of the current window.
+
+@i(clear-and-redraw) ^L
+
+ Clear the screen and redraw the entire display. Usefull on
+timesharing systems where messages and other things can garbage the display.
+
+@b[(13) MULTIPLE BUFFERS]
+
+@i(select-buffer) ^X-B
+
+ Switch to using another buffer in the current window. MicroEMACS
+will prompt you for the name of the buffer to use.
+
+@i(next-buffer) ^X-X
+
+ Switch to using the next buffer in the buffer list in the
+current window.
+
+@i(name-buffer) M-^N
+
+ Change the name of the current buffer.
+
+@i(kill-buffer) ^X-K
+
+ Dispose of an undisplayed buffer in the editor and reclaim the
+space. This does not delete the file the buffer was read from.
+
+@i(list-buffers) ^X-^B
+
+ Split the current window and in one half bring up a list of all
+the buffers currently existing in the editor. The active modes, change
+flag, and active flag for each buffer is also displayed. (The change
+flag is an * if the buffer has been changed and not written out. the
+active flag is not an * if the file had been specified on the command
+line, but has not been read in yet since nothing has switched to that
+buffer.)
+
+@i[(14) READING FROM DISK]
+
+@i(find-file) ^X-^F
+
+ FInd the named file. If it is already in a buffer, make that
+buffer active in the current window, otherwise attemt tocreate a new
+buffer and read the file into it.
+
+@i(read-file) ^X-^R
+
+ Read the named file into the current buffer (overwriting the
+previous contents of the current buffer. If the change flag is set, a
+confirmation will be asked).
+
+@i(insert-file) ^X-^I
+
+ Insert the named file into the current position of the current
+buffer.
+
+@i(view-file) ^X-^V
+
+ Like find-file, this command either finds the file in a buffer,
+or creates a new buffer and reads the file in. In addition, this leaves
+that buffer in VIEW mode.
+
+@i[(15) SAVING TO DISK]
+
+@i(save-file) ^X-^S
+
+ If the contents of the current buffer have been changed, write
+it back to the file it was read from.
+
+@i(write-file) ^X-^W
+
+ Write the contents of the current file to the named file, this
+also changed the file name associated with the current buffer to the new
+file name.
+
+@i(change-file-name) ^X-N
+
+ Change the name associated with the current buffer to the file
+name given.
+
+@i(quick-exit) M-Z
+
+ Write out all changed buffers to the files they were read from
+and exit the editor.
+
+@b[(16) ACCESSING THE OPERATING SYSTEM]
+
+@i(shell-command) ^X-!
+
+ Send one command to execute to the operating system command
+processor, or shell. Upon completion, MicroEMACS will wait for a
+keystroke to redraw the screen.
+
+@i(pipe-command) ^X-@
+
+ Execute one operating system command and pipe the resulting
+output into a buffer by the name of "command".
+
+@i(filter-buffer) ^X-#
+
+ Execute one operating system command, using the contents of the
+current buffer as input, and sending the results back to the same
+buffer, replacing the original text.
+
+@i(i-shell) ^X-C
+
+ Push up to a new command processor or shell. Upon exiting the
+shell, MicroEMACS will redraw its screen and continue editing.
+
+@i(suspend-emacs) ^X-D [only under BSD4.2]
+
+ This command suspends the editing processor and puts it into the
+background. The "fg" command will restart MicroEMACS.
+
+@i(exit-emacs) ^X-^C
+
+ Exit MicroEMACS back to the operating system. If there are any
+unwritten, changed buffers, the editor will promt to discard changes.
+
+@b[(17) KEY BINDINGS AND COMMANDS]
+
+@i(bind-to-key) M-K
+
+ This command takes one of the named commands and binds it to a
+key. From then on, whenever that key is struck, the bound command is
+executed.
+
+@i(unbind-key) M-^K
+
+ This unbinds a command from a key.
+
+@i(describe-key) ^X-?
+
+ This command will allow you to type a key and it will then
+report the name of the command bound to that key.
+
+@i(execute-named-command) M-X
+
+ This command will prompt you for the name of a command to
+execute. Typing <SPACE> part way thought will tell the editor to
+attempt to complete the name on its own. If it then beeps, there is no
+such command to complete.
+
+@i(describe-bindings) UNBOUND
+
+ This command splits the current window, and in one of the
+windows makes a list of all the named commands, and the keys currently
+bound to them.
+
+@b[(18) COMMAND EXECUTION]
+
+ Commands can also be executed as command scripts. This allows
+comands and their arguments to be stored in files and executed. The
+general form of a command script line is:
+
+ <optional repeat count> {command-name} <optional arguments>
+
+@i(execute-command-line) UNBOUND
+
+ Execute a typed in script line.
+
+@i(execute-buffer) UNBOUND
+
+ Executes script lines in the named buffer. If the buffer is off
+screen and an error occurs during execution, the cursor will be left on
+the line causing the error.
+
+@i(execute-file) UNBOUND
+
+ Executes script lines from a file. This is the normal way to
+execute a special script.
+
+@i(clear-message-line) UNBOUND
+
+ Clears the message line during script execution. This is
+usefull so as not to leave a confusion message from the last commands
+in a script.
+
+@i(unmark-buffer) UNBOUND
+
+ Remove the change flag from the current buffer. This is very
+usefull in scripts where you are creating help windows, and don't want
+MicroEMACS to complain about not saving them to a file.
+
+@i(insert-string) UNBOUND
+
+ Insert a string into the current buffer. This allows you to
+build up text within a buffer without reading it in from a file. Some
+special characters are allowd, as follows:
+
+ ~n newline
+ ~t tab
+ ~b backspace
+ ~f formfeed
+
+
+@b[(19) MACRO EXECUTION]
+
+ Also availible is one keyboard macro, which allows you to record
+a number of commands as they are executed and play them back.
+
+@i(begin-macro) ^X (
+
+ Start recording keyboard macro
+
+@i(end-macro) ^X )
+
+ Stop recording keyboard macro
+
+@i(execute-macro) ^X E
+
+ Execute keyboard macro
+
+@i(store-macro) UNBOUND
+
+ This command is used to store script lines in a hiffen buffer by
+the name of "[Macro nn]" where <nn> is a number from 1 to 40 and
+coresponds to the argument given this command. All script lines then
+encountered will be stored in this buffer rather than being executed. A
+script line consisting of only "[end]" tells the editor that the macro
+is complete, and stops recording script lines in the buffer.
+
+@i(execute-macro-nn) UNBOUND [shift-<F1> thru shift-<F10>]
+
+ This is the command to execute a script stored in one of the
+hidden macro buffers. On the IBM-PC the first ten of these are bound to
+shift-<F1> thru shift-<F10>.
+@end(verbatim)
Added: clients/emacs/emacsfm.rc
===================================================================
--- clients/emacs/emacsfm.rc (rev 0)
+++ clients/emacs/emacsfm.rc 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,126 @@
+; EMACS.RC: Startup file for MicroEMACS 3.4
+;
+; This file is executed everytime the
+; editor is entered
+;
+; This version of the files contains bindings that more closely
+; match the EMACS documentation in the Forthmacs User's Manual.
+
+; Set up Forthmacs-compatible bindings
+
+; I find that the location of the ESC key on most PC keyboards is too far
+; from the home keys for effective use with EMACS. I am accustomed to the
+; ESC key being in the location where the PC puts the ` key. I therefore
+; prefer to bind the ` key to be the meta prefix, instead of the real ESC
+; key. This works well if you can train yourself not to look for the
+; ESC label on the key cap, and just touch type ` without looking.
+
+; bind-to-key meta-prefix `
+
+bind-to-key find-file ^X^V
+bind-to-key delete-window ^X^D
+bind-to-key next-window ^XN
+; bind-to-key incremental-search ^S
+; bind-to-key reverse-incremental-search ^R
+bind-to-key search-forward ^S
+bind-to-key search-forward ^\
+bind-to-key search-reverse ^R
+bind-to-key save-file ^XS
+bind-to-key apropos M-?
+bind-to-key select-buffer ^X^O
+bind-to-key delete-buffer ^XK
+bind-to-key move-window-down ^Z
+bind-to-key move-window-up M-Z
+
+
+; ***** Rebind the Function key group
+
+bind-to-key execute-macro-11 FN;
+bind-to-key execute-named-command FN<
+bind-to-key hunt-forward FN=
+bind-to-key hunt-backward FN>
+bind-to-key next-window FN?
+bind-to-key execute-macro FN@
+bind-to-key find-file FNA
+bind-to-key view-file FNB
+bind-to-key save-file FNC
+bind-to-key exit-emacs FND
+
+; set screen colors
+add-global-mode "blue"
+
+; Enter Help
+11 store-macro
+ help
+ 8 resize-window
+ bind-to-key execute-macro-12 FNI
+ bind-to-key execute-macro-13 FNQ
+ bind-to-key execute-macro-14 FN;
+ add-mode "red"
+ begining-of-file
+ 2 forward-character
+ clear-message-line
+[end]
+
+; bring up the function key window
+1 store-macro
+ 2 split-current-window
+ select-buffer "Function Keys"
+ add-mode "red"
+ begining-of-file
+ 2 resize-window
+ insert-string "F1 help on/off F2 exec cmd F3 hunt F4 back hunt F5 next window"
+ newline
+ insert-string "F6 exec macro F7 find file F8 view file F9 save file F10 exit emacs"
+ begining-of-file
+ unmark-buffer
+ bind-to-key execute-macro-15 FNT
+ next-window
+[end]
+
+; reselect function key window
+15 store-macro
+ 2 split-current-window
+ select-buffer "Function Keys"
+ begining-of-file
+ 2 resize-window
+ add-mode "red"
+ next-window
+[end]
+
+; consult file
+3 store-macro
+ 2 split-current-window
+ previous-window
+ view-file "@File to Consult: "
+ 8 resize-window
+ add-mode "green"
+ add-mode "Black"
+ next-window
+[end]
+
+; Exit Help
+14 store-macro
+ bind-to-key previous-page FNI
+ bind-to-key next-page FNQ
+ bind-to-key execute-macro-1 FN;
+ delete-window
+ clear-message-line
+[end]
+
+; last help page
+12 store-macro
+ begining-of-line
+ search-reverse "=>"
+ 1 redraw-display
+[end]
+
+; next help page
+13 store-macro
+ begining-of-line
+ 2 forward-character
+ search-forward "=>"
+ 1 redraw-display
+[end]
+
+execute-macro-1
Added: clients/emacs/emacsobp.rc
===================================================================
--- clients/emacs/emacsobp.rc (rev 0)
+++ clients/emacs/emacsobp.rc 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,56 @@
+; EMACS.RC: Startup file for MicroEMACS 3.4
+;
+; This file is executed everytime the
+; editor is entered
+;
+; This version of the file contains bindings for Open Firmware.
+
+; Set up bindings
+
+; bind-to-key meta-prefix `
+
+bind-to-key find-file ^X^V
+bind-to-key delete-window ^X^D
+bind-to-key next-window ^XN
+bind-to-key search-forward ^S
+bind-to-key search-forward ^\
+bind-to-key search-reverse ^R
+bind-to-key save-file ^XS
+bind-to-key apropos M-?
+bind-to-key select-buffer ^X^O
+bind-to-key delete-buffer ^XK
+bind-to-key move-window-down ^Z
+bind-to-key move-window-up M-Z
+
+
+; set screen colors
+add-global-mode "blue"
+add-global-mode "WHITE"
+
+; consult file
+3 store-macro
+ 2 split-current-window
+ previous-window
+ view-file "@File to Consult: "
+ 8 resize-window
+ add-mode "green"
+ add-mode "Black"
+ next-window
+[end]
+
+; last help page
+12 store-macro
+ begining-of-line
+ search-reverse "=>"
+ 1 redraw-display
+[end]
+
+; next help page
+13 store-macro
+ begining-of-line
+ 2 forward-character
+ search-forward "=>"
+ 1 redraw-display
+[end]
+
+execute-macro-1
Added: clients/emacs/epath.h
===================================================================
--- clients/emacs/epath.h (rev 0)
+++ clients/emacs/epath.h 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,61 @@
+/* PATH: This file contains certain info needed to locate the
+ MicroEMACS files on a system dependant basis.
+
+ */
+
+/* possible names and paths of help files under different OSs */
+
+char *pathname[] =
+
+#if OFW
+{
+ "emacs.rc",
+ "emacs.hlp",
+ "",
+ "/disk:\\",
+ "rom:"
+};
+#endif
+
+#if AMIGA
+{
+ ".emacsrc",
+ "emacs.hlp",
+ "",
+ ":c/",
+ ":t/"
+};
+#endif
+
+#if MSDOS
+{
+ "emacs.rc",
+ "emacs.hlp",
+ "",
+ "\\",
+ "\\bin\\",
+ "\\fm\\emacs\\",
+ "c:\\fm\\emacs\\"
+};
+#endif
+
+#if V7 | BSD | USG
+{
+ ".emacsrc",
+ "emacs.hlp",
+ "/usr/local/",
+ "/usr/lib/",
+ ""
+};
+#endif
+
+#if VMS
+{
+ "emacs.rc",
+ "emacs.hlp",
+ "",
+ "sys$sysdevice:[vmstools]"
+};
+#endif
+
+#define NPNAMES (sizeof(pathname)/sizeof(char *))
Added: clients/emacs/estruct.h
===================================================================
--- clients/emacs/estruct.h (rev 0)
+++ clients/emacs/estruct.h 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,247 @@
+/* ESTRUCT: Structure and preprocesser defined for
+ MicroEMACS 3.7
+
+ written by Dave G. Conroy
+ modified by Steve Wilhite, George Jones
+ greatly modified by Daniel Lawrence
+*/
+
+#include "config.h"
+
+/* System dependant library redefinitions, structures and includes */
+
+#if MSDOS & AZTEC
+#undef fputc
+#undef fgetc
+#define fputc aputc
+#define fgetc agetc
+#define int86 sysint
+#define inp inportb
+
+struct XREG {
+ int ax,bx,cx,dx,si,di;
+};
+
+struct HREG {
+ char al,ah,bl,bh,cl,ch,dl,dh;
+};
+
+union REGS {
+ struct XREG x;
+ struct HREG h;
+};
+#endif
+
+#if MSDOS & LATTICE
+#undef CPM
+#undef LATTICE
+#include <dos.h>
+#undef CPM
+#endif
+
+/* internal constants */
+
+#define NBINDS 200 /* max # of bound keys */
+#define NFILEN 80 /* # of bytes, file name */
+#define NBUFN 16 /* # of bytes, buffer name */
+#define NLINE 256 /* # of bytes, line */
+#define NSTRING 256 /* # of bytes, string buffers */
+#define NKBDM 256 /* # of strokes, keyboard macro */
+#define NPAT 80 /* # of bytes, pattern */
+#define HUGE 1000 /* Huge number */
+#define NLOCKS 100 /* max # of file locks active */
+#define NCOLORS 8 /* number of supported colors */
+#define KBLOCK 250 /* sizeof kill buffer chunks */
+#define NBLOCK 16 /* line block chunk size */
+
+#define AGRAVE 0x60 /* M- prefix, Grave (LK201) */
+#define METACH 0x1B /* M- prefix, Control-[, ESC */
+#define CTMECH 0x1C /* C-M- prefix, Control-\ */
+#define EXITCH 0x1D /* Exit level, Control-] */
+#define CTRLCH 0x1E /* C- prefix, Control-^ */
+#define HELPCH 0x1F /* Help key, Control-_ */
+
+#define CTRL 0x0100 /* Control flag, or'ed in */
+#define META 0x0200 /* Meta flag, or'ed in */
+#define CTLX 0x0400 /* ^X flag, or'ed in */
+#define SPEC 0x0800 /* special key (function keys) */
+
+#define FALSE 0 /* False, no, bad, etc. */
+#define TRUE 1 /* True, yes, good, etc. */
+#define ABORT 2 /* Death, ^G, abort, etc. */
+
+#define FIOSUC 0 /* File I/O, success. */
+#define FIOFNF 1 /* File I/O, file not found. */
+#define FIOEOF 2 /* File I/O, end of file. */
+#define FIOERR 3 /* File I/O, error. */
+#define FIOLNG 4 /*line longer than allowed len */
+
+#define CFCPCN 0x0001 /* Last command was C-P, C-N */
+#define CFKILL 0x0002 /* Last command was a kill */
+
+#define BELL 0x07 /* a bell character */
+#define TAB 0x09 /* a tab character */
+
+/*
+ * There is a window structure allocated for every active display window. The
+ * windows are kept in a big list, in top to bottom screen order, with the
+ * listhead at "wheadp". Each window contains its own values of dot and mark.
+ * The flag field contains some bits that are set by commands to guide
+ * redisplay; although this is a bit of a compromise in terms of decoupling,
+ * the full blown redisplay is just too expensive to run for every input
+ * character.
+ */
+typedef struct WINDOW {
+ struct WINDOW *w_wndp; /* Next window */
+ struct BUFFER *w_bufp; /* Buffer displayed in window */
+ struct LINE *w_linep; /* Top line in the window */
+ struct LINE *w_dotp; /* Line containing "." */
+ short w_doto; /* Byte offset for "." */
+ struct LINE *w_markp; /* Line containing "mark" */
+ short w_marko; /* Byte offset for "mark" */
+ char w_toprow; /* Origin 0 top row of window */
+ char w_ntrows; /* # of rows of text in window */
+ char w_force; /* If NZ, forcing row. */
+ char w_flag; /* Flags. */
+#if COLOR
+ char w_fcolor; /* current forground color */
+ char w_bcolor; /* current background color */
+#endif
+} WINDOW;
+
+#define WFFORCE 0x01 /* Window needs forced reframe */
+#define WFMOVE 0x02 /* Movement from line to line */
+#define WFEDIT 0x04 /* Editing within a line */
+#define WFHARD 0x08 /* Better to a full display */
+#define WFMODE 0x10 /* Update mode line. */
+#define WFCOLR 0x20 /* Needs a color change */
+
+/*
+ * Text is kept in buffers. A buffer header, described below, exists for every
+ * buffer in the system. The buffers are kept in a big list, so that commands
+ * that search for a buffer by name can find the buffer header. There is a
+ * safe store for the dot and mark in the header, but this is only valid if
+ * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
+ * the buffer is kept in a circularly linked list of lines, with a pointer to
+ * the header line in "b_linep".
+ * Buffers may be "Inactive" which means the files accosiated with them
+ * have not been read in yet. These get read in at "use buffer" time.
+ */
+typedef struct BUFFER {
+ struct BUFFER *b_bufp; /* Link to next BUFFER */
+ struct LINE *b_dotp; /* Link to "." LINE structure */
+ short b_doto; /* Offset of "." in above LINE */
+ struct LINE *b_markp; /* The same as the above two, */
+ short b_marko; /* but for the "mark" */
+ struct LINE *b_linep; /* Link to the header LINE */
+ char b_active; /* window activated flag */
+ char b_nwnd; /* Count of windows on buffer */
+ char b_flag; /* Flags */
+ char b_mode; /* editor mode of this buffer */
+ char b_fname[NFILEN]; /* File name */
+ char b_bname[NBUFN]; /* Buffer name */
+} BUFFER;
+
+#define BFINVS 0x01 /* Internal invisable buffer */
+#define BFCHG 0x02 /* Changed since last write */
+
+/* mode flags */
+#define NUMMODES 7 /* # of defined modes */
+
+#define MDWRAP 0x0001 /* word wrap */
+#define MDCMOD 0x0002 /* C indentation and fence match*/
+#define MDSPELL 0x0004 /* spell error parcing */
+#define MDEXACT 0x0008 /* Exact matching for searches */
+#define MDVIEW 0x0010 /* read-only buffer */
+#define MDOVER 0x0020 /* overwrite mode */
+#define MDMAGIC 0x0040 /* regular expresions in search */
+
+/*
+ * The starting position of a region, and the size of the region in
+ * characters, is kept in a region structure. Used by the region commands.
+ */
+typedef struct {
+ struct LINE *r_linep; /* Origin LINE address. */
+ short r_offset; /* Origin LINE offset. */
+ long r_size; /* Length in characters. */
+} REGION;
+
+/*
+ * All text is kept in circularly linked lists of "LINE" structures. These
+ * begin at the header line (which is the blank line beyond the end of the
+ * buffer). This line is pointed to by the "BUFFER". Each line contains a the
+ * number of bytes in the line (the "used" size), the size of the text array,
+ * and the text. The end of line is not stored as a byte; it's implied. Future
+ * additions will include update hints, and a list of marks into the line.
+ */
+typedef struct LINE {
+ struct LINE *l_fp; /* Link to the next line */
+ struct LINE *l_bp; /* Link to the previous line */
+ short l_size; /* Allocated size */
+ short l_used; /* Used size */
+ char l_text[1]; /* A bunch of characters. */
+} LINE;
+
+#define lforw(lp) ((lp)->l_fp)
+#define lback(lp) ((lp)->l_bp)
+#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)
+#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
+#define llength(lp) ((lp)->l_used)
+
+/*
+ * The editor communicates with the display using a high level interface. A
+ * "TERM" structure holds useful variables, and indirect pointers to routines
+ * that do useful operations. The low level get and put routines are here too.
+ * This lets a terminal, in addition to having non standard commands, have
+ * funny get and put character code too. The calls might get changed to
+ * "termp->t_field" style in the future, to make it possible to run more than
+ * one terminal type.
+ */
+typedef struct {
+ short t_nrow; /* Number of rows. */
+ short t_ncol; /* Number of columns. */
+ short t_margin; /* min margin for extended lines*/
+ short t_scrsiz; /* size of scroll region " */
+ int t_pause; /* # times thru update to pause */
+ int (*t_open)(); /* Open terminal at the start. */
+ int (*t_close)(); /* Close terminal at end. */
+ int (*t_getchar)(); /* Get character from keyboard. */
+ int (*t_putchar)(); /* Put character to display. */
+ int (*t_flush)(); /* Flush output buffers. */
+ int (*t_move)(); /* Move the cursor, origin 0. */
+ int (*t_eeol)(); /* Erase to end of line. */
+ int (*t_eeop)(); /* Erase to end of page. */
+ int (*t_beep)(); /* Beep. */
+ int (*t_rev)(); /* set reverse video state */
+#if COLOR
+ int (*t_setfor)(); /* set forground color */
+ int (*t_setback)(); /* set background color */
+#endif
+} TERM;
+
+/* structure for the table of initial key bindings */
+
+typedef struct {
+ short k_code; /* Key code */
+ int (*k_fp)(); /* Routine to handle it */
+} KEYTAB;
+
+/* structure for the name binding table */
+
+typedef struct {
+ char *n_name; /* name of function key */
+ int (*n_func)(); /* function name is bound to */
+} NBIND;
+
+/* The editor holds deleted text chunks in the KILL buffer. The
+ kill buffer is logically a stream of ascii characters, however
+ due to its unpredicatable size, it gets implemented as a linked
+ list of chunks. (The d_ prefix is for "deleted" text, as k_
+ was taken up by the keycode structure */
+
+typedef struct KILL {
+ struct KILL *d_next; /* link to next chunk, NULL if last */
+ char d_chunk[KBLOCK]; /* deleted text */
+} KILL;
+
+#define NULL 0
Added: clients/emacs/estructp.h
===================================================================
--- clients/emacs/estructp.h (rev 0)
+++ clients/emacs/estructp.h 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,302 @@
+/* ESTRUCT: Structure and preprocesser defined for
+ MicroEMACS 3.7
+
+ written by Dave G. Conroy
+ modified by Steve Wilhite, George Jones
+ greatly modified by Daniel Lawrence
+*/
+
+#undef LATTICE /* don't use their definitions...use ours */
+#undef MSDOS
+#undef CPM
+#undef AMIGA
+
+/* Machine/OS definitions */
+
+#define AMIGA 0 /* AmigaDOS */
+#define ST520 0 /* ST520, TOS */
+#define MSDOS 1 /* MS-DOS */
+#define V7 0 /* V7 UN*X or Coherent or BSD4.2*/
+#define BSD 0 /* UNIX BSD 4.2 and ULTRIX */
+#define USG 0 /* UNIX system V */
+#define VMS 0 /* VAX/VMS */
+#define CPM 0 /* CP/M-86 */
+
+/* Compiler definitions */
+#define MWC86 0 /* marc williams compiler */
+#define LATTICE 0 /* either lattice compiler */
+#define LAT2 0 /* Lattice 2.15 */
+#define LAT3 0 /* Lattice 3.0 */
+#define AZTEC 0 /* Aztec C 3.20e */
+#define MSC 1 /* MicroSoft C compile version 3 */
+
+/* Profiling options */
+#define APROF 0 /* turn Aztec C profiling on? */
+#define NBUCK 100 /* number of buckets to profile */
+
+/* Special keyboard definitions */
+
+#define WANGPC 0 /* WangPC - mostly escape sequences */
+
+/* Terminal Output definitions */
+
+#define ANSI 0 /* ansi escape sequences */
+#define HP150 0 /* HP150 screen driver */
+#define VMSVT 0 /* various VMS terminal entries */
+#define VT52 0 /* VT52 terminal (Zenith). */
+#define VT100 0 /* Handle VT100 style keypad. */
+#define LK201 0 /* Handle LK201 style keypad. */
+#define RAINBOW 0 /* Use Rainbow fast video. */
+#define TERMCAP 0 /* Use TERMCAP */
+#define IBMPC 1 /* IBM-PC specific driver */
+#define DG10 0 /* Data General system/10 */
+
+/* Configuration options */
+
+#define CVMVAS 1 /* arguments to page forward/back in pages */
+#define NFWORD 1 /* forward word jumps to begining of word */
+#define CLRMSG 0 /* space clears the message line with no insert */
+#define TYPEAH 1 /* type ahead causes update to be skipped */
+#define FILOCK 0 /* file locking under unix BSD 4.2 */
+#define REVSTA 1 /* Status line appears in reverse video */
+#define COLOR 1 /* color commands and windows */
+#define ACMODE 1 /* auto CMODE on .C and .H files */
+#define CFENCE 1 /* fench matching in CMODE */
+#define ISRCH 1 /* Incremental searches like ITS EMACS */
+#define WORDPRO 1 /* Advanced word processing features */
+
+/* System dependant library redefinitions, structures and includes */
+
+#if MSDOS & AZTEC
+#undef fputc
+#undef fgetc
+#define fputc aputc
+#define fgetc agetc
+#define int86 sysint
+#define inp inportb
+
+struct XREG {
+ int ax,bx,cx,dx,si,di;
+};
+
+struct HREG {
+ char al,ah,bl,bh,cl,ch,dl,dh;
+};
+
+union REGS {
+ struct XREG x;
+ struct HREG h;
+};
+#endif
+
+#if MSDOS & LATTICE
+#undef CPM
+#undef LATTICE
+#include <dos.h>
+#undef CPM
+#endif
+
+/* internal constants */
+
+#define NBINDS 200 /* max # of bound keys */
+#define NFILEN 80 /* # of bytes, file name */
+#define NBUFN 16 /* # of bytes, buffer name */
+#define NLINE 256 /* # of bytes, line */
+#define NSTRING 256 /* # of bytes, string buffers */
+#define NKBDM 256 /* # of strokes, keyboard macro */
+#define NPAT 80 /* # of bytes, pattern */
+#define HUGE 1000 /* Huge number */
+#define NLOCKS 100 /* max # of file locks active */
+#define NCOLORS 8 /* number of supported colors */
+#define KBLOCK 250 /* sizeof kill buffer chunks */
+#define NBLOCK 16 /* line block chunk size */
+
+#define AGRAVE 0x60 /* M- prefix, Grave (LK201) */
+#define METACH 0x1B /* M- prefix, Control-[, ESC */
+#define CTMECH 0x1C /* C-M- prefix, Control-\ */
+#define EXITCH 0x1D /* Exit level, Control-] */
+#define CTRLCH 0x1E /* C- prefix, Control-^ */
+#define HELPCH 0x1F /* Help key, Control-_ */
+
+#define CTRL 0x0100 /* Control flag, or'ed in */
+#define META 0x0200 /* Meta flag, or'ed in */
+#define CTLX 0x0400 /* ^X flag, or'ed in */
+#define SPEC 0x0800 /* special key (function keys) */
+
+#define FALSE 0 /* False, no, bad, etc. */
+#define TRUE 1 /* True, yes, good, etc. */
+#define ABORT 2 /* Death, ^G, abort, etc. */
+
+#define FIOSUC 0 /* File I/O, success. */
+#define FIOFNF 1 /* File I/O, file not found. */
+#define FIOEOF 2 /* File I/O, end of file. */
+#define FIOERR 3 /* File I/O, error. */
+#define FIOLNG 4 /*line longer than allowed len */
+
+#define CFCPCN 0x0001 /* Last command was C-P, C-N */
+#define CFKILL 0x0002 /* Last command was a kill */
+
+#define BELL 0x07 /* a bell character */
+#define TAB 0x09 /* a tab character */
+
+/*
+ * There is a window structure allocated for every active display window. The
+ * windows are kept in a big list, in top to bottom screen order, with the
+ * listhead at "wheadp". Each window contains its own values of dot and mark.
+ * The flag field contains some bits that are set by commands to guide
+ * redisplay; although this is a bit of a compromise in terms of decoupling,
+ * the full blown redisplay is just too expensive to run for every input
+ * character.
+ */
+typedef struct WINDOW {
+ struct WINDOW *w_wndp; /* Next window */
+ struct BUFFER *w_bufp; /* Buffer displayed in window */
+ struct LINE *w_linep; /* Top line in the window */
+ struct LINE *w_dotp; /* Line containing "." */
+ short w_doto; /* Byte offset for "." */
+ struct LINE *w_markp; /* Line containing "mark" */
+ short w_marko; /* Byte offset for "mark" */
+ char w_toprow; /* Origin 0 top row of window */
+ char w_ntrows; /* # of rows of text in window */
+ char w_force; /* If NZ, forcing row. */
+ char w_flag; /* Flags. */
+#if COLOR
+ char w_fcolor; /* current forground color */
+ char w_bcolor; /* current background color */
+#endif
+} WINDOW;
+
+#define WFFORCE 0x01 /* Window needs forced reframe */
+#define WFMOVE 0x02 /* Movement from line to line */
+#define WFEDIT 0x04 /* Editing within a line */
+#define WFHARD 0x08 /* Better to a full display */
+#define WFMODE 0x10 /* Update mode line. */
+#define WFCOLR 0x20 /* Needs a color change */
+
+/*
+ * Text is kept in buffers. A buffer header, described below, exists for every
+ * buffer in the system. The buffers are kept in a big list, so that commands
+ * that search for a buffer by name can find the buffer header. There is a
+ * safe store for the dot and mark in the header, but this is only valid if
+ * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
+ * the buffer is kept in a circularly linked list of lines, with a pointer to
+ * the header line in "b_linep".
+ * Buffers may be "Inactive" which means the files accosiated with them
+ * have not been read in yet. These get read in at "use buffer" time.
+ */
+typedef struct BUFFER {
+ struct BUFFER *b_bufp; /* Link to next BUFFER */
+ struct LINE *b_dotp; /* Link to "." LINE structure */
+ short b_doto; /* Offset of "." in above LINE */
+ struct LINE *b_markp; /* The same as the above two, */
+ short b_marko; /* but for the "mark" */
+ struct LINE *b_linep; /* Link to the header LINE */
+ char b_active; /* window activated flag */
+ char b_nwnd; /* Count of windows on buffer */
+ char b_flag; /* Flags */
+ char b_mode; /* editor mode of this buffer */
+ char b_fname[NFILEN]; /* File name */
+ char b_bname[NBUFN]; /* Buffer name */
+} BUFFER;
+
+#define BFINVS 0x01 /* Internal invisable buffer */
+#define BFCHG 0x02 /* Changed since last write */
+
+/* mode flags */
+#define NUMMODES 7 /* # of defined modes */
+
+#define MDWRAP 0x0001 /* word wrap */
+#define MDCMOD 0x0002 /* C indentation and fence match*/
+#define MDSPELL 0x0004 /* spell error parcing */
+#define MDEXACT 0x0008 /* Exact matching for searches */
+#define MDVIEW 0x0010 /* read-only buffer */
+#define MDOVER 0x0020 /* overwrite mode */
+#define MDMAGIC 0x0040 /* regular expresions in search */
+
+/*
+ * The starting position of a region, and the size of the region in
+ * characters, is kept in a region structure. Used by the region commands.
+ */
+typedef struct {
+ struct LINE *r_linep; /* Origin LINE address. */
+ short r_offset; /* Origin LINE offset. */
+ long r_size; /* Length in characters. */
+} REGION;
+
+/*
+ * All text is kept in circularly linked lists of "LINE" structures. These
+ * begin at the header line (which is the blank line beyond the end of the
+ * buffer). This line is pointed to by the "BUFFER". Each line contains a the
+ * number of bytes in the line (the "used" size), the size of the text array,
+ * and the text. The end of line is not stored as a byte; it's implied. Future
+ * additions will include update hints, and a list of marks into the line.
+ */
+typedef struct LINE {
+ struct LINE *l_fp; /* Link to the next line */
+ struct LINE *l_bp; /* Link to the previous line */
+ short l_size; /* Allocated size */
+ short l_used; /* Used size */
+ char l_text[1]; /* A bunch of characters. */
+} LINE;
+
+#define lforw(lp) ((lp)->l_fp)
+#define lback(lp) ((lp)->l_bp)
+#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)
+#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
+#define llength(lp) ((lp)->l_used)
+
+/*
+ * The editor communicates with the display using a high level interface. A
+ * "TERM" structure holds useful variables, and indirect pointers to routines
+ * that do useful operations. The low level get and put routines are here too.
+ * This lets a terminal, in addition to having non standard commands, have
+ * funny get and put character code too. The calls might get changed to
+ * "termp->t_field" style in the future, to make it possible to run more than
+ * one terminal type.
+ */
+typedef struct {
+ short t_nrow; /* Number of rows. */
+ short t_ncol; /* Number of columns. */
+ short t_margin; /* min margin for extended lines*/
+ short t_scrsiz; /* size of scroll region " */
+ int t_pause; /* # times thru update to pause */
+ int (*t_open)(); /* Open terminal at the start. */
+ int (*t_close)(); /* Close terminal at end. */
+ int (*t_getchar)(); /* Get character from keyboard. */
+ int (*t_putchar)(); /* Put character to display. */
+ int (*t_flush)(); /* Flush output buffers. */
+ int (*t_move)(); /* Move the cursor, origin 0. */
+ int (*t_eeol)(); /* Erase to end of line. */
+ int (*t_eeop)(); /* Erase to end of page. */
+ int (*t_beep)(); /* Beep. */
+ int (*t_rev)(); /* set reverse video state */
+#if COLOR
+ int (*t_setfor)(); /* set forground color */
+ int (*t_setback)(); /* set background color */
+#endif
+} TERM;
+
+/* structure for the table of initial key bindings */
+
+typedef struct {
+ short k_code; /* Key code */
+ int (*k_fp)(); /* Routine to handle it */
+} KEYTAB;
+
+/* structure for the name binding table */
+
+typedef struct {
+ char *n_name; /* name of function key */
+ int (*n_func)(); /* function name is bound to */
+} NBIND;
+
+/* The editor holds deleted text chunks in the KILL buffer. The
+ kill buffer is logically a stream of ascii characters, however
+ due to its unpredicatable size, it gets implemented as a linked
+ list of chunks. (The d_ prefix is for "deleted" text, as k_
+ was taken up by the keycode structure */
+
+typedef struct KILL {
+ struct KILL *d_next; /* link to next chunk, NULL if last */
+ char d_chunk[KBLOCK]; /* deleted text */
+} KILL;
Added: clients/emacs/exec.c
===================================================================
--- clients/emacs/exec.c (rev 0)
+++ clients/emacs/exec.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,727 @@
+/* This file is for functions dealing with execution of
+ commands, command lines, buffers, files and startup files
+
+ written 1986 by Daniel Lawrence */
+
+#include "estruct.h"
+#include "edef.h"
+
+/* namedcmd: execute a named command even if it is not bound
+*/
+
+namedcmd(f, n)
+
+int f, n; /* command arguments [passed through to command executed] */
+
+{
+ register (*kfunc)(); /* ptr to the requexted function to bind to */
+ int (*getname())();
+
+ /* prompt the user to type a named command */
+ mlwrite(": ");
+
+ /* and now get the function name to execute */
+ kfunc = getname();
+ if (kfunc == NULL) {
+ mlwrite("[No such function]");
+ return(FALSE);
+ }
+
+ /* and then execute the command */
+ return((*kfunc)(f, n));
+}
+
+/* execcmd: Execute a command line command to be typed in
+ by the user */
+
+execcmd(f, n)
+
+int f, n; /* default Flag and Numeric argument */
+
+{
+ register int status; /* status return */
+ char cmdstr[NSTRING]; /* string holding command to execute */
+
+ /* get the line wanted */
+ if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
+ return(status);
+
+ return(docmd(cmdstr));
+}
+
+/* docmd: take a passed string as a command line and translate
+ it to be executed as a command. This function will be
+ used by execute-command-line and by all source and
+ startup files.
+
+ format of the command line is:
+
+ {# arg} <command-name> {<argument string(s)>}
+
+ Macro storing is turned off by a line:
+
+ [end]
+*/
+
+docmd(cline)
+
+char *cline; /* command line to execute */
+
+{
+ register char *tp; /* pointer to current position in token */
+ register int f; /* default argument flag */
+ register int n; /* numeric repeat value */
+ register int i;
+ int sign; /* sign of numeric argument */
+ int (*fnc)(); /* function to execute */
+ int status; /* return status of function */
+ int oldcle; /* old contents of clexec flag */
+ int llen; /* length of cline */
+ struct LINE *lp; /* a line pointer */
+ char token[NSTRING]; /* next token off of command line */
+ int (*fncmatch())();
+
+ /* check to see if this line turns macro storage off */
+ if (strcmp(cline, "[end]") == 0) {
+ mstore = FALSE;
+ bstore = NULL;
+ return(TRUE);
+ }
+
+ /* if macro store is on, just salt this away */
+ if (mstore) {
+ /* trim leading indentation */
+ while (cline[0] == ' ' || cline[0] == '\t')
+ strcpy(cline, &cline[1]);
+
+ /* allocate the space for the line */
+ llen = strlen(cline);
+ if ((lp=lalloc(llen)) == NULL) {
+ mlwrite("Out of memory while storing macro");
+ return (FALSE);
+ }
+
+ /* copy the text into the new line */
+ for (i=0; i<llen; ++i)
+ lputc(lp, i, cline[i]);
+
+ /* attach the line to the end of the buffer */
+ bstore->b_linep->l_bp->l_fp = lp;
+ lp->l_bp = bstore->b_linep->l_bp;
+ bstore->b_linep->l_bp = lp;
+ lp->l_fp = bstore->b_linep;
+ return (TRUE);
+ }
+
+ /* first set up the default command values */
+ f = FALSE;
+ n = 1;
+
+ strcpy(sarg, cline); /* move string to string argument buffer */
+ if ((status = nxtarg(token)) != TRUE) /* and grab the first token */
+ return(status);
+
+ /* check for and process numeric leadin argument */
+ if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') {
+ f = TRUE;
+ n = 0;
+ tp = &token[0];
+
+ /* check for a sign! */
+ sign = 1;
+ if (*tp == '-') {
+ ++tp;
+ sign = -1;
+ }
+
+ /* calc up the digits in the token string */
+ while(*tp) {
+ if (*tp >= '0' && *tp <= '9')
+ n = n * 10 + *tp - '0';
+ ++tp;
+ }
+ n *= sign; /* adjust for the sign */
+
+ /* and now get the command to execute */
+ if ((status = nxtarg(token)) != TRUE)
+ return(status);
+ }
+
+ /* and match the token to see if it exists */
+ if ((fnc = fncmatch(token)) == NULL) {
+ mlwrite("[No such Function]");
+ return(FALSE);
+ }
+
+ /* save the arguments and go execute the command */
+ oldcle = clexec; /* save old clexec flag */
+ clexec = TRUE; /* in cline execution */
+ status = (*fnc)(f, n); /* call the function */
+ clexec = oldcle; /* restore clexec flag */
+ return(status);
+}
+
+/* gettok: chop a token off a string
+ return a pointer past the token
+*/
+
+char *gettok(src, tok)
+
+char *src, *tok; /* source string, destination token string */
+
+{
+ register int quotef; /* is the current string quoted? */
+
+ /* first scan past any whitespace in the source string */
+ while (*src == ' ' || *src == '\t')
+ ++src;
+
+ /* if quoted, record it */
+ quotef = (*src == '"');
+ if (quotef)
+ ++src;
+
+ /* scan through the source string */
+ while (*src) {
+ /* process special characters */
+ if (*src == '~') {
+ ++src;
+ if (*src == 0)
+ break;
+ switch (*src++) {
+ case 'r': *tok++ = 13; break;
+ case 'n': *tok++ = 10; break;
+ case 't': *tok++ = 9; break;
+ case 'b': *tok++ = 8; break;
+ case 'f': *tok++ = 12; break;
+ case '@': *tok++ = 192;break;
+ default: *tok++ = *(src-1);
+ }
+ } else {
+ /* check for the end of the token */
+ if (quotef) {
+ if (*src == '"')
+ break;
+ } else {
+ if (*src == ' ' || *src == '\t')
+ break;
+ }
+
+ /* record the character */
+ *tok++ = *src++;
+ }
+ }
+
+ /* terminate the token and exit */
+ if (*src)
+ ++src;
+ *tok = 0;
+ return(src);
+}
+
+/* nxtarg: grab the next token out of sarg, return it, and
+ chop it of sarg */
+
+nxtarg(tok)
+
+char *tok; /* buffer to put token into */
+
+{
+ register char *newsarg; /* pointer to new begining of sarg */
+ register oldexec; /* saved execution flag */
+ register BUFFER *bp; /* ptr to buffer to get arg from */
+ register int status;
+ char *gettok();
+
+ newsarg = gettok(sarg, tok); /* grab the token */
+ strcpy(sarg, newsarg); /* and chop it of sarg */
+
+ /* check for an interactive argument */
+ if (*tok == '@') { /* get interactive argument */
+ oldexec = clexec; /* save execution flag */
+ clexec = FALSE;
+ status = mlreply(&tok[1], &tok[0], NSTRING);
+ clexec = oldexec;
+ if (status != TRUE)
+ return(status);
+ }
+
+ /* check for a quoted "@" in the first position */
+ if ((unsigned char)*tok == 192)
+ *tok = '@';
+
+ /* check for an argument from a buffer */
+ if (*tok == '#') {
+
+ /* get the referenced buffer */
+ bp = bfind(&tok[1], FALSE, 0);
+ if (bp == NULL)
+ return(FALSE);
+
+ /* make sure we are not at the end */
+ if (bp->b_linep == bp->b_dotp)
+ return(FALSE);
+
+ /* grab the line as an argument */
+ strncpy(tok, bp->b_dotp->l_text, bp->b_dotp->l_used);
+ tok[bp->b_dotp->l_used] = 0;
+
+ /* and step the buffer's line ptr ahead a line */
+ bp->b_dotp = bp->b_dotp->l_fp;
+ bp->b_doto = 0;
+ }
+
+ return(TRUE);
+}
+
+/* storemac: Set up a macro buffer and flag to store all
+ executed command lines there */
+
+storemac(f, n)
+
+int f; /* default flag */
+int n; /* macro number to use */
+
+{
+ register struct BUFFER *bp; /* pointer to macro buffer */
+ char bname[NBUFN]; /* name of buffer to use */
+
+ /* must have a numeric argument to this function */
+ if (f == FALSE) {
+ mlwrite("No macro specified");
+ return(FALSE);
+ }
+
+ /* range check the macro number */
+ if (n < 1 || n > 40) {
+ mlwrite("Macro number out of range");
+ return(FALSE);
+ }
+
+ /* construct the macro buffer name */
+ strcpy(bname, "[Macro xx]");
+ bname[7] = '0' + (n / 10);
+ bname[8] = '0' + (n % 10);
+
+ /* set up the new macro buffer */
+ if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
+ mlwrite("Can not create macro");
+ return(FALSE);
+ }
+
+ /* and make sure it is empty */
+ bclear(bp);
+
+ /* and set the macro store pointers to it */
+ mstore = TRUE;
+ bstore = bp;
+ return(TRUE);
+}
+
+/* execbuf: Execute the contents of a buffer of commands */
+
+execbuf(f, n)
+
+int f, n; /* default flag and numeric arg */
+
+{
+ register BUFFER *bp; /* ptr to buffer to execute */
+ register int status; /* status return */
+ char bufn[NBUFN]; /* name of buffer to execute */
+
+ /* find out what buffer the user wants to execute */
+ if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
+ return(status);
+
+ /* find the pointer to that buffer */
+ if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
+ mlwrite("No such buffer");
+ return(FALSE);
+ }
+
+ /* and now execute it as asked */
+ while (n-- > 0)
+ if ((status = dobuf(bp)) != TRUE)
+ return(status);
+ return(TRUE);
+}
+
+/* dobuf: execute the contents of the buffer pointed to
+ by the passed BP */
+
+dobuf(bp)
+
+BUFFER *bp; /* buffer to execute */
+
+{
+ register int status; /* status return */
+ register LINE *lp; /* pointer to line to execute */
+ register LINE *hlp; /* pointer to line header */
+ register int linlen; /* length of line to execute */
+ register WINDOW *wp; /* ptr to windows to scan */
+ char eline[NSTRING]; /* text of line to execute */
+
+ /* starting at the beginning of the buffer */
+ hlp = bp->b_linep;
+ lp = hlp->l_fp;
+ while (lp != hlp) {
+ /* calculate the line length and make a local copy */
+ linlen = lp->l_used;
+ if (linlen > NSTRING - 1)
+ linlen = NSTRING - 1;
+ strncpy(eline, lp->l_text, linlen);
+ eline[linlen] = 0; /* make sure it ends */
+
+ /* if it is not a comment, execute it */
+ if (eline[0] != ';' && eline[0] != 0) {
+ status = docmd(eline);
+ if (status != TRUE) { /* a command error */
+ /* look if buffer is showing */
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_bufp == bp) {
+ /* and point it */
+ wp->w_dotp = lp;
+ wp->w_doto = 0;
+ wp->w_flag |= WFHARD;
+ }
+ wp = wp->w_wndp;
+ }
+ /* in any case set the buffer . */
+ bp->b_dotp = lp;
+ bp->b_doto = 0;
+ return(status);
+ }
+ }
+ lp = lp->l_fp; /* on to the next line */
+ }
+ return(TRUE);
+}
+
+execfile(f, n) /* execute a series of commands in a file
+*/
+
+int f, n; /* default flag and numeric arg to pass on to file */
+
+{
+ register int status; /* return status of name query */
+ char *fname[NSTRING]; /* name of file to execute */
+
+ if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE)
+ return(status);
+
+ /* otherwise, execute it */
+ while (n-- > 0)
+ if ((status=dofile(fname)) != TRUE)
+ return(status);
+
+ return(TRUE);
+}
+
+/* dofile: yank a file into a buffer and execute it
+ if there are no errors, delete the buffer on exit */
+
+dofile(fname)
+
+char *fname; /* file name to execute */
+
+{
+ register BUFFER *bp; /* buffer to place file to exeute */
+ register BUFFER *cb; /* temp to hold current buf while we read */
+ register int status; /* results of various calls */
+ char bname[NBUFN]; /* name of buffer */
+
+ makename(bname, fname); /* derive the name of the buffer */
+ if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
+ return(FALSE);
+
+ bp->b_mode = MDVIEW; /* mark the buffer as read only */
+ cb = curbp; /* save the old buffer */
+ curbp = bp; /* make this one current */
+ /* and try to read in the file to execute */
+ if ((status = readin(fname, FALSE)) != TRUE) {
+ curbp = cb; /* restore the current buffer */
+ return(status);
+ }
+
+ /* go execute it! */
+ curbp = cb; /* restore the current buffer */
+ if ((status = dobuf(bp)) != TRUE)
+ return(status);
+
+ /* if not displayed, remove the now unneeded buffer and exit */
+ if (bp->b_nwnd == 0)
+ zotbuf(bp);
+ return(TRUE);
+}
+
+/* cbuf: Execute the contents of a numbered buffer */
+
+cbuf(f, n, bufnum)
+
+int f, n; /* default flag and numeric arg */
+int bufnum; /* number of buffer to execute */
+
+{
+ register BUFFER *bp; /* ptr to buffer to execute */
+ register int status; /* status return */
+ static char bufname[] = "[Macro xx]";
+
+ /* make the buffer name */
+ bufname[7] = '0' + (bufnum / 10);
+ bufname[8] = '0' + (bufnum % 10);
+
+ /* find the pointer to that buffer */
+ if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
+ mlwrite("Macro not defined");
+ return(FALSE);
+ }
+
+ /* and now execute it as asked */
+ while (n-- > 0)
+ if ((status = dobuf(bp)) != TRUE)
+ return(status);
+ return(TRUE);
+}
+
+cbuf1(f, n)
+
+{
+ cbuf(f, n, 1);
+}
+
+cbuf2(f, n)
+
+{
+ cbuf(f, n, 2);
+}
+
+cbuf3(f, n)
+
+{
+ cbuf(f, n, 3);
+}
+
+cbuf4(f, n)
+
+{
+ cbuf(f, n, 4);
+}
+
+cbuf5(f, n)
+
+{
+ cbuf(f, n, 5);
+}
+
+cbuf6(f, n)
+
+{
+ cbuf(f, n, 6);
+}
+
+cbuf7(f, n)
+
+{
+ cbuf(f, n, 7);
+}
+
+cbuf8(f, n)
+
+{
+ cbuf(f, n, 8);
+}
+
+cbuf9(f, n)
+
+{
+ cbuf(f, n, 9);
+}
+
+cbuf10(f, n)
+
+{
+ cbuf(f, n, 10);
+}
+
+cbuf11(f, n)
+
+{
+ cbuf(f, n, 11);
+}
+
+cbuf12(f, n)
+
+{
+ cbuf(f, n, 12);
+}
+
+cbuf13(f, n)
+
+{
+ cbuf(f, n, 13);
+}
+
+cbuf14(f, n)
+
+{
+ cbuf(f, n, 14);
+}
+
+cbuf15(f, n)
+
+{
+ cbuf(f, n, 15);
+}
+
+cbuf16(f, n)
+
+{
+ cbuf(f, n, 16);
+}
+
+cbuf17(f, n)
+
+{
+ cbuf(f, n, 17);
+}
+
+cbuf18(f, n)
+
+{
+ cbuf(f, n, 18);
+}
+
+cbuf19(f, n)
+
+{
+ cbuf(f, n, 19);
+}
+
+cbuf20(f, n)
+
+{
+ cbuf(f, n, 20);
+}
+
+cbuf21(f, n)
+
+{
+ cbuf(f, n, 21);
+}
+
+cbuf22(f, n)
+
+{
+ cbuf(f, n, 22);
+}
+
+cbuf23(f, n)
+
+{
+ cbuf(f, n, 23);
+}
+
+cbuf24(f, n)
+
+{
+ cbuf(f, n, 24);
+}
+
+cbuf25(f, n)
+
+{
+ cbuf(f, n, 25);
+}
+
+cbuf26(f, n)
+
+{
+ cbuf(f, n, 26);
+}
+
+cbuf27(f, n)
+
+{
+ cbuf(f, n, 27);
+}
+
+cbuf28(f, n)
+
+{
+ cbuf(f, n, 28);
+}
+
+cbuf29(f, n)
+
+{
+ cbuf(f, n, 29);
+}
+
+cbuf30(f, n)
+
+{
+ cbuf(f, n, 30);
+}
+
+cbuf31(f, n)
+
+{
+ cbuf(f, n, 31);
+}
+
+cbuf32(f, n)
+
+{
+ cbuf(f, n, 32);
+}
+
+cbuf33(f, n)
+
+{
+ cbuf(f, n, 33);
+}
+
+cbuf34(f, n)
+
+{
+ cbuf(f, n, 34);
+}
+
+cbuf35(f, n)
+
+{
+ cbuf(f, n, 35);
+}
+
+cbuf36(f, n)
+
+{
+ cbuf(f, n, 36);
+}
+
+cbuf37(f, n)
+
+{
+ cbuf(f, n, 37);
+}
+
+cbuf38(f, n)
+
+{
+ cbuf(f, n, 38);
+}
+
+cbuf39(f, n)
+
+{
+ cbuf(f, n, 39);
+}
+
+cbuf40(f, n)
+
+{
+ cbuf(f, n, 40);
+}
+
+
Added: clients/emacs/file.c
===================================================================
--- clients/emacs/file.c (rev 0)
+++ clients/emacs/file.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,503 @@
+/*
+ * The routines in this file
+ * handle the reading and writing of
+ * disk files. All of details about the
+ * reading and writing of the disk are
+ * in "fileio.c".
+ */
+#include "estruct.h"
+#include "edef.h"
+
+/*
+ * Read a file into the current
+ * buffer. This is really easy; all you do it
+ * find the name of the file, and call the standard
+ * "read a file into the current buffer" code.
+ * Bound to "C-X C-R".
+ */
+fileread(f, n)
+{
+ register int s;
+ char fname[NFILEN];
+
+ if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
+ return(s);
+ return(readin(fname, TRUE));
+}
+
+/*
+ * Insert a file into the current
+ * buffer. This is really easy; all you do it
+ * find the name of the file, and call the standard
+ * "insert a file into the current buffer" code.
+ * Bound to "C-X C-I".
+ */
+insfile(f, n)
+{
+ register int s;
+ char fname[NFILEN];
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE)
+ return(s);
+ return(ifile(fname));
+}
+
+/*
+ * Select a file for editing.
+ * Look around to see if you can find the
+ * fine in another buffer; if you can find it
+ * just switch to the buffer. If you cannot find
+ * the file, create a new buffer, read in the
+ * text, and switch to the new buffer.
+ * Bound to C-X C-F.
+ */
+filefind(f, n)
+{
+ char fname[NFILEN]; /* file user wishes to find */
+ register int s; /* status return */
+
+ if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
+ return(s);
+ return(getfile(fname, TRUE));
+}
+
+viewfile(f, n) /* visit a file in VIEW mode */
+{
+ char fname[NFILEN]; /* file user wishes to find */
+ register int s; /* status return */
+ register WINDOW *wp; /* scan for windows that need updating */
+
+ if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
+ return (s);
+ s = getfile(fname, FALSE);
+ if (s) { /* if we succeed, put it in view mode */
+ curwp->w_bufp->b_mode |= MDVIEW;
+
+ /* scan through and update mode lines of all windows */
+ wp = wheadp;
+ while (wp != NULL) {
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ }
+ return(s);
+}
+
+getfile(fname, lockfl)
+
+char fname[]; /* file name to find */
+int lockfl; /* check the file for locks? */
+
+{
+ register BUFFER *bp;
+ register LINE *lp;
+ register int i;
+ register int s;
+ char bname[NBUFN]; /* buffer name to put file */
+
+ for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
+ if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) {
+ swbuffer(bp);
+ lp = curwp->w_dotp;
+ i = curwp->w_ntrows/2;
+ while (i-- && lback(lp)!=curbp->b_linep)
+ lp = lback(lp);
+ curwp->w_linep = lp;
+ curwp->w_flag |= WFMODE|WFHARD;
+ mlwrite("[Old buffer]");
+ return (TRUE);
+ }
+ }
+ makename(bname, fname); /* New buffer name. */
+ while ((bp=bfind(bname, FALSE, 0)) != NULL) {
+ s = mlreply("Buffer name: ", bname, NBUFN);
+ if (s == ABORT) /* ^G to just quit */
+ return (s);
+ if (s == FALSE) { /* CR to clobber it */
+ makename(bname, fname);
+ break;
+ }
+ }
+ if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
+ mlwrite("Cannot create buffer");
+ return (FALSE);
+ }
+ if (--curbp->b_nwnd == 0) { /* Undisplay. */
+ curbp->b_dotp = curwp->w_dotp;
+ curbp->b_doto = curwp->w_doto;
+ curbp->b_markp = curwp->w_markp;
+ curbp->b_marko = curwp->w_marko;
+ }
+ curbp = bp; /* Switch to it. */
+ curwp->w_bufp = bp;
+ curbp->b_nwnd++;
+ return(readin(fname, lockfl)); /* Read it in. */
+}
+
+/*
+ * Read file "fname" into the current
+ * buffer, blowing away any text found there. Called
+ * by both the read and find commands. Return the final
+ * status of the read. Also called by the mainline,
+ * to read in a file specified on the command line as
+ * an argument. If the filename ends in a ".c", CMODE is
+ * set for the current buffer.
+ */
+readin(fname, lockfl)
+
+char fname[]; /* name of file to read */
+int lockfl; /* check for file locks? */
+
+{
+ register LINE *lp1;
+ register LINE *lp2;
+ register int i;
+ register WINDOW *wp;
+ register BUFFER *bp;
+ register int s;
+ register int nbytes;
+ register int nline;
+ register char *sptr; /* pointer into filename string */
+ int lflag; /* any lines longer than allowed? */
+ char line[NLINE];
+
+#if FILOCK
+ if (lockfl && lockchk(fname) == ABORT)
+ return(ABORT);
+#endif
+ bp = curbp; /* Cheap. */
+ if ((s=bclear(bp)) != TRUE) /* Might be old. */
+ return (s);
+ bp->b_flag &= ~(BFINVS|BFCHG);
+#if ACMODE
+ if (strlen(fname) > 1) { /* check if a 'C' file */
+ sptr = fname + strlen(fname) - 2;
+ if (*sptr == '.' &&
+ (*(sptr + 1) == 'c' || *(sptr + 1) == 'h'))
+ bp->b_mode |= MDCMOD;
+ }
+#endif
+ strcpy(bp->b_fname, fname);
+ if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
+ goto out;
+ if (s == FIOFNF) { /* File not found. */
+ mlwrite("[New file]");
+ goto out;
+ }
+ mlwrite("[Reading file]");
+ nline = 0;
+ lflag = FALSE;
+ while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
+ if (s == FIOLNG)
+ lflag = TRUE;
+ nbytes = strlen(line);
+ if ((lp1=lalloc(nbytes)) == NULL) {
+ s = FIOERR; /* Keep message on the */
+ break; /* display. */
+ }
+ lp2 = lback(curbp->b_linep);
+ lp2->l_fp = lp1;
+ lp1->l_fp = curbp->b_linep;
+ lp1->l_bp = lp2;
+ curbp->b_linep->l_bp = lp1;
+ for (i=0; i<nbytes; ++i)
+ lputc(lp1, i, line[i]);
+ ++nline;
+ }
+ ffclose(); /* Ignore errors. */
+ if (s == FIOEOF) { /* Don't zap message! */
+ if (nline == 1)
+ mlwrite("[Read 1 line]");
+ else
+ mlwrite("[Read %d lines]", nline);
+ }
+ if (lflag)
+ mlwrite("[Read %d line(s), Long lines wrapped]",nline);
+out:
+ for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
+ if (wp->w_bufp == curbp) {
+ wp->w_linep = lforw(curbp->b_linep);
+ wp->w_dotp = lforw(curbp->b_linep);
+ wp->w_doto = 0;
+ wp->w_markp = NULL;
+ wp->w_marko = 0;
+ wp->w_flag |= WFMODE|WFHARD;
+ }
+ }
+ if (s == FIOERR || s == FIOFNF) /* False if error. */
+ return(FALSE);
+ return (TRUE);
+}
+
+/*
+ * Take a file name, and from it
+ * fabricate a buffer name. This routine knows
+ * about the syntax of file names on the target system.
+ * I suppose that this information could be put in
+ * a better place than a line of code.
+ */
+makename(bname, fname)
+char bname[];
+char fname[];
+{
+ register char *cp1;
+ register char *cp2;
+
+ cp1 = &fname[0];
+ while (*cp1 != 0)
+ ++cp1;
+
+#if AMIGA
+ while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
+ --cp1;
+#endif
+#if VMS
+ while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
+ --cp1;
+#endif
+#if CPM
+ while (cp1!=&fname[0] && cp1[-1]!=':')
+ --cp1;
+#endif
+#if MSDOS
+ while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
+ --cp1;
+#endif
+#if V7 | USG | BSD
+ while (cp1!=&fname[0] && cp1[-1]!='/')
+ --cp1;
+#endif
+#if OFW
+ while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\' && cp1[-1]!='/'
+ && cp1[-1]!=',')
+ --cp1;
+#endif
+ cp2 = &bname[0];
+ while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
+ *cp2++ = *cp1++;
+ *cp2 = 0;
+}
+
+/*
+ * Ask for a file name, and write the
+ * contents of the current buffer to that file.
+ * Update the remembered file name and clear the
+ * buffer changed flag. This handling of file names
+ * is different from the earlier versions, and
+ * is more compatable with Gosling EMACS than
+ * with ITS EMACS. Bound to "C-X C-W".
+ */
+filewrite(f, n)
+{
+ register WINDOW *wp;
+ register int s;
+ char fname[NFILEN];
+
+ if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
+ return (s);
+ if ((s=writeout(fname)) == TRUE) {
+ strcpy(curbp->b_fname, fname);
+ curbp->b_flag &= ~BFCHG;
+ wp = wheadp; /* Update mode lines. */
+ while (wp != NULL) {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ }
+ return (s);
+}
+
+/*
+ * Save the contents of the current
+ * buffer in its associatd file. No nothing
+ * if nothing has changed (this may be a bug, not a
+ * feature). Error if there is no remembered file
+ * name for the buffer. Bound to "C-X C-S". May
+ * get called by "C-Z".
+ */
+filesave(f, n)
+{
+ register WINDOW *wp;
+ register int s;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */
+ return (TRUE);
+ if (curbp->b_fname[0] == 0) { /* Must have a name. */
+ mlwrite("No file name");
+ return (FALSE);
+ }
+ if ((s=writeout(curbp->b_fname)) == TRUE) {
+ curbp->b_flag &= ~BFCHG;
+ wp = wheadp; /* Update mode lines. */
+ while (wp != NULL) {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ }
+ return (s);
+}
+
+/*
+ * This function performs the details of file
+ * writing. Uses the file management routines in the
+ * "fileio.c" package. The number of lines written is
+ * displayed. Sadly, it looks inside a LINE; provide
+ * a macro for this. Most of the grief is error
+ * checking of some sort.
+ */
+writeout(fn)
+char *fn;
+{
+ register int s;
+ register LINE *lp;
+ register int nline;
+
+ if ((s=ffwopen(fn)) != FIOSUC) /* Open writes message. */
+ return (FALSE);
+ mlwrite("[Writing..]"); /* tell us were writing */
+ lp = lforw(curbp->b_linep); /* First line. */
+ nline = 0; /* Number of lines. */
+ while (lp != curbp->b_linep) {
+ if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
+ break;
+ ++nline;
+ lp = lforw(lp);
+ }
+ if (s == FIOSUC) { /* No write error. */
+ s = ffclose();
+ if (s == FIOSUC) { /* No close error. */
+ if (nline == 1)
+ mlwrite("[Wrote 1 line]");
+ else
+ mlwrite("[Wrote %d lines]", nline);
+ }
+ } else /* Ignore close error */
+ ffclose(); /* if a write error. */
+ if (s != FIOSUC) /* Some sort of error. */
+ return (FALSE);
+ return (TRUE);
+}
+
+/*
+ * The command allows the user
+ * to modify the file name associated with
+ * the current buffer. It is like the "f" command
+ * in UNIX "ed". The operation is simple; just zap
+ * the name in the BUFFER structure, and mark the windows
+ * as needing an update. You can type a blank line at the
+ * prompt if you wish.
+ */
+filename(f, n)
+{
+ register WINDOW *wp;
+ register int s;
+ char fname[NFILEN];
+
+ if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
+ return (s);
+ if (s == FALSE)
+ strcpy(curbp->b_fname, "");
+ else
+ strcpy(curbp->b_fname, fname);
+ wp = wheadp; /* Update mode lines. */
+ while (wp != NULL) {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ curbp->b_mode &= ~MDVIEW; /* no longer read only mode */
+ return (TRUE);
+}
+
+/*
+ * Insert file "fname" into the current
+ * buffer, Called by insert file command. Return the final
+ * status of the read.
+ */
+ifile(fname)
+char fname[];
+{
+ register LINE *lp0;
+ register LINE *lp1;
+ register LINE *lp2;
+ register int i;
+ register BUFFER *bp;
+ register int s;
+ register int nbytes;
+ register int nline;
+ int lflag; /* any lines longer than allowed? */
+ char line[NLINE];
+
+ bp = curbp; /* Cheap. */
+ bp->b_flag |= BFCHG; /* we have changed */
+ bp->b_flag &= ~BFINVS; /* and are not temporary*/
+ if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
+ goto out;
+ if (s == FIOFNF) { /* File not found. */
+ mlwrite("[No such file]");
+ return(FALSE);
+ }
+ mlwrite("[Inserting file]");
+
+ /* back up a line and save the mark here */
+ curwp->w_dotp = lback(curwp->w_dotp);
+ curwp->w_doto = 0;
+ curwp->w_markp = curwp->w_dotp;
+ curwp->w_marko = 0;
+
+ nline = 0;
+ lflag = FALSE;
+ while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
+ if (s == FIOLNG)
+ lflag = TRUE;
+ nbytes = strlen(line);
+ if ((lp1=lalloc(nbytes)) == NULL) {
+ s = FIOERR; /* Keep message on the */
+ break; /* display. */
+ }
+ lp0 = curwp->w_dotp; /* line previous to insert */
+ lp2 = lp0->l_fp; /* line after insert */
+
+ /* re-link new line between lp0 and lp2 */
+ lp2->l_bp = lp1;
+ lp0->l_fp = lp1;
+ lp1->l_bp = lp0;
+ lp1->l_fp = lp2;
+
+ /* and advance and write out the current line */
+ curwp->w_dotp = lp1;
+ for (i=0; i<nbytes; ++i)
+ lputc(lp1, i, line[i]);
+ ++nline;
+ }
+ ffclose(); /* Ignore errors. */
+ curwp->w_markp = lforw(curwp->w_markp);
+ if (s == FIOEOF) { /* Don't zap message! */
+ if (nline == 1)
+ mlwrite("[Inserted 1 line]");
+ else
+ mlwrite("[Inserted %d lines]", nline);
+ }
+ if (lflag)
+ mlwrite("[Inserted %d line(s), Long lines wrapped]",nline);
+out:
+ /* advance to the next line and mark the window for changes */
+ curwp->w_dotp = lforw(curwp->w_dotp);
+ curwp->w_flag |= WFHARD | WFMODE;
+
+ /* copy window parameters back to the buffer structure */
+ curbp->b_dotp = curwp->w_dotp;
+ curbp->b_doto = curwp->w_doto;
+ curbp->b_markp = curwp->w_markp;
+ curbp->b_marko = curwp->w_marko;
+
+ if (s == FIOERR) /* False if error. */
+ return (FALSE);
+ return (TRUE);
+}
Added: clients/emacs/fileio.c
===================================================================
--- clients/emacs/fileio.c (rev 0)
+++ clients/emacs/fileio.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,127 @@
+/*
+ * The routines in this file read and write ASCII files from the disk. All of
+ * the knowledge about files are here. A better message writing scheme should
+ * be used.
+ */
+#include "stdio.h"
+#include "estruct.h"
+#include "edef.h"
+
+FILE *ffp; /* File pointer, all functions. */
+
+/*
+ * Open a file for reading.
+ */
+ffropen(fn)
+char *fn;
+{
+ if ((ffp=fopen(fn, "r")) == NULL)
+ return (FIOFNF);
+ return (FIOSUC);
+}
+
+/*
+ * Open a file for writing. Return TRUE if all is well, and FALSE on error
+ * (cannot create).
+ */
+ffwopen(fn)
+char *fn;
+{
+#if VMS
+ register int fd;
+
+ if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
+ || (ffp=fdopen(fd, "w")) == NULL) {
+#else
+ if ((ffp=fopen(fn, "w")) == NULL) {
+#endif
+ mlwrite("Cannot open file for writing");
+ return (FIOERR);
+ }
+ return (FIOSUC);
+}
+
+/*
+ * Close a file. Should look at the status in all systems.
+ */
+ffclose()
+{
+#if MSDOS
+ fputc(26, ffp); /* add a ^Z at the end of the file */
+#endif
+
+#if V7 | USG | BSD | (MSDOS & (LATTICE | MSC))
+ if (fclose(ffp) != FALSE) {
+ mlwrite("Error closing file");
+ return(FIOERR);
+ }
+ return(FIOSUC);
+#else
+ fclose(ffp);
+ return (FIOSUC);
+#endif
+}
+
+/*
+ * Write a line to the already opened file. The "buf" points to the buffer,
+ * and the "nbuf" is its length, less the free newline. Return the status.
+ * Check only at the newline.
+ */
+ffputline(buf, nbuf)
+char buf[];
+{
+ register int i;
+
+ for (i = 0; i < nbuf; ++i)
+ fputc(buf[i]&0xFF, ffp);
+
+ fputc('\n', ffp);
+
+ if (ferror(ffp)) {
+ mlwrite("Write I/O error");
+ return (FIOERR);
+ }
+
+ return (FIOSUC);
+}
+
+/*
+ * Read a line from a file, and store the bytes in the supplied buffer. The
+ * "nbuf" is the length of the buffer. Complain about long lines and lines
+ * at the end of the file that don't have a newline present. Check for I/O
+ * errors too. Return status.
+ */
+ffgetline(buf, nbuf)
+register char buf[];
+{
+ register int c;
+ register int i;
+
+ i = 0;
+
+ while ((c = fgetc(ffp)) != EOF && c != '\n') {
+ if (i >= nbuf-2) {
+ buf[nbuf - 2] = c; /* store last char read */
+ buf[nbuf - 1] = 0; /* and terminate it */
+ mlwrite("File has long line");
+ return (FIOLNG);
+ }
+ buf[i++] = c;
+ }
+
+ if (c == EOF) {
+ if (ferror(ffp)) {
+ mlwrite("File read error");
+ return (FIOERR);
+ }
+
+ if (i != 0) {
+ mlwrite("File has funny line at EOF");
+ return (FIOERR);
+ }
+ return (FIOEOF);
+ }
+
+ buf[i] = 0;
+ return (FIOSUC);
+}
Added: clients/emacs/hp150.c
===================================================================
--- clients/emacs/hp150.c (rev 0)
+++ clients/emacs/hp150.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,361 @@
+/*
+ * The routines in this file provide support for HP150 screens
+ * and routines to access the Keyboard through KEYCODE mode.
+ * It compiles into nothing if not an HP150 screen device.
+ * added by Daniel Lawrence
+ */
+
+#define termdef 1 /* don't define "term" external */
+
+#include "estruct.h"
+#include "edef.h"
+
+#if HP150
+
+#define NROW 24 /* Screen size. */
+#define NCOL 80 /* Edit if you want to. */
+#define MARGIN 8 /* size of minimim margin and */
+#define SCRSIZ 64 /* scroll size for extended lines */
+#define NPAUSE 15 /* # times thru update to pause */
+#define BEL 0x07 /* BEL character. */
+#define ESC 0x1B /* ESC character. */
+
+extern int openhp(); /* Forward references. */
+extern int ttgetc();
+extern int ttputc();
+extern int ttflush();
+extern int hpflush();
+extern int closehp();
+extern int hp15move();
+extern int hp15eeol();
+extern int hp15eeop();
+extern int hp15beep();
+extern int gethpkey();
+extern int hp15rev();
+#if COLOR
+extern int hp15fcol();
+extern int hp15bcol();
+#endif
+
+/* weird to ascii translation table */
+
+char trans[][2] = {
+ 0x24, 9, /* tab */
+ 0x25, 13, /* ret */
+ 0x27, 8, /* backspace */
+ 0x30, 48, /* zero */
+ 0x31, 49, /* one */
+ 0x32, 50, /* two */
+ 0x33, 51, /* three */
+ 0x34, 52, /* four */
+ 0x35, 53, /* five */
+ 0x36, 54, /* six */
+ 0x37, 55, /* seven */
+ 0x38, 56, /* eight */
+ 0x39, 57, /* nine */
+ 0x50, 13, /* enter */
+ 0x54, 27, /* break -> ESC */
+ 0x55, 27, /* esc */
+ 0x58, 24, /* stop -> ^X */
+ 0x70, 45, /* N-minus */
+ 0x71, 42, /* N-asterisk */
+ 0x72, 43, /* N-plus */
+ 0x73, 47, /* N-slash */
+ 0x74, 44, /* N-comma */
+ 0x75, 13, /* N-enter */
+ 0x76, 9, /* N-tab */
+ 0x77, 46 /* N-period */
+};
+
+#define NTRANS sizeof(trans) / 2
+
+union REGS r; /* register set for bios and dos (AGIOS) calls */
+int capslock = 0; /* caps lock flag */
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM term = {
+ NROW-1,
+ NCOL,
+ MARGIN,
+ SCRSIZ,
+ NPAUSE,
+ openhp,
+ closehp,
+ gethpkey,
+ ttputc,
+ hpflush,
+ hp15move,
+ hp15eeol,
+ hp15eeop,
+ hp15beep,
+ hp15rev
+#if COLOR
+ , hp15fcol,
+ hp15bcol
+#endif
+};
+
+hp15move(row, col)
+{
+ ttputc(ESC);
+ ttputc('&');
+ ttputc('a');
+ hp15parm(col);
+ ttputc('c');
+ hp15parm(row);
+ ttputc('R');
+}
+
+hpflush()
+
+{
+
+}
+
+hp15eeol()
+{
+ ttputc(ESC);
+ ttputc('K');
+}
+
+hp15eeop()
+{
+ ttputc(ESC);
+ ttputc('J');
+}
+
+hp15rev(status) /* change the reverse video status */
+
+int status; /* TRUE = on, FALSE = off */
+
+{
+ ttputc(ESC);
+ ttputc('&');
+ ttputc('d');
+ ttputc(status ? 'B': '@');
+}
+
+hp15beep()
+{
+ ttputc(BEL);
+ ttflush();
+}
+
+hp15parm(n)
+register int n;
+{
+ register int q;
+
+ q = n/10;
+ if (q != 0)
+ hp15parm(q);
+ ttputc((n%10) + '0');
+}
+
+#if COLOR
+hp15fcol() /* we really can't do colors here, so just ignore it */
+{
+}
+
+hp15bcol() /* we really can't do colors here, so just ignore it */
+{
+}
+#endif
+
+gethpkey() /* get a key from the HP keyboard while in keycode mode */
+
+{
+ static int keepflag = 0; /* kept ahead char flag */
+ static int keepchar = 0; /* kept ehead flag */
+ int c;
+ int devid; /* device ID */
+ int ctype; /* type of character gotten */
+ int shiftb; /* state of shift keys */
+ int i;
+
+ /* if we are in an extended char sequence, finish it */
+ if (keepflag != 0) {
+ keepflag = 0;
+ return(keepchar);
+ }
+
+ /* grab the next 4 char sequence */
+next: shiftb = ttgetc();
+ devid = ttgetc();
+ c = ttgetc();
+ ttgetc(); /* skip null byte */
+
+ /* make sure we are from the keyboard */
+ if (devid != 192)
+ goto next;
+
+ /* if normal ascii, return it */
+ if ((shiftb & 0x80) == 0) {
+ if (capslock && c >= 'a' && c <= 'z')
+ c -= 32;
+ return(c);
+ }
+
+ /* check specifically for the caps lock key */
+ if (c == 0x56) {
+ capslock = ~capslock;
+ goto next;
+ }
+
+ /* check to see if it needs translation */
+ for (i=0; i < NTRANS; i++)
+ if (trans[i][0] == c)
+ return((int)trans[i][1]);
+
+ /* other wise, shove it in the keep char and return the leadin code */
+ keepchar = c;
+ keepflag = 1;
+ return(0);
+}
+
+openhp() /* open the HP150 keyboard for input */
+
+{
+ revexist = TRUE;
+
+ /* define key charectoristics with AGIOS call (0, 40) */
+ defkey();
+
+ /* Turn on RAW mode with MSDOS call 44h */
+ rawon();
+
+ /* Turn off Control-C checking MS-DOS 33h */
+ ckeyoff();
+
+ /* Turn on keycode mode with AGIOS call (0,43) */
+ keycon();
+}
+
+closehp() /* close the HP150 keyboard for input */
+
+{
+ /* define key charectoristics with AGIOS call (0, 40) */
+ undefkey();
+
+ /* Turn off RAW mode with MSDOS call 44h */
+ rawoff();
+
+ /* Turn on Control-C checking MS-DOS 33h */
+ ckeyon();
+
+ /* Turn off keycode mode with AGIOS call (0,43) */
+ keycoff();
+}
+
+rawon() /* put the HP150 keyboard into RAW mode */
+
+{
+ /* get the IO control info */
+
+ r.x.ax = 0x4400; /* IO ctrl get device information */
+ r.x.bx = 0x0001; /* File handle; 1 for console */
+ intdos(&r, &r); /* go fer it */
+
+ r.h.dh = 0; /* clear high byte for put */
+ r.h.dl |= 0x20; /* set raw bit */
+
+ /* and put it back */
+
+ r.x.ax = 0x4401; /* IO ctrl put device information */
+ r.x.bx = 0x0001; /* File handle; 1 for console */
+ intdos(&r, &r); /* go fer it */
+}
+
+rawoff() /* put the HP150 keyboard into COOKED mode */
+
+{
+ /* get the IO control info */
+
+ r.x.ax = 0x4400; /* IO ctrl get device information */
+ r.x.bx = 0x0001; /* File handle; 1 for console */
+ intdos(&r, &r); /* go fer it */
+
+ r.h.dh = 0; /* clear high byte for put */
+ r.h.dl &= 0xdf; /* set raw bit */
+
+ /* and put it back */
+
+ r.x.ax = 0x4401; /* IO ctrl put device information */
+ r.x.bx = 0x0001; /* File handle; 1 for console */
+ intdos(&r, &r); /* go fer it */
+}
+
+
+ckeyoff() /* turn control-C trapping off */
+
+{
+ r.h.ah = 0x33; /* ctrl-break check */
+ r.h.al = 1; /* set the state of the ctrl-break check */
+ r.h.dl = 0; /* turn it off */
+ intdos(&r, &r);
+}
+
+ckeyon() /* turn control-C trapping on */
+
+{
+ r.h.ah = 0x33; /* ctrl-break check */
+ r.h.al = 1; /* set the state of the ctrl-break check */
+ r.h.dl = 1; /* turn it on */
+ intdos(&r, &r);
+}
+
+agios(buf, len) /* perform an AGIOS call */
+
+char *buf; /* sequence of bytes in command */
+int len; /* length of command in bytes */
+
+{
+ r.x.ax = 0x4403; /* I/O ctrl write */
+ r.x.bx = 1; /* console handle */
+ r.x.cx = len; /* buffer length */
+ r.x.dx = (unsigned)buf; /* buffer address */
+ return(intdos(&r, &r)); /* do it */
+}
+
+keycon() /* turn keycode mode on */
+
+{
+ static char cmd[] = {43, 0, 1};
+
+ return(agios(&cmd[0], 3));
+}
+
+keycoff() /* turn keycode mode off */
+
+{
+ static char cmd[] = {43, 0, 0};
+
+ return(agios(&cmd[0], 3));
+}
+
+defkey() /* change all special keys to intercept mode */
+
+{
+ static char cmd[] = {40, 0, 2, 0, 0xfe, 0};
+
+ return(agios(&cmd[0], 6));
+}
+
+undefkey() /* change all special keys to intercept mode */
+
+{
+ static char cmd[] = {40, 0, 0, 0, 0xfe, 0};
+
+ return(agios(&cmd[0], 6));
+}
+
+#else
+
+h15hello()
+
+{
+}
+#endif
Added: clients/emacs/ibmpc.c
===================================================================
--- clients/emacs/ibmpc.c (rev 0)
+++ clients/emacs/ibmpc.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,299 @@
+/*
+ * The routines in this file provide support for the IBM-PC and other
+ * compatible terminals. It goes directly to the graphics RAM to do
+ * screen output. It compiles into nothing if not an IBM-PC driver
+ */
+
+#define termdef 1 /* don't define "term" external */
+
+#include "estruct.h"
+#include "edef.h"
+#ifdef __ZTC__
+#include <dos.h>
+#endif
+
+#ifdef DOS386
+#define WORD short
+#define SCREEN _far
+#include <dos.h>
+#else
+#define WORD int
+#define SCREEN
+#define far_out movmem
+#endif
+
+#if IBMPC
+
+#define NROW 25 /* Screen size. */
+#define NCOL 80 /* Edit if you want to. */
+#define MARGIN 8 /* size of minimim margin and */
+#define SCRSIZ 64 /* scroll size for extended lines */
+#define NPAUSE 200 /* # times thru update to pause */
+#define BEL 0x07 /* BEL character. */
+#define ESC 0x1B /* ESC character. */
+#define SPACE 32 /* space character */
+#define SCADD 0xb8000000L /* address of screen RAM */
+
+WORD SCREEN *scptr[NROW]; /* pointer to screen lines */
+WORD sline[NCOL]; /* screen line image */
+
+extern int ttopen(); /* Forward references. */
+extern int ttgetc();
+extern int ttputc();
+extern int ttflush();
+extern int ttclose();
+extern int ibmmove();
+extern int ibmeeol();
+extern int ibmeeop();
+extern int ibmbeep();
+extern int ibmopen();
+extern int ibmrev();
+extern int ibmclose();
+extern int ibmputc();
+
+#if COLOR
+extern int ibmfcol();
+extern int ibmbcol();
+
+int cfcolor = -1; /* current forground color */
+int cbcolor = -1; /* current background color */
+int ctrans[] = /* ansi to ibm color translation table */
+ {0, 4, 2, 6, 1, 5, 3, 7};
+#endif
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM term = {
+ NROW-1,
+ NCOL,
+ MARGIN,
+ SCRSIZ,
+ NPAUSE,
+ ibmopen,
+ ibmclose,
+ ttgetc,
+ ibmputc,
+ ttflush,
+ ibmmove,
+ ibmeeol,
+ ibmeeop,
+ ibmbeep,
+ ibmrev
+#if COLOR
+ , ibmfcol,
+ ibmbcol
+#endif
+};
+
+extern union REGS rg;
+
+#if COLOR
+ibmfcol(color) /* set the current output color */
+
+int color; /* color to set */
+
+{
+ cfcolor = ctrans[color];
+}
+
+ibmbcol(color) /* set the current background color */
+
+int color; /* color to set */
+
+{
+ cbcolor = ctrans[color];
+}
+#endif
+
+ibmmove(row, col)
+{
+ rg.h.ah = 2; /* set cursor position function code */
+ rg.h.dl = col;
+ rg.h.dh = row;
+ rg.h.bh = 0; /* set screen page number */
+ int86(0x10, &rg, &rg);
+}
+
+ibmeeol() /* erase to the end of the line */
+
+{
+ int attr; /* attribute byte mask to place in RAM */
+ WORD *lnptr; /* pointer to the destination line */
+ int i;
+ int ccol; /* current column cursor lives */
+ int crow; /* row */
+
+ /* find the current cursor position */
+ rg.h.ah = 3; /* read cursor position function code */
+ rg.h.bh = 0; /* current video page */
+ int86(0x10, &rg, &rg);
+ ccol = rg.h.dl; /* record current column */
+ crow = rg.h.dh; /* and row */
+
+ /* build the attribute byte and setup the screen pointer */
+#if COLOR
+ attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
+#else
+ attr = 0x0700;
+#endif
+ lnptr = &sline[0];
+ for (i=0; i < NCOL; i++)
+ *lnptr++ = SPACE | attr;
+
+ /* wait for vertical retrace to be off */
+ while ((inp(0x3da) & 8))
+ ;
+
+ /* and to be back on */
+ while ((inp(0x3da) & 8) == 0)
+ ;
+
+ /* and send the string out */
+ far_out(&sline[0], scptr[crow]+ccol, (NCOL-ccol)*2);
+
+}
+
+ibmputc(ch) /* put a character at the current position in the
+ current colors */
+
+int ch;
+
+{
+ rg.h.ah = 14; /* write char to screen with current attrs */
+ rg.h.al = ch;
+#if COLOR
+ rg.h.bl = cfcolor;
+#else
+ rg.h.bl = 0x07;
+#endif
+ int86(0x10, &rg, &rg);
+}
+
+ibmeeop()
+{
+ int attr; /* attribute to fill screen with */
+
+ rg.h.ah = 6; /* scroll page up function code */
+ rg.h.al = 0; /* # lines to scroll (clear it) */
+ rg.x.cx = 0; /* upper left corner of scroll */
+ rg.x.dx = 0x174f; /* lower right corner of scroll */
+#if COLOR
+ attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
+#else
+ attr = 0;
+#endif
+ rg.h.bh = attr;
+ int86(0x10, &rg, &rg);
+}
+
+ibmrev(state) /* change reverse video state */
+
+int state; /* TRUE = reverse, FALSE = normal */
+
+{
+ /* This never gets used under the IBM-PC driver */
+}
+
+ibmbeep()
+{
+ bdos(6, BEL, 0);
+}
+
+ibmopen()
+{
+ scinit();
+ revexist = TRUE;
+ ttopen();
+}
+
+ibmclose()
+
+{
+#if COLOR
+ ibmfcol(7);
+ ibmbcol(0);
+#endif
+ ttclose();
+}
+
+scinit() /* initialize the screen head pointers */
+
+{
+ union {
+ long laddr; /* long form of address */
+ int *paddr; /* pointer form of address */
+ } addr;
+ int i;
+
+#ifdef DOS386
+ scptr[0] = (short _far *)_x386_mk_protected_ptr(SCADD >> 12);
+
+ /* Coerce the selector to the current privilege level */
+ scptr[0] = MK_FP(FP_SEG(scptr[0]) | (getDS() & 3), FP_OFF(scptr[0]));
+
+ for (i = 1; i < NROW; i++)
+ scptr[i] = scptr[i-1] + NCOL;
+#else
+ /* initialize the screen pointer array */
+ for (i = 0; i < NROW; i++) {
+ addr.laddr = SCADD + (long)(NCOL * i * 2);
+ scptr[i] = addr.paddr;
+ }
+#endif
+
+}
+
+scwrite(row, outstr, forg, bacg) /* write a line out*/
+
+int row; /* row of screen to place outstr on */
+char *outstr; /* string to write out (must be NCOL long) */
+int forg; /* forground color of string to write */
+int bacg; /* background color */
+
+{
+ int attr; /* attribute byte mask to place in RAM */
+ WORD *lnptr; /* pointer to the destination line */
+ int i;
+
+ /* build the attribute byte and setup the screen pointer */
+#if COLOR
+ attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
+#else
+ attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
+#endif
+ lnptr = &sline[0];
+ for (i=0; i<NCOL; i++)
+ *lnptr++ = (outstr[i] & 255) | attr;
+
+ /* wait for vertical retrace to be off */
+ while ((inp(0x3da) & 8))
+ ;
+
+ /* and to be back on */
+ while ((inp(0x3da) & 8) == 0)
+ ;
+
+ /* and send the string out */
+ far_out(&sline[0], scptr[row],NCOL*2);
+}
+#ifdef DOS386
+far_out(source, dest, size)
+
+char *source; /* mem location to move memory from */
+char _far *dest; /* memory location to move text to */
+int size; /* number of bytes to move */
+
+{
+ register int i;
+
+ for (i=0; i < size; i++)
+ *dest++ = *source++;
+}
+#endif
+#else
+ibmhello()
+{
+}
+#endif
Added: clients/emacs/input.c
===================================================================
--- clients/emacs/input.c (rev 0)
+++ clients/emacs/input.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,507 @@
+/* INPUT: Various input routines for MicroEMACS 3.7
+ written by Daniel Lawrence
+ 5/9/86 */
+
+#include "estruct.h"
+#include "edef.h"
+
+/*
+ * Ask a yes or no question in the message line. Return either TRUE, FALSE, or
+ * ABORT. The ABORT status is returned if the user bumps out of the question
+ * with a ^G. Used any time a confirmation is required.
+ */
+
+mlyesno(prompt)
+
+char *prompt;
+
+{
+ char c; /* input character */
+ char buf[NPAT]; /* prompt to user */
+
+ for (;;) {
+ /* build and prompt the user */
+ strcpy(buf, prompt);
+ strcat(buf, " [y/n]? ");
+ mlwrite(buf);
+
+ /* get the responce */
+ c = (*term.t_getchar)();
+
+ if (c == BELL) /* Bail out! */
+ return(ABORT);
+
+ if (c=='y' || c=='Y')
+ return(TRUE);
+
+ if (c=='n' || c=='N')
+ return(FALSE);
+ }
+}
+
+/*
+ * Write a prompt into the message line, then read back a response. Keep
+ * track of the physical position of the cursor. If we are in a keyboard
+ * macro throw the prompt away, and return the remembered response. This
+ * lets macros run at full speed. The reply is always terminated by a carriage
+ * return. Handle erase, kill, and abort keys.
+ */
+
+mlreply(prompt, buf, nbuf)
+ char *prompt;
+ char *buf;
+{
+ return(mlreplyt(prompt,buf,nbuf,'\n'));
+}
+
+/* A more generalized prompt/reply function allowing the caller
+ to specify the proper terminator. If the terminator is not
+ a return ('\n') it will echo as "<NL>"
+ */
+mlreplyt(prompt, buf, nbuf, eolchar)
+
+char *prompt;
+char *buf;
+char eolchar;
+
+{
+ register int cpos; /* current character position in string */
+ register int i;
+ register int c;
+ register int quotef; /* are we quoting the next char? */
+ register int status; /* status return value */
+
+
+ cpos = 0;
+ quotef = FALSE;
+
+ if (kbdmop != NULL) {
+ while ((c = *kbdmop++) != '\0')
+ buf[cpos++] = c;
+
+ buf[cpos] = 0;
+
+ if (buf[0] == 0)
+ return(FALSE);
+
+ return(TRUE);
+ }
+
+ /* check to see if we are executing a command line */
+ if (clexec) {
+ status = nxtarg(buf);
+ buf[nbuf-1] = 0; /* make sure we null terminate it */
+ return(status);
+ }
+
+ mlwrite(prompt);
+
+ for (;;) {
+ /* get a character from the user. if it is a <ret>, change it
+ to a <NL> */
+ c = (*term.t_getchar)();
+ if (c == 0x0d)
+ c = '\n';
+
+ if (c == eolchar && quotef == FALSE) {
+ buf[cpos++] = 0;
+
+ if (kbdmip != NULL) {
+ if (kbdmip+cpos > &kbdm[NKBDM-3]) {
+ ctrlg(FALSE, 0);
+ (*term.t_flush)();
+ return(ABORT);
+ }
+
+ for (i=0; i<cpos; ++i)
+ *kbdmip++ = buf[i];
+ }
+
+ (*term.t_move)(term.t_nrow, 0);
+ ttcol = 0;
+ (*term.t_flush)();
+
+ if (buf[0] == 0)
+ return(FALSE);
+
+ return(TRUE);
+
+ } else if (c == 0x07 && quotef == FALSE) {
+ /* Bell, abort */
+ (*term.t_putchar)('^');
+ (*term.t_putchar)('G');
+ ttcol += 2;
+ ctrlg(FALSE, 0);
+ (*term.t_flush)();
+ return(ABORT);
+
+ } else if ((c==0x7F || c==0x08) && quotef==FALSE) {
+ /* rubout/erase */
+ if (cpos != 0) {
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)('\b');
+ --ttcol;
+
+ if (buf[--cpos] < 0x20) {
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)('\b');
+ --ttcol;
+ }
+
+ if (buf[cpos] == '\n') {
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)('\b');
+ --ttcol;
+ --ttcol;
+ }
+
+ (*term.t_flush)();
+ }
+
+ } else if (c == 0x15 && quotef == FALSE) {
+ /* C-U, kill */
+ while (cpos != 0) {
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)('\b');
+ --ttcol;
+
+ if (buf[--cpos] < 0x20) {
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)('\b');
+ --ttcol;
+ }
+ }
+
+ (*term.t_flush)();
+
+ } else if (c == quotec && quotef == FALSE) {
+ quotef = TRUE;
+ } else {
+ quotef = FALSE;
+ if (cpos < nbuf-1) {
+ buf[cpos++] = c;
+
+ if ((c < ' ') && (c != '\n')) {
+ (*term.t_putchar)('^');
+ ++ttcol;
+ c ^= 0x40;
+ }
+
+ if (c != '\n')
+ (*term.t_putchar)(c);
+ else { /* put out <NL> for <ret> */
+ (*term.t_putchar)('<');
+ (*term.t_putchar)('N');
+ (*term.t_putchar)('L');
+ (*term.t_putchar)('>');
+ ttcol += 3;
+ }
+ ++ttcol;
+ (*term.t_flush)();
+ }
+ }
+ }
+}
+
+/* get a command name from the command line. Command completion means
+ that pressing a <SPACE> will attempt to complete an unfinished command
+ name if it is unique.
+*/
+
+int (*getname())()
+
+{
+ register int cpos; /* current column on screen output */
+ register int c;
+ register char *sp; /* pointer to string for output */
+ register NBIND *ffp; /* first ptr to entry in name binding table */
+ register NBIND *cffp; /* current ptr to entry in name binding table */
+ register NBIND *lffp; /* last ptr to entry in name binding table */
+ char buf[NSTRING]; /* buffer to hold tentative command name */
+ int (*fncmatch())();
+
+ /* starting at the begining of the string buffer */
+ cpos = 0;
+
+ /* if we are executing a keyboard macro, fill our buffer from there,
+ and attempt a straight match */
+ if (kbdmop != NULL) {
+ while ((c = *kbdmop++) != '\0')
+ buf[cpos++] = c;
+
+ buf[cpos] = 0;
+
+ /* return the result of a match */
+ return(fncmatch(&buf[0]));
+ }
+
+ /* if we are executing a command line get the next arg and match it */
+ if (clexec) {
+ if (nxtarg(buf) != TRUE)
+ return(FALSE);
+ return(fncmatch(&buf[0]));
+ }
+
+ /* build a name string from the keyboard */
+ while (TRUE) {
+ c = (*term.t_getchar)();
+
+ /* if we are at the end, just match it */
+ if (c == 0x0d) {
+ buf[cpos] = 0;
+
+ /* save keyboard macro string if needed */
+ if (kbdtext(&buf[0]) == ABORT)
+ return( (int (*)()) NULL);
+
+ /* and match it off */
+ return(fncmatch(&buf[0]));
+
+ } else if (c == 0x07) { /* Bell, abort */
+ (*term.t_putchar)('^');
+ (*term.t_putchar)('G');
+ ttcol += 2;
+ ctrlg(FALSE, 0);
+ (*term.t_flush)();
+ return( (int (*)()) NULL);
+
+ } else if (c == 0x7F || c == 0x08) { /* rubout/erase */
+ if (cpos != 0) {
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)('\b');
+ --ttcol;
+ --cpos;
+ (*term.t_flush)();
+ }
+
+ } else if (c == 0x15) { /* C-U, kill */
+ while (cpos != 0) {
+ (*term.t_putchar)('\b');
+ (*term.t_putchar)(' ');
+ (*term.t_putchar)('\b');
+ --cpos;
+ --ttcol;
+ }
+
+ (*term.t_flush)();
+
+ } else if (c == ' ') {
+/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
+ /* attempt a completion */
+ buf[cpos] = 0; /* terminate it for us */
+ ffp = &names[0]; /* scan for matches */
+ while (ffp->n_func != NULL) {
+ if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) {
+ /* a possible match! More than one? */
+ if ((ffp + 1)->n_func == NULL ||
+ (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) {
+ /* no...we match, print it */
+ sp = ffp->n_name + cpos;
+ while (*sp)
+ (*term.t_putchar)(*sp++);
+ (*term.t_flush)();
+ return(ffp->n_func);
+ } else {
+/* << << << << << << << << << << << << << << << << << */
+ /* try for a partial match against the list */
+
+ /* first scan down until we no longer match the current input */
+ lffp = (ffp + 1);
+ while ((lffp+1)->n_func != NULL) {
+ if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0)
+ break;
+ ++lffp;
+ }
+
+ /* and now, attempt to partial complete the string, char at a time */
+ while (TRUE) {
+ /* add the next char in */
+ buf[cpos] = ffp->n_name[cpos];
+
+ /* scan through the candidates */
+ cffp = ffp + 1;
+ while (cffp <= lffp) {
+ if (cffp->n_name[cpos] != buf[cpos])
+ goto onward;
+ ++cffp;
+ }
+
+ /* add the character */
+ (*term.t_putchar)(buf[cpos++]);
+ }
+/* << << << << << << << << << << << << << << << << << */
+ }
+ }
+ ++ffp;
+ }
+
+ /* no match.....beep and onward */
+ (*term.t_beep)();
+onward:;
+ (*term.t_flush)();
+/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
+ } else {
+ if (cpos < NSTRING-1 && c > ' ') {
+ buf[cpos++] = c;
+ (*term.t_putchar)(c);
+ }
+
+ ++ttcol;
+ (*term.t_flush)();
+ }
+ }
+}
+
+kbdtext(buf) /* add this text string to the current keyboard macro
+ definition */
+
+char *buf; /* text to add to keyboard macro */
+
+{
+ /* if we are defining a keyboard macro, save it */
+ if (kbdmip != NULL) {
+ if (kbdmip+strlen(buf) > &kbdm[NKBDM-4]) {
+ ctrlg(FALSE, 0);
+ (*term.t_flush)();
+ return(ABORT);
+ }
+
+ /* copy string in and null terminate it */
+ while (*buf)
+ *kbdmip++ = *buf++;
+ *kbdmip++ = 0;
+ }
+ return(TRUE);
+}
+
+/* GET1KEY: Get one keystroke. The only prefixs legal here
+ are the SPEC and CTRL prefixes.
+ */
+
+get1key()
+
+{
+ int c;
+#if AMIGA
+ int d;
+#endif
+
+ /* get a keystroke */
+ c = (*term.t_getchar)();
+#if 0
+ (*term.t_putchar)("0123456789abcdef"[(c>>4)&0xf]);
+ (*term.t_putchar)("0123456789abcdef"[c&0xf]);
+ (*term.t_putchar)('\r');
+ (*term.t_putchar)('\n');
+#endif
+
+#if RAINBOW
+
+ if (c & Function_Key)
+ {
+ int i;
+
+ for (i = 0; i < lk_map_size; i++)
+ if (c == lk_map[i][0])
+ return lk_map[i][1];
+ }
+ else if (c == Shift + 015) return CTRL | 'J';
+ else if (c == Shift + 0x7F) return META | 0x7F;
+#endif
+
+#if MSDOS
+ if (c == 0) { /* Apply SPEC prefix */
+ c = (*term.t_getchar)();
+ if (c>=0x00 && c<=0x1F) /* control key? */
+ c = CTRL | (c+'@');
+ return(SPEC | c);
+ }
+#endif
+
+#if AMIGA
+ /* apply SPEC prefix */
+ if ((unsigned)c == 155) {
+ c = (*term.t_getchar)();
+
+ /* first try to see if it is a cursor key */
+ if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T')
+ return(SPEC | c);
+
+ /* next, a 2 char sequence */
+ d = (*term.t_getchar)();
+ if (d == '~')
+ return(SPEC | c);
+
+ /* decode a 3 char sequence */
+ c = d + 32;
+ /* if a shifted function key, eat the tilde */
+ if (d >= '0' && d <= '9')
+ d = (*term.t_getchar)();
+ return(SPEC | c);
+ }
+#endif
+
+#if WANGPC
+ if (c == 0x1F) { /* Apply SPEC prefix */
+ c = (*term.t_getchar)();
+ return(SPEC | c);
+ }
+#endif
+
+#if OFW
+ if (c == 0x9b) { /* Apply SPEC prefix */
+ c = (*term.t_getchar)();
+ if (c == 'O') /* Function key */
+ c = (*term.t_getchar)();
+ return(SPEC | c);
+ }
+#endif
+
+ if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
+ c = CTRL | (c+'@');
+ return (c);
+}
+
+/* GETCMD: Get a command from the keyboard. Process all applicable
+ prefix keys
+ */
+getcmd()
+
+{
+ int c; /* fetched keystroke */
+
+ /* get initial character */
+ c = get1key();
+
+ /* process META prefix */
+ if (c == metac) {
+ c = get1key();
+ if (c>='a' && c<='z') /* Force to upper */
+ c -= 0x20;
+ if (c>=0x00 && c<=0x1F) /* control key */
+ c = CTRL | (c+'@');
+ return(META | c);
+ }
+
+ /* process CTLX prefix */
+ if (c == ctlxc) {
+ c = get1key();
+ if (c>='a' && c<='z') /* Force to upper */
+ c -= 0x20;
+ if (c>=0x00 && c<=0x1F) /* control key */
+ c = CTRL | (c+'@');
+ return(CTLX | c);
+ }
+
+ /* otherwise, just return it */
+ return(c);
+}
Added: clients/emacs/isearch.c
===================================================================
--- clients/emacs/isearch.c (rev 0)
+++ clients/emacs/isearch.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,543 @@
+/*
+ * The functions in this file implement commands that perform incremental
+ * searches in the forward and backward directions. This "ISearch" command
+ * is intended to emulate the same command from the original EMACS
+ * implementation (ITS). Contains references to routines internal to
+ * SEARCH.C.
+ *
+ * REVISION HISTORY:
+ *
+ * D. R. Banks 9-May-86
+ * - added ITS EMACSlike ISearch
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+/* string search input parameters */
+
+#define PTBEG 1 /* leave the point at the beginning on search */
+#define PTEND 2 /* leave the point at the end on search */
+
+#define CMDBUFLEN 256 /* Length of our command buffer */
+
+extern int forscan(); /* Handy search routine */
+extern int eq(); /* Compare chars, match case */
+
+/* A couple of "own" variables for re-eat */
+
+int (*saved_get_char)(); /* Get character routine */
+int eaten_char = -1; /* Re-eaten char */
+
+/* A couple more "own" variables for the command string */
+
+char cmd_buff[CMDBUFLEN]; /* Save the command args here */
+int cmd_offset; /* Current offset into command buff */
+int cmd_reexecute = -1; /* > 0 if re-executing command */
+
+/* Some character constants within ISearch */
+
+#define IS_ABORT 0x07 /* Abort the isearch */
+#define IS_BACKSP 0x08 /* Delete previous char */
+#define IS_TAB 0x09 /* Tab character (allowed search char) */
+#define IS_NEWLINE 0x0D /* New line from keyboard (Carriage return) */
+#define IS_QUOTE 0x11 /* Quote next character */
+#define IS_REVERSE 0x12 /* Search backward */
+#define IS_FORWARD 0x13 /* Search forward */
+#define IS_VMSQUOTE 0x16 /* VMS quote character */
+#define IS_VMSFORW 0x18 /* Search forward for VMS */
+#define IS_QUIT 0x1B /* Exit the search */
+#define IS_RUBOUT 0x7F /* Delete previous character */
+
+/*
+ * Subroutine to do incremental reverse search. It actually uses the
+ * same code as the normal incremental search, as both can go both ways.
+ */
+
+int risearch(f, n)
+{
+ LINE *curline; /* Current line on entry */
+ int curoff; /* Current offset on entry */
+
+ /* remember the initial . on entry: */
+
+ curline = curwp->w_dotp; /* Save the current line pointer */
+ curoff = curwp->w_doto; /* Save the current offset */
+
+ /* Make sure the search doesn't match where we already are: */
+
+ backchar(TRUE, 1); /* Back up a character */
+
+ if (!(isearch(f, -n))) /* Call ISearch backwards */
+ { /* If error in search: */
+ curwp->w_dotp = curline; /* Reset the line pointer */
+ curwp->w_doto = curoff; /* and the offset to original value */
+ curwp->w_flag |= WFMOVE; /* Say we've moved */
+ update(FALSE); /* And force an update */
+ mlwrite ("[search failed]"); /* Say we died */
+ } else mlerase (); /* If happy, just erase the cmd line */
+}
+
+/* Again, but for the forward direction */
+
+int fisearch(f, n)
+{
+ LINE *curline; /* Current line on entry */
+ int curoff; /* Current offset on entry */
+
+ /* remember the initial . on entry: */
+
+ curline = curwp->w_dotp; /* Save the current line pointer */
+ curoff = curwp->w_doto; /* Save the current offset */
+
+ /* do the search */
+
+ if (!(isearch(f, n))) /* Call ISearch forwards */
+ { /* If error in search: */
+ curwp->w_dotp = curline; /* Reset the line pointer */
+ curwp->w_doto = curoff; /* and the offset to original value */
+ curwp->w_flag |= WFMOVE; /* Say we've moved */
+ update(FALSE); /* And force an update */
+ mlwrite ("[search failed]"); /* Say we died */
+ } else mlerase (); /* If happy, just erase the cmd line */
+}
+
+/*
+ * Subroutine to do an incremental search. In general, this works similarly
+ * to the older micro-emacs search function, except that the search happens
+ * as each character is typed, with the screen and cursor updated with each
+ * new search character.
+ *
+ * While searching forward, each successive character will leave the cursor
+ * at the end of the entire matched string. Typing a Control-S or Control-X
+ * will cause the next occurrence of the string to be searched for (where the
+ * next occurrence does NOT overlap the current occurrence). A Control-R will
+ * change to a backwards search, ESC will terminate the search and Control-G
+ * will abort the search. Rubout will back up to the previous match of the
+ * string, or if the starting point is reached first, it will delete the
+ * last character from the search string.
+ *
+ * While searching backward, each successive character will leave the cursor
+ * at the beginning of the matched string. Typing a Control-R will search
+ * backward for the next occurrence of the string. Control-S or Control-X
+ * will revert the search to the forward direction. In general, the reverse
+ * incremental search is just like the forward incremental search inverted.
+ *
+ * In all cases, if the search fails, the user will be feeped, and the search
+ * will stall until the pattern string is edited back into something that
+ * exists (or until the search is aborted).
+ */
+
+isearch(f, n)
+{
+ int status; /* Search status */
+ int col; /* prompt column */
+ register int cpos; /* character number in search string */
+ register int c; /* current input character */
+ char pat_save[NPAT]; /* Saved copy of the old pattern str */
+ LINE *curline; /* Current line on entry */
+ int curoff; /* Current offset on entry */
+ int init_direction; /* The initial search direction */
+
+ /* Initialize starting conditions */
+
+ cmd_reexecute = -1; /* We're not re-executing (yet?) */
+ cmd_offset = 0; /* Start at the beginning of the buff */
+ cmd_buff[0] = '\0'; /* Init the command buffer */
+ strncpy (pat_save, pat, NPAT); /* Save the old pattern string */
+ curline = curwp->w_dotp; /* Save the current line pointer */
+ curoff = curwp->w_doto; /* Save the current offset */
+ init_direction = n; /* Save the initial search direction */
+
+ /* This is a good place to start a re-execution: */
+
+start_over:
+
+ /* ask the user for the text of a pattern */
+ col = promptpattern("ISearch: "); /* Prompt, remember the col */
+
+ cpos = 0; /* Start afresh */
+ status = TRUE; /* Assume everything's cool */
+
+ /*
+ Get the first character in the pattern. If we get an initial Control-S
+ or Control-R, re-use the old search string and find the first occurrence
+ */
+
+ c = get_char(); /* Get the first character */
+ if ((c == IS_FORWARD) ||
+ (c == IS_REVERSE) ||
+ (c == IS_VMSFORW)) /* Reuse old search string? */
+ {
+ for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */
+ col = echochar(pat[cpos],col); /* and re-echo the string */
+ if (c == IS_REVERSE) { /* forward search? */
+ n = -1; /* No, search in reverse */
+ backchar (TRUE, 1); /* Be defensive about EOB */
+ } else
+ n = 1; /* Yes, search forward */
+ status = scanmore(pat,n,status); /* Do the search */
+ c = get_char (); /* Get another character */
+ }
+
+ /* Top of the per character loop */
+
+ for (;;) /* ISearch per character loop */
+ {
+ /* Check for magic characters first: */
+ /* Most cases here change the search */
+
+ switch (c) /* dispatch on the input char */
+ {
+ case IS_ABORT: /* If abort search request */
+ return(FALSE); /* Quit searching again */
+
+ case IS_REVERSE: /* If backward search */
+ case IS_FORWARD: /* If forward search */
+ case IS_VMSFORW: /* of either flavor */
+ if (c == IS_REVERSE) /* If reverse search */
+ n = -1; /* Set the reverse direction */
+ else /* Otherwise, */
+ n = 1; /* go forward */
+ status = scanmore(pat,n,TRUE); /* Start the search again */
+ c = get_char (); /* Get the next char */
+ continue; /* Go continue with the search*/
+
+ case IS_QUIT: /* Want to quit searching? */
+ return (TRUE); /* Quit searching now */
+
+ case IS_NEWLINE: /* Carriage return */
+ c = '\n'; /* Make it a new line */
+ break; /* Make sure we use it */
+
+ case IS_QUOTE: /* Quote character */
+ case IS_VMSQUOTE: /* of either variety */
+ c = get_char (); /* Get the next char */
+
+ case IS_TAB: /* Generically allowed */
+ case '\n': /* controlled characters */
+ break; /* Make sure we use it */
+
+ case IS_BACKSP: /* If a backspace: */
+ case IS_RUBOUT: /* or if a Rubout: */
+ if (cmd_offset <= 1) /* Anything to delete? */
+ return (TRUE); /* No, just exit */
+ --cmd_offset; /* Back up over the Rubout */
+ cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char */
+ curwp->w_dotp = curline; /* Reset the line pointer */
+ curwp->w_doto = curoff; /* and the offset */
+ n = init_direction; /* Reset the search direction */
+ strncpy (pat, pat_save, NPAT); /* Restore the old search str */
+ cmd_reexecute = 0; /* Start the whole mess over */
+ goto start_over; /* Let it take care of itself */
+
+ /* Presumably a quasi-normal character comes here */
+
+ default: /* All other chars */
+ if (c < ' ') /* Is it printable? */
+ { /* Nope. */
+ reeat (c); /* Re-eat the char */
+ return (TRUE); /* And return the last status */
+ }
+ } /* Switch */
+
+ /* I guess we got something to search for, so search for it */
+
+ pat[cpos++] = c; /* put the char in the buffer */
+ if (cpos >= NPAT) /* too many chars in string? */
+ { /* Yup. Complain about it */
+ mlwrite("? Search string too long");
+ return(TRUE); /* Return an error */
+ }
+ pat[cpos] = 0; /* null terminate the buffer */
+ col = echochar(c,col); /* Echo the character */
+ if (!status) { /* If we lost last time */
+ (*term.t_putchar)(BELL); /* Feep again */
+ (*term.t_flush)(); /* see that the feep feeps */
+ } else /* Otherwise, we must have won*/
+ if (!(status = checknext(c,pat,n,status))) /* See if match */
+ status = scanmore(pat,n,TRUE); /* or find the next match */
+ c = get_char (); /* Get the next char */
+ } /* for {;;} */
+}
+
+/*
+ * Trivial routine to insure that the next character in the search string is
+ * still true to whatever we're pointing to in the buffer. This routine will
+ * not attempt to move the "point" if the match fails, although it will
+ * implicitly move the "point" if we're forward searching, and find a match,
+ * since that's the way forward isearch works.
+ *
+ * If the compare fails, we return FALSE and assume the caller will call
+ * scanmore or something.
+ */
+
+int checknext (chr, patrn, dir, sts)/* Check next character in search string */
+char chr; /* Next char to look for */
+char *patrn; /* The entire search string (incl chr) */
+int dir; /* Search direction */
+int sts; /* Search status */
+{
+ register LINE *curline; /* current line during scan */
+ register int curoff; /* position within current line */
+ register int buffchar; /* character at current position */
+ int status; /* how well things go */
+
+ if (!sts) return(FALSE); /* Don't try unless ok so far */
+
+ /* setup the local scan pointer to current "." */
+
+ curline = curwp->w_dotp; /* Get the current line structure */
+ curoff = curwp->w_doto; /* Get the offset within that line */
+
+ if (dir > 0) /* If searching forward */
+ {
+ if (curoff == llength(curline)) /* If at end of line */
+ {
+ curline = lforw(curline); /* Skip to the next line */
+ if (curline == curbp->b_linep)
+ return (FALSE); /* Abort if at end of buffer */
+ curoff = 0; /* Start at the beginning of the line */
+ buffchar = '\n'; /* And say the next char is NL */
+ } else
+ buffchar = lgetc(curline, curoff++); /* Get the next char */
+ if (status = eq(buffchar, chr)) /* Is it what we're looking for? */
+ {
+ curwp->w_dotp = curline; /* Yes, set the buffer's point */
+ curwp->w_doto = curoff; /* to the matched character */
+ curwp->w_flag |= WFMOVE; /* Say that we've moved */
+ }
+ return (status); /* And return the status */
+ } else /* Else, if reverse search: */
+ return (match_pat (patrn)); /* See if we're in the right place */
+}
+
+/*
+ * This hack will search for the next occurrence of <pat> in the buffer, either
+ * forward or backward. It is called with the status of the prior search
+ * attempt, so that it knows not to bother if it didn't work last time. If
+ * we can't find any more matches, "point" is left where it was before. If
+ * we do find a match, "point" will be at the end of the matched string for
+ * forward searches and at the beginning of the matched string for reverse
+ * searches.
+ */
+
+int scanmore(patrn,dir,sts) /* search forward or back for a pattern */
+char *patrn; /* string to scan for */
+int dir; /* direction to search */
+int sts; /* previous search status */
+{
+ if (sts) /* don't try unless successful last time */
+ {
+ if (dir < 0) /* reverse search? */
+ sts = bakscan(patrn); /* Yes, call our hacky routine*/
+ else
+ sts = forscan(patrn,PTEND); /* Nope. Go forward */
+ }
+ if (!sts) {
+ (*term.t_putchar)(BELL); /* Feep if search fails */
+ (*term.t_flush)(); /* see that the feep feeps */
+ }
+ return(sts); /* else, don't even try */
+}
+
+/*
+ * The following is a minimal implementation of the reverse of "forscan".
+ * We aren't using the routine in SEARCH.C because it likes to type stuff,
+ * but the real solution is probably to fix that instead of duplicate the
+ * code here like we're doing. On the other hand, we don't want to touch
+ * more modules than we have to for this first round ...
+ *
+ * This always leaves "." at the beginning of the matched pattern string
+ */
+
+int bakscan (patrn) /* Scan backwards for a match */
+char *patrn; /* Search string to be matched */
+{
+ LINE *initline; /* initial line pointer before scan */
+ int initoff; /* position within initial line */
+
+ /* Remember "point" on entry: */
+
+ initline = curwp->w_dotp; /* Get the current line structure */
+ initoff = curwp->w_doto; /* Get the offset within that line */
+
+ /*
+ * Loop here, stepping the cursor until we match or until we reach the top
+ * of the buffer
+ */
+
+ while (backchar(TRUE, 1)) /* As long as there're chars */
+ if (match_pat (patrn)) /* See if we match */
+ return (TRUE); /* Yep. Stop'er right here */
+ curwp->w_dotp = initline; /* Top of buffer, just reset */
+ curwp->w_doto = initoff; /* to original "point" */
+ curwp->w_flag |= WFMOVE; /* In case backchar moved us */
+ return (FALSE); /* And return failure */
+}
+
+/*
+ * The following is a worker subroutine used by the reverse search. It
+ * compares the pattern string with the characters at "." for equality. If
+ * any characters mismatch, it will return FALSE.
+ *
+ * This isn't used for forward searches, because forward searches leave "."
+ * at the end of the search string (instead of in front), so all that needs to
+ * be done is match the last char input.
+ */
+
+int match_pat (patrn) /* See if the pattern string matches string at "." */
+char *patrn; /* String to match to buffer */
+{
+ register int i; /* Generic loop index/offset */
+ register int buffchar; /* character at current position */
+ register LINE *curline; /* current line during scan */
+ register int curoff; /* position within current line */
+
+ /* setup the local scan pointer to current "." */
+
+ curline = curwp->w_dotp; /* Get the current line structure */
+ curoff = curwp->w_doto; /* Get the offset within that line */
+
+ /* top of per character compare loop: */
+
+ for (i = 0; i < strlen(patrn); i++) /* Loop for all characters in patrn */
+ {
+ if (curoff == llength(curline)) /* If at end of line */
+ {
+ curline = lforw(curline); /* Skip to the next line */
+ curoff = 0; /* Start at the beginning of the line */
+ if (curline == curbp->b_linep)
+ return (FALSE); /* Abort if at end of buffer */
+ buffchar = '\n'; /* And say the next char is NL */
+ } else
+ buffchar = lgetc(curline, curoff++); /* Get the next char */
+ if (!eq(buffchar, patrn[i])) /* Is it what we're looking for? */
+ return (FALSE); /* Nope, just punt it then */
+ }
+ return (TRUE); /* Everything matched? Let's celebrate*/
+}
+
+/* Routine to prompt for I-Search string. */
+
+int promptpattern(prompt)
+char *prompt;
+{
+ char tpat[NPAT+20];
+
+ strcpy(tpat, prompt); /* copy prompt to output string */
+ strcat(tpat, " ["); /* build new prompt string */
+ expandp(pat, &tpat[strlen(tpat)], NPAT/2); /* add old pattern */
+ strcat(tpat, "]<ESC>: ");
+
+ /* check to see if we are executing a command line */
+ if (!clexec) {
+ mlwrite(tpat);
+ }
+ return(strlen(tpat));
+}
+
+/* routine to echo i-search characters */
+
+int echochar(c,col)
+int c; /* character to be echoed */
+int col; /* column to be echoed in */
+{
+ movecursor(term.t_nrow,col); /* Position the cursor */
+ if ((c < ' ') || (c == 0x7F)) /* Control character? */
+ {
+ switch (c) /* Yes, dispatch special cases*/
+ {
+ case '\n': /* Newline */
+ (*term.t_putchar)('<');
+ (*term.t_putchar)('N');
+ (*term.t_putchar)('L');
+ (*term.t_putchar)('>');
+ col += 3;
+ break;
+
+ case '\t': /* Tab */
+ (*term.t_putchar)('<');
+ (*term.t_putchar)('T');
+ (*term.t_putchar)('A');
+ (*term.t_putchar)('B');
+ (*term.t_putchar)('>');
+ col += 4;
+ break;
+
+ case 0x7F: /* Rubout: */
+ (*term.t_putchar)('^'); /* Output a funny looking */
+ (*term.t_putchar)('?'); /* indication of Rubout */
+ col++; /* Count the extra char */
+ break;
+
+ default: /* Vanilla control char */
+ (*term.t_putchar)('^'); /* Yes, output prefix */
+ (*term.t_putchar)(c+0x40); /* Make it "^X" */
+ col++; /* Count this char */
+ }
+ } else
+ (*term.t_putchar)(c); /* Otherwise, output raw char */
+ (*term.t_flush)(); /* Flush the output */
+ return(++col); /* return the new column no */
+}
+
+/*
+ * Routine to get the next character from the input stream. If we're reading
+ * from the real terminal, force a screen update before we get the char.
+ * Otherwise, we must be re-executing the command string, so just return the
+ * next character.
+ */
+
+int get_char ()
+{
+ int c; /* A place to get a character */
+
+ /* See if we're re-executing: */
+
+ if (cmd_reexecute >= 0) /* Is there an offset? */
+ if ((c = cmd_buff[cmd_reexecute++]) != 0)
+ return (c); /* Yes, return any character */
+
+ /* We're not re-executing (or aren't any more). Try for a real char */
+
+ cmd_reexecute = -1; /* Say we're in real mode again */
+ update(FALSE); /* Pretty up the screen */
+ if (cmd_offset >= CMDBUFLEN-1) /* If we're getting too big ... */
+ {
+ mlwrite ("? command too long"); /* Complain loudly and bitterly */
+ return (IS_QUIT); /* And force a quit */
+ }
+ c = (*term.t_getchar)(); /* Get the next character */
+ cmd_buff[cmd_offset++] = c; /* Save the char for next time */
+ cmd_buff[cmd_offset] = '\0';/* And terminate the buffer */
+ return (c); /* Return the character */
+}
+
+/*
+ * Hacky routine to re-eat a character. This will save the character to be
+ * re-eaten by redirecting the input call to a routine here. Hack, etc.
+ */
+
+/* Come here on the next term.t_getchar call: */
+
+int uneat()
+{
+ int c;
+
+ term.t_getchar = saved_get_char; /* restore the routine address */
+ c = eaten_char; /* Get the re-eaten char */
+ eaten_char = -1; /* Clear the old char */
+ return(c); /* and return the last char */
+}
+
+int reeat(c)
+int c;
+{
+ if (eaten_char != -1) /* If we've already been here */
+ return (0); /* Don't do it again */
+ eaten_char = c; /* Else, save the char for later */
+ saved_get_char = term.t_getchar; /* Save the char get routine */
+ term.t_getchar = uneat; /* Replace it with ours */
+}
+
Added: clients/emacs/line.c
===================================================================
--- clients/emacs/line.c (rev 0)
+++ clients/emacs/line.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,526 @@
+/*
+ * The functions in this file are a general set of line management utilities.
+ * They are the only routines that touch the text. They also touch the buffer
+ * and window structures, to make sure that the necessary updating gets done.
+ * There are routines in this file that handle the kill buffer too. It isn't
+ * here for any good reason.
+ *
+ * Note that this code only updates the dot and mark values in the window list.
+ * Since all the code acts on the current window, the buffer that we are
+ * editing must be being displayed, which means that "b_nwnd" is non zero,
+ * which means that the dot and mark values in the buffer headers are nonsense.
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+KILL *ykbuf; /* ptr to current kill buffer chunk being yanked */
+int ykboff; /* offset into that chunk */
+
+/*
+ * This routine allocates a block of memory large enough to hold a LINE
+ * containing "used" characters. The block is always rounded up a bit. Return
+ * a pointer to the new block, or NULL if there isn't any memory left. Print a
+ * message in the message line if no space.
+ */
+LINE *
+lalloc(used)
+register int used;
+{
+ register LINE *lp;
+ register int size;
+
+ size = (used+NBLOCK-1) & ~(NBLOCK-1);
+ if (size == 0) /* Assume that an empty */
+ size = NBLOCK; /* line is for type-in. */
+ if ((lp = (LINE *) malloc((size_t)(sizeof(LINE)+size))) == NULL) {
+ mlwrite("Cannot allocate %d bytes", size);
+ return (NULL);
+ }
+ lp->l_size = size;
+ lp->l_used = used;
+ return (lp);
+}
+
+/*
+ * Delete line "lp". Fix all of the links that might point at it (they are
+ * moved to offset 0 of the next line. Unlink the line from whatever buffer it
+ * might be in. Release the memory. The buffers are updated too; the magic
+ * conditions described in the above comments don't hold here.
+ */
+lfree(lp)
+register LINE *lp;
+{
+ register BUFFER *bp;
+ register WINDOW *wp;
+
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_linep == lp)
+ wp->w_linep = lp->l_fp;
+ if (wp->w_dotp == lp) {
+ wp->w_dotp = lp->l_fp;
+ wp->w_doto = 0;
+ }
+ if (wp->w_markp == lp) {
+ wp->w_markp = lp->l_fp;
+ wp->w_marko = 0;
+ }
+ wp = wp->w_wndp;
+ }
+ bp = bheadp;
+ while (bp != NULL) {
+ if (bp->b_nwnd == 0) {
+ if (bp->b_dotp == lp) {
+ bp->b_dotp = lp->l_fp;
+ bp->b_doto = 0;
+ }
+ if (bp->b_markp == lp) {
+ bp->b_markp = lp->l_fp;
+ bp->b_marko = 0;
+ }
+ }
+ bp = bp->b_bufp;
+ }
+ lp->l_bp->l_fp = lp->l_fp;
+ lp->l_fp->l_bp = lp->l_bp;
+ free((char *) lp);
+}
+
+/*
+ * This routine gets called when a character is changed in place in the current
+ * buffer. It updates all of the required flags in the buffer and window
+ * system. The flag used is passed as an argument; if the buffer is being
+ * displayed in more than 1 window we change EDIT t HARD. Set MODE if the
+ * mode line needs to be updated (the "*" has to be set).
+ */
+lchange(flag)
+register int flag;
+{
+ register WINDOW *wp;
+
+ if (curbp->b_nwnd != 1) /* Ensure hard. */
+ flag = WFHARD;
+ if ((curbp->b_flag&BFCHG) == 0) { /* First change, so */
+ flag |= WFMODE; /* update mode lines. */
+ curbp->b_flag |= BFCHG;
+ }
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= flag;
+ wp = wp->w_wndp;
+ }
+}
+
+insspace(f, n) /* insert spaces forward into text */
+
+int f, n; /* default flag and numeric argument */
+
+{
+ linsert(n, ' ');
+ backchar(f, n);
+}
+
+/*
+ * Insert "n" copies of the character "c" at the current location of dot. In
+ * the easy case all that happens is the text is stored in the line. In the
+ * hard case, the line has to be reallocated. When the window list is updated,
+ * take special care; I screwed it up once. You always update dot in the
+ * current window. You update mark, and a dot in another window, if it is
+ * greater than the place where you did the insert. Return TRUE if all is
+ * well, and FALSE on errors.
+ */
+linsert(n, c)
+{
+ register char *cp1;
+ register char *cp2;
+ register LINE *lp1;
+ register LINE *lp2;
+ register LINE *lp3;
+ register int doto;
+ register int i;
+ register WINDOW *wp;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ lchange(WFEDIT);
+ lp1 = curwp->w_dotp; /* Current line */
+ if (lp1 == curbp->b_linep) { /* At the end: special */
+ if (curwp->w_doto != 0) {
+ mlwrite("bug: linsert");
+ return (FALSE);
+ }
+ if ((lp2=lalloc(n)) == NULL) /* Allocate new line */
+ return (FALSE);
+ lp3 = lp1->l_bp; /* Previous line */
+ lp3->l_fp = lp2; /* Link in */
+ lp2->l_fp = lp1;
+ lp1->l_bp = lp2;
+ lp2->l_bp = lp3;
+ for (i=0; i<n; ++i)
+ lp2->l_text[i] = c;
+ curwp->w_dotp = lp2;
+ curwp->w_doto = n;
+ return (TRUE);
+ }
+ doto = curwp->w_doto; /* Save for later. */
+ if (lp1->l_used+n > lp1->l_size) { /* Hard: reallocate */
+ if ((lp2=lalloc(lp1->l_used+n)) == NULL)
+ return (FALSE);
+ cp1 = &lp1->l_text[0];
+ cp2 = &lp2->l_text[0];
+ while (cp1 != &lp1->l_text[doto])
+ *cp2++ = *cp1++;
+ cp2 += n;
+ while (cp1 != &lp1->l_text[lp1->l_used])
+ *cp2++ = *cp1++;
+ lp1->l_bp->l_fp = lp2;
+ lp2->l_fp = lp1->l_fp;
+ lp1->l_fp->l_bp = lp2;
+ lp2->l_bp = lp1->l_bp;
+ free((char *) lp1);
+ } else { /* Easy: in place */
+ lp2 = lp1; /* Pretend new line */
+ lp2->l_used += n;
+ cp2 = &lp1->l_text[lp1->l_used];
+ cp1 = cp2-n;
+ while (cp1 != &lp1->l_text[doto])
+ *--cp2 = *--cp1;
+ }
+ for (i=0; i<n; ++i) /* Add the characters */
+ lp2->l_text[doto+i] = c;
+ wp = wheadp; /* Update windows */
+ while (wp != NULL) {
+ if (wp->w_linep == lp1)
+ wp->w_linep = lp2;
+ if (wp->w_dotp == lp1) {
+ wp->w_dotp = lp2;
+ if (wp==curwp || wp->w_doto>doto)
+ wp->w_doto += n;
+ }
+ if (wp->w_markp == lp1) {
+ wp->w_markp = lp2;
+ if (wp->w_marko > doto)
+ wp->w_marko += n;
+ }
+ wp = wp->w_wndp;
+ }
+ return (TRUE);
+}
+
+/*
+ * Insert a newline into the buffer at the current location of dot in the
+ * current window. The funny ass-backwards way it does things is not a botch;
+ * it just makes the last line in the file not a special case. Return TRUE if
+ * everything works out and FALSE on error (memory allocation failure). The
+ * update of dot and mark is a bit easier then in the above case, because the
+ * split forces more updating.
+ */
+lnewline()
+{
+ register char *cp1;
+ register char *cp2;
+ register LINE *lp1;
+ register LINE *lp2;
+ register int doto;
+ register WINDOW *wp;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ lchange(WFHARD);
+ lp1 = curwp->w_dotp; /* Get the address and */
+ doto = curwp->w_doto; /* offset of "." */
+ if ((lp2=lalloc(doto)) == NULL) /* New first half line */
+ return (FALSE);
+ cp1 = &lp1->l_text[0]; /* Shuffle text around */
+ cp2 = &lp2->l_text[0];
+ while (cp1 != &lp1->l_text[doto])
+ *cp2++ = *cp1++;
+ cp2 = &lp1->l_text[0];
+ while (cp1 != &lp1->l_text[lp1->l_used])
+ *cp2++ = *cp1++;
+ lp1->l_used -= doto;
+ lp2->l_bp = lp1->l_bp;
+ lp1->l_bp = lp2;
+ lp2->l_bp->l_fp = lp2;
+ lp2->l_fp = lp1;
+ wp = wheadp; /* Windows */
+ while (wp != NULL) {
+ if (wp->w_linep == lp1)
+ wp->w_linep = lp2;
+ if (wp->w_dotp == lp1) {
+ if (wp->w_doto < doto)
+ wp->w_dotp = lp2;
+ else
+ wp->w_doto -= doto;
+ }
+ if (wp->w_markp == lp1) {
+ if (wp->w_marko < doto)
+ wp->w_markp = lp2;
+ else
+ wp->w_marko -= doto;
+ }
+ wp = wp->w_wndp;
+ }
+ return (TRUE);
+}
+
+/*
+ * This function deletes "n" bytes, starting at dot. It understands how do deal
+ * with end of lines, etc. It returns TRUE if all of the characters were
+ * deleted, and FALSE if they were not (because dot ran into the end of the
+ * buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
+ */
+ldelete(n, kflag)
+
+long n; /* # of chars to delete */
+int kflag; /* put killed text in kill buffer flag */
+
+{
+ register char *cp1;
+ register char *cp2;
+ register LINE *dotp;
+ register int doto;
+ register int chunk;
+ register WINDOW *wp;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ while (n != 0) {
+ dotp = curwp->w_dotp;
+ doto = curwp->w_doto;
+ if (dotp == curbp->b_linep) /* Hit end of buffer. */
+ return (FALSE);
+ chunk = dotp->l_used-doto; /* Size of chunk. */
+ if (chunk > n)
+ chunk = n;
+ if (chunk == 0) { /* End of line, merge. */
+ lchange(WFHARD);
+ if (ldelnewline() == FALSE
+ || (kflag!=FALSE && kinsert('\n')==FALSE))
+ return (FALSE);
+ --n;
+ continue;
+ }
+ lchange(WFEDIT);
+ cp1 = &dotp->l_text[doto]; /* Scrunch text. */
+ cp2 = cp1 + chunk;
+ if (kflag != FALSE) { /* Kill? */
+ while (cp1 != cp2) {
+ if (kinsert(*cp1) == FALSE)
+ return (FALSE);
+ ++cp1;
+ }
+ cp1 = &dotp->l_text[doto];
+ }
+ while (cp2 != &dotp->l_text[dotp->l_used])
+ *cp1++ = *cp2++;
+ dotp->l_used -= chunk;
+ wp = wheadp; /* Fix windows */
+ while (wp != NULL) {
+ if (wp->w_dotp==dotp && wp->w_doto>=doto) {
+ wp->w_doto -= chunk;
+ if (wp->w_doto < doto)
+ wp->w_doto = doto;
+ }
+ if (wp->w_markp==dotp && wp->w_marko>=doto) {
+ wp->w_marko -= chunk;
+ if (wp->w_marko < doto)
+ wp->w_marko = doto;
+ }
+ wp = wp->w_wndp;
+ }
+ n -= chunk;
+ }
+ return (TRUE);
+}
+
+/*
+ * Delete a newline. Join the current line with the next line. If the next line
+ * is the magic header line always return TRUE; merging the last line with the
+ * header line can be thought of as always being a successful operation, even
+ * if nothing is done, and this makes the kill buffer work "right". Easy cases
+ * can be done by shuffling data around. Hard cases require that lines be moved
+ * about in memory. Return FALSE on error and TRUE if all looks ok. Called by
+ * "ldelete" only.
+ */
+ldelnewline()
+{
+ register char *cp1;
+ register char *cp2;
+ register LINE *lp1;
+ register LINE *lp2;
+ register LINE *lp3;
+ register WINDOW *wp;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ lp1 = curwp->w_dotp;
+ lp2 = lp1->l_fp;
+ if (lp2 == curbp->b_linep) { /* At the buffer end. */
+ if (lp1->l_used == 0) /* Blank line. */
+ lfree(lp1);
+ return (TRUE);
+ }
+ if (lp2->l_used <= lp1->l_size-lp1->l_used) {
+ cp1 = &lp1->l_text[lp1->l_used];
+ cp2 = &lp2->l_text[0];
+ while (cp2 != &lp2->l_text[lp2->l_used])
+ *cp1++ = *cp2++;
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_linep == lp2)
+ wp->w_linep = lp1;
+ if (wp->w_dotp == lp2) {
+ wp->w_dotp = lp1;
+ wp->w_doto += lp1->l_used;
+ }
+ if (wp->w_markp == lp2) {
+ wp->w_markp = lp1;
+ wp->w_marko += lp1->l_used;
+ }
+ wp = wp->w_wndp;
+ }
+ lp1->l_used += lp2->l_used;
+ lp1->l_fp = lp2->l_fp;
+ lp2->l_fp->l_bp = lp1;
+ free((char *) lp2);
+ return (TRUE);
+ }
+ if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL)
+ return (FALSE);
+ cp1 = &lp1->l_text[0];
+ cp2 = &lp3->l_text[0];
+ while (cp1 != &lp1->l_text[lp1->l_used])
+ *cp2++ = *cp1++;
+ cp1 = &lp2->l_text[0];
+ while (cp1 != &lp2->l_text[lp2->l_used])
+ *cp2++ = *cp1++;
+ lp1->l_bp->l_fp = lp3;
+ lp3->l_fp = lp2->l_fp;
+ lp2->l_fp->l_bp = lp3;
+ lp3->l_bp = lp1->l_bp;
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_linep==lp1 || wp->w_linep==lp2)
+ wp->w_linep = lp3;
+ if (wp->w_dotp == lp1)
+ wp->w_dotp = lp3;
+ else if (wp->w_dotp == lp2) {
+ wp->w_dotp = lp3;
+ wp->w_doto += lp1->l_used;
+ }
+ if (wp->w_markp == lp1)
+ wp->w_markp = lp3;
+ else if (wp->w_markp == lp2) {
+ wp->w_markp = lp3;
+ wp->w_marko += lp1->l_used;
+ }
+ wp = wp->w_wndp;
+ }
+ free((char *) lp1);
+ free((char *) lp2);
+ return (TRUE);
+}
+
+/*
+ * Delete all of the text saved in the kill buffer. Called by commands when a
+ * new kill context is being created. The kill buffer array is released, just
+ * in case the buffer has grown to immense size. No errors.
+ */
+kdelete()
+{
+ KILL *kp; /* ptr to scan kill buffer chunk list */
+
+ if (kbufh != NULL) {
+
+ /* first, delete all the chunks */
+ kbufp = kbufh;
+ while (kbufp != NULL) {
+ kp = kbufp->d_next;
+ free(kbufp);
+ kbufp = kp;
+ }
+
+ /* and reset all the kill buffer pointers */
+ kbufh = kbufp = NULL;
+ kused = KBLOCK;
+ }
+}
+
+/*
+ * Insert a character to the kill buffer, allocating new chunks as needed.
+ * Return TRUE if all is well, and FALSE on errors.
+ */
+
+kinsert(c)
+
+int c; /* character to insert in the kill buffer */
+
+{
+ KILL *nchunk; /* ptr to newly malloced chunk */
+
+ /* check to see if we need a new chunk */
+ if (kused >= KBLOCK) {
+ if ((nchunk = (KILL *)malloc(sizeof(KILL))) == NULL)
+ return(FALSE);
+ if (kbufh == NULL) /* set head ptr if first time */
+ kbufh = nchunk;
+ if (kbufp != NULL) /* point the current to this new one */
+ kbufp->d_next = nchunk;
+ kbufp = nchunk;
+ kbufp->d_next = NULL;
+ kused = 0;
+ }
+
+ /* and now insert the character */
+ kbufp->d_chunk[kused++] = c;
+ return(TRUE);
+}
+
+/*
+ * Yank text back from the kill buffer. This is really easy. All of the work
+ * is done by the standard insert routines. All you do is run the loop, and
+ * check for errors. Bound to "C-Y".
+ */
+yank(f, n)
+{
+ register int c;
+ register int i;
+ register char *sp; /* pointer into string to insert */
+ KILL *kp; /* pointer into kill buffer */
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ /* make sure there is something to yank */
+ if (kbufh == NULL)
+ return(TRUE); /* not an error, just nothing */
+
+ /* for each time.... */
+ while (n--) {
+ kp = kbufh;
+ while (kp != NULL) {
+ if (kp->d_next == NULL)
+ i = kused;
+ else
+ i = KBLOCK;
+ sp = kp->d_chunk;
+ while (i--) {
+ if ((c = *sp++) == '\n') {
+ if (lnewline(FALSE, 1) == FALSE)
+ return (FALSE);
+ } else {
+ if (linsert(1, c) == FALSE)
+ return (FALSE);
+ }
+ }
+ kp = kp->d_next;
+ }
+ }
+ return (TRUE);
+}
+
+
Added: clients/emacs/lock.c
===================================================================
--- clients/emacs/lock.c (rev 0)
+++ clients/emacs/lock.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,163 @@
+/* LOCK: File locking command routines for MicroEMACS
+ written by Daniel Lawrence
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+#if FILOCK
+#if BSD
+#include <sys/errno.h>
+
+extern int sys_nerr; /* number of system error messages defined */
+extern char *sys_errlist[]; /* list of message texts */
+extern int errno; /* current error */
+
+char *lname[NLOCKS]; /* names of all locked files */
+int numlocks; /* # of current locks active */
+
+/* lockchk: check a file for locking and add it to the list */
+
+lockchk(fname)
+
+char *fname; /* file to check for a lock */
+
+{
+ register int i; /* loop indexes */
+ register int status; /* return status */
+ char *undolock();
+
+ /* check to see if that file is already locked here */
+ if (numlocks > 0)
+ for (i=0; i < numlocks; ++i)
+ if (strcmp(fname, lname[i]) == 0)
+ return(TRUE);
+
+ /* if we have a full locking table, bitch and leave */
+ if (numlocks == NLOCKS) {
+ mlwrite("LOCK ERROR: Lock table full");
+ return(ABORT);
+ }
+
+ /* next, try to lock it */
+ status = lock(fname);
+ if (status == ABORT) /* file is locked, no override */
+ return(ABORT);
+ if (status == FALSE) /* locked, overriden, dont add to table */
+ return(TRUE);
+
+ /* we have now locked it, add it to our table */
+ lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1);
+ if (lname[numlocks - 1] == NULL) { /* malloc failure */
+ undolock(fname); /* free the lock */
+ mlwrite("Cannot lock, out of memory");
+ --numlocks;
+ return(ABORT);
+ }
+
+ /* everthing is cool, add it to the table */
+ strcpy(lname[numlocks-1], fname);
+ return(TRUE);
+}
+
+/* lockrel: release all the file locks so others may edit */
+
+lockrel()
+
+{
+ register int i; /* loop index */
+ register int status; /* status of locks */
+ register int s; /* status of one unlock */
+
+ status = TRUE;
+ if (numlocks > 0)
+ for (i=0; i < numlocks; ++i) {
+ if ((s = unlock(lname[i])) != TRUE)
+ status = s;
+ free(lname[i]);
+ }
+ numlocks = 0;
+ return(status);
+}
+
+/* lock: Check and lock a file from access by others
+ returns TRUE = files was not locked and now is
+ FALSE = file was locked and overridden
+ ABORT = file was locked, abort command
+*/
+
+lock(fname)
+
+char *fname; /* file name to lock */
+
+{
+ register char *locker; /* lock error message */
+ register int status; /* return status */
+ char msg[NSTRING]; /* message string */
+ char *dolock();
+
+ /* attempt to lock the file */
+ locker = dolock(fname);
+ if (locker == NULL) /* we win */
+ return(TRUE);
+
+ /* file failed...abort */
+ if (strncmp(locker, "LOCK", 4) == 0) {
+ lckerror(locker);
+ return(ABORT);
+ }
+
+ /* someone else has it....override? */
+ strcpy(msg, "File in use by ");
+ strcat(msg, locker);
+ strcat(msg, ", overide?");
+ status = mlyesno(msg); /* ask them */
+ if (status == TRUE)
+ return(FALSE);
+ else
+ return(ABORT);
+}
+
+/* unlock: Unlock a file
+ this only warns the user if it fails
+ */
+
+unlock(fname)
+
+char *fname; /* file to unlock */
+
+{
+ register char *locker; /* undolock return string */
+ char *undolock();
+
+ /* unclock and return */
+ locker = undolock(fname);
+ if (locker == NULL)
+ return(TRUE);
+
+ /* report the error and come back */
+ lckerror(locker);
+ return(FALSE);
+}
+
+lckerror(errstr) /* report a lock error */
+
+char *errstr; /* lock error string to print out */
+
+{
+ char obuf[NSTRING]; /* output buffer for error message */
+
+ strcpy(obuf, errstr);
+ strcat(obuf, " - ");
+ if (errno < sys_nerr)
+ strcat(obuf, sys_errlist[errno]);
+ else
+ strcat(obuf, "[can not get system error message]");
+ mlwrite(obuf);
+}
+#endif
+#else
+lckhello() /* dummy function */
+{
+}
+#endif
Added: clients/emacs/main.c
===================================================================
--- clients/emacs/main.c (rev 0)
+++ clients/emacs/main.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,920 @@
+/*
+ * This program is in public domain; written by Dave G. Conroy.
+ * This file contains the main driving routine, and some keyboard processing
+ * code, for the MicroEMACS screen editor.
+ *
+ * REVISION HISTORY:
+ *
+ * 1.0 Steve Wilhite, 30-Nov-85
+ * - Removed the old LK201 and VT100 logic. Added code to support the
+ * DEC Rainbow keyboard (which is a LK201 layout) using the the Level
+ * 1 Console In ROM INT. See "rainbow.h" for the function key defs
+ * Steve Wilhite, 1-Dec-85
+ * - massive cleanup on code in display.c and search.c
+ *
+ * 2.0 George Jones, 12-Dec-85
+ * - Ported to Amiga.
+ *
+ * 3.0 Daniel Lawrence, 29-Dec-85
+ * - rebound keys/added new fast buffered I/O for AMIGA
+ * - added META- repeat commands
+ * - added reposition default to center screen (yeah!)
+ * - changed exit with modified buffers message
+ * - made filesave tell us what it is doing
+ * - changed search string entry to terminate with <ESC>
+ * so we can use <NL> in search/replace strings
+ * - updated version number in mode line to 3.0
+ * 12-Jan-86
+ * - Added code to reconize the Search/replace functions
+ * - Added code to perform search/replace & query functions
+ * 14-Jan-86
+ * - moved search logic to separate function in search.c
+ * - added replace and query replace functions
+ * - separated out control key expansions to be used by others in search.c
+ * 15-Jan-86
+ * - changed "visiting" to finding
+ * - changed yes/no responces to not need return
+ * - cleaned up various messages
+ * 16-jan-86
+ * - fixed spurious spawn message in MSDOS
+ * - added ^X-S synonime to save command
+ * - moved escape to shell to ^X-C
+ * 21-jan-86
+ * - added code to suspend shell under BSD
+ * 22-jan-86
+ * - added function key support (SPEC) under MSDOS
+ * - Abort now prints [Aborted] on message line
+ * 23-jan-86
+ * - Added modes and commends to set/unset them
+ * 24-jan-86
+ * - Added Goto Line command
+ * - added Rename Buffer command
+ * 28-jan-86
+ * - added goto begining and end of paragraph commands (META-P/META-N)
+ * - re-wrote kdelete to use realloc. gained MUCH speed here when
+ * doing large wipes both on UNIX and MSDOS. Changed kill buffer
+ * allocation block size from 256 bytes to 1 k
+ * 29-jan-86
+ * - moved extern function declarations to efunc.h
+ * - made name[] name binding table
+ * 30-jan-86
+ * - fixed Previous/Next paragraph command not to wrap around EOF
+ * - added Fill Paragraph command (META-Q)
+ * 4-feb-86
+ * - added code to properly display long lines, scrolling them right
+ * to left
+ * 5-feb-85
+ * - rewrote code to right/left scroll...much better
+ * - added shifted arror keys on IBMPC
+ * 6-feb-85
+ * - add option to allow forword-word to jump to begining of
+ * next word instead of end of current one. This is different from
+ * other emacs' but can be configured off in estruct.h
+ * - added VIEW mode to allow a buffer to be read only
+ * (-v switch on command line will activate this)
+ * - changed quick exit to write out ALL changed buffers!!!
+ * MAKE SURE YOU KNOW THIS WHEN META-Zing
+ * 10-feb-86
+ * - added handling of lines longer than allowed on file read in
+ * (they wrap on additional lines)
+ * - made having space clear the message line and NOT insert itself
+ * a configuration option in ed.h
+ * 11-feb-86
+ * - added Describe-command and Help commands.
+ * 13-feb-86
+ * - added View file command (^X ^V) and finished HELP command
+ * 14-feb-86
+ * - added option to let main loop skip update if type ahead commands
+ * are queued up
+ * 16-feb-86
+ * - added Insert File command
+ * 17-feb-86
+ * - added scroll next window up/down commands
+ * 18-feb-86
+ * - added CMODE indentation
+ * - re-arranged header files to standerdize extern and global
+ * definitions
+ * - changed version number to 3.2
+ * - added numeric arguments to search, reverse search and
+ * search and replace
+ * 24-feb-86
+ * - added Bind To Key function (^C for now) to allow the user
+ * to change his command keys
+ * - added Unbind key function (M-^C for now)
+ * - added execute named command to execute unbound commands (M-X)
+ * - added describe bindings command (not bound)
+ * - changed version number to 3.3
+ * 25-feb-86
+ * - scrapped CERROR mode (too many compilers)
+ * - added EXACT mode for case sensitive searchers
+ * 26-feb-86
+ * - added command completion on execute named command and
+ * all routined grabbing a command name
+ * - adding execute-command-line command and its support functions
+ * (in preporation for sourcing files)
+ * - added Execute Buffer command
+ * 27-feb-86
+ * - added execute(source) file command and added code to automatically
+ * execute emacs.rc (or .emacsrc on UNIX) before initial read in
+ * - changed version number to 3.4
+ * 4-mar-86
+ * - changed word delete to be consistant with word move (it gets
+ * rid of the inter word space now) This is configurable with the
+ * NFWORD symbol in estruct.h
+ * - added B_ACTIVE entry to the buffer table. Let emacs read multiple
+ * file names from the command line and only read them in as needed
+ * 5-mar-85
+ * - rewrote command line parser to get rid of my patchy code
+ * - changed version number to 3.5
+ * 1-apr-86
+ * - added support for Aztec C 3.20e under MSDOS
+ * - fixed bug in mlwrite on ADM3's and thier ilk under V7
+ * - added insertion of pounds in column one under CMODE
+ * - changed version number to 3.6
+ * 3-apr-86
+ * - added next-buffer command (^X-X)
+ * 5-apr-86
+ * - added kill paragraph command (M-^W)
+ * - changed fill-paragraph to leave 2 spaces after a period at the
+ * end of a word.
+ * - added OVERWRITE mode
+ * 7-apr-86
+ * - fixed overwrite mode to handle tabs
+ * 8-apr-86
+ * - added add/delete global mode (<ESC>M & <ESC> ^M) commands
+ * 9-apr-86
+ * - added insert space command
+ * - moved bindings around ^C insert space
+ * M-K bind-to-key
+ * INSERT insert space
+ * DELETE forwdel
+ * - added hunt forward and hunt reverse commands
+ * 10-apr-86
+ * - fixed bug in DOBUF with non-terminated command string
+ * 15-apr-86
+ * - fixed tab expansion bug in DISPLAY which hung the AMIGA
+ * (send in by Dawn Banks)
+ * - fixed curcol problen if forwline/backline during keyboard
+ * macro execution (sent in by Ernst Christen)
+ * - added AMIGA function/cursor key support
+ * - fixed nonterminating <NL> replacement bug
+ * - fixed word wrapping problems
+ * 16-apr-86
+ * - updated documentation and froze development for 3.6 net release
+ * 23-apr-86 version 3.6a
+ * - added forground and background colors. Setable with the
+ * add mode commands for the moment
+ * 24-apr-86
+ * - added command to pipe CLI output to a buffer
+ * 25-apr-86
+ * - added Dana Hoggat's code to replace lattice's sick system()
+ * function, now we no longer care what the switchar is.
+ * - cleaned up the positioning on several of the spawing commands
+ * 26-apr-86
+ * - added a output flush in vttidy(). Unix really appreciates this.
+ * - added filter-buffer (^X#) command to send a buffer through
+ * a dos filter
+ * - made automatic CMODE on .c and .h file compilation dependant
+ * in estruct.h
+ * 1-may-86
+ * - optimized some code in update(). It certainly need a lot more.
+ * - added AZTEC profiling capabilities. These are conditional on
+ * the APROF symbol in estruct.h
+ * 2-may-86
+ * - added (u)ndo command in query-replace. undoes last repalce.
+ * 6-may-86
+ * - re-orginized and wrote the update() function in display.c
+ * now my color hacks are in the right places and the code can be
+ * understood.
+ * [Released version 3.6f for BETA test sites]
+ * 8-may-86
+ * - fixed bug in new display routine to wrap cursor on extended
+ * lines at the right time
+ * - modified the buffer-position command to give reasonable info
+ * 9-may-86
+ * - improved the word wrap algorithm as not to discard non-space
+ * delimiters. The backscan now looks for white space rather than
+ * !inword().
+ * [Released version 3.6g to Krannert]
+ * 10-may-86
+ * - Added IBMPC.C an IBM-PC specific display driver. This makes paging
+ * 4-6 times faster. Also made some conditional changes to DISPLAY.C
+ * to eliminate the pscreen[] if using the PC driver.
+ * [changed version number to 3.6i]
+ * 12-may-86
+ * - added delete-window (^X 0) command to dispose of a single window
+ * - fixed problem with multiple prefixes from a command line which
+ * was reported by John Gamble
+ * 14-may-86
+ * - Added AZTEC support for the IBMPC display driver. Had to
+ * readjust some includes and defines for this.
+ * - fixed bug in delete-window.
+ * - fixed some bizarre behavior with the cursor after coming back
+ * from spawn calls.
+ * [changed version number to 3.7 Freezing development for net release]
+ * 15-may-86
+ * - (that didn't last long...) Added execute-macro-(1 thru 20) commands
+ * to execute macro buffers (named "[Macro nn]")
+ * - changed BFTEMP to BFINVS and cleaned up treatment of invisable
+ * buffers.
+ * 16-may-86
+ * - added store-macro (unbound) to store any executed command lines to
+ * macro buffer.
+ * - added clear-message-line (unbound) command to do just that
+ * - added resize-window command to change a window's size to the
+ * specified argument
+ * - improved help's logic not to re-read the file if it was already
+ * in a buffer
+ * - added MAGIC mode to all structures and command tables, but the
+ * regular expression code that John Gamble is writting is not ready.
+ * 18-may-86
+ * - added interactive prompt requests in command line execution. IE
+ * while executing a macro, a parameter starting with an at sign (@)
+ * causes emacs to prompt with the rest of the parameter and return
+ * the resulting input as the value of the parameter.
+ * - added arguments to split-current-window to force the cursor into
+ * the upper or lower window.
+ * 20-may-86
+ * - added support for the Microsoft C compiler as per the changes
+ * send in by Oliver Sharp
+ * - made some upgrades and fixes for VMS sent in by Guy Streeter
+ * 21-may-86
+ * - fixed an AZTEC bug in ttgetc by clearing the upper byte
+ * - fixed buf in CMODE with #preprocesser input (bug fix submitted by
+ * Willis of unknown path)
+ * - added support of alternative startup file ( @<filename> ) in
+ * the command line
+ * - added ^Q quoting in interactive input (mlreplyt()).
+ * - added re-binding of meta-prefix and ctlx-prefix
+ * 22-may-86
+ * - reorginize getkey routines to make more sense and let prefix
+ * binding work properly.
+ * 23-may-86
+ * - checked new code on BSD4.2 made a few fixes
+ * - added optional fence matching while in CMODE
+ * - added goto and search command line arguments by Mike Spitzer
+ * 26-may-86
+ * - added parameter fetching from buffers
+ * 27-may-86
+ * - fixed some HP150 bugs......
+ * 31-may-86
+ * - Added Wang PC keyboard support from modifications by
+ * Sid Shapiro @ Wang Institute
+ * - Fixed some reverse video bugs with code submitted by Peter Chubb
+ * - Fixed bug in nextbuffer reported by Dave Forslund
+ * - added system V support (USG) from Linwood Varney
+ * 2-jun-86
+ * - changed defines to just define one unix define (for example,
+ * just define BSD for Unix BSD 4.2)
+ * - Added Incremental search functions written by D. R. Banks
+ * in file ISEARCH.C
+ * - added insert-string (unbound) command to help the macro
+ * language out.
+ * - added unmark-buffer (M-~) command to turn off the current buffers
+ * change flag
+ * - fixed nxtarg to truncate strings longer than asked for max length
+ * 4-jun-86
+ * - added special characters in command line tokens. Tidle (~) is
+ * the special leadin character for "nrtb".
+ * - Fixed bad ifdef in aztec code so it could look at HOME dir
+ * for startup, help, and emacs.rc files
+ * 6-jun-86
+ * - make delete word commands clear the kill buffer if not after another
+ * kill command
+ * 11-jun-86
+ * - made ~@ in string arguments pass as char(192) to nxtarg() so one can
+ * quote @ at the begining of string arguments
+ * - changed buffer size vars in listbuffers() to long (for big files)
+ * - re-wrote buffer-position command to be much faster
+ * 12-jun-86
+ * - added count-words (M-^C) command to count the words/chars and
+ * lines in a region
+ * - changed regions so they could be larger than 65535 (short ->
+ * long in the REGION structure)
+ * - changed ldelete() and all callers to use a long size. The kill
+ * buffer will still have a problem >65535 that can not be solved
+ * until I restructure it.
+ * - grouped paragraph commands and word count together under symbol
+ * WORDPRO to allow them to be conditionally made (or not)
+ * 13-jun-86
+ * - re-wrote kill buffer routines again. Now they support an unlimited
+ * size kill buffer, and are (in theory) faster.
+ * - changed delete-next-word (M-D) to not eat the newline after a word,
+ * instead it checks and eats a newline at the cursor.
+ * 17-jun-85
+ * - added numeric argument to next/previous-window to access the nth
+ * window from the top/bottom
+ * - added support for the data General 10 MSDOS machine
+ * - added save-window (unbound) and restore-window (unbound) commands
+ * for the use of the menu script. Save-window remembers which window
+ * is current, and restore-window returns the cursor to that window.
+ * 20-jun-86
+ * - fixed a bug with the fence matching locking up near the begining
+ * of a buffer
+ * - added argument to update to selectivaly force a complete update
+ * - added update-screen (unbound) command so macros can force a
+ * screen update
+ * 21-jun-86
+ * - rearranged token() and nxtarg() calls so that command names and
+ * repeat counts could also be prompted and fetched from buffers
+ * - added write-message (unbound) command to write out a message
+ * on the message line (for macros)
+ * - changed ifdef's so that color modes are reconized as legal in
+ * b/w version, and simply do nothing (allowing us to use the same
+ * script files)
+ */
+
+
+/* make global definitions not external */
+#define maindef
+
+#include "estruct.h" /* global structures and defines */
+#include "efunc.h" /* function declarations and name table */
+#include "edef.h" /* global definitions */
+#include "ebind.h" /* default key bindings */
+
+#if VMS
+#include <ssdef.h>
+#define GOOD (SS$_NORMAL)
+#endif
+
+#if IBMPC
+#define MIN8BITCHAR 0x80
+#else
+#define MIN8BITCHAR 0xA0
+#endif
+
+#ifndef GOOD
+#define GOOD 0
+#endif
+
+#if APROF /* Declarations needed for AZTEC C profiling */
+int _Corg(); /* first address of program */
+int _Cend(); /* last address of program */
+
+short monbuf[NBUCK]; /* buffer for gather info */
+#endif
+
+#ifndef NOMAIN
+main(argc, argv)
+char *argv[];
+{
+ emacs_main(argc, argv);
+}
+#endif
+
+int initialized;
+
+#ifdef NOMAIN
+#include <setjmp.h>
+jmp_buf done;
+#endif
+
+emacs_main(argc, argv)
+char *argv[];
+{
+ register int c;
+ register int f;
+ register int n;
+ register int mflag;
+ register BUFFER *bp;
+ register int ffile; /* first file flag */
+ register int carg; /* current arg to scan */
+ static int startf; /* startup executed flag */
+ int basec; /* c stripped of meta character */
+ register int viewflag; /* are we starting in view mode? */
+ int gotoflag; /* do we need to goto a line at start? */
+ int gline; /* if so, what line? */
+ int searchflag; /* Do we need to search at start? */
+ char bname[NBUFN]; /* buffer name of file to read */
+
+#if APROF
+ /* if we are doing AZTEC C profiling, start it up */
+ /*_intr_sp(18); set clock interupt for 60/second */
+ monitor(_Corg, _Cend, monbuf, NBUCK, 0);
+#endif
+
+#ifdef NOMAIN
+ if (setjmp(done))
+ return;
+
+ if (initialized == TRUE)
+ goto skipinit;
+
+ initialized = TRUE;
+#endif
+
+ /* initialize the editor and process the command line arguments */
+ strcpy(bname, "main"); /* default buffer name */
+ vtinit(); /* Displays. */
+ edinit(bname); /* Buffers, windows. */
+ startf = FALSE; /* startup file not executed yet */
+
+#ifdef NOMAIN
+skipinit:
+#endif
+
+ viewflag = FALSE; /* view mode defaults off in command line */
+ gotoflag = FALSE; /* set to off to begin with */
+ searchflag = FALSE; /* set to off to begin with */
+ ffile = TRUE; /* no file to edit yet */
+
+#if COLOR
+ curwp->w_fcolor = gfcolor; /* and set colors */
+ curwp->w_bcolor = gbcolor;
+#endif
+
+ /* scan through the command line and get the files to edit */
+ for (carg = 1; carg < argc; ++carg) {
+ /* if its a switch, process it */
+ if (argv[carg][0] == '-') {
+ switch (argv[carg][1]) {
+ case 'v': /* -v for View File */
+ case 'V':
+ viewflag = TRUE;
+ break;
+ case 'e': /* -e for Edit file */
+ case 'E':
+ viewflag = FALSE;
+ break;
+ case 's': /* -s for initial search string */
+ case 'S':
+ searchflag = TRUE;
+ strcpy(pat,&argv[carg][2]);
+ break;
+ case 'g': /* -g for initial goto */
+ case 'G':
+ gotoflag = TRUE;
+ gline = atoi(&argv[carg][2]);
+ break;
+ default: /* unknown switch */
+ /* ignore this for now */
+ break;
+ }
+ } else /* check for a macro file */
+ if (argv[carg][0]== '@') {
+
+ if (startup(&argv[carg][1]) == TRUE)
+ startf = TRUE; /* don't execute emacs.rc */
+
+ } else { /* process a file name */
+ /* if we haven't run emacs.rc, do it now */
+ if (startf == FALSE) {
+ startup("");
+ startf = TRUE;
+ }
+
+#ifdef NOMAIN
+ /* if this is the first file, read it in */
+ if (ffile) {
+ if (getfile(argv[carg], (viewflag==FALSE))
+ == ABORT) {
+ bp = curbp;
+ strcpy(bp->b_bname, "main");
+ strcpy(bp->b_fname, "");
+ }
+ bp = curbp;
+#else
+ /* set up a buffer for this file */
+ makename(bname, argv[carg]);
+
+ /* if this is the first file, read it in */
+ if (ffile) {
+ bp = curbp;
+ makename(bname, argv[carg]);
+ strcpy(bp->b_bname, bname);
+ strcpy(bp->b_fname, argv[carg]);
+ if (readin(argv[carg], (viewflag==FALSE))
+ == ABORT) {
+ strcpy(bp->b_bname, "main");
+ strcpy(bp->b_fname, "");
+ }
+#endif
+
+ bp->b_dotp = bp->b_linep;
+ bp->b_doto = 0;
+ ffile = FALSE;
+ } else {
+ /* set this to inactive */
+ bp = bfind(bname, TRUE, 0);
+ strcpy(bp->b_fname, argv[carg]);
+ bp->b_active = FALSE;
+ }
+
+ /* set the view mode appropriatly */
+ if (viewflag)
+ bp->b_mode |= MDVIEW;
+ }
+ }
+
+ /* if invoked with nothing, run the startup file here */
+ if (startf == FALSE) {
+ startup("");
+ startf = TRUE;
+ }
+
+ /* Deal with startup gotos and searches */
+
+ if (gotoflag && searchflag) {
+ update(FALSE);
+ mlwrite("[Can not search and goto at the same time!]");
+ }
+ else if (gotoflag) {
+ if (gotoline(TRUE,gline) == FALSE) {
+ update(FALSE);
+ mlwrite("[Bogus goto argument]");
+ }
+ } else if (searchflag) {
+ if (forscan(&pat[0], 2) == FALSE) {
+ update(FALSE);
+ mlwrite("Not found.");
+ }
+ }
+
+ /* setup to process commands */
+#ifdef NOMAIN
+ refresh(FALSE,1);
+#endif
+ lastflag = 0; /* Fake last flags. */
+ curbp->b_mode |= gmode; /* and set default modes*/
+ curwp->w_flag |= WFMODE; /* and force an update */
+#if COLOR
+ curwp->w_fcolor = gfcolor; /* and set colors */
+ curwp->w_bcolor = gbcolor;
+#endif
+
+loop:
+ update(FALSE); /* Fix up the screen */
+ c = getcmd();
+ if (mpresf != FALSE) {
+ mlerase();
+ update(FALSE);
+#if CLRMSG
+ if (c == ' ') /* ITS EMACS does this */
+ goto loop;
+#endif
+ }
+ f = FALSE;
+ n = 1;
+
+ /* do META-# processing if needed */
+
+ basec = c & ~META; /* strip meta char off if there */
+ if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
+ f = TRUE; /* there is a # arg */
+ n = 0; /* start with a zero default */
+ mflag = 1; /* current minus flag */
+ c = basec; /* strip the META */
+ while ((c >= '0' && c <= '9') || (c == '-')) {
+ if (c == '-') {
+ /* already hit a minus or digit? */
+ if ((mflag == -1) || (n != 0))
+ break;
+ mflag = -1;
+ } else {
+ n = n * 10 + (c - '0');
+ }
+ if ((n == 0) && (mflag == -1)) /* lonely - */
+ mlwrite("Arg:");
+ else
+ mlwrite("Arg: %d",n * mflag);
+
+ c = getcmd(); /* get the next key */
+ }
+ n = n * mflag; /* figure in the sign */
+ }
+
+ /* do ^U repeat argument processing */
+
+ if (c == (CTRL|'U')) { /* ^U, start argument */
+ f = TRUE;
+ n = 4; /* with argument of 4 */
+ mflag = 0; /* that can be discarded. */
+ mlwrite("Arg: 4");
+ while ((c=getcmd()) >='0' && c<='9' || c==(CTRL|'U') || c=='-'){
+ if (c == (CTRL|'U'))
+ n = n*4;
+ /*
+ * If dash, and start of argument string, set arg.
+ * to -1. Otherwise, insert it.
+ */
+ else if (c == '-') {
+ if (mflag)
+ break;
+ n = 0;
+ mflag = -1;
+ }
+ /*
+ * If first digit entered, replace previous argument
+ * with digit and set sign. Otherwise, append to arg.
+ */
+ else {
+ if (!mflag) {
+ n = 0;
+ mflag = 1;
+ }
+ n = 10*n + c - '0';
+ }
+ mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
+ }
+ /*
+ * Make arguments preceded by a minus sign negative and change
+ * the special argument "^U -" to an effective "^U -1".
+ */
+ if (mflag == -1) {
+ if (n == 0)
+ n++;
+ n = -n;
+ }
+ }
+
+ if (kbdmip != NULL) { /* Save macro strokes. */
+ if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) {
+ ctrlg(FALSE, 0);
+ goto loop;
+ }
+ if (f != FALSE) {
+ *kbdmip++ = (CTRL|'U');
+ *kbdmip++ = n;
+ }
+ *kbdmip++ = c;
+ }
+ execute(c, f, n); /* Do it. */
+ goto loop;
+}
+
+/*
+ * Initialize all of the buffers and windows. The buffer name is passed down
+ * as an argument, because the main routine may have been told to read in a
+ * file by default, and we want the buffer name to be right.
+ */
+edinit(bname)
+char bname[];
+{
+ register BUFFER *bp;
+ register WINDOW *wp;
+
+ bp = bfind(bname, TRUE, 0); /* First buffer */
+ blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer */
+ wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */
+ if (bp==NULL || wp==NULL || blistp==NULL)
+ errexit();
+ curbp = bp; /* Make this current */
+ wheadp = wp;
+ curwp = wp;
+ wp->w_wndp = NULL; /* Initialize window */
+ wp->w_bufp = bp;
+ bp->b_nwnd = 1; /* Displayed. */
+ wp->w_linep = bp->b_linep;
+ wp->w_dotp = bp->b_linep;
+ wp->w_doto = 0;
+ wp->w_markp = NULL;
+ wp->w_marko = 0;
+ wp->w_toprow = 0;
+#if COLOR
+ /* initalize colors to global defaults */
+ wp->w_fcolor = gfcolor;
+ wp->w_bcolor = gbcolor;
+#endif
+ wp->w_ntrows = term.t_nrow-1; /* "-1" for mode line. */
+ wp->w_force = 0;
+ wp->w_flag = WFMODE|WFHARD; /* Full. */
+}
+
+/*
+ * This is the general command execution routine. It handles the fake binding
+ * of all the keys to "self-insert". It also clears out the "thisflag" word,
+ * and arranges to move it to the "lastflag", so that the next command can
+ * look at it. Return the status of command.
+ */
+execute(c, f, n)
+{
+ register KEYTAB *ktp;
+ register int status;
+
+ ktp = &keytab[0]; /* Look in key table. */
+ while (ktp->k_fp != NULL) {
+ if (ktp->k_code == c) {
+ thisflag = 0;
+ status = (*ktp->k_fp)(f, n);
+ lastflag = thisflag;
+ return (status);
+ }
+ ++ktp;
+ }
+
+ /*
+ * If a space was typed, fill column is defined, the argument is non-
+ * negative, wrap mode is enabled, and we are now past fill column,
+ * and we are not read-only, perform word wrap.
+ */
+ if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
+ n >= 0 && getccol(FALSE) > fillcol &&
+ (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
+ wrapword();
+
+ if ((c>=0x20 && c<=0x7E) /* Self inserting. */
+ || (c>=MIN8BITCHAR && c<=0xFE)) {
+ if (n <= 0) { /* Fenceposts. */
+ lastflag = 0;
+ return (n<0 ? FALSE : TRUE);
+ }
+ thisflag = 0; /* For the future. */
+
+ /* if we are in overwrite mode, not at eol,
+ and next char is not a tab or we are at a tab stop,
+ delete a char forword */
+ if (curwp->w_bufp->b_mode & MDOVER &&
+ curwp->w_doto < curwp->w_dotp->l_used &&
+ (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
+ (curwp->w_doto) % 8 == 7))
+ ldelete(1L, FALSE);
+
+ /* do the appropriate insertion */
+ if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
+ status = insbrace(n, c);
+ else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
+ status = inspound();
+ else
+ status = linsert(n, c);
+
+#if CFENCE
+ /* check for CMODE fence matching */
+ if ((c == '}' || c == ')') && (curbp->b_mode & MDCMOD) != 0)
+ fmatch(c);
+#endif
+
+ lastflag = thisflag;
+ return (status);
+ }
+ (*term.t_beep)();
+ mlwrite("[Key not bound]"); /* complain */
+ lastflag = 0; /* Fake last flags. */
+ return (FALSE);
+}
+
+/*
+ * Fancy quit command, as implemented by Norm. If the any buffer has
+ * changed do a write on that buffer and exit emacs, otherwise simply exit.
+ */
+quickexit(f, n)
+{
+ register BUFFER *bp; /* scanning pointer to buffers */
+
+ bp = bheadp;
+ while (bp != NULL) {
+ if ((bp->b_flag&BFCHG) != 0 /* Changed. */
+ && (bp->b_flag&BFINVS) == 0) { /* Real. */
+ curbp = bp; /* make that buffer cur */
+ mlwrite("[Saving %s]",bp->b_fname);
+ filesave(f, n);
+ }
+ bp = bp->b_bufp; /* on to the next buffer */
+ }
+ quit(f, n); /* conditionally quit */
+}
+
+/*
+ * Quit command. If an argument, always quit. Otherwise confirm if a buffer
+ * has been changed and not written out. Normally bound to "C-X C-C".
+ */
+quit(f, n)
+{
+ register int s;
+
+ if (f != FALSE /* Argument forces it. */
+ || anycb() == FALSE /* All buffers clean. */
+ /* User says it's OK. */
+ || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
+#if FILOCK
+ if (lockrel() != TRUE) {
+ (*term.t_putchar)('\n');
+ (*term.t_putchar)('\r');
+ (*term.t_close)();
+ exit(1);
+ }
+#endif
+ vttidy();
+#if APROF
+ /* if doing AZTEC C profiling, close up and write it out */
+ monitor(0,0,0,0,0);
+#endif
+#ifdef NOMAIN
+ longjmp(done,0);
+#else
+ exit(GOOD);
+#endif
+ }
+ mlwrite("");
+ return (s);
+}
+
+/*
+ * Begin a keyboard macro.
+ * Error if not at the top level in keyboard processing. Set up variables and
+ * return.
+ */
+ctlxlp(f, n)
+{
+ if (kbdmip!=NULL || kbdmop!=NULL) {
+ mlwrite("Not now");
+ return (FALSE);
+ }
+ mlwrite("[Start macro]");
+ kbdmip = &kbdm[0];
+ return (TRUE);
+}
+
+/*
+ * End keyboard macro. Check for the same limit conditions as the above
+ * routine. Set up the variables and return to the caller.
+ */
+ctlxrp(f, n)
+{
+ if (kbdmip == NULL) {
+ mlwrite("Not now");
+ return (FALSE);
+ }
+ mlwrite("[End macro]");
+ kbdmip = NULL;
+ return (TRUE);
+}
+
+/*
+ * Execute a macro.
+ * The command argument is the number of times to loop. Quit as soon as a
+ * command gets an error. Return TRUE if all ok, else FALSE.
+ */
+ctlxe(f, n)
+{
+ register int c;
+ register int af;
+ register int an;
+ register int s;
+
+ if (kbdmip!=NULL || kbdmop!=NULL) {
+ mlwrite("Not now");
+ return (FALSE);
+ }
+ if (n <= 0)
+ return (TRUE);
+ do {
+ kbdmop = &kbdm[0];
+ do {
+ af = FALSE;
+ an = 1;
+ if ((c = *kbdmop++) == (CTRL|'U')) {
+ af = TRUE;
+ an = *kbdmop++;
+ c = *kbdmop++;
+ }
+ s = TRUE;
+ } while (c!=(CTLX|')') && (s=execute(c, af, an))==TRUE);
+ kbdmop = NULL;
+ } while (s==TRUE && --n);
+ return (s);
+}
+
+/*
+ * Abort.
+ * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
+ * Sometimes called as a routine, to do general aborting of stuff.
+ */
+ctrlg(f, n)
+{
+ (*term.t_beep)();
+ if (kbdmip != NULL) {
+ kbdm[0] = (CTLX|')');
+ kbdmip = NULL;
+ }
+ mlwrite("[Aborted]");
+ return (ABORT);
+}
+
+/* tell the user that this command is illegal while we are in
+ VIEW (read-only) mode */
+
+rdonly()
+
+{
+ (*term.t_beep)();
+ mlwrite("[Key illegal in VIEW mode]");
+ return(FALSE);
+}
+
+meta() /* dummy function for binding to meta prefix */
+{
+}
+
+cex() /* dummy function for binding to control-x prefix */
+{
+}
+
+errexit()
+{
+#ifdef NOMAIN
+ longjmp(done, 1);
+#else
+ exit(1);
+#endif
+}
Added: clients/emacs/makefile
===================================================================
--- clients/emacs/makefile (rev 0)
+++ clients/emacs/makefile 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,79 @@
+# Makefile for MicroEMACS 3.7 for use with Forthmacs/386. To compile EMACS
+# for inclusion in the Zortech protected-mode loader (forth.exe), type:
+#
+# make objects
+#
+# It is also possible to compile MicroEMACS by itself, without including it
+# in the Forth loader. To do so, type:
+#
+# make emacs.exe
+#
+# If you make emacs.exe, you must re-make "objects" before attempting to
+# recompile the Forth loader (in the dos/zortech directory), because the
+# main.obj file is different when compiled for self-contained emacs.exe
+# than when compiled for use with Forth (in particular, it does not have a
+# main() routine when compiled for Forth - the Forth loader supplies main())
+
+CFLAGS= -mx -p
+CC= ztc
+LFLAGS= -mx
+LD= ztc
+
+HFILES= estruct.h edef.h efunc.h epath.h ebind.h evar.h
+
+OFILES= ansi.obj basic.obj bind.obj buffer.obj display.obj \
+ exec.obj file.obj fileio.obj ibmpc.obj \
+ input.obj isearch.obj line.obj lock.obj \
+ random.obj region.obj search.obj spawn.obj termio.obj \
+ window.obj word.obj
+
+config.h: config.zth
+ cp config.zth config.h
+
+objects: $(OFILES) config.h
+ $(CC) $(CFLAGS) -DNOMAIN -c main.c
+
+emacs.exe: $(OFILES)
+ $(CC) $(CFLAGS) -c main.c
+ $(LD) $(LFLAGS) -o $@ *.obj
+
+basic.obj: basic.c
+
+bind.obj: bind.c
+
+buffer.obj: buffer.c
+
+display.obj: display.c
+
+exec.obj: exec.c
+
+file.obj: file.c
+
+fileio.obj: fileio.c
+
+ibmpc.obj: ibmpc.c
+
+input.obj: input.c
+
+isearch.obj: isearch.c
+
+line.obj: line.c
+
+lock.obj: lock.c
+
+random.obj: random.c
+
+region.obj: region.c
+
+search.obj: search.c
+
+spawn.obj: spawn.c
+
+termio.obj: termio.c
+
+window.obj: window.c
+
+word.obj: word.c
+
+.C.OBJ:
+ $(CC) $(CFLAGS) -c $*
Added: clients/emacs/makefile.obp
===================================================================
--- clients/emacs/makefile.obp (rev 0)
+++ clients/emacs/makefile.obp 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,76 @@
+# Makefile for MicroEMACS 3.7 for use with Forthmacs/386. To compile EMACS
+# for inclusion in the Zortech protected-mode loader (forth.exe), type:
+#
+# make objects
+#
+# It is also possible to compile MicroEMACS by itself, without including it
+# in the Forth loader. To do so, type:
+#
+# make emacs.exe
+#
+# If you make emacs.exe, you must re-make "objects" before attempting to
+# recompile the Forth loader (in the dos/zortech directory), because the
+# main.obj file is different when compiled for self-contained emacs.exe
+# than when compiled for use with Forth (in particular, it does not have a
+# main() routine when compiled for Forth - the Forth loader supplies main())
+
+CFLAGS= -mx -p
+CC= ztc
+LFLAGS= -mx
+LD= ztc
+
+HFILES= estruct.h edef.h efunc.h epath.h ebind.h evar.h
+
+OFILES= ansi.obj basic.obj bind.obj buffer.obj display.obj \
+ exec.obj file.obj fileio.obj ibmpc.obj \
+ input.obj isearch.obj line.obj lock.obj \
+ random.obj region.obj search.obj spawn.obj termio.obj \
+ window.obj word.obj
+
+objects: $(OFILES)
+ $(CC) $(CFLAGS) -DNOMAIN -c main.c
+
+emacs.exe: $(OFILES)
+ $(CC) $(CFLAGS) -c main.c
+ $(LD) $(LFLAGS) -o $@ *.obj
+
+basic.obj: basic.c
+
+bind.obj: bind.c
+
+buffer.obj: buffer.c
+
+display.obj: display.c
+
+exec.obj: exec.c
+
+file.obj: file.c
+
+fileio.obj: fileio.c
+
+ibmpc.obj: ibmpc.c
+
+input.obj: input.c
+
+isearch.obj: isearch.c
+
+line.obj: line.c
+
+lock.obj: lock.c
+
+random.obj: random.c
+
+region.obj: region.c
+
+search.obj: search.c
+
+spawn.obj: spawn.c
+
+termio.obj: termio.c
+
+window.obj: window.c
+
+word.obj: word.c
+
+.C.OBJ:
+ $(CC) $(CFLAGS) -c $*
Added: clients/emacs/me.man
===================================================================
--- clients/emacs/me.man (rev 0)
+++ clients/emacs/me.man 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,810 @@
+From: sun!oliveb!hplabs!hp-pcd!craig
+Article 2071 of net.emacs:
+Relay-Version: version B 2.10.2 9/18/84 SMI; site sun.uucp
+Posting-Version: notesfiles - hp 1.2 08/01/83; site hp-pcd.UUCP
+Path: sun!oliveb!hplabs!hp-pcd!craig
+>From: craig(a)hp-pcd.UUCP (craig)
+Newsgroups: net.emacs
+Subject: Re: MicroEmacs manual
+Message-ID: <9900002(a)hpcvlo.UUCP>
+Date: 20 Jul 86 06:38:00 GMT
+Date-Received: 21 Jul 86 23:22:09 GMT
+References: <9900001(a)hpcvlo.UUCP>
+Organization: Hewlett-Packard - Corvallis, OR
+Lines: 583
+Nf-ID: #R:hpcvlo:9900001:hpcvlo:9900002:000:25482
+Nf-From: hpcvlo!craig Jul 19 22:38:00 1986
+
+
+ ME Documentation
+For the most part, read the Goslings or Unipress EMACS manuals.
+
+Soft keys and Function keys
+keyboard ME key Bound to
+ F1 ~1
+ F2 ~2
+ F3 ~3
+ F4 ~4
+ F5 ~5
+ F6 ~6
+ F7 ~7
+ F8 ~8
+ F9 ~9
+ F10 ~0
+ home ~A (mark-and-home)
+ end ~B (mark-and-end)
+ up arrow ~C (previous-line)
+ down arrow ~D (next-line)
+ right arrow ~E (forward-character)
+ left arrow ~F (backward-character)
+ insert ~G (center-cursor)
+ delete ~H (delete-char)
+ page up ~I (previous-page)
+ page down ~J (next-page)
+ clear line ~K (kill-line)
+ delete line ~L (delete-line)
+ insert line ~M (insert-line)
+ select ~N (set-mark)
+ roll up ~O (scroll-down)
+ roll down ~P (scroll-up)
+
+ ALT 0..9A..Z! mapped to META 0..9A..Z!
+ Use the ALT key like the control key (ie hold it down while you press the
+ next key).
+
+Anytime you are being queried on the message line the softkeys return
+their internal value. So if you want to bind F1, you can press F1
+when bind-to-key asks for a key.
+
+Case of letters:
+ Meta keys and Control X commands: next letter is ALWAYS uppercase.
+ Softkeys are case sensitive.
+
+TERMS
+args Parameters or arguments that will be requested by the command. If
+ [] surround the arg, then it will only be requested in certain cases.
+binding See bound.
+bound A key is attached or bound to a command or program. If the key is
+ pressed, whatever it is bound to is invoked.
+buffer A buffer is the internal workspace. If a buffer is visible, it is
+ shown through one or more windows. It is usually attached to a file (ie
+ contains the contents of the file). If the buffer is created by reading
+ in a file, the buffer name is created by removing the path from it (and
+ leaving only the name and extension).
+command A ME built in command such as (search-forward). These can be bound
+ to a key to make executing them easier.
+dot The place between two characters. It is immediately to the left of
+ the cursor. Also known as point. One per window or buffer.
+file
+ For MS-DOS, you can use forward slashes "/" as part of the path name.
+Kill buffer An invisible buffer that holds things created by
+ (kill-region) and (copy-region). Used to cut and paste or just paste.
+ If you want to move a block of text about: 1, set the mark at one end
+ and then move the dot to the other end. 2, kill the region. 3, move
+ the dot to the start of where you want the text to begin and 4, yank
+ the kill buffer. Bingo.
+ Copy and kill append to the kill buffer if last command was also a
+ kill or copy, otherwise the kill buffer is cleared before the new text
+ is entered.
+macro A sequence of keystrokes that can be replayed on command. Used
+ when you don't want to spend the time writing a program. Created by
+ going through the motions (which are actually done so you can verify
+ that what you want to happen is actually happening) (see (start-macro)
+ and (end-macro)). When replayed, the exact sequence you typed in is
+ reentered.
+mark A user settable dot. One per window or buffer.
+message line or
+minibuffer The bottom line of the screen. This is the
+ place where all questions are asked, error messages sent, etc.
+MUT The built in programming language. Refer to the MUT documentation.
+n Argument prefix (set by ^U). This means repeat the key (or what
+ its bound to) or command n times. If ^U is not used then n
+ defaults to 1.
+program A program created by (defun). Very few of these are builtin - most
+ of them are created by the user to make his editing easier.
+region The area between dot and mark.
+window A portion of the screen. A window provides a view of a buffer.
+ There can be more than one window showing a buffer. Windows are
+ separated from each by a mode line. Mode lines look like:
+ -* MicroEMACS -- buffer_name -- file_name ---------------
+ The * is present only if the buffer has been modified. The
+ file_name is present only if a file is associated with the buffer.
+word A string of letters, digits, "$" or "_".
+
+COMMAND default binding, args and comments
+(abort) ^G
+ Back out of anything.
+ If remembering a macro, forget it.
+ If executing a program, stop it.
+(apropos) $? args: keyword
+ List all commands and programs that have a keyword in them. For example,
+ if you apropos commands with "mark" in them you would get:
+ PROGRAMS:
+ mark-and-end ~B
+ mark-and-home ~A
+ COMMANDS:
+ exchange-dot-and-mark ^X^X
+ set-mark ^@ $SPACE ~N
+ On the left is the command name. On the right is the key(s) it is
+ bound to. So, in this case, (set-mark) is bound to control-@,
+ escape-space and softkey-N.
+ Command completion is on.
+ See also: (describe-bindings).
+
+(backward-character) ^B ~F (left arrow)
+ Move the dot backwards by a character.
+ See also: (forward-character).
+(backward-word) $B
+ Move backwards until dot is at the beginning of a word or beginning of
+ buffer.
+ Word is a digit, letter, "$" or "_".
+ See also: (delete-previous-word), (delete-next-word), (forward-word).
+(beginning-of-buffer) $<
+ Move the dot to the top of the buffer.
+ See also: (end-of-buffer), (mark-and-end), (mark-and-home).
+(beginning-of-line) ^A
+ Move the dot to the start of the line.
+ See also: (end-of-line).
+(bind-to-key) Not bound. args: command name, keystroke(s)
+ Attach a key to a command or program. When ever the key is pressed, the
+ command or program will be executed (except when a question is being
+ asked).
+ Possible keys are single key strokes, soft keys and double keystrokes.
+ Double keystrokes are prefixed keys. Prefix keys are: ^X
+ and escape (^[). They can be prefixed to any key except soft keys.
+ When asked for the key you can press the key(s) or enter the keycode.
+ Keycodes are ascii (ie no control characters and such) representations
+ of a key. For example, escape-D is represented by the 3 characters ^[D,
+ control-C by the 2 characters ^C and function key 1 (aka soft key 1) by
+ ~1. Keycodes should be used when programming to avoid screwing up
+ things like printers (when you print out the file).
+ eg (bind-to-key "foo" "~1")
+ Note: Always use uppercase for control keys.
+ Command completion is on.
+ See also: (defun).
+
+(case-region-lower) ^X^L
+ Convert a region to lower case.
+(case-region-upper) ^X^U
+ Convert a region to upper case.
+(case-word-capitalize) $C
+ Capitalize word after dot.
+ If dot is between words, searches forward to the start of the next word
+ and capitalizes that one.
+(case-word-lower) $L
+ Convert word to lower case.
+ If dot is between words, searches forward to the start of the next word
+ and lower case that one.
+(case-word-upper) $U
+ Convert word to upper case.
+ If dot is between words, searches forward to the start of the next word
+ and upper case that one.
+(center-cursor) ~G (insert)
+ Center the dot vertically in the current window.
+ Same as (arg-prefix 0) (reposition-window).
+ See also: (refresh-screen), (reposition-window).
+(completion) Not bound args: word to complete
+ Asks for a command, allows command completion and inserts the
+ command. The arg prefix selects the list to be completed
+ Selector: or the lists you want (default is 3 (system & program)).
+ bit value list
+ 0 1 system keywords
+ 1 2 program names
+ 2 4 MUT keywords
+ 3 8 buffer names
+(copy-region) $W
+ Copy a region to the kill buffer. If the last command was
+ a kill command, append to the kill buffer. The region is uneffected.
+ See also: (kill-region), (yank-from-killbuffer).
+
+(decompile) Not bound args: program name
+ Dump a program at the dot. It is ready to be recompiled
+ (with (execute-buffer) or (load)) but will need to be formatted before
+ you save it to a file.
+ Command completion is on.
+ See also: (defun).
+(delete-blank-lines) Not bound
+ Delete blank line above and below the dot. If the dot is not on a blank
+ line, this command does nothing. A blank line is one with nothing on
+ it (and that includes whitespace). Does not put deleted lines
+ in kill buffer.
+(delete-char) ^D or ~H (delete)
+ Delete the character after the dot (visually under the cursor). If at
+ the end of the line, the next line is joined to the current line. If
+ given an argument, deleted characters are put into the kill buffer.
+(delete-line) ~L (delete line)
+ Make a line disappear. Saved to the kill buffer.
+ Same as (beginning-of-line) (arg-prefix 1) (kill-line).
+(delete-next-word) $D
+ Delete a word. Save them in the kill buffer.
+(delete-other-windows) ^X1
+ Make the current window the only window on the screen.
+ See also: (split-window).
+(delete-previous-character) ^H or DEL
+ Delete the character before the dot (visually to the left of the cursor).
+ If at the beginning of the line, the current line is joined to the end
+ of the previous line. If given an argument, deleted characters are put
+ into the kill buffer.
+(delete-previous-word) $DEL or $^H
+ Delete the previous word. Save them in the kill buffer.
+(describe-bindings) Not bound
+ List all commands and programs along with their key bindings in the same
+ format as (apropos).
+ See also: (apropos).
+(describe-key) Not bound args: keystroke(s)
+ Tell what command a key is bound to. If n, inserts the command name.
+ For example, (describe-key "^A") returns "^A is bound to
+ beginning-of-line".
+ For MUT programmer types, a handy program is:
+ (defun "deref-key" ; surround a command with braces
+ {
+ (set-mark) (let-user-respond) (arg-prefix 1) ; get a key
+ (if (describe-key) ; if it is bound put braces around it
+ {
+ (insert-text ")") (exchange-dot-and-mark) (insert-text "(")
+ (exchange-dot-and-mark)
+ } {})
+ })
+ This allows programming using keys rather than remembering command
+ names.
+ See also: (completion), (apropos).
+
+(end-macro) ^X)
+ Stop remembering keystrokes. The keystrokes are stored in the macro
+ buffer ready to be replayed by (execute-macro).
+ See also: (execute-macro), (start-macro).
+(end-of-buffer) $>
+ Move the dot to the bottom of the buffer.
+ See also: (beginning-of-buffer), (mark-and-end), (mark-and-home).
+(end-of-line) ^E
+ Move the dot to the end of the line.
+ See also: (beginning-of-line).
+(enlarge-window) ^XZ
+ Enlarge the current window by a line.
+ See also: (shrink-window).
+(exchange-dot-and-mark) ^X^X
+ Move the dot to the mark and set the mark to old dot value. Visually,
+ move to where the mark was set. Repeating this command will undo it.
+ See also: (set-mark).
+(execute-buffer) Not bound args: buffer name
+ Execute cmds or MUT programs in a buffer. You can't execute the buffer you
+ are in (since if you changed the buffer you would change the program
+ which would probably tank ME). The dot will track the pc (program
+ counter) so, if there is an error, the dot will (hopefully) be right
+ after the error (when you switch to the buffer). If you are single
+ stepping, ^L will cause the code that is executing to be on screen
+ (assuming the buffer is on screen).
+ Command completion is on.
+ See also: (execute-line), (load), document on MUT programming.
+(execute-extended-command) $X args: command or program name
+ Execute a command or program. ie one of the things listed in this
+ document. When asked what to Execute: use the name as listed here
+ (without the "()"'s). eg Execute: execute-extended-command
+ Command completion is in effect.
+(execute-line) $$ args: MUT code
+ Execute one line of MUT code. eg (= HELP 0) or (bind-to-key "foo" "^F")
+ See also: (execute-buffer).
+(execute-macro) ^XE
+ Replay the keystrokes saved in the macro buffer.
+ See also: (start-macro), (end-macro).
+(execute-monitor-command) ^X! args: op sys command
+ Call the operating system to perform a command or run a program and then
+ return to editing.
+ MS-DOS example: To copy a file: (execute-monitor-command "copy foo bar")
+ To get a directory listing: (execute-monitor-command "ls").
+ See also: (spawn-cli).
+(exit) ^C or ^X^C args: [yes or no]
+ Exit emacs. If there is a modified buffer (one that has changed since it
+ was last saved), ask the user the user about it.
+ If n, quit no matter what and without making any noise.
+ See also: (quick-exit).
+
+(filter-region) Not bound args: filter name
+ Take a region and give to a filter as standard input.
+ Take the output of the filter and use it to replace the region.
+ For example: If the region is a paragraph and adjust is a program that
+ formats text then (filter-region "adjust") will replace the paragraph
+ with a formatted copy.
+ If you don't want to remove anything, just make a null region (set the
+ mark at the dot). eg (set-mark)(filter-region "ls") will insert a
+ directory listing at the dot.
+(forward-character) ^F or ~E (right arrow)
+ Move right a character.
+ See also: (backward-character).
+(forward-word) $F
+ Move forwards until dot is after the end of a word or end of buffer.
+ Word is a digit, letter, "$" or "_".
+ See also: (backward-word), (delete-previous-word), (delete-next-word).
+
+(goto-line) $G
+ Goto the nth line.
+
+(insert-file) ^X^I args: file name
+ Insert a file at the dot.
+ See also: (read-file), (visit-file), (write-file).
+(insert-line) ~M (insert line)
+ Same as (beginning-of-line) (open-line)
+
+(kill-buffer) ^XK args: buffer name, [yes or no]
+ Remove a buffer. It disappears into ness-ness land. Ask if the buffer
+ has been modified. If the buffer is the only one on the screen,
+ replace it with the (next-buffer). If it is the only buffer, replace
+ it with "main".
+ Defaults to the current buffer.
+ Command completion is on.
+ See also: (delete-other-windows).
+(kill-line) ^K or ~K (clear line)
+ Delete text from dot to the end of the line.
+ If an argument is given:
+ If n = 0: kill from beginning of line to dot.
+ If n > 0: kill forward over n newlines.
+ If n < 0: kill backword over n newlines.
+ The deleted text is put into the kill buffer or appended to the kill
+ buffer if the last command was also a kill command.
+ See also: (delete-next-word), (delete-previous-word),
+ (yank-from-killbuffer).
+(kill-region) ^W
+ Delete a region and save it in the kill buffer. If the last command was
+ a kill command, append to the kill buffer.
+ See also: (copy-region), (yank-from-killbuffer).
+
+(list-buffers) ^X^B
+ List all the buffers currently loaded. Magic buffers are not listed
+ (such as the list-buffers buffer).
+ C Size Buffer File
+ - ---- ------ ----
+ 933 init.mut ../init.mut
+ * 14287 me.doc me.doc
+ C is * if the buffer is modified. Size in bytes of the buffer or file.
+ File is the name of the file associated with a buffer.
+(load) Not bound args: file name
+ Load a file filled with MUT commands.
+ The file "init.mut" is loaded when ME is fired up (unless it does not
+ exist).
+ If the file is not in the current directory, it is looked
+ for in ME directory (pointed to by the ME environment variable). Note
+ that the ME var must end with a slash (eg ME=A:\foo\).
+ See also: (execute-buffer), (execute-line), document on MUT programming.
+(mark-and-end) ~B (end)
+ Same as (set-mark) (end-of-buffer).
+ See also: (beginning-of-buffer), (end-of-buffer), (mark-and-home).
+(mark-and-home) ~A (end)
+ Same as (set-mark) (beginning-of-buffer).
+ See also: (beginning-of-buffer), (end-of-buffer), (mark-and-end).
+
+(newline) ^M
+ Insert a newline before the dot (visually before the cursor).
+ See also: (newline-and-indent), (open-line).
+(newline-and-indent) ^J
+ Insert a newline before the dot and duplicate the indentation of the
+ previous line (the one the dot just left).
+ See also: (newline), (open-line).
+(next-buffer) Not bound
+ Replace the current buffer with the next buffer in the
+ buffer list. The buffer list is in alphabetical order.
+ See also: (list-buffers), (switch-to-buffer), (use-old-buffer).
+(next-line) ^N or ~D (down arrow)
+ Move the dot vertically down the screen. Trys to stay in the same
+ column.
+ See also: (previous-line).
+(next-page) ^V or ~J (page down)
+ Scroll forwards a page (window size -2).
+ See also: (previous-page).
+(next-window) ^XN
+ Move to the next window down the screen and make it the current window.
+ See Also: (previous-window)
+(not-modified) Not bound
+ Mark the current buffer as not modified. When this has been done,
+ (save-buffer) will not write out the file until further changes are
+ made, (exit) won't complain about modified buffer, etc.
+
+(open-line) ^O (oh, not zero)
+ Insert a newline after the dot. The dot does not move.
+ See also: (newline), (newline-and-indent).
+
+(previous-line) ^P or ~C (up arrow)
+ Move the dot vertically up the screen. Trys to stay in the same
+ column.
+ See also: (next-line).
+(previous-page) $V or ~I (page up)
+ Scroll backwards a page (window size -2).
+ See also: (next-page).
+(previous-window) ^XP
+ Move to the window immediately above the current window and make it the
+ current window.
+ See also: (next-window).
+
+(query-replace) $Q args: search string, replace string
+ Interactively search and replace strings. The mark is set at the point
+ where the search started and returned there after a successful
+ (query-replace).
+ <ESC>,n,N : No, don't replace. Go on to next match.
+ <SPACE>,y,Y : Yes, replace and go to next match.
+ ! : Replace all the rest without asking.
+ ^G : Abort. The command stops and the cursor is left where it is. To
+ get to the start of the query-replace, use (exchange-dot-and-mark).
+ Patterns are saved across searches. See (search-forward).
+ See also: (replace-string), (search-xxx).
+(quick-exit) Not bound args: [yes or no]
+ Write out the current buffer if it has changed, exit. If any modified
+ buffers exist, ask about them. If n, don't ask about modified buffers.
+ See also: (exit).
+(quote) ^Q or ^^ (control-^)
+ Insert the next character typed into the buffer. This is how to get
+ control characters and the like into the buffer.
+ Note: This is not much use with ALT keys or softkeys.
+
+(read-file) ^X^R args: file name, [yes or no]
+ Clear the current buffer (asking if the buffer has been modified) and read
+ in a file.
+ The file name defaults to the file name of the current buffer.
+ See also: (insert-file), (visit-file), (write-file).
+(refresh-screen) ^L
+ Repaint the screen. If n, then center the dot vertically in the window.
+ See also: (center-cursor), (reposition-window).
+(rename-buffer) Not bound args: new file name
+ Change the file name associated with the current buffer. If you want to
+ disassociate the buffer from a file, use a null response.
+ Command completion is on.
+(replace-string) $R args: search string, replace string
+ Search and replace string without asking.
+ Patterns are saved across searches. See (search-forward).
+ See also: (query-replace), (search-xxx).
+(reposition-window) $!
+ Move the current window so that the line the dot is on is n lines
+ from the top of the window.
+ If n<0, move the dot so that it is n lines from the bottom.
+ If n==0, the dot is centered vertically centered in the window.
+ See also: (center-cursor), (refresh-screen).
+
+(save-buffer) ^X^S
+ Write the current buffer to the file associated with it. Does not
+ do anything if the buffer is unmodified. If you want to force a write,
+ use (write-file).
+ See also: (write-file).
+(scroll-down) ^X^N or ~O (oh) (roll up)
+ Move the current window down by a line. Visually, the dot moves up the
+ screen.
+(scroll-up) ^X^P or ~P (roll down)
+ Move the current window up by a line. Visually, the dot moves down the
+ screen.
+(search-forward) ^\ or ^S args: search string
+(search-reverse) ^R args: search string
+ Search for a string.
+ CR ends patterns, LF (^J) => start of line.
+ The pattern is saved across searches. The pattern is also the
+ default search pattern for the replace commands. Whenever the
+ search pattern changes, the replace pattern is cleared (this is so
+ you can replace something with nothing).
+ (search-forward) The dot is after the last character matched.
+ (search-reverse) The dot is before the last character matched, or put
+ another way, to the left of the first character of the search string.
+ See also: (query-replace), (replace-string).
+(set-fill-column) ^XF
+ Sets the column at which wordwrap is attempted. Wordwrap is also turned
+ on. If no n the fill-column is set to the current column. If n==0,
+ turn off wordwrap.
+ See also: Note on wordwrap.
+(set-mark) ^@ or $SPACE or ~N (select)
+ Set the mark at the dot. Visually, under the cursor.
+ See also: (exchange-dot-and-mark).
+(show-position) ^X=
+ Show stats in the form:
+ Row=rrr Col=c Y=y CH=h .=dddd (x% of z) Unused=a
+ where Row is the buffer row, Col is screen column, Y is screen row, CH is
+ the character after the dot, . is the position of the dot (the number of
+ characters between the beginning-of-buffer and dot), x% percent of the
+ buffer is before the dot, z is the size of the buffer and Unused is how
+ much wasted space there is in the buffer.
+(shrink-window) ^X^Z
+ Shrink the current window by a line.
+ See also: (enlarge-window).
+(spawn-cli) ^_
+ Jump to the operating system (shell) for a while. ME is still loaded and
+ will sit in the background until you exit the shell (via exit in MS-DOS).
+ See also: (execute-monitor-command).
+(split-window) ^X2
+ Make 2 windows out of the current window. A window with less than 3
+ lines cannot be split.
+ See also: (delete-other-windows).
+(start-macro) ^X(
+ Start remembering keystrokes until (end-macro).
+ See also: (end-macro), (execute-macro).
+(switch-to-buffer) ^XB args: buffer name
+ Replace the current window with another buffer.
+ Command completion is on.
+ See also: (list-buffers), (next-buffer), (use-old-buffer).
+
+(tab) ^I or the tab key
+ Set tab stops or insert a tab.
+ If given an argument then set the tab stops to every nth column.
+ If n==0 use the tab character.
+ If n>1 use spaces to simulate the tab character.
+ If no argument then move to the next tab stop.
+(transpose-characters) ^T
+ Swaps the 2 characters on either side of the dot. If you want to change
+ "ab" to "ba" then put the cursor on the b and (transpose-characters).
+
+(use-old-buffer) ^X^O (oh) args: name of existing buffer
+ Replace the current window with a buffer that already exists.
+ Command completion is on.
+ See also: (list-buffers), (switch-to-buffer).
+
+(version) Not bound
+ Show the current version of ME.
+(visit-file) ^X^F or ^X^V args: file name
+ Split the current buffer. If the file (buffer) is already loaded, switch
+ to it. Otherwise, read in the file. The dot is set to the beginning of
+ the buffer and the mark is erased.
+ See also: (insert-file), (read-file), (write-file).
+
+(write-file) ^X^W args: file name
+ Write the current buffer to a file. If the file existed, it is
+ overwritten. If the file does not already exist, it is created.
+ The file name defaults to the file name of the current buffer.
+ See also: (insert-file), (read-file), (save-buffer), (visit-file).
+
+(yank-from-killbuffer) ^Y
+ Insert the contents of the killbuffer before the dot (visually before the
+ cursor). Does not affect the kill buffer.
+ The dot is left after the yanked text. The mark does not move.
+ See also: (copy-region), (kill-region).
+
+VAR COMMENTS
+HELP Set the help level. 0 => no help.
+
+Notes:
+If you are being asked a question:
+ Key bindings are not in effect. This means if have bound a normal key to
+ something by accident, you can unbind it without undo grief.
+ "Special" keys:
+ ^H or DEL Backspace.
+ ^G Abort out of the question. Also causes command to be aborted.
+ ^I Tab.
+ ^J Returns the code for newline. handy for searches.
+ ^M or return End the question.
+ ^U Erase everything and start over.
+ Control keys in general return the code for the key.
+ Function keys return the function key itself NOT what its bound to.
+
+ If you answer the question by hitting <return or enter> and the line is
+ empty, you have entered the null line zone. This can be interpreted as:
+ 1. An empty line. It will then be ignored or complained about or
+ stop the command.
+ 2. A ^M. (bind-to-key) does this.
+ 3. A request to the default. This is usually the current thing
+ being manipulated (where thing is buffer, file, etc).
+ eg (write-file) defaults to current file name and (kill-buffer)
+ defaults to current buffer name.
+
+Command completion is triggered by the SPACE key. Can be used if the
+ invoked command uses one of the lists that can be completed.
+ See also: (completion).
+
+Marks: If the mark is at the dot (ie where it is when the mark is set) and
+ do something (insert text, yank text, etc), it is done between the dot
+ and mark, that is, the mark is before the change and the dot after.
+
+Word wrap: Setting the (set-fill-column)>0 turns it on, 0 turns it off.
+ When you are typing at the end of a line and cross the fill column
+ the last "word" is wrapped to the next line. If have some left
+ margin you wish to preserve, bind CR to newline-and-indent
+ (bind-to-key "newline-and-indent" "^M").
+
+What me does not have that emacs does (partial list):
+* file name completion
+* local key bindings
+* over write mode
+* recursive editing
+* regular expressions
+bunch more
+
+
+From: sun!oliveb!hplabs!hp-pcd!craig
+Article 2072 of net.emacs:
+Relay-Version: version B 2.10.2 9/18/84 SMI; site sun.uucp
+Posting-Version: notesfiles - hp 1.2 08/01/83; site hp-pcd.UUCP
+Path: sun!oliveb!hplabs!hp-pcd!craig
+>From: craig(a)hp-pcd.UUCP (craig)
+Newsgroups: net.emacs
+Subject: Re: MicroEmacs manual
+Message-ID: <9900003(a)hpcvlo.UUCP>
+Date: 20 Jul 86 06:38:00 GMT
+Date-Received: 21 Jul 86 23:22:53 GMT
+References: <9900001(a)hpcvlo.UUCP>
+Organization: Hewlett-Packard - Corvallis, OR
+Lines: 189
+Nf-ID: #R:hpcvlo:9900001:hpcvlo:9900003:000:6422
+Nf-From: hpcvlo!craig Jul 19 22:38:00 1986
+
+
+ MICROEMACS COMMAND SUMMARY
+ Note: n means argument prefix (set by ^U).
+ dot is current cursor position.
+ ^@ Set mark at current position (dot).
+ ^A Move cursor to beginning of line.
+ ^B Move cursor back one character.
+ ^C Exit without saving buffers (same as ^x^C).
+ ^D Delete current character. If n then save to kill buffer.
+ ^E Move cursor to end of line.
+ ^F Move cursor forward one character.
+ ^G Abort any command. (shades of Teco).
+ ^H (backspace) Delete previous character.
+ If n, save to kill buffer.
+ ^I Tab. If n = 0 use tab. If n>1, set tab stops & use blanks.
+ ^J Newline and match indent of previous line.
+ ^K Kill (delete) to end of line.
+ If n = 0: kill from begining of line to dot.
+ If n > 0: kill forward over n newlines.
+ If n < 0: kill backword over n newlines.
+ ^L Redisplay screen. If n, center cursor.
+ ^M Carriage return.
+ ^N Move cursor to next line.
+ ^O Open a new line.
+ ^P Move to previous line.
+ ^Q Quote the next character (insert the next character typed).
+ ^R Reverse search.
+ ^S Forward search.
+ ^T Transpose characters.
+ ^U Enter repeat count for next command (set n).
+ ^V View the next screen (scroll up one screen).
+ ^W Kill region (all text between cursor and last mark set).
+ ^Y Yank (undelete) last text killed (deleted).
+ ^_ Push to a new interactive command shell.
+ ^^ Quote the next character (same as ^Q).
+ ^\ Forward search (same as ^S).
+
+ ^x! Fork a command.
+ ^x( Begin keyboard macro.
+ ^x) End keyboard macro.
+ ^x= Show current position.
+ ^x1 Display only current window.
+ ^x2 Split the current window.
+ ^xB Prompt for new buffer. If given n, buffer must exist.
+ ^xE Execute keyboard macro.
+ ^xF Set fill column (for word wrap).
+ If n, set to n else set to current column.
+ if n = 0, turn off word wrap.
+ ^xK Kill a buffer.
+ ^xN Move to next window.
+ ^xP Move to previous window.
+ ^xZ Enlarge current window by n lines.
+
+ ^x^B Show active buffers.
+ ^x^C Exit without saving buffers.
+ ^x^F Visit file.
+ ^x^G Abort.
+ ^x^I Insert file at dot.
+ ^x^L Lower case region.
+ ^x^N Scroll current window up by n lines.
+ ^x^O Use old buffer. Same as ^U^xB
+ ^x^P Scroll current window down by n lines.
+ ^x^R Read file into current buffer. Defaults to current file name.
+ ^x^S Save (write) current buffer to its file.
+ Only writes if changed.
+ ^x^U Uppercase region.
+ ^x^V Visit a file. Read file and display in current window.
+ ^x^W Write buffer to file. Defaults to current file name.
+ Always writes.
+ ^x^X Swap dot and mark.
+ ^x^Z Reduce current window by n lines.
+
+ <del> delete previous character.
+
+ $! Move current line to n lines from top of window.
+ if n = 0 center cursor.
+ $$ Execute-line.
+ $<space> Set mark.
+ $< Move cursor to beginning of buffer.
+ $> Move cursor to end of buffer.
+ $? List all commands that have keyword in them.
+ $1, $2, $3, $4, $5, $6, $7, $8, $9
+ Enter n for next command (like ^U).
+ $B Move cursor back one word.
+ $C Capitalize word.
+ $D Delete next word.
+ $<del> Delete previous word.
+ $F Move cursor forward one word.
+ $G Move cusor to line specified by n.
+ $^G Abort.
+ $L Lowercase next word.
+ $Q Query replace. Mark is set to begining of search.
+ $U Uppercase next word.
+ $V View the previous screen (scroll down one screen).
+ $W Copy region to kill buffer.
+ $X Execute meta command (such as goto-line). Command
+ completation when SPACE typed.
+
+ COMMAND BINDING
+ PROGRAMS:
+ center-cursor ~G
+ delete-line ~L
+ insert-line ~M
+ mark-and-end ~B
+ mark-and-home ~A
+ COMMANDS:
+ abort ^G
+ apropos $?
+ backward-character ^B ~F
+ backward-word $B
+ beginning-of-buffer $<
+ beginning-of-line ^A
+ bind-to-key Not bound
+ case-region-lower ^X^L
+ case-region-upper ^X^U
+ case-word-capitalize $C
+ case-word-lower $L
+ case-word-upper $U
+ completion Not bound
+ copy-region $W
+ decompile Not bound
+ delete-blank-lines Not bound
+ delete-char ^D ~H
+ delete-next-word $D
+ delete-other-windows ^X1
+ delete-previous-character ^H DEL
+ delete-previous-word $DEL $^H
+ describe-bindings Not bound
+ describe-key Not bound
+ end-macro ^X)
+ end-of-buffer $>
+ end-of-line ^E
+ enlarge-window ^XZ
+ exchange-dot-and-mark ^X^X
+ execute-buffer Not bound
+ execute-extended-command $X
+ execute-line $^[
+ execute-macro ^XE
+ execute-monitor-command ^X!
+ exit ^C ^X^C
+ filter-region Not bound
+ forward-character ^F ~E
+ forward-word $F
+ goto-line $G
+ insert-file ^X^I
+ kill-buffer ^XK
+ kill-line ^K ~K
+ kill-region ^W
+ list-buffers ^X^B
+ load Not bound
+ newline ^M
+ newline-and-indent ^J
+ next-buffer Not bound
+ next-line ^N ~D
+ next-page ^V ~J
+ next-window ^XN
+ not-modified Not bound
+ open-line ^O
+ previous-line ^P ~C
+ previous-page $V ~I
+ previous-window ^XP
+ query-replace $Q
+ quick-exit Not bound
+ quote ^^ ^Q
+ read-file ^X^R
+ refresh-screen ^L
+ rename-buffer Not bound
+ replace-string $R
+ reposition-window $!
+ save-buffer ^X^S
+ scroll-down ^X^N ~O
+ scroll-up ^X^P ~P
+ search-forward ^\ ^S
+ search-reverse ^R
+ set-fill-column ^XF
+ set-mark ^@ $SPACE ~N
+ show-position ^X=
+ shrink-window ^X^Z
+ spawn-cli ^_
+ split-window ^X2
+ start-macro ^X(
+ switch-to-buffer ^XB
+ tab ^I
+ transpose-characters ^T
+ use-old-buffer ^X^O
+ version Not bound
+ visit-file ^X^F ^X^V
+ write-file ^X^W
+ yank-from-killbuffer ^Y
+
+
Added: clients/emacs/menu.cmd
===================================================================
--- clients/emacs/menu.cmd (rev 0)
+++ clients/emacs/menu.cmd 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,629 @@
+; MENU.CMD: Menu learning system for MicroEMACS 3.7
+;
+; This file is executed to activate MicroEMACS's
+; menu interface code
+
+; setup windows for use
+
+ add-global-mode "blue"
+ 1 split-current-window
+ 5 resize-window
+ add-mode "red"
+ view-file "menu1"
+ name-buffer "menu window"
+ change-file-name ""
+ add-mode "view"
+ next-window
+
+; Load menu routines as needed
+
+; Activate Main Menu
+
+1 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<01"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key execute-macro-3 FN;
+ bind-to-key execute-macro-4 FN<
+ bind-to-key execute-macro-5 FN=
+ bind-to-key execute-macro-6 FN>
+ bind-to-key execute-macro-7 FN?
+ bind-to-key execute-macro-8 FN@
+ bind-to-key execute-macro-9 FNA
+ bind-to-key execute-macro-2 FNB
+ bind-to-key execute-macro-10 FNC
+ bind-to-key exit-emacs FND
+ clear-message-line
+[end]
+
+; and bring that menu up
+
+ execute-macro-1
+ write-message " [loading MENU system]"
+
+; set up the editor control menu
+
+2 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<02"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key execute-macro-11 FN;
+ bind-to-key execute-macro-12 FN<
+ bind-to-key execute-macro-13 FN=
+ bind-to-key execute-macro-14 FN>
+ bind-to-key execute-macro-15 FN?
+ bind-to-key execute-macro-16 FN@
+ bind-to-key execute-macro-17 FNA
+ bind-to-key execute-macro-18 FNB
+ bind-to-key execute-macro-19 FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate word case/screen control Menu
+
+3 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<03"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key case-word-upper FN;
+ bind-to-key case-region-upper FN<
+ bind-to-key case-word-lower FN=
+ bind-to-key case-region-lower FN>
+ bind-to-key case-word-capitalize FN?
+ unbind-key FN@
+ bind-to-key clear-and-redraw FNA
+ bind-to-key set-mark FNB
+ bind-to-key redraw-display FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate paging/scrolling Menu
+
+4 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<08"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key previous-page FN;
+ bind-to-key next-page FN<
+ bind-to-key move-window-down FN=
+ bind-to-key move-window-up FN>
+ bind-to-key scroll-next-up FN?
+ unbind-key FN@
+ bind-to-key scroll-next-down FNA
+ unbind-key FNB
+ bind-to-key exchange-point-and-mark FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate cut & paste Menu
+
+5 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<04"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key set-mark FN;
+ unbind-key FN<
+ bind-to-key kill-region FN=
+ unbind-key FN>
+ bind-to-key copy-region FN?
+ unbind-key FN@
+ bind-to-key yank FNA
+ unbind-key FNB
+ unbind-key FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate Search & replace Menu
+
+6 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<09"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key search-forward FN;
+ bind-to-key search-reverse FN<
+ bind-to-key hunt-forward FN=
+ bind-to-key hunt-backward FN>
+ bind-to-key incremental-search FN?
+ bind-to-key reverse-incremental-search FN@
+ bind-to-key replace-string FNA
+ bind-to-key query-replace-string FNB
+ unbind-key FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate Deletion Menu
+
+7 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<05"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key delete-previous-character FN;
+ unbind-key FN<
+ bind-to-key delete-next-character FN=
+ unbind-key FN>
+ bind-to-key kill-to-end-of-line FN?
+ unbind-key FN@
+ bind-to-key delete-blank-lines FNA
+ unbind-key FNB
+ unbind-key FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate Word procesing Menu
+
+8 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<10"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key previous-word FN;
+ bind-to-key next-word FN<
+ bind-to-key previous-paragraph FN=
+ bind-to-key next-paragraph FN>
+ bind-to-key fill-paragraph FN?
+ bind-to-key kill-paragraph FN@
+ bind-to-key delete-previous-word FNA
+ bind-to-key delete-next-word FNB
+ bind-to-key count-words FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate Insertion Menu
+
+9 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<06"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key open-line FN;
+ bind-to-key insert-string FN<
+ bind-to-key handle-tab FN=
+ bind-to-key quote-character FN>
+ bind-to-key insert-space FN?
+ bind-to-key transpose-characters FN@
+ bind-to-key newline-and-indent FNA
+ unbind-key FNB
+ bind-to-key newline FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+; Activate Cursor movement Menu
+
+10 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<07"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key begining-of-file FN;
+ bind-to-key previous-line FN<
+ bind-to-key backward-character FN=
+ bind-to-key forward-character FN>
+ bind-to-key end-of-file FN?
+ bind-to-key next-line FN@
+ bind-to-key begining-of-line FNA
+ bind-to-key end-of-line FNB
+ bind-to-key execute-macro-21 FNC
+ bind-to-key execute-macro-1 FND
+ clear-message-line
+[end]
+
+21 store-macro
+ "@Line number to go to: " goto-line
+[end]
+
+; Activate Buffer Menu
+
+11 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<11"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key buffer-position FN;
+ bind-to-key unmark-buffer FN<
+ bind-to-key delete-buffer FN=
+ bind-to-key next-buffer FN>
+ bind-to-key list-buffers FN?
+ bind-to-key execute-macro-22 FN@
+ bind-to-key name-buffer FNA
+ unbind-key FNB
+ bind-to-key select-buffer FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+22 store-macro
+ filter-buffer "@Name of DOS filter: "
+[end]
+; Macro Menu
+
+12 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<11"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key begin-macro FN;
+ unbind-key FN<
+ bind-to-key end-macro FN=
+ unbind-key FN>
+ bind-to-key execute-macro FN?
+ unbind-key FN@
+ unbind-key FNA
+ unbind-key FNB
+ unbind-key FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+; Color change Menu
+
+13 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<12"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key execute-macro-23 FN;
+ unbind-key FN<
+ bind-to-key execute-macro-24 FN=
+ unbind-key FN>
+ bind-to-key execute-macro-25 FN?
+ unbind-key FN@
+ bind-to-key execute-macro-26 FNA
+ unbind-key FNB
+ unbind-key FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+; Set forground color
+
+23 store-macro
+ save-window
+ 1 next-window
+ select-buffer "[color]"
+ begining-of-file
+ insert-string "@Color to change to: "
+ newline
+ begining-of-file
+ case-word-upper
+ begining-of-file
+ unmark-buffer
+ select-buffer "menu window"
+ 1 redraw-display
+ restore-window
+ add-mode "#[color]"
+ delete-buffer "[color]"
+[end]
+
+; Set background color
+
+24 store-macro
+ save-window
+ 1 next-window
+ select-buffer "[color]"
+ begining-of-file
+ insert-string "@Color to change to: "
+ newline
+ begining-of-file
+ case-word-lower
+ begining-of-file
+ unmark-buffer
+ select-buffer "menu window"
+ 1 redraw-display
+ restore-window
+ add-mode "#[color]"
+ delete-buffer "[color]"
+[end]
+
+; Set global forground color
+
+25 store-macro
+ save-window
+ 1 next-window
+ select-buffer "[color]"
+ begining-of-file
+ insert-string "@Color to change to: "
+ newline
+ begining-of-file
+ case-word-upper
+ begining-of-file
+ unmark-buffer
+ select-buffer "menu window"
+ 1 redraw-display
+ restore-window
+ add-global-mode "#[color]"
+ delete-buffer "[color]"
+[end]
+
+; Set global background color
+
+26 store-macro
+ save-window
+ 1 next-window
+ select-buffer "[color]"
+ begining-of-file
+ insert-string "@Color to change to: "
+ newline
+ begining-of-file
+ case-word-lower
+ begining-of-file
+ unmark-buffer
+ select-buffer "menu window"
+ 1 redraw-display
+ restore-window
+ add-global-mode "#[color]"
+ delete-buffer "[color]"
+[end]
+
+; set Mode Menu
+
+14 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<17"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key add-mode FN;
+ bind-to-key add-global-mode FN<
+ bind-to-key delete-mode FN=
+ bind-to-key delete-global-mode FN>
+ unbind-key FN?
+ bind-to-key execute-macro-27 FN@
+ unbind-key FNA
+ unbind-key FNB
+ bind-to-key select-buffer FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+27 store-macro
+ "@Column to fill to: " set-fill-column
+[end]
+
+; DOS command Menu
+
+15 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<13"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key shell-command FN;
+ unbind-key FN<
+ bind-to-key pipe-command FN=
+ unbind-key FN>
+ bind-to-key i-shell FN?
+ unbind-key FN@
+ bind-to-key quick-exit FNA
+ unbind-key FNB
+ bind-to-key exit-emacs FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+; Script Menu
+
+16 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<18"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key execute-file FN;
+ bind-to-key execute-command-line FN<
+ bind-to-key execute-buffer FN=
+ bind-to-key execute-named-command FN>
+ unbind-key FN?
+ unbind-key FN@
+ unbind-key FNA
+ unbind-key FNB
+ unbind-key FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+; File access Menu
+
+17 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<14"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key find-file FN;
+ bind-to-key save-file FN<
+ bind-to-key view-file FN=
+ bind-to-key write-file FN>
+ bind-to-key read-file FN?
+ bind-to-key change-file-name FN@
+ bind-to-key insert-file FNA
+ unbind-key FNB
+ unbind-key FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+; Window Menu
+
+18 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<19"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key split-current-window FN;
+ bind-to-key delete-other-windows FN<
+ bind-to-key resize-window FN=
+ bind-to-key delete-window FN>
+ bind-to-key shrink-window FN?
+ bind-to-key grow-window FN@
+ bind-to-key next-window FNA
+ bind-to-key previous-window FNB
+ unbind-key FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+; key binding Menu
+
+19 store-macro
+ save-window
+ 1 next-window
+ begining-of-file
+ search-forward "<<15"
+ next-line
+ 1 redraw-display
+ restore-window
+ update-screen
+
+; ***** Rebind the Function key group
+
+ bind-to-key bind-to-key FN;
+ unbind-key FN<
+ bind-to-key unbind-key FN=
+ unbind-key FN>
+ bind-to-key describe-key FN?
+ unbind-key FN@
+ bind-to-key describe-bindings FNA
+ unbind-key FNB
+ unbind-key FNC
+ bind-to-key execute-macro-2 FND
+ clear-message-line
+[end]
+
+ clear-message-line
Added: clients/emacs/menu1
===================================================================
--- clients/emacs/menu1 (rev 0)
+++ clients/emacs/menu1 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,115 @@
+--<<01>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 WORD CASE/SCREEN CONTROL F2 PAGING/SCROLLING
+[Main Menu] F3 CUT & PASTE F4 SEARCH AND REPLACE
+ F5 DELETION COMMANDS F6 WORD PROCESSING
+ F7 INSERTION COMMANDS F8 EDITOR CONTROL
+ 06/18/86 F9 CURSOR MOVEMENT F10 exit MicroEMACS
+--<<02>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 BUFFER CONTROL F2 MACROS
+[Editor control] F3 COLOR CHANGES F4 MODES
+ F5 DOS COMMANDS F6 SCRIPTS
+ F7 FILE ACCESS F8 WINDOWS
+ F9 KEY BINDINGS F10 exit to MAIN MENU
+--<<03>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 upper case a word F2 upper case a region
+ Word case & F3 lower case a word F4 lower case a region
+ Screen control F5 capitilize a word
+ F7 redraw the screen F8 mark a region
+ F9 center the current line F10 exit to MAIN MENU
+--<<04>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 mark a region
+ Cut & Paste F3 delete the region
+ F5 copy the region to the kill buffer
+ F7 insert the kill buffer into the text here
+ F10 exit to MAIN MENU
+--<<05>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 delete the last character
+ Deletions F3 delete the next character
+ F5 delete to the end of the current line
+ F7 delete all the blank lines around the cursor
+ F10 exit to MAIN MENU
+--<<06>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 open a blank line F2 insert a prompted string
+ Insertion F3 insert a tab F4 quote the next character
+ F5 insert a space F6 transpose last 2 chars
+ F7 insert a newline and indent like the last line
+ F9 insert a newline F10 exit to MAIN MENU
+--<<07>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 begining of the file F2 up one line
+ Cursor Movement F3 left F4 right
+ F^2 F5 end of the file F6 down one line
+ F3 < + > F4 F7 begining of line F8 end of line
+ FV6 F9 goto line F10 exit to MAIN MENU
+--<<08>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 go up one page F2 go down one page
+ Paging and F3 scroll the screen up F4 scroll the screen down
+ Scrolling F5 make the next widow go up one page
+ F7 make the next window go down one page
+ F9 exchange cursor & mark F10 exit to MAIN MENU
+--<<09>>-----------------------------------------------------------------------
+MicroEMACS 3.7 f1 search forward f2 seach backwards
+ Search and F3 hunt forward f4 hunt backwards
+ Replace F5 isearch forward F6 isearch backward
+ F7 replace string F8 replace string w/query
+ F10 exit to MAIN MENU
+--<<10>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 go back a word F2 go forward a word
+ Word processing F3 go back a paragraph F4 go forward a paragraph
+ F5 fill paragraph F6 delete current paragraph
+ F7 delete last word F8 delete next word
+ F9 count words in region F10 exit to MAIN MENU
+--<<11>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 report position F2 unmark buffer
+ Buffer Control F3 delete buffer F4 switch to next buffer
+ F5 list all buffers F6 filter buffer through
+ F7 rename current buffer DOS program
+ F9 select buffer F10 exit to CONTROL MENU
+--<<12>>-----------------------------------------------------------------------
+MicroEMACS 3.7 Colors: | F1 current window's forground color
+ Color changes Black Magenta | F3 current window's background color
+ Blue Cyan | F5 global forground color
+ Red Yellow | F7 global background color
+ Green White | F10 exit to CONTROL MENU
+--<<13>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 execute one DOS command
+ DOS commands F3 pipe one DOS command to a buffer
+ F5 shell up to a new command interpeter
+ F7 QUICK exit (write out all changed buffers and exit)
+ F9 exit MicroEMACS F10 exit to CONTROL MENU
+--<<14>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 find file F2 save current file
+ File Access F3 view file (in VIEW mode) F4 write file w/ new name
+ F5 read file into buffer F6 change current file name
+ F7 insert file into buffer
+ F10 exit to CONTROL MENU
+--<<15>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 bind a function to a key
+ Key Bindings F3 unbind a key
+ F5 describe a key
+ F7 describe all bindings
+ F10 exit to CONTROL MENU
+--<<16>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 define macro The keyboard macro only works
+ Keyboard Macro F3 end macro for standard commands, NOT for
+ F5 execute macro menu selections.
+
+ F10 exit to CONTROL MENU
+--<<17>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 set mode F2 set global mode
+ Modes F3 delete mode F4 delete global mode
+ Standard modes are: F6 set fill column
+ WRAP VIEW CMODE EXACT OVER MAGIC
+ F10 exit to CONTROL MENU
+--<<18>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 execute script file F2 execute script line
+ Script F3 execute script in buffer F4 execute command (by name)
+ Script line format:
+ {<repeat count>} <command name> {<argument(s)> | "<argument(s)>"}
+ F10 exit to CONTROL MENU
+--<<19>>-----------------------------------------------------------------------
+MicroEMACS 3.7 F1 split current window F2 delete all other windows
+ Windows F3 resize window F4 delete current window
+ F5 shrink window F6 enlarge window
+ F7 next window F8 previous window
+ F10 exit to CONTROL MENU
+-------------------------------------------------------------------------------
Added: clients/emacs/ofwtermio.c
===================================================================
--- clients/emacs/ofwtermio.c (rev 0)
+++ clients/emacs/ofwtermio.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,67 @@
+/*
+ * The functions in this file negotiate with the operating system for
+ * characters, and write characters in a barely buffered fashion on the display.
+ * All operating systems.
+ */
+
+#include "estruct.h"
+#include "edef.h"
+#include "stdio.h"
+
+/*
+ * This function is called once to set up the terminal device streams.
+ */
+ttopen()
+{
+ /* on all screens we are not sure of the initial position
+ of the cursor */
+ ttrow = 999;
+ ttcol = 999;
+}
+
+/*
+ * This function gets called just before we go back home to the command
+ * interpreter. It can be used to put the terminal back in a reasonable state.
+ */
+ttclose()
+{
+}
+
+/*
+ * Write a character to the display.
+ */
+ttputc(c)
+ char c;
+{
+ fputc(c, stdout);
+}
+
+/*
+ * Flush terminal buffer. Does real work where the terminal output is buffered
+ * up. A no-operation on systems where byte at a time terminal I/O is done.
+ */
+ttflush()
+{
+ fflush(stdout);
+}
+
+/*
+ * Read a character from the terminal, performing no editing and doing no echo
+ * at all.
+ */
+ttgetc()
+{
+ return(fgetc(stdin));
+}
+
+#if TYPEAH
+/* typahead: Check to see if any characters are already in the
+ keyboard buffer
+*/
+
+typahead()
+{
+ return(FALSE);
+}
+#endif
+
Added: clients/emacs/random.c
===================================================================
--- clients/emacs/random.c (rev 0)
+++ clients/emacs/random.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,739 @@
+/*
+ * This file contains the command processing functions for a number of random
+ * commands. There is no functional grouping here, for sure.
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+int tabsize; /* Tab size (0: use real tabs) */
+
+/*
+ * Set fill column to n.
+ */
+setfillcol(f, n)
+{
+ fillcol = n;
+ mlwrite("[Fill column is %d]",n);
+ return(TRUE);
+}
+
+/*
+ * Display the current position of the cursor, in origin 1 X-Y coordinates,
+ * the character that is under the cursor (in hex), and the fraction of the
+ * text that is before the cursor. The displayed column is not the current
+ * column, but the column that would be used on an infinite width display.
+ * Normally this is bound to "C-X =".
+ */
+showcpos(f, n)
+{
+ register LINE *lp; /* current line */
+ register long numchars; /* # of chars in file */
+ register int numlines; /* # of lines in file */
+ register long predchars; /* # chars preceding point */
+ register int predlines; /* # lines preceding point */
+ register int curchar; /* character under cursor */
+ int ratio;
+ int col;
+ int savepos; /* temp save for current offset */
+ int ecol; /* column pos/end of current line */
+
+ /* starting at the begining of the buffer */
+ lp = lforw(curbp->b_linep);
+
+ /* start counting chars and lines */
+ numchars = 0;
+ numlines = 0;
+ while (lp != curbp->b_linep) {
+ /* if we are on the current line, record it */
+ if (lp == curwp->w_dotp) {
+ predlines = numlines;
+ predchars = numchars + curwp->w_doto;
+ if ((curwp->w_doto) == llength(lp))
+ curchar = '\n';
+ else
+ curchar = lgetc(lp, curwp->w_doto);
+ }
+ /* on to the next line */
+ ++numlines;
+ numchars += llength(lp) + 1;
+ lp = lforw(lp);
+ }
+
+ /* if at end of file, record it */
+ if (curwp->w_dotp == curbp->b_linep) {
+ predlines = numlines;
+ predchars = numchars;
+ }
+
+ /* Get real column and end-of-line column. */
+ col = getccol(FALSE);
+ savepos = curwp->w_doto;
+ curwp->w_doto = llength(curwp->w_dotp);
+ ecol = getccol(FALSE);
+ curwp->w_doto = savepos;
+
+ ratio = 0; /* Ratio before dot. */
+ if (numchars != 0)
+ ratio = (100L*predchars) / numchars;
+
+ /* summarize and report the info */
+ mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x",
+ predlines+1, numlines+1, col, ecol,
+ predchars, numchars, ratio, curchar);
+ return (TRUE);
+}
+
+/*
+ * Return current column. Stop at first non-blank given TRUE argument.
+ */
+getccol(bflg)
+int bflg;
+{
+ register int c, i, col;
+ col = 0;
+ for (i=0; i<curwp->w_doto; ++i) {
+ c = lgetc(curwp->w_dotp, i);
+ if (c!=' ' && c!='\t' && bflg)
+ break;
+ if (c == '\t')
+ col |= 0x07;
+ else if (c<0x20 || c==0x7F)
+ ++col;
+ ++col;
+ }
+ return(col);
+}
+
+/*
+ * Twiddle the two characters on either side of dot. If dot is at the end of
+ * the line twiddle the two characters before it. Return with an error if dot
+ * is at the beginning of line; it seems to be a bit pointless to make this
+ * work. This fixes up a very common typo with a single stroke. Normally bound
+ * to "C-T". This always works within a line, so "WFEDIT" is good enough.
+ */
+twiddle(f, n)
+{
+ register LINE *dotp;
+ register int doto;
+ register int cl;
+ register int cr;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ dotp = curwp->w_dotp;
+ doto = curwp->w_doto;
+ if (doto==llength(dotp) && --doto<0)
+ return (FALSE);
+ cr = lgetc(dotp, doto);
+ if (--doto < 0)
+ return (FALSE);
+ cl = lgetc(dotp, doto);
+ lputc(dotp, doto+0, cr);
+ lputc(dotp, doto+1, cl);
+ lchange(WFEDIT);
+ return (TRUE);
+}
+
+/*
+ * Quote the next character, and insert it into the buffer. All the characters
+ * are taken literally, with the exception of the newline, which always has
+ * its line splitting meaning. The character is always read, even if it is
+ * inserted 0 times, for regularity. Bound to "C-Q"
+ */
+quote(f, n)
+{
+ register int s;
+ register int c;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ c = (*term.t_getchar)();
+ if (n < 0)
+ return (FALSE);
+ if (n == 0)
+ return (TRUE);
+ if (c == '\n') {
+ do {
+ s = lnewline();
+ } while (s==TRUE && --n);
+ return (s);
+ }
+ return (linsert(n, c));
+}
+
+/*
+ * Set tab size if given non-default argument (n <> 1). Otherwise, insert a
+ * tab into file. If given argument, n, of zero, change to true tabs.
+ * If n > 1, simulate tab stop every n-characters using spaces. This has to be
+ * done in this slightly funny way because the tab (in ASCII) has been turned
+ * into "C-I" (in 10 bit code) already. Bound to "C-I".
+ */
+tab(f, n)
+{
+ if (n < 0)
+ return (FALSE);
+ if (n == 0 || n > 1) {
+ tabsize = n;
+ return(TRUE);
+ }
+ if (! tabsize)
+ return(linsert(1, '\t'));
+ return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
+}
+
+/*
+ * Open up some blank space. The basic plan is to insert a bunch of newlines,
+ * and then back up over them. Everything is done by the subcommand
+ * procerssors. They even handle the looping. Normally this is bound to "C-O".
+ */
+openline(f, n)
+{
+ register int i;
+ register int s;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ if (n == 0)
+ return (TRUE);
+ i = n; /* Insert newlines. */
+ do {
+ s = lnewline();
+ } while (s==TRUE && --i);
+ if (s == TRUE) /* Then back up overtop */
+ s = backchar(f, n); /* of them all. */
+ return (s);
+}
+
+/*
+ * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
+ * indentation as specified.
+ */
+newline(f, n)
+{
+ register int s;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+
+ /* if we are in C mode and this is a default <NL> */
+ if (n == 1 && (curbp->b_mode & MDCMOD) &&
+ curwp->w_dotp != curbp->b_linep)
+ return(cinsert());
+
+ /* insert some lines */
+ while (n--) {
+ if ((s=lnewline()) != TRUE)
+ return (s);
+ }
+ return (TRUE);
+}
+
+cinsert() /* insert a newline and indentation for C */
+
+{
+ register char *cptr; /* string pointer into text to copy */
+ register int tptr; /* index to scan into line */
+ register int bracef; /* was there a brace at the end of line? */
+ register int i;
+ char ichar[NSTRING]; /* buffer to hold indent of last line */
+
+ /* grab a pointer to text to copy indentation from */
+ cptr = &curwp->w_dotp->l_text[0];
+
+ /* check for a brace */
+ tptr = curwp->w_doto - 1;
+ bracef = (cptr[tptr] == '{');
+
+ /* save the indent of the previous line */
+ i = 0;
+ while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
+ && (i < NSTRING - 1)) {
+ ichar[i] = cptr[i];
+ ++i;
+ }
+ ichar[i] = 0; /* terminate it */
+
+ /* put in the newline */
+ if (lnewline() == FALSE)
+ return(FALSE);
+
+ /* and the saved indentation */
+ i = 0;
+ while (ichar[i])
+ linsert(1, ichar[i++]);
+
+ /* and one more tab for a brace */
+ if (bracef)
+ tab(FALSE, 1);
+
+ return(TRUE);
+}
+
+insbrace(n, c) /* insert a brace into the text here...we are in CMODE */
+
+int n; /* repeat count */
+int c; /* brace to insert (always { for now) */
+
+{
+ register int ch; /* last character before input */
+ register int i;
+ register int target; /* column brace should go after */
+
+ /* if we are at the begining of the line, no go */
+ if (curwp->w_doto == 0)
+ return(linsert(n,c));
+
+ /* scan to see if all space before this is white space */
+ for (i = curwp->w_doto - 1; i >= 0; --i) {
+ ch = lgetc(curwp->w_dotp, i);
+ if (ch != ' ' && ch != '\t')
+ return(linsert(n, c));
+ }
+
+ /* delete back first */
+ target = getccol(FALSE); /* calc where we will delete to */
+ target -= 1;
+ target -= target % (tabsize == 0 ? 8 : tabsize);
+ while (getccol(FALSE) > target)
+ backdel(FALSE, 1);
+
+ /* and insert the required brace(s) */
+ return(linsert(n, c));
+}
+
+inspound() /* insert a # into the text here...we are in CMODE */
+
+{
+ register int ch; /* last character before input */
+ register int i;
+
+ /* if we are at the begining of the line, no go */
+ if (curwp->w_doto == 0)
+ return(linsert(1,'#'));
+
+ /* scan to see if all space before this is white space */
+ for (i = curwp->w_doto - 1; i >= 0; --i) {
+ ch = lgetc(curwp->w_dotp, i);
+ if (ch != ' ' && ch != '\t')
+ return(linsert(1, '#'));
+ }
+
+ /* delete back first */
+ while (getccol(FALSE) >= 1)
+ backdel(FALSE, 1);
+
+ /* and insert the required pound */
+ return(linsert(1, '#'));
+}
+
+/*
+ * Delete blank lines around dot. What this command does depends if dot is
+ * sitting on a blank line. If dot is sitting on a blank line, this command
+ * deletes all the blank lines above and below the current line. If it is
+ * sitting on a non blank line then it deletes all of the blank lines after
+ * the line. Normally this command is bound to "C-X C-O". Any argument is
+ * ignored.
+ */
+deblank(f, n)
+{
+ register LINE *lp1;
+ register LINE *lp2;
+ long nld;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ lp1 = curwp->w_dotp;
+ while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
+ lp1 = lp2;
+ lp2 = lp1;
+ nld = 0;
+ while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
+ ++nld;
+ if (nld == 0)
+ return (TRUE);
+ curwp->w_dotp = lforw(lp1);
+ curwp->w_doto = 0;
+ return (ldelete(nld, FALSE));
+}
+
+/*
+ * Insert a newline, then enough tabs and spaces to duplicate the indentation
+ * of the previous line. Assumes tabs are every eight characters. Quite simple.
+ * Figure out the indentation of the current line. Insert a newline by calling
+ * the standard routine. Insert the indentation by inserting the right number
+ * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
+ * subcomands failed. Normally bound to "C-J".
+ */
+indent(f, n)
+{
+ register int nicol;
+ register int c;
+ register int i;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ while (n--) {
+ nicol = 0;
+ for (i=0; i<llength(curwp->w_dotp); ++i) {
+ c = lgetc(curwp->w_dotp, i);
+ if (c!=' ' && c!='\t')
+ break;
+ if (c == '\t')
+ nicol |= 0x07;
+ ++nicol;
+ }
+ if (lnewline() == FALSE
+ || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
+ || ((i=nicol%8)!=0 && linsert(i, ' ')==FALSE))
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * Delete forward. This is real easy, because the basic delete routine does
+ * all of the work. Watches for negative arguments, and does the right thing.
+ * If any argument is present, it kills rather than deletes, to prevent loss
+ * of text if typed with a big argument. Normally bound to "C-D".
+ */
+forwdel(f, n)
+{
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (backdel(f, -n));
+ if (f != FALSE) { /* Really a kill. */
+ if ((lastflag&CFKILL) == 0)
+ kdelete();
+ thisflag |= CFKILL;
+ }
+ return (ldelete((long)n, f));
+}
+
+/*
+ * Delete backwards. This is quite easy too, because it's all done with other
+ * functions. Just move the cursor back, and delete forwards. Like delete
+ * forward, this actually does a kill if presented with an argument. Bound to
+ * both "RUBOUT" and "C-H".
+ */
+backdel(f, n)
+{
+ register int s;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (forwdel(f, -n));
+ if (f != FALSE) { /* Really a kill. */
+ if ((lastflag&CFKILL) == 0)
+ kdelete();
+ thisflag |= CFKILL;
+ }
+ if ((s=backchar(f, n)) == TRUE)
+ s = ldelete((long)n, f);
+ return (s);
+}
+
+/*
+ * Kill text. If called without an argument, it kills from dot to the end of
+ * the line, unless it is at the end of the line, when it kills the newline.
+ * If called with an argument of 0, it kills from the start of the line to dot.
+ * If called with a positive argument, it kills from dot forward over that
+ * number of newlines. If called with a negative argument it kills backwards
+ * that number of newlines. Normally bound to "C-K".
+ */
+killtext(f, n)
+{
+ register LINE *nextp;
+ long chunk;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
+ kdelete(); /* last wasn't a kill. */
+ thisflag |= CFKILL;
+ if (f == FALSE) {
+ chunk = llength(curwp->w_dotp)-curwp->w_doto;
+ if (chunk == 0)
+ chunk = 1;
+ } else if (n == 0) {
+ chunk = curwp->w_doto;
+ curwp->w_doto = 0;
+ } else if (n > 0) {
+ chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
+ nextp = lforw(curwp->w_dotp);
+ while (--n) {
+ if (nextp == curbp->b_linep)
+ return (FALSE);
+ chunk += llength(nextp)+1;
+ nextp = lforw(nextp);
+ }
+ } else {
+ mlwrite("neg kill");
+ return (FALSE);
+ }
+ return(ldelete(chunk, TRUE));
+}
+
+setmode(f, n) /* prompt and set an editor mode */
+
+int f, n; /* default and argument */
+
+{
+ adjustmode(TRUE, FALSE);
+}
+
+delmode(f, n) /* prompt and delete an editor mode */
+
+int f, n; /* default and argument */
+
+{
+ adjustmode(FALSE, FALSE);
+}
+
+setgmode(f, n) /* prompt and set a global editor mode */
+
+int f, n; /* default and argument */
+
+{
+ adjustmode(TRUE, TRUE);
+}
+
+delgmode(f, n) /* prompt and delete a global editor mode */
+
+int f, n; /* default and argument */
+
+{
+ adjustmode(FALSE, TRUE);
+}
+
+adjustmode(kind, global) /* change the editor mode status */
+
+int kind; /* true = set, false = delete */
+int global; /* true = global flag, false = current buffer flag */
+{
+ register char *scan; /* scanning pointer to convert prompt */
+ register int i; /* loop index */
+#if COLOR
+ register int uflag; /* was modename uppercase? */
+#endif
+ char prompt[50]; /* string to prompt user with */
+ char cbuf[NPAT]; /* buffer to recieve mode name into */
+
+ /* build the proper prompt string */
+ if (global)
+ strcpy(prompt,"Global mode to ");
+ else
+ strcpy(prompt,"Mode to ");
+
+ if (kind == TRUE)
+ strcat(prompt, "add: ");
+ else
+ strcat(prompt, "delete: ");
+
+ /* prompt the user and get an answer */
+
+ mlreply(prompt, cbuf, NPAT - 1);
+
+ /* make it uppercase */
+
+ scan = cbuf;
+#if COLOR
+ uflag = (*scan >= 'A' && *scan <= 'Z');
+#endif
+ while (*scan != 0) {
+ if (*scan >= 'a' && *scan <= 'z')
+ *scan = *scan - 32;
+ scan++;
+ }
+
+ /* test it first against the colors we know */
+ for (i=0; i<NCOLORS; i++) {
+ if (strcmp(cbuf, cname[i]) == 0) {
+ /* finding the match, we set the color */
+#if COLOR
+ if (uflag)
+ if (global)
+ gfcolor = i;
+ else
+ curwp->w_fcolor = i;
+ else
+ if (global)
+ gbcolor = i;
+ else
+ curwp->w_bcolor = i;
+
+ curwp->w_flag |= WFCOLR;
+#endif
+ mlerase();
+ return(TRUE);
+ }
+ }
+
+ /* test it against the modes we know */
+
+ for (i=0; i < NUMMODES; i++) {
+ if (strcmp(cbuf, modename[i]) == 0) {
+ /* finding a match, we process it */
+ if (kind == TRUE)
+ if (global)
+ gmode |= (1 << i);
+ else
+ curwp->w_bufp->b_mode |= (1 << i);
+ else
+ if (global)
+ gmode &= ~(1 << i);
+ else
+ curwp->w_bufp->b_mode &= ~(1 << i);
+ /* display new mode line */
+ if (global == 0)
+ upmode();
+ mlerase(); /* erase the junk */
+ return(TRUE);
+ }
+ }
+
+ mlwrite("No such mode!");
+ return(FALSE);
+}
+
+/* This function simply clears the message line,
+ mainly for macro usage */
+
+clrmes(f, n)
+
+int f, n; /* arguments ignored */
+
+{
+ mlwrite("");
+ return(TRUE);
+}
+
+/* This function writes a string on the message line
+ mainly for macro usage */
+
+writemsg(f, n)
+
+int f, n; /* arguments ignored */
+
+{
+ register char *sp; /* pointer into buf to expand %s */
+ register char *np; /* ptr into nbuf */
+ register int status;
+ char buf[NPAT]; /* buffer to recieve mode name into */
+ char nbuf[NPAT*2]; /* buffer to expand string into */
+
+ if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE)
+ return(status);
+
+ /* expand all '%' to "%%" so mlwrite won't expect arguments */
+ sp = buf;
+ np = nbuf;
+ while (*sp) {
+ *np++ = *sp;
+ if (*sp++ == '%')
+ *np++ = '%';
+ }
+ *np = '\0';
+ mlwrite(nbuf);
+ return(TRUE);
+}
+
+/* Close fences are matched against their partners, and if
+ on screen the cursor briefly lights there */
+
+fmatch(ch)
+
+char ch; /* fence type to match against */
+
+{
+ register LINE *oldlp; /* original line pointer */
+ register int oldoff; /* and offset */
+ register LINE *toplp; /* top line in current window */
+ register int count; /* current fence level count */
+ register char opench; /* open fence */
+ register char c; /* current character in scan */
+ register int i;
+
+ /* first get the display update out there */
+ update(FALSE);
+
+ /* save the original cursor position */
+ oldlp = curwp->w_dotp;
+ oldoff = curwp->w_doto;
+
+ /* setup proper open fence for passed close fence */
+ if (ch == ')')
+ opench = '(';
+ else
+ opench = '{';
+
+ /* find the top line and set up for scan */
+ toplp = curwp->w_linep->l_bp;
+ count = 1;
+ backchar(FALSE, 2);
+
+ /* scan back until we find it, or reach past the top of the window */
+ while (count > 0 && curwp->w_dotp != toplp) {
+ c = lgetc(curwp->w_dotp, curwp->w_doto);
+ if (c == ch)
+ ++count;
+ if (c == opench)
+ --count;
+ backchar(FALSE, 1);
+ if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp &&
+ curwp->w_doto == 0)
+ break;
+ }
+
+ /* if count is zero, we have a match, display the sucker */
+ /* there is a real machine dependant timing problem here we have
+ yet to solve......... */
+ if (count == 0) {
+ forwchar(FALSE, 1);
+ for (i = 0; i < term.t_pause; i++)
+ update(FALSE);
+ }
+
+ /* restore the current position */
+ curwp->w_dotp = oldlp;
+ curwp->w_doto = oldoff;
+ return(TRUE);
+}
+
+istring(f, n) /* ask for and insert a string into the current
+ buffer at the current point */
+
+int f, n; /* ignored arguments */
+
+{
+ register char *tp; /* pointer into string to add */
+ register int status; /* status return code */
+ char tstring[NPAT+1]; /* string to add */
+
+ /* ask for string to insert */
+ status = mlreplyt("String to insert<ESC>: ", tstring, NPAT, 27);
+ if (status != TRUE)
+ return(status);
+
+ /* insert it */
+ tp = &tstring[0];
+ while (*tp) {
+ if (*tp == 0x0a)
+ status = lnewline();
+ else
+ status = linsert(1, *tp);
+ ++tp;
+ if (status != TRUE)
+ return(status);
+ }
+ return(TRUE);
+}
+
Added: clients/emacs/readme
===================================================================
--- clients/emacs/readme (rev 0)
+++ clients/emacs/readme 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,48 @@
+This directory contains the C source code for MicroEMACS 3.7 .
+
+MicroEMACS is an implementation of the EMACS text editor that was
+written and placed in the public domain by Dave Conroy, circa 1985.
+Daniel Lawrence subsequently extended it quite substantially,
+creating the 3.x series of versions.
+
+Version 3.7 is the last version that was released to the public domain.
+
+Version 3.8 and subsequent versions are copyrighted by Daniel Lawrence.
+3.11 is the latest version that I know of; it was relased in late 1991
+or early 1992. The copyrighted versions have been made available to
+users under quite generous terms, but they cannot be incorporated into
+commercial products. That is the one of the reasons why version 3.7,
+and not a more recent version, is included with Forthmacs.
+
+Another reason is "creeping featurism". Many of the later features
+are, in my opinion, of marginal utility, and the size of the 3.11
+distribution is much larger than the 3.7 distribution. Some of the
+new features (such as mouse support) are worthwhile, but the whole
+package is just too big to deal with (some people may think the same
+of Forthmacs!).
+
+This copy of MicroEMACS 3.7 has been modified slightly. A few of the
+modifications are simple bug fixes. The others are changes that were
+necessary in order to make MicroEMACS callable from Forth, so that
+you could go back and forth between Forth and MicroEMACS, without
+losing either environment's state. Primarily, this involved changes
+in the initilization code and elimination of calls to "exit()" (they
+now essentially do subroutine returns rather than process exits).
+
+The other category of changes, limited to the ibmpc.c file, involved
+making the video driver work under 32-bit protected mode. This was
+accomplished by using a far pointer to access the video memory.
+
+I also changed the binding of the F1 function key in the emacs.rc
+startup file, so it now executes the help function (DOS applications
+commonly use F1 for help).
+
+In this directory, MicroEMACS may be compiled either as a self-contained
+application (EMACS.EXE) or as a component of Forth (a set of subroutines
+linked into FORTH.EXE). See the makefile in this directory for more
+information. The makefile is set up to compile with Zortech C++. It
+would be possible to compile the self-contained version of EMACS with
+another C compiler, such as Microsoft C or Borland C. However, the
+"component of Forth" version must currently be compiled with Zortech C++,
+since Forth requires the 32-bit code generation and DOS Extender features
+of Zortech C++.
Added: clients/emacs/readme.dl
===================================================================
--- clients/emacs/readme.dl (rev 0)
+++ clients/emacs/readme.dl 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,382 @@
+ MicroEMACS 3.7 release notes
+
+ First off, I would like to thank all the people that send in
+various comments, bug fixes and code segments. I have included as many
+of these as possible in this current source. All the new features which
+are larger than a couple of lines are IFDEF'ed by symbols in the
+ESTRUCT.H header file. As long as everyone keeps sending these in, I
+will keep trying to incorporate them, at least in spirit.
+
+ Installation is fairly straight forward. Copy or compile the
+appropriate version of the editor into EMACS (EMACS.EXE on MS/PC DOS)
+somewhere on your executable path. Then copy the emacs.hlp file to one
+of the directories names in the epath.h file for your system. A startup
+file .emacsrc (EMACS.RC on PC/MS DOS) can be placed in the directory
+pointed to by your HOME environment variable.
+
+[ Note for AMIGA users: Lattice 3.02 was giving me some rather
+mysterious software task failure errors while compiling some of the
+modules. Not having the Amiga long enough to solve this, I upgraded to
+Lattice 3.03 and these problems disappeared. If enough people are stuck
+with 3.02 and someone comes up with a fix and sends it to me, I will
+incorporate it into the master sources. Remember to say "stack 16000"
+before compiling the larger files.]
+
+ A new reference manual with a listing of all the commands and
+descriptions is now included. Commands are listed in logical groups.
+Also coming in the near future will be a beginner's document to replace
+"emacs.tut".
+
+ Also included are two files, "menu.cmd" and "menu1" that make up
+a simple menu driven interface to MicroEMACS 3.7. For people who prefer
+menu driven interfaces, rename "menu.cmd" as "emacs.rc" and place it
+where a startup file would be expected. Also find a place for the text
+file "menu1" and change your "emacs.rc" to view-file from that directory
+for "menu1".
+
+ MicroEMACS 3.7 is distributed on three 5 1/4" diskettes, or as one
+3 1/2" diskette, or as apx. ten shell archives. The shell archives are
+posted to USENET mod.sources and do not include the executable files.
+The executable PC and AMIGA versions will also be posted in the relevent
+USENET groups.
+
+Disk ONE contains:
+
+ readme this file
+
+ acemacs.exe MSDOS ansi color executable
+ icemacs.exe PCDOS color executable
+
+ ebind.h default biding structures
+ edef.h static global data declarations
+ efunc.h function names binding table
+ epath.h help/startup file path definitions
+ estruct.h structure and configuration header file
+
+ emacs.hlp online help file
+ emacs.key command wall chart
+ emacs.rc standard startup file
+ emacs2.mss reference manual (in MicroSCRIBE format)
+ emacs.tut beginers tutorial file
+ makefile UNIX V7/BSD 4.2 compilation command file
+ azmap.cmd an example MicroEMACS macro file
+ menu.cmd Menu driven command driver script
+ menu1 data file for menu.cmd
+
+Disk TWO contains:
+
+ ansi.c ANSI screen driver
+ basic.c cursor movement
+ bind.c bind/unbind and help commands
+ buffer.c buffer management
+ display.c display update functions
+ dg10.c Data General System/10 screen driver
+ exec.c macro line execution functions
+ file.c use file commands
+ fileio.c file I/O functions
+ hp150.c HP150 screen/keyboard driver
+ ibmpc.c IBM-PC screen driver
+ input.c message line input routines
+ isearch.c interactive search commands
+ line.c line editing functions
+ lock.c file locking front end
+ main.c command line and keyboard command parsing
+ random.c some random commands
+ region.c wipe/copy/yank commands
+ search.c normal search commands
+ spawn.c DOS interface commands
+ tcap.c UNIX screen drivers
+ termio.c Keyboard I/O routines
+ vmsvt.c VMS screen drivers
+ vt52.c VT52 screen drivers
+ window.c window management commands
+ word.c word move/delete/reformat commands
+
+Disk THREE contains:
+
+ hpemacs.exe HP150 executable
+ dgemacs.exe Data General System/10 executable
+ wgemacs.exe Wang PC executable
+ amemacs.exe Commodore AMIGA executable
+
+ The next version of MicroEMACS (3.8) will probably not be until
+late fall 1986, but it will probably be accompanied by the first version
+of MicroSCRIBE, a text formater to go along with MicroEMACS. As I will
+continue to support MicroEMACS, ideas, comments, bug fixes and new code
+should be send to:
+
+ Daniel Lawrence
+ 617 New York St
+ Lafayette, IN 47091
+
+ or
+
+ ihnp4!pur-ee!pur-phy!duncan!lawrence on USENET
+
+ and, as before, copies of MicroEMACS 3.7 may be gotten by
+sending a self addressed, self stamped mailer with two 5 1/4" diskettes
+to the above address.
+
+-------------------------------------------------------------------------------
+ MicroEMACS 3.7 - New Features
+
+*** COLOR!!!!
+
+ The forground and backgound color of buffers may be set
+with the add-mode and add-global-mode commands. Forgound colors
+are set with capitalized color names, and background colors with
+lower case color names. Availible colors are the ANSI color set:
+
+black, blue, red, green, yellow, cyan, magenta, and white
+
+ This feature is only availible on machines that support
+color properly in text mode. (IBM-PC w/color graphics adapter
+and its clones)
+
+*** Pipe command
+
+ The pipe-command (^X-@) command allows you to execute an
+operating system command and send the results into a buffer.
+MicroEMACS will make a buffer by the name of "command" for the
+results. This is only supported on systems that allow I/O redirection.
+
+*** Filter buffer
+
+ The filter-buffer (^X-#) command allows you to send an
+existing buffer's contents through a filter which runs under the
+current operating system. The result replaces the contents of
+the current buffer (beware of non-existant filters). Its a good
+idea to make a backup of the buffer to be filtered.
+
+*** Switchar is fixed
+
+ MicroEMACS under PC/MS DOS no longer cares about the
+setting of the switchar. It uses the DOS call to look it up and
+use it in its fork and system calls.
+
+*** CMODE is configurable
+
+ Automatic entering of CMODE for .c and .h extension
+files is now configurable with the ACMODE symbol in estruct.h
+
+*** Query-replace UNDO command
+
+ While making a query-replace (M-^R) run, the U key now
+undoes the last replace.
+
+*** New cursor position report
+
+ Re-wrote the buffer-position (^X-=) command to give more
+usefull information on # lines in file, current line and column,
+percentage of text before cursor and the hex value of the
+character the cursor is on.
+
+*** Word wrapping improved
+
+ Words are now only broken at spaces and tabs by the word
+wrapping algorithm. No more disapearing punctuation delimiters.
+
+*** IBM-PC Color board display driver
+
+ A new screen driver for the IBM-PC color board is in the
+file IBMPC.C and this vastly improves the paging speed and
+eliminates the retrace flicker. However, under the color
+version, the update while adding text is a little more slugish
+than I would hope. We will be working to improve this in the future.
+
+*** Destroying windows!!
+
+ A new command, delete-window (^X-0 [zero]) allows you to
+delete just the current window from the screen, leaving all the
+others intact, (and one of them bigger). This is very convient
+when you have a lot of windows on the screen.
+
+*** Execute Macro commands
+
+ Buffers holding commands can now be executed as a "macro". The
+names of these buffers is in the form "[Macro nn]" where nn is a number
+from 1 to 20. Each buffer has a corrosponding execute-macro-nn command,
+the first ten of which are bound to the shifted function keys on the IBM
+versions.
+
+*** Macro loading
+
+ Macroes can be loaded from a command file (or startup file) with
+the use of the store-macro command. For example, to make macro 5 insert
+a blank line at the begining of the current line, one would put the
+following in their startup file:
+
+; Open up a line before the current line
+
+5 store-macro
+ begining-of-line
+ open-line
+[end]
+
+ more details on this can be found in the standard startup file
+and the reference manual.
+
+*** Clear message line
+
+ Sometimes when executing macroes you want the last command not
+to leave a message on the message line at the bottom of the screen. The
+clear-message-line command does just that.
+
+*** Absolute window resizing
+
+ This new command, resize-window (^X-W) allows you to specify the
+number of lines you wish to have in the current window. For example,
+M 12 ^X W forces the current window to a size of 12 lines if possible.
+
+*** Interactive macro arguments
+
+ When executing a command line, if any of the arguments begin
+with an at sign (@) MicroEMACS will prompt the user for that argument on
+the message line, using whatever text follows. A quick macro
+demonstating this can be:
+
+; consult file
+2 store-macro
+ 2 split-current-window
+ previous-window
+ view-file "@File to Consult: "
+ 8 resize-window
+ add-mode "green"
+ add-mode "Black"
+ next-window
+[end]
+
+*** Buffer Macro arguments
+
+ When executing a command line, any arguments begining with a
+pound sign (#) mean that the argument is to be fetched from the current
+line of the named buffer. The point in that buffer is then advanced one
+line if that buffer is not currently being displayed.
+
+*** Split window modified
+
+ The split window command normally leaves the cursor in the window
+where the cursor was originaly. Now a numeric argument of one forces the
+cursor into the upper window, and an argument of 2 forces the cursor
+into the lower window.
+
+*** MicroSoft C compiler support
+
+ The MicroSoft C compiler (version 3) now can be used
+successfully to compile MicroEMACS. Use the large data, small program
+model for best results. Thanks to Oliver Sharp for the needed
+modifications.
+
+*** VMS terminal support upgraded
+
+ VMS now uses the newer terminal modes when executing MicroEMACS.
+Also some bugs were fixed. Both of these are thanks to Guy Streeter.
+
+*** CMODE enhanced
+
+ Lines starting with # as the first non-blank character (ie
+pre-processer directives) force the # into column one. Also, if
+matching open parenthises and braces are being displayed when the
+closing one is typed, the cursor will breifly flash to the open and
+back.
+
+*** Special character quoting
+
+ When typing in search/replace strings, ^Q quotes the following
+character, allowing keys like <ESC> to be searched for.
+
+*** Bindable prefix keys
+
+ The META and ^X prefixes may now be bound to other keys. Only
+one key may be a prefix key at a time, when one of these is rebound, the
+old key is automatically unbound.
+
+*** New command line options
+
+ @<file> Specifies an alternative startup file(s) to
+ run instead of emacs.rc or .emacsrc
+
+ -g<n> go to line <n> of the first file read in
+
+ -s<string> search the first file for <string> and leave
+ the cursor there.
+
+*** Wang keyboard support
+
+ The Wang-PC keyboard and is function keys are now supported.
+(Define WANG in estruct.h as 1) Thanks to Sid Shapiro for this code.
+
+*** System V support
+
+ Unix system V should now compile and execute MicroEMACS
+properly. Code for this was submited by Linwood Varney.
+
+*** Unix definitions reorginized
+
+ Now only ONE of the unix symbols should be defined when
+compiling on unices.
+
+*** Incremental Search added
+
+ For those clamering for it.....Isearch commands. This code was
+submited by D. R. Banks and seems to work well. (Later we will merge it
+with parts of the normal searching code to conserve space) This is
+availible conditionally depending on the ISRCH symbol in estruct.h
+
+*** Insert string command
+
+ The insert-string command (unbound) allows you to insert text
+into a line from a macro. This can be used to build special help and
+text screens.
+
+*** Unmark buffer command
+
+ The unmark-command (unbound) allows you to unmark a buffer.
+This will keep the exit commands from complaining abount unchanged
+buffers. This is most usefull when you have built up a text screen from
+a macro and have no intention of saving it.
+
+*** Special characters
+
+ Inside of string argument in macroes, the following special
+characters are active:
+
+ ~n newline
+ ~t tab
+ ~b backspace
+ ~f formfeed
+
+*** Fixed large file problems
+
+ Several problems caused by keeping character counts in integers
+have been fixed by making these counts be longs. Also regions can now
+be larger than 65535 chars.
+
+*** Kill buffer re-coded
+
+ New kill buffer routines should (and do) work faster. Also an
+unlimited (except by RAM) amount of text can be killed safely.
+
+*** Word counting
+
+ The count-words (M-^C) command counts the number of words,
+characters and lines in the current region. It also gives an average
+words/character total.
+
+*** Changed delete-word behavior
+
+ Delete-next-word no longer kills the newline as it deletes tha
+last word on the line. It does however then delete the newline as it
+deletes the first word on the next line.
+
+*** Next/Previous buffer cammands augmented
+
+ Both now take a numeric argument to switch to the nth window
+from the top/bottom.
+
+*** Data General Support
+
+ MicroEMACS now supprts the Data General System/10 computer under
+MSDOS.
+
+
Added: clients/emacs/region.c
===================================================================
--- clients/emacs/region.c (rev 0)
+++ clients/emacs/region.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,205 @@
+/*
+ * The routines in this file
+ * deal with the region, that magic space
+ * between "." and mark. Some functions are
+ * commands. Some functions are just for
+ * internal use.
+ */
+#include "estruct.h"
+#include "edef.h"
+
+/*
+ * Kill the region. Ask "getregion"
+ * to figure out the bounds of the region.
+ * Move "." to the start, and kill the characters.
+ * Bound to "C-W".
+ */
+killregion(f, n)
+{
+ register int s;
+ REGION region;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if ((s=getregion(®ion)) != TRUE)
+ return (s);
+ if ((lastflag&CFKILL) == 0) /* This is a kill type */
+ kdelete(); /* command, so do magic */
+ thisflag |= CFKILL; /* kill buffer stuff. */
+ curwp->w_dotp = region.r_linep;
+ curwp->w_doto = region.r_offset;
+ return (ldelete(region.r_size, TRUE));
+}
+
+/*
+ * Copy all of the characters in the
+ * region to the kill buffer. Don't move dot
+ * at all. This is a bit like a kill region followed
+ * by a yank. Bound to "M-W".
+ */
+copyregion(f, n)
+{
+ register LINE *linep;
+ register int loffs;
+ register int s;
+ REGION region;
+
+ if ((s=getregion(®ion)) != TRUE)
+ return (s);
+ if ((lastflag&CFKILL) == 0) /* Kill type command. */
+ kdelete();
+ thisflag |= CFKILL;
+ linep = region.r_linep; /* Current line. */
+ loffs = region.r_offset; /* Current offset. */
+ while (region.r_size--) {
+ if (loffs == llength(linep)) { /* End of line. */
+ if ((s=kinsert('\n')) != TRUE)
+ return (s);
+ linep = lforw(linep);
+ loffs = 0;
+ } else { /* Middle of line. */
+ if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
+ return (s);
+ ++loffs;
+ }
+ }
+ return (TRUE);
+}
+
+/*
+ * Lower case region. Zap all of the upper
+ * case characters in the region to lower case. Use
+ * the region code to set the limits. Scan the buffer,
+ * doing the changes. Call "lchange" to ensure that
+ * redisplay is done in all buffers. Bound to
+ * "C-X C-L".
+ */
+lowerregion(f, n)
+{
+ register LINE *linep;
+ register int loffs;
+ register int c;
+ register int s;
+ REGION region;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if ((s=getregion(®ion)) != TRUE)
+ return (s);
+ lchange(WFHARD);
+ linep = region.r_linep;
+ loffs = region.r_offset;
+ while (region.r_size--) {
+ if (loffs == llength(linep)) {
+ linep = lforw(linep);
+ loffs = 0;
+ } else {
+ c = lgetc(linep, loffs);
+ if (c>='A' && c<='Z')
+ lputc(linep, loffs, c+'a'-'A');
+ ++loffs;
+ }
+ }
+ return (TRUE);
+}
+
+/*
+ * Upper case region. Zap all of the lower
+ * case characters in the region to upper case. Use
+ * the region code to set the limits. Scan the buffer,
+ * doing the changes. Call "lchange" to ensure that
+ * redisplay is done in all buffers. Bound to
+ * "C-X C-L".
+ */
+upperregion(f, n)
+{
+ register LINE *linep;
+ register int loffs;
+ register int c;
+ register int s;
+ REGION region;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if ((s=getregion(®ion)) != TRUE)
+ return (s);
+ lchange(WFHARD);
+ linep = region.r_linep;
+ loffs = region.r_offset;
+ while (region.r_size--) {
+ if (loffs == llength(linep)) {
+ linep = lforw(linep);
+ loffs = 0;
+ } else {
+ c = lgetc(linep, loffs);
+ if (c>='a' && c<='z')
+ lputc(linep, loffs, c-'a'+'A');
+ ++loffs;
+ }
+ }
+ return (TRUE);
+}
+
+/*
+ * This routine figures out the
+ * bounds of the region in the current window, and
+ * fills in the fields of the "REGION" structure pointed
+ * to by "rp". Because the dot and mark are usually very
+ * close together, we scan outward from dot looking for
+ * mark. This should save time. Return a standard code.
+ * Callers of this routine should be prepared to get
+ * an "ABORT" status; we might make this have the
+ * conform thing later.
+ */
+getregion(rp)
+register REGION *rp;
+{
+ register LINE *flp;
+ register LINE *blp;
+ long fsize;
+ long bsize;
+
+ if (curwp->w_markp == NULL) {
+ mlwrite("No mark set in this window");
+ return (FALSE);
+ }
+ if (curwp->w_dotp == curwp->w_markp) {
+ rp->r_linep = curwp->w_dotp;
+ if (curwp->w_doto < curwp->w_marko) {
+ rp->r_offset = curwp->w_doto;
+ rp->r_size = (long)(curwp->w_marko-curwp->w_doto);
+ } else {
+ rp->r_offset = curwp->w_marko;
+ rp->r_size = (long)(curwp->w_doto-curwp->w_marko);
+ }
+ return (TRUE);
+ }
+ blp = curwp->w_dotp;
+ bsize = (long)curwp->w_doto;
+ flp = curwp->w_dotp;
+ fsize = (long)(llength(flp)-curwp->w_doto+1);
+ while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
+ if (flp != curbp->b_linep) {
+ flp = lforw(flp);
+ if (flp == curwp->w_markp) {
+ rp->r_linep = curwp->w_dotp;
+ rp->r_offset = curwp->w_doto;
+ rp->r_size = fsize+curwp->w_marko;
+ return (TRUE);
+ }
+ fsize += llength(flp)+1;
+ }
+ if (lback(blp) != curbp->b_linep) {
+ blp = lback(blp);
+ bsize += llength(blp)+1;
+ if (blp == curwp->w_markp) {
+ rp->r_linep = blp;
+ rp->r_offset = curwp->w_marko;
+ rp->r_size = bsize - curwp->w_marko;
+ return (TRUE);
+ }
+ }
+ }
+ mlwrite("Bug: lost mark");
+ return (FALSE);
+}
Added: clients/emacs/search.c
===================================================================
--- clients/emacs/search.c (rev 0)
+++ clients/emacs/search.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,607 @@
+/*
+ * The functions in this file implement commands that search in the forward
+ * and backward directions. There are no special characters in the search
+ * strings. Probably should have a regular expression search, or something
+ * like that.
+ *
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+/*
+ * Search forward. Get a search string from the user, and search, beginning at
+ * ".", for the string. If found, reset the "." to be just after the match
+ * string, and [perhaps] repaint the display. Bound to "C-S".
+ */
+
+/* string search input parameters */
+
+#define PTBEG 1 /* leave the point at the begining on search */
+#define PTEND 2 /* leave the point at the end on search */
+
+forwsearch(f, n)
+
+{
+ register int status;
+
+ /* resolve the repeat count */
+ if (n == 0)
+ n = 1;
+ if (n < 1) /* search backwards */
+ return(backsearch(f, -n));
+
+ /* ask the user for the text of a pattern */
+ if ((status = readpattern("Search")) != TRUE)
+ return(status);
+
+ /* search for the pattern */
+ while (n-- > 0) {
+ if ((status = forscan(&pat[0],PTEND)) == FALSE)
+ break;
+ }
+
+ /* and complain if not there */
+ if (status == FALSE)
+ mlwrite("Not found");
+ return(status);
+}
+
+forwhunt(f, n)
+
+{
+ register int status;
+
+ /* resolve the repeat count */
+ if (n == 0)
+ n = 1;
+ if (n < 1) /* search backwards */
+ return(backhunt(f, -n));
+
+ /* Make sure a pattern exists */
+ if (pat[0] == 0) {
+ mlwrite("No pattern set");
+ return(FALSE);
+ }
+
+ /* search for the pattern */
+ while (n-- > 0) {
+ if ((status = forscan(&pat[0],PTEND)) == FALSE)
+ break;
+ }
+
+ /* and complain if not there */
+ if (status == FALSE)
+ mlwrite("Not found");
+ return(status);
+}
+
+/*
+ * Reverse search. Get a search string from the user, and search, starting at
+ * "." and proceeding toward the front of the buffer. If found "." is left
+ * pointing at the first character of the pattern [the last character that was
+ * matched]. Bound to "C-R".
+ */
+backsearch(f, n)
+
+{
+ register int s;
+
+ /* resolve null and negative arguments */
+ if (n == 0)
+ n = 1;
+ if (n < 1)
+ return(forwsearch(f, -n));
+
+ /* get a pattern to search */
+ if ((s = readpattern("Reverse search")) != TRUE)
+ return(s);
+
+ /* and go search for it */
+ bsearchcom(f,n);
+ return(TRUE);
+}
+
+backhunt(f, n) /* hunt backward for the last search string entered */
+
+{
+ /* resolve null and negative arguments */
+ if (n == 0)
+ n = 1;
+ if (n < 1)
+ return(forwhunt(f, -n));
+
+ /* Make sure a pattern exists */
+ if (pat[0] == 0) {
+ mlwrite("No pattern set");
+ return(FALSE);
+ }
+
+ /* and go search for it */
+ bsearchcom(f,n);
+ return(TRUE);
+}
+
+bsearchcom(f, n)
+
+int f; /* default flag */
+int n; /* # of repetitions wanted */
+
+{
+ register LINE *clp;
+ register int cbo;
+ register LINE *tlp;
+ register int tbo;
+ register int c;
+ register char *epp;
+ register char *pp;
+
+ /* find a pointer to the end of the pattern */
+ for (epp = &pat[0]; epp[1] != 0; ++epp)
+ ;
+
+ /* make local copies of the starting location */
+ clp = curwp->w_dotp;
+ cbo = curwp->w_doto;
+
+ while (n-- > 0) {
+ for (;;) {
+ /* if we are at the begining of the line, wrap back around */
+ if (cbo == 0) {
+ clp = lback(clp);
+
+ if (clp == curbp->b_linep) {
+ mlwrite("Not found");
+ return(FALSE);
+ }
+
+ cbo = llength(clp)+1;
+ }
+
+ /* fake the <NL> at the end of a line */
+ if (--cbo == llength(clp))
+ c = '\n';
+ else
+ c = lgetc(clp, cbo);
+
+ /* check for a match against the end of the pattern */
+ if (eq(c, *epp) != FALSE) {
+ tlp = clp;
+ tbo = cbo;
+ pp = epp;
+
+ /* scanning backwards through the rest of the
+ pattern looking for a match */
+ while (pp != &pat[0]) {
+ /* wrap across a line break */
+ if (tbo == 0) {
+ tlp = lback(tlp);
+ if (tlp == curbp->b_linep)
+ goto fail;
+
+ tbo = llength(tlp)+1;
+ }
+
+ /* fake the <NL> */
+ if (--tbo == llength(tlp))
+ c = '\n';
+ else
+ c = lgetc(tlp, tbo);
+
+ if (eq(c, *--pp) == FALSE)
+ goto fail;
+ }
+
+ /* A Match! reset the current cursor */
+ curwp->w_dotp = tlp;
+ curwp->w_doto = tbo;
+ curwp->w_flag |= WFMOVE;
+ goto next;
+ }
+fail:;
+ }
+next:;
+ }
+ return(TRUE);
+}
+
+/*
+ * Compare two characters. The "bc" comes from the buffer. It has it's case
+ * folded out. The "pc" is from the pattern.
+ */
+eq(bc, pc)
+ int bc;
+ int pc;
+
+{
+ if ((curwp->w_bufp->b_mode & MDEXACT) == 0) {
+ if (bc>='a' && bc<='z')
+ bc -= 0x20;
+
+ if (pc>='a' && pc<='z')
+ pc -= 0x20;
+ }
+
+ if (bc == pc)
+ return(TRUE);
+
+ return(FALSE);
+}
+
+/*
+ * Read a pattern. Stash it in the external variable "pat". The "pat" is not
+ * updated if the user types in an empty line. If the user typed an empty line,
+ * and there is no old pattern, it is an error. Display the old pattern, in the
+ * style of Jeff Lomicka. There is some do-it-yourself control expansion.
+ * change to using <ESC> to delemit the end-of-pattern to allow <NL>s in
+ * the search string.
+ */
+readpattern(prompt)
+
+char *prompt;
+
+{
+ register int s;
+ char tpat[NPAT+20];
+
+ strcpy(tpat, prompt); /* copy prompt to output string */
+ strcat(tpat, " ["); /* build new prompt string */
+ expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2); /* add old pattern */
+ strcat(tpat, "]<ESC>: ");
+
+ s = mlreplyt(tpat, tpat, NPAT, 27); /* Read pattern */
+
+ if (s == TRUE) /* Specified */
+ strcpy(pat, tpat);
+ else if (s == FALSE && pat[0] != 0) /* CR, but old one */
+ s = TRUE;
+
+ return(s);
+}
+
+sreplace(f, n) /* Search and replace (ESC-R) */
+
+int f; /* default flag */
+int n; /* # of repetitions wanted */
+
+{
+ return(replaces(FALSE, f, n));
+}
+
+qreplace(f, n) /* search and replace with query (ESC-CTRL-R) */
+
+int f; /* default flag */
+int n; /* # of repetitions wanted */
+
+{
+ return(replaces(TRUE, f, n));
+}
+
+/* replaces: search for a string and replace it with another
+ string. query might be enabled (according to
+ kind). */
+replaces(kind, f, n)
+
+int kind; /* Query enabled flag */
+int f; /* default flag */
+int n; /* # of repetitions wanted */
+
+{
+ register int i; /* loop index */
+ register int s; /* success flag on pattern inputs */
+ register int slength,
+ rlength; /* length of search and replace strings */
+ register int numsub; /* number of substitutions */
+ register int nummatch; /* number of found matches */
+ int nlflag; /* last char of search string a <NL>? */
+ int nlrepl; /* was a replace done on the last line? */
+ char tmpc; /* temporary character */
+ char c; /* input char for query */
+ char tpat[NPAT]; /* temporary to hold search pattern */
+ LINE *origline; /* original "." position */
+ int origoff; /* and offset (for . query option) */
+ LINE *lastline; /* position of last replace and */
+ int lastoff; /* offset (for 'u' query option) */
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+
+ /* check for negative repititions */
+ if (f && n < 0)
+ return(FALSE);
+
+ /* ask the user for the text of a pattern */
+ if ((s = readpattern(
+ (kind == FALSE ? "Replace" : "Query replace"))) != TRUE)
+ return(s);
+ strcpy(&tpat[0], &pat[0]); /* salt it away */
+
+ /* ask for the replacement string */
+ strcpy(&pat[0], &rpat[0]); /* set up default string */
+ if ((s = readpattern("with")) == ABORT)
+ return(s);
+
+ /* move everything to the right place and length them */
+ strcpy(&rpat[0], &pat[0]);
+ strcpy(&pat[0], &tpat[0]);
+ slength = strlen(&pat[0]);
+ rlength = strlen(&rpat[0]);
+
+ /* set up flags so we can make sure not to do a recursive
+ replace on the last line */
+ nlflag = (pat[slength - 1] == '\n');
+ nlrepl = FALSE;
+
+ if (kind) {
+ /* build query replace question string */
+ strcpy(tpat, "Replace '");
+ expandp(&pat[0], &tpat[strlen(tpat)], NPAT/3);
+ strcat(tpat, "' with '");
+ expandp(&rpat[0], &tpat[strlen(tpat)], NPAT/3);
+ strcat(tpat, "'? ");
+
+ /* initialize last replaced pointers */
+ lastline = NULL;
+ lastoff = 0;
+ }
+
+ /* save original . position */
+ origline = curwp->w_dotp;
+ origoff = curwp->w_doto;
+
+ /* scan through the file */
+ numsub = 0;
+ nummatch = 0;
+ while ((f == FALSE || n > nummatch) &&
+ (nlflag == FALSE || nlrepl == FALSE)) {
+
+ /* search for the pattern */
+ if (forscan(&pat[0],PTBEG) != TRUE)
+ break; /* all done */
+ ++nummatch; /* increment # of matches */
+
+ /* check if we are on the last line */
+ nlrepl = (lforw(curwp->w_dotp) == curwp->w_bufp->b_linep);
+
+ /* check for query */
+ if (kind) {
+ /* get the query */
+pprompt: mlwrite(&tpat[0], &pat[0], &rpat[0]);
+qprompt:
+ update(FALSE); /* show the proposed place to change */
+ c = (*term.t_getchar)(); /* and input */
+ mlwrite(""); /* and clear it */
+
+ /* and respond appropriately */
+ switch (c) {
+ case 'y': /* yes, substitute */
+ case ' ':
+ break;
+
+ case 'n': /* no, onword */
+ forwchar(FALSE, 1);
+ continue;
+
+ case '!': /* yes/stop asking */
+ kind = FALSE;
+ break;
+
+ case 'u': /* undo last and re-prompt */
+
+ /* restore old position */
+ if (lastline == NULL) {
+ /* there is nothing to undo */
+ (*term.t_beep)();
+ goto qprompt;
+ }
+ curwp->w_dotp = lastline;
+ curwp->w_doto = lastoff;
+ lastline = NULL;
+ lastoff = 0;
+
+ /* delete the new string */
+ backchar(FALSE, rlength);
+ if (ldelete((long)rlength, FALSE) != TRUE) {
+ mlwrite("ERROR while deleting");
+ return(FALSE);
+ }
+
+ /* and put in the old one */
+ for (i=0; i<slength; i++) {
+ tmpc = pat[i];
+ s = (tmpc == '\n' ? lnewline() :
+ linsert(1, tmpc));
+ if (s != TRUE) {
+ /* error while inserting */
+ mlwrite("Out of memory while inserting");
+ return(FALSE);
+ }
+ }
+
+ --numsub; /* one less substitutions */
+
+ /* backup, and reprompt */
+ backchar(FALSE, slength);
+ goto pprompt;
+
+ case '.': /* abort! and return */
+ /* restore old position */
+ curwp->w_dotp = origline;
+ curwp->w_doto = origoff;
+ curwp->w_flag |= WFMOVE;
+
+ case BELL: /* abort! and stay */
+ mlwrite("Aborted!");
+ return(FALSE);
+
+ default: /* bitch and beep */
+ (*term.t_beep)();
+
+ case '?': /* help me */
+ mlwrite(
+"(Y)es, (N)o, (!)Do rest, (U)ndo last, (^G)Abort, (.)Abort back, (?)Help: ");
+ goto qprompt;
+
+ }
+ }
+
+ /* delete the sucker */
+ if (ldelete((long)slength, FALSE) != TRUE) {
+ /* error while deleting */
+ mlwrite("ERROR while deleteing");
+ return(FALSE);
+ }
+
+ /* and insert its replacement */
+ for (i=0; i<rlength; i++) {
+ tmpc = rpat[i];
+ s = (tmpc == '\n' ? lnewline() : linsert(1, tmpc));
+ if (s != TRUE) {
+ /* error while inserting */
+ mlwrite("Out of memory while inserting");
+ return(FALSE);
+ }
+ }
+
+ /* save where we are if we might undo this... */
+ if (kind) {
+ lastline = curwp->w_dotp;
+ lastoff = curwp->w_doto;
+ }
+
+ numsub++; /* increment # of substitutions */
+ }
+
+ /* and report the results */
+ mlwrite("%d substitutions",numsub);
+ return(TRUE);
+}
+
+forscan(patrn,leavep) /* search forward for a <patrn> */
+
+char *patrn; /* string to scan for */
+int leavep; /* place to leave point
+ PTBEG = begining of match
+ PTEND = at end of match */
+
+{
+ register LINE *curline; /* current line during scan */
+ register int curoff; /* position within current line */
+ register LINE *lastline; /* last line position during scan */
+ register int lastoff; /* position within last line */
+ register int c; /* character at current position */
+ register LINE *matchline; /* current line during matching */
+ register int matchoff; /* position in matching line */
+ register char *patptr; /* pointer into pattern */
+
+ /* setup local scan pointers to global "." */
+
+ curline = curwp->w_dotp;
+ curoff = curwp->w_doto;
+
+ /* scan each character until we hit the head link record */
+
+ while (curline != curbp->b_linep) {
+
+ /* save the current position in case we need to
+ restore it on a match */
+
+ lastline = curline;
+ lastoff = curoff;
+
+ /* get the current character resolving EOLs */
+
+ if (curoff == llength(curline)) { /* if at EOL */
+ curline = lforw(curline); /* skip to next line */
+ curoff = 0;
+ c = '\n'; /* and return a <NL> */
+ } else
+ c = lgetc(curline, curoff++); /* get the char */
+
+ /* test it against first char in pattern */
+ if (eq(c, patrn[0]) != FALSE) { /* if we find it..*/
+ /* setup match pointers */
+ matchline = curline;
+ matchoff = curoff;
+ patptr = &patrn[0];
+
+ /* scan through patrn for a match */
+ while (*++patptr != 0) {
+ /* advance all the pointers */
+ if (matchoff == llength(matchline)) {
+ /* advance past EOL */
+ matchline = lforw(matchline);
+ matchoff = 0;
+ c = '\n';
+ } else
+ c = lgetc(matchline, matchoff++);
+
+ /* and test it against the pattern */
+ if (eq(*patptr, c) == FALSE)
+ goto fail;
+ }
+
+ /* A SUCCESSFULL MATCH!!! */
+ /* reset the global "." pointers */
+ if (leavep == PTEND) { /* at end of string */
+ curwp->w_dotp = matchline;
+ curwp->w_doto = matchoff;
+ } else { /* at begining of string */
+ curwp->w_dotp = lastline;
+ curwp->w_doto = lastoff;
+ }
+ curwp->w_flag |= WFMOVE; /* flag that we have moved */
+ return(TRUE);
+
+ }
+fail:; /* continue to search */
+ }
+
+ /* we could not find a match */
+
+ return(FALSE);
+}
+
+/* expandp: expand control key sequences for output */
+
+expandp(srcstr, deststr, maxlength)
+
+char *srcstr; /* string to expand */
+char *deststr; /* destination of expanded string */
+int maxlength; /* maximum chars in destination */
+
+{
+ char c; /* current char to translate */
+
+ /* scan through the string */
+ while ((c = *srcstr++) != 0) {
+ if (c == '\n') { /* its an EOL */
+ *deststr++ = '<';
+ *deststr++ = 'N';
+ *deststr++ = 'L';
+ *deststr++ = '>';
+ maxlength -= 4;
+ } else if (c < 0x20 || c == 0x7f) { /* control character */
+ *deststr++ = '^';
+ *deststr++ = c ^ 0x40;
+ maxlength -= 2;
+ } else if (c == '%') {
+ *deststr++ = '%';
+ *deststr++ = '%';
+ maxlength -= 2;
+
+ } else { /* any other character */
+ *deststr++ = c;
+ maxlength--;
+ }
+
+ /* check for maxlength */
+ if (maxlength < 4) {
+ *deststr++ = '$';
+ *deststr = '\0';
+ return(FALSE);
+ }
+ }
+ *deststr = '\0';
+ return(TRUE);
+}
Added: clients/emacs/spawn.c
===================================================================
--- clients/emacs/spawn.c (rev 0)
+++ clients/emacs/spawn.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,533 @@
+/* Spawn: various DOS access commands
+ for MicroEMACS
+*/
+
+#include "estruct.h"
+#include "edef.h"
+
+#if AMIGA
+#define NEW 1006
+#endif
+
+#if VMS
+#define EFN 0 /* Event flag. */
+
+#include <ssdef.h> /* Random headers. */
+#include <stsdef.h>
+#include <descrip.h>
+#include <iodef.h>
+
+extern int oldmode[3]; /* In "termio.c" */
+extern int newmode[3]; /* In "termio.c" */
+extern short iochan; /* In "termio.c" */
+#endif
+
+#if V7 | USG | BSD
+#include <signal.h>
+extern int vttidy();
+#endif
+
+#if MSDOS & MSC
+#include <process.h>
+#define system(a) spawnlp(P_WAIT, a, NULL)
+#endif
+
+/*
+ * Create a subjob with a copy of the command intrepreter in it. When the
+ * command interpreter exits, mark the screen as garbage so that you do a full
+ * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
+ * Under some (unknown) condition, you don't get one free when DCL starts up.
+ */
+spawncli(f, n)
+{
+#if AMIGA
+ long newcli;
+
+ newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+ mlwrite("[Starting new CLI]");
+ sgarbf = TRUE;
+ Execute("", newcli, 0);
+ Close(newcli);
+ return(TRUE);
+#endif
+
+#if V7 | USG | BSD
+ register char *cp;
+ char *getenv();
+#endif
+#if VMS
+ movecursor(term.t_nrow, 0); /* In last line. */
+ mlputs("[Starting DCL]\r\n");
+ (*term.t_flush)(); /* Ignore "ttcol". */
+ sgarbf = TRUE;
+ return (sys(NULL)); /* NULL => DCL. */
+#endif
+#if CPM
+ mlwrite("Not in CP/M-86");
+#endif
+#if MSDOS & AZTEC
+ movecursor(term.t_nrow, 0); /* Seek to last line. */
+ (*term.t_flush)();
+ (*term.t_close)();
+ system("command.com");
+ (*term.t_open)();
+ sgarbf = TRUE;
+ return(TRUE);
+#endif
+#if MSDOS & LATTICE
+ movecursor(term.t_nrow, 0); /* Seek to last line. */
+ (*term.t_flush)();
+ (*term.t_close)();
+ sys("\\command.com", ""); /* Run CLI. */
+ (*term.t_open)();
+ sgarbf = TRUE;
+ return(TRUE);
+#endif
+#if OFW
+ movecursor(term.t_nrow, 0); /* Seek to last line. */
+ (*term.t_flush)();
+ (*term.t_close)();
+ OFEnter(); /* Run CLI. */
+ (*term.t_open)();
+ sgarbf = TRUE;
+ return(TRUE);
+#endif
+#if V7 | USG | BSD
+ movecursor(term.t_nrow, 0); /* Seek to last line. */
+ (*term.t_flush)();
+ ttclose(); /* stty to old settings */
+ if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
+ system(cp);
+ else
+#if BSD
+ system("exec /bin/csh");
+#else
+ system("exec /bin/sh");
+#endif
+ sgarbf = TRUE;
+ sleep(2);
+ ttopen();
+ return(TRUE);
+#endif
+}
+
+#if BSD
+
+bktoshell() /* suspend MicroEMACS and wait to wake up */
+{
+ int pid;
+
+ vttidy();
+ pid = getpid();
+ kill(pid,SIGTSTP);
+}
+
+rtfrmshell()
+{
+ ttopen();
+ curwp->w_flag = WFHARD;
+ sgarbf = TRUE;
+}
+#endif
+
+/*
+ * Run a one-liner in a subjob. When the command returns, wait for a single
+ * character to be typed, then mark the screen as garbage so a full repaint is
+ * done. Bound to "C-X !".
+ */
+spawn(f, n)
+{
+ register int s;
+ char line[NLINE];
+#if AMIGA
+ long newcli;
+
+ if ((s=mlreply("!", line, NLINE)) != TRUE)
+ return (s);
+ newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+ Execute(line,0,newcli);
+ Close(newcli);
+ (*term.t_getchar)(); /* Pause. */
+ sgarbf = TRUE;
+ return(TRUE);
+#endif
+#if VMS
+ if ((s=mlreply("!", line, NLINE)) != TRUE)
+ return (s);
+ (*term.t_putchar)('\n'); /* Already have '\r' */
+ (*term.t_flush)();
+ s = sys(line); /* Run the command. */
+ mlputs("\r\n\n[End]"); /* Pause. */
+ (*term.t_flush)();
+ (*term.t_getchar)();
+ sgarbf = TRUE;
+ return (s);
+#endif
+#if CPM
+ mlwrite("Not in CP/M-86");
+ return (FALSE);
+#endif
+#if MSDOS | OFW
+ if ((s=mlreply("!", line, NLINE)) != TRUE)
+ return(s);
+ movecursor(term.t_nrow - 1, 0);
+ (*term.t_close)();
+ system(line);
+ (*term.t_open)();
+ mlputs("\r\n\n[End]"); /* Pause. */
+ (*term.t_getchar)(); /* Pause. */
+ sgarbf = TRUE;
+ return (TRUE);
+#endif
+#if V7 | USG | BSD
+ if ((s=mlreply("!", line, NLINE)) != TRUE)
+ return (s);
+ (*term.t_putchar)('\n'); /* Already have '\r' */
+ (*term.t_flush)();
+ ttclose(); /* stty to old modes */
+ system(line);
+ ttopen();
+ mlputs("[End]"); /* Pause. */
+ (*term.t_flush)();
+ while ((s = (*term.t_getchar)()) != '\r' && s != ' ')
+ ;
+ sgarbf = TRUE;
+ return (TRUE);
+#endif
+}
+
+/*
+ * Pipe a one line command into a window
+ * Bound to ^X @
+ */
+pipe(f, n)
+{
+ register int s; /* return status from CLI */
+ register WINDOW *wp; /* pointer to new window */
+ register BUFFER *bp; /* pointer to buffer to zot */
+ char line[NLINE]; /* command line send to shell */
+ static char bname[] = "command";
+
+#if AMIGA
+ static char filnam[] = "ram:command";
+ long newcli;
+#else
+ static char filnam[] = "command";
+#endif
+
+#if VMS
+ mlwrite("Not availible under VMS");
+ return(FALSE);
+#endif
+#if CPM
+ mlwrite("Not availible under CP/M-86");
+ return(FALSE);
+#endif
+#if OFW
+ /* XXX we could do this by creating a special redirect I/O package */
+ mlwrite("Not availible under Open Firmware");
+ return(FALSE);
+#endif
+
+ /* get the command to pipe in */
+ if ((s=mlreply("@", line, NLINE)) != TRUE)
+ return(s);
+
+ /* get rid of the command output buffer if it exists */
+ if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
+ /* try to make sure we are off screen */
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp->w_bufp == bp) {
+ onlywind(FALSE, 1);
+ break;
+ }
+ wp = wp->w_wndp;
+ }
+ if (zotbuf(bp) != TRUE)
+ return(FALSE);
+ }
+
+#if AMIGA
+ newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+ strcat(line, " >");
+ strcat(line, filnam);
+ Execute(line,0,newcli);
+ s = TRUE;
+ Close(newcli);
+ sgarbf = TRUE;
+#endif
+#if MSDOS
+ strcat(line," >");
+ strcat(line,filnam);
+ movecursor(term.t_nrow - 1, 0);
+ (*term.t_close)();
+ system(line);
+ (*term.t_open)();
+ sgarbf = TRUE;
+ s = TRUE;
+#endif
+#if V7 | USG | BSD
+ (*term.t_putchar)('\n'); /* Already have '\r' */
+ (*term.t_flush)();
+ ttclose(); /* stty to old modes */
+ strcat(line,">");
+ strcat(line,filnam);
+ system(line);
+ ttopen();
+ (*term.t_flush)();
+ sgarbf = TRUE;
+ s = TRUE;
+#endif
+
+ if (s != TRUE)
+ return(s);
+
+ /* split the current window to make room for the command output */
+ if (splitwind(FALSE, 1) == FALSE)
+ return(FALSE);
+
+ /* and read the stuff in */
+ if (getfile(filnam, FALSE) == FALSE)
+ return(FALSE);
+
+ /* make this window in VIEW mode, update all mode lines */
+ curwp->w_bufp->b_mode |= MDVIEW;
+ wp = wheadp;
+ while (wp != NULL) {
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+#ifndef OBP
+ /* and get rid of the temporary file */
+ unlink(filnam);
+#endif
+ return(TRUE);
+}
+
+/*
+ * filter a buffer through an external DOS program
+ * Bound to ^X #
+ */
+filter(f, n)
+
+{
+ register int s; /* return status from CLI */
+ register BUFFER *bp; /* pointer to buffer to zot */
+ char line[NLINE]; /* command line send to shell */
+ char tmpnam[NFILEN]; /* place to store real file name */
+ static char bname1[] = "fltinp";
+
+#if AMIGA
+ static char filnam1[] = "ram:fltinp";
+ static char filnam2[] = "ram:fltout";
+ long newcli;
+#else
+ static char filnam1[] = "fltinp";
+ static char filnam2[] = "fltout";
+#endif
+
+#if VMS
+ mlwrite("Not availible under VMS");
+ return(FALSE);
+#endif
+#if CPM
+ mlwrite("Not availible under CP/M-86");
+ return(FALSE);
+#endif
+#if OFW
+ /* XXX we could do this by creating a special redirect I/O package */
+ mlwrite("Not availible under Open Firmware");
+ return(FALSE);
+#endif
+
+ /* get the filter name and its args */
+ if ((s=mlreply("#", line, NLINE)) != TRUE)
+ return(s);
+
+ /* setup the proper file names */
+ bp = curbp;
+ strcpy(tmpnam, bp->b_fname); /* save the original name */
+ strcpy(bp->b_fname, bname1); /* set it to our new one */
+
+ /* write it out, checking for errors */
+ if (writeout(filnam1) != TRUE) {
+ mlwrite("[Cannot write filter file]");
+ strcpy(bp->b_fname, tmpnam);
+ return(FALSE);
+ }
+
+#if AMIGA
+ newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+ strcat(line, " <ram:fltinp >ram:fltout");
+ Execute(line,0,newcli);
+ s = TRUE;
+ Close(newcli);
+ sgarbf = TRUE;
+#endif
+#if MSDOS
+ strcat(line," <fltinp >fltout");
+ movecursor(term.t_nrow - 1, 0);
+ (*term.t_close)();
+ system(line);
+ (*term.t_open)();
+ sgarbf = TRUE;
+ s = TRUE;
+#endif
+#if V7 | USG | BSD
+ (*term.t_putchar)('\n'); /* Already have '\r' */
+ (*term.t_flush)();
+ ttclose(); /* stty to old modes */
+ strcat(line," <fltinp >fltout");
+ system(line);
+ ttopen();
+ (*term.t_flush)();
+ sgarbf = TRUE;
+ s = TRUE;
+#endif
+
+ /* on failure, escape gracefully */
+ if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
+ mlwrite("[Execution failed]");
+ strcpy(bp->b_fname, tmpnam);
+#ifndef OBP
+ unlink(filnam1);
+ unlink(filnam2);
+#endif
+ return(s);
+ }
+
+ /* reset file name */
+ strcpy(bp->b_fname, tmpnam); /* restore name */
+ bp->b_flag |= BFCHG; /* flag it as changed */
+
+ /* and get rid of the temporary file */
+#ifndef OBP
+ unlink(filnam1);
+ unlink(filnam2);
+#endif
+ return(TRUE);
+}
+
+#if VMS
+/*
+ * Run a command. The "cmd" is a pointer to a command string, or NULL if you
+ * want to run a copy of DCL in the subjob (this is how the standard routine
+ * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
+ * and the way out, because DCL does not want the channel to be in raw mode.
+ */
+sys(cmd)
+register char *cmd;
+{
+ struct dsc$descriptor cdsc;
+ struct dsc$descriptor *cdscp;
+ long status;
+ long substatus;
+ long iosb[2];
+
+ status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+ oldmode, sizeof(oldmode), 0, 0, 0, 0);
+ if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+ return (FALSE);
+ cdscp = NULL; /* Assume DCL. */
+ if (cmd != NULL) { /* Build descriptor. */
+ cdsc.dsc$a_pointer = cmd;
+ cdsc.dsc$w_length = strlen(cmd);
+ cdsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ cdsc.dsc$b_class = DSC$K_CLASS_S;
+ cdscp = &cdsc;
+ }
+ status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
+ if (status != SS$_NORMAL)
+ substatus = status;
+ status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+ newmode, sizeof(newmode), 0, 0, 0, 0);
+ if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+ return (FALSE);
+ if ((substatus&STS$M_SUCCESS) == 0) /* Command failed. */
+ return (FALSE);
+ return (TRUE);
+}
+#endif
+
+#if ~AZTEC & MSDOS
+
+/*
+ * This routine, once again by Bob McNamara, is a C translation of the "system"
+ * routine in the MWC-86 run time library. It differs from the "system" routine
+ * in that it does not unconditionally append the string ".exe" to the end of
+ * the command name. We needed to do this because we want to be able to spawn
+ * off "command.com". We really do not understand what it does, but if you don't
+ * do it exactly "malloc" starts doing very very strange things.
+ */
+sys(cmd, tail)
+char *cmd;
+char *tail;
+{
+#if MWC_86
+ register unsigned n;
+ extern char *__end;
+
+ n = __end + 15;
+ n >>= 4;
+ n = ((n + dsreg() + 16) & 0xFFF0) + 16;
+ return(execall(cmd, tail, n));
+#endif
+
+#if LATTICE
+ return(forklp(cmd, tail, (char *)NULL));
+#endif
+
+#if MSC
+ return(spawnlp(P_WAIT, cmd, tail, NULL));
+#endif
+}
+#endif
+
+#if MSDOS & LATTICE
+/* System: a modified version of lattice's system() function
+ that detects the proper switchar and uses it
+ written by Dana Hogget */
+
+system(cmd)
+
+char *cmd; /* Incoming command line to execute */
+
+{
+ char *getenv();
+ static char *swchar = "/C"; /* Execution switch */
+ union REGS inregs; /* parameters for dos call */
+ union REGS outregs; /* Return results from dos call */
+ char *shell; /* Name of system command processor */
+ char *p; /* Temporary pointer */
+ int ferr; /* Error condition if any */
+
+ /* get name of system shell */
+ if ((shell = getenv("COMSPEC")) == NULL) {
+ return (-1); /* No shell located */
+ }
+
+ p = cmd;
+ while (isspace(*p)) { /* find out if null command */
+ p++;
+ }
+
+ /** If the command line is not empty, bring up the shell **/
+ /** and execute the command. Otherwise, bring up the **/
+ /** shell in interactive mode. **/
+
+ if (p && *p) {
+ /** detect current switch character and us it **/
+ inregs.h.ah = 0x37; /* get setting data */
+ inregs.h.al = 0x00; /* get switch character */
+ intdos(&inregs, &outregs);
+ *swchar = outregs.h.dl;
+ ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
+ } else {
+ ferr = forkl(shell, "command", (char *)NULL);
+ }
+
+ return (ferr ? ferr : wait());
+}
+#endif
+
Added: clients/emacs/tags
===================================================================
--- clients/emacs/tags (rev 0)
+++ clients/emacs/tags 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,371 @@
+Mmain main.c /^main(argc, argv)$/
+addline buffer.c /^addline(text)$/
+adjustmode random.c /^adjustmode(kind, global) \/* change the editor mode/
+agios hp150.c /^agios(buf, len) \/* perform an AGIOS call *\/$/
+amg_flush termio.c /^amg_flush()$/
+ansibcol ansi.c /^ansibcol(color) \/* set the current background col/
+ansibeep ansi.c /^ansibeep()$/
+ansiclose ansi.c /^ansiclose()$/
+ansieeol ansi.c /^ansieeol()$/
+ansieeop ansi.c /^ansieeop()$/
+ansifcol ansi.c /^ansifcol(color) \/* set the current output color */
+ansihello ansi.c /^ansihello()$/
+ansimove ansi.c /^ansimove(row, col)$/
+ansiopen ansi.c /^ansiopen()$/
+ansiparm ansi.c /^ansiparm(n)$/
+ansirev ansi.c /^ansirev(state) \/* change reverse video state *\/$/
+anycb buffer.c /^anycb()$/
+backchar basic.c /^backchar(f, n)$/
+backdel random.c /^backdel(f, n)$/
+backhunt search.c /^backhunt(f, n) \/* hunt backward for the last searc/
+backline basic.c /^backline(f, n)$/
+backpage basic.c /^backpage(f, n)$/
+backsearch search.c /^backsearch(f, n)$/
+backword word.c /^backword(f, n)$/
+bakscan isearch.c /^int bakscan (patrn) \/* Scan backwards for a match/
+bclear buffer.c /^bclear(bp)$/
+bfind buffer.c /^bfind(bname, cflag, bflag)$/
+bindtokey bind.c /^bindtokey(f, n)$/
+bktoshell spawn.c /^bktoshell() \/* suspend MicroEMACS and wait to wak/
+bsearchcom search.c /^bsearchcom(f, n)$/
+capword word.c /^capword(f, n)$/
+cbuf exec.c /^cbuf(f, n, bufnum)$/
+cbuf1 exec.c /^cbuf1(f, n)$/
+cbuf10 exec.c /^cbuf10(f, n)$/
+cbuf11 exec.c /^cbuf11(f, n)$/
+cbuf12 exec.c /^cbuf12(f, n)$/
+cbuf13 exec.c /^cbuf13(f, n)$/
+cbuf14 exec.c /^cbuf14(f, n)$/
+cbuf15 exec.c /^cbuf15(f, n)$/
+cbuf16 exec.c /^cbuf16(f, n)$/
+cbuf17 exec.c /^cbuf17(f, n)$/
+cbuf18 exec.c /^cbuf18(f, n)$/
+cbuf19 exec.c /^cbuf19(f, n)$/
+cbuf2 exec.c /^cbuf2(f, n)$/
+cbuf20 exec.c /^cbuf20(f, n)$/
+cbuf21 exec.c /^cbuf21(f, n)$/
+cbuf22 exec.c /^cbuf22(f, n)$/
+cbuf23 exec.c /^cbuf23(f, n)$/
+cbuf24 exec.c /^cbuf24(f, n)$/
+cbuf25 exec.c /^cbuf25(f, n)$/
+cbuf26 exec.c /^cbuf26(f, n)$/
+cbuf27 exec.c /^cbuf27(f, n)$/
+cbuf28 exec.c /^cbuf28(f, n)$/
+cbuf29 exec.c /^cbuf29(f, n)$/
+cbuf3 exec.c /^cbuf3(f, n)$/
+cbuf30 exec.c /^cbuf30(f, n)$/
+cbuf31 exec.c /^cbuf31(f, n)$/
+cbuf32 exec.c /^cbuf32(f, n)$/
+cbuf33 exec.c /^cbuf33(f, n)$/
+cbuf34 exec.c /^cbuf34(f, n)$/
+cbuf35 exec.c /^cbuf35(f, n)$/
+cbuf36 exec.c /^cbuf36(f, n)$/
+cbuf37 exec.c /^cbuf37(f, n)$/
+cbuf38 exec.c /^cbuf38(f, n)$/
+cbuf39 exec.c /^cbuf39(f, n)$/
+cbuf4 exec.c /^cbuf4(f, n)$/
+cbuf40 exec.c /^cbuf40(f, n)$/
+cbuf5 exec.c /^cbuf5(f, n)$/
+cbuf6 exec.c /^cbuf6(f, n)$/
+cbuf7 exec.c /^cbuf7(f, n)$/
+cbuf8 exec.c /^cbuf8(f, n)$/
+cbuf9 exec.c /^cbuf9(f, n)$/
+cex main.c /^cex() \/* dummy function for binding to control-x p/
+checknext isearch.c /^int checknext (chr, patrn, dir, sts)\/* Check next /
+cinsert random.c /^cinsert() \/* insert a newline and indentation for /
+ckeyoff hp150.c /^ckeyoff() \/* turn control-C trapping off *\/$/
+ckeyon hp150.c /^ckeyon() \/* turn control-C trapping on *\/$/
+closehp hp150.c /^closehp() \/* close the HP150 keyboard for input */
+clrmes random.c /^clrmes(f, n)$/
+cmdstr bind.c /^cmdstr(c, seq) \/* change a key command to a string/
+copyregion region.c /^copyregion(f, n)$/
+ctlxe main.c /^ctlxe(f, n)$/
+ctlxlp main.c /^ctlxlp(f, n)$/
+ctlxrp main.c /^ctlxrp(f, n)$/
+ctrlg main.c /^ctrlg(f, n)$/
+deblank random.c /^deblank(f, n)$/
+defkey hp150.c /^defkey() \/* change all special keys to intercept m/
+delbword word.c /^delbword(f, n)$/
+delfword word.c /^delfword(f, n)$/
+delgmode random.c /^delgmode(f, n) \/* prompt and delete a global edito/
+delmode random.c /^delmode(f, n) \/* prompt and delete an editor mode /
+delwind window.c /^delwind(f,n)$/
+desbind bind.c /^desbind(f, n) \/* describe bindings$/
+deskey bind.c /^deskey(f, n) \/* describe the command for a certain/
+dg10bcol dg10.c /^dg10bcol(color) \/* set the current background col/
+dg10beep dg10.c /^dg10beep()$/
+dg10close dg10.c /^dg10close()$/
+dg10eeol dg10.c /^dg10eeol()$/
+dg10eeop dg10.c /^dg10eeop()$/
+dg10fcol dg10.c /^dg10fcol(color) \/* set the current output color */
+dg10hello dg10.c /^dg10hello()$/
+dg10move dg10.c /^dg10move(row, col)$/
+dg10open dg10.c /^dg10open()$/
+dg10rev dg10.c /^dg10rev(state) \/* change reverse video state *\/$/
+dobuf exec.c /^dobuf(bp)$/
+docmd exec.c /^docmd(cline)$/
+dofile exec.c /^dofile(fname)$/
+echochar isearch.c /^int echochar(c,col)$/
+edinit main.c /^edinit(bname)$/
+eltoa buffer.c /^eltoa(buf, width, num)$/
+emacs_main main.c /^emacs_main(argc, argv)$/
+enlargewind window.c /^enlargewind(f, n)$/
+eq search.c /^eq(bc, pc)$/
+errexit main.c /^errexit()$/
+execbuf exec.c /^execbuf(f, n)$/
+execcmd exec.c /^execcmd(f, n)$/
+execfile exec.c /^execfile(f, n) \/* execute a series of commands in /
+execute main.c /^execute(c, f, n)$/
+expandp search.c /^expandp(srcstr, deststr, maxlength)$/
+far_out ibmpc.c /^far_out(source, dest, size)$/
+ffclose fileio.c /^ffclose()$/
+ffgetline fileio.c /^ffgetline(buf, nbuf)$/
+ffputline fileio.c /^ffputline(buf, nbuf)$/
+ffropen fileio.c /^ffropen(fn)$/
+ffwopen fileio.c /^ffwopen(fn)$/
+filefind file.c /^filefind(f, n)$/
+filename file.c /^filename(f, n)$/
+fileread file.c /^fileread(f, n)$/
+filesave file.c /^filesave(f, n)$/
+filewrite file.c /^filewrite(f, n)$/
+fillpara word.c /^fillpara(f, n) \/* Fill the current paragraph accor/
+filter spawn.c /^filter(f, n)$/
+fisearch isearch.c /^int fisearch(f, n)$/
+fmatch random.c /^fmatch(ch)$/
+fncmatch bind.c /^int (*fncmatch(fname))() \/* match fname to a funct/
+forscan search.c /^forscan(patrn,leavep) \/* search forward for a <pat/
+forwchar basic.c /^forwchar(f, n)$/
+forwdel random.c /^forwdel(f, n)$/
+forwhunt search.c /^forwhunt(f, n)$/
+forwline basic.c /^forwline(f, n)$/
+forwpage basic.c /^forwpage(f, n)$/
+forwsearch search.c /^forwsearch(f, n)$/
+forwword word.c /^forwword(f, n)$/
+get1key input.c /^get1key()$/
+get_char isearch.c /^int get_char ()$/
+getccol random.c /^getccol(bflg)$/
+getckey bind.c /^getckey(mflag) \/* get a command key sequence from /
+getcmd input.c /^getcmd()$/
+getfile file.c /^getfile(fname, lockfl)$/
+getgoal basic.c /^getgoal(dlp)$/
+gethpkey hp150.c /^gethpkey() \/* get a key from the HP keyboard while/
+getname input.c /^int (*getname())()$/
+getregion region.c /^getregion(rp)$/
+gettok exec.c /^char *gettok(src, tok)$/
+gotobob basic.c /^gotobob(f, n)$/
+gotobol basic.c /^gotobol(f, n)$/
+gotobop basic.c /^gotobop(f, n) \/* go back to the begining of the cu/
+gotoeob basic.c /^gotoeob(f, n)$/
+gotoeol basic.c /^gotoeol(f, n)$/
+gotoeop basic.c /^gotoeop(f, n) \/* go forword to the end of the curr/
+gotoline basic.c /^gotoline(f, n) \/* move to a particular line.$/
+h15hello hp150.c /^h15hello()$/
+hello tcap.c /^hello()$/
+hellovms vmsvt.c /^hellovms()$/
+help bind.c /^help(f, n) \/* give me some help!!!!$/
+hp15bcol hp150.c /^hp15bcol() \/* we really can't do colors here, so j/
+hp15beep hp150.c /^hp15beep()$/
+hp15eeol hp150.c /^hp15eeol()$/
+hp15eeop hp150.c /^hp15eeop()$/
+hp15fcol hp150.c /^hp15fcol() \/* we really can't do colors here, so j/
+hp15move hp150.c /^hp15move(row, col)$/
+hp15parm hp150.c /^hp15parm(n)$/
+hp15rev hp150.c /^hp15rev(status) \/* change the reverse video statu/
+hpflush hp150.c /^hpflush()$/
+ibmbcol ibmpc.c /^ibmbcol(color) \/* set the current background colo/
+ibmbeep ibmpc.c /^ibmbeep()$/
+ibmclose ibmpc.c /^ibmclose()$/
+ibmeeol ibmpc.c /^ibmeeol() \/* erase to the end of the line *\/$/
+ibmeeop ibmpc.c /^ibmeeop()$/
+ibmfcol ibmpc.c /^ibmfcol(color) \/* set the current output color *\//
+ibmhello ibmpc.c /^ibmhello()$/
+ibmmove ibmpc.c /^ibmmove(row, col)$/
+ibmopen ibmpc.c /^ibmopen()$/
+ibmputc ibmpc.c /^ibmputc(ch) \/* put a character at the current posi/
+ibmrev ibmpc.c /^ibmrev(state) \/* change reverse video state *\/$/
+ifile file.c /^ifile(fname)$/
+indent random.c /^indent(f, n)$/
+insbrace random.c /^insbrace(n, c) \/* insert a brace into the text her/
+insfile file.c /^insfile(f, n)$/
+inspound random.c /^inspound() \/* insert a # into the text here...we a/
+insspace line.c /^insspace(f, n) \/* insert spaces forward into text /
+inword word.c /^inword()$/
+isearch isearch.c /^isearch(f, n)$/
+istring random.c /^istring(f, n) \/* ask for and insert a string into /
+kbdtext input.c /^kbdtext(buf) \/* add this text string to the curren/
+kdelete line.c /^kdelete()$/
+keycoff hp150.c /^keycoff() \/* turn keycode mode off *\/$/
+keycon hp150.c /^keycon() \/* turn keycode mode on *\/$/
+killbuffer buffer.c /^killbuffer(f, n)$/
+killpara word.c /^killpara(f, n) \/* delete n paragraphs starting wit/
+killregion region.c /^killregion(f, n)$/
+killtext random.c /^killtext(f, n)$/
+kinsert line.c /^kinsert(c)$/
+lalloc line.c /^lalloc(used)$/
+lback estruct.h /^#define lback(lp) ((lp)->l_bp)$/
+lback estructp.h /^#define lback(lp) ((lp)->l_bp)$/
+lchange line.c /^lchange(flag)$/
+lckerror lock.c /^lckerror(errstr) \/* report a lock error *\/$/
+lckhello lock.c /^lckhello() \/* dummy function *\/$/
+ldelete line.c /^ldelete(n, kflag)$/
+ldelnewline line.c /^ldelnewline()$/
+lforw estruct.h /^#define lforw(lp) ((lp)->l_fp)$/
+lforw estructp.h /^#define lforw(lp) ((lp)->l_fp)$/
+lfree line.c /^lfree(lp)$/
+lgetc estruct.h /^#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)$/
+lgetc estructp.h /^#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)$/
+linsert line.c /^linsert(n, c)$/
+listbuffers buffer.c /^listbuffers(f, n)$/
+llength estruct.h /^#define llength(lp) ((lp)->l_used)$/
+llength estructp.h /^#define llength(lp) ((lp)->l_used)$/
+lnewline line.c /^lnewline()$/
+lock lock.c /^lock(fname)$/
+lockchk lock.c /^lockchk(fname)$/
+lockrel lock.c /^lockrel()$/
+lowerregion region.c /^lowerregion(f, n)$/
+lowerword word.c /^lowerword(f, n)$/
+lputc estruct.h /^#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))$/
+lputc estructp.h /^#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))$/
+makelist buffer.c /^makelist()$/
+makename file.c /^makename(bname, fname)$/
+match_pat isearch.c /^int match_pat (patrn) \/* See if the pattern string/
+meta main.c /^meta() \/* dummy function for binding to meta prefi/
+mlerase display.c /^mlerase()$/
+mlputf display.c /^mlputf(s)$/
+mlputi display.c /^mlputi(i, r)$/
+mlputli display.c /^mlputli(l, r)$/
+mlputs display.c /^mlputs(s)$/
+mlreply input.c /^mlreply(prompt, buf, nbuf)$/
+mlreplyt input.c /^mlreplyt(prompt, buf, nbuf, eolchar)$/
+mlwrite display.c /^mlwrite(fmt, arg)$/
+mlyesno input.c /^mlyesno(prompt)$/
+modeline display.c /^modeline(wp)$/
+movecursor display.c /^movecursor(row, col)$/
+mvdnwind window.c /^mvdnwind(f, n)$/
+mvupwind window.c /^mvupwind(f, n)$/
+namebuffer buffer.c /^namebuffer(f,n) \/* Rename the current buffer *\/$/
+namedcmd exec.c /^namedcmd(f, n)$/
+newline random.c /^newline(f, n)$/
+nextbuffer buffer.c /^nextbuffer(f, n) \/* switch to the next buffer in t/
+nextwind window.c /^nextwind(f, n)$/
+nxtarg exec.c /^nxtarg(tok)$/
+onlywind window.c /^onlywind(f, n)$/
+openhp hp150.c /^openhp() \/* open the HP150 keyboard for input *\/$/
+openline random.c /^openline(f, n)$/
+pipe spawn.c /^pipe(f, n)$/
+prevwind window.c /^prevwind(f, n)$/
+promptpattern isearch.c /^int promptpattern(prompt)$/
+putline display.c /^putline(row, col, buf)$/
+putnpad tcap.c /^putnpad(str, n)$/
+putpad tcap.c /^putpad(str)$/
+qreplace search.c /^qreplace(f, n) \/* search and replace with query (E/
+quickexit main.c /^quickexit(f, n)$/
+quit main.c /^quit(f, n)$/
+quote random.c /^quote(f, n)$/
+rawoff hp150.c /^rawoff() \/* put the HP150 keyboard into COOKED mod/
+rawon hp150.c /^rawon() \/* put the HP150 keyboard into RAW mode */
+rdonly main.c /^rdonly()$/
+readin file.c /^readin(fname, lockfl)$/
+readpattern search.c /^readpattern(prompt)$/
+reeat isearch.c /^int reeat(c)$/
+reframe display.c /^reframe(wp)$/
+refresh window.c /^refresh(f, n)$/
+replaces search.c /^replaces(kind, f, n)$/
+reposition window.c /^reposition(f, n)$/
+resize window.c /^resize(f, n)$/
+restwnd window.c /^restwnd(f, n) \/* restore the saved screen *\/$/
+risearch isearch.c /^int risearch(f, n)$/
+rtfrmshell spawn.c /^rtfrmshell()$/
+savewnd window.c /^savewnd(f, n) \/* save ptr to current window *\/$/
+scanmore isearch.c /^int scanmore(patrn,dir,sts) \/* search forward or b/
+scinit ibmpc.c /^scinit() \/* initialize the screen head pointers *\//
+scrnextdw window.c /^scrnextdw(f, n) \/* scroll the next window down (f/
+scrnextup window.c /^scrnextup(f, n) \/* scroll the next window up (bac/
+scwrite ibmpc.c /^scwrite(row, outstr, forg, bacg) \/* write a line o/
+setfillcol random.c /^setfillcol(f, n)$/
+setgmode random.c /^setgmode(f, n) \/* prompt and set a global editor m/
+setmark basic.c /^setmark(f, n)$/
+setmode random.c /^setmode(f, n) \/* prompt and set an editor mode *\/$/
+showcpos random.c /^showcpos(f, n)$/
+shrinkwind window.c /^shrinkwind(f, n)$/
+spawn spawn.c /^spawn(f, n)$/
+spawncli spawn.c /^spawncli(f, n)$/
+splitwind window.c /^splitwind(f, n)$/
+sreplace search.c /^sreplace(f, n) \/* Search and replace (ESC-R) *\/$/
+startup bind.c /^startup(sfname)$/
+storemac exec.c /^storemac(f, n)$/
+swapmark basic.c /^swapmark(f, n)$/
+swbuffer buffer.c /^swbuffer(bp) \/* make buffer BP current *\/$/
+sys spawn.c /^sys(cmd)$/
+sys spawn.c /^sys(cmd, tail)$/
+system spawn.c /^#define system(a) spawnlp(P_WAIT, a, NULL)$/
+system spawn.c /^system(cmd)$/
+tab random.c /^tab(f, n)$/
+tcapbcol tcap.c /^tcapbcol() \/* no colors here, ignore this *\/$/
+tcapbeep tcap.c /^tcapbeep()$/
+tcapeeol tcap.c /^tcapeeol()$/
+tcapeeop tcap.c /^tcapeeop()$/
+tcapfcol tcap.c /^tcapfcol() \/* no colors here, ignore this *\/$/
+tcapmove tcap.c /^tcapmove(row, col)$/
+tcapopen tcap.c /^tcapopen()$/
+tcaprev tcap.c /^tcaprev(state) \/* change reverse video status *\/$/
+ttclose termio.c /^ttclose()$/
+ttflush termio.c /^ttflush()$/
+ttgetc termio.c /^ttgetc()$/
+ttopen termio.c /^ttopen()$/
+ttputc termio.c /^ttputc(c)$/
+ttputs vmsvt.c /^ttputs(string)$/
+twiddle random.c /^twiddle(f, n)$/
+typahead termio.c /^typahead()$/
+unbindkey bind.c /^unbindkey(f, n)$/
+undefkey hp150.c /^undefkey() \/* change all special keys to intercept/
+uneat isearch.c /^int uneat()$/
+unlock lock.c /^unlock(fname)$/
+unmark buffer.c /^unmark(f, n) \/* unmark the current buffers change /
+updall display.c /^updall(wp)$/
+update display.c /^update(force)$/
+updateline display.c /^updateline(row, vp1)$/
+updateline display.c /^updateline(row, vp1, vp2)$/
+upddex display.c /^upddex()$/
+updext display.c /^updext()$/
+updgar display.c /^updgar()$/
+updone display.c /^updone(wp)$/
+updpos display.c /^updpos()$/
+updupd display.c /^updupd(force)$/
+upmode display.c /^upmode() \/* update all the mode lines *\/$/
+upperregion region.c /^upperregion(f, n)$/
+upperword word.c /^upperword(f, n)$/
+upscreen display.c /^upscreen(f, n)$/
+usebuffer buffer.c /^usebuffer(f, n)$/
+viewfile file.c /^viewfile(f, n) \/* visit a file in VIEW mode *\/$/
+vmsbcol vmsvt.c /^vmsbcol()$/
+vmsbeep vmsvt.c /^vmsbeep()$/
+vmseeol vmsvt.c /^vmseeol()$/
+vmseeop vmsvt.c /^vmseeop()$/
+vmsfcol vmsvt.c /^vmsfcol()$/
+vmsgtty vmsvt.c /^vmsgtty()$/
+vmsmove vmsvt.c /^vmsmove(row, col)$/
+vmsopen vmsvt.c /^vmsopen()$/
+vmspad vmsvt.c /^vmspad(count)$/
+vmsrev vmsvt.c /^vmsrev(status)$/
+vt52bcol vt52.c /^vt52bcol() \/* set the background color [NOT IMPLIM/
+vt52beep vt52.c /^vt52beep()$/
+vt52eeol vt52.c /^vt52eeol()$/
+vt52eeop vt52.c /^vt52eeop()$/
+vt52fcol vt52.c /^vt52fcol() \/* set the forground color [NOT IMPLIME/
+vt52move vt52.c /^vt52move(row, col)$/
+vt52open vt52.c /^vt52open()$/
+vt52rev vt52.c /^vt52rev(status) \/* set the reverse video state *\/$/
+vteeol display.c /^vteeol()$/
+vtinit display.c /^vtinit()$/
+vtmove display.c /^vtmove(row, col)$/
+vtputc display.c /^vtputc(c)$/
+vtpute display.c /^vtpute(c)$/
+vttidy display.c /^vttidy()$/
+wordcount word.c /^wordcount(f, n)$/
+wpopup window.c /^wpopup()$/
+wrapword word.c /^wrapword(n)$/
+writemsg random.c /^writemsg(f, n)$/
+writeout file.c /^writeout(fn)$/
+yank line.c /^yank(f, n)$/
+zotbuf buffer.c /^zotbuf(bp) \/* kill the buffer pointed to by bp *\/$/
Added: clients/emacs/tcap.c
===================================================================
--- clients/emacs/tcap.c (rev 0)
+++ clients/emacs/tcap.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,202 @@
+/* tcap: Unix V5, V7 and BS4.2 Termcap video driver
+ for MicroEMACS
+*/
+
+#define termdef 1 /* don't define "term" external */
+
+#include "estruct.h"
+#include "edef.h"
+
+#if TERMCAP
+
+#define MARGIN 8
+#define SCRSIZ 64
+#define NPAUSE 10 /* # times thru update to pause */
+#define BEL 0x07
+#define ESC 0x1B
+
+extern int ttopen();
+extern int ttgetc();
+extern int ttputc();
+extern int tgetnum();
+extern int ttflush();
+extern int ttclose();
+extern int tcapmove();
+extern int tcapeeol();
+extern int tcapeeop();
+extern int tcapbeep();
+extern int tcaprev();
+extern int tcapopen();
+extern int tput();
+extern char *tgoto();
+#if COLOR
+extern int tcapfcol();
+extern int tcapbcol();
+#endif
+
+#define TCAPSLEN 315
+char tcapbuf[TCAPSLEN];
+char *UP, PC, *CM, *CE, *CL, *SO, *SE;
+
+TERM term = {
+ NULL, /* these two values are set dynamically at open time */
+ NULL,
+ MARGIN,
+ SCRSIZ,
+ NPAUSE,
+ tcapopen,
+ ttclose,
+ ttgetc,
+ ttputc,
+ ttflush,
+ tcapmove,
+ tcapeeol,
+ tcapeeop,
+ tcapbeep,
+ tcaprev
+#if COLOR
+ , tcapfcol,
+ tcapbcol
+#endif
+};
+
+tcapopen()
+
+{
+ char *getenv();
+ char *t, *p, *tgetstr();
+ char tcbuf[1024];
+ char *tv_stype;
+ char err_str[72];
+
+ if ((tv_stype = getenv("TERM")) == NULL)
+ {
+ puts("Environment variable TERM not defined!");
+ exit(1);
+ }
+
+ if ((tgetent(tcbuf, tv_stype)) != 1)
+ {
+ sprintf(err_str, "Unknown terminal type %s!", tv_stype);
+ puts(err_str);
+ exit(1);
+ }
+
+
+ if ((term.t_nrow=(short)tgetnum("li")-1) == -1){
+ puts("termcap entry incomplete (lines)");
+ exit(1);
+ }
+
+ if ((term.t_ncol=(short)tgetnum("co")) == -1){
+ puts("Termcap entry incomplete (columns)");
+ exit(1);
+ }
+
+ p = tcapbuf;
+ t = tgetstr("pc", &p);
+ if(t)
+ PC = *t;
+
+ CL = tgetstr("cl", &p);
+ CM = tgetstr("cm", &p);
+ CE = tgetstr("ce", &p);
+ UP = tgetstr("up", &p);
+ SE = tgetstr("se", &p);
+ SO = tgetstr("so", &p);
+ if (SO != NULL)
+ revexist = TRUE;
+
+ if(CL == NULL || CM == NULL || UP == NULL)
+ {
+ puts("Incomplete termcap entry\n");
+ exit(1);
+ }
+
+ if (CE == NULL) /* will we be able to use clear to EOL? */
+ eolexist = FALSE;
+
+ if (p >= &tcapbuf[TCAPSLEN])
+ {
+ puts("Terminal description too big!\n");
+ exit(1);
+ }
+ ttopen();
+}
+
+tcapmove(row, col)
+register int row, col;
+{
+ putpad(tgoto(CM, col, row));
+}
+
+tcapeeol()
+{
+ putpad(CE);
+}
+
+tcapeeop()
+{
+ putpad(CL);
+}
+
+tcaprev(state) /* change reverse video status */
+
+int state; /* FALSE = normal video, TRUE = reverse video */
+
+{
+ static int revstate = FALSE;
+ /* mustn't send SE unless SO already sent, and vice versa */
+
+#if 0
+ if (state) {
+ if ((SO != NULL) && (revstate == FALSE))
+ putpad(SO);
+ } else
+ if ((SE != NULL) && (revstate == TRUE))
+ putpad(SE);
+
+ revstate = state;
+#endif
+ if (state) {
+ if (SO != NULL)
+ putpad(SO);
+ } else
+ if (SE != NULL)
+ putpad(SE);
+}
+
+#if COLOR
+tcapfcol() /* no colors here, ignore this */
+{
+}
+
+tcapbcol() /* no colors here, ignore this */
+{
+}
+#endif
+
+tcapbeep()
+{
+ ttputc(BEL);
+}
+
+putpad(str)
+char *str;
+{
+ tputs(str, 1, ttputc);
+}
+
+putnpad(str, n)
+char *str;
+{
+ tputs(str, n, ttputc);
+}
+
+#else
+
+hello()
+{
+}
+
+#endif TERMCAP
Added: clients/emacs/termio.c
===================================================================
--- clients/emacs/termio.c (rev 0)
+++ clients/emacs/termio.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,476 @@
+/*
+ * The functions in this file negotiate with the operating system for
+ * characters, and write characters in a barely buffered fashion on the display.
+ * All operating systems.
+ */
+
+#include "estruct.h"
+#include "edef.h"
+#ifdef __ZTC__
+#include <dos.h>
+#endif
+#if V7 | USG | BSD | OFW
+#include "stdio.h"
+#endif
+
+#if AMIGA
+#define NEW 1006
+#define AMG_MAXBUF 1024
+static long terminal;
+static char scrn_tmp[AMG_MAXBUF+1];
+static int scrn_tmp_p = 0;
+#endif
+
+#if VMS
+#include <stsdef.h>
+#include <ssdef.h>
+#include <descrip.h>
+#include <iodef.h>
+#include <ttdef.h>
+#include <tt2def.h>
+
+#define NIBUF 128 /* Input buffer size */
+#define NOBUF 1024 /* MM says bug buffers win! */
+#define EFN 0 /* Event flag */
+
+char obuf[NOBUF]; /* Output buffer */
+int nobuf; /* # of bytes in above */
+char ibuf[NIBUF]; /* Input buffer */
+int nibuf; /* # of bytes in above */
+int ibufi; /* Read index */
+int oldmode[3]; /* Old TTY mode bits */
+int newmode[3]; /* New TTY mode bits */
+short iochan; /* TTY I/O channel */
+#endif
+
+#if CPM
+#include <bdos.h>
+#endif
+
+#if MSDOS & (LATTICE | MSDOS)
+union REGS rg; /* cpu register for use of DOS calls */
+int nxtchar = -1; /* character held from type ahead */
+#endif
+
+#if RAINBOW
+#include "rainbow.h"
+#endif
+
+#if USG /* System V */
+#include <signal.h>
+#include <termio.h>
+struct termio otermio; /* original terminal characteristics */
+struct termio ntermio; /* charactoristics to use inside */
+#endif
+
+#if V7 | BSD
+#undef CTRL
+#include <sgtty.h> /* for stty/gtty functions */
+#include <signal.h>
+struct sgttyb ostate; /* saved tty state */
+struct sgttyb nstate; /* values for editor mode */
+struct tchars otchars; /* Saved terminal special character set */
+struct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ /* A lot of nothing */
+#if BSD
+#include <sys/ioctl.h> /* to get at the typeahead */
+extern int rtfrmshell(); /* return from suspended shell */
+#define TBUFSIZ 128
+char tobuf[TBUFSIZ]; /* terminal output buffer */
+#endif
+#endif
+
+/*
+ * This function is called once to set up the terminal device streams.
+ * On VMS, it translates TT until it finds the terminal, then assigns
+ * a channel to it and sets it raw. On CPM it is a no-op.
+ */
+ttopen()
+{
+ /* on all screens we are not sure of the initial position
+ of the cursor */
+ ttrow = 999;
+ ttcol = 999;
+
+#if AMIGA
+ terminal = Open("RAW:1/1/639/199/MicroEMACS 3.7/Amiga", NEW);
+#endif
+#if VMS
+ struct dsc$descriptor idsc;
+ struct dsc$descriptor odsc;
+ char oname[40];
+ int iosb[2];
+ int status;
+
+ odsc.dsc$a_pointer = "TT";
+ odsc.dsc$w_length = strlen(odsc.dsc$a_pointer);
+ odsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ odsc.dsc$b_class = DSC$K_CLASS_S;
+ idsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ idsc.dsc$b_class = DSC$K_CLASS_S;
+ do {
+ idsc.dsc$a_pointer = odsc.dsc$a_pointer;
+ idsc.dsc$w_length = odsc.dsc$w_length;
+ odsc.dsc$a_pointer = &oname[0];
+ odsc.dsc$w_length = sizeof(oname);
+ status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
+ if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
+ exit(status);
+ if (oname[0] == 0x1B) {
+ odsc.dsc$a_pointer += 4;
+ odsc.dsc$w_length -= 4;
+ }
+ } while (status == SS$_NORMAL);
+ status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
+ if (status != SS$_NORMAL)
+ exit(status);
+ status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
+ oldmode, sizeof(oldmode), 0, 0, 0, 0);
+ if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+ exit(status);
+ newmode[0] = oldmode[0];
+ newmode[1] = oldmode[1] | TT$M_NOECHO;
+ newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
+ newmode[2] = oldmode[2] | TT2$M_PASTHRU;
+ status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+ newmode, sizeof(newmode), 0, 0, 0, 0);
+ if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+ exit(status);
+ term.t_nrow = (newmode[1]>>24) - 1;
+ term.t_ncol = newmode[0]>>16;
+
+#endif
+#if CPM
+#endif
+
+#if MSDOS & (HP150 == 0) & LATTICE
+ /* kill the ctrl-break interupt */
+ rg.h.ah = 0x33; /* control-break check dos call */
+ rg.h.al = 1; /* set the current state */
+ rg.h.dl = 0; /* set it OFF */
+ intdos(&rg, &rg); /* go for it! */
+#endif
+
+#if USG
+ ioctl(o, TCGETA, &otermio); /* save old settings */
+ ntermio.c_iflag = 0; /* setup new settings */
+ ntermio.c_oflag = 0;
+ ntermio.c_cflag = otermio.c_cflag;
+ ntermio.c_lflag = 0;
+ ntermio.c_line = otermio.c_line;
+ ntermio.c_cc[VMIN] = 1;
+ ntermio.c_cc[VTIME] = 0;
+ ioctl(0, TCSETA, &ntermio); /* and activate them */
+#endif
+
+#if V7 | BSD
+ gtty(0, &ostate); /* save old state */
+ gtty(0, &nstate); /* get base of new state */
+ nstate.sg_flags |= RAW;
+ nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */
+ stty(0, &nstate); /* set mode */
+ ioctl(0, TIOCGETC, &otchars); /* Save old characters */
+ ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */
+#if BSD
+ /* provide a smaller terminal output buffer so that
+ the type ahead detection works better (more often) */
+ setbuffer(stdout, &tobuf[0], TBUFSIZ);
+ signal(SIGTSTP,SIG_DFL); /* set signals so that we can */
+ signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */
+#endif
+#endif
+}
+
+/*
+ * This function gets called just before we go back home to the command
+ * interpreter. On VMS it puts the terminal back in a reasonable state.
+ * Another no-operation on CPM.
+ */
+ttclose()
+{
+#if AMIGA
+ amg_flush();
+ Close(terminal);
+#endif
+#if VMS
+ int status;
+ int iosb[1];
+
+ ttflush();
+ status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+ oldmode, sizeof(oldmode), 0, 0, 0, 0);
+ if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+ exit(status);
+ status = SYS$DASSGN(iochan);
+ if (status != SS$_NORMAL)
+ exit(status);
+#endif
+#if CPM
+#endif
+#if MSDOS & (HP150 == 0) & LATTICE
+ /* restore the ctrl-break interupt */
+ rg.h.ah = 0x33; /* control-break check dos call */
+ rg.h.al = 1; /* set the current state */
+ rg.h.dl = 1; /* set it ON */
+ intdos(&rg, &rg); /* go for it! */
+#endif
+
+#if USG
+ ioctl(0, TCSETA, &otermio); /* restore terminal settings */
+#endif
+
+#if V7 | BSD
+ stty(0, &ostate);
+ ioctl(0, TIOCSETC, &otchars); /* Place old character into K */
+#endif
+#if OFW
+ ansibcol(7);
+ ansifcol(0);
+ ansieeol();
+ ttflush();
+ OFInterpret0("false to already-go?");
+#endif
+}
+
+/*
+ * Write a character to the display. On VMS, terminal output is buffered, and
+ * we just put the characters in the big array, after checking for overflow.
+ * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
+ * MS-DOS (use the very very raw console output routine).
+ */
+ttputc(c)
+#if AMIGA
+ char c;
+#endif
+{
+#if AMIGA
+ scrn_tmp[scrn_tmp_p++] = c;
+ if(scrn_tmp_p>=AMG_MAXBUF)
+ amg_flush();
+#endif
+#if VMS
+ if (nobuf >= NOBUF)
+ ttflush();
+ obuf[nobuf++] = c;
+#endif
+
+#if CPM
+ bios(BCONOUT, c, 0);
+#endif
+
+#if MSDOS & MWC86
+ dosb(CONDIO, c, 0);
+#endif
+
+#if MSDOS & (LATTICE | AZTEC | MSC) & ~IBMPC
+ bdos(6, c, 0);
+#endif
+
+#if RAINBOW
+ Put_Char(c); /* fast video */
+#endif
+
+
+#if V7 | USG | BSD | OFW
+ fputc(c, stdout);
+#endif
+}
+
+#if AMIGA
+amg_flush()
+{
+ if(scrn_tmp_p)
+ Write(terminal,scrn_tmp,scrn_tmp_p);
+ scrn_tmp_p = 0;
+}
+#endif
+
+/*
+ * Flush terminal buffer. Does real work where the terminal output is buffered
+ * up. A no-operation on systems where byte at a time terminal I/O is done.
+ */
+ttflush()
+{
+#if AMIGA
+ amg_flush();
+#endif
+#if VMS
+ int status;
+ int iosb[2];
+
+ status = SS$_NORMAL;
+ if (nobuf != 0) {
+ status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
+ iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
+ if (status == SS$_NORMAL)
+ status = iosb[0] & 0xFFFF;
+ nobuf = 0;
+ }
+ return (status);
+#endif
+
+#if CPM
+#endif
+
+#if MSDOS
+#endif
+
+#if V7 | USG | BSD | OFW
+ fflush(stdout);
+#endif
+}
+
+/*
+ * Read a character from the terminal, performing no editing and doing no echo
+ * at all. More complex in VMS that almost anyplace else, which figures. Very
+ * simple on CPM, because the system can do exactly what you want.
+ */
+ttgetc()
+{
+#if AMIGA
+ char ch;
+ amg_flush();
+ Read(terminal, &ch, 1);
+ return(255 & (int)ch);
+#endif
+#if VMS
+ int status;
+ int iosb[2];
+ int term[2];
+
+ while (ibufi >= nibuf) {
+ ibufi = 0;
+ term[0] = 0;
+ term[1] = 0;
+ status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
+ iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
+ if (status != SS$_NORMAL)
+ exit(status);
+ status = iosb[0] & 0xFFFF;
+ if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
+ exit(status);
+ nibuf = (iosb[0]>>16) + (iosb[1]>>16);
+ if (nibuf == 0) {
+ status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
+ iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
+ if (status != SS$_NORMAL
+ || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
+ exit(status);
+ nibuf = (iosb[0]>>16) + (iosb[1]>>16);
+ }
+ }
+ return (ibuf[ibufi++] & 0xFF); /* Allow multinational */
+#endif
+
+#if CPM
+ return (biosb(BCONIN, 0, 0));
+#endif
+
+#if RAINBOW
+ int Ch;
+
+ while ((Ch = Read_Keyboard()) < 0);
+
+ if ((Ch & Function_Key) == 0)
+ if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
+ Ch &= 0xFF;
+
+ return Ch;
+#endif
+
+#if MSDOS & MWC86
+ return (dosb(CONRAW, 0, 0));
+#endif
+
+#if MSDOS & (LATTICE | MSC)
+ int c; /* character read */
+
+ /* if a char already is ready, return it */
+ if (nxtchar >= 0) {
+ c = nxtchar;
+ nxtchar = -1;
+ return(c);
+ }
+
+ /* call the dos to get a char */
+ rg.h.ah = 7; /* dos Direct Console Input call */
+ intdos(&rg, &rg);
+ c = rg.h.al; /* grab the char */
+ return(c & 255);
+#endif
+
+#if MSDOS & AZTEC
+ int c; /* character read */
+
+ /* if a char already is ready, return it */
+ if (nxtchar >= 0) {
+ c = nxtchar;
+ nxtchar = -1;
+ return(c);
+ }
+
+ /* call the dos to get a char */
+ rg.h.ah = 7; /* dos Direct Console I/O call */
+ sysint(33, &rg, &rg);
+ c = rg.h.al; /* grab the char */
+ return(c & 255);
+#endif
+
+#if V7 | USG | BSD
+ return(127 & fgetc(stdin));
+#endif
+
+#if OFW
+ return(fgetc(stdin));
+#endif
+}
+
+#if TYPEAH
+/* typahead: Check to see if any characters are already in the
+ keyboard buffer
+*/
+
+typahead()
+
+{
+#if MSDOS & (LATTICE | AZTEC)
+ int c; /* character read */
+ int flags; /* cpu flags from dos call */
+
+#if MSC
+ if (kbhit() != 0)
+ return(TRUE);
+ else
+ return(FALSE);
+#endif
+
+ if (nxtchar >= 0)
+ return(TRUE);
+
+ rg.h.ah = 6; /* Direct Console I/O call */
+ rg.h.dl = 255; /* does console input */
+#if LATTICE
+ flags = intdos(&rg, &rg);
+#else
+ flags = sysint(33, &rg, &rg);
+#endif
+ c = rg.h.al; /* grab the character */
+
+ /* no character pending */
+ if ((flags & 64) != 0)
+ return(FALSE);
+
+ /* save the character and return true */
+ nxtchar = c;
+ return(TRUE);
+#endif
+
+#if BSD
+ int x; /* holds # of pending chars */
+
+ return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
+#endif
+ return(FALSE);
+}
+#endif
+
Added: clients/emacs/vmsvt.c
===================================================================
--- clients/emacs/vmsvt.c (rev 0)
+++ clients/emacs/vmsvt.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,310 @@
+/*
+ * VMS terminal handling routines
+ *
+ * Known types are:
+ * VT52, VT100, and UNKNOWN (which is defined to be an ADM3a)
+ * written by Curtis Smith
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+#if VMSVT
+
+#define termdef 1 /* don't define "term" external */
+
+#include <ssdef.h> /* Status code definitions */
+#include <descrip.h> /* Descriptor structures */
+#include <iodef.h> /* IO commands */
+#include <ttdef.h> /* tty commands */
+
+extern int ttopen(); /* Forward references. */
+extern int ttgetc();
+extern int ttputc();
+extern int ttflush();
+extern int ttclose();
+extern int vmsopen();
+extern int vmseeol();
+extern int vmseeop();
+extern int vmsbeep();
+extern int vmsmove();
+extern int vmsrev();
+extern int eolexist;
+#if COLOR
+extern int vmsfcol();
+extern int vmsbcol();
+#endif
+
+#define NROWS 24 /* # of screen rolls */
+#define NCOLS 80 /* # of screen columns */
+#define MARGIN 8 /* size of minimim margin and */
+#define SCRSIZ 64 /* scroll size for extended lines */
+#define NPAUSE 100 /* # times thru update to pause */
+
+/*
+ * Dispatch table. All the
+ * hard fields just point into the
+ * terminal I/O code.
+ */
+TERM term = {
+ NROWS - 1,
+ NCOLS,
+ MARGIN,
+ SCRSIZ,
+ NPAUSE,
+ &vmsopen,
+ &ttclose,
+ &ttgetc,
+ &ttputc,
+ &ttflush,
+ &vmsmove,
+ &vmseeol,
+ &vmseeop,
+ &vmsbeep,
+ &vmsrev
+#if COLOR
+ , &vmsfcol,
+ &vmsbcol
+#endif
+};
+
+char * termeop; /* Erase to end of page string */
+int eoppad; /* Number of pad characters after eop */
+char * termeol; /* Erase to end of line string */
+int eolpad; /* Number of pad characters after eol */
+char termtype; /* Terminal type identifier */
+
+
+/*******
+ * ttputs - Send a string to ttputc
+ *******/
+
+ttputs(string)
+char * string;
+{
+ while (*string != '\0')
+ ttputc(*string++);
+}
+
+
+/*******
+ * vmspad - Pad the output after an escape sequence
+ *******/
+
+vmspad(count)
+int count;
+{
+ while (count-- > 0)
+ ttputc('\0');
+}
+
+
+/*******
+ * vmsmove - Move the cursor
+ *******/
+
+vmsmove(row, col)
+{
+ switch (termtype) {
+ case TT$_UNKNOWN:
+ ttputc('\033');
+ ttputc('=');
+ ttputc(row+' ');
+ ttputc(col+' ');
+ break;
+ case TT$_VT52:
+ ttputc('\033');
+ ttputc('Y');
+ ttputc(row+' ');
+ ttputc(col+' ');
+ break;
+ case TT$_VT100: /* I'm assuming that all these */
+ case TT$_VT101: /* are a super set of the VT100 */
+ case TT$_VT102: /* If I'm wrong, just remove */
+ case TT$_VT105: /* those entries that aren't. */
+ case TT$_VT125:
+ case TT$_VT131:
+ case TT$_VT132:
+ case TT$_VT200_SERIES:
+ {
+ char buffer[24];
+
+ sprintf(buffer, "\033[%d;%dH", row+1, col+1);
+ ttputs(buffer);
+ vmspad(50);
+ }
+ }
+}
+
+/*******
+ * vmsrev - set the reverse video status
+ *******/
+
+vmsrev(status)
+
+int status; /* TRUE = reverse video, FALSE = normal video */
+{
+ switch (termtype) {
+ case TT$_UNKNOWN:
+ break;
+ case TT$_VT52:
+ break;
+ case TT$_VT100:
+ if (status) {
+ ttputc('\033');
+ ttputc('[');
+ ttputc('7');
+ ttputc('m');
+ } else {
+ ttputc('\033');
+ ttputc('[');
+ ttputc('m');
+ }
+ break;
+ }
+}
+
+#if COLOR
+/*******
+ * vmsfcol - Set the forground color (not implimented)
+ *******/
+
+vmsfcol()
+{
+}
+
+/*******
+ * vmsbcol - Set the background color (not implimented)
+ *******/
+
+vmsbcol()
+{
+}
+#endif
+
+/*******
+ * vmseeol - Erase to end of line
+ *******/
+
+vmseeol()
+{
+ ttputs(termeol);
+ vmspad(eolpad);
+}
+
+
+/*******
+ * vmseeop - Erase to end of page (clear screen)
+ *******/
+
+vmseeop()
+{
+ ttputs(termeop);
+ vmspad(eoppad);
+}
+
+
+/*******
+ * vmsbeep - Ring the bell
+ *******/
+
+vmsbeep()
+{
+ ttputc('\007');
+}
+
+
+/*******
+ * vmsopen - Get terminal type and open terminal
+ *******/
+
+vmsopen()
+{
+ termtype = vmsgtty();
+ switch (termtype) {
+ case TT$_UNKNOWN: /* Assume ADM3a */
+ eolexist = FALSE;
+ termeop = "\032";
+ eoppad = 0;
+ break;
+ case TT$_VT52:
+ termeol = "\033K";
+ eolpad = 0;
+ termeop = "\033H\033J";
+ eoppad = 0;
+ break;
+ case TT$_VT100:
+ revexist = TRUE;
+ termeol = "\033[K";
+ eolpad = 3;
+ termeop = "\033[;H\033[2J";
+ eoppad = 50;
+ break;
+ default:
+ puts("Terminal type not supported");
+ exit (SS$_NORMAL);
+ }
+ ttopen();
+}
+
+
+struct iosb { /* I/O status block */
+ short i_cond; /* Condition value */
+ short i_xfer; /* Transfer count */
+ long i_info; /* Device information */
+};
+
+struct termchar { /* Terminal characteristics */
+ char t_class; /* Terminal class */
+ char t_type; /* Terminal type */
+ short t_width; /* Terminal width in characters */
+ long t_mandl; /* Terminal's mode and length */
+ long t_extend; /* Extended terminal characteristics */
+};
+
+/*******
+ * vmsgtty - Get terminal type from system control block
+ *******/
+
+vmsgtty()
+{
+ short fd;
+ int status;
+ struct iosb iostatus;
+ struct termchar tc;
+ $DESCRIPTOR(devnam, "SYS$INPUT");
+
+ status = sys$assign(&devnam, &fd, 0, 0);
+ if (status != SS$_NORMAL)
+ exit (status);
+
+ status = sys$qiow( /* Queue and wait */
+ 0, /* Wait on event flag zero */
+ fd, /* Channel to input terminal */
+ IO$_SENSEMODE, /* Get current characteristic */
+ &iostatus, /* Status after operation */
+ 0, 0, /* No AST service */
+ &tc, /* Terminal characteristics buf */
+ sizeof(tc), /* Size of the buffer */
+ 0, 0, 0, 0); /* P3-P6 unused */
+
+ /* De-assign the input device */
+ if (sys$dassgn(fd) != SS$_NORMAL)
+ exit(status);
+
+ if (status != SS$_NORMAL) /* Jump out if bad status */
+ exit(status);
+ if (iostatus.i_cond != SS$_NORMAL)
+ exit(iostatus.i_cond);
+
+ return tc.t_type; /* Return terminal type */
+}
+
+#else
+
+hellovms()
+
+{
+}
+
+#endif VMSVT
Added: clients/emacs/vt52.c
===================================================================
--- clients/emacs/vt52.c (rev 0)
+++ clients/emacs/vt52.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,133 @@
+/*
+ * The routines in this file
+ * provide support for VT52 style terminals
+ * over a serial line. The serial I/O services are
+ * provided by routines in "termio.c". It compiles
+ * into nothing if not a VT52 style device. The
+ * bell on the VT52 is terrible, so the "beep"
+ * routine is conditionalized on defining BEL.
+ */
+#define termdef 1 /* don't define "term" external */
+
+#include "estruct.h"
+#include "edef.h"
+
+#if VT52
+
+#define NROW 24 /* Screen size. */
+#define NCOL 80 /* Edit if you want to. */
+#define MARGIN 8 /* size of minimim margin and */
+#define SCRSIZ 64 /* scroll size for extended lines */
+#define NPAUSE 100 /* # times thru update to pause */
+#define BIAS 0x20 /* Origin 0 coordinate bias. */
+#define ESC 0x1B /* ESC character. */
+#define BEL 0x07 /* ascii bell character */
+
+extern int ttopen(); /* Forward references. */
+extern int ttgetc();
+extern int ttputc();
+extern int ttflush();
+extern int ttclose();
+extern int vt52move();
+extern int vt52eeol();
+extern int vt52eeop();
+extern int vt52beep();
+extern int vt52open();
+extern int vt52rev();
+#if COLOR
+extern int vt52fcol();
+extern int vt52bcol();
+#endif
+
+/*
+ * Dispatch table. All the
+ * hard fields just point into the
+ * terminal I/O code.
+ */
+TERM term = {
+ NROW-1,
+ NCOL,
+ MARGIN,
+ SCRSIZ,
+ NPAUSE,
+ &vt52open,
+ &ttclose,
+ &ttgetc,
+ &ttputc,
+ &ttflush,
+ &vt52move,
+ &vt52eeol,
+ &vt52eeop,
+ &vt52beep,
+ &vt52rev
+#if COLOR
+ , &vt52fcol,
+ &vt52bcol
+#endif
+};
+
+vt52move(row, col)
+{
+ ttputc(ESC);
+ ttputc('Y');
+ ttputc(row+BIAS);
+ ttputc(col+BIAS);
+}
+
+vt52eeol()
+{
+ ttputc(ESC);
+ ttputc('K');
+}
+
+vt52eeop()
+{
+ ttputc(ESC);
+ ttputc('J');
+}
+
+vt52rev(status) /* set the reverse video state */
+
+int status; /* TRUE = reverse video, FALSE = normal video */
+
+{
+ /* can't do this here, so we won't */
+}
+
+#if COLOR
+vt52fcol() /* set the forground color [NOT IMPLIMENTED] */
+{
+}
+
+vt52bcol() /* set the background color [NOT IMPLIMENTED] */
+{
+}
+#endif
+
+vt52beep()
+{
+#ifdef BEL
+ ttputc(BEL);
+ ttflush();
+#endif
+}
+
+#endif
+
+vt52open()
+{
+#if V7 | BSD
+ register char *cp;
+ char *getenv();
+
+ if ((cp = getenv("TERM")) == NULL) {
+ puts("Shell variable TERM not defined!");
+ exit(1);
+ }
+ if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) {
+ puts("Terminal type not 'vt52'or 'z19' !");
+ exit(1);
+ }
+#endif
+ ttopen();
+}
Added: clients/emacs/window.c
===================================================================
--- clients/emacs/window.c (rev 0)
+++ clients/emacs/window.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,571 @@
+/*
+ * Window management. Some of the functions are internal, and some are
+ * attached to keys that the user actually types.
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+/*
+ * Reposition dot in the current window to line "n". If the argument is
+ * positive, it is that line. If it is negative it is that line from the
+ * bottom. If it is 0 the window is centered (this is what the standard
+ * redisplay code does). With no argument it defaults to 0. Bound to M-!.
+ */
+reposition(f, n)
+ {
+ if (f == FALSE) /* default to 0 to center screen */
+ n = 0;
+ curwp->w_force = n;
+ curwp->w_flag |= WFFORCE;
+ return (TRUE);
+ }
+
+/*
+ * Refresh the screen. With no argument, it just does the refresh. With an
+ * argument it recenters "." in the current window. Bound to "C-L".
+ */
+refresh(f, n)
+ {
+ if (f == FALSE)
+ sgarbf = TRUE;
+ else
+ {
+ curwp->w_force = 0; /* Center dot. */
+ curwp->w_flag |= WFFORCE;
+ }
+
+ return (TRUE);
+ }
+
+/*
+ * The command make the next window (next => down the screen) the current
+ * window. There are no real errors, although the command does nothing if
+ * there is only 1 window on the screen. Bound to "C-X C-N".
+ *
+ * with an argument this command finds the <n>th window from the top
+ *
+ */
+nextwind(f, n)
+
+int f, n; /* default flag and numeric argument */
+
+{
+ register WINDOW *wp;
+ register int nwindows; /* total number of windows */
+
+ if (f) {
+
+ /* first count the # of windows */
+ wp = wheadp;
+ nwindows = 1;
+ while (wp->w_wndp != NULL) {
+ nwindows++;
+ wp = wp->w_wndp;
+ }
+
+ /* if the argument is negative, it is the nth window
+ from the bottom of the screen */
+ if (n < 0)
+ n = nwindows + n + 1;
+
+ /* if an argument, give them that window from the top */
+ if (n > 0 && n <= nwindows) {
+ wp = wheadp;
+ while (--n)
+ wp = wp->w_wndp;
+ } else {
+ mlwrite("Window number out of range");
+ return(FALSE);
+ }
+ } else
+ if ((wp = curwp->w_wndp) == NULL)
+ wp = wheadp;
+ curwp = wp;
+ curbp = wp->w_bufp;
+ upmode();
+ return (TRUE);
+}
+
+/*
+ * This command makes the previous window (previous => up the screen) the
+ * current window. There arn't any errors, although the command does not do a
+ * lot if there is 1 window.
+ */
+prevwind(f, n)
+{
+ register WINDOW *wp1;
+ register WINDOW *wp2;
+ register int nwindows; /* total # of windows */
+
+ /* if we have an argument, we mean the nth window from the bottom */
+ if (f)
+ return(nextwind(f, -n));
+
+ wp1 = wheadp;
+ wp2 = curwp;
+
+ if (wp1 == wp2)
+ wp2 = NULL;
+
+ while (wp1->w_wndp != wp2)
+ wp1 = wp1->w_wndp;
+
+ curwp = wp1;
+ curbp = wp1->w_bufp;
+ upmode();
+ return (TRUE);
+}
+
+/*
+ * This command moves the current window down by "arg" lines. Recompute the
+ * top line in the window. The move up and move down code is almost completely
+ * the same; most of the work has to do with reframing the window, and picking
+ * a new dot. We share the code by having "move down" just be an interface to
+ * "move up". Magic. Bound to "C-X C-N".
+ */
+mvdnwind(f, n)
+ int n;
+ {
+ return (mvupwind(f, -n));
+ }
+
+/*
+ * Move the current window up by "arg" lines. Recompute the new top line of
+ * the window. Look to see if "." is still on the screen. If it is, you win.
+ * If it isn't, then move "." to center it in the new framing of the window
+ * (this command does not really move "."; it moves the frame). Bound to
+ * "C-X C-P".
+ */
+mvupwind(f, n)
+ int n;
+ {
+ register LINE *lp;
+ register int i;
+
+ lp = curwp->w_linep;
+
+ if (n < 0)
+ {
+ while (n++ && lp!=curbp->b_linep)
+ lp = lforw(lp);
+ }
+ else
+ {
+ while (n-- && lback(lp)!=curbp->b_linep)
+ lp = lback(lp);
+ }
+
+ curwp->w_linep = lp;
+ curwp->w_flag |= WFHARD; /* Mode line is OK. */
+
+ for (i = 0; i < curwp->w_ntrows; ++i)
+ {
+ if (lp == curwp->w_dotp)
+ return (TRUE);
+ if (lp == curbp->b_linep)
+ break;
+ lp = lforw(lp);
+ }
+
+ lp = curwp->w_linep;
+ i = curwp->w_ntrows/2;
+
+ while (i-- && lp != curbp->b_linep)
+ lp = lforw(lp);
+
+ curwp->w_dotp = lp;
+ curwp->w_doto = 0;
+ return (TRUE);
+ }
+
+/*
+ * This command makes the current window the only window on the screen. Bound
+ * to "C-X 1". Try to set the framing so that "." does not have to move on the
+ * display. Some care has to be taken to keep the values of dot and mark in
+ * the buffer structures right if the distruction of a window makes a buffer
+ * become undisplayed.
+ */
+onlywind(f, n)
+{
+ register WINDOW *wp;
+ register LINE *lp;
+ register int i;
+
+ while (wheadp != curwp) {
+ wp = wheadp;
+ wheadp = wp->w_wndp;
+ if (--wp->w_bufp->b_nwnd == 0) {
+ wp->w_bufp->b_dotp = wp->w_dotp;
+ wp->w_bufp->b_doto = wp->w_doto;
+ wp->w_bufp->b_markp = wp->w_markp;
+ wp->w_bufp->b_marko = wp->w_marko;
+ }
+ free((char *) wp);
+ }
+ while (curwp->w_wndp != NULL) {
+ wp = curwp->w_wndp;
+ curwp->w_wndp = wp->w_wndp;
+ if (--wp->w_bufp->b_nwnd == 0) {
+ wp->w_bufp->b_dotp = wp->w_dotp;
+ wp->w_bufp->b_doto = wp->w_doto;
+ wp->w_bufp->b_markp = wp->w_markp;
+ wp->w_bufp->b_marko = wp->w_marko;
+ }
+ free((char *) wp);
+ }
+ lp = curwp->w_linep;
+ i = curwp->w_toprow;
+ while (i!=0 && lback(lp)!=curbp->b_linep) {
+ --i;
+ lp = lback(lp);
+ }
+ curwp->w_toprow = 0;
+ curwp->w_ntrows = term.t_nrow-1;
+ curwp->w_linep = lp;
+ curwp->w_flag |= WFMODE|WFHARD;
+ return (TRUE);
+}
+
+/*
+ * Delete the current window, placing its space in the window above,
+ * or, if it is the top window, the window below. Bound to C-X 0.
+ */
+
+delwind(f,n)
+
+int f, n; /* arguments are ignored for this command */
+
+{
+ register WINDOW *wp; /* window to recieve deleted space */
+ register WINDOW *lwp; /* ptr window before curwp */
+ register int target; /* target line to search for */
+
+ /* if there is only one window, don't delete it */
+ if (wheadp->w_wndp == NULL) {
+ mlwrite("Can not delete this window");
+ return(FALSE);
+ }
+
+ /* find window before curwp in linked list */
+ wp = wheadp;
+ lwp = NULL;
+ while (wp != NULL) {
+ if (wp == curwp)
+ break;
+ lwp = wp;
+ wp = wp->w_wndp;
+ }
+
+ /* find recieving window and give up our space */
+ wp = wheadp;
+ if (curwp->w_toprow == 0) {
+ /* find the next window down */
+ target = curwp->w_ntrows + 1;
+ while (wp != NULL) {
+ if (wp->w_toprow == target)
+ break;
+ wp = wp->w_wndp;
+ }
+ if (wp == NULL)
+ return(FALSE);
+ wp->w_toprow = 0;
+ wp->w_ntrows += target;
+ } else {
+ /* find the next window up */
+ target = curwp->w_toprow - 1;
+ while (wp != NULL) {
+ if ((wp->w_toprow + wp->w_ntrows) == target)
+ break;
+ wp = wp->w_wndp;
+ }
+ if (wp == NULL)
+ return(FALSE);
+ wp->w_ntrows += 1 + curwp->w_ntrows;
+ }
+
+ /* get rid of the current window */
+ if (--curwp->w_bufp->b_nwnd == 0) {
+ curwp->w_bufp->b_dotp = curwp->w_dotp;
+ curwp->w_bufp->b_doto = curwp->w_doto;
+ curwp->w_bufp->b_markp = curwp->w_markp;
+ curwp->w_bufp->b_marko = curwp->w_marko;
+ }
+ if (lwp == NULL)
+ wheadp = curwp->w_wndp;
+ else
+ lwp->w_wndp = curwp->w_wndp;
+ free((char *)curwp);
+ curwp = wp;
+ wp->w_flag |= WFHARD;
+ curbp = wp->w_bufp;
+ upmode();
+ return(TRUE);
+}
+
+/*
+
+Split the current window. A window smaller than 3 lines cannot be
+split. An argument of 1 forces the cursor into the upper window, an
+argument of two forces the cursor to the lower window. The only other
+error that is possible is a "malloc" failure allocating the structure
+for the new window. Bound to "C-X 2".
+
+ */
+splitwind(f, n)
+
+int f, n; /* default flag and numeric argument */
+
+{
+ register WINDOW *wp;
+ register LINE *lp;
+ register int ntru;
+ register int ntrl;
+ register int ntrd;
+ register WINDOW *wp1;
+ register WINDOW *wp2;
+
+ if (curwp->w_ntrows < 3) {
+ mlwrite("Cannot split a %d line window", curwp->w_ntrows);
+ return (FALSE);
+ }
+ if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
+ mlwrite("Cannot allocate WINDOW block");
+ return (FALSE);
+ }
+ ++curbp->b_nwnd; /* Displayed twice. */
+ wp->w_bufp = curbp;
+ wp->w_dotp = curwp->w_dotp;
+ wp->w_doto = curwp->w_doto;
+ wp->w_markp = curwp->w_markp;
+ wp->w_marko = curwp->w_marko;
+ wp->w_flag = 0;
+ wp->w_force = 0;
+#if COLOR
+ /* set the colors of the new window */
+ wp->w_fcolor = gfcolor;
+ wp->w_bcolor = gbcolor;
+#endif
+ ntru = (curwp->w_ntrows-1) / 2; /* Upper size */
+ ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */
+ lp = curwp->w_linep;
+ ntrd = 0;
+ while (lp != curwp->w_dotp) {
+ ++ntrd;
+ lp = lforw(lp);
+ }
+ lp = curwp->w_linep;
+ if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
+ /* Old is upper window. */
+ if (ntrd == ntru) /* Hit mode line. */
+ lp = lforw(lp);
+ curwp->w_ntrows = ntru;
+ wp->w_wndp = curwp->w_wndp;
+ curwp->w_wndp = wp;
+ wp->w_toprow = curwp->w_toprow+ntru+1;
+ wp->w_ntrows = ntrl;
+ } else { /* Old is lower window */
+ wp1 = NULL;
+ wp2 = wheadp;
+ while (wp2 != curwp) {
+ wp1 = wp2;
+ wp2 = wp2->w_wndp;
+ }
+ if (wp1 == NULL)
+ wheadp = wp;
+ else
+ wp1->w_wndp = wp;
+ wp->w_wndp = curwp;
+ wp->w_toprow = curwp->w_toprow;
+ wp->w_ntrows = ntru;
+ ++ntru; /* Mode line. */
+ curwp->w_toprow += ntru;
+ curwp->w_ntrows = ntrl;
+ while (ntru--)
+ lp = lforw(lp);
+ }
+ curwp->w_linep = lp; /* Adjust the top lines */
+ wp->w_linep = lp; /* if necessary. */
+ curwp->w_flag |= WFMODE|WFHARD;
+ wp->w_flag |= WFMODE|WFHARD;
+ return (TRUE);
+}
+
+/*
+ * Enlarge the current window. Find the window that loses space. Make sure it
+ * is big enough. If so, hack the window descriptions, and ask redisplay to do
+ * all the hard work. You don't just set "force reframe" because dot would
+ * move. Bound to "C-X Z".
+ */
+enlargewind(f, n)
+{
+ register WINDOW *adjwp;
+ register LINE *lp;
+ register int i;
+
+ if (n < 0)
+ return (shrinkwind(f, -n));
+ if (wheadp->w_wndp == NULL) {
+ mlwrite("Only one window");
+ return (FALSE);
+ }
+ if ((adjwp=curwp->w_wndp) == NULL) {
+ adjwp = wheadp;
+ while (adjwp->w_wndp != curwp)
+ adjwp = adjwp->w_wndp;
+ }
+ if (adjwp->w_ntrows <= n) {
+ mlwrite("Impossible change");
+ return (FALSE);
+ }
+ if (curwp->w_wndp == adjwp) { /* Shrink below. */
+ lp = adjwp->w_linep;
+ for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
+ lp = lforw(lp);
+ adjwp->w_linep = lp;
+ adjwp->w_toprow += n;
+ } else { /* Shrink above. */
+ lp = curwp->w_linep;
+ for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
+ lp = lback(lp);
+ curwp->w_linep = lp;
+ curwp->w_toprow -= n;
+ }
+ curwp->w_ntrows += n;
+ adjwp->w_ntrows -= n;
+ curwp->w_flag |= WFMODE|WFHARD;
+ adjwp->w_flag |= WFMODE|WFHARD;
+ return (TRUE);
+}
+
+/*
+ * Shrink the current window. Find the window that gains space. Hack at the
+ * window descriptions. Ask the redisplay to do all the hard work. Bound to
+ * "C-X C-Z".
+ */
+shrinkwind(f, n)
+{
+ register WINDOW *adjwp;
+ register LINE *lp;
+ register int i;
+
+ if (n < 0)
+ return (enlargewind(f, -n));
+ if (wheadp->w_wndp == NULL) {
+ mlwrite("Only one window");
+ return (FALSE);
+ }
+ if ((adjwp=curwp->w_wndp) == NULL) {
+ adjwp = wheadp;
+ while (adjwp->w_wndp != curwp)
+ adjwp = adjwp->w_wndp;
+ }
+ if (curwp->w_ntrows <= n) {
+ mlwrite("Impossible change");
+ return (FALSE);
+ }
+ if (curwp->w_wndp == adjwp) { /* Grow below. */
+ lp = adjwp->w_linep;
+ for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
+ lp = lback(lp);
+ adjwp->w_linep = lp;
+ adjwp->w_toprow -= n;
+ } else { /* Grow above. */
+ lp = curwp->w_linep;
+ for (i=0; i<n && lp!=curbp->b_linep; ++i)
+ lp = lforw(lp);
+ curwp->w_linep = lp;
+ curwp->w_toprow += n;
+ }
+ curwp->w_ntrows -= n;
+ adjwp->w_ntrows += n;
+ curwp->w_flag |= WFMODE|WFHARD;
+ adjwp->w_flag |= WFMODE|WFHARD;
+ return (TRUE);
+}
+
+/* Resize the current window to the requested size */
+
+resize(f, n)
+
+int f, n; /* default flag and numeric argument */
+
+{
+ int clines; /* current # of lines in window */
+
+ /* must have a non-default argument, else ignore call */
+ if (f == FALSE)
+ return(TRUE);
+
+ /* find out what to do */
+ clines = curwp->w_ntrows;
+
+ /* already the right size? */
+ if (clines == n)
+ return(TRUE);
+
+ return(enlargewind(TRUE, n - clines));
+}
+
+/*
+ * Pick a window for a pop-up. Split the screen if there is only one window.
+ * Pick the uppermost window that isn't the current window. An LRU algorithm
+ * might be better. Return a pointer, or NULL on error.
+ */
+WINDOW *
+wpopup()
+{
+ register WINDOW *wp;
+
+ if (wheadp->w_wndp == NULL /* Only 1 window */
+ && splitwind(FALSE, 0) == FALSE) /* and it won't split */
+ return (NULL);
+ wp = wheadp; /* Find window to use */
+ while (wp!=NULL && wp==curwp)
+ wp = wp->w_wndp;
+ return (wp);
+}
+
+scrnextup(f, n) /* scroll the next window up (back) a page */
+
+{
+ nextwind(FALSE, 1);
+ backpage(f, n);
+ prevwind(FALSE, 1);
+}
+
+scrnextdw(f, n) /* scroll the next window down (forward) a page */
+
+{
+ nextwind(FALSE, 1);
+ forwpage(f, n);
+ prevwind(FALSE, 1);
+}
+
+savewnd(f, n) /* save ptr to current window */
+
+{
+ swindow = curwp;
+ return(TRUE);
+}
+
+restwnd(f, n) /* restore the saved screen */
+
+{
+ register WINDOW *wp;
+
+ /* find the window */
+ wp = wheadp;
+ while (wp != NULL) {
+ if (wp == swindow) {
+ curwp = wp;
+ curbp = wp->w_bufp;
+ upmode();
+ return (TRUE);
+ }
+ wp = wp->w_wndp;
+ }
+
+ mlwrite("[No such window exists]");
+ return(FALSE);
+}
Added: clients/emacs/word.c
===================================================================
--- clients/emacs/word.c (rev 0)
+++ clients/emacs/word.c 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,531 @@
+/*
+ * The routines in this file implement commands that work word or a
+ * paragraph at a time. There are all sorts of word mode commands. If I
+ * do any sentence mode commands, they are likely to be put in this file.
+ */
+
+#include "estruct.h"
+#include "edef.h"
+
+/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
+ * line and stop on the first word-break or the beginning of the line. If we
+ * reach the beginning of the line, jump back to the end of the word and start
+ * a new line. Otherwise, break the line at the word-break, eat it, and jump
+ * back to the end of the word.
+ * Returns TRUE on success, FALSE on errors.
+ */
+wrapword(n)
+
+int n;
+
+{
+ register int cnt; /* size of word wrapped to next line */
+ register int c; /* charector temporary */
+
+ /* backup from the <NL> 1 char */
+ if (!backchar(0, 1))
+ return(FALSE);
+
+ /* back up until we aren't in a word,
+ make sure there is a break in the line */
+ cnt = 0;
+ while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
+ && (c != '\t')) {
+ cnt++;
+ if (!backchar(0, 1))
+ return(FALSE);
+ /* if we make it to the begining, start a new line */
+ if (curwp->w_doto == 0) {
+ gotoeol(FALSE, 0);
+ return(newline(0,1));
+ }
+ }
+
+ /* delete the forward white space */
+ if (!forwdel(0, 1))
+ return(FALSE);
+
+ /* put in a end of line */
+ if (!newline(0, 1))
+ return(FALSE);
+
+ /* and past the first word */
+ while (cnt-- > 0) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * Move the cursor backward by "n" words. All of the details of motion are
+ * performed by the "backchar" and "forwchar" routines. Error if you try to
+ * move beyond the buffers.
+ */
+backword(f, n)
+{
+ if (n < 0)
+ return (forwword(f, -n));
+ if (backchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ while (n--) {
+ while (inword() == FALSE) {
+ if (backchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ while (inword() != FALSE) {
+ if (backchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ }
+ return (forwchar(FALSE, 1));
+}
+
+/*
+ * Move the cursor forward by the specified number of words. All of the motion
+ * is done by "forwchar". Error if you try and move beyond the buffer's end.
+ */
+forwword(f, n)
+{
+ if (n < 0)
+ return (backword(f, -n));
+ while (n--) {
+#if NFWORD
+ while (inword() != FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+#endif
+ while (inword() == FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+#if NFWORD == 0
+ while (inword() != FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+#endif
+ }
+ return(TRUE);
+}
+
+/*
+ * Move the cursor forward by the specified number of words. As you move,
+ * convert any characters to upper case. Error if you try and move beyond the
+ * end of the buffer. Bound to "M-U".
+ */
+upperword(f, n)
+{
+ register int c;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ while (n--) {
+ while (inword() == FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ while (inword() != FALSE) {
+ c = lgetc(curwp->w_dotp, curwp->w_doto);
+ if (c>='a' && c<='z') {
+ c -= 'a'-'A';
+ lputc(curwp->w_dotp, curwp->w_doto, c);
+ lchange(WFHARD);
+ }
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+/*
+ * Move the cursor forward by the specified number of words. As you move
+ * convert characters to lower case. Error if you try and move over the end of
+ * the buffer. Bound to "M-L".
+ */
+lowerword(f, n)
+{
+ register int c;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ while (n--) {
+ while (inword() == FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ while (inword() != FALSE) {
+ c = lgetc(curwp->w_dotp, curwp->w_doto);
+ if (c>='A' && c<='Z') {
+ c += 'a'-'A';
+ lputc(curwp->w_dotp, curwp->w_doto, c);
+ lchange(WFHARD);
+ }
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+/*
+ * Move the cursor forward by the specified number of words. As you move
+ * convert the first character of the word to upper case, and subsequent
+ * characters to lower case. Error if you try and move past the end of the
+ * buffer. Bound to "M-C".
+ */
+capword(f, n)
+{
+ register int c;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ while (n--) {
+ while (inword() == FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ if (inword() != FALSE) {
+ c = lgetc(curwp->w_dotp, curwp->w_doto);
+ if (c>='a' && c<='z') {
+ c -= 'a'-'A';
+ lputc(curwp->w_dotp, curwp->w_doto, c);
+ lchange(WFHARD);
+ }
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ while (inword() != FALSE) {
+ c = lgetc(curwp->w_dotp, curwp->w_doto);
+ if (c>='A' && c<='Z') {
+ c += 'a'-'A';
+ lputc(curwp->w_dotp, curwp->w_doto, c);
+ lchange(WFHARD);
+ }
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ }
+ }
+ }
+ return (TRUE);
+}
+
+/*
+ * Kill forward by "n" words. Remember the location of dot. Move forward by
+ * the right number of words. Put dot back where it was and issue the kill
+ * command for the right number of characters. Bound to "M-D".
+ */
+delfword(f, n)
+{
+ register LINE *dotp;
+ register int doto;
+ long size;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
+ kdelete(); /* last wasn't a kill. */
+ thisflag |= CFKILL;
+ dotp = curwp->w_dotp;
+ doto = curwp->w_doto;
+ size = 0;
+ while (n--) {
+#if NFWORD
+ if (curwp->w_doto == llength(curwp->w_dotp)) {
+ if (forwchar(FALSE,1) == FALSE)
+ return(FALSE);
+ ++size;
+ }
+
+ while (inword() != FALSE) {
+ if (forwchar(FALSE,1) == FALSE)
+ return(FALSE);
+ ++size;
+ }
+
+ while ((inword() == FALSE) &&
+ (curwp->w_doto != llength(curwp->w_dotp))) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ ++size;
+ }
+#else
+ while (inword() == FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ ++size;
+ }
+
+ while (inword() != FALSE) {
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ ++size;
+ }
+#endif
+ }
+ curwp->w_dotp = dotp;
+ curwp->w_doto = doto;
+ return (ldelete(size, TRUE));
+}
+
+/*
+ * Kill backwards by "n" words. Move backwards by the desired number of words,
+ * counting the characters. When dot is finally moved to its resting place,
+ * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
+ */
+delbword(f, n)
+{
+ long size;
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (n < 0)
+ return (FALSE);
+ if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
+ kdelete(); /* last wasn't a kill. */
+ thisflag |= CFKILL;
+ if (backchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ size = 0;
+ while (n--) {
+ while (inword() == FALSE) {
+ if (backchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ ++size;
+ }
+ while (inword() != FALSE) {
+ if (backchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ ++size;
+ }
+ }
+ if (forwchar(FALSE, 1) == FALSE)
+ return (FALSE);
+ return (ldelete(size, TRUE));
+}
+
+/*
+ * Return TRUE if the character at dot is a character that is considered to be
+ * part of a word. The word character list is hard coded. Should be setable.
+ */
+inword()
+{
+ register int c;
+
+ if (curwp->w_doto == llength(curwp->w_dotp))
+ return (FALSE);
+ c = lgetc(curwp->w_dotp, curwp->w_doto);
+ if (c>='a' && c<='z')
+ return (TRUE);
+ if (c>='A' && c<='Z')
+ return (TRUE);
+ if (c>='0' && c<='9')
+ return (TRUE);
+ if (c=='$' || c=='_') /* For identifiers */
+ return (TRUE);
+ return (FALSE);
+}
+
+#if WORDPRO
+fillpara(f, n) /* Fill the current paragraph according to the current
+ fill column */
+
+int f, n; /* deFault flag and Numeric argument */
+
+{
+ register int c; /* current char durring scan */
+ register int wordlen; /* length of current word */
+ register int clength; /* position on line during fill */
+ register int i; /* index during word copy */
+ register int newlength; /* tentative new line length */
+ register int eopflag; /* Are we at the End-Of-Paragraph? */
+ register int firstflag; /* first word? (needs no space) */
+ register LINE *eopline; /* pointer to line just past EOP */
+ register int dotflag; /* was the last char a period? */
+ char wbuf[NSTRING]; /* buffer for current word */
+
+ if (curbp->b_mode&MDVIEW) /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+ if (fillcol == 0) { /* no fill column set */
+ mlwrite("No fill column set");
+ return(FALSE);
+ }
+
+ /* record the pointer to the line just past the EOP */
+ gotoeop(FALSE, 1);
+ eopline = lforw(curwp->w_dotp);
+
+ /* and back top the begining of the paragraph */
+ gotobop(FALSE, 1);
+
+ /* initialize various info */
+ clength = curwp->w_doto;
+ if (clength && curwp->w_dotp->l_text[0] == TAB)
+ clength = 8;
+ wordlen = 0;
+ dotflag = FALSE;
+
+ /* scan through lines, filling words */
+ firstflag = TRUE;
+ eopflag = FALSE;
+ while (!eopflag) {
+ /* get the next character in the paragraph */
+ if (curwp->w_doto == llength(curwp->w_dotp)) {
+ c = ' ';
+ if (lforw(curwp->w_dotp) == eopline)
+ eopflag = TRUE;
+ } else
+ c = lgetc(curwp->w_dotp, curwp->w_doto);
+
+ /* and then delete it */
+ ldelete(1L, FALSE);
+
+ /* if not a separator, just add it in */
+ if (c != ' ' && c != ' ') {
+ dotflag = (c == '.'); /* was it a dot */
+ if (wordlen < NSTRING - 1)
+ wbuf[wordlen++] = c;
+ } else if (wordlen) {
+ /* at a word break with a word waiting */
+ /* calculate tantitive new length with word added */
+ newlength = clength + 1 + wordlen;
+ if (newlength <= fillcol) {
+ /* add word to current line */
+ if (!firstflag) {
+ linsert(1, ' '); /* the space */
+ ++clength;
+ }
+ firstflag = FALSE;
+ } else {
+ /* start a new line */
+ lnewline();
+ clength = 0;
+ }
+
+ /* and add the word in in either case */
+ for (i=0; i<wordlen; i++) {
+ linsert(1, wbuf[i]);
+ ++clength;
+ }
+ if (dotflag) {
+ linsert(1, ' ');
+ ++clength;
+ }
+ wordlen = 0;
+ }
+ }
+ /* and add a last newline for the end of our new paragraph */
+ lnewline();
+ return(TRUE);
+}
+
+killpara(f, n) /* delete n paragraphs starting with the current one */
+
+int f; /* default flag */
+int n; /* # of paras to delete */
+
+{
+ register int status; /* returned status of functions */
+
+ while (n--) { /* for each paragraph to delete */
+
+ /* mark out the end and begining of the para to delete */
+ gotoeop(FALSE, 1);
+
+ /* set the mark here */
+ curwp->w_markp = curwp->w_dotp;
+ curwp->w_marko = curwp->w_doto;
+
+ /* go to the begining of the paragraph */
+ gotobop(FALSE, 1);
+ curwp->w_doto = 0; /* force us to the begining of line */
+
+ /* and delete it */
+ if ((status = killregion(FALSE, 1)) != TRUE)
+ return(status);
+
+ /* and clean up the 2 extra lines */
+ ldelete(2L, TRUE);
+ }
+ return(TRUE);
+}
+
+
+/* wordcount: count the # of words in the marked region,
+ along with average word sizes, # of chars, etc,
+ and report on them. */
+
+wordcount(f, n)
+
+int f, n; /* ignored numeric arguments */
+
+{
+ register LINE *lp; /* current line to scan */
+ register int offset; /* current char to scan */
+ long size; /* size of region left to count */
+ register int ch; /* current character to scan */
+ register int wordflag; /* are we in a word now? */
+ register int lastflag; /* were we just in a word? */
+ long nwords; /* total # of words */
+ long nchars; /* total number of chars */
+ int nlines; /* total number of lines in region */
+ int avgch; /* average number of chars/word */
+ int status; /* status return code */
+ REGION region; /* region to look at */
+
+ /* make sure we have a region to count */
+ if ((status = getregion(®ion)) != TRUE)
+ return(status);
+ lp = region.r_linep;
+ offset = region.r_offset;
+ size = region.r_size;
+
+ /* count up things */
+ lastflag = FALSE;
+ nchars = 0L;
+ nwords = 0L;
+ nlines = 0;
+ while (size--) {
+
+ /* get the current character */
+ if (offset == llength(lp)) { /* end of line */
+ ch = '\n';
+ lp = lforw(lp);
+ offset = 0;
+ ++nlines;
+ } else {
+ ch = lgetc(lp, offset);
+ ++offset;
+ }
+
+ /* and tabulate it */
+ wordflag = ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ (ch == '$' || ch == '_'));
+ if (wordflag == TRUE && lastflag == FALSE)
+ ++nwords;
+ lastflag = wordflag;
+ ++nchars;
+ }
+
+ /* and report on the info */
+ if (nwords > 0L)
+ avgch = (int)((100L * nchars) / nwords);
+ else
+ avgch = 0;
+
+ mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
+ nwords, nchars, nlines + 1, avgch);
+ return(TRUE);
+}
+#endif
Added: clients/emacs/x86/Makefile
===================================================================
--- clients/emacs/x86/Makefile (rev 0)
+++ clients/emacs/x86/Makefile 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,51 @@
+# Makefile for MicroEMACS 3.7 for use with Open Firmware.
+#
+# To make emacs, type: make emacs
+# or just: make
+#
+
+BP=../../..
+SRCDIR=..
+HLIBDIR=$(BP)/clients/lib
+LIBDIR=$(HLIBDIR)/x86
+
+CFLAGS= -I. -I$(SRCDIR) -I$(HLIBDIR)
+
+CC= gcc
+LFLAGS= -T emacs.lds -N -e _start
+LD= ld
+
+HFILES= ../estruct.h edef.h efunc.h epath.h ebind.h
+
+OFILES= ansi.o basic.o bind.o buffer.o display.o \
+ exec.o file.o fileio.o \
+ input.o isearch.o line.o lock.o main.o \
+ random.o region.o search.o spawn.o termio.o \
+ window.o word.o
+
+LIBS= $(LIBDIR)/libobp.a
+
+# emacs.elf: emacs.obp
+# $(BP)/tools/xcftobin <emacs.obp >emacs.bin
+# $(BP)/tools/bintoelf -e$(ORIGIN) <emacs.bin >emacs.elf
+
+emacs.obp: $(LIBDIR)/start.o $(OFILES) $(LIBS) Makefile
+ $(LD) $(LFLAGS) -o $@ $(LIBDIR)/start.o $(OFILES) $(LIBS)
+ size $@
+ nm -n $@ >emacs.nm
+ strip $@
+
+$(LIBDIR)/start.o: $(LIBDIR)/start.s
+ (cd $(LIBDIR); make start.o)
+
+$(LIBDIR)/libobp.a: $(HLIBDIR)/lib.c
+ (cd $(LIBDIR); make libobp.a)
+
+%.o:$(SRCDIR)/%.c
+ $(CC) $(CFLAGS) -c $<
+
+main.o: $(SRCDIR)/ebind.h
+
+clean:
+ -rm -f *.o *.a
+
Added: clients/emacs/x86/config.h
===================================================================
--- clients/emacs/x86/config.h (rev 0)
+++ clients/emacs/x86/config.h 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,55 @@
+/* Machine/OS definitions */
+
+#define OFW 1 /* Open Boot Prom */
+#define AMIGA 0 /* AmigaDOS */
+#define ST520 0 /* ST520, TOS */
+#define MSDOS 0 /* MS-DOS */
+#define V7 0 /* V7 UN*X or Coherent or BSD4.2*/
+#define BSD 0 /* UNIX BSD 4.2 and ULTRIX */
+#define USG 0 /* UNIX system V */
+#define VMS 0 /* VAX/VMS */
+#define CPM 0 /* CP/M-86 */
+
+/* Compiler definitions */
+#define GCC 1 /* Gnu C Compiler */
+#define MWC86 0 /* marc williams compiler */
+#define LATTICE 0 /* either lattice compiler */
+#define LAT2 0 /* Lattice 2.15 */
+#define LAT3 0 /* Lattice 3.0 */
+#define AZTEC 0 /* Aztec C 3.20e */
+#define MSC 0 /* MicroSoft C compile version 3 */
+
+/* Profiling options */
+#define APROF 0 /* turn Aztec C profiling on? */
+#define NBUCK 100 /* number of buckets to profile */
+
+/* Special keyboard definitions */
+
+#define WANGPC 0 /* WangPC - mostly escape sequences */
+
+/* Terminal Output definitions */
+
+#define ANSI 1 /* ansi escape sequences */
+#define HP150 0 /* HP150 screen driver */
+#define VMSVT 0 /* various VMS terminal entries */
+#define VT52 0 /* VT52 terminal (Zenith). */
+#define VT100 0 /* Handle VT100 style keypad. */
+#define LK201 0 /* Handle LK201 style keypad. */
+#define RAINBOW 0 /* Use Rainbow fast video. */
+#define TERMCAP 0 /* Use TERMCAP */
+#define IBMPC 0 /* IBM-PC specific driver */
+#define DG10 0 /* Data General system/10 */
+
+/* Configuration options */
+
+#define CVMVAS 1 /* arguments to page forward/back in pages */
+#define NFWORD 0 /* forward word jumps to begining of word */
+#define CLRMSG 0 /* space clears the message line with no insert */
+#define TYPEAH 1 /* type ahead causes update to be skipped */
+#define FILOCK 0 /* file locking under unix BSD 4.2 */
+#define REVSTA 0 /* Status line appears in reverse video */
+#define COLOR 1 /* color commands and windows */
+#define ACMODE 1 /* auto CMODE on .C and .H files */
+#define CFENCE 1 /* fench matching in CMODE */
+#define ISRCH 1 /* Incremental searches like ITS EMACS */
+#define WORDPRO 1 /* Advanced word processing features */
Added: clients/emacs/x86/emacs.lds
===================================================================
--- clients/emacs/x86/emacs.lds (rev 0)
+++ clients/emacs/x86/emacs.lds 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,11 @@
+OUTPUT_FORMAT("elf32-i386");
+OUTPUT_ARCH(i386);
+
+ENTRY(_start);
+SECTIONS {
+ . = 0x100000;
+ _start = . ;
+ .data : {
+ *(.data)
+ }
+}
Added: clients/emacs/x86/emacs.rc
===================================================================
--- clients/emacs/x86/emacs.rc (rev 0)
+++ clients/emacs/x86/emacs.rc 2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,94 @@
+; EMACS.RC: Startup file for MicroEMACS 3.4
+;
+; This file is executed everytime the
+; editor is entered
+
+; ***** Rebind the Function key group
+
+bind-to-key execute-macro-11 FNP
+bind-to-key execute-named-command FNQ
+bind-to-key hunt-forward FNW
+bind-to-key hunt-backward FNx
+bind-to-key next-window FNt
+bind-to-key find-file FNu
+bind-to-key save-file FNq
+bind-to-key exit-emacs FNr
+
+; set screen colors
+add-global-mode "blue"
+
+; Enter Help
+11 store-macro
+ help
+ 8 resize-window
+ bind-to-key execute-macro-12 FN? ; page up
+ bind-to-key execute-macro-13 FN/ ; page down
+ bind-to-key execute-macro-14 FNP ; fixed
+ add-mode "red"
+ begining-of-file
+ 2 forward-character
+ clear-message-line
+[end]
+
+; bring up the function key window
+1 store-macro
+ 2 split-current-window
+ select-buffer "Function Keys"
+ add-mode "red"
+ begining-of-file
+ 2 resize-window
+ insert-string " F1 Help on/off F5 Open File F6 Save File F7 Exit"
+ newline
+ insert-string " Move with arrow keys, PageUp, PageDown, Home, and End"
+ begining-of-file
+ unmark-buffer
+; bind-to-key execute-macro-15 FNT
+ next-window
+[end]
+
+; reselect function key window
+15 store-macro
+ 2 split-current-window
+ select-buffer "Function Keys"
+ begining-of-file
+ 2 resize-window
+ add-mode "red"
+ next-window
+[end]
+
+; consult file
+3 store-macro
+ 2 split-current-window
+ previous-window
+ view-file "@File to Consult: "
+ 8 resize-window
+ add-mode "green"
+ add-mode "Black"
+ next-window
+[end]
+
+; Exit Help
+14 store-macro
+ bind-to-key previous-page FN?
+ bind-to-key next-page FN/
+ bind-to-key execute-macro-11 FNP ; fixed
+ delete-window
+ clear-message-line
+[end]
+
+; last help page
+12 store-macro
+ begining-of-line
+ search-reverse "=>"
+ 1 redraw-display
+[end]
+
+; next help page
+13 store-macro
+ begining-of-line
+ 2 forward-character
+ search-forward "=>"
+ 1 redraw-display
+[end]
+
+execute-macro-1
[View Less]