EPIC5-2.2

*** News 06/15/2022 -- EPIC5-2.1.12 (2078 - Secondment) released here
	This release improves build behavior for openbsd and others.

*** News 06/05/2022 -- EPIC5-2.1.11 (2071 - Adynaton) released here
	This release is entirely quality improvements, focused on 
	removing (rather than handling) type punning, and signed-
	pointer issues where c99 behaves differently from c90.

*** News 05/22/2022 -- EPIC5-2.1.10 (2059 - Casuistry) released here
	This release is entirely quality improvements now that we've 
	to C99 -- addressing undefined behavior, etc.

*** News 05/09/2022 -- EPIC5-2.1.9 (2053 - Decoupage) released here
*** News 05/09/2022 -- EPIC5-2.1.8 (2052 - Decoupage) released here
	I screwed up the release of 2.1.8 so I redid it as 2.1.9

*** News 05/09/2022 -- EPIC is now a C99 program
	As of this release, EPIC is now expected to be a well-defined C99
	program.  This release has eliminated all type punning/aliasing 
	shenanigans (or at least given the compiler fair warning about it)
	Type-punning pointer casts are done through unions, as C99 requires.
	Consequently, EPIC is now compiled with -O2, which I hope I don't come
	to regret.

*** News 05/02/2022 -- New $info() values, $info(Z:*)
	$info(Z:configure_args)		returns what you passed to 'configure'
	$info(Z:compiler_version)	returns "$CC -v" that was used
	$info(Z:final_link)		returns the command used to link epic5
	$info(Z:cflags)			returns the CFLAGS used during build
	$info(Z:libs)			returns the libs used during build
	$info(Z)			returns all the above in a json dict

*** News 04/10/2022 -- Window /LOGs now don't require logged window to exist
	There is a question -- do logs log _a particular window instance_
	or do they log _any window matching a descirption_?  Previously you
	could not /log add a window that didn't exist because the window 
	lookup failed.  

	Starting now, you can /log add any window you want even if the window
	does not exist -- you can /log add a refnum, a name, or a uuid, and
	any window that ends up using that refnum, name, or uuid, will log
	to the log; not just the window that existed when the log was created.

	On the flip side of this, if you are logging a window refnum and then
	you change a window's refnum, it might stop logging -- so if you want
	to log _a particular window_, log its uuid, for example:
		/log add $windowctl(GET 5 UUID)

*** News 04/08/2022 -- Restatement of /WINDOW QUERY
	The behavior of /WINDOW QUERY, /WINDOW ADD, and /WINDOW REMOVE 
	was unified some time ago, but the behavior was inconsistent
	and unclear.  So the code has been harmonized and now has the
	following behavior:

	/WINDOW QUERY nick
		Add 'nick' to target list and make current target (query)
	/WINDOW QUERY nick1,nick2
		Add 'nick1' and 'nick2' to target list and make the last
		target (nick2) the current target (query)
	/WINDOW QUERY
		Remove the current target (query) from the target list.
		If there are other targets in the target list, then the 
		previous query will become the new current target (query)
	/WINDOW -QUERY
		Remove all targets from the window's target list.
		There will be no query.

	/WINDOW ADD nick
		Add 'nick' to target list, but not as the current target
	/WINDOW REMOVE nick
		Remove 'nick' from the target list.  If you REMOVE the
		current target (query) then another target will become
		the new current target (query)

	Don't forget the SWITCH_QUERY keybinding, to cycle between the
	targets in a window.

*** News 04/06/2022 -- New functtions $pledge() and $unveil()
	These functions call the OpenBSD syscalls, if you're running on 
	OpenBSD.

	$PLEDGE()
	======================
	Simple Example:
		/@pledge(stdio rpath inet dns tty proc)
	Read the man page for more information.
	Returns:
		empty string - pledge(2) is not supported
		anything else - the return value of pledge(2)

	Complex examples:
		/@pledge({"test": true})
			Return 1 if $pledge() is supported, and 0 if not.

		/@pledge({"promises": "...", "execpromises": "..."})
			Pass these values to the 'promises' and 'execpromises'
			parameters of pledge(2)


	$UNVEIL()
	====================
	Simple Example:
		/@unveil(/path/to/directory r)
		/@unveil(/path/to/another/directory wc)
		/@unveil()
	Read the man page for more information
	Returns:
		empty string - unveil(2) is not supported
		anything else - the reteurn value of unveil(2)

	Complex examples:
		/@unveil({"test": true})
			Return 1 if $unveil() is supported, and 0 if not.

		/@unveil({"path": "/path/to/directory", "permissions": "r"})
		/@unveil({"path": "/path/to/another/directory", "permissions": "wc"})
		/@unveil({"close": true})
			Does the same thing as the simple example

*** News 04/04/2022 -- TCL support removed
	TCL support passed away quietly this afternoon.  It was 19 years old

*** News 04/04/2022 -- Install target de-cruftified
	EPIC has been doing lots of strange stuff when you 'make install'
	since its earliest days.  But in these modern worlds with silicon
	chips and whatnots, it makes little sense to compile our own version
	of test and ship a weird version of 'bsdinstall'.  Make install
	is now optimized for how package maintainers actually use it, so
	hopefully they'll not have to patch the heck out of epic to make 
	it behave like all the other programs

*** News 03/28/2021 -- New /SET, /SET AUTOMARGIN_OVERRIDE (default OFF)
	Previously, automargin support was conditionally built into 
	the client at compile time.  The default was to include it.
	The support is now always included.

	Traditionally, the use of the last column depended on whether the 
	client was convinced your terminal emulator safely supported it.
	At the request of skered, this /SET was added that allows you
	to force it, even if the client doesn't know how to safely turn
	it on.  Therefore, using this /SET may cause display corruption
	if the final column is used -- and this would not be considered
	a bug in the client.

	/SET AUTOMARGIN_OVERRIDE ON
		Try to use the final column, even if you aren't sure if
		it can be done safely -- (at your own risk -- if you have
		screen corruption, this is "normal")
	/SET AUTOMARGIN_OVERRIDE OFF
		Use (or don't use) the final column based on whether the
		client is sure (or isn't sure) if it's safe.

*** News 03/27/2021 -- EPIC5-2.1.7 (2011 - Cinereous) released here

*** News 03/21/2022 -- New built in function $rgb()
	There are three ways to call the $rgb() function:
	   1. As three numbers
		$rgb(255 0 255)
	   2. As a string
		$rgb(#FF00FF)
	   3. As kwargs
		$rgb({"r":255, "g":0, "b":255, "attr":true})

	This will return a string that will change to the indicated color.
	(ie, it is of the form ^Xab, where "ab" are two hex digits)
	The kwarg version is the only way to prevent prefixing with ^X
	(ie, to get the color number).   The 'attr' flag is optional.

*** News 03/06/2022 -- New serverctl(DONT_CONNECT), sets the -s CLI
	The -s command line option ("dont connect to a server") can now
	be set by your ~/.epicrc with 
		@serverctl(DONT_CONNECT 1)
	Obviously this only matters at client startup.  Setting it at
	any other time is pointless

*** News 03/06/2022 -- New math operator: "??" -- Coalesce
	The coalesce operator is a binary operator that returns the left
	value if the left value is true-y, otherwise returns the right
	value.  Therefore, "x ?? y" is shorthand for "x ? x : y"
	The operator precedence is the same as "||".

*** News 03/06/2022 -- New /set BROKEN_AIXTERM
	Some terminal emulators are silly and don't/can't/won't support
	bold and color at the same time, instead insisting that you send
	proprietary/non-standard ansi codes that were pioneered by a
	vendor that also couldn't get its terminal emulator to properly
	emulate real terminals.

	If you are using such an emulator, you can /set broken_aixterm
	and bold colors will send aixterm codes instead of standard codes.

*** News 02/06/2022 -- What is $serverctl(GET x OPEN)?
	Zlonix asked me to document "what does OPEN mean for a server?"

	A server is "open" when it has a file descriptor open.  
	This is entirely different from whether it is connected to IRC.
	(for that, use $serverctl(GET x CONNECTED))

	When a server is "open" then it is under the active management
	of the client.  When a server is "closed" then the client has 
	stopped paying attention to it and nothing further will happen
	with it until the user (or script) does something.

	During the course of a connection, several *different*
	file descriptors get used by a server as it goes through the
	server states:

	Server State	Is "Open"?	What is fd used for?
	-------------	-------------	----------------------------
	CREATED		No
	RECONNECT	No
	DNS		Yes*		DNS helper subprocess
	CONNECTING	Yes*		socket that is not yet connect()ed
	SSL_CONNECTING	Yes*		connected socket not yet ssl'd
	REGISTERING	Yes		socket that is trying to get on irc
	SYNCING		Yes		socket that is on irc
	ACTIVE		Yes		socket that is on irc
	EOF		Yes*		socket that has seen an end-of-file
	ERROR		Yes*		socket that has fatal error
	CLOSING		Yes*		socket that is shutting down
	CLOSED		No		
	DELETED		No		

	* - Just because a server is "open" does not mean that it is useful
	    for IRC purposes.  It only means that the fd has not yet been
	    closed at the OS level.  These states still have an 'fd that 
	    has not been close(2)d', but don't represent useful states

*** News 02/05/2022 -- New $serverctl(GET x NEXT_SERVER_IN_GROUP)
	This will return the server that /server + will connect to

*** News 11/11/2021 -- $json_implode() takes kwargs, adds "compact mode"
	The standard behavior of $json_implode() is to take a single word 
	as an argument, the root of a assign tree to convert into a json 
	object.
		$json_implode(q)	# Collapse $q.* into json object

	The standard behavior of $json_implode() is to return a "human-
	formatted" string, with newlines and indentation.  This is nice 
	for looking at, but isn't appropriate for every situation.

	So $json_implode() is our pilot test for json object argument lists.
	It now supports the following two arguments:
		root	  string    The root of the assign tree (required)
		compact	  boolean   false - return human readable (default)
				    true - return one line

	Example:
		@ q.one = [val1]
		@ q.two = [val2]
	then,
		$json_implode({"root": "q", "compact": true})
	would return
		{"one":"val1","two","val2"}

	
*** News 11/18/2021 -- New concept -- json object as argument list ("kwargs")
	You'll start noticing something new happening more and more.
	The idea of "json object as an argument list" is being introduced,
	to allow passing of parameters in a more deterministic way.

	JSON objects (also known as "dicts") are a collection of key-value pairs.
		{ "field1", "val1", "field2", "val2"}
	You already operate on these with $json_implode() and $json_explode().
	Most RESTful APIs in the world send and receive them.  

	For backwards compatability reasons, of course, this feature will be
	rolled out on a case-by-case basis whenever it seems appropriate.
	But, occasionally, a new feature might be available only through json
	object arguments because it makes sense.

*** News 10/06/2021 -- EPIC5-2.1.6 (1981 - Impignorate) released Here

*** News 09/21/2021 -- Another round of clang static analysis
	Somewhere around here we did another round of static analysis
	with clang's analyzer, and fixed whatever it recommended.

*** News 09/19/2021 -- "reconnect" script has been reimplemented
	The reconnect script has been renamed to "reconnect.orig".
	If you want the original behavior, just /load reconnect.orig
	The new script is based on improvements we've made in epic5
	to make reconnection logic more reliable and dependable.

*** News 09/11/2021 -- New option,  $serverctl(GET x PADDR)
	The $serverctl(GET x PADDR) returns the server's presentation
	address.  This is "1.2.3.4" for ipv4, or "2600::1" for ipv6.
	This represents the IP address we're connected to.

*** News 09/11/2021 -- New /window operation, /WINDOW CLEARREGEX <regex>
	This was requested by Zlonix.

	The /WINDOW CLEARREGEX <regex> operation removes all items from
	the window's lastlog whose text (what you see on the screen) 
	matches the <regex>.  Removing them from the lastlog removes
	them from the scrollback and your screen as well.  This is useful
	for making conversations with annoying bots go away retroactively.
	Example:	/window clearregex annoybot

*** News 09/11/2021 -- New /ON, /ON RECONNECT_REQUIRED 
	The /ON RECONNECT_REQUIRED hook is thrown by the client when it
	feels that a reconnection intervention is appropriate.  
	We are going to start this small, and build in more use cases
	as we go forward.

	  1. When server is in ACTIVE state and the socket dies
	  2. When a write to the server fails

	In these situations, your script should take whatever measures
	are necessary to save the state of windows, channels, etc,
	in preparation for the upcoming disconnection.

	This /ON is thrown while the server is in a state of chaos.
	The internal state of the system is wrong, and you must assume
	that the connection to the server has already been lost.  

	YOU MUST _*_*_NOT_*_*_ try to do anything clever in this /on.
	If you have this idea of moving windows or servers or channels,
	please don't!  I recommend setting up /timer's and /defer's so
	you can do those sorts of changes away from the blast radius.

	YOU MUST _*_*_NEVER_*_*_ attempt to do any direct intervention
	in this /on -- instead, you should save information and create 
	a timer to deal with the problem later.  YOU HAVE BEEN WARNED.

	/ON RECONNECT_REQUIRED currently provides this information
		$0 	The server that unexpected failed on us.
			Reconnection will be required.  Remember,
			you cannot do reconnection in the /on, you
			have to schedule it to happen "later"

*** News 09/08/2021 -- New /window operation, /WINDOW CLEARLEVEL [levels]
	This was requested by Zlonix.

	The /WINDOW CLEARLEVEL [levels] operation removes all items from
	the window's lastlog of the levels you specify.  Removing them
	from your lastlog removes them from your screen as well.  This is
	useful for making noise go away retroactively
	Example:	/window clearlevel joins,parts,quits,kicks

*** News 09/08/2021 -- New statement type: block-with-arglist
	The ircII syntax now supports a new statement type, which I'm 
	calling a "block with arglist"

		(arglist) {block}

	You could also think of this as an "inline anonymous function".
	For the purposes of the statement, $* is modified by (arglist)
	and then {block} is run.

	Please note there are several caveats to this:
	  1. Arglist is not magic, it is syntactic sugar.  So it creates real 
	     local variables, and those local variables have their ordinary 
	     scope.  So they will persist after the end of the statement.
	  2. The statement only modifies $* during the statement itself.
	     So after {block} is run, $* goes back to what it was originally.
	  3. Note that this is a *statement* and not a *block* so if you are
	     working with something that expects a block, wrap it in {}s to
	     create a block.
		if (# == 3) {(arg0, arg1, arg2) {... code ...}}
	  4. Arglist processing isn't "free" so doing it in a tight loop will
	     be slower than doing it outside of the loop

*** News 09/07/2021 -- Pass window refnum in /ON CHANNEL_LOST
	The /ON CHANNEL_LOST hook now provides the window that a channel
	was in as $2
		$0 - The server refnum of a channel
		$1 - The name of a channel
		$2 - The window refnum of a channel

*** News 09/06/2021 -- Functions for JSON document handling
	Some time ago some new functions appeared for handling
	JSON documents, but they were not documented.  So now
	I am going to document them!

	CONVERTING JSON DOCS TO /ASSIGNS
	--------------------------------
	Syntax:    $json_explode(varbase json-document)

	An example is worth a thousand words:

	    $json_explode(e {"one": 1, "two": { "sub1", "hi", "sub2", "bye" })
	will result in three new assigns
		$e[one]		-> 1
		$e[two][sub1]	-> hi
		$e[two][sub2]	-> bye

	CONVERTING ASSIGNS TO JSON DOCS
	-------------------------------
	Syntax:	   $json_implode(varbase)

	This converts everything under $varbase[*] into a JSON doc.

	HANDLING ERRORS
	--------------
	If there is an error, $json_error() will tell you about it.

*** News 09/06/2021 -- SSL handling improvements (take 2)
	The other day I posted some info on how the SSL handling has been 
	improved.  But then things got revamped again, so I delete the old 
	info and am replacing it with this info.

	1) Step one - You connect to an SSL server
	 You connect to an irc server doing something like
		/SERVER irc.example.com:6697:type=irc-ssl
	 This goes through connect()ing to the server, and then doing an 
	 SSL_connect() to set up the certificate exchange and TLS negotiation.

	2) Step two - The SSL handshake is completed
	 After the SSL_connect() step has completed, we now have a fully 
	 functioning TLS socket with an SSL certificate.  Before we use the 
	 TLS socket, we're supposed to verify we trust the SSL certificate, 
	 to ensure we're talking to who we think we are.

	3) Step three - The client watches the certificate verification
	 OpenSSL "verifies" the certificate and the client provides
	 a C function to tag along for the ride.  The callback function
	 is called every time:
	   (1) An error is discovered, or
	   (2) There are no (further) errors in a certificate.
	 Thus, if a certificate is trusted, it will only report 
	 "no problems" for each link in the chain.

	 This permits the client to trap and categorize every error that
	 happens - some certificates have multiple problems!  There are
	 three buckets the client uses:
		(1) Self-signed certificates
		(2) Incorrect-hostname certificates
		(3) Any other (serious) error
	 The client tracks the "most serious error" (if there is one),
	 using the above priorities.

	4) Step four - The cliet offers you /ON SSL_SERVER_CERT
	  The client sets $serverctl(SET <refnum> SSL_ACCEPT_CERT -1)
	  and then throws /ON SSL_SERVER_CERT.   The use of -1 is on
	  purpose so the client can determine whether your /ON handler
	  sets it to 0 or 1.  

	  If your handler does a $serverctl(SET <retval> SSL_ACCEPT_CERT 0|1)
	  then that is taken as the final disposition of the handling, and 
	  nothing further occurs. (ie, it skips the rest of the steps)

	  Parameters of /ON SSL_SERVER_CERT
		$0  The fd of the socket
		    (Use $serverctl(FROM_SERVER) to get the server refnum)
		$1  Certificate Subject, url-encoded
		$2  Certificate Issuer, url-encoded
		$3  Bits used in the public key 
		$4  OpenSSL error code of the "most serious error"
			(18 is "Self-signed certificate",
			 62 is "Hostname mismatch",
			 everything else is irregular/bad)
		$5  The SSL regime being used (ie, TLSv1.2)
		$6  The Certificate Hash
		$7  Was there a hostname mismatch?  0 = no error, 1 = error
		$8  Was there a self-signed error?  0 = no error, 1 = error
		$9  Was there another (serious) error?  
			0 = no other error 1 = other error
		$10 Was there any error of any kind?  
			0 = no errors of any kind, 1 = some kind of error

	5) Step five - The client makes a provisional decision
	  Next, the client looks at the errors and decides whether
	  it thinks the cert is ok.  
	    * Cert has no errors 		   -> ACCEPT
	    * Cert has "self signed" or "wrong hostname" error
	      and /SET ACCEPT_INVALID_SSL_CERT ON  -> ACCEPT
	    * Cert has "self signed" or "wrong hostname" error
	      and /SET ACCEPT_INVALID_SSL_CERT OFF -> REJECT
	    * Cert has any serious error	   -> REJECT
	  The client sets this provisional value with 
		$serverctl(SET <refnum> SSL_ACCEPT_CERT 0|1)

	6) Step six - The client offers you /ON SERVER_SSL_EVAL
	  Then, the client hooks /ON SERVER_SSL_EVAL.  At this point,
	  all of the information your script needs to make a fully 
	  informed decision to accept or overrule the client's choice
	  is available.  Your handler is not obligated to make any
	  change, but it certainly can if it wants to 

	  Parameters of /ON SERVER_SSL_EVAL
		$0  The server refnum
		$1  The "ourname" of the server (what you /server'd to)
		$2  Was there any error at all? 
			0 = no errors of any kind   1 = some kind of error
		$3  Was there a hostname mismatch?  0 = no error, 1 = error
		$4  Was there a self-signed error?  0 = no error, 1 = error
		$5  Was there another (serious) error?
			0 = no other error, 1 = other error
		$6  What does the client suggest?
			0 = reject certificate, 1 = accept certificate

	  Using $serverctl() to get info about the certificate
	  Use $serverctl(GET <refnum> <item>) where <item> is:
		SSL_CIPHER		The encryption cipher being used
		SSL_PEM			The certificate (in PEM format)
		SSL_CERT_HASH		The certificate's hash
		SSL_PKEY_BITS		The bits in the public key
		SSL_SUBJECT		Who the cert was issued to
		SSL_SUBJECT_URL		Who the cert was issued to (url-encoded)
		SSL_ISSUER		Who issued the cert
		SSL_ISSUER_URL		Who issued the cert (url-encoded)
		SSL_VERSION		What version of SSL being used (ie, TLSv1.2)
		SSL_SANS		Subject Alternate Names in the cert
		SSL_CHECKHOST_ERROR	Hostname Mismatch error - 0 (no) 1 (yes)
		SSL_SELF_SIGNED_ERROR	Self-signed error - 0 (no) 1 (yes)
		SSL_OTHER_ERROR	        Any other (serious) error - 0 (no) 1 (yes)
		SSL_MOST_SERIOUS_ERROR	The OpenSSL error code of the most serious error
					18 (self-signed) and 62 (hostname mismatch)
					are considered non-serious (routine) errors
		SSL_VERIFY_ERROR	Any error at all - 0 (no) 1 (yes)
		SSL_ACCEPT_CERT		Is this cert headed for acceptance?  0 (no) 1 (yes)

	   Use $serverctl(SET <refnum> SSL_ACCEPT_CERT 0) to reject the cert
	   Use $serverctl(SET <refnum> SSL_ACCEPT_CERT 1) to accept the cert
	   If you don't do anything, the client will do the most reasonable thing

	7) Step seven - The client moves forward
	  Finally, everyone has had a chance to weigh in.  
	  Whatever the value of $serverctl(GET <refnum> SSL_ACCEPT_CERT) 
	  is after all this, is used to accept or reject the SSL connection.

*** News 09/02/2021 -- Configuring SSL Ciphers
	Now, if you know what you are doing, you can set
	the SSL Ciphersuites that the client will use for
	SSL connections, via
		/SET SSL_CIPHERS <stuff>
	If you don't know what you're doing, don't touch.
	The default value is "unset", which means we let
	openssl choose the ciphers for us.

*** News 09/02/2021 -- SSL Handling improvements
	[replaced -- see above]

*** News 08/30/2021 -- New server description field "ssl-strict"
	[this feature was removed]

*** News 05/29/2021 -- EPIC5-2.1.5 released here (Fecund) (Commit id: 1945)

*** News 05/25/2021 -- Updated configure to autoconf-2.69
	We upgraded configure from autoconf-2.13 to 2.69 here.
	Along the way, we fixed the support for python3.8+

*** News 05/20/2021 -- Windows have UUIDs ($windowctl(GET x UUID))
	Every window now receives an immutable UUID when it is 
	created.  This UUID is globally unique and cannot be changed.

	Although the UUID is not user-facing (as in /window list),
	you can get it with $windowctl(GET refnum UUID).

	The UUID is an lval (that is, it does not contain hyphens),
	so you can use it as part of a variable name if you wish.

*** News 05/20/2021 -- New concept, "claiming channels"
	When EPIC receives a protocol JOIN message for a channel, 
	it has to decide what window to put the channel in.  
	A common request has been the opportunity to let scripts 
	decide where new channels should go, rather than it being 
	hardcoded.

	So now when a JOIN is received, an /ON will be thrown 
	(see below) which is an invitiation for your script to do
	whatever preparatory work for the channel you see fit.

	One thing in particular is /WINDOW CLAIM (see below), which
	tells EPIC which window the channel should be put into.
	As part of this process, EPIC will suggest a window the 
	channel should go into, unless you choose to overrule that.

	*** NONE OF THIS APPLIES TO /JOIN or /WINDOW CHANNEL
	    when the user is deliberately moving a channel they are
	    already on between windows.  You can't stop that.

*** News 05/20/2021 -- New /ON, /ON CHANNEL_CLAIM 
	The /ON CHANNEL_CLAIM is thrown when a JOIN is received,
	but before the client has assigned the channel to a window.
		$0 - The server refnum 
		$1 - The channel being joined
		$2 - The window refnum epic proposes to put the
		     window into.

	If your handler does /WINDOW CLAIM in any particular window,
	then the channel will go to that window that you specify.

	At this time, you can only do /WINDOW CLAIM in a window that
	is connected to the server in $0. In the future, this will
	probably change.  But for now, a /WINDOW BIND in a "window
	connected to the wrong server" is treated as invalid.

	If you do not do a valid /WINDOW CLAIM, then the channel will
	go into the window proposed by EPIC.

*** News 05/20/2021 -- New /WINDOW operation. /WINDOW CLAIM #channel
	During the handling of an /ON CHANNEL_CLAIM, you may perform
	the /WINDOW CLAIM operation to direct EPIC to put the new
	channel into a particular window.

	You must pass the name of the channel as a paraemter.
	It is available as $1 in the /on.

	You may only claim the channel in a window that is connected
	to the correct server (from $0).  Attempting to claim a 
	channel in a window connected to the wrong server is invalid
	and has no effect.   This will change in the future.

*** News 05/20/2021 -- $uuid4() can now return lvals (NODASHES)
	You can now get a uuid4 that is valid as an lval if you
	supply NODASHES as the only argument
		@ a.$uuid4(NODASHES) = [whatever]

	ALL ARGUMENTS TO THIS FUNCTION ARE RESERVED FOR FUTURE EXPANSION.
	There are now two defined behaviors:
		$uuid4()	 - UUID4 with dashes
		$uuid4(NODASHES) - UUID4 without dashes
	EVERYTHING ELSE IS UNDEFINED BEHAVIOR (ie, other arguments may 
	do something today, but forwards compatability is not guaranteed)

*** News 03/26/2021 -- EPIC5-2.1.4 released here (Redound) (Commit id: 1927)

*** News 02/13/2021 -- /UNLOAD now supports /TIMERs
	If you create a /TIMER in a script you /LOAD with /PACKAGE
	the timer will be tagged just like any aliases or assigns
	or ons or whatever.

	Note that /TIMERs are _not_ tagged if they are created 
	after /load time.  This includes but is not limited to 
	timers created by aliases that are tagged; as well as
	timers that create new versions of themselves (but it 
	will catch timers that run forever)

*** News 02/10/2021 -- New /WINDOW operation, /WINDOW UNCLEAR
	There was already an /UNCLEAR command, and a /CLEAR and
	/WINDOW CLEAR command, but there was no /WINDOW UNCLEAR.
	WHy not? Anyways...

*** News 02/07/2021 -- Low level operations on cutbuffer - $inputctl()
	Harzilein asked if there was a way to manipulate the cutbuffer
	without having to put something in the input line.  As it happens,
	that has never been requested before.  So here we go!

	$inputctl(GET cutbuffer)
		This returns the cut buffer.  This is the same as $U

	$inputctl(SET cutbuffer ... new value ...)
		This sets the cut buffer.  This would be effectively
		the same as:
		 * Saving the input line (with $L)
		 * Erasing the input line (parsekey ERASE_LINE)
		 * /TYPEing what you want into the cut buffer
		 * Erasing the input line (to put it into the cut buffer)
		 * /TYPEing the origial input line
		But this doesn't require you to disrupt the input line.

		Please remember that there is only one cut buffer,
		and a large number of operations replace it -- so 
		whatever you put in the cut buffer, use it quickly,
		or the user might clobber it.

*** News 02/05/2021 -- /ON SERVER_STATUS changed to /ON SERVER_STATE
	Some expressed some confusion about whather "SERVER STATUS"
	and "SERVER STATE" were the same thing, and what the states
	were and what they meant.  To reduce this confusion, there
	will be only one term, "SERVER STATE". However, much code
	already uses "SERVER STATUS".  So we have to support both.

	For now, /ON SERVER_STATUS and /ON SERVER_STATE will both 
	exist side by side.   However, I recommend you use 
	/ON SERVER_STATE for new code, and think about migrating
	your old code.   There will come a day when /ON SERVER_STATUS
	will beoome an alias for /ON SERVER_STATE.

	To be unambiguous, using /ON SERVER_STATUS will never break.
	But you should know the official name is going to be 
	SERVER_STATE.

	The stock scripts have been updated.  You can get the changes
	by making sure to do a 'make install'

*** News 02/05/2021 -- $serverctl(GET x STATUS) changed to STATE
	As per the above, both $serverctl(GET x STATUS) and 
	$serverctl(GET x STATE) will return the server's state.
	However, you are encouraged to start using "STATE", since
	that is now the official term for it.

	The stock scripts have been updated.  You can get the changes
	by making sure to do a 'make install'

*** News 07/03/2020 -- New /WINDOW operation, /WINDOW DELETE_KILL
	Harzilein pointed out:
	  1) You cannot delete the last window on a screen
	  2) Deleting a screen does not kill a window
	  3) Therefore, deleting a screen necessarily orphans a window
	But what if you don't want to orphan a window when you kill a
	screeN?  

	The /WINDOW DELETE_KILL operation does a /WINDOW DELETE and
	then does a /WINDOW KILL on the window that was the current
	window.  There are several caveats to this *which i reserve
	the right to change in the future*
	
	Caveat 1) Only the "current window" gets killed.  So if you 
	    DELETE_KILL a screen with multiple windows, other windows
	    will be orphaned in the ordinary way.  I reserve the right
 	    to change this behavior (it will be documented)
	Caveat 2) If you cannot kill the window for other reasons, 
	    such as /window killable off, then the attempt to kill the
	    window will fail, and it will be orphaned.

*** News 05/11/2020 -- EPIC5-2.1.2 released here (Lugubrious) (Commit id: 1908)

*** News 05/09/2020 -- New built in function $execctl()
	You can now program the /EXEC command with this low level function

	--- warning ---
	Many of the things you can set here are not sanity checked.
	If you feed it garbage in, you will get garbage out.
	If you need safety rails, use the /EXEC command.
	--- warning ---

	Usage:
	------
	$execctl(REFNUMS)
		Get all refnums in the entire system (as integers)
	$execctl(REFNUM <description>)
		Convert a description (like %3 or %myproc) into a refnum integer

	$execctl(NEW <commands>)
		Create a new /exec process (does not run it!)
	$execctl(LAUNCH <refnum>)
		Run an /exec process that hasn't been started yet
	$execctl(CLOSEIN <refnum>)
		Close the STDIN to the process (this means you can't send any
		more data to the program.  This is useful for programs
		that wait until they've got an EOF from stdin to do their 
		thing)
	$execctl(CLOSEOUT <refnum>)
		Close the STDOUT and STDERR from the process (this means 
		we won't receive any more output from the program.  This is
		useful if we don't want any more output from the program.
		Many programs will die from SIGPIPE if stdout is closed)
	$execctl(SIGNAL <signal> <refnum>)
		KILL (send a signal) to a process.  The <signal> may either
		be an integer (like $execctl(SIGNAL 9 3) or it may
		be a short name (like $execctlSIGNAL HUP 3) to kill 
		process 3.

	$execctl(GET <refnum> [FIELD])
	$execctl(SET <refnum> [FIELD] [VALUE])
		You can GET all the fields of the object, and SET some of them.
		Some fields cannot be changed after the process is launched.

	Field		Set?	Notes
	-------------	------	-----------------------------------
	REFNUM		No	The integer refnum - never repeated.
	REFNUM_DESC	No	The "target" version (ie, %3)
	LOGICAL		Yes	The user-supplied name - must be unique
	LOGICAL_DESC	No	The "target" version (ie, %myproc)
				-- This will change if you SET LOGICAL
	COMMANDS	Yes	The commands to run (**)
	DIRECT		Yes	Whether to use a shell (**)
	REDIRECT	Yes	Either PRIVMSG or NOTICE
	WHO		Yes	The target to send output to
				-- Output from the process is redirected verbatim
	WINDOW_REFNUM	Yes	The window this exec runs in context of
				-- Undefined behavior if window does not exist
	SERVER_REFNUM	Yes	The server this exec runs in context of
				-- This is for redirects and code callbacks
	LINES_LIMIT	Yes	How many lines to receive before CLOSEOUT
				-- 0 means "no limit"
	STDOUTC		Yes	ircII code for every complete line of stdout
	STDOUTPC	Yes	ircII code for every partial line of stdout
	STDERRC		Yes	ircII code for every complete line of stderr
	STDERRPC	Yes	ircII code for every partial line of stderr

	PID		No	The process id of the process (after launch)
				-- This is -1 before launch
	STARTED_AT	No	When the process was created or launched
				-- It is first set when creation happens
				-- It is last set when launched
	P_STDIN		No	File descriptor to talk to process's STDIN
	P_STDOUT	No	File descriptor to read from process's STDOUT
	P_STDERR	No	File descriptor to read form process's STDERR
				-- There is nothing you can do with these.
				-- Don't try.
	LINES_RECVD	No	How many lines of output the process has sent
	LINES_SENT	No	How many lines we sent to the process
	EXITED		No	0 if process has exited yet -- 1 if it has
	TERMSIG		No	The signal that killed the process
				-- It is -1 if the process has not died
				-- It is -1 if the process exited normally
	RETCODE		No	The exit code of the process
				-- It is -1 if the process has not died
				-- It is -1 if the process was killed
	DUMB		No	Reserved for future/internal use
	DISOWNED	No	Reserved for future/internal use
	(Note: ** - Cannot be SET after launch)

*** News 05/08/2020 -- New flag to /EXEC, /EXEC -NOLAUNCH
	The /EXEC -NOLAUNCH flag directs the /EXEC command not to launch 
	a process that has not already launched.  You can launch it later 
	merely by referencing it with its name or refnum.

		/EXEC -nolaunch -name myproc ls -l
		/EXEC -nolaunch -limit 5 %myproc
		/EXEC %myproc

	Many /EXEC operations do not work on an unlaunched process.

*** News 05/07/2020 -- New function, $uuid4()
	This function returns a random UUID4 string.  If you know what that is,
	you might know why it's handy to be able to have one.

	ALL ARGUMENTS TO THIS FUNCTION ARE RESERVED FOR FUTURE EXPANSION.
	To get the default behavior, pass no arguments to this function.
	Forwards compatability is not guaranteed if you pass undefined args

*** News 05/07/2020 -- New /ON, /ON SEND_EXEC
	Whenever text is being sent to an /EXEC process, either through /EXEC -IN
	or /MSG %proc or a /QUERY or whatever, it is displayed to your screen.
	The /ON SEND_EXEC process will let you adorn how this text is displayed,
	instead of it just being displayed blankly as it has always done.

*** News 05/07/2020 -- The /EXEC command
	The /EXEC command has always been part of ircII, but it hasn't
	changed much during EPIC's lifetime.  There were some rough edges
	related to querying exec'd processes, things not always going
	to the windows people expected, some flags not being able to be
	used with other flags, etc.

	So the /EXEC command has been substantially revamped, with an intention
	of everything being "do what i expect".  If you find things that are 
	weirdly behaving, please let me know!

	Instead of describing the changes, let's just level-set the behavior:

	Every /EXEC command can create or modify one process

	[The most general explanation of the syntax]
	Modify an existing running exec:
		/EXEC [options] %refnum [extra arguments]
		/EXEC [options] %logical-name [extra arguments]

	Create a new exec:
		/EXEC [options] commands to run
		/EXEC [options] (commands to run) [extra-arguments]

	OPTIONS to /EXEC

	   [ Options related to sending data to/from the process ]
		-CLOSE
			Close the process's STDIN, STDOUT, and STDERR
		-CLOSEIN
			Close the process's STDIN
		-CLOSEOUT
			Close the process's STDOUT and STDERR
		-IN [extra arguments]
			Send data to a process

	   [ Options related to how the process integrates with ircII ]
		-NAME
			Change the logical name of a process
		-OUT
			Send all output from the process to the now-current 
			channel in the now-current window.
		-WINDOW
			Display all output from or related to the process to the 
			now-current window.
		-WINTARGET <windesc>
			Display all output from or related to the process to the 
			specified window
		-MSG [target]
			Send all output from the process to the target.
			The target can be an irc, dcc chat, or other exec,
			or anything you can send a message to.
			Messages sent over IRC are sent as PRIVMSGs
		-NOTICE
			Send all output from the process to the target.
			Messages sent over IRC are sent as NOTICEs.

	    [ Options related to scripting with processes ]
		-LINE {code}
			Run {code} for each full line of output from stdout of the process.
			$* will be the line of output
		-LINEPART {code}
			Run {code} for each incomplete line of output from stdout of the process.
			$* will be the incomplete line of output
		-ERROR {code}
			Run {code} for each full line of output from stderr of the process.
			$* will be the incomplete line of output
		-ERRORPART {code}
			Run {code} for each incomplete line of output from stderr of the process.
			$* will be the incomplete line of output
		-END {code}
			Run {code} when the process has completed.  This means when the process
			has exited and all of its output has been processed.  (Sometimes this 
			lags the actual exit)
				$0 is the logical process name or its refnum
				$1 is the signal that killed it (if it was killed)
				$2 is the exit code (if it exited)

	    [ Options that don't fit in the other categories ]
		-DIRECT
			Run the program directly -- do not use a shell.  
			Advantages:  The command you give is literally executed
			Disadvantages: If you depend on filename globbing or aliases, well, tough
		-LIMIT <number>
			Read <number> lines from the process and then -CLOSE it.

	    [ Options related to sending a signal to the process ]
		-<signal_number>
			Send the signal to the process, similar to kill -<signal_number> <pid>
		-<signal_name>
			Send the signal to the process, similar to kill -<signal_name> <pid>

	Additionally, %<procref> or %<procname> are full blown message targets that you can 
	/msg or /query or whatever you want, just like all other targets.

	[Examples of how this works]


*** News 04/26/2020 -- New python script, 'shortener'
	You can load this script with
		pyload shortener
	This script provides an in-client URL shortening service.
	Whenever someone provides a URL in a message, the service
	will create a short URL that will be served by an http
	redirection server that runs in client

	Example:
	--------
	<nick> hey, please visit www.frobnitz.com/really-long-and-wraps
        +onto-the-next-line-so-you-can-tpaste-it
	*** http://127.0.0.1:8080/1

	Then you can visit http://127.0.0.1:8080/1 and it will
	redirect you to the original url.

*** News 02/24/2019 -- EPIC5-2.1.1 (Abulia) was released here
	Even though not everything is done, I think I've probably
	dragged my feet long enough

*** News 11/28/2018 -- /EXEC -WINTARGET outsputs to a window by name (caf)
	The normal behavior of /EXEC is to send the output of a command
	to the current window (or is it the OTHER window?  I forget)
	Before this, you couldn't ordinarily send it to just any old
	random window you wanted.  

	You can use /EXEC -WINTARGET to send it to any window you want:
	Example:
		/exec -wintarget msgwin ls

*** News 02/24/2019 -- EPIC5-2.1.1 released here (Abulia) (Commit id: 1899)

*** News 02/05/2018 -- CTCP UTC now implemented as script
	Given the below feature, CTCP PING support has been 
	rewritten, and CTCP UTC is now scripted.

*** News 02/13/2018 -- New flag for $ctcpctl(), "REPLACE_ARGS"
	There are actually two kinds of CTCPs that replace things

	* CTCP PING replaces its argument(s), but is otherwise
	  handled "normally"
		NOTICE nick :\001PING <sec> <usec>\001
	  becomes
		NOTICE nick :\001PING <sec> seconds\001

	* CTCP UTC replaces itself entirely:
		PRIVMSG nick :\001UTC 1518582810\001
	  becomes
		PRIVMSG nick :Tue Feb 13 22:33:30 2018

	So it's not enough to say that "a CTCP handler can replace 
	itself by returning a string", you need to be able to say
	whether this CTCP replaces its arguments only, or whether
	it replaces itself entirely.

	  * $ctcpctl(SET <ctcp-name> REPLACE_ARGS 1)
	  * $ctcpctl(SET <ctcp-name> REPLACE_ARGS 0)
		Select whether or not a CTCP handler that returns a 
		string replaces its arguments (like CTCP PING) or 
		replaces itself entirely (like CTCP UTC).  
		The default is 0 (replace entirely)

*** News 02/05/2018 -- Some CTCPs are now implemented as scripts
	YOU NEED TO START DOING /LOAD ctcp  IN YOUR STARTUP SCRIPTS.

	One of the larger projects in EPIC5 was to move as many
	hard coded things into scripts as was feasible, so you,
	the user (or the script you're using) can have as complete
	control over them.  We've moved a lot of functionality out
	into scripts.

	Traditionally those users who don't have startup scripts 
	(~/.epicrc or ~/.ircrc) get /load global as their startup
	script.  One of the things /load global does is /load builtins
	which brings in the scripted features.  

	Now /load builtins will /load ctcp, which implements these 
	core CTCP functions entirely in ircII, so you are welcome 
