First, I moved a bunch of useless files into the new "dreg" directory:

	beos.c directfb.c directfb_cursors.h finger.c framebuffer.c
	pmshell.c smb.c svgalib.c win32.c x.c

I also copied os_dep.c, os_dep.h and os_depx.h into dreg, then removed
all non-Plan 9 stuff from them. Coping with variety by using #ifdefs
is a bad idea and slows down the compiler by making it pointlessly
read too-large header files.

Altogether, that eliminated about 10,000 lines of useless code that we
no longer have to compile. I edit mkfile to match.

I have tried to resist the strong temptation to improve the code,
except where I had to understand it.

I have worked over links.h. I added the abbreviations uchar, ushort
and ulong and typedefs for some structs. I cleaned out a lot of the
GNU #include stupidity: if a header is required by ANSI, I just
include it without #ifdefing it. People who don't have ANSI C
compilers yet are just out of luck. I deleted the incorrect default
definition of FD_SETSIZE and added a correct, portable definition to
select.c, the only file that uses it. I added the Chunk and Block
types for future use; the code obviously needs them. I can't believe
links.h is 4,000 lines!

I fixed a misplaced #endif in cfg.h.

I sorted config.h so I could find things faster, but I don't think you
need to use my config.h

I have rationalised connect.c somewhat, especially its SSL code. In
addition, it no longer uses select to detect output streams ready for
output, since select only guarantees that a single byte can be written
without blocking. Instead, I just write the stuff and take the risk
of blocking, which shouldn't happen given that Plan 9 has generous
networking buffering and that we aren't writing very much to the
network at one time. I had hoped to use just the Plan 9 event
machinery, which is only good for input streams, but realised it's
just too hard: with http connections coming and going, we'd have to
have a way to undo the effect of estart(), say an estop() routine. It
might be feasible to fork or rfork a process just to create an http
connection, write a request, read the result, and exit, which would
permit the use of ordinary blocking I/O and eliminate the need for
select. It might even help to manage memory more effectively.

It looks like my changes to default.c are cosmetic, so you don't have
to pick them up. I did get rid of a pile of (unsigned char *) casts
in the tables, though.

I cleaned up dither.c in preparation for making it run faster, but
ultimately didn't, so you probably don't need it either.

I added a little tracing to http.c, but I don't think you need it
either.

I fixed many font errors in links.1 and generally made it less ugly.

main.c is mostly cosmetic changes, but I added the "shootme" machinery
for trying to kill the new event-watching process in plan9.c. It
doesn't always work; I don't know why. I unbuffered stderr so that
error messages appear immediately instead of being buffered (mostly
useful during debugging).

You'll want my mkfile.

os_dep* are greatly slimmed-down.

I worked over plan9.c a bit too: used structure assignment to copy
rectangles, cleaned up key-code translation, redid event handling and
select implementation, changed when to call flushimage and redraw. I
call flushimage at the end of the two bitmap routines and also after
each select(); it's probably overkill but it seems to help. I also
call redraw once every 5 seconds to force out delayed updates.
Calling redraw more often does make the system noticeably more busy
(keep `stats -slIc' running while you run links).

It looks like my changes to sched.c are just cosmetic.

select.c has been mauled. I got rid of the fd_sets for writes
entirely. I refactored some of the code out of the main select_loop.
Some of the stupider had has been removed with

	if (Braindamage)
		stupid-code;

where Braindamage is defined as 0. There are bits of shootme
machinery in here too. There's new debugging code (normally compiled
out). There are now strict upper and lower bounds on how long select
may sleep. The upper bound is to make sure flushimage and redraw get
called regularly. Debugging showed sleeps as short as 1 microsecond
and a lot of them were just 101 microseconds; no wonder we were eating
up the CPU! select is not cheap on Unix, it's even more expensive on
APE. The code under `if (errno == EBADF) {' is no longer getting
called; it was needed at one time, but no more; it could be deleted.
Similarly, the "sleep(1)" in the `errno != EINTR' if statement could
probably be deleted now; I was paranoid about CPU-bound loops chewing
up the CPU. The frequent, yet random, calls to check_timers,
check_signals and CHK_BH seem arbitrary and appear to be symptoms of a
program whose author doesn't understand it. There's new code for
plan9.c's benefit at the end, I think it's pretty obvious.

url.c removes dumb shit like "finger" and "smb" protocols; we don't
need them, don't want them and nobody uses them in web pages. Good
riddance. Here and elsewhere I have deleted code, including entire
functions, that was commented out. If it's not needed, get rid of the
trash, I figure. More (unsigned char *) casts in tables are gone.

My approach to events should be pretty obvious from the code, but it's
essentially this: create a (bidirectional) pipe, call einit, and
rfork(RFPROC|RFMEM) a trivial process to wait for keyboard and mouse
events, which are then store in (shared) memory. When one arrives,
send a byte up the pipe to the parent process, which is selecting on
that end of the pipe, along with any other fds that the rest of the
program is watching. When activated after select returns, the parent,
to synchronise, reads the byte from the pipe, processes any queued
mouse and keyboard events (which should be quick), and writes a
different byte back down the pipe. The child process has been reading
from its end of the pipe for synchronisation, and upon seeing the byte
from the parent, resumes waiting for events. The event package will
queue any events that arrive while the child is reading and writing
the pipe, so none should be lost. The main reason for having the
parent process the events is so that it can do them synchronously with
the main select() call (from select_loop), thus eliminating a possible
source of races.

Obviously it would be better to radically rewrite the program to
eliminate all use of select, but I'll leave that for another day.

This has been working well for me, except that links is a major memory
hog, and it did crash my terminal once during debugging.

I'm attaching the code, omitting the files that I didn't touch.