Newsgroups: comp.editors
Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!think.com!zaphod.mps.ohio-state.edu!caen!news.cs.indiana.edu!maytag!mks.com!ant
From: ant@mks.com (Anthony Howe)
Subject: Simple Editor (IOCCC '91 Entry)
Date: Thu, 30 May 91 13:09:45 GMT
Message-ID: <1991May30.130945.4341@mks.com>
Organization: Mortice Kern Systems, Waterloo, Ontario, CANADA
Sender: ant@mks.com (Anthony Howe)

I've been iching to post this for over a year now to this group,
but had to wait till after the closing of entries for the
International Obfuscated C Code Contest for this year.  This code
may or may not win, but it should prove interesting.

What you'll find below is my simple VI-like full screen editor.
Now before I get caught in the cross-fire of the VI vs Emacs war,
remember that the *source* code has to be less than 1.5k or 1536
bytes to enter the IOCCC. The use of modes and VI-like keys made
the code all that much smaller allowing me to add more commands
like word movement.  With a little careful unwrapping of the
source, it should be *very* easy to configure the program to use
CURSES' keypad(1) function and the KEY_xxxx macros to obtain use
of all your favourite terminal function keys.  I had experimental
versions that did this.

This code should also prove interesting since I use the Buffer Gap
scheme that was discussed in the this group in the Editor 101 and
102 articles.

All entries into the IOCCC must be in the public domain and so
this means you can do what you like to it.  Below is the entry
exactly as I sent it off.  You'll have to cut out the man page
which follows the remarks: line and also cut out the source.  
Note that the leading X's in the source are part of the entry 
form not the code.


---header items---
name:		Anthony C Howe

org:		Mortice Kern Systems Inc.
		35 King St. N, Waterloo, On, Canada, N2J 2W9

email address:	ant@mks.com	or   ..!watmath!mks!ant

postal address:	#CL-23, 268 Phillip St, Waterloo, On, Canada, N2L 6G9

environment:	Interactive UNIX System V/386 Release 3.2
		BSD Unix 4.3
		Atari Mega ST using Sozobon C
		NEC Ultralite using WatCom C v7
		Some PC 386 box using Turbo C v1.5

entry:		0

remarks:	

NAME
	ae	Ant's Editor vIOCCC91


USAGE
	ae <filename>	

where <filename> is the text file to edit or create.


DESCRIPTION
<< ae >> is a full screen, VI style text editor.  The source 
should be portable to any environment that provides a K&R C 
compiler and a CURSES library. (Even EBCDIC machines provided 
the above two requirements are met.)

Text files consists of lines of printable text or tab characters.  
A line can be of arbitary length and is delimited by either a 
newline or the end of file.  Carriage return is mapped to newline 
on input and ignored on output.  Tab stops are every eight columns.
Non-printable characters may have unpredictable results depending
on the implementation of CURSES.


COMMANDS
h j k l		left, down, up, right cursor movement
H J K L		word left, page down, page up, word right
[ ]		beginning and end of line
t b		top and bottom of file
i		enter insert mode, formfeed to quit
x		delete character under the cursor
W		write buffer to file
R		refresh the screen
Q		quit


EXIT STATUS
0	success
2	missing edit filename


INSTALLATION 
Requires K&R C and a CURSES library for the given target machine.

The file creation MODE should be set at compile time to 0600 for 
Unix systems, or 0 for the Atari ST and PC. 

The BUF size should be set at compile time to 32767.  This value
was used because the Sozobon C compiler for the Atari ST has 16 
bit ints and a limit on the size of arrays & structures of 32k.  
Also the WatCom C compiler for the PC also has 16 bits ints.  On 
machines that have 32 bit ints (most unix boxes), a larger value 
for BUF could be used.

It is recommend that compact memory model be used on PC class
machines.  Small memory model may work too provided BUF is not
too large.

The character constants '\b', '\f', '\n', '\r', '\t' are used 
in order to provide more portable code, since the compiler should
handle the translation of them into the native character set.
Note that '\f' (formfeed) was used to exit insert mode because
K&R C had no escape constant for the escape-key.

Note that the "int " definition at the top of the source was for
the benifit of Turbo C, which returns lots of warnings.  WatCom C
should return no warnings provided your curses.h has no NULL
expression defined for functions.  System V and BSD should also
generate no warnings.  The source should pass basic linting.
The source still looks like a mess when passed through our
C beautifier (your milleage may vary).

My goals for this project were to learn and experiment with the 
Buffer Gap Scheme [Fin80][net90], write a useful and *portable* 
programme, and meet the requirements of the IOCCC.  I initially 
planned to have a mini CURSES built-in like the IOCCC Tetris entry 
from a previous year, however this was not as portable as using a
CURSES library with TERMINFO/TERMCAP support.  


REFERENCES
[Fin80]	Craig A. Finseth, "Theory and Practice of Text Editors or 
	A Cookbook For An EMACS", TM-165, MIT Lab. for Computer 
	Science

[KeP81]	Kernighan & Plauger, "Software Tools in Pascal", 
	Addison-Wesley, 81, chapter 6

[Mil86]	Eugene W. Myers & Webb Miller, "Row-replacement Algorithums
	for Screen Editors", TR 86-19, Dept. of Compter Science, 
	U. of Arizona

[MyM86]	Eugene W. Myers & Webb Miller, "A simple row-replacement 
	method", TR 86-28, Dept. of Compter Science, U. of Arizona

[Mil87]	Webb Miller, "A Software Tools Sampler", Prentice Hall, 87
	ISBN 0-13-822305-X, chapter 5

[net90]	"Editor 101/102" articles from comp.editors


FILES
ae.c		Obfuscated source
ae.man		Manual page


---how to ANSI compile---
---how to common compile---
X # SYS V
X cc -DMODE=0600 -DBUF=32767 -o ae ae.c -lcurses
X # BSD
X #cc -DMODE=0600 -DBUF=32767 -o ae ae.c -lcurses -ltermcap
X # ATARI ST 
X #cc -DMODE=0 -DBUF=32767 -o ae.ttp ae.c curses.a
X # PC class 
X #wcl -mc -DMODE=0 -DBUF=32767 ae.c curses.lib
---program---
X#include <curses.h>
X#define Z(x) (x==' '||x=='\t'||x=='\n')
Xint a,d,i,q=1,x,y;char b[BUF],*c,*g=b,*h,*p=b,*m=b,*n,*f,
Xk[]="hjklHJKL[]tbixWRQ";S(){p=b;}T(){p=c;}Q(){q=0;}P(){clear();Y();}
XV(){if(p<g)while(p<g)*--h= *--g;if(h<=p)while(h<p)*g++= *h++;p=h;}
Xchar*M(s)char*s;{while(b<(s=s-h?s:g)&&*--s!='\n');return b<s?s+1:b;}
Xchar*N(s)char*s;{while((s=s-g?s:h)<c&&*s++!='\n');return s<c?s:c;}
XA(){for(i=0,p=p-g?p:h;p<c&&*p!='\n'&&i<x;i+= *p-'\t'?1:8-(i&7),R());}
XL(){p=h-p?p:g;b<p&&--p;--y;}R(){p=p-g?p:h;p<c&&++p;}U(){p=M(M(p)-1);A();--y;}
XD(){p=N(p);A();}H(){p=M(p);}E(){p=N(p);L();}
XB(){while(!Z(*p)&&b<p)L();while(Z(*p)&&b<p)L();}
XJ(){m=p=M(M(n)-1);while(y--)p=N(p);A();n=c;}
XK(){for(i=d;--i;m=M(M(m)-1),p=M(M(p)-1));A();}
XW(){while(!Z(*p)&&p<c)R();while(Z(*p)&&p<c)R();}
XI(){V();while((a=getch())-'\f'){if(a-'\b')h-g&&(*g++=a-'\r'?a:'\n');
Xelse b<g&&--g;Y();}}X(){V();p=h<c?++h:p;}
XF(){p=b;V();write(i=creat(f,MODE),h,(int)(c-h));close(i);}
X(*z[])()={L,D,U,R,B,J,K,W,H,E,S,T,I,X,F,P,Q,V};
XY(){if(p<m)m=M(p);if(n<=p||++y==d)for(m=N(p),i=m-c?d:d-2;i--;m=M(M(m)-1));
Xmove(0,0);for(i=a=0,n=m;;){n=n-g?n:h;n-p||(y=i,x=a);if(d<=i||c<=n)break;
X*n-'\r'&&(addch(*n),a+= *n-'\t'?1:8-(a&7));if(*n++=='\n'||COLS<=a)++i,a=0;}
Xclrtobot();++i<d&&mvaddstr(i,0,"<< EOF >>");move(y,x);refresh();}
Xmain(u,v)char**v;{h=n=c=b+BUF;if(u<2)return 2;initscr();d=LINES;raw();
Xnoecho();idlok(stdscr,1);
Xif(0<(i=open(f= *++v,0)))g+=read(i,b,BUF),g=g<b?b:g,close(i);while(q){Y();
Xfor(a=getch(),i=0;k[i]&&a!=k[i];++i);(*z[i])();}endwin();return 0;}
---end---
-- 
ant@mks.com                                                   Anthony C Howe 
Mortice Kern Systems Inc. 35 King St. N., Waterloo, Ontario, Canada, N2J 6W9
"Fate favors fools, small children, and ships named Enterprise" - Riker
