home *** CD-ROM | disk | FTP | other *** search
/ ftp.update.uu.se / ftp.update.uu.se.2014.03.zip / ftp.update.uu.se / pub / irc / Kiwi.4.37.el < prev    next >
Text File  |  1996-09-07  |  427KB  |  11,636 lines

  1. ;(set (make-local-variable 'debug-on-error) t)
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;; -*- Mode: Emacs-Lisp -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;; Kiwi.el --- A user interface for the Internet Relay Chat
  4. (defconst irc-version "Kiwi v4.36 for GNU Emacs" "Current Kiwi version.")
  5. (defconst irc-ftp-version "4.37" "Current FTP'able version.")
  6. (defconst irc-ftp-file-names (list (format "Kiwi.%s.el*" irc-ftp-version)
  7.                  "Kiwi.README"))
  8. (defconst irc-ftp-source (list (list "FTP.Update.UU.SE" "pub/irc"
  9.                      irc-ftp-file-names)
  10.                    (list "FTP.FUNet.FI" "pub/unix/irc/Emacs"
  11.                      irc-ftp-file-names)))
  12. (defconst irc-hacker "Klaus.Zeuge@Student.DoCS.UU.SE"
  13.   "Email address of the person to send complaints and ideas too.")
  14. ;;;;;;;;;
  15. ;; v4.37 Sun Sep  8 21:33:43 1996    sojge@Student.DoCS.UU.SE
  16. ;;    - Changed FTP sites.
  17. ;; v4.36 Fri Sep  6 19:21:56 1996    sojge@Student.DoCS.UU.SE
  18. ;;    - Message 325 (channel creation time), 338 (login time for a
  19. ;;      user) and 339 (time when the topic of a channel was set)
  20. ;; v4.35 Mon Aug 26 00:07:03 1996    sojge@Student.DoCS.UU.SE
  21. ;;    - Better Undernet handling in various places.
  22. ;;    - BUGFIX: make it harder to issue /WHO command w/o arument.
  23. ;;    - New value for irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1.
  24. ;; v4.34 Fri Feb  9 19:38:02 1996    sojge@Student.DoCS.UU.SE
  25. ;;    - Use last-command-char instead of last-input-char.
  26. ;;    - Obsoleted irc-explain-who-mode, moved to code to 352 handler.
  27. ;;    - Added undernet message 329, 333.
  28. ;;    - If emacs-version > 18, assume irc-emacs-knows-ISO8859-1 to t.
  29. ;;    - Added RPL262.
  30. ;;    - Made irc-startup-hook non-depended on LUSERS commands, moved it to
  31. ;;      CLIENT-SYNCH like mechanism (CLIENT-START)
  32. ;;      - Added 250 highest connect count.
  33. ;;    - Added a "whois x x" in irc-execute-info.
  34. ;;    - Added ignore stuff in notify detector, RPL303.
  35. ;;    - Added 409 no origin spec'ed (from /quo ping).
  36. ;;    - Reply 442 keeps changing, more kludging added.
  37. ;;    - BUGFIX, now understands 002 message "ircd2.8/dog3-super.pl7"
  38. ;; v4.33 Tue Dec 13 18:59:10 1994    sojge@Student.DoCS.UU.SE
  39. ;;    - Added new variable irc-scroll-step.
  40. ;;    - Added better knoweldge of &channels.
  41. ;;    - Show own nickname in ping replies on screen from others.
  42. ;;    - Cleaned up server informatio in /LINKS reply.
  43. ;;    - Better regexp when parsing 203:205 messages.
  44. ;;    - Put \< and \> around nick regexp for backtalk.
  45. ;;    - IRC-servers now understands command "TOPIC #C"
  46. ;;    - BUGFIX: 2.8.20 has a new 204 format with funky timer.
  47. ;; v4.32 Mon Aug  8 02:53:16 1994    sojge@Student.DoCS.UU.SE
  48. ;;    - BUGFIX: server 2.8.20 has new 317 message.
  49. ;;    - Added status line counter irc-reply-count for /who, /names, /links.
  50. ;;    - Added new /signal detect for /notify detect/lost sight messages.
  51. ;;    - Added new variable irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1
  52. ;;      to be used if one wants irc-self-insert to map certain keystrokes.
  53. ;;    - Changed irc-self-insert to be able to map from ISO 646-SE2 to
  54. ;;      ISO 8859-1.
  55. ;;    - Fixed typo in docstring of irc-time-diff.
  56. ;;    - Use irc-userhost in irc-parse-channel.
  57. ;; v4.31 Tue Oct 19 20:59:11 1993    sojge@Student.DoCS.UU.SE
  58. ;;    - BUGFIX: don't crash if CTCP quote is last in string.
  59. ;;    - BUGFIX: name buffer accoring to connected TCP-port, not default
  60. ;;      TCP-port.
  61. ;;    - Better handling of channel topic display.
  62. ;;    - Added handling of ERR 422 and 443, and RPL 249.
  63. ;;    - Clean up CTCP VERSION reply before displaying it.
  64. ;; v4.30 Tue Aug 24 20:52:21 1993    sojge@Student.DoCS.UU.SE
  65. ;;    - BUG FIX: erroneous format string fixed when handling CTCP ECHO reply.
  66. ;;    - Bug fix in irc-execute-notify, don't try to irc-forget a non nick.
  67. ;;    - Added backtalk to documentation of /signal.
  68. ;;    - Made variable irc-port (ie the TCP port used to connect to an IRC
  69. ;;      server) buffer local so different sessions can use diffferent ports.
  70. ;;    - Added handling of RPL 392.
  71. ;;    - Better handling of RPL 322.
  72. ;;    - Now cleans up QUIT messages.
  73. ;;    - Added handling ERR 422, no MOTD file.
  74. ;;    - Minor betterification in character mapping.
  75. ;; v4.29 Thu Aug 12 03:24:57 1993    sojge@Student.DoCS.UU.SE
  76. ;;    - If DEL pressed while point is at first postion in input region,
  77. ;;      scroll down page instead of beep.
  78. ;;    - More channel modes explained in irc-explain-mode (k and v).
  79. ;;    - Force emacs to offer to save the Kiwi buffer before exiting emacs.
  80. ;;    - Splitted up irc-parse-RPL so it's byte-compile'able with v18 emacs.
  81. ;;    - Remove the CTCP MOOD command as no one else used it.
  82. ;;    - As there are a lot of old clients out there, send several CTCP pings.
  83. ;;    - Unless debug-on-error is non-nil, don't crash when finding dots in
  84. ;;      host names, nicks etc.
  85. ;;    - New function irc-time-diff used to not send ISON commands more often
  86. ;;      than every 60 second.
  87. ;;    - New handling of topic, see /HELP TOPIC.
  88. ;;    - Don't care what user tries to /VERSION, let server decide if it
  89. ;;      makes sense.
  90. ;;    - Added handling of RPL 305, 306, 371, 374, 392, 394.
  91. ;;    - Added handling of RPL 242, 243, 244, 253, 261.
  92. ;;    - New format in TRACE output in RPL 200, 211.
  93. ;;    - Better parsing of "hello this is ircd version xxx" string at startup.
  94. ;;    - Added handling of ERR 436, 444, 445, 446, 467, 475.
  95. ;;    - Some minor changes in the CTCP handling. Nothing important.
  96. ;;    - make-local-variable doesn't set the variable in emacs v19, so needed
  97. ;;      to add a set in several places. NOW RUNS WITH GNU EMACS VERSION 19.
  98. ;;    - Fumbled around some more with character set convertings. Should go
  99. ;;      the v19 way, in the future.
  100. ;; v4.28 Mon Apr 19 15:48:45 1993    sojge@Student.DoCS.UU.SE
  101. ;;    - Made client somewhat compliant to ircd 2.8.
  102. ;;    - Added some (as of yet incomplete) support for different character
  103. ;;      sets like ISO 8859-1 and SIS E47.
  104. ;;    - Changed output of /WHO
  105. ;;    - Bugfixed irc-lowlevel-dequote to not crash when getting erroneous
  106. ;;      messages breaking the CNTRL/P quoting.
  107. ;;    - Bugfixed irc-execute-event.
  108. ;;    - Added CTCP MOOD. No /MOOD command yet, though.
  109. ;;    - Clean up a users full name in WHO replies.
  110. ;; v4.27 Mon Sep 14 19:17:23 1992    sojge@Student.DoCS.UU.SE
  111. ;;    - Better handling of versions through irc-ftp-* variables.
  112. ;;    - Added variable irc-show-japanese-characters to get better control
  113. ;;      about in what way japanese characters are inserted into buffer.
  114. ;;    - Spiffed up CTCP VERSION handling to comply to CTCP.mem v13.
  115. ;;    - Added flag irc-drop-ircII-text-kludge-control-characters for those
  116. ;;      users who WANT to see ^B, ^V and ^_ in text.
  117. ;;    - Ignore CNTRL/B, CNTRL/V and CNTRL/_ in incoming messages, as those
  118. ;;      are used by the ircII client to toggle reverse, underline and bold
  119. ;;      attributes of text.
  120. ;;    - Added variable irc-emacs-knows-ISO8859-1.
  121. ;;    - Fixed timing problem when receiving a PRIVMSG just after changing
  122. ;;      the nickname of oneself.
  123. ;; v4.26 Thu Aug 20 05:17:00 1992    sojge@Student.DoCS.UU.SE
  124. ;;    - Assorted small fixes.
  125. ;;    - Some new table headers (like for WHO).
  126. ;;    - Added RPL369, end of WHOWAS.
  127. ;;    - Added L line reply handling (RPL241).
  128. ;;    - Be nicer when sending automatic warnings.
  129. ;;    - Better handling of CTCP PING replies.
  130. ;;    - Reordered most global variable initialisations.
  131. ;; v4.25 Fri May 29 21:00:32 1992    sojge@Student.DoCS.UU.SE
  132. ;;    - Added user modes (eg /mode sojge -o)
  133. ;;    - Handles display of a channel's ban list (ie reply to /mode #x -b).
  134. ;;    - Better handling of some STATS replies.
  135. ;;    - Fixed irc-parse-quit.
  136. ;;    - Fixed irc-parse-kick.
  137. ;;    - Take care of v2.7.2 message ERROR: Closing Link.
  138. ;;    - Added CTCP commands ECHO, PING, SOURCE.
  139. ;;    - Started on a crude but better /IGNORE command.
  140. ;;    - Made Kiwi display unknown NOTICE's in block style.
  141. ;;    - Added /PING command, based on CTCP. Coded by Kimmo.Suominen@lut.fi.
  142. ;;    - Started on inout and output convertion tables to displat different
  143. ;;      character sets on different equipment.
  144. ;; 4.24 Mon Feb 24 17:01:09 1992    Klaus-Zeuge@DoCS.UU.SE
  145. ;;    - Still more RPL312 hacking. Hopefully looks OK on a 2.6.2 server now.
  146. ;; 4.23 Sat Feb 22 20:57:27 1992    Klaus.Zeuge@DoCS.UU.SE
  147. ;;    - Added real version number and edit history.
  148. ;; 4.22 Sat Feb 22 17:23:41 1992    Klaus.Zeuge@DoCS.UU.SE
  149. ;;    - Bugfixed CTCP VERSION reply from ircII.
  150. ;; 4.21 Sat Feb 22 16:38:05 1992    Klaus.Zeuge@DoCS.UU.SE
  151. ;;    - Removed annoying bug which mixed up different hash tables.
  152. ;;    - /mode can set modes for a user.
  153. ;;    - Added Q and Y to /stats.
  154. ;;    - /notify, a new command helping to see when your friends enter IRC.
  155. ;;    - /topic understands #channels, both when querying and setting.
  156. ;;    - /whois takes an optional first argument with name of server which
  157. ;;      should answer the whois question.
  158. ;;    - /quit now takes an optional reason.
  159. ;;    - Made /quote send an illegal command to server to help synchronizing.
  160. ;;    - Created variables irc-notify-looked-for and irc-notify-detected.
  161. ;;    - Added user mode in irc-explain-mode, added frontend functions
  162. ;;      irc-explain-user-mode and irc-explain-channel-mode.
  163. ;;    - Cope with different RPL312 styles.
  164. ;;    - Doing a somewhat better job at parsing ircII's ugly CTCP VERSION
  165. ;;      replies.
  166. ;;    - Cope with new RPL201-209, 211, 212, 213-219, 221.
  167. ;;    - Cope with some new NOTICE's.
  168. ;;    - Cope with new format of "Received SQUIT" NOTICE.
  169. ;;    - Cosmetic change in presenting other persons QUIT reasons.
  170. ;;    - Renamed irc-notifies into irc-events (lessens confusion with /notify)
  171. ;;    - Recognize the 500 series of ERR's from server.
  172. ;;    - Do a a sleep-for after EVERY received line from server.
  173. ;;    - Moved logging in *debug* buffer into irc-log-in-debug-buffer.
  174. ;; v4.20 Wed Dec 18 06:33:57 1991    Klaus.Zeuge@DoCS.UU.SE
  175. ;;    - Change a!b@c on incoming messages into a in irc-parse-server-msg.
  176. ;;      (Can you say kludge? I *knew* you could!)
  177. ;;    - Added RPL353 and RPL352 as front ends for NAMREPLY and WHOREPLY.
  178. ;;    - Parse 2.7(.0) version string correctly.
  179. ;;    - Better value for irc-msg-cont-used when reporting a channels mode.
  180. ;;    - Added Kimmo's code for detecting people on IRC using the ISON
  181. ;;      mechanism, irc-execute-notify. Also his irc-notify-list etc.
  182. ;;    - Added Kimmo's code for /ME and /DESCRIBE commands for CTCP ACTION.
  183. ;;    - Added Kimmo's code for recognizing CTCP ACTION commands.
  184. ;;    - Added fixes to keep Kiwi.el from choking on 2.7 messages.
  185. ;;      Fixed RPL messages are: 206, 209, 301, 304, 352, 353, 354,
  186. ;;      367, 368, 371, 373, 383, 384. Thank you Kimmo Suominen <kim@lut.fi>
  187. ;;      for supplying fixes.
  188. ;;    - Made comand "/join #channel +p" and friends kosher.
  189. ;;    - Added : as /MSG like command again after getting requests for it.
  190. ;;    - Threw out my irc-current-time based on writing irc-idle-scratch-file
  191. ;;      and replaced it by one donated by Stephen Ma <ma_s@maths.su.oz.au>.
  192. ;;    - Removed bug in irc-execute-signal.
  193. ;;    - Fixed parse error in irc-parse-pong.
  194. ;;    - More defensive handling of RPL319.
  195. ;; v4.19 Wed Nov 13 15:18:00 1991    Klaus.Zeuge@DoCS.UU.SE
  196. ;;    - Removed forgotten disabling of /KILL command. Ehum...
  197. ;;    - Use function make-temp-name when naming irc-idle-scratch-file.
  198. ;;    - Better formatting in /membership display.
  199. ;;    - Made irc-nuke-whitespace remove trailing spaces too.
  200. ;;    - Understand USERHOST replies (RPL302).
  201. ;;    - More 442 messages understood. Sigh.
  202. ;;    - Incoming TOPIC messages might contain channel name field.
  203. ;;    - USERS reply might contain word "display". Still valid.
  204. ;;    - Cope with 2.6.2e type of TRACE link lines.
  205. ;;    - "Understand" reason field in incoming QUIT messages.
  206. ;;    - Added Kims (kim@lut.fi) fix for 2.6.2e type of LUSER reply.
  207. ;;    - Fixed bug wtih dropped first character when user says "/mode * o u".
  208. ;; v4.18 Tue Oct 22 06:46:49 1991    Klaus.Zeuge@DoCS.UU.SE
  209. ;;    - Moved creation of irc-count-incoming-messages to irc-mode from
  210. ;;      irc-parse-server-msg.
  211. ;;    - Changed irc-truncate-buffer to chop down to irc-minimum-size whenever
  212. ;;      buffer has grown to irc-maximum-size.
  213. ;;    - Made irc-maximum-size = 64KB.
  214. ;;    - Added irc-minimum-size = 32KB.
  215. ;;    - Made most hash table twice as big.
  216. ;; v4.17 Sun Oct 20 17:05:01 1991    Klaus.Zeuge@DoCS.UU.SE
  217. ;;    - Rewrote most calls to string-match so they don't depend on . in
  218. ;;      regexps, as . doesn't match \n.
  219. ;;    - Made CTCP handling more iterative (recursive handling turned out
  220. ;;      to exhaust stacks in worst cases).
  221. ;;    - Made a few more variables buffer local.
  222. ;;    - Added low level quoting of \000, \n, \r, \020 and changed CTCP level
  223. ;;      quoting to use only \001 and \\.
  224. ;;    - Better irc-execute-stats.
  225. ;;    - Replaced all "\\s " by " " and all "\\S " by "[^: ]". Hopefully
  226. ;;      works better.
  227. ;;    - Crude RPL303 handling (reply to ISON).
  228. ;;    - Ripped out irc-maintain-tree! Hooray! Replaced by hash table code
  229. ;;      BUT named the new functions irc-remember, irc-recall, irc-forget.
  230. ;;      This speeded up /NAMES from some 5 minutes to some 10 seconds.
  231. ;; v4.16 Tue Sep 17 21:07:01 1991    Klaus.Zeuge@DoCS.UU.SE
  232. ;;    - When seeing idle time from IrcII clients, translate the large number
  233. ;;      of seconds into days, hours, minutes and seconds.
  234. ;;    - Writing to /dev/null to keep track of idle isn't portable. Use a
  235. ;;      temporary file in the users home directory instead.
  236. ;; v4.15 Thu Aug 22 13:46:03 1991    sojge@mizar.docs.uu.se
  237. ;;    - If user connects to server at host foo.bar.se and foo.se is an
  238. ;;      alias for rela.name.se, Kiwi gets confused. Now irc-server is
  239. ;;      set to real (ie generic) name from the servers Welcome message.
  240. ;;    - Fixed the macro subfield so it won't evaluate at compile time.
  241. ;;      Sigh. Stupid sojge. Thank you Lennart Staflin, Link|ping.
  242. ;;    - Fixed irc-parse-RPL: 317 does NOT give victims nick.
  243. ;;    - Fixed irc-maintain-tree to not crash when removing a service.
  244. ;;    - Added "Notice unauthorized connect" in irc-parse-notice.
  245. ;;    - Added CTCP query and reply for "FINGER". Hopefully this is added in
  246. ;;      a portable way, but I don't really KNOW ... :-(
  247. ;;    - Made irc-is-receiver recognize foo@bar.dom as valid receiver.
  248. ;; v4.14 Mon Aug 12 10:15:05 1991    sojge@mizar.docs.uu.se
  249. ;;    - Fixed /MODE command to work even when saying "/mode ..." in the
  250. ;;      buffer, not only when using C-c m.
  251. ;;    - Fixed some ERR-reply parsing code to grok new format.
  252. ;;    - Added /LEAVE 0 to leave all channels, and made /JOIN 0 just stop
  253. ;;      talking to the current channel.
  254. ;;    - Better nickname control, new scheme with irc-nick-used to keep track
  255. ;;      of what nick we have.
  256. ;;    - Renamed irc-linkstree into irc-linksinfo.
  257. ;;    - Kludged the mess with 2.6 servers first being names 2.6pre19,
  258. ;;      later 2.6.1a so the latter gets a HIGHER irc-edit-version number.
  259. ;;    - Parse RPL 364 messages, ie answers to /LINKS in 2.6.1 servers.
  260. ;;    - For now, ignore message 318.
  261. ;; v4.13 Thu Jun 13 10:28:31 1991    sojge@mizar.docs.uu.se
  262. ;;    - Handle ERR_NICKNAMEINUSE (433) at "login" time.
  263. ;;    - More homogenous command parsing (both /-style and keybound).
  264. ;;    - Cache subscribed channel names.
  265. ;;    - Name  Kiwi buffer "*Kiwi-<server>*".
  266. ;;    - Always run in "slow speed terminal" mode.
  267. ;;    - Shorter messages displayed when seeing a KILL, skipped path.
  268. ;;    - Renamed irc-hosttree into irc-servernames.
  269. ;;    - Added code to put communication in -*debug* buffer IFF it exists.
  270. ;;    - Changed regexp for host names yet again.
  271. ;;    - When getting the windows width, make sure it's the Kiwi window.
  272. ;;    - Prepared function irc to handle several sessions.
  273. ;;    - Handle some 2.6pre19 messages (324, MODE, 403).
  274. ;;    - Bound C-c i to /info.
  275. ;;    - Changed C-c m from /motd to /mode.
  276. ;;    - Fixed misfeature for v18.57 GNU Emacs. Several return values from
  277. ;;      function process-status are valid. Don't start a new session when
  278. ;;      an old one is running.
  279. ;;    - Fixed bug in showing LIST or NAMES reply of Kanjii channel.
  280. ;;    - Clean up channel names as they can contain cntrl-chars too.
  281. ;;    - Fixed display of time to be nicer.
  282. ;;    - Make the (interactive)-part of the irc-execute-* commands more alike
  283. ;;      each other.
  284. ;;    - Bugfix: understand ESC in channel names in a few more places.
  285. ;;    - Bugfix: understand "i" etc, not only "+i" when parsing MODE.
  286. ;;    - Made /COMMAND be shown in buffer when doing command by keys.
  287. ;;    - Amazingly how yours truly can mess up code! Fixed /LEAVE again :-)
  288. ;; v4.12 Sun Mar  3 02:45:21 1991    sojge@mizar.docs.uu.se
  289. ;;    - Changed wording on ctcp (client-to-client protocol) answer for
  290. ;;      a VERSION query.
  291. ;;    - Added C-c C-k to do irc-execute-kill.
  292. ;;    - Bugfixed irc-execute-leave so it works when typing /LEAVE not just
  293. ;;      when typing C-c q.
  294. ;;    - Better handling of /STATS C replies from remote servers.
  295. ;;    - Handle error after /kick user when user's not on channel.
  296. ;; v4.11 Fri Mar  1 16:31:04 1991    sojge@mizar.docs.uu.se
  297. ;;    - Bugfix, corrected misspelled variable for when replying to unkown
  298. ;;      client-to-client PRIVMSG.
  299. ;; v4.10 Thu Feb 28 20:06:05 1991    sojge@mizar.docs.uu.se
  300. ;;    - New behaivour of /WHO, see /HELP WHO.
  301. ;;    - Various bugfixes. (Mostly due to bound keys).
  302. ;;    - Replaced irc-read-user/host by irc-read-object.
  303. ;; v4.9 Wed Feb 27 20:29:58 1991    sojge@mizar.docs.uu.se
  304. ;;    - Added quoting of messages between CNTRL/A:s.
  305. ;;    - Better grok of WALLOPS.
  306. ;;    - Remember correct spelling of a services nickname when seeing
  307. ;;      NOTICES's from one.
  308. ;;    - Bugfixed /CONNECT which w/o "remoteserver" goofed.
  309. ;; v4.8 Wed Feb 27 03:57:50 1991    sojge@mizar.docs.uu.se
  310. ;;    - More initialisation help.
  311. ;;    - Changed client-to-client protocol in non-backward compatible way.
  312. ;;    - OK'ed "/version mizar*".
  313. ;;    - Better handling of /join 0 when on #channel. Updates irc-channel.
  314. ;;    - Changed handling of unknown NOTICE's to be treated as PRIVMSG's.
  315. ;;    - Fixed bug when replying to CLIENT ERRMSG.
  316. ;;    - Show irc-channel in status line.
  317. ;;    - Always send two ^A's, even if to queries/answers are in a row.
  318. ;;    - Made /msg grok broadcast addresses ($server, #host) when enabled.
  319. ;;    - Fixed bugs in /kick.
  320. ;;    - Better help for how to install your personal IRC initiation.
  321. ;; v4.7 Sun Feb  3 03:51:59 1991    sojge@mizar.docs.uu.se
  322. ;;    - Take care of some new styled NOTICE's from the server.
  323. ;;    - Cleaned up the code of irc-parse-priv.
  324. ;;    - Bugfixed irc-parse-kick to keep better track of where we are.
  325. ;;    - Added command /SERVICE.
  326. ;; v4.6 Fri Feb  1 04:03:31 1991    sojge@mizar.docs.uu.se
  327. ;;    - Better handling of /WHOWAS.
  328. ;;    - Changed string from "Kiwi Operator" into "Kiwi, Operator" while
  329. ;;      enabled.
  330. ;; v4.5 Fri Feb  1 02:24:00 1991    sojge@mizar.docs.uu.se
  331. ;;    - Added command /USERINFO to set a string which can be queried by other
  332. ;;      users. Augmented commands /INFO and /VERSION to query the user
  333. ;;      settable string and to query some client version from a users client.
  334. ;;    - Added knowledge of some more NOTICE's from the server.
  335. ;;    - Better handling of STATS, both in giving command (/STATS) and
  336. ;;      parsing L type replies (ie how much data). Added /HELP STATS.
  337. ;;    - Display another field in WHOIS/WHOWAS replies, showing servers text
  338. ;;      field from message 312.
  339. ;;    - Added in irc-parse-notice case for "*** ..." messages.
  340. ;;    - Bugfixed irc-execute-help, so it deals with aliases and topics which
  341. ;;      aren't commands.
  342. ;;    - Changed clients name from sojge-irc.el to Kiwi.el
  343. ;;      (Kiwi initially was irc.el).
  344. ;;    - Added varibales irc-msg-info-pre and -post for letting user select
  345. ;;      how information (default eg: [Foo has joined channel +Bar], the [
  346. ;;      and ] characters) messages start and end.
  347. ;;    - Statistics display nicyfied.
  348. ;; v4.4 Mon Dec 17 17:51:24 1990    sojge@mizar.docs.uu.se
  349. ;;    - Added column alignment (irc-msg-cont-used) for RPL322 and RPL323
  350. ;;      messages (RPL_LIST and RPL_LISTEND).
  351. ;;    - Bugfix: prevents client from crashing (when connected to a 2.6-server
  352. ;;      and doing a TRACE for a nonexistent server) by adding some
  353. ;;      code the for 402 ERR reply (ERR_NOSUCHSERVER).
  354. ;; v4.3 Sun Dec 16 19:19:00 1990    sojge@mizar.docs.uu.se
  355. ;;    - Added case for trace reply "UNKNOWN" in irc-parse-notice.
  356. ;;    - Added key C-c = to do a /MEMBER command.
  357. ;;    - Bugfix: changed general regexp in irc-parse-server-msg to not allow
  358. ;;      spaces in the server part.
  359. ;;    - Made irc-execute-whois handle the /WHOWAS command.
  360. ;;    - Tell the clients version too, after a /VERSION.
  361. ;;    - Bugfix: rewrote irc-execute-topic to put the (interactive) "command"
  362. ;;      in "topmode".
  363. ;;    - Save username in 2.6 kind of USER-traces.
  364. ;;    - Bugfix: Don't remove bogus irc-nick from irc-nicknames on startup
  365. ;;      when setting first nick after default nick failed.
  366. ;; v4.2 Sat Dec 15 04:14:22 1990    sojge@mizar.docs.uu.se
  367. ;;    - Bugfix in irc-parse-server-msg: NOTICE's don't have a : before them
  368. ;;      (except the optional :server part).
  369. ;;    - Can't set topic of a #channel, changed irc-execute-topic.
  370. ;;    - Bugfix: irc-parse-notice now recognizes IRC OPERs as users in traces.
  371. ;;    - Made "NOTICE -- Received kill" equivalente to older
  372. ;;      "NOTICE: Received kill".
  373. ;; v4.1 Thu Dec 13 13:35:43 1990    sojge@mizar.docs.uu.se
  374. ;;    - Zapped irc-news to contain little, but current, information.
  375. ;;    - Corrected bug in alignment of output of who-replies for
  376. ;;      servers w/o end-of-who markes (hello 2.6.pre14!) in
  377. ;;      irc-parse-whoreply.
  378. ;;    - Added knowledge of some trace messages in irc-parse-notice.
  379. ;;    - Fixed bug in irc-parse-notice, so the number of invisble users
  380. ;;      will be displayed if you're an enabled irc operator.
  381. ;;      Thank's heu@byron.u.washington.edu.
  382. ;;    - Fixed irc-execute-links to only reset list of known hosts on
  383. ;;      a LINKS of all the world. (Ie don't reset on LINKS *.SE).
  384. ;;    - Spiffed up sojge-irc's grok of which privmsg go where, changed
  385. ;;      way irc-parse-priv talks to irc-parse-public.
  386. ;;    - Added /MEMBER to show which channels the user's listening and
  387. ;;      talking to.
  388. ;;    - Indicate ircII's CNTRL/B's by *'s.
  389. ;;    - Scrapped [You have joined/left]-messages, instead tell user which
  390. ;;      she's listening and writing to, if any.
  391. ;;    - Added NOTICE-pattern matching of OPER to be analogous to USER
  392. ;;      and CHANOP.
  393. ;;      Thank's kim@lut.fi.
  394. ;;    - Swapped key definitions of C-c C-q and C-c q.
  395. ;;      Thank's kim@lut.fi.
  396. ;;    - Made irc-parse-public look for single old channel in
  397. ;;      irc-subscribed-channels.
  398. ;;    - Added better support for irc-subscribed-channels.
  399. ;;    - irc-parse-RPL, 472: s/inventation/invitation/.
  400. ;;    - Made /WHOWASRPL's be written correctly.
  401. ;;    - Rewrote irc-parse-channel to be better in coping with #channels.
  402. ;;    - Added #channels to be recognized in irc-is-named-channel and in
  403. ;;      irc-is-channelname.
  404. ;;    - Fixed typo in irc-parse-notice.
  405. ;; v4.0 Fri Nov 16 07:06:02 1990    sojge@mizar.docs.uu.se
  406. ;;      Seems to work with both v2.5.1 and v2.6pre14 servers.
  407. ;;    - Made irc-execute-msg send with PRIVMSG is irc-channel is a #channel.
  408. ;;    - Added PART when on 2.6 server in irc-execute-leave.
  409. ;;    - Added JOIN when on 2.6 server in irc-execute-join.
  410. ;;    - Added 2.6 level reply message 317 in irc-parse-RPL.
  411. ;;    - Added 2.6 level commands JOIN and PART in irc-parse-server-msg and
  412. ;;      irc-parse-channel.
  413. ;;    - On nonmatcher NOTICE, just give the notice to the user with out
  414. ;;      frightening her with big WARNING signs.
  415. ;;    - Removed buggy string-match in irc-parse-notice for svarte being
  416. ;;      matched against a terminal (rt).
  417. ;;    - irc-parse-RPL: set irc-msg-cont-used when receiving message 314
  418. ;;      (RPL_WHOWASUSER).
  419. ;;    - Made confirmation when sending to several users/channels at once
  420. ;;      being written one confirmation per line.
  421. ;; v3.14 Thu Nov  1 19:47:09 1990    sojge@mizar.docs.uu.se
  422. ;;    - Made /OOPS work without an argument, if non given, ask for one.
  423. ;;    - Added possible bugfix in irc-parse-RPL for message 322.
  424. ;;    - irc-execute-command: don't put "'s around help w/ possible commands.
  425. ;;    - irc-insert-most: use right-most argument of irc-choose-break-point.
  426. ;;    - irc-insert: use right-most argument of irc-choose-break-point.
  427. ;;    - irc-choose-break-point: use parameter right-most, not (window-width).
  428. ;;    - irc-parse-notice: slightly new "no users logged in" message.
  429. ;;    - irc-parse-notice: write "serverlink", not "connection" in /TRACES.
  430. ;;    - irc-parse-wallops: set irc-msg-cont-used to max window-width / 2.
  431. ;;    - irc-parse-priv: set irc-msg-cont-used to max window-width / 2.
  432. ;;    - irc-parse-public: set irc-msg-cont-used to max window-width / 2.
  433. ;;    - irc-parse-channel: prevent negative string length in pd.
  434. ;; v3.13 Tue Oct  9 04:35:51 1990    sojge@mizar.docs.uu.se
  435. ;;    - Sigh, when do I learn not to release code when being ++tired?
  436. ;;      Fixed a newborn bug in irc-execute-msg.
  437. ;; v3.12 Tue Oct  9 03:49:14 1990    sojge@mizar.docs.uu.se
  438. ;;    - Made a quick and dirty bugfix to prevent crashing in irc-insert-more.
  439. ;;      Sort of works. Sigh.
  440. ;;    - Fixed bug in irc-parse-server-msg, do accept NOTICEs from "strange"
  441. ;;      origins...
  442. ;;    - Set global irc-msg-cont-used in irc-parse-RPL while parsing WHOIS
  443. ;;      replies.
  444. ;;    - Removed two bugs in irc-insert-more.
  445. ;;    - Made /WHOIS STRING trying to get information even if STRING isn't
  446. ;;      remembered in irc-nicknames as being present.
  447. ;;    - Made /WHO USER do a WHOIS USER, while /WHO CHANNEL does a
  448. ;;      WHO CHANNEL.
  449. ;;    - Made irc-execute-wallops confirm if irc-confirm is non-nil.
  450. ;; v3.11 Thu Aug 30 17:41:18 1990    sojge@mizar.docs.uu.se
  451. ;;    - Sigh, fixed bug in irc-execute-whowas. I'd better do a RPLACA...
  452. ;; v3.10 Thu Aug 30 15:47:36 1990    sojge@mizar.docs.uu.se
  453. ;;    - Added irc-execute-whowas (long due).
  454. ;;    - Fixed som other minor bugs. I hope.
  455. ;;    - BUGFIX in irc-remove-from-tree, do comparsion in upcase.
  456. ;;    - Made irc-execute-msg tell if receivers are users or channels.
  457. ;;    - Fixed bug in irc-is-channel. ("-77?" is NOT a channel ID).
  458. ;;    - Recognize Kanji message and replace with generic string.
  459. ;; v3.9 Wed Aug 22 08:07:21 1990    sojge@mizar.docs.uu.se
  460. ;;    - Added a rudimentary function irc-execute-kick.
  461. ;;    - Wrote predicate irc-is-channelname.
  462. ;;    - Updated predicate irc-is-nickname to better reflect reality.
  463. ;;    - Made irc-execute-msg grok channel's as receipants.
  464. ;;    - Added simplistic irc-execute-mode function.
  465. ;;    - FIXED BUG in irc-find-to by rewriting it.
  466. ;;    - Made message 421 grok 2.5 messages too.
  467. ;;    - Added function irc-parse-kick.
  468. ;;    - Added some more (let ((irc-msg-cont-used ...) around irc-insert's.
  469. ;;    - Made irc-explain-mode work.
  470. ;;    - Changed count in irc-execute-send so irc-msg-sent is right justified.
  471. ;; v3.8 Sun Aug 19 04:55:31 1990    sojge@mizar.docs.uu.se
  472. ;;    - BUGFIX: v3.6 introduced bug making it hard to join negative channels,
  473. ;;      now it's easy again.
  474. ;; v3.7 Sat Aug 18 23:48:56 1990    sojge@mizar.docs.uu.se
  475. ;;    - Set irc-msg-cont-used before calling irc-insert for some lists.
  476. ;;    - Understand ERR_NOTONCHANNEL message.
  477. ;;    - Don't explecitly request MOTD (message of the day) when connected
  478. ;;      to v2.5 servers or later. They give it anyway.
  479. ;;    - Don't show the "no topic set" messages from remote old server
  480. ;;      at topic changes.
  481. ;;    - Collect server names in irc-parse-RPL.
  482. ;;    - Added irc-split-lines to make better line splits in irc-insert.
  483. ;; v3.6 Fri Aug 17 04:41:19 1990    sojge@mizar.docs.uu.se
  484. ;;    - Changed format of how the status in a WHO listing appears.
  485. ;;    - Ignore error messages from other old server complaining MODE being
  486. ;;      an unknown command.
  487. ;;    - Understands the WHO-reply statuses "channel operator"
  488. ;;      and "channe operator and IRC operator".
  489. ;;    - Sort of understands reply message 316 .
  490. ;;    - Join channel 007, not +007 at "/join 007" (ie no prepending of + when
  491. ;;      first letter in channelname is a digit).
  492. ;;    - Understand reply message 324.
  493. ;;    - Say "using default" after a "/query *".
  494. ;; v3.5 Thu Jun 14 07:23:51 1990    sojge@emil.csd.uu.se
  495. ;;    - Teached /KILL to understand comments.
  496. ;;    - Added a simplistic header to linreply display.
  497. ;;    - Make it possible for away messages to start with :.
  498. ;;    - Save nickname in irc-parse-wallops.
  499. ;; v3.4 Mon Jun 11 03:55:08 1990    sojge@emil.csd.uu.se
  500. ;;    - Added operator level command /CONNECT.
  501. ;;    - Remapped C-C C-S to be irc-execute-squit.
  502. ;;    - Added operator level command /SQUIT.
  503. ;;    - Added operator level command /WALLOPS.
  504. ;;    - Added some support for mnemonic channel ID's, ie not only numbers
  505. ;;      but also strings can identify a channel. Probaly a bit buggy.
  506. ;;      Problem: How long can an ID be?
  507. ;;    - Made irc-channel into a string, from being a number.
  508. ;;    - Made /WHO SOJGE show a one line WHO reply (plus header) about SOJGE,
  509. ;;      ie not doing a WHOIS for SOJGE. Will probaly change.
  510. ;; v3.3 Wed Jun  6 07:26:57 1990    sojge@emil.csd.uu.se
  511. ;;    - Keep statistics on LIST replies in a new way.
  512. ;;    - Made irc-add-to-tree do it's string comparsions in upper case, this
  513. ;;      prevents the same name in two different cases to be stored.
  514. ;;    - Corrected minor bug in irc-parse-notice about reconizing USERS
  515. ;;      replies.
  516. ;;    - Changed (irc-insert "foo\nbar") into 
  517. ;;      (irc-insert "foo") (irc-insert "bar")
  518. ;;    - Made the "IRC halted" message a bit more flashy.
  519. ;; v3.2 Mon Jun  4 19:59:00 1990    sojge@emil.csd.uu.se
  520. ;;    - When on a fast terminal (see irc-terminal-is-slow), don't bother
  521. ;;      to collect various replies in temporary storage lists. Display the
  522. ;;      unsorted entrys as fast as they come in.
  523. ;;    - Improved handling of /USERS replies.
  524. ;; v3.1 Sat May 26 03:05:46 1990    sojge@emil.csd.uu.se
  525. ;;    - Corrected bug which prevented LINK to actually display any data...
  526. ;; v3.0 Sat May 26 02:21:52 1990    sojge@emil.csd.uu.se
  527. ;;    - Changed version from 1.9 to 3.0 in one step.
  528. ;;    - Set irc-nick according to incoming NOTICE messages.
  529. ;;    - Made the WHOREPLY header be displayed when the first reply comes in.
  530. ;;    - Understand message 314, RPL_WHOWASUSER.
  531. ;;    - Renamed irc-nameslist (former irc-whotree) into irc-nicknames.
  532. ;;    - Added case for "no motd at server", both for 2.4 and pre 2.4 servers.
  533. ;;    - Beautified "IRC server xx runs version yy" message.
  534. ;;    - Added irc-execute-version.
  535. ;;    - Added irc-execute-motd.
  536. ;; v1.9 Sat May 19 14:44:58 1990    sojge@emil.csd.uu.se
  537. ;;    - Wrote irc-parse-pong to collect host name from ping messages.
  538. ;;    - Made irc-extract-hosts skip parts between between nodename and "!".
  539. ;;    - Made WHO lists more mnemonic.
  540. ;;    - Made LINREPLYs be gathered in a variable before sorting and
  541. ;;      displaying it even for 2.2 type servers.
  542. ;;    - Make client ask for the message of the day (MOTD) when seeing
  543. ;;      the (final line of the) servers welcome message, not at "start up".
  544. ;;    - Look as far as 1/3 of the line from the right when choosing a
  545. ;;      break point in irc-insert. Makes a few listing look better on
  546. ;;      a 80 column screen.
  547. ;;    - Take care of "unknown connection" message in irc-parse-notice.
  548. ;; v1.8 Thu May 17 00:53:20 1990    sojge@emil.csd.uu.se
  549. ;;    - Say "use /HELP" if user seems totaly confused on channel 0.
  550. ;;    - Fixed bug in irc-parse-whoreply, don't add header to irc-whotree.
  551. ;;    - Say "no users" on a 2.4 (or later) server if user issued /who 
  552. ;;      for an empty channel.
  553. ;; v1.7 Wed May 16 23:34:01 1990    sojge@emil.csd.uu.se
  554. ;;    - Show time when being pinged, not every x minutes.
  555. ;;    - Don't crash if server closed connection, reopen it,
  556. ;;    - Skip some messages like START OF MOTD ...
  557. ;;    - Show what remote server, if any, a message came from.
  558. ;;    - Take care of a bunch of new NOTICE messages.
  559. ;;    - Understand new (server v2.4) type of welcome message.
  560. ;;    - Ignore empty lines from server.
  561. ;;    - Moved logic about format of different information keeping trees
  562. ;;      into irc-maintain-tree.
  563. ;;    - Made (most) error messages start with a % sign.
  564. ;;    - Renamed IRC-WHOTREE into IRC-NAMESTREE.
  565. ;;    - Keeps track of what version the used server is, and depending on it
  566. ;;      uses (or not) the fact that it's possible to gather WHOREPLYs and
  567. ;;      LINREPLYs before displaying it. Exploits the "end of who/links"
  568. ;;      message from the server.
  569. ;;    - Understands new MOTD notices, collects data until end-of-motd-list.
  570. ;;    - Better handling of extracting hostnames from different places.
  571. ;;      Uses irc-extract-hostname.
  572. ;;    - Made irc-maintain-tree use upcase and irc-extract-hostname on items
  573. ;;      for irc-hosttree.
  574. ;;    - Now extracts info from MOTD replies.
  575. ;; v1.6 Mon Apr  9 22:25:22 1990    sojge@emil.csd.uu.se
  576. ;;    - Improved handling of %-signs in messages (data part so to say) by
  577. ;;      doing a s/%/%%/ in functions irc-parse-public and irc-parse-privmsg.
  578. ;; v1.5 Mon Apr  9 17:32:51 1990    sojge@emil.csd.uu.se
  579. ;;    - Extract server names from KILL messages paths.
  580. ;; v1.4 Fri Apr  6 01:30:46 1990    sojge@emil.csd.uu.se
  581. ;;    - Removed s/%/%%/ from irc-parse-server-msg.
  582. ;;    - Let function irc check that the *IRC* buffer has an open stream
  583. ;;      "process" associated with it before trying to switch to the buffer.
  584. ;;      This is handy when the stream has been closed.
  585. ;; v1.3 Tue Apr  3 23:51:38 1990    sojge@emil.csd.uu.se
  586. ;;    - Made irc.el cope with new format on some NOTICE messages.
  587. ;;      (:server NOTICE ...)
  588. ;; v1.2 Fri Mar 30 03:42:31 1990    sojge@emil.csd.uu.se
  589. ;;    - Changed protocol, initiate with USER <username> * * <realname> now.
  590. ;;    - Changed misc. error messages to start with %.
  591. ;;    - Made a few "server message unkown" messages tell where they are
  592. ;;      in the code.
  593. ;;    - Added code to make WHOIS * invokde WHOIS for all users.
  594. ;;    - Made irc-parse-channel set irc-msg-cont-used.
  595. ;;    - Added and removed code for automatic greeting of new joiners to
  596. ;;      channels, in irc-parse-channel. But this doesn't seem to be enough.
  597. ;;      More debugging needed ...
  598. ;;    - Made irc.el understand MOTD messages from server, not reliying on
  599. ;;      all lines in MOTD file starting with a blank.
  600. ;; v1.1 Mon Mar 26 03:37:03 1990    sojge@emil.csd.uu.se
  601. ;;    - Cleaned up some more, in how things are displayed. Servers
  602. ;;      domain names are displayed in upper case, in
  603. ;;      irc-parse-linrpl and their information text "as is". Some
  604. ;;      headers  are underlined.
  605. ;;    - Corrected (?) bug in irc-parse-RPL which handled RPL_MOTD
  606. ;;      messages incorrectly.
  607. ;; v1.0 Wed Feb 28 21:53:49 1990    sojge@emil.csd.uu.se
  608. ;;    - Changed look and feel by introducing a couple of variables
  609. ;;      and removing the conserve-space kludge. Apperence is now user
  610. ;;      settable.
  611. ;;    - Rewritten buggy irc-insert so it works. No more infinite looping.
  612. ;;    - Added a few key bindings.
  613. ;;    - Made irc-parse-RPL (at RPL_WHOISSERVER) and irc-parse-notice add
  614. ;;      information to the irc-hostlist, just like irc-parse-linreply does.
  615. ;; v0.9 Sometime 1989    flax@mizar.docs.uu.se
  616. ;;    - Made irc-linreply add to a list of known hosts so completion of
  617. ;;      host names in irc-execute-admin and others will work. Neat.
  618. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  619. ;; Author          : David C Lawrence           <tale@pawl.rpi.edu>
  620. ;; Created On      : Wed Jun 14 22:22:57 1989
  621. ;; Last major modification: Jonas Flygare
  622. ;; Last minor modification: Klaus Zeuge
  623. ;; Last Modified On: Wed Jan 24 00:54:29 1990
  624. ;; Update Count    : 100
  625. ;; Status          : Stable
  626. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  627. ;;  Copyright (C) 1989  David C Lawrence
  628.  
  629. ;;  This program is free software; you can redistribute it and/or modify
  630. ;;  it under the terms of the GNU General Public License as published by
  631. ;;  the Free Software Foundation; either version 1, or (at your option)
  632. ;;  any later version.
  633.  
  634. ;;  This program is distributed in the hope that it will be useful,
  635. ;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
  636. ;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  637. ;;  GNU General Public License for more details.
  638.  
  639. ;;  You should have received a copy of the GNU General Public License
  640. ;;  along with this program; if not, write to the Free Software
  641. ;;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  642.  
  643. ;; Comments and/or bug reports about this interface should be directed to:
  644. ;;     Dave Lawrence          <tale@{pawl,itsgw}.rpi.edu>
  645. ;;     76 1/2 13th Street     +1 518 273 5385
  646. ;;     Troy NY 12180          Generally available on IRC as "tale"
  647.  
  648. ;; History         
  649. ;; 27-Sep-1989        Gnu Maint Acct    (gnu at life.pawl.rpi.edu)
  650. ;;    Last Modified: Wed Sep 27 18:56:19 1989 #6
  651. ;;    * Fixed a misrefenced variable in irc-parse-server-msg so that lines
  652. ;;      which can't be parsed insert only that unparsable line.
  653. ;;    * Added irc-parse-topic and changed irc-signals and irc-notifies
  654. ;;      appropriately.
  655. ;;    * Moved setting of irc-channel to irc-parse-channel from irc-execute-join
  656. ;;      because a channel change isn't guaranteed (ie, trying to change to
  657. ;;      a channel not in 0-10 which has ten users on it).
  658. ;;    * Made irc-message-stamp 'private by default. (Geoff)
  659. ;;    * Made irc-time-stamp 0 by default.      (Also Geoff)
  660. ;;      This tickled an unseen bug in the start-up function which incremented
  661. ;;      irc-last-stamp.  It's fixed now.
  662. ;;    * Fixed a bug with interactive irc-execute-names -- prefix arg was being
  663. ;;      (list ...)ed.
  664. ;;    * Fixed a bug in irc-parse-namreply that dropped a name in the output
  665. ;;      when a line got wrapped.
  666. ;;    * Added /lusers.  I really dislike the name.
  667. ;;    * Added irc-parse-kill.
  668. ;;    * Made irc-execute-msg strip one space after the colon in messages;
  669. ;;      ie, "tale: hi" will send "hi" as a message not " hi".
  670. ;;    * Took out hardcoded width numbers for word-wrapping.  Uses
  671. ;;      (window-width) instead.
  672. ;;    * Added to the regexp for failed nickname changes in irc-parse-error;
  673. ;;      the sentences got changed in the newer servers.
  674. ;;    * Wrapped irc-check-time around display-time-filter for better accuracy
  675. ;;      if a display-time process is running.
  676. ;;    * Made the "IRC Session finished" message include the time.
  677. ;;    * Added irc-conserve-space to imitate the C client message style.  I
  678. ;;      really dislike it aesthetically, but it is handy for people running
  679. ;;      on 24 line screens and at slow baud rates. (Kimmel & others)
  680. ;;    * Support IRCNICK and IRCSERVER environment variables at load time. (Kim)
  681. ;;    * Made /WHO call /WHOIS if given a non-numeric argument.  (Nate)
  682. ;;    * Fixed a bug where an alias would be executed before an exactly matching
  683. ;;      command; ie, alias /WHOALIAS whould execute when /WHO was entered.
  684. ;;    * Runs things in auto-fill-mode with a fill-column of 75 by default.
  685. ;;    * Processes the whole input region as one line instead of line-at-a-time.
  686. ;;    * Made irc-change-alias for non-interactive setting/removing of aliases;
  687. ;;      ie, via irc-mode-hook.  No frills.  (Chris & Nate)
  688. ;;    * _Finally_ got around to adding parsing of numeric notices for new
  689. ;;      servers.
  690.  
  691. ;; Need backquote.el for our macros.
  692. (require 'backquote)
  693.  
  694.  
  695. ;; Defined variables
  696.  
  697. (defvar irc-abusive-ignore nil
  698.   "If non nil, send back a message to persons being ignored, instead of
  699. being silent, while throwing away messages from them.")
  700.  
  701.  
  702. (defvar irc-alias-alist
  703.   '(
  704.     ("?" . "help")            ; Abbrevation
  705.     ("BYE" . "quit")
  706.     ("CHANNEL" . "join")
  707.     ("END" . "quit")            ; Plenty of ways out
  708.     ("EXIT" . "quit")
  709.     ("IDLE" . "who")            ; for people too used to Connect
  710.     ("L" . "list")            ; Abbrevation
  711.     ("M" . "msg")            ; Abbrevation
  712.     ("MS" . "msg")            ; Abbrevation
  713.     ("N" . "names")            ; Abbrevation
  714.     ("QUERY" . "send")            ; For people used to the C client
  715.     ("STOP" . "quit")            ; Plenty of ways out
  716.     ("U". "users")            ; Abbrevation
  717.     ("US". "users")            ; Abbrevation
  718.     ("USE". "users")            ; Abbrevation
  719.     ("USER". "users")            ; Abbrevation
  720.     ("W" . "who")            ; Abbrevation
  721.     ("WHAT" . "list")            ; /WHAT from Connect
  722.     )
  723.   "An association list of command aliases used in irc-mode.
  724. This is the first list checked when irc-mode is looking for a command and it
  725. is maintained with the /ALIAS and /UNALIAS commands.")
  726.  
  727.  
  728. (make-variable-buffer-local
  729.  (defvar irc-cache-n+s nil
  730.    "Cache of known nicks and servers"))
  731.  
  732.  
  733. (make-variable-buffer-local
  734.  (defvar irc-cache-c+n+s nil
  735.    "Cache of known channels, nicks and servers"))
  736.  
  737.  
  738. (make-variable-buffer-local
  739.  (defvar irc-called-from-buffer nil
  740.    "Flag saying whether a command is called from the irc buffer with /names
  741. or invoked through pressing a key like C-c C-c."))
  742.  
  743.  
  744. (make-variable-buffer-local
  745.  (defvar irc-called-from-buffer nil
  746.    "Flag saying whether a command is called from the irc buffer with /names
  747. or invoked through pressing a key like C-c C-c."))
  748.  
  749.  
  750. (defconst irc-command-alist
  751.     '(("ADMIN" . "admin")        ; Get information about IRC admins
  752.       ("ALIAS" . "alias")        ; Add command aliases
  753.       ("AWAY" . "away")            ; Give som indication of your presenc
  754.       ("CONFIRM" . "confirm")        ; Set message confirmation on or off
  755.       ("DESCRIBE" . "describe")        ; CTCP action.
  756.       ("DIE" . "die")            ; Tell server to die.
  757.       ("EVENT" . "event")        ; Change which events give notification
  758.       ("FINGER" . "finger")        ; CTCP finger.
  759.       ("HELP" . "help")            ; Get help on the /COMMANDs
  760.       ("HERE" . "here")            ; Remove the away mark
  761.       ("IGNORE" . "ignore")        ; Ignore messages from a specified user
  762.       ("INFO" . "info")            ; Information about users and authors
  763.       ("INVITE" . "invite")        ; Ask another user to join your channel
  764.       ("JOIN" . "join")            ; Join a channel
  765.       ("KICK" . "kick")            ; Boot a user from a channel
  766.       ("LEAVE" . "leave")        ; Leave a channel
  767.       ("LINKS" . "links")        ; Show which servers are in the IRC-net
  768.       ("LIST" . "list")            ; Show a list of channels and topics
  769.       ("LUSERS" . "lusers")        ; Get the number of users and servers
  770.       ("MAIL" . "mail")            ; Give commands to the mail subsystem.
  771.       ("ME" . "me")            ; Send a CTCP ACTION message to channel
  772.       ("MEMBERSHIPS" . "memberships")    ; Show subscribed channels.
  773.       ("MODE" . "mode")            ; Change or inspect the mode of a chan
  774.       ("MOTD" . "motd")            ; Message of the day
  775.       ("MSG" . "privmsg")        ; Send a private message to someone
  776.       ("NAMES" . "names")        ; Display nick names on each channel
  777.       ("NEWS" . "news")            ; Show news about client.
  778.       ("NICKNAME" . "nick")        ; Change your IRC nickname
  779.       ("NOTIFY" . "notify")        ; Notify when selected nicks are seen
  780.       ("OOPS" . "oops")            ; Resend a misdirected message
  781.       ("OPER" . "oper")            ; Login as an IRC operator
  782.       ("QUIT" . "quit")            ; Exit IRC
  783.       ("QUOTE" . "quote")        ; Send raw text to the server
  784.       ("PING" . "ping")            ; Send CTCP PING to another user
  785.       ("REDIRECT" . "redirect")        ; Send the last message to someone else
  786.       ("SEND" . "send")            ; Set the implicit send list for msgs's
  787.       ("SERVICE" . "service")        ; Add and subtract to list of automates
  788.       ("SIGNAL" . "signal")        ; Change which events give a signal
  789.       ("STAMP" . "stamp")        ; Set time notification interval
  790.       ("STATS" . "stats")        ; Get statistics from server.
  791.       ("SUMMON" . "summon")        ; Ask a user not on IRC to join it
  792.       ("TIME" . "time")            ; Get the current time from a server
  793.       ("TOPIC" . "topic")        ; Change the topic of the channel
  794.       ("TRACE" . "trace")        ; Show the links between servers
  795.       ("UNALIAS" . "unalias")        ; Remove command aliases
  796.       ("UNIGNORE" . "unignore")        ; Stop ignoring user
  797.       ("USERINFO" . "userinfo")        ; Set information about oneself
  798.       ("USERS" . "users")        ; Show users logged in at a server
  799.       ("VERSION" . "version")        ; Version of a server or a users client
  800.       ("WALLOPS" . "wallops")        ; Send a message to all operators
  801.       ("WHO" . "who")            ; Get list of users and their channels
  802.       ("WHOIS" . "whois")        ; Get longer information about a user
  803.       ("WHOWAS" . "whois"))        ; Check who user who has left IRC was.
  804.   "An association list of the regular commands to which all users have access.
  805. Form is (\"COMMAND\" . \"function\") where \"function\" is that last element in
  806. an irc-execute-* symbol.  See also irc-alias-alist and irc-operator-alist.")
  807.  
  808.  
  809. (defvar irc-confirm t
  810.   "*If non-nil, provide confirmation for messages sent on IRC.
  811. It should be noted that confirmation only indicates where irc-mode
  812. tried to send the message, not whether it was actually received.
  813. Use the /CONFIRM command to change.")
  814.  
  815.  
  816. (make-variable-buffer-local
  817.  (defvar irc-default-to "*;"
  818.    "The default recipient of a message if no : or ; is provided.
  819. \"*\" means the current channel, no matter what it is."))
  820.  
  821.  
  822. (make-variable-buffer-local
  823.  (defvar irc-drop-ircII-text-kludge-control-characters t
  824.    "*If nil, show CNTRL/B, CNTRL/V and CNTRL/_ as ^B. ^V and ^_ in text. These
  825. characters are used as a kludge by the client ircII to toggle the attributes
  826. reverse, underline and bold respectivly in text. If non-nil, drop those three
  827. characters."))
  828.  
  829.  
  830. (defvar irc-emacs-knows-ISO8859-1 (>= (string-to-int emacs-version) 19)
  831.   "*Non-nil if Kiwi shouldn't translate octets in incoming messages with
  832. the high bit set to \xyz strings; nil if translation for such characters
  833. (0240 - 0377) should occur.")
  834.  
  835.  
  836. (make-variable-buffer-local
  837.  (defvar irc-events '(ctcp join nick quit topic)
  838.    "Events in IRC that should get notification messages.
  839. A notification message is just one line to indicate that the event has
  840. occurred.  The \"ctcp\", \"join\", \"nick\", \"quit\" and \"topic\"
  841. events are currently supported by the /EVENT command."))
  842.  
  843.  
  844. (defconst irc-help-topic-alist
  845.     '((";" . "Usage: RECEIVER[,RECEIVER]...; MESSAGE
  846.  
  847. Send a message to one or several receivers.
  848. About the same as /MSG and :, see /HELP : and /HELP MSG.
  849.  
  850. When no receiver is given yet, on a line, and you press ; first on that line,
  851. the last receiver is inserted (this may be a users nickname, a channelname,
  852. a list of receivers, etc)
  853.  
  854. Don't use any spaces left of the ;.")
  855.       (":" . "Usage: RECEIVER [, RECEIVER] ... ; MESSAGE
  856.  
  857. Send a message to one or several receivers.
  858. About the same as /MSG and ;, see /HELP ; and /HELP MSG
  859.  
  860. When no receiver was given yet, and : is inserted first on the line, the
  861. last person you sent to will be the default receiver.
  862.  
  863. Don't use any spaces left of the :.")
  864.       ("STARTUP" . "Initiation and startup
  865.  
  866. To make your GNU Emacs know of this IRC user interface, you can add
  867. the following command to your GNU Emacs initialisation file (normaly
  868. .emacs) in your home directory:
  869.         (autoload 'irc \"Kiwi\"
  870.             \"Internet Relay Chat user interface.\" t nil)
  871.  
  872. This will make your Emacs to load the library file Kiwi.elc or Kiwi.el
  873. when you typing M-x irc RET. The file must be in one of the
  874. directories mentioned in the variable load-path. (You can check this
  875. variables value by typing C-h v load-path RET). You can compile the
  876. file Kiwi.el by typing M-x byte-compile-file RET Kiwi.el RET to get
  877. Kiwi.elc.
  878.  
  879. At startup time of IRC, you may want to initiate some settings and
  880. give some commands. This can be done by setting some variables in your
  881. GNU Emacs initialisation file (normaly called .emacs). Some typical
  882. initialisations may be
  883.  
  884.        (setq irc-server \"minsk.docs.uu.se\"      ;Which server to use.
  885.              irc-msg-public \"%s%9s/%s:  \"       ;How to display public msgs
  886.              irc-pop-on-signal 3                ;Use about 1/3 of screen when
  887.                                                 ; popping up a Kiwi buffer.
  888.              ;; Give some information about yourself, whatever you want.
  889.              irc-userinfo (concat
  890.                            \"Studying computer science at the university of\"
  891.                            \" Uppsala. Call me on +46 18 463253.\")
  892.              ;; Commands to be executed when seeing the Welcome message
  893.              ;; from a server we just connected to.
  894.              irc-startup-hook '(lambda ()
  895.                                 (irc-execute-command \"links *.se\")
  896.                                 (irc-execute-command \"who *.se\")))
  897.  
  898. This will make IRC use about 1/3 of the screen when popping up a
  899. window (this happens for instance when you have deselcted all IRC
  900. windows and someone sends you a message). Also, the information string
  901. for you (which can contain any information you choose) is initiated.
  902. When a server says \"welcome\", you will be shown all active servers
  903. in Sweden (SE) and all active users using IRC in Sweden.
  904.  
  905. Don't give the leading / in the arguments to irc-execute-command.
  906.  
  907. If you want more control over how to display public and/or private messages
  908. (at the time exluding WALLs and WALLOPSs) you can use this clumsy way (be
  909. patient, a more user friendly method is on it's way) of setting the variables
  910. irc-public-insert and irc-private-insert to functions taking 3 strings as
  911. arguments, namely the name of the sender, name of the receiver (user or channel
  912. name normaly) and the message itself (in raw format, after extracting the
  913. client-to-client protocol stuff). All this sums up to, that if you don't know
  914. elisp, you probaly don't want to use this method, or else just change the
  915. control string constants in the examples below.
  916. Examples:
  917.   (setq
  918.    irc-public-insert '(lambda (from to msg)
  919.                (let* ((same-chan (string= (upcase irc-channel)
  920.                           (upcase to)))
  921.                   (hdr
  922.                    (format (if same-chan
  923.                        \"%s %9s:  \"
  924.                        \"%s %9s/%s:  \")
  925.                        (if (and irc-message-stamp
  926.                         (not (eq irc-message-stamp
  927.                              'private)))
  928.                        (irc-get-time)
  929.                        \"\")
  930.                        from
  931.                        to))
  932.                   (irc-msg-cont-used
  933.                    (make-string 
  934.                 (min (length hdr)
  935.                      (/ (window-width (get-buffer-window
  936.                                (current-buffer)))
  937.                     2))
  938.                 ? )))
  939.              (irc-insert
  940.               (concat hdr (irc-clean-up-message msg)))))
  941.    irc-private-insert '(lambda (from to msg)
  942.             (let* ((to-whom
  943.                 (cond ((string= (upcase irc-nick-used)
  944.                         (upcase to))
  945.                        \"*%s %s*  \")
  946.                       ((irc-is-broadcastname to)
  947.                        (concat \"=%s %s BROADCAST to all\"
  948.                            \"users on IRC server(s)\"
  949.                            \" \\\"%s\\\"=  \"))
  950.                       (t \"*%s %s/%s*  \")))
  951.                    (hdr
  952.                 (format to-whom
  953.                     (if (and
  954.                          irc-message-stamp
  955.                          (eq irc-message-stamp
  956.                          'private))
  957.                         (irc-get-time)
  958.                         \"\")
  959.                     from
  960.                     to))
  961.                    (irc-msg-cont-used (make-string 
  962.                            (min (length hdr)
  963.                             (/ (window-width (get-buffer-window (current-buffer)))
  964.                                2))
  965.                            ? )))
  966.               (irc-insert
  967.                (concat hdr (irc-clean-up-message msg))))))
  968.  
  969. Hint: the internal control strings uses 2 or 3 of the %s to write the time,
  970. the senders name and the receivers name. If only 2 %s are given, the receivers
  971. name won't be written.
  972.  
  973. [Note: this is a preliminary version of the help text, please send mail
  974. to Klaus.Zeuge@Student.DoCS.UU.SE if you think it needs to be changed.]"))
  975.   "A-list with car = keyword-string for a topic and cdr = descriptions string
  976. of the keyword.")
  977.  
  978.  
  979. (make-variable-buffer-local
  980.  (defvar irc-history nil
  981.    "A list of messages which irc-mode has processed.
  982. This includes both successfully and unsuccessfully sent messages, starting
  983. with the most recent first.  irc-max-history limits the number of items
  984. that can appear in the list when using irc-add-to-history."))
  985.  
  986.  
  987. (make-variable-buffer-local
  988.  (defvar irc-ignore-automatic-warnings nil
  989.    "*Variable to say whether to to display or not display automatic warnings
  990. from users. Such warnings start with the marker \"<Automatic warning> \" in
  991. a message either directly to to, or on a channel. The default and RECOMMENDED
  992. value is nil, ie to display. Set to non-nil to supress such messages."))
  993.  
  994.  
  995. (make-variable-buffer-local
  996.  (defvar irc-ignores nil
  997.    "A list of NICKNAMES whose events will be ignored.
  998. Messages or other actions (like joining a channel) generated by anyone in
  999. the list will not be displayed or signalled.  This list is maintained with
  1000. the /IGNORE and /UNIGNORE commands."))
  1001.  
  1002.  
  1003. (make-variable-buffer-local
  1004.  (defvar irc-ignore-trunk nil
  1005.    "A trunk (for now an array of hash tables) of events and nicks to ignore."))
  1006.  
  1007.  
  1008. (defvar irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1 nil
  1009.   "*Set to true if you want the sevenbit ISO 646-SE2 characters @[\]^`{|}~ to
  1010. be mapped into the corrosponding eightbith ISO 8859-1 characters when
  1011. being typed.
  1012.  
  1013. Set to nil to get no such mapping.
  1014.  
  1015. Set to neither t or nil if you want to get the mapping with the case
  1016. for ], [, \\ reversed, i.e. want to have the [ key treated as \344 and
  1017. the { key treated as \304.")
  1018.  
  1019.  
  1020. (defvar irc-max-history 40
  1021.   "*The maximum number of messages retained by irc-mode.
  1022. This limits messages sent, not messages received.  They are stored to be
  1023. easily recalled by irc-history-prev and irc-history-next (C-c C-p and C-c C-n
  1024. by default).")
  1025.  
  1026.  
  1027. (defvar irc-max-server-message-length 512
  1028.   "The maximum length of a message one can send to a server. This include the
  1029. trailing CRLF, so the \"real\" message length is 2 less.")
  1030.  
  1031.  
  1032. (defvar irc-maximum-size (* 64 1024)
  1033.   "*Maximum size that the *Kiwi-server* buffer can attain, in bytes.
  1034. The default value of 64KB represents an average of about 1500 lines, or roughly
  1035. 65 screens on a standard 24 line monitor. See also irc-minimum-size.")
  1036.  
  1037.  
  1038. (defvar irc-message-stamp 'private
  1039.   "*Mark messages received in IRC with the time of their arrival if non-nil.
  1040. If this is the symbol \"private\" or \"public\" then only messages of the
  1041. specified type are marked with the time.  WALL messages are always
  1042. time-stamped.")
  1043.  
  1044.  
  1045. (defvar irc-minimum-size (* 32 1024)
  1046.   "*Minimum size that the *Kiwi-server* buffer will get truncated to after
  1047. hitting the size in irc-maximum-size.")
  1048.  
  1049. (defvar irc-mode-hook nil
  1050.   "*Hook to run after starting irc-mode but before connecting to the server.")
  1051.  
  1052.  
  1053. (defvar irc-mode-map nil
  1054.   "The keymap which irc-mode uses.
  1055.  
  1056. Currently set to: \\{irc-mode-map}")
  1057.  
  1058.  
  1059. (make-variable-buffer-local
  1060.  (defvar irc-msg-info-post (if (boundp 'irc-msg-info-post)
  1061.                    irc-msg-info-post
  1062.                  "]")
  1063.    "*String to end an information message with."))
  1064.  
  1065.  
  1066. (make-variable-buffer-local
  1067.  (defvar irc-msg-info-pre (if (boundp 'irc-msg-info-pre)
  1068.                   irc-msg-info-pre
  1069.                 "[")
  1070.    "*String to start an information message with."))
  1071.  
  1072.  
  1073. (make-variable-buffer-local
  1074.  (defvar irc-msg-cont (if (boundp 'irc-msg-cont)
  1075.               irc-msg-cont
  1076.             (make-string 23 (string-to-char " ")))
  1077.    "*The string put first on a continued line."))
  1078.  
  1079.  
  1080. (make-variable-buffer-local
  1081.  (defvar irc-msg-priv (if (boundp 'irc-msg-priv)
  1082.               irc-msg-priv
  1083.             "==%%s%%%ds == ")
  1084.    "*The string put first on a line where a private message begins,
  1085. using TIME and SENDER strings, and EXTRA string."))
  1086.  
  1087.  
  1088. (make-variable-buffer-local
  1089.  (defvar irc-msg-public (if (boundp 'irc-msg-public)
  1090.                 irc-msg-public
  1091.               "-- %s%9s (on %s) -- ")
  1092.    "*The string put first on a line where a public message begins,
  1093. using TIME string, SENDER string and CHANNEL number"))
  1094.  
  1095.  
  1096. (make-variable-buffer-local
  1097.  (defvar irc-msg-sent (if (boundp 'irc-msg-sent)
  1098.               irc-msg-sent
  1099.             "(Message sent to %s)")
  1100.    "*Message displayed after sending a string to the server.
  1101. Contains TYPE (ie \"channel\" or \"person\") and RECEIVER (ie channel name or
  1102. users nick)."))
  1103.  
  1104.  
  1105. (make-variable-buffer-local
  1106.  (defvar irc-msg-wall (if (boundp 'irc-msg-wall)
  1107.               irc-msg-wall
  1108.             "##%s%s ## ")
  1109.    "*The string put first on a line where awrite all (wall) message begins,
  1110. using TIME and SENDER strings."))
  1111.  
  1112.  
  1113. (make-variable-buffer-local
  1114.  (defvar irc-multiple-leave-in-progress nil
  1115.    "Flag saying whether a multiple /LEAVE command is in progress, so that
  1116. irc-parse-channel shouldn't call irc-show-subscribed-channels."))
  1117.  
  1118.  
  1119. (make-variable-buffer-local
  1120.  (defvar irc-nick (or (getenv "IRCNICK") (user-login-name))
  1121.    "*The nickname with which to enter IRC.
  1122. The default value is set from your login name.  Using /NICKNAME changes it."))
  1123.  
  1124.  
  1125. (defconst irc-legal-session-name "^\\*Kiwi-\\([^/]+\\)/\\([0-9]+\\)\\*$"
  1126.   "A regexp describing a legal session-name. (See irc-get-*-from-session-name).
  1127. Two fields are extracted, the first being a host name, and the second a
  1128. TCP port number.")
  1129.  
  1130.  
  1131. (defvar irc-notify-interval 2
  1132.   "*How often to check for people. The time is in minutes.")
  1133.  
  1134.  
  1135. (defvar irc-oops "Oops ... please ignore that."
  1136.   "*The text to send to the original IRC message recipient when using /OOPS.")
  1137.  
  1138.  
  1139. (defconst irc-operator-alist
  1140.   '(("CONNECT" . "connect")        ; Establish links between servers
  1141.     ("KILL" . "kill")            ; Forcibly remove a user
  1142.     ("REHASH" . "rehash")        ; Reread irc.conf
  1143.     ("SQUIT" . "squit")        ; Quit links between servers
  1144.     ("WALL" . "wall"))        ; Send a message to everyone on IRC
  1145.   "As association list of commands which only an IRC Operator can use.
  1146. It is kept as a separate list so that regular users won't wonder how
  1147. come the commands don't work for them.")
  1148.  
  1149.  
  1150. (make-variable-buffer-local
  1151.  (defvar irc-output-character-set (if (boundp 'irc-output-character-set)
  1152.                       irc-output-character-set
  1153.                     (if irc-emacs-knows-ISO8859-1
  1154.                     'ISO-8859-1
  1155.                       'ASCII))
  1156.    "*Specifies whether the Emacs understands just ASCII (seven bit characters),
  1157. ISO-8859/1 (8 bits) or Kanjii (16 bits). The value is one of the following
  1158. atoms: ASCII ISO-8859-1 KANJII"))
  1159.  
  1160.  
  1161. (defvar irc-pop-on-signal 4
  1162.   "*An integer value means to display the *IRC* buffer when a signal is issued.
  1163. The number represents roughly how much of the Emacs screen to use when
  1164. popping up the IRC window if only one window is visible.  The reciprocal
  1165. is used, so a value of 1 causes the window to appear full-screen, 2 makes
  1166. the window half of the screen, 3 makes it one third, et cetera.  If the value
  1167. is not an integer then no attempt is made to show the *IRC* buffer if it
  1168. is not already visible.")
  1169.  
  1170.  
  1171. (make-variable-buffer-local
  1172.  (defvar irc-port (if (boundp 'irc-port)
  1173.               irc-port
  1174.             (let* ((p (getenv "IRCPORT"))
  1175.                (np (and p (string-to-int p))))
  1176.               (if (and (numberp np) (> np 0) (< np 16384)) np 6667)))
  1177.    "*The port on which the IRC server responds.
  1178. Many sites don't have irc as a named service (ie, it has no entry in
  1179. /etc/inetd.conf) so you might have to set this to a number; the most
  1180. common configuration is to have IRC respond on port 6667. If there is
  1181. an enviroment variable called IRCPORT and it's value is nummeric
  1182. between 1 and 16387, that value is used instead."))
  1183.  
  1184.  
  1185. (defvar irc-private-insert nil
  1186.   "*Hook to be used to insert private messages (PRIVMSG) sent to you.")
  1187.  
  1188.  
  1189. (defvar irc-processes nil
  1190.   "All currently open streams to irc-servers are kept in this list.
  1191. It is used so that the \"irc\" function knows whether to start a new process
  1192. by default.")
  1193.  
  1194.  
  1195. (defvar irc-public-insert nil
  1196.   "*Hook to be used to insert public messages (MSG) sent to channel.")
  1197.  
  1198.  
  1199. (make-variable-buffer-local
  1200.  (defvar irc-reply-count 0
  1201.    "Internal Kiwi variable to keep track of number of replies to /LINKS,
  1202. /NAMES, or /WHO."))
  1203.  
  1204.  
  1205. (make-variable-buffer-local
  1206.  (defvar irc-reply-count-interval 1
  1207.    "Internal Kiwi variable to keep track of how many seconds should
  1208. pass at least between each display of irc-reply-count when waiting
  1209. for the reply of a /LINKS, /NAMES, or /WHO to finnish."))
  1210.  
  1211.  
  1212. (make-variable-buffer-local
  1213.  (defvar irc-reply-count-time '(0 0)
  1214.    "Internal Kiwi variable to keep track of en irc-reply-count was displayed
  1215. last."))
  1216.  
  1217.  
  1218. (make-variable-buffer-local
  1219.  (defvar irc-scroll-step (if (boundp 'irc-scroll-step)
  1220.                  irc-scroll-step
  1221.                  nil)
  1222.    "*The scroll step used by irc-insert. Set to non-number to get
  1223. the nice automatic behaivour you get by default."))
  1224.  
  1225.  
  1226. (make-variable-buffer-local
  1227.  (defvar irc-server (if (boundp 'irc-server)
  1228.             irc-server
  1229.               (or (getenv "IRCSERVER") "irc.ludd.luth.se"))
  1230.    "*The name of the internet host running the IRC daemon.
  1231. IRC servers generally restrict which machines can maintain connetions with
  1232. them, so you'll probably have to find a server in your local domain.
  1233. Initiated from enviroment variable IRCSERVER."))
  1234.  
  1235.  
  1236. (make-variable-buffer-local
  1237.  (defvar irc-show-japanese-characters nil
  1238.    "*If nil, replace Kanjii characters in text by a marker like \"Old Kanjii\"
  1239. followed by a list of integers denoting the 16 bit values of the characters.
  1240. If t, enter the text \"as is\" e.i., keep even the ESCape characters.
  1241. If neither nil nor t, enter the text in \"raw\" mode e.i., replace the ESCapes
  1242. by ^[ and insert the resulting text in the buffer.
  1243. The default is nil."))
  1244.  
  1245.  
  1246. (make-variable-buffer-local
  1247.  (defvar irc-signals '((backtalk t)
  1248.                (detect nil)
  1249.                (invite t)
  1250.                (join nil)
  1251.                (nick nil)
  1252.                (private t)
  1253.                (topic nil)
  1254.                (wall t)
  1255.                        (public nil)
  1256.                (user nil))
  1257.    "Events in IRC that should get signalled when they occur.
  1258. Generally the signal is an audible beep.  The value of irc-signals is an
  1259. association list of events recognized by irc-mode and is maintained with
  1260. the /SIGNAL command."))
  1261.  
  1262.  
  1263. (defvar irc-spacebar-pages t
  1264.   "*When this variable is non-nil, the following keys are in effect when
  1265. point is in the output region.
  1266.  
  1267. SPC      scroll-forward    DEL           scroll-backward
  1268. TAB      previous-line     LFD or RET    next-line")
  1269.  
  1270.  
  1271. (defvar irc-time-stamp 5
  1272.   "*How often to insert a time-stamp into *IRC* buffers.
  1273. The first time one is based from the hour the IRC process was started so that
  1274. values which divide evenly into 60 minutes (like the default of 10) will split
  1275. the hour evenly (as in 13:10, 13:20, 13:30, et cetera).  To disable the
  1276. time-stamping set this variable to 0.  This can be set with the /STAMP command.
  1277.  
  1278. The accuracy of the time-stamping can be improved greatly by running
  1279. M-x display-time; with default settings this guarantees that Emacs will have
  1280. some sort of predictable activity every minute.  If display-time is not running
  1281. and the IRC session is idle, the time-stamp can be up to two minutes late.")
  1282.  
  1283. (defvar irc-translation-table-incoming
  1284.   (cond
  1285.    ((and (boundp 'irc-translation-table-incoming)
  1286.      (arrayp irc-translation-table-incoming)
  1287.      (= 256 (length irc-translation-table-incoming)))
  1288.     irc-translation-table-incoming)
  1289.    ((and (boundp 'irc-translation-table-incoming)
  1290.      (symbolp irc-translation-table-incoming)
  1291.      (eq 'scandinavian irc-translation-table-incoming))
  1292.     irc-translation-table-incoming-scandinavian7)
  1293.    (t nil)
  1294.    (t 'scandinavian7))            ;Obsolete default
  1295.   "*Translation table for incoming characters.
  1296. If non-nil, single characters are translated one by one according to
  1297. this table. The table consists of a 256 elements long array, where each
  1298. element is either a string or nil. If the element is nil, the character
  1299. with the corresponding code is dropped, if the element is a string, the
  1300. string is inserted instead of the character.")
  1301.  
  1302. (defvar irc-translation-table-incoming-scandinavian7
  1303.   '["^@"                ;000
  1304.     "^A"                ;001
  1305.     ""                    ;002    ircII kludge
  1306.     "^C"                ;003
  1307.     "^D"                ;004
  1308.     "^E"                ;005
  1309.     "^F"                ;006
  1310.     "^G"                ;007
  1311.     "^H"                ;010
  1312.     "^I"                ;011
  1313.     "^J\n"                ;012
  1314.     "^K"                ;013
  1315.     "^L"                ;014
  1316.     "^M"                ;015
  1317.     "^N"                ;016
  1318.     ""                    ;017    ircII kludge
  1319.     "^P"                ;020
  1320.     "^Q"                ;021
  1321.     "^R"                ;022
  1322.     "^S"                ;023
  1323.     "^T"                ;024
  1324.     "^U"                ;025
  1325.     ""                    ;026    ircII kludge
  1326.     "^W"                ;027
  1327.     "^X"                ;030
  1328.     "^Y"                ;031
  1329.     "^Z"                ;032
  1330.     "^["                ;033
  1331.     "^\\"                ;034
  1332.     "^]"                ;035
  1333.     "^^"                ;036
  1334.     ""                    ;037    ircII kludge
  1335.     " "                    ;040
  1336.     "!"                    ;041
  1337.     "\""                ;042
  1338.     "#"                    ;043
  1339.     "$"                    ;044
  1340.     "%%"                ;045    Need %% to not disturb format.
  1341.     "&"                    ;046
  1342.     "'"                    ;047
  1343.     "("                    ;050
  1344.     ")"                    ;051
  1345.     "*"                    ;052
  1346.     "+"                    ;053
  1347.     ","                    ;054
  1348.     "-"                    ;055
  1349.     "."                    ;056
  1350.     "/"                    ;057
  1351.     "0"                    ;060
  1352.     "1"                    ;061
  1353.     "2"                    ;062
  1354.     "3"                    ;063
  1355.     "4"                    ;064
  1356.     "5"                    ;065
  1357.     "6"                    ;066
  1358.     "7"                    ;067
  1359.     "8"                    ;070
  1360.     "9"                    ;071
  1361.     ":"                    ;072
  1362.     ";"                    ;073
  1363.     "<"                    ;074
  1364.     "="                    ;075
  1365.     ">"                    ;076
  1366.     "?"                    ;077
  1367.     "@"                    ;100
  1368.     "A"                    ;101
  1369.     "B"                    ;102
  1370.     "C"                    ;103
  1371.     "D"                    ;104
  1372.     "E"                    ;105
  1373.     "F"                    ;106
  1374.     "G"                    ;107
  1375.     "H"                    ;110
  1376.     "I"                    ;111
  1377.     "J"                    ;112
  1378.     "K"                    ;113
  1379.     "L"                    ;114
  1380.     "M"                    ;115
  1381.     "N"                    ;116
  1382.     "O"                    ;117
  1383.     "P"                    ;120
  1384.     "Q"                    ;121
  1385.     "R"                    ;122
  1386.     "S"                    ;123
  1387.     "T"                    ;124
  1388.     "U"                    ;125
  1389.     "V"                    ;126
  1390.     "W"                    ;127
  1391.     "X"                    ;130
  1392.     "Y"                    ;131
  1393.     "Z"                    ;132
  1394.     "["                    ;133
  1395.     "\\"                ;134
  1396.     "]"                    ;135
  1397.     "^"                    ;136
  1398.     "_"                    ;137
  1399.     "`"                    ;140
  1400.     "a"                    ;141
  1401.     "b"                    ;142
  1402.     "c"                    ;143
  1403.     "d"                    ;144
  1404.     "e"                    ;145
  1405.     "f"                    ;146
  1406.     "g"                    ;147
  1407.     "h"                    ;150
  1408.     "i"                    ;151
  1409.     "j"                    ;152
  1410.     "k"                    ;153
  1411.     "l"                    ;154
  1412.     "m"                    ;155
  1413.     "n"                    ;156
  1414.     "o"                    ;157
  1415.     "p"                    ;160
  1416.     "q"                    ;161
  1417.     "r"                    ;162
  1418.     "s"                    ;163
  1419.     "t"                    ;164
  1420.     "u"                    ;165
  1421.     "v"                    ;166
  1422.     "w"                    ;167
  1423.     "x"                    ;170
  1424.     "y"                    ;171
  1425.     "z"                    ;172
  1426.     "{"                    ;173
  1427.     "|"                    ;174
  1428.     "}"                    ;175
  1429.     "~"                    ;176
  1430.     "^?"                ;177
  1431.     "\200"                ;200
  1432.     "~"                    ;201 MSDOS
  1433.     "\202"                ;202
  1434.     "\203"                ;203
  1435.     "{"                    ;204 MSDOS
  1436.     "\205"                ;205
  1437.     "}"                    ;206 MSDOS
  1438.     "\207"                ;207
  1439.     "\210"                ;210
  1440.     "\211"                ;211
  1441.     "\212"                ;212
  1442.     "\213"                ;213
  1443.     "\214"                ;214
  1444.     "\215"                ;215
  1445.     "["                    ;216 MSDOS
  1446.     "]"                    ;217 MSDOS
  1447.     "\220"                ;220
  1448.     "\221"                ;221
  1449.     "\222"                ;222
  1450.     "\223"                ;223
  1451.     "|"                    ;224 MSDOS
  1452.     "\225"                ;225
  1453.     "\226"                ;226
  1454.     "\227"                ;227
  1455.     "\230"                ;230
  1456.     "\\"                ;231 MSDOS
  1457.     "^"                    ;232 MSDOS
  1458.     "\233"                ;233
  1459.     "\234"                ;234
  1460.     "\235"                ;235
  1461.     "\236"                ;236
  1462.     "\237"                ;237
  1463.     " "                    ;240
  1464.     "!"                    ;241
  1465.     "c"                    ;242
  1466.     "#"                    ;243
  1467.     "$"                    ;244
  1468.     "Y"                    ;245
  1469.     "|"                    ;246
  1470.     "$"                    ;247
  1471.     "\""                ;250
  1472.     "c"                    ;251
  1473.     "+"                    ;252
  1474.     "<<"                ;253
  1475.     "!"                    ;254
  1476.     "-"                    ;255
  1477.     "R"                    ;256
  1478.     "~"                    ;257
  1479.     "C"                    ;260
  1480.     "+"                    ;261
  1481.     "2"                    ;262
  1482.     "3"                    ;263
  1483.     "'"                    ;264
  1484.     "u"                    ;265
  1485.     "$"                    ;266
  1486.     "-"                    ;267
  1487.     ","                    ;270
  1488.     "1"                    ;271
  1489.     "0"                    ;272
  1490.     ">>"                ;273
  1491.     "?"                    ;274
  1492.     "?"                    ;275
  1493.     "?"                    ;276
  1494.     "?"                    ;277
  1495.     "A"                    ;300
  1496.     "A"                    ;301
  1497.     "A"                    ;302
  1498.     "A"                    ;303
  1499.     "["                    ;304
  1500.     "]"                    ;305
  1501.     "["                    ;306
  1502.     "C"                    ;307
  1503.     "E"                    ;310
  1504.     "@"                    ;311
  1505.     "E"                    ;312
  1506.     "E"                    ;313
  1507.     "I"                    ;314
  1508.     "I"                    ;315
  1509.     "I"                    ;316
  1510.     "I"                    ;317
  1511.     "D"                    ;320
  1512.     "N"                    ;321
  1513.     "O"                    ;322
  1514.     "O"                    ;323
  1515.     "O"                    ;324
  1516.     "O"                    ;325
  1517.     "\\"                ;326
  1518.     "*"                    ;327
  1519.     "\\"                ;330
  1520.     "U"                    ;331
  1521.     "U"                    ;332
  1522.     "U"                    ;333
  1523.     "^"                    ;334
  1524.     "Y"                    ;335
  1525.     "T"                    ;336
  1526.     "ss"                ;337
  1527.     "a"                    ;340
  1528.     "a"                    ;341
  1529.     "a"                    ;342
  1530.     "a"                    ;343
  1531.     "{"                    ;344
  1532.     "}"                    ;345
  1533.     "{"                    ;346
  1534.     "c"                    ;347
  1535.     "e"                    ;350
  1536.     "`"                    ;351
  1537.     "e"                    ;352
  1538.     "e"                    ;353
  1539.     "i"                    ;354
  1540.     "i"                    ;355
  1541.     "i"                    ;356
  1542.     "i"                    ;357
  1543.     "d"                    ;360
  1544.     "n"                    ;361
  1545.     "o"                    ;362
  1546.     "o"                    ;363
  1547.     "o"                    ;364
  1548.     "o"                    ;365
  1549.     "|"                    ;366
  1550.     "/"                    ;367
  1551.     "|"                    ;370
  1552.     "u"                    ;371
  1553.     "u"                    ;372
  1554.     "u"                    ;373
  1555.     "~"                    ;374
  1556.     "y"                    ;375
  1557.     "t"                    ;376
  1558.     "y"]                ;377
  1559.   "*Translation table for incoming characters to translate from ISO 8859-1
  1560. to SIS E47. Also handles some MSDOS characters.")
  1561.  
  1562.  
  1563. (defvar irc-translation-table-incoming-scandinavian8
  1564.   '["^@"                ;000
  1565.     "^A"                ;001
  1566.     ""                    ;002    ircII kludge
  1567.     "^C"                ;003
  1568.     "^D"                ;004
  1569.     "^E"                ;005
  1570.     "^F"                ;006
  1571.     "^G"                ;007
  1572.     "^H"                ;010
  1573.     "^I"                ;011
  1574.     "^J\n"                ;012
  1575.     "^K"                ;013
  1576.     "^L"                ;014
  1577.     "^M"                ;015
  1578.     "^N"                ;016
  1579.     ""                    ;017    ircII kludge
  1580.     "^P"                ;020
  1581.     "^Q"                ;021
  1582.     "^R"                ;022
  1583.     "^S"                ;023
  1584.     "^T"                ;024
  1585.     "^U"                ;025
  1586.     ""                    ;026    ircII kludge
  1587.     "^W"                ;027
  1588.     "^X"                ;030
  1589.     "^Y"                ;031
  1590.     "^Z"                ;032
  1591.     "^["                ;033
  1592.     "^\\"                ;034
  1593.     "^]"                ;035
  1594.     "^^"                ;036
  1595.     ""                    ;037    ircII kludge
  1596.     " "                    ;040
  1597.     "!"                    ;041
  1598.     "\""                ;042
  1599.     "#"                    ;043
  1600.     "$"                    ;044
  1601.     "%%"                ;045    Need %% to not disturb format.
  1602.     "&"                    ;046
  1603.     "'"                    ;047
  1604.     "("                    ;050
  1605.     ")"                    ;051
  1606.     "*"                    ;052
  1607.     "+"                    ;053
  1608.     ","                    ;054
  1609.     "-"                    ;055
  1610.     "."                    ;056
  1611.     "/"                    ;057
  1612.     "0"                    ;060
  1613.     "1"                    ;061
  1614.     "2"                    ;062
  1615.     "3"                    ;063
  1616.     "4"                    ;064
  1617.     "5"                    ;065
  1618.     "6"                    ;066
  1619.     "7"                    ;067
  1620.     "8"                    ;070
  1621.     "9"                    ;071
  1622.     ":"                    ;072
  1623.     ";"                    ;073
  1624.     "<"                    ;074
  1625.     "="                    ;075
  1626.     ">"                    ;076
  1627.     "?"                    ;077
  1628.     "\311"                ;100
  1629.     "A"                    ;101
  1630.     "B"                    ;102
  1631.     "C"                    ;103
  1632.     "D"                    ;104
  1633.     "E"                    ;105
  1634.     "F"                    ;106
  1635.     "G"                    ;107
  1636.     "H"                    ;110
  1637.     "I"                    ;111
  1638.     "J"                    ;112
  1639.     "K"                    ;113
  1640.     "L"                    ;114
  1641.     "M"                    ;115
  1642.     "N"                    ;116
  1643.     "O"                    ;117
  1644.     "P"                    ;120
  1645.     "Q"                    ;121
  1646.     "R"                    ;122
  1647.     "S"                    ;123
  1648.     "T"                    ;124
  1649.     "U"                    ;125
  1650.     "V"                    ;126
  1651.     "W"                    ;127
  1652.     "X"                    ;130
  1653.     "Y"                    ;131
  1654.     "Z"                    ;132
  1655.     "\304"                ;133
  1656.     "\326"                ;134
  1657.     "\305"                ;135
  1658.     "\334"                ;136
  1659.     "_"                    ;137
  1660.     "\351"                ;140
  1661.     "a"                    ;141
  1662.     "b"                    ;142
  1663.     "c"                    ;143
  1664.     "d"                    ;144
  1665.     "e"                    ;145
  1666.     "f"                    ;146
  1667.     "g"                    ;147
  1668.     "h"                    ;150
  1669.     "i"                    ;151
  1670.     "j"                    ;152
  1671.     "k"                    ;153
  1672.     "l"                    ;154
  1673.     "m"                    ;155
  1674.     "n"                    ;156
  1675.     "o"                    ;157
  1676.     "p"                    ;160
  1677.     "q"                    ;161
  1678.     "r"                    ;162
  1679.     "s"                    ;163
  1680.     "t"                    ;164
  1681.     "u"                    ;165
  1682.     "v"                    ;166
  1683.     "w"                    ;167
  1684.     "x"                    ;170
  1685.     "y"                    ;171
  1686.     "z"                    ;172
  1687.     "\344"                ;173
  1688.     "\366"                ;174
  1689.     "\345"                ;175
  1690.     "\374"                ;176
  1691.     "^?"                ;177
  1692.     "\200"                ;200
  1693.     "\374"                ;201 MSDOS
  1694.     "\202"                ;202
  1695.     "\203"                ;203
  1696.     "\344"                ;204 MSDOS
  1697.     "\205"                ;205
  1698.     "\345"                ;206 MSDOS
  1699.     "\207"                ;207
  1700.     "\210"                ;210
  1701.     "\211"                ;211
  1702.     "\212"                ;212
  1703.     "\213"                ;213
  1704.     "\214"                ;214
  1705.     "\215"                ;215
  1706.     "\305"                ;216 MSDOS
  1707.     "\304"                ;217 MSDOS
  1708.     "\220"                ;220
  1709.     "\221"                ;221
  1710.     "\222"                ;222
  1711.     "\223"                ;223
  1712.     "\366"                ;224 MSDOS
  1713.     "\225"                ;225
  1714.     "\226"                ;226
  1715.     "\227"                ;227
  1716.     "\230"                ;230
  1717.     "\326"                ;231 MSDOS
  1718.     "\334"                ;232 MSDOS
  1719.     "\233"                ;233
  1720.     "\234"                ;234
  1721.     "\235"                ;235
  1722.     "\236"                ;236
  1723.     "\237"                ;237
  1724.     "\240"                ;240
  1725.     "\241"                ;241
  1726.     "\242"                ;242
  1727.     "\243"                ;243
  1728.     "\244"                ;244
  1729.     "\245"                ;245
  1730.     "\246"                ;246
  1731.     "\247"                ;247
  1732.     "\250"                ;250
  1733.     "\251"                ;251
  1734.     "\252"                ;252
  1735.     "\253"                ;253
  1736.     "\254"                ;254
  1737.     "\255"                ;255
  1738.     "\256"                ;256
  1739.     "\257"                ;257
  1740.     "\260"                ;260
  1741.     "\261"                ;261
  1742.     "\262"                ;262
  1743.     "\263"                ;263
  1744.     "\264"                ;264
  1745.     "\265"                ;265
  1746.     "\266"                ;266
  1747.     "\267"                ;267
  1748.     "\270"                ;270
  1749.     "\271"                ;271
  1750.     "\272"                ;272
  1751.     "\273"                ;273
  1752.     "\274"                ;274
  1753.     "\275"                ;275
  1754.     "\276"                ;276
  1755.     "\277"                ;277
  1756.     "\300"                ;300
  1757.     "\301"                ;301
  1758.     "\302"                ;302
  1759.     "\303"                ;303
  1760.     "\304"                ;304
  1761.     "\305"                ;305
  1762.     "\306"                ;306
  1763.     "\307"                ;307
  1764.     "\310"                ;310
  1765.     "\311"                ;311
  1766.     "\312"                ;312
  1767.     "\313"                ;313
  1768.     "\314"                ;314
  1769.     "\315"                ;315
  1770.     "\316"                ;316
  1771.     "\317"                ;317
  1772.     "\320"                ;320
  1773.     "\321"                ;321
  1774.     "\322"                ;322
  1775.     "\323"                ;323
  1776.     "\324"                ;324
  1777.     "\325"                ;325
  1778.     "\326"                ;326
  1779.     "\327"                ;327
  1780.     "\330"                ;330
  1781.     "\331"                ;331
  1782.     "\332"                ;332
  1783.     "\333"                ;333
  1784.     "\334"                ;334
  1785.     "\335"                ;335
  1786.     "\336"                ;336
  1787.     "\337"                ;337
  1788.     "\340"                ;340
  1789.     "\341"                ;341
  1790.     "\342"                ;342
  1791.     "\343"                ;343
  1792.     "\344"                ;344
  1793.     "\345"                ;345
  1794.     "\346"                ;346
  1795.     "\347"                ;347
  1796.     "\350"                ;350
  1797.     "\351"                ;351
  1798.     "\352"                ;352
  1799.     "\353"                ;353
  1800.     "\354"                ;354
  1801.     "\355"                ;355
  1802.     "\356"                ;356
  1803.     "\357"                ;357
  1804.     "\360"                ;360
  1805.     "\361"                ;361
  1806.     "\362"                ;362
  1807.     "\363"                ;363
  1808.     "\364"                ;364
  1809.     "\365"                ;365
  1810.     "\366"                ;366
  1811.     "\367"                ;367
  1812.     "\370"                ;370
  1813.     "\371"                ;371
  1814.     "\372"                ;372
  1815.     "\373"                ;373
  1816.     "\374"                ;374
  1817.     "\375"                ;375
  1818.     "\376"                ;376
  1819.     "\377"]                ;377
  1820.   "*Translation table for incoming characters to translate from SIS E47
  1821. to ISO 8859-1. Also handles some MSDOS characters.")
  1822.  
  1823.  
  1824. (make-variable-buffer-local
  1825.  (defvar irc-userinfo (if (boundp 'irc-userinfo)
  1826.               irc-userinfo
  1827.               nil)
  1828.    "*If non-nil, a user settable string to be replied with when the client is
  1829. queried by some other user."))
  1830.  
  1831.  
  1832.  
  1833.  
  1834. ;;; Macros
  1835. ;;;
  1836. (defmacro subfield (str n)
  1837.   "Return a substring of STR. The substring is field N, as used in the latest
  1838. string-match."
  1839.   (` (if (and (numberp (match-beginning (, n)))
  1840.           (numberp (match-end (, n))))
  1841.      (substring (, str) (match-beginning (, n)) (match-end (, n)))
  1842.      "")))
  1843.  
  1844.  
  1845. ;;; Handle host names.
  1846. ;;;
  1847. ;;; First a constant regular expression string matching only host names.
  1848. ;;;
  1849. (defconst irc-hostname "^[A-Za-z][A-Za-z0-9.-.---]*$"
  1850.   "A regexp matching a string if and only if the string is a hostname.")
  1851.  
  1852.  
  1853. (defconst irc-hostname-complement "\\(^\\.\\|\\.$\\)")
  1854.  
  1855.  
  1856. ;;; See RFC 952
  1857. (defconst irc-hostname-chars '(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m
  1858.                    ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
  1859.                    ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M
  1860.                    ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
  1861.                    ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?- ?.))
  1862.  
  1863.  
  1864. (defun irc-is-hostname (name)
  1865.   "Returns t if the NAME is a hostname, nil else.
  1866. This functions is more paranoid (Hello RFC 952!) than the IRC servers."
  1867.   (and (stringp name)
  1868.        (not (not (and (string-match irc-hostname name)
  1869.               (string-match "\\." name)
  1870.               (not (string-match (regexp-quote irc-hostname-complement)
  1871.                      name)))))))
  1872.  
  1873.  
  1874. (defun irc-is-nickname (name)
  1875.   "Returns t if the NAME is a valid nick name in IRC."
  1876.   (and (numberp (string-match (concat "^[]A-Z[\\^_a-z{|}~`]"
  1877.                       "[]A-Z0-9[\\_^a-z{|}~`-`---]*$")
  1878.                   name))
  1879.        (not (numberp (string-match "\n" name)))))
  1880.  
  1881.  
  1882. (defun irc-is-channelname (name)
  1883.   "Returns t if NAME is a valid channel identification."
  1884.   (or (and (irc-server-has-multijoinable-channels)
  1885.        (or (= ?# (aref name 0))
  1886.            (= ?& (aref name 0)))
  1887.        (irc-is-named-channel name))
  1888.       (and (irc-server-has-non-numeric-channel-names)
  1889.        (= ?+ (aref name 0))
  1890.        (irc-is-named-channel name))
  1891.       (and (numberp (string-match "^ *-?[0-9]+ *$" name))
  1892.        (irc-is-named-channel (concat "+" name)))))
  1893.  
  1894.  
  1895. (defun irc-is-broadcastname (name)
  1896.   "Return t if NAME is a valid broadcast address, ie is a server- or hostname
  1897. containing wildcards prepended by $ (server) or # (host). Broadcasts came at
  1898. the same time as #channels."
  1899.   (and (irc-server-has-multijoinable-channels)
  1900.        (or (= ?$ (aref name 0)) (= ?# (aref name 0)))))
  1901.  
  1902.  
  1903. (defun irc-is-named-channel (name)
  1904.   "Return t if NAME is a valid nummeric channel identification."
  1905.   (or (and (irc-server-has-multijoinable-channels)
  1906.        (numberp (string-match "^[&#+][]/a-zA-Z#+{}[^~()*!@.,0-9_-_---]*$"
  1907.                   name)))
  1908.       (and (irc-server-has-non-numeric-channel-names)
  1909.        (numberp (string-match "^+[]/a-zA-Z+{}[^~()*!@.,0-9_-_---]*$"
  1910.                   name)))))
  1911.  
  1912.  
  1913. (defun irc-is-multijoinable-channel (channel)
  1914.   "True if CHANNEL is a multijoinable channel, ie a channel one can listen
  1915. to along several other multijoinable channels. This feature was introduced in
  1916. server version 2.6."
  1917.   (and (stringp channel)
  1918.        (or (= (aref channel 0) ?#)
  1919.        (= (aref channel 0) ?&))))
  1920.  
  1921.  
  1922. (defun irc-is-receiver (obj)
  1923.   "True if STR could be either a nick or channel name.
  1924. If user is an enabled irc operator, broadcast addresses are OK too."
  1925.   (or (string= "*" obj)
  1926.       (irc-is-nickname obj)
  1927.       (and (string-match "^\\([^@]+\\)@\\([^@]+\\)$" obj)
  1928.        (let ((pre (subfield obj 1))
  1929.          (post (subfield obj 2)))
  1930.          (and (irc-is-nickname pre)
  1931.           (irc-is-hostname post))))
  1932.       (irc-is-channelname obj)
  1933.       (and irc-operator (irc-is-broadcastname obj))))
  1934.  
  1935.  
  1936. (defun irc-format-channel (channel &optional width)
  1937.   "Format a CHANNEL identification (name, number or * (ie private)) to be left
  1938. justified in a 15 character wide field. Ie make what the format string %-15s
  1939. SHOULD do. If the channel equals irc-channel, ie the current channel, it is
  1940. postpended with a %.
  1941.  
  1942. Arguments are a string with the channel ID, and optional a number saying how
  1943. wide the resulting string should be at least. If none is given, 15 is used as
  1944. the default."
  1945.   (let* ((w (max 0 (or (and (numberp width) width) 15)))
  1946.      (isnamed (irc-is-named-channel channel))
  1947.      (c (cond ((string= "*" channel) "Private")
  1948.           ((string= channel irc-channel) (concat channel "%"))
  1949.           (t channel)))
  1950.      (rpad (make-string (max 0 (- w (length c))) ? )))
  1951.     (concat c rpad)))
  1952.  
  1953.  
  1954. (defun irc-extract-hostname (s)
  1955.   "Extract the hostname part from the STRING, ignoring a trailing comment.
  1956. The string doesn't start with a host name, return nil."
  1957.   (let ((i 0)
  1958.     (len (length s)))
  1959.     (while (and (< i len)
  1960.         (memq (string-to-char (substring s i))
  1961.               irc-hostname-chars))
  1962.       (setq i (1+ i)))
  1963.     (if (irc-is-hostname (substring s 0 i))
  1964.     (substring s 0 i)
  1965.     nil)))
  1966.  
  1967.  
  1968. (defun irc-extract-hosts (path)
  1969.   "Extract and remember the different hosts mentioned in the path string,
  1970. \"h1!h2!h3!x\" where x is either a host or a nick name."
  1971.   (let* ((first-host (irc-extract-hostname path))
  1972.      (first-! (string-match "!" path))
  1973.      (len (length first-host)))
  1974.     (cond ((string= path "") nil)
  1975.       ((and (not first-host) first-!)
  1976.        (irc-extract-hosts (substring path (1+ first-!))))
  1977.       ((not first-host) nil)
  1978.       (t (irc-extract-hosts (substring path len))))))
  1979.  
  1980. ;; keymap
  1981. ;; what i tend to like for keys might be very different from what most people
  1982. ;; find useful; in fact i tend to type the /COMMANDs more than use any bindings
  1983.  
  1984. ;; there are more things bound here just so people can see the different
  1985. ;; things available to them
  1986. (or irc-mode-map
  1987.     (progn
  1988.       (setq irc-mode-map (make-keymap))
  1989.       (define-key irc-mode-map "\C-j"        'irc-process-input)
  1990.       (define-key irc-mode-map "\C-m"        'irc-process-input)
  1991.       (define-key irc-mode-map "\C-i"        'irc-tab)
  1992.       (define-key irc-mode-map "\C-c\C-a"    'irc-execute-alias)
  1993.       (define-key irc-mode-map "\C-c\C-c"    'irc-execute-names)
  1994.       (define-key irc-mode-map "\C-c\C-h"    'irc-execute-help)
  1995.       (define-key irc-mode-map "\C-c\C-i"    'irc-execute-invite)
  1996.       (define-key irc-mode-map "\C-c\C-j"    'irc-execute-join)
  1997.       (define-key irc-mode-map "\C-c\C-k"    'irc-execute-kill)
  1998.       (define-key irc-mode-map "\C-c\C-l"    'irc-execute-list)
  1999.       (define-key irc-mode-map "\C-c\C-m"    'irc-history-menu)
  2000.       (define-key irc-mode-map "\C-c\C-n"    'irc-history-next)
  2001.       (define-key irc-mode-map "\C-c\C-o"    'irc-execute-oops)
  2002.       (define-key irc-mode-map "\C-c\C-p"    'irc-history-prev)
  2003.       (define-key irc-mode-map "\C-c\C-q"    'irc-execute-quote)
  2004.       (define-key irc-mode-map "\C-c\C-r"    'irc-execute-redirect)
  2005.       (define-key irc-mode-map "\C-c\C-s"    'irc-execute-squit)
  2006.       (define-key irc-mode-map "\C-c\C-t"    'irc-execute-topic)
  2007.       (define-key irc-mode-map "\C-c\C-u"    'irc-kill-input)
  2008.       (define-key irc-mode-map "\C-c\C-v"    'irc-execute-version)
  2009.       (define-key irc-mode-map "\C-c\C-w"    'irc-execute-who)
  2010.       (define-key irc-mode-map "\C-c\C-?"    'irc-kill-input)
  2011.       ;; it's nice to bind to a key while in development, but regular users
  2012.       ;; wonder about it in production.
  2013.       ;; (define-key irc-mode-map "\C-c " 'irc-pong)
  2014.       (define-key irc-mode-map "\C-c#" 'irc-execute-lusers)
  2015.       (define-key irc-mode-map "\C-c=" 'irc-execute-memberships)
  2016.       (define-key irc-mode-map "\C-c?" 'describe-mode)
  2017.       (define-key irc-mode-map "\C-ca" 'irc-execute-admin)
  2018.       (define-key irc-mode-map "\C-cc" 'irc-execute-connect)
  2019.       (define-key irc-mode-map "\C-cf" 'irc-execute-finger)
  2020.       (define-key irc-mode-map "\C-ci" 'irc-execute-info)
  2021.       (define-key irc-mode-map "\C-ck" 'irc-execute-quit)
  2022.       (define-key irc-mode-map "\C-cl" 'irc-execute-links)
  2023.       (define-key irc-mode-map "\C-cm" 'irc-execute-mode)
  2024.       (define-key irc-mode-map "\C-cn" 'irc-execute-news)
  2025.       (define-key irc-mode-map "\C-co" 'irc-execute-oper)
  2026.       (define-key irc-mode-map "\C-cp" 'irc-yank-prev-command)
  2027.       (define-key irc-mode-map "\C-cq"    'irc-execute-leave)
  2028.       (define-key irc-mode-map "\C-cs" 'irc-execute-summon)
  2029.       (define-key irc-mode-map "\C-ct" 'irc-execute-trace)
  2030.       (define-key irc-mode-map "\C-cu" 'irc-execute-users)
  2031.       (define-key irc-mode-map "\C-cv" 'irc-version)
  2032.       (define-key irc-mode-map "\C-cw" 'irc-execute-whois)
  2033.       (define-key irc-mode-map "\C-?"  'irc-del-backward-char)
  2034.       ;; make any self-inserting keys call irc-self-insert
  2035.       (mapcar (function
  2036.                (lambda (key)
  2037.         (define-key irc-mode-map key 'irc-self-insert)))
  2038.           (append
  2039.            (where-is-internal 'self-insert-command nil nil)
  2040.            '(" " "!" "\"" "#" "$" "%" "&" "'"
  2041.          "(" ")" "*" "+" "," "-" "." "/"
  2042.          "0" "1" "2" "3" "4" "5" "6" "7"
  2043.          "8" "9" ":" ";" "<" "=" ">" "?"
  2044.          "@" "A" "B" "C" "D" "E" "F" "G"
  2045.          "H" "I" "J" "K" "L" "M" "N" "O"
  2046.          "P" "Q" "R" "S" "T" "U" "V" "W"
  2047.          "X" "Y" "Z" "[" "\\" "]" "^" "_"
  2048.          "`" "a" "b" "c" "d" "e" "f" "g"
  2049.          "h" "i" "j" "k" "l" "m" "n" "o"
  2050.          "p" "q" "r" "s" "t" "u" "v" "w"
  2051.          "x" "y" "z" "{" "|" "}" "~")))))
  2052.  
  2053. ;; filters (mostly irc-parse-*)
  2054. ;; Filtering of server messages from reception to insertion in the buffer
  2055. ;; are all done on this page.  In particular, if a new server message has
  2056. ;; to be dealt with, it should be added in the irc-parse-server-msg function.
  2057. (defun irc-filter (proc str)
  2058.   "Filtering procedure for IRC server messages.
  2059. It waits until everything up to a newline is accumulated before handing the
  2060. string over to irc-parse-server-msg to be processed.  If irc-pop-on-signal
  2061. is an integer and a signal is issued then the *IRC* buffer will be displayed.
  2062.  
  2063. Unless irc-maximum-size is zero or negative, truncate the Kiwi buffer to
  2064. be no larger than irc-maximum-size. If it is larger, truncate it to
  2065. the size irc-minimum-size."
  2066.   (let* ((ibuf (process-buffer proc))
  2067.          bell irc-mark-to-point new-point old-irc-mark win)
  2068.     (save-excursion
  2069.       (set-buffer ibuf)
  2070.       ;; still can't tell why i need this; sure, i probably change point
  2071.       ;; in ibuf.  but so what?  set-window-point should clean up after that.
  2072.       ;; it works with it though and not without it, so it stays.
  2073.       (save-excursion 
  2074.     ;; trim buffer if needed
  2075.     (if (> irc-maximum-size 0)
  2076.         (irc-truncate-buffer irc-maximum-size irc-minimum-size))
  2077.         (setq irc-mark-to-point   ; so we can restore relative position later
  2078.               (- (point) (setq old-irc-mark (goto-char irc-mark)))
  2079.               ;; just glue str to the end of any partial line that's there
  2080.               irc-scratch (concat irc-scratch str))
  2081.         ;; see if it is time for a message
  2082.         (irc-check-time)
  2083.         (while (string-match "\n" irc-scratch) ; do as many lines as possible
  2084.           ;; first use irc-scratch for the dp returned by irc-parse-server-msg
  2085.           (setq irc-scratch (irc-parse-server-msg irc-scratch)
  2086.         bell (cdr irc-scratch) ; issue a signal?
  2087.                 ;; now irc-scratch is what it was, minus the line parsed
  2088.                 irc-scratch (car irc-scratch))
  2089.           (if bell
  2090.           (progn
  2091.         ;; issue a signal; no need to trash someone's kbd-macro over it
  2092.         (ding 'no-terminate)
  2093.         (irc-minibuffer-message "%sBell in %s%s"
  2094.                     irc-msg-info-pre
  2095.                     (buffer-name ibuf)
  2096.                     irc-msg-info-post))))
  2097.         ;; if point was in front of the irc-mark, new-point is figured relative
  2098.         ;; to the old mark, otherwise it is relative to the new one
  2099.         (setq new-point (+ (if (< irc-mark-to-point 0) old-irc-mark irc-mark)
  2100.                            irc-mark-to-point))))
  2101.     ;; update point based on whether the buffer is visible
  2102.     ;; we have a real problem here if there is more than one window displaying
  2103.     ;; the process-buffer and the user is not in the first canonical one.
  2104.     ;; i haven't yet determined a nice way to solve this
  2105.     (if (setq win (if (eq (window-buffer) ibuf)    ;930224/PS: Use selected
  2106.               (selected-window)    ; window if it shows that buffer.
  2107.               (get-buffer-window ibuf)))
  2108.     (set-window-point win new-point)
  2109.     (save-excursion (set-buffer ibuf) (goto-char new-point)))
  2110.     ;; if *IRC* isn't visible, a bell was issued and irc-pop-on-signal is an
  2111.     ;; integer then show the buffer.
  2112.     (if (and (integerp irc-pop-on-signal) bell (not win))
  2113.     (progn
  2114.       (setq win (selected-window))
  2115.       (if (/= (irc-count-windows 'no-mini) 1)
  2116.           (display-buffer ibuf) ;don't futz with sizes if more than 1 win's
  2117.           ;; we might be in the mininbuffer at the moment, so insure that
  2118.           ;; this happens starting in the current regular window
  2119.           (select-window (next-window win 'no-mini))
  2120.           ;; full screen doesn't get handled well by the algorithm
  2121.           ;; for the rest
  2122.           (if (= irc-pop-on-signal 1)
  2123.           (set-window-buffer (selected-window) ibuf)
  2124.           (split-window nil
  2125.                 (if (fboundp 'frame-height)
  2126.                     (- (frame-height)
  2127.                        (/ (frame-height) irc-pop-on-signal))
  2128.                   (- (screen-height)
  2129.                      (/ (screen-height) irc-pop-on-signal))))
  2130.           (display-buffer ibuf)
  2131.           ;; perhaps we need to go back to the minibuffer
  2132.           (select-window win)))))))
  2133.  
  2134.  
  2135. (defun irc-string-display-length (str)
  2136.   "Return the number of display positions a string would take when
  2137. being displayed by GNU-emacs. A character can be displayed in 1, 2 or
  2138. 4 positions. Also a TAB can be 1 to 8 positions wide.
  2139.  
  2140. This function is pessimistic, and will rather return a too large count than a
  2141. too small."
  2142.   (let ((len 0)
  2143.     (i (length str))
  2144.     (x 0))
  2145.     (while (> i 0)
  2146.       (setq i (1- i)
  2147.         x (+ x (let ((c (aref i str)))
  2148.              (cond
  2149.                ((= c \t) 8)    ;TAB.
  2150.                ((or (< c ?\040) (= c ?\177)) ;Normal CNTRL character.
  2151.             (if ctl-arrow 2 4)) ;^X or \030 notation.
  2152.                ((< c ?\177) 1) ;Regular character.
  2153.                ((< c ?\240) 4) ;Eight bit "CNTRL" chararacter.
  2154.                ((< c ?\400)
  2155.             (cond ((eq irc-output-character-set 'ASCII) 4)
  2156.                   ((eq irc-output-character-set 'ISO-8859-1) 1)
  2157.                   (t 4)))
  2158.                (t 4))))))
  2159.     x))
  2160.  
  2161.  
  2162. (defun irc-clean-up-message (str)
  2163.   "Exchange all \"%\" with \"%%\" in STR. Also exchange CNTRL/X in STR
  2164. with ^X. Substitute a ^B for CNTRL/B (which is used by ircII to togle the
  2165. boldness of text) if irc-drop-ircII-text-kludge-control-characters is true,
  2166. or else drop the character. As a further kudo, replace japanese characters
  2167. coded with JIS etc unless irc-show-japanese-characters is nil."
  2168.   (let* ((clean "")
  2169.      (dirty-chars (concat "%"
  2170.                   "\000\001\002\003\004\005\006\007"
  2171.                   "\010\011\012\013\014\015\016\017"
  2172.                   "\020\021\022\023\024\025\026\027"
  2173.                   "\030\031\032\033\034\035\036\037"
  2174.  
  2175.                   "\177"
  2176.                   
  2177.                   "\200\201\202\203\204\205\206\207"
  2178.                   "\210\211\212\213\214\215\216\217"
  2179.                   "\220\221\222\223\224\225\226\227"
  2180.                   "\230\231\232\233\234\235\236\237"
  2181.  
  2182.                   (if irc-emacs-knows-ISO8859-1
  2183.                   ""
  2184.                   (concat "\240\241\242\243\244\245\246\247"
  2185.                       "\250\251\252\253\254\255\256\257"
  2186.                       "\260\261\262\263\264\265\266\267"
  2187.                       "\270\271\272\273\274\275\276\277"
  2188.                       "\300\301\302\303\304\305\306\307"
  2189.                       "\310\311\312\313\314\315\316\317"
  2190.                       "\320\321\322\323\324\325\326\327"
  2191.                       "\330\331\332\333\334\335\336\337"
  2192.                       "\340\341\342\343\344\345\346\347"
  2193.                       "\350\351\352\353\354\355\356\357"
  2194.                       "\360\361\362\363\364\365\366\367"
  2195.                       "\370\371\372\373\374\375\376\377"))
  2196.                   ""))
  2197.      (dirty (concat "[" dirty-chars "]"))
  2198.      (non-dirty (concat "[^" dirty-chars "]")))
  2199.     (if (symbolp irc-translation-table-incoming)
  2200.     (cond ((eq 'scandinavian7 irc-translation-table-incoming)
  2201.            (setq irc-translation-table-incoming
  2202.              irc-translation-table-incoming-scandinavian7))
  2203.           ((eq 'scandinavian8 irc-translation-table-incoming)
  2204.            (setq irc-translation-table-incoming
  2205.              irc-translation-table-incoming-scandinavian8))))
  2206.     (while (or (string-match dirty str)
  2207.            (and irc-translation-table-incoming
  2208.             (string< "" str)))
  2209.       (let ((split (cond ((and (or (eq irc-show-japanese-characters t)
  2210.                    (eq irc-show-japanese-characters nil))
  2211.                    (string-match (concat
  2212.                           "^ ?\033$\\([@AB]\\)\\([^\033]*"
  2213.                           "\\)\033\\([()]. ?\\)")
  2214.                          str))
  2215.               (cond
  2216.                 ((eq irc-show-japanese-characters t)
  2217.                  (let* ((pre (subfield str 1))
  2218.                     (msg (subfield str 2))
  2219.                     (trail (subfield str 3)))
  2220.                  (cons (concat "\033$"
  2221.                        pre
  2222.                        (irc-clean-up-message msg)
  2223.                        trail))
  2224.                    (substring str (match-end 0))))
  2225.                 ((eq irc-show-japanese-characters nil)
  2226.                  (let ((msgend (match-end 0))
  2227.                    (type (substring str
  2228.                             (match-beginning 1)
  2229.                             (match-end 1))))
  2230.                    (cons (concat irc-msg-info-pre
  2231.                          (cond ((string= type "@")
  2232.                             "Old Kanjii: ")
  2233.                            ((string= type "A")
  2234.                             "Probaly chinese: ")
  2235.                            ((string= type "B")
  2236.                             "Modern Kanjii: ")
  2237.                            (t "Unkown 16-bit: "))
  2238.                          (irc-clean-up-message
  2239.                           (irc-translate-kanji
  2240.                            (substring str
  2241.                               (match-beginning 2)
  2242.                               (match-end 2))))
  2243.                          irc-msg-info-post
  2244.                          " ")
  2245.                      (substring str msgend))))
  2246.                 (t (irc-insert (concat "%%Bug in japanese part of"
  2247.                            " irc-clean-up-message."))
  2248.                    (cons (substring str 0 (match-end 0))
  2249.                      (substring str (match-end 0))))))
  2250.              ((not (null irc-translation-table-incoming))
  2251.               (cons (aref irc-translation-table-incoming
  2252.                       (aref str 0))
  2253.                 (substring str 1)))
  2254.              ((and (>= (aref str 0) ?\200) ;8 bit?
  2255.                    (or (< (aref str 0) ?\240)
  2256.                    (not (eq irc-output-character-set
  2257.                         'ISO-8859-1))))
  2258.               (cons (concat (format "\\%o" (aref str 0)))
  2259.                 (substring str 1)))
  2260.              ((string-match (concat "^" non-dirty "*%") str)
  2261.               (cons (concat (substring str 0 (1- (match-end 0)))
  2262.                     "%%")
  2263.                 (substring str (match-end 0))))
  2264.              ((= (aref str 0) ?\t)
  2265.               (cons "^I" (substring str 1)))
  2266.              ((= (aref str 0) ?\177)
  2267.               (cons "^?" (substring str 1)))
  2268.              ((and irc-drop-ircII-text-kludge-control-characters
  2269.                    (irc-member-general (aref str 0)
  2270.                            '(?\002 ?\017 ?\026 ?\037)
  2271.                            '=))
  2272.               (cons "" (substring str 1)))
  2273.              ((and (>= (aref str 0) ?\000)
  2274.                    (<= (aref str 0) ?\037))
  2275.               (cons
  2276.                (concat "^" (char-to-string (+ ?@ (aref str 0))))
  2277.                (substring str 1)))
  2278.              ((string-match (concat "^" non-dirty "+") str)
  2279.               (cons (substring str
  2280.                        (match-beginning 0)
  2281.                        (match-end 0))
  2282.                 (substring str (match-end 0))))
  2283.              (t (cons (substring str 0 1) (substring str 1))))))
  2284.     (setq clean (concat clean (car split))
  2285.           str (cdr split))))
  2286.     (concat clean str)))
  2287.  
  2288.  
  2289. (defun irc-translate-kanji (str)
  2290.   "Translate a japanese Kanjicoded message in STR into nummeric codes.
  2291. Just exchange every two octet sequence into their nummeric codes."
  2292.   (let ((retval ""))
  2293.     (while (>= (length str) 2)
  2294.       (let ((double (+ (* (aref str 0) 256) (aref str 1))))
  2295.     (setq retval (format "%s%s%d"
  2296.                  retval
  2297.                  (if (string= "" retval) "" " ")
  2298.                  double)
  2299.           str (substring str 2))))
  2300.     (if (> (length str) 0)
  2301.     (format "ODD %d" (aref str 0))
  2302.     retval)))
  2303.  
  2304.  
  2305. (defun irc-parse-server-msg (str)
  2306.   "Take the first line from STR and pass it on to the appropriate irc-parse-*
  2307. function.  If the message is one which irc-mode doesn't recognize, just display
  2308. it as the raw server message.
  2309.  
  2310. It returns a dotted-pair whose car is the remainder of STR after the first
  2311. newline and whose cdr is either t or nil, indicating whether a signal should
  2312. be issued."
  2313.   (let ((n (string-match "\r" str)))
  2314.     (while n
  2315.       (setq str (concat (substring str 0 n)
  2316.             (substring str (1+ n)))
  2317.         n (string-match "\r" str))))
  2318.   (let* ((nl (string-match "\n" str)) 
  2319.      (eol (or nl (length str)))
  2320.      (line (substring str 0 eol))
  2321.      (dummy (irc-log-in-debug-buffer (concat "  " line)))
  2322.      (new (or (string-match "^:\\([^! :]+\\)!\\([^@ :]+\\)@\\([^ :]+\\)"
  2323.                 line)))
  2324.      (triple (if new (cons (subfield line 1)
  2325.                    (cons (subfield line 2)
  2326.                      (subfield line 3)))))
  2327.      (rest (if new (substring line (match-end 0))))
  2328.      (irc-userhost (if new
  2329.                (format " <%s@%s>"
  2330.                    (car (cdr triple)) (cdr (cdr triple)))
  2331.                ""))
  2332.      (line (if new (format ":%s%s" (car triple) rest) line))
  2333.      (last-NOTICE-rcv irc-last-NOTICE-rcv)
  2334.      (last-NOTICE-src irc-last-NOTICE-src))
  2335.     (if (not nl)
  2336.     (irc-insert "%%WARNING: got incomplete line from server! No newline."))
  2337.     (setq irc-last-NOTICE-rcv ""
  2338.       irc-last-NOTICE-src "")
  2339.     (if (not (boundp 'irc-count-incoming-messages))
  2340.     (progn
  2341.       (message "?Kiwi: Variable irc-count-incoming-messages unbound")
  2342.       (set (make-local-variable 'irc-count-incoming-messages) nil)))
  2343.     (if (not (numberp irc-count-incoming-messages))
  2344.     (progn
  2345.       (message "?Kiwi: irc-count-incoming-messages=%d, not a number"
  2346.            irc-count-incoming-messages)
  2347.       (setq irc-count-incoming-messages 0)))
  2348.     (setq line (irc-lowlevel-dequote line)
  2349.       irc-count-incoming-messages (1+ irc-count-incoming-messages))
  2350.     (if (= 0 (% irc-count-incoming-messages 50))
  2351.     (irc-send (concat "PONG " irc-server)))
  2352.     (cons
  2353.      ;; the part of str not being parsed.
  2354.      (substring str (1+ (string-match "\n" str)))
  2355.      (cond
  2356.        ;; each function here should return t or nil indicating whether
  2357.        ;; to issue a signal.  Some of these regexps are fugly because
  2358.        ;; of inconsistent protocol use by the servers.  Fortunately Jarkko
  2359.        ;; is fixing that.
  2360.        ((string-match "^ *$" line) nil)    ;Ignore empty lines.
  2361.        ((string-match "^:[^: ]+ +MSG " line) (irc-parse-public line))
  2362.        ((string-match "^:[^: ]+ +CHANNEL " line) (irc-parse-channel line))
  2363.        ((string-match "^:[^ ]+ +JOIN " line) (irc-parse-channel line))
  2364.        ((string-match "^:[^: ]+ +PART " line) (irc-parse-channel line))
  2365.        ((string-match "^:[^: ]+ +INVITE " line) (irc-parse-invite line))
  2366.        ((string-match "^:[^: ]+ +NICK " line) (irc-parse-nick line))
  2367.        ((string-match "^:[^: ]+ +WALL " line) (irc-parse-wall line))
  2368.        ((string-match "^:[^: ]+ +WALLOPS " line) (irc-parse-wallops line))
  2369.        ((string-match "^:[^: ]+ +QUIT " line) (irc-parse-quit line))
  2370.        ((string-match "^:[^: ]+ +KICK " line) (irc-parse-kick line))
  2371.        ((string-match "^:[^: ]+ +KILL " line) (irc-parse-kill line))
  2372.        ((string-match "^:[^: ]+ +TOPIC " line) (irc-parse-topic line))
  2373.        ((string-match "^:[^: ]+ +MODE " line) (irc-parse-mode-reply line))
  2374.        ((string-match "^:[^: ]+ +[023][0-9][0-9][^0-9]" line)
  2375.     (irc-parse-RPL line))
  2376.        ((string-match "^:[^: ]+ +[4-5][0-9][0-9][^0-9]" line)
  2377.     (irc-parse-ERR line))
  2378.        ((string-match (concat "^\\(:?\\)\\([^: ]*\\) *NOTICE"
  2379.                   " +\\([^: ]+\\) *:"
  2380.                   "\\([^\001]*\001[^\001]*\001\\)")
  2381.               line)
  2382.     (setq irc-last-NOTICE-rcv last-NOTICE-rcv
  2383.           irc-last-NOTICE-src last-NOTICE-src)
  2384.     (let* ((colon (subfield line 1))
  2385.            (from (subfield line 2))
  2386.            (to (subfield line 3))
  2387.            (msg (concat (subfield line 4)
  2388.                 (substring line (match-end 0))))
  2389.            (frm (if (string= "" from) irc-server from)))
  2390.       (if (irc-is-nickname frm)
  2391.           (irc-remember frm 'irc-nicknames))
  2392.       (while (string-match "^\\([^\001]*\\)\\(\001[^\001]*\001\\)" msg)
  2393.         (let ((start (subfield msg 1))
  2394.           (ctcp (subfield msg 2))
  2395.           (end (substring msg (match-end 0))))
  2396.           (setq msg (concat start end))
  2397.           (if (string= "\001\001" ctcp)
  2398.           (setq msg (concat msg "\001"))
  2399.           (irc-parse-CLIENT-answer frm to ctcp))))
  2400.       (if (not (string-match "^ *$" msg))
  2401.           (irc-parse-server-msg
  2402.            (concat colon from " NOTICE " to " :" msg "\n")))))
  2403.        ((string-match "^\\(:[^: ]* +\\)?NOTICE " line)
  2404.     (setq irc-last-NOTICE-rcv last-NOTICE-rcv
  2405.           irc-last-NOTICE-src last-NOTICE-src)
  2406.     (irc-parse-notice line))
  2407.        ((string-match (concat "^\\(:?\\)\\([^: ]*\\) *PRIVMSG"
  2408.                   " +\\([^ ]+\\) +:"
  2409.                   "\\([^\001]*\001[^\001]*\001\\)") 
  2410.               line)
  2411.     (let* ((colon (subfield line 1))
  2412.            (from (subfield line 2))
  2413.            (to (subfield line 3))
  2414.            (msg (concat (subfield line 4)
  2415.                 (substring line (match-end 0))))
  2416.            (frm (if (string= "" from) irc-server from)))
  2417.       (if (irc-is-nickname frm)
  2418.           (irc-remember frm 'irc-nicknames))
  2419.       (while (string-match "^\\([^\001]*\\)\\(\001[^\001]*\001\\)" msg)
  2420.         (let ((start (subfield msg 1))
  2421.           (ctcp (subfield msg 2))
  2422.           (end (substring msg (match-end 0))))
  2423.           (setq msg (concat start end))
  2424.           (if (string= "\001\001" ctcp)
  2425.           (setq msg (concat msg "\001"))
  2426.           (irc-parse-CLIENT-query frm to ctcp))))
  2427.       (if (not (string-match "^ *$" msg))
  2428.           (irc-parse-server-msg
  2429.            (concat colon from " PRIVMSG " to " :" msg "\n")))))
  2430.        ((string-match "^\\(:[^: ]* +\\)?PRIVMSG " line)
  2431.     (irc-parse-priv line))
  2432.        ((string-match "^PING " line) (irc-pong))
  2433.        ((string-match "^\\(:[^: ^]* +\\)?PONG " line)
  2434.     (irc-parse-pong line))
  2435.        ((string-match "^ERROR " line) (irc-parse-error line))
  2436.        ((string-match "^WHOREPLY " line) (irc-parse-whoreply line))
  2437.        ((string-match "^NAMREPLY " line) (irc-parse-namreply line))
  2438.        ((string-match "^LINREPLY " line) (irc-parse-linreply line))
  2439.        (t (irc-insert (concat "%%Received unkown message from server,"
  2440.                   " in function irc-parse-server-msg:"))
  2441.       (irc-insert "%% \"%s\" (cleaned up line)."
  2442.               (irc-clean-up-message line))
  2443.       (irc-insert (concat "%% Please let %s know about this;"
  2444.                   " it might be a bug.")
  2445.               irc-hacker)
  2446.       nil)))))
  2447.  
  2448.  
  2449. (defun irc-parse-channel (str)
  2450.   "Examine CHANNEL, JOIN and PART messages from the IRC server.
  2451. CHANNEL indicates a user entering or leaving the channel which you are
  2452. on, JOIN indicates a user entering a channel and PART indicates a user
  2453. leaving the channel. If the user is not being ignored and \"join\" is
  2454. in irc-events, a message is inserted indicating the change.  A
  2455. message is always provided as confirmation if the user is the irc-mode
  2456. user.
  2457.  
  2458. This function returns t if a bell should be issued for the \"join\" event,
  2459. nil otherwise."
  2460.   (if (not (or (string-match (concat "^: *\\([^ ]+\\) +\\(JOIN\\)"
  2461.                      " +:?\\([^ ]+\\) +\\([^ ]*\\) *$")
  2462.                  str)
  2463.            (string-match (concat "^: *\\([^ ]+\\) +\\(JOIN\\)"
  2464.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2465.                  str)
  2466.            (string-match (concat "^: *\\([^ ]+\\) +\\(PART\\)"
  2467.                      " +:?\\([^ ]+\\) +\\([^ ]*\\) *$")
  2468.                  str)
  2469.            (string-match (concat "^: *\\([^ ]+\\) +\\(PART\\)"
  2470.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2471.                  str)
  2472.            (string-match (concat "^: *\\([^ ]+\\) +\\(CHANNEL\\)"
  2473.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2474.                  str)))
  2475.       (progn (irc-insert (concat "%%Unknown format on command from server,"
  2476.                  " please notify %s, it migh be a bug.")
  2477.              irc-hacker)
  2478.          (irc-insert "%% str=\"%s\"." str)
  2479.          (irc-insert "%% Function irc-parse-channel."))
  2480.       (let* ((user (subfield str 1))
  2481.          (type (subfield str 2))
  2482.          (channel (subfield str 3))
  2483.          (mode (subfield str 4))
  2484.          (left (or (string= type "PART")
  2485.                (and (string= type "CHANNEL") (string= channel "0"))))
  2486.          (pd (make-string (max 0 (1- (length channel))) ? ))
  2487.          (cont (concat irc-msg-cont pd)))
  2488.     (if (string= user irc-nick-used)
  2489.         (progn
  2490.           (if left
  2491.           (irc-forget channel 'irc-subscribed-channels)
  2492.           (irc-remember channel 'irc-subscribed-channels)))
  2493.         )
  2494.     (if (string= user irc-nick-used)
  2495.         (progn
  2496.           (if left
  2497.           (if (irc-server-has-multijoinable-channels)
  2498.               (if (or (string= (upcase channel) (upcase irc-channel))
  2499.                   (string= irc-channel "0"))
  2500.               (progn
  2501.                 (setq irc-channel "0")
  2502.                 (irc-show-subscribed-channels))
  2503.               (progn
  2504.                 (if nil
  2505.                 (irc-remember channel
  2506.                           'irc-subscribed-channels))
  2507.                 (irc-show-subscribed-channels)))
  2508.               (progn
  2509.             (if nil
  2510.                 (irc-remember irc-channel
  2511.                       'irc-subscribed-channels))
  2512.             (setq irc-channel "0")
  2513.             (irc-show-subscribed-channels)))
  2514.           (progn (setq irc-channel channel)
  2515.              (if nil
  2516.                  (irc-remember channel 'irc-subscribed-channels))
  2517.              (irc-send (concat "MODE " irc-channel))
  2518.              (irc-show-subscribed-channels))))
  2519.         (if (and (not (irc-recall user 'irc-ignored-ppl))
  2520.              (memq 'join irc-events))
  2521.         (progn
  2522.           (if left
  2523.               (irc-insert "%s%s%s has LEFT channel %s%s"
  2524.                   irc-msg-info-pre
  2525.                   user
  2526.                   irc-userhost
  2527.                   (if (irc-server-has-multijoinable-channels)
  2528.                       channel
  2529.                       irc-channel)
  2530.                   irc-msg-info-post)
  2531.               (progn
  2532.             (irc-remember user 'irc-nicknames)
  2533.             (irc-insert "%s%s%s has JOINED channel %s%s"
  2534.                     irc-msg-info-pre
  2535.                     user
  2536.                     irc-userhost
  2537.                     channel
  2538.                     irc-msg-info-post)))
  2539.           )
  2540.         (irc-signal user 'join)))))) ; check for signal for join
  2541.  
  2542.  
  2543. (defun irc-parse-CLIENT-answer (sndr rcvr str)
  2544.   "Examine a client answer message from another client.
  2545.  
  2546. Generally, incoming message will look like \"^ACLIENT keyword arg1 .. argN^A\"
  2547. one or several pasted together."
  2548.   (if (irc-recall sndr 'irc-ignored-ppl)
  2549.       ;; Ignored person.
  2550.       (setq str ""))
  2551.   (if (not (string-match "^\001\\([^\001]*\\)\001$" str))
  2552.       (progn (irc-insert "%%Got non-clientmessage in irc-parse-CLIENT-answer:")
  2553.          (irc-insert "%% \"%s\" (str)." str)
  2554.          (irc-insert "%% Please tell %s, probaly en internal error."
  2555.              irc-hacker))
  2556.     (setq str (irc-ctcp-dequote
  2557.            (substring str (match-beginning 1) (match-end 1)))))
  2558.   (if (not (string-match (concat " *\\([^\001 \t]+\\)"    ;1 keyword
  2559.                  " *:?"            ;optional colon
  2560.                  " *\\([^\001]*\\)"        ;2 data
  2561.                  " *$")
  2562.              str))
  2563.       (if (string< "" str)
  2564.       (progn (irc-insert "%%Received unknown CTCP answer message:")
  2565.          (irc-insert "%% \"%s\" (str)." (irc-clean-up-message str))
  2566.          (irc-insert "%% This is probaly NOT a bug.")))
  2567.       (let* ((keyw (subfield str 1))
  2568.          (args (subfield str 2))
  2569.          (pre (concat irc-msg-info-pre "User \"" sndr "\" "))
  2570.          (irc-msg-cont-used (make-string (length pre) ? )))
  2571.     (cond
  2572.       ((string= keyw "ACTION")    ;Ignore ACTION replies.
  2573.        )
  2574.       ((string= keyw "CLIENTINFO")
  2575.        (irc-insert (concat "%sis using a client which is using the"
  2576.                    " client-to-client-protocol keyword %s in the"
  2577.                    " following way: %s%s")
  2578.                pre keyw args irc-msg-info-post))
  2579.       ((string= keyw "ECHO")
  2580.        (irc-insert "%sechoed back \"%s\" to us with (CTCP) ECHO%s"
  2581.                pre args irc-msg-info-post))
  2582.       ((string= keyw "PING")
  2583.        (cond ((not (string-match "^[0-9]+$" args))
  2584.           (irc-insert (concat "%%Received bogus (CTCP) PING reply from"
  2585.                       " user %s: \"%s\".")
  2586.                   sndr args))
  2587.          (t (let* ((cur (car (cdr (irc-current-time))))
  2588.                (rep (string-to-int args))
  2589.                (ans (- cur rep))
  2590.                (tos (/ (* 10 (if (< ans 0)
  2591.                          (+ cur (- 65536 rep))
  2592.                          ans))
  2593.                    2))
  2594.                (int-part (/ tos 10))
  2595.                (dec-part  (- tos (* 10 int-part))))
  2596.               (irc-insert (concat "%sis about %d.%d seconds"
  2597.                       " away from you, %s%s")
  2598.                   pre int-part dec-part irc-nick-used
  2599.                   irc-msg-info-post)))))
  2600.       ((string= keyw "ERRMSG")
  2601.        (cond ((string-match "^PING +RELAY +\\([0-9]+\\)\\( +:.*\\)? *$"
  2602.                 args)
  2603.           (irc-parse-CLIENT-answer sndr
  2604.                        rcvr
  2605.                        (format "\001PING %s\001"
  2606.                            (subfield args 1))))
  2607.          ((string-match "^ACTION " args)
  2608.           ;; Ignore complaints about CTCP ACTION.
  2609.           )
  2610.          (t (irc-insert (concat "%%Errormessage from client of"
  2611.                     " user %s: \"%s\".")
  2612.                 sndr args))))
  2613.       ((string= keyw "FINGER")
  2614.        (let* ((data (if (string-match (concat "^ *Please +check +"
  2615.                           "my +USERINFO +instead"
  2616.                           " *:")
  2617.                       args)
  2618.                 (substring args (match-end 0))
  2619.                 args)))
  2620.          (if (string-match (concat "^\\(.* +Idle *\\)\\(for +\\)?"
  2621.                        "\\([0-9]+\\) *seconds? *$")
  2622.                    data)
  2623.          (let* ((m (subfield data 1))
  2624.             (idle (subfield data 3))
  2625.             (xpre (concat "\"" (irc-clean-up-message m)))
  2626.             (idle-time (string-to-int idle))
  2627.             (xpost (if (= 1 idle-time) "second" "seconds"))
  2628.             (idle-string (if (>= idle-time 60)
  2629.                      (format "%s %s\" (%s)"
  2630.                          idle
  2631.                          xpost
  2632.                          (irc-sec-to-time idle-time))
  2633.                      (concat idle " " xpost "\""))))
  2634.            (irc-insert "%shas FINGER-info %s%s"
  2635.                    pre
  2636.                    (concat xpre idle-string)
  2637.                    irc-msg-info-post))
  2638.          (irc-insert "%shas fingerinfo \"%s\"%s"
  2639.                  pre data irc-msg-info-post))))
  2640.       ((string= keyw "SOURCE")
  2641.        (cond
  2642.          ((string-match "^ *$" args)
  2643.           (irc-insert "%sEnd of source site listing%s"
  2644.               irc-msg-info-pre irc-msg-info-post))
  2645.          ((string-match "^ *\\([^: ]+\\) *: *\\([^: ]+\\) *: *\\(.*\\) *"
  2646.                 args)
  2647.           (let ((site (subfield args 1))
  2648.             (dir (subfield args 2))
  2649.             (files (subfield args 3)))
  2650.         (irc-insert "%sSource site: %s (directory %s, files %s)%s"
  2651.                 irc-msg-info-pre
  2652.                 site dir files
  2653.                 irc-msg-info-post)))
  2654.          (t (irc-insert "%%Received unknown CTCP %s reply from %s: %s"
  2655.                 keyw sndr args))))
  2656.       ((string= keyw "USERINFO")
  2657.        (if (or (string-match "^ *$" args)
  2658.            (string-match
  2659.             "^ *\\(HUH *\\?\\) *WHO +WANTS +TO +KNOW *\\? *$"
  2660.             (upcase args))
  2661.            (string= "<None Supplied>" args)
  2662.            (string= "And what you want to know?" args)
  2663.            (string= "No user info given." args)
  2664.            )
  2665.            (irc-insert (concat "%shasn't given any information"
  2666.                    " about him/herself%s")
  2667.                pre irc-msg-info-post)
  2668.            (progn
  2669.          (string-match "\\(\\.?\\)$" args)
  2670.          (let ((info (substring args 0 (match-beginning 0)))
  2671.                (dot (subfield args 2)))
  2672.            (irc-insert (concat "%shas given the information"
  2673.                        " \"%s\"%s about him/herself%s")
  2674.                    pre
  2675.                    (irc-clean-up-message info)
  2676.                    dot
  2677.                    irc-msg-info-post)))))
  2678.       ((or (string= keyw "VERSION")    ;CLIENT_VERSION
  2679.            (string= keyw "VRSN"))
  2680.        (if (string-match "^ *\\([^:]+\\) *: *\\([^:]+\\) *: *\\(.*\\) *$"
  2681.                  args)
  2682.            (let ((name (subfield args 1))
  2683.              (vrsn (subfield args 2))
  2684.              (env (subfield args 3)))
  2685.          (irc-insert (concat "%sUser \"%s\" claims to be using"
  2686.                      " client %s version %s (%s)%s")
  2687.                  irc-msg-info-pre
  2688.                  sndr name (irc-clean-up-message vrsn) env
  2689.                  irc-msg-info-post))
  2690.            (irc-insert "%sclaims to be using client %s%s"
  2691.                pre
  2692.                (irc-clean-up-message
  2693.                 (let ((c (cond
  2694.                        ((or (string-match
  2695.                          (concat
  2696.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2697.                           "\\([0-9]+\\.[0-9]+[^:]+\\) *:"
  2698.                           "[^0-9]*\\([0-9]\\.[0-9][^ \\.]+"
  2699.                           "*\\).*$")
  2700.                          args)
  2701.                         (string-match
  2702.                          (concat
  2703.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2704.                           "[^:]*: *\\(.*[0-9]\\."
  2705.                           "[0-9].*\\) *\\(\\)$")
  2706.                          args)
  2707.                         (string-match
  2708.                          (concat
  2709.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2710.                           "\\([^:]+\\) *:.*\\(\\)$")
  2711.                          args))
  2712.                     (concat "ircII "
  2713.                         (subfield args 1)
  2714.                         (subfield args 2)))
  2715.                        ((string-match
  2716.                      (concat "^[^:]*: *\\(.*[0-9]+\\."
  2717.                          "[0-9]+.*.*\\) *$")
  2718.                      args)
  2719.                     (subfield args 1))
  2720.                        ((string-match
  2721.                      "^[^:]*[0-9]+\\.[0-9]+[^:]*"
  2722.                      args)
  2723.                     (substring args 0 (match-end 0)))
  2724.                        (t args))))
  2725.                   (irc-nuke-whitespace
  2726.                    (progn
  2727.                  (while
  2728.                      (or (string-match
  2729.                       " The one true client\\." c)
  2730.                      (string-match (concat
  2731.                             " Who could ask for"
  2732.                             " anything more\\.")
  2733.                                c)
  2734.                      (string-match "SIAWPIO!" c))
  2735.                    (setq c (concat
  2736.                         (substring c 0 (match-beginning 0))
  2737.                         (substring c (match-end 0)))))
  2738.                  c))))
  2739.                irc-msg-info-post)))
  2740.       ((string= keyw "VRSN")
  2741.        (if (string-match "^ *\\([^:]+\\) *: *\\([^:]+\\) *: *\\(.*\\) *$"
  2742.                  args)
  2743.            (let ((name (subfield args 1))
  2744.              (vrsn (subfield args 2))
  2745.              (env (subfield args 3)))
  2746.          (irc-insert (concat "%sUser \"%s\" claims to be using"
  2747.                      " client %s version %s (%s)%s")
  2748.                  irc-msg-info-pre
  2749.                  sndr name vrsn env
  2750.                  irc-msg-info-post))
  2751.            (irc-insert "%%Received unknown (CTCP) %s reply from %s: %s"
  2752.                keyw sndr args)))
  2753.       (t (irc-insert (concat "%%Received unknown answer with keyword"
  2754.                  " \"%s\" from client of user \"%s\":"
  2755.                  " \"%s\".")
  2756.              keyw sndr args))))))
  2757.  
  2758.  
  2759. (defun irc-parse-CLIENT-query (sndr rcvr str)
  2760.   "Examine a client query message from another client.
  2761.  
  2762. Generally, incoming message will look like \"^A CLIENT keyword data
  2763. ... ^A\" where sndr is nick of client query is comming from, rcvr is
  2764. nick of receiver (either one self or a channel or a broadcast), and
  2765. keyword being a token in the set VERSION, USERINFO, ERRMSG etc. Arg1
  2766. to argN are optional." 
  2767.   (cond
  2768.     ((irc-recall sndr 'irc-ignored-ppl)
  2769.      ;; Ignored person.
  2770.      nil)
  2771.     ((not (string-match "^\001\\([^\001]*\\)\001$" str))
  2772.      (progn (irc-insert "%%Got non-CTCP query in irc-parse-CLIENT-query:")
  2773.         (irc-insert "%% \"%s\" (str)." str)
  2774.         (irc-insert "%% Please tell %s, probaly an internal error."
  2775.             irc-hacker)))
  2776.     (t (setq str (irc-ctcp-dequote
  2777.           (substring str (match-beginning 1) (match-end 1))))
  2778.        (if (not (string-match (concat " *\\([^\001 \t]+\\)" ;1 keyword
  2779.                       " *\\([^\001]*\\)" ;2 data
  2780.                       " *$")
  2781.                   str))
  2782.        (if (and debug-on-error
  2783.             (string< "" str))
  2784.            (progn
  2785.          (irc-insert "%%Received unknown CTCP request:")
  2786.          (irc-insert "%% \"%s\" (str)." (irc-clean-up-message str))
  2787.          (irc-insert "%% This is probaly not a bug.")))
  2788.        (let ((keyw (substring str (match-beginning 1) (match-end 1)))
  2789.          (args (substring str (match-beginning 2) (match-end 2)))
  2790.          (tell (memq 'ctcp irc-events)))
  2791.          (cond
  2792.            ((string= keyw "ACTION") ;CLIENT_ACTION
  2793.         (if (string= "" args)
  2794.             (irc-send (format "NOTICE %s :\001ERRMSG ACTION :%s\001"
  2795.                       sndr
  2796.                       "No argument supplied."))
  2797.             (irc-insert ">>> (To %s) User %s %s"
  2798.                 rcvr
  2799.                 sndr
  2800.                 (irc-clean-up-message args))))
  2801.            ((string= keyw "CLIENTINFO")
  2802.         (cond ((string-match "^ *$" args) ;No arguments
  2803.                (irc-send
  2804.             (concat "NOTICE " sndr " :\001"
  2805.                 (irc-ctcp-enquote
  2806.                  (concat
  2807.                   "CLIENTINFO :You can request help of the"
  2808.                   " commands ACTION CLIENTINFO ECHO ERRMSG"
  2809.                   " FINGER PING SOURCE USERINFO VERSION"
  2810.                   " by giving an argument to CLIENTINFO."))
  2811.                 "\001"))
  2812.                (if tell
  2813.                (irc-insert
  2814.                 "%sAnswered (CTCP) CLIENTINFO query to %s by %s%s"
  2815.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)) )
  2816.               ((string-match "^ *\\([^: ]+\\) *$" args) ;1 arg
  2817.                (let* ((w (substring args
  2818.                         (match-beginning 1)
  2819.                         (match-end 1)))
  2820.                   (uw (upcase w))
  2821.                   (info (cond
  2822.                       ((string= uw "ACTION")
  2823.                        (concat
  2824.                     "ACTION takes one or more arguments,"
  2825.                     " and displayes them as a \"MUD like"
  2826.                     " feeling\" to this user. If nick"
  2827.                     " sojge sends \"falls down\", this"
  2828.                     " user gets a message looking more or"
  2829.                     " less like \"User sojge falls"
  2830.                     " down\"."))
  2831.                       ((string= uw "CLIENTINFO")
  2832.                        (concat
  2833.                     "CLIENTINFO with 0 arguments gives"
  2834.                     " a list of known client query"
  2835.                     " keywords. With 1 argument,"
  2836.                     " a description of the client query"
  2837.                     " keyword is returned."))
  2838.                       ((string= uw "ECHO")
  2839.                        (concat
  2840.                     "ECHO returns whatever argument is"
  2841.                     " given."))
  2842.                       ((string= uw "ERRMSG")
  2843.                        (concat
  2844.                     "ERRMSG is returned either when the"
  2845.                     " query keyword is ERRMSG (in which"
  2846.                     " case all arguments are echoed) or"
  2847.                     " when an error in a query is"
  2848.                     " detected or some other error"
  2849.                     " happens in connection to CTCP (in"
  2850.                     " which case the query is returned as"
  2851.                     " the replies arguments, with a short"
  2852.                     " error message added)."))
  2853.                       ((string= uw "FINGER")
  2854.                        (concat
  2855.                     "FINGER shows user's real name, login"
  2856.                     " name, client machine and idle"
  2857.                     " time."))
  2858.                       ((string= uw "PING")
  2859.                        (concat
  2860.                     "PING takes a integer number as its"
  2861.                     " argument and echoes it back to the"
  2862.                     " sender."))
  2863.                       ((string= uw "SOURCE")
  2864.                        (concat
  2865.                     "SOURCE takes 0 arguments and returns"
  2866.                     " a description of where to find the"
  2867.                     " source code of the client. The"
  2868.                     " description is made up out of zero"
  2869.                     " or more lines followed by an end"
  2870.                     " marker. Every line is a CTCP"
  2871.                     " reply with the SOURCE keyword,"
  2872.                     " a space, the name of a FTP-server, a"
  2873.                     " colon, a directory name, a colon,"
  2874.                     " and 0 or more file names."
  2875.                     " If no file names are given, all the"
  2876.                     " files in the named directory are"
  2877.                     " needed. The end marker contains just"
  2878.                     " the keyword."))
  2879.                       ((string= uw "VERSION")
  2880.                        (concat
  2881.                     "VERSION takes 0 arguments and"
  2882.                     " returns a list of words consisting"
  2883.                     " of clients name, any number of"
  2884.                     " versions (starting with the major"
  2885.                     " version), and ending with the"
  2886.                     " enviroment the client runs in. A"
  2887.                     " colon and a plain text descrpition"
  2888.                     " of the clients version is appended"
  2889.                     " after the list."))
  2890.                       ((string= uw "USERINFO")
  2891.                        (concat
  2892.                     "USERINFO takes no arguments and"
  2893.                     " returns a user settable"
  2894.                     " string."))
  2895.                       (t nil))))
  2896.              (cond ((stringp info)
  2897.                 (irc-send
  2898.                  (concat "NOTICE " sndr " :\001"
  2899.                      (irc-ctcp-enquote
  2900.                       (concat "CLIENTINFO :" info))
  2901.                      "\001"))
  2902.                 (if tell
  2903.                     (irc-insert
  2904.                      (concat "%sAnswered (CTCP)"
  2905.                          " CLIENTINFO %s to %s by %s%s")
  2906.                      irc-msg-info-pre
  2907.                      uw
  2908.                      rcvr
  2909.                      sndr
  2910.                      irc-msg-info-post)))
  2911.                    (t (irc-send
  2912.                    (concat
  2913.                     "NOTICE " sndr " :\001"
  2914.                     (irc-ctcp-enquote
  2915.                      (concat
  2916.                       "ERRMSG " keyw
  2917.                       (if args
  2918.                       (concat " " args)
  2919.                       "")
  2920.                       " :Unknown keyword in CLIENTINFO"
  2921.                       " client query. Send CLIENTINFO"
  2922.                       " CLIENTINFO for help."))
  2923.                     "\001"))))))
  2924.               (t (irc-send
  2925.               (concat "NOTICE " sndr " :\001"
  2926.                   (irc-ctcp-enquote
  2927.                    (concat "ERRMSG " keyw " " args " :"
  2928.                        "CLIENTINFO takes 0 or 1"
  2929.                        " argument. Send"
  2930.                        " CLIENTINFO CLIENTINFO"
  2931.                        " for help."))
  2932.                   "\001"))
  2933.              (if tell
  2934.                  (irc-insert (concat
  2935.                       "%sComplained about user %s's"
  2936.                       " corrupted CTCP CLIENTINFO query to"
  2937.                       " %s%s")
  2938.                      irc-msg-info-pre
  2939.                      sndr
  2940.                      rcvr
  2941.                      irc-msg-info-post)))))
  2942.            ((string= keyw "ECHO") 
  2943.         (irc-send (format "NOTICE %s :\001ECHO %s\001"
  2944.                   sndr
  2945.                   (irc-ctcp-enquote args)))
  2946.         (if tell
  2947.             (irc-insert (concat "%sAnswered to (CTCP) ECHO request"
  2948.                     " from %s to %s, echoed back \"%s\"%s")
  2949.                 irc-msg-info-pre rcvr sndr args
  2950.                 irc-msg-info-post)))
  2951.            ((string= keyw "ERRMSG")
  2952.         (irc-send (format "NOTICE %s :\001ERRMSG %s :No errors.\001"
  2953.                   sndr args))
  2954.         (cond ((not tell)
  2955.                )
  2956.               ((string-match "^ *PING +RELAY +[0-9]+ *$" args)
  2957.                (irc-insert (concat "%sAnswered to (CTCP) ERRMSG PING"
  2958.                        " RELAY request to %s from %s%s")
  2959.                    irc-msg-info-pre rcvr sndr
  2960.                    irc-msg-info-post))
  2961.               (t (irc-insert (concat "%sAnswered to (CTCP) ERRMSG"
  2962.                          " request to %s from %s, echoed"
  2963.                          " back \"%s\"%s")
  2964.                      irc-msg-info-pre
  2965.                      rcvr sndr (concat args " :No errors")
  2966.                      irc-msg-info-post))))
  2967.            ((string= keyw "FINGER")
  2968.         (let* ((idle (irc-idle-time))
  2969.                (verbose-idle (concat "(" (irc-sec-to-time idle) ") "))
  2970.                (plur (not (= 1 idle))))
  2971.           (irc-send (format (concat "NOTICE %s :\001FINGER :Please"
  2972.                         " check my USERINFO instead :%s"
  2973.                         " (%s@%s) %d second%s %sha%s"
  2974.                         " passed since %s gave a command"
  2975.                         " last.\001")
  2976.                     sndr
  2977.                     (user-full-name)
  2978.                     (user-real-login-name)
  2979.                     (system-name)
  2980.                     idle
  2981.                     (if plur "s" "")
  2982.                     (if (>= idle 60) verbose-idle "")
  2983.                     (if plur "ve" "s")
  2984.                     irc-nick-used)))
  2985.         (if tell
  2986.             (irc-insert "%sAnswered (CTCP) FINGER query to %s by %s%s"
  2987.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  2988.            ((string= keyw "PING")
  2989.         (cond ((string-match "^[0-9]+$" args)
  2990.                (irc-send (format "NOTICE %s :\001PING %s\001"
  2991.                      sndr
  2992.                      (irc-ctcp-enquote args)))
  2993.                (if tell
  2994.                (irc-insert
  2995.                 "%sAnswered to (CTCP) PING query to %s from %s%s"
  2996.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  2997.               (t (irc-send (format "NOTICE %s :\001%s %s :%s\001"
  2998.                        sndr
  2999.                        "ERRMSG PING"
  3000.                        (irc-ctcp-enquote args)
  3001.                        "Argument was not a number"))
  3002.              (cond
  3003.                (tell
  3004.                 (irc-insert (concat "%%Received unknown CTCP PING"
  3005.                         " query to %s from user"
  3006.                         " \"%s\":")
  3007.                     rcvr sndr)
  3008.                 (irc-insert "%% \"%s\" (args)." args)
  3009.                 (irc-insert "%% This is probaly NOT a bug."))))))
  3010.            ((string= keyw "SOURCE")
  3011.         (let ((s irc-ftp-source))
  3012.           (while (not (null s))
  3013.             (let* ((r (car s))
  3014.                (site (nth 0 r))
  3015.                (dir (nth 1 r))
  3016.                (files (nth 2 r)))
  3017.               (irc-send
  3018.                (concat "NOTICE " sndr " :\001"
  3019.                    (irc-ctcp-enquote
  3020.                 (format "SOURCE %s:%s:%s"
  3021.                     site
  3022.                     dir
  3023.                     (irc-listify files " " "")))
  3024.                    "\001"))
  3025.               (setq s (cdr s))))
  3026.           (irc-send (concat "NOTICE " sndr " :\001SOURCE\001"))
  3027.           (if tell
  3028.               (irc-insert
  3029.                "%sAnswered (CTCP) SOURCE query to %s by %s%s"
  3030.                irc-msg-info-pre
  3031.                rcvr sndr
  3032.                irc-msg-info-post))))
  3033.            ((string= keyw "USERINFO") ;CLIENT_USERINFO
  3034.         (irc-send (concat "NOTICE " sndr " :\001"
  3035.                   (irc-ctcp-enquote
  3036.                    (concat "USERINFO :"
  3037.                        (if (stringp irc-userinfo)
  3038.                            irc-userinfo
  3039.                            "")))
  3040.                   "\001"))
  3041.         (if tell
  3042.             (irc-insert
  3043.              "%sAnswered (CTCP) USERINFO query to %s by %s%s"
  3044.              irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  3045.            ((string= keyw "VERSION")
  3046.         (cond ((string-match (concat
  3047.                       "^ *\\([^: ]+\\) +v?\\([0-9]+[^ ]+\\)"
  3048.                       " +\\(.*\\) *$")
  3049.                      irc-version)
  3050.                (irc-send
  3051.             (concat "NOTICE " sndr " :\001"
  3052.                 (irc-ctcp-enquote
  3053.                  (format "%s %s:%s:%s, %s, emacs %s"
  3054.                      keyw
  3055.                      (subfield irc-version 1)
  3056.                      (subfield irc-version 2)
  3057.                      (subfield irc-version 3)
  3058.                      (cond
  3059.                        (irc-emacs-knows-ISO8859-1
  3060.                         "8bit ISO 8859-1 characters")
  3061.                        (irc-translation-table-incoming
  3062.                         "8bit characters")
  3063.                        (t (concat "7bit ISO 646 characters"
  3064.                               " (ie ASCII with"
  3065.                               " friends)")))
  3066.                      emacs-version))
  3067.                 "\001"))
  3068.                (if tell
  3069.                (irc-insert
  3070.                 "%sAnswered (CTCP) %s query to %s by %s%s"
  3071.                 irc-msg-info-pre keyw rcvr sndr
  3072.                 irc-msg-info-post)))
  3073.               (t (irc-send (concat "NOTICE " sndr " :\001"
  3074.                        (irc-ctcp-enquote
  3075.                         (format "%s Kiwi::%s"
  3076.                             keyw
  3077.                             irc-version))
  3078.                        "\001"))
  3079.              (cond
  3080.                (tell
  3081.                 (irc-insert
  3082.                  "%sAnswered (CTCP) %s query to %s by %s%s"
  3083.                  irc-msg-info-pre keyw rcvr sndr irc-msg-info-post)
  3084.                 (irc-insert "%% Client doesn't know who it is!")
  3085.                 (irc-insert "%% Please tell %s." irc-hacker))))))
  3086.            (t (and nil
  3087.                (irc-send
  3088.            (concat "NOTICE " sndr " :\001"
  3089.                (irc-ctcp-enquote
  3090.                 (concat "ERRMSG "
  3091.                     keyw
  3092.                     (if args
  3093.                     (concat " " args)
  3094.                     "")
  3095.                     " :Query is unknown"))
  3096.                "\001"))
  3097.                )
  3098.           (cond
  3099.             (tell
  3100.              (irc-insert (concat "%%Received unknown CTCP \"%s\" to %s"
  3101.                      " from user \"%s\".")
  3102.                  str rcvr sndr))))))))))
  3103.  
  3104.  
  3105. (defun irc-parse-ERR (str)
  3106.   "Examine a numeric ERR_ message from the IRC server. Numeric
  3107. control messages are used by newer servers to aid in generalized
  3108. client design; while people are converting to the new servers the
  3109. older irc-parse-error, irc-parse-notice, et al, functions are
  3110. redundant with irc-parse-ERR and irc-parse-RPL.  Values used by this
  3111. function are found in the IRC source file numeric.h.
  3112.  
  3113. Note well that some things are still going to come out wrong because the
  3114. servers are currently still doing things inconsistently."
  3115.   (if (not (string-match (concat "^:\\(.*\\) +\\([4-5][0-9][0-9]\\) +"
  3116.                  "\\([^: ]*\\)? *:? *\\(.*\\) *$")
  3117.              str))
  3118.       (progn
  3119.     (irc-insert (concat "%%Received an ERR message with unknown format in"
  3120.                 " function irc-parse-ERR:"))
  3121.     (irc-insert "%% \"%s\"." str)
  3122.     (irc-insert "%%Please report this to %s." irc-hacker))
  3123.       (let*
  3124.       ;; we assume that the server and message are consistent for us; just
  3125.       ;; worry about the numeric value and the rest of the line
  3126.       ((srvr (subfield str 1))
  3127.        (code (subfield str 2))
  3128.        (txt (subfield str 4))
  3129.        (num (string-to-int code))
  3130.        (parorg (if (string= (upcase srvr) (upcase irc-server))
  3131.                ""
  3132.                (concat "(" srvr ") ")))
  3133.        (tmp1 nil))
  3134.     (if (not (string= "" srvr))
  3135.         (irc-remember srvr 'irc-servernames))
  3136.     (cond
  3137.       ((= num 401)        ; ERR_NOSUCHNICK
  3138.        (cond ((string-match (concat "^[^: ]+ +401 +[^: ]+ +"
  3139.                     ":Hunting +for +ghosts +?.*$")
  3140.                 str)
  3141.           nil)        ;Ignore "Hunting for ghosts ?" message.
  3142.          ((string-match (concat "^[^: ]+ +401 +[^: ]+ +"
  3143.                     ":Cannot +kick +user +off +"
  3144.                     "channel *$")
  3145.                 str)
  3146.           (irc-insert "%%%sCan't boot that user from that channel."
  3147.                   parorg))
  3148.          ((string-match "^@?[^:@ ]+" txt)
  3149.           (let* ((user (substring txt
  3150.                       (match-beginning 0)
  3151.                       (match-end 0)))
  3152.              (is-service (irc-recall user 'irc-services)))
  3153.             (if is-service
  3154.             (irc-insert (concat "%%Service %s isn't reachable at"
  3155.                         " the moment, please try again"
  3156.                         " later.")
  3157.                     is-service)
  3158.             (progn
  3159.               (if (irc-is-nickname user)
  3160.                   (irc-forget user 'irc-nicknames))
  3161.               (irc-insert (concat
  3162.                        "%%%sThere is no user called"
  3163.                        " \"%s\" on IRC at the moment.")
  3164.                       parorg
  3165.                       user)))
  3166.             (if (and (>= irc-major-version 2)
  3167.                  (>= irc-minor-version 6))
  3168.             (irc-send (concat "WHOWAS :" user))
  3169.             )))
  3170.          (t (irc-insert (concat "%%%sUnrecognized NO SUCH NICK"
  3171.                     " message follows; please tell %s:")
  3172.                 parorg
  3173.                 irc-hacker)
  3174.             (irc-insert "%% \"%s\"." str)
  3175.             (irc-insert "%%Function irc-parse-err, at 401."))))
  3176.       ((= num 402)        ; ERR_NOSUCHSERVER
  3177.        (cond ((or (string-match (concat "^ *\\(.+\\) *: *"
  3178.                         "\\(\\*\\*\\* * \\)?No +such +"
  3179.                         "server *.? *$")
  3180.                     txt)
  3181.               (string-match (concat "^:? *\\** *No +such"
  3182.                         " +server *( *"
  3183.                         "\\([^: ]+\\) *) *.?"
  3184.                         " *$")
  3185.                     txt))
  3186.           (irc-insert (concat "%%%sThere is no server \"%s\" on the"
  3187.                       " IRCnet at the moment.")
  3188.                   parorg
  3189.                   (irc-nuke-whitespace (subfield txt 1))))
  3190.          (t (irc-insert (concat "%%Unknown ERR 402 message received"
  3191.                     " in function irc-parse-ERR:"))
  3192.             (irc-insert "%% txt=\"%s\"." txt)
  3193.             (irc-insert "%% Please tell %s, it might be a bug."
  3194.                 irc-hacker))))
  3195.       ((= num 403)        ; ERR_NOSUCHCHANNEL
  3196.        (if (string= (upcase srvr) (upcase irc-server))
  3197.            (let ((chn (if (string-match "^\\([^: ]+\\) *:.*$" txt)
  3198.                   (subfield txt 1))))
  3199.          (if chn
  3200.              (irc-insert (concat "%%%sThere is no channel called"
  3201.                      " \"%s\" in use right now.")
  3202.                  parorg chn)
  3203.              (irc-insert "%%%sNo such channel in use." parorg)))))
  3204.       ((= num 404)        ; ERR_CANNOTSENDTOCHAN
  3205.        (if (string-match "^ *\\([^ :]+\\) *:" txt)
  3206.            (irc-insert "%%%sChannel %s rejected the message."
  3207.                parorg (subfield txt 1))
  3208.            (irc-insert "%%%sChannel rejected the message." parorg)))
  3209.       ((= num 405)
  3210.        (cond ((string-match (concat "^ *\\([^ ]+\\) *: *You +have +joined"
  3211.                     " +too +many +channels.? *$")
  3212.                 txt)
  3213.           (irc-insert (concat "%%Failed joining channel %s, as you're"
  3214.                       " already listening to too many"
  3215.                       " channels.")
  3216.                   (subfield txt 1)))
  3217.          (t (irc-insert "*** %s %s." parorg txt))))
  3218.       ((= num 406)
  3219.        (if (string-match "^ *\\([^: ]+\\) *: *\\(.*\\) *$"
  3220.                  txt)
  3221.            (let ((m (substring txt (match-beginning 2) (match-end 2)))
  3222.              (n (substring txt (match-beginning 1) (match-end 1))))
  3223.          (irc-insert
  3224.           "%%No trace left about \"%s\" in history of server %s."
  3225.           n srvr))
  3226.            (progn
  3227.          (irc-insert "%%Unknown type 406 error message from server:")
  3228.          (irc-insert "%% \"%s\" (str)." str)
  3229.          (irc-insert "%% Please tell %s, it migth be a bug."
  3230.                  irc-hacker))))
  3231.       ((= num 409)
  3232.        ;txt="No origin specified"
  3233.        (irc-insert "%%%s%s" parorg txt))
  3234.       ((= num 411)        ; ERR_NORECIPIENT
  3235.        (irc-insert "%%%sThe last message had no recipient." parorg))
  3236.       ((= num 412)        ; ERR_NOTEXTTOSEND
  3237.        (irc-insert "%%%sThe last message had no text to send." parorg))
  3238.       ((= num 413)
  3239.        (irc-insert "%%%sNo top level domain specified (no such receiver)."
  3240.                parorg))
  3241.       ((= num 421)        ; ERR_UNKNOWNCOMMAND
  3242.        (cond ((string-match "^CLIENT-SYNCH :?\\(.*\\) *:Unknown command$"
  3243.                 txt)
  3244.           (let* ((cmd (irc-nuke-whitespace (subfield txt 1)))
  3245.              (ucmd (upcase cmd)))
  3246.             (cond 
  3247.              ((or t (string-match "^QUOTE " ucmd))
  3248.               (irc-insert "%sEnd of quoted command%s"
  3249.                   irc-msg-info-pre irc-msg-info-post))
  3250.              (t (irc-insert (concat "%%Unknown internal"
  3251.                         " synchronisation in"
  3252.                         " irc-parse-ERR at 421:"))
  3253.             (irc-insert "%% \"%s\" (txt)." txt)
  3254.             (irc-insert "%% Please tell %s, this *is* a bug."
  3255.                     irc-hacker)))))
  3256.          ((string-match (concat "^\\(MODE\\|KICK\\|JOIN\\|PART\\)"
  3257.                     ".*Unknown :?command *$")
  3258.                 txt)
  3259.           nil)
  3260.          ((string-match "^CLIENT-START *: *Unknown *command *$" txt)
  3261.           (run-hooks 'irc-startup-hook))
  3262.          ((or (string-match "^\\(.*\\) :?Unknown :?command$" txt)
  3263.               (string-match "^:?Unknown command \\(.*[^ ].*\\) *$"
  3264.                     txt))
  3265.           (if (string= (upcase irc-server) (upcase srvr))
  3266.               (irc-insert "%%%sUnknown server command: %s."
  3267.                   parorg
  3268.                   (subfield txt 1))))
  3269.          (t (irc-insert (concat "%%%sUnkown server command,"
  3270.                     " reported in unknown format:")
  3271.                 parorg)
  3272.             (irc-insert "%% \"%s\" (txt)." txt)
  3273.             (irc-insert "%% Function irc-parse-err, at 421."))))
  3274.       ((or (= num 422)        ;ERR_NOMOTD
  3275.            (= num 423))        ;ERR_NOADMIN
  3276.        (irc-insert "%%%s%s" parorg txt))
  3277.       ((= num 431)        ; ERR_NONICKNAMEGIVEN
  3278.        (irc-insert "%%%sNo nickname give to change to." parorg))
  3279.       ((= num 432)        ; ERR_ERRONEUSNICKNAME
  3280.        (irc-insert (concat "%%%sBad format for nickname change. Your"
  3281.                    " nickname is \"%s\".")
  3282.                parorg irc-nick-used))
  3283.       ((= num 433)        ; ERR_NICKNAMEINUSE
  3284.        (if (or (string-match (concat "^:[^: \t]+ +433 +"
  3285.                      "\\([^: \t]+\\) +"
  3286.                      "\\([^: \t]+\\) +:")
  3287.                  str)
  3288.            (string-match (concat "^:[^: \t]+ +433 +\\(\\)"
  3289.                      "\\([^: \t]+\\) +:")
  3290.                  str))
  3291.            (let ((current (subfield str 1))
  3292.              (failed (subfield str 2)))
  3293.          (irc-insert (concat "%%%sNickname \"%s\" is already being"
  3294.                      " used, please choose another one.")
  3295.                  parorg
  3296.                  failed)
  3297.          (irc-insert "%sHmmm ... looks like you're still %s%s"
  3298.                  irc-msg-info-pre
  3299.                  (if (string= current "")
  3300.                  (concat "without a nickname, use \"/HELP"
  3301.                      " NICK\" to get help about how to"
  3302.                      " set one")
  3303.                  (concat "\"" current "\""))
  3304.                  irc-msg-info-post))
  3305.            (irc-insert "%%Unknown ERR 433 type message received:")
  3306.            (irc-insert "%% \"%s\" (str)." str)
  3307.            (irc-insert "%% Please tell %s." irc-hacker)))
  3308.       ((= num 436)
  3309.        (cond ((string-match "^\\([^ :]+\\) :Nickname collision KILL$" txt)
  3310.           (let ((nick (subfield txt 1)))
  3311.             (irc-insert "%sUser %s killed due to NAMECLASH at %s%s"
  3312.                 irc-msg-info-pre
  3313.                 nick
  3314.                 srvr
  3315.                 irc-msg-info-post)
  3316.             (irc-forget nick 'irc-nicknames)))
  3317.          (t (irc-insert "%%Unknown ERR 436 type message received:")
  3318.             (irc-insert "%% \"%s\" (txt)." txt)
  3319.             (irc-insert "%% Please tell %s." irc-hacker))))
  3320.       ((= num 441)        ; ERR_USERNOTINCHANNEL
  3321.        (if (string= (upcase irc-server) (upcase srvr))
  3322.            (irc-insert "%%%sYou're not on any channel." parorg)))
  3323.       ((= num 442)        ; ERR_NOTONCHANNEL
  3324.        (cond ((or (string-match (concat "^ *\\([^ :]+\\) +"
  3325.                         "\\([^ :]+\\) *: *"
  3326.                         "\\([^ :]+\\) +is +not"
  3327.                         " +here *.? *$")
  3328.                     txt)
  3329.               (string-match (concat "^ *\\([^: ]+\\) *\\(\\):\\"
  3330.                         "([^: ]+\\) +is +not +here *$")
  3331.                     str))
  3332.           (let* ((o1 (subfield txt 1))
  3333.              (c (subfield txt 2))
  3334.              (o2 (subfield txt 3))
  3335.              (chn (if (string= c "") irc-channel c))
  3336.              (name (if (string= o1 o2)
  3337.                    o1
  3338.                    (concat o2 " (" o1 ")"))))
  3339.             (irc-insert (concat "%%You can't change the channel"
  3340.                     " operator status of %s while s/he"
  3341.                     " isn't here on %s.")
  3342.                 name chn)))
  3343.          ((string-match (concat "^ *\\([^ :]+\\) +\\([^ :]+\\)"
  3344.                     " *: *\\(isn't +on +your"
  3345.                     " +channel\\|Cannot +kick"
  3346.                     " +user +off\\ +channel\\)")
  3347.                 txt)
  3348.           (let ((who (subfield txt 1))
  3349.             (chn (subfield txt 2))
  3350.             (msg (subfield txt 3)))
  3351.             (cond ((string-match "^isn't" msg)
  3352.                (irc-insert (concat "%%Can't /KICK %s while"
  3353.                            " s/he's not on your"
  3354.                            " channel %s.")
  3355.                        who chn))
  3356.               (t (irc-insert (concat "%%Failed to /KICK %s from"
  3357.                          " channel %s.")
  3358.                      who chn)))))
  3359.          ((string-match (concat "^: *[^: ]+ +442 +[^: ]+"
  3360.                     " +\\([^: ]+\\) *: *"
  3361.                     "isn't *on *your *"
  3362.                     "channel *!* *$")
  3363.                 str)
  3364.           (let ((u (subfield str 1)))
  3365.             (irc-insert (concat "%%Can't /kick user %s while s/he's"
  3366.                     " not on this channel.")
  3367.                 u)))
  3368.          ((or (string-match (concat ":[^: ]+ +442 +[^: ]+"
  3369.                         " +\\([^: ]+\\) +: *You're +not"
  3370.                         " +on *\\(that\\)? +channel *$")
  3371.                     str)
  3372.               (string-match
  3373.                (concat "^:[^: ]+ +442 +[^: ]+ +\\([^ ]+\\) *: *Not"
  3374.                    " *On *Channel$")
  3375.                str)
  3376.               (string-match (concat "^[^: ]+ +442 +[^: ]+"
  3377.                         " +\\([^ ]+\\): *You're +not +on"
  3378.                         " +channel +\\([^ ]+\\) *$")
  3379.                     str)
  3380.               (string-match (concat "^:[^: ]+ +442 +[^: ]+"
  3381.                         " *: *You're +not on"
  3382.                         " +channel +\\([^ ]+\\) *$")
  3383.                     str))
  3384.           (let ((c (subfield str 1)))
  3385.             (irc-insert "%%You're not on channel %s." c)))
  3386.          ((string-match "^\\([^ :]+\\) *:\\(.*\\)$" txt)
  3387.           (irc-insert "%%%s: %s" (subfield txt 2) (subfield txt 1)))
  3388.          ((string= (upcase irc-server) (upcase srvr))
  3389.           (irc-insert (concat "%%Unknown format on"
  3390.                       " ERR_NOTONCHANNEL message;"
  3391.                       " please tell %s, it might be"
  3392.                       " a bug:")
  3393.                   irc-hacker)
  3394.           (irc-insert "%% \"%s\" (str)." str)
  3395.           (irc-insert "%% Function irc-parse-ERR, at 442."))))
  3396.       ((= num 443)
  3397.        (if (string-match (concat "^\\([^: ]+\\) +\\([^: ]+\\) +"
  3398.                      ":is already on channel.?$")
  3399.                  txt)
  3400.            (let ((nick (subfield txt 1))
  3401.              (chan (subfield txt 2)))
  3402.          (irc-insert "%%User %s is already on channel %s." nick chan))
  3403.            (irc-insert "%%Unknown ERR433 message seen in irc-parse-ERR:")
  3404.            (irc-insert "%% \"%s\" (txt)." txt)
  3405.            (irc-insert "%% Please tell %s." irc-hacker)))
  3406.       ((= num 444)
  3407.        (if (string-match "^\\([^: ]+\\) +:\\(.*\\)$" txt)
  3408.            (let ((user (subfield txt 1))
  3409.              (mesg (subfield txt 2)))
  3410.          (irc-insert "%%%sNo such user as \"%s\" logged in."
  3411.                  parorg user))
  3412.            (irc-insert "%%%sNo such user logged in." parorg)))
  3413.       ((= num 445)
  3414.        (irc-insert "%%%s%s" parorg txt))
  3415.       ((= num 446)
  3416.        (irc-insert "%%%sCommand /%s" parorg txt))
  3417.       ((= num 451)        ; ERR_NOTREGISTERED
  3418.        (irc-insert "%%%sYou haven't checked in yet.  Choose a nickname."
  3419.                parorg))
  3420.       ((= num 461)        ; ERR_NEEDMOREPARAMS
  3421.        (if (or (string= "" srvr)
  3422.            (string= (upcase irc-server) (upcase srvr)))
  3423.            (irc-insert (concat "%%%sThere weren't enough arguments for"
  3424.                    " the last command.")
  3425.                parorg)))
  3426.       ((= num 462)        ; ERR_ALREADYREGISTRED
  3427.        (irc-insert "%%%sYou've already registered." parorg))
  3428.       ((= num 463)        ; ERR_NOPERMFORHOST
  3429.        (irc-insert "%%%sYour host isn't permitted." parorg))
  3430.       ((= num 464)        ; ERR_PASSWDMISMATCH
  3431.        (irc-insert "%%%sThat password is incorrect." parorg))
  3432.       ((= num 465)        ; ERR_YOUREBANNEDCREEP
  3433.        (irc-insert "%%%sYou've been banned from IRC." parorg))
  3434.       ((= num 466)        ; ERR_YOUWILLBEBANNED
  3435.        (irc-insert "%%%sYou will be banned from IRC (%s)." parorg str))
  3436.       ((= num 467)
  3437.        (if (string-match "^\\([^ :]+\\) :" txt)
  3438.            (irc-insert (concat "%%%sChannel %s already has a key, use"
  3439.                    " /MODE %s to see it.")
  3440.                parorg
  3441.                (subfield txt 1)
  3442.                (subfield txt 1))
  3443.            (irc-insert (concat "%%%sChannel already has a key, use /MODE"
  3444.                    " to see it.")
  3445.                parorg)))
  3446.       ((= num 471)        ; ERR_CHANNELISFULL
  3447.        (string-match "^[^: ]+" txt)
  3448.        (let ((s (substring txt (match-beginning 0) (match-end 0))))
  3449.          (irc-insert (concat "%%%sChannel %s is full. (Check limit with"
  3450.                  " /MODE %s)")
  3451.              parorg s s)))
  3452.       ((= num 472)        ; ERR_UNKNOWNMODE
  3453.        (if (not (string-match (concat "^: *\\([^: ]+\\) +472 +"
  3454.                       "\\([^: ]+\\) +\\(.*\\) +:?is +"
  3455.                       "unknown +mode +char +to +me *$")
  3456.                   str))
  3457.            (progn (irc-insert (concat "%%Unrecognized type 472 message;"
  3458.                       " please tell %s:")
  3459.                   irc-hacker)
  3460.               (irc-insert "%% \"%s\"." str)
  3461.               (irc-insert "%% Function irc-parse-ERR, at 472."))
  3462.            (let ((srv (substring str (match-beginning 1) (match-end 1)))
  3463.              (nick (substring str (match-beginning 2) (match-end 2)))
  3464.              (chr (substring str (match-beginning 3) (match-end 3))))
  3465.          (if (not (string= (upcase srvr) (upcase srv)))
  3466.              (irc-remember srv 'irc-servernames))
  3467.          (irc-remember nick 'irc-nicknames)
  3468.          (irc-insert "%%Character \"%s\" is not a MODE character."
  3469.                  chr))))
  3470.       ((= num 473)        ; ERR_INVITEONLYCHAN
  3471.        (if (not (string-match (concat "^:[^: ]+ +473 +[^: ]+ +"
  3472.                       "\\([^ ]+\\) +.*")
  3473.                   str))
  3474.            (progn (irc-insert (concat "%%%sUnknown format on"
  3475.                       " ERR_INVITEONLYCHAN; please tell"
  3476.                       " %s, it might be a bug:")
  3477.                   parorg
  3478.                   irc-hacker)
  3479.               (irc-insert "%% \"%s\" (str)." str)
  3480.               (irc-insert "%% Function irc-parse-ERR, at 473."))
  3481.            (let ((chn (substring str (match-beginning 1) (match-end 1))))
  3482.          (irc-insert (concat "%%%sYou need an invitation to join"
  3483.                      " invitation-only channel \"%s\".")
  3484.                  parorg
  3485.                  chn))))
  3486.       ((= num 474)
  3487.        (cond
  3488.          ((string-match "^\\([^ ]+\\) +:" txt)
  3489.           (let ((channel (subfield txt 1)))
  3490.         (irc-insert (concat "%%Can't join channel %s -- you're"
  3491.                     " banned from it.")
  3492.                 channel)))
  3493.          (t (irc-insert "%%Unknown ERR474 seen in irc-parse-ERR:")
  3494.         (irc-insert "%% \"%s\" (txt)" txt)
  3495.         (irc-insert "%% Please tell %s, it might be a bug."
  3496.                 irc-hacker))))
  3497.       ((= num 475)            ;ERR_CANT_JOIN
  3498.        (cond ((string-match "^\\([^ ]+\\) +:" txt)
  3499.           (let ((channel (subfield txt 1)))
  3500.             (irc-insert (concat "%%Can't join channel %s -- you"
  3501.                     " haven't supplied the right channel"
  3502.                     " key/password."))))
  3503.          (t (irc-insert "%%Unknown ERR475 seen in irc-parse-ERR:")
  3504.             (irc-insert "%% \"%s\" (txt)" txt)
  3505.             (irc-insert "%% Please tell %s, it might be a bug."
  3506.                 irc-hacker))))
  3507.       ((= num 481)        ; ERR_NOPRIVILEGES
  3508.        (if (string= (upcase irc-server) (upcase srvr))
  3509.            (if (string-match "CHANNEL" str)
  3510.            (irc-insert
  3511.             (concat "%%%sYou must be a channel operator"
  3512.                 " to "
  3513.                 (cond
  3514.                   ((string-match (concat ":Cannot set topic, not"
  3515.                              " channel OPER$")
  3516.                          str)
  3517.                    "set the channels topic.")
  3518.                   (t "do that.")))
  3519.             parorg)
  3520.            (irc-insert (concat "%%%sYou must be an enabled IRC"
  3521.                        " Operator to do THAT!")
  3522.                    parorg))))
  3523.       ((= num 482)        ; ERR_NOOPERHOST
  3524.        (if (and (irc-server-has-channelname-in-msgs)
  3525.             (string-match "^\\([^ ]+\\) *:.*$" txt))
  3526.            (irc-insert "%%%sYou're not a channel operator for %s!"
  3527.                parorg
  3528.                (subfield txt 1))
  3529.            (irc-insert (concat "%%%sYou're not a channel operator on"
  3530.                    " that channel!")
  3531.                parorg)))
  3532.       ((= num 491)        ; ERR_NOOPERHOST
  3533.        (irc-insert (concat "%%Password check failed at server %s,"
  3534.                    " you're still a disabled luser.")
  3535.                (upcase srvr)))
  3536.       ((= num 501)        ; ERR_UMODEUNKNOWNFLAG
  3537.        (irc-insert "%%%s." txt))
  3538.       ((= num 502)        ; ERR_USERSDONTMATCH
  3539.        (irc-insert (concat "%%You can't change, not even look at, other"
  3540.                    " user's modes.")))
  3541.       ((= num 513)
  3542.        (if (string-match "^To connect, type /QUOTE PONG \\([1-9][0-9]*\\)$"
  3543.                  txt)
  3544.            (irc-send (format "PONG :%s" (subfield txt 1)))
  3545.          (irc-insert "%%Unknown MSG 513 \"%s\"" txt)))
  3546.       (t                                 ; default
  3547.        (irc-insert (concat "%%%sUnrecognized numeric ERR message"
  3548.                    " follows; please tell %s:")
  3549.                parorg
  3550.                irc-hacker)
  3551.        (irc-insert "%% \"%s\" (str)." str)
  3552.        (irc-insert "%%Function irc-parse-err, at catch all.")))))
  3553.   nil)
  3554.  
  3555.  
  3556. (defun irc-parse-error (str)
  3557.   "Examine an ERROR message from the IRC server.
  3558. ERROR is used when something bogus happens like an unparsable command
  3559. is issued to the server.  Usually this will not happen unless something
  3560. like /QUOTE is used.  This message is also used when a user attempts to
  3561. change to a name that already exists.
  3562.  
  3563. Returns nil; currently no signals are issued for an error."
  3564.   (string-match " +:" str)        ;Skip "^ERROR :"
  3565.   (setq str (substring str (match-end 0)))
  3566.   (cond
  3567.     ((string-match (concat "^ *Nickname +[^: ]* +\\(is \\)?"
  3568.                "\\(already\\|not +chan\\|in use\\) *$")
  3569.            str)
  3570.      (irc-insert "%%%s" str)
  3571.      ;; either we couldn't change the current nickname
  3572.      (setq irc-nick (or (and irc-nick (get 'irc-nick 'o-nick))
  3573.             ;; or we never even had one
  3574.             "NO NAME YET (/NICK to set one)"))
  3575.      (set-buffer-modified-p (buffer-modified-p))
  3576.      (irc-insert (if (get 'irc-nick 'o-nick)
  3577.              "%sHmmm ... looks like you're still \"%s\"%s" 
  3578.              "%s%s%s")
  3579.          irc-msg-info-pre
  3580.          irc-nick
  3581.          irc-msg-info-post))
  3582.     ((string-match " *No +option +specified. *Try +MAIL +HELP *$" str)
  3583.      (irc-insert "%%No option specified; try /HELP MAIL and /MAIL HELP."))
  3584.     ((or (string-match (concat "Closing +Link *: *\\([^[ :]+\\[[^]]+\\]\\)"
  3585.                    " *\\(\\)(\\(.*\\)) *$")
  3586.                str)
  3587.      (string-match (concat "Closing +Link *: *\\([^ :]+\\) +\\([^ :]+\\)"
  3588.                    " *\\(.\\|\n\\)+$")
  3589.                str))
  3590.      (let* ((id (subfield str 1))
  3591.         (srce (subfield str 2))
  3592.         (preason (subfield str 3))
  3593.         (reason (if (and (> (length preason) 0)
  3594.                  (= ?\050 (aref preason 0))
  3595.                  (= ?\051 (aref preason (1- (length preason)))))
  3596.             (substring preason 1 (1- (length preason)))
  3597.             preason))
  3598.         (matches (string-match "^\\([^[]+\\)\\[\\([^]]+\\)\\]$" id))
  3599.         (nick (if matches (subfield id 1) ""))
  3600.         (host (if matches (subfield id 2) "")))
  3601.        (irc-parse-quit (format ":%s QUIT %s :%s"
  3602.                    nick
  3603.                    nick
  3604.                    reason))))
  3605.     (t (irc-insert "%%%s" str)))
  3606.   nil)
  3607.  
  3608.  
  3609. (defun irc-parse-invite (str)
  3610.   "Examine an INVITE message from the IRC server.
  3611. INVITE is sent when one user invites another to a channel.
  3612. If the inviter is not being ignored a message is inserted in the buffer.
  3613.  
  3614. This function returns t if a bell should be issued for the \"invite\" event,
  3615. nil otherwise."
  3616.   (let ((user (substring str 1 (string-match " +INVITE " str)))
  3617.         (to (substring str (match-end 0)
  3618.                        (string-match " +:?" str (match-end 0))))
  3619.         (channel (substring str (match-end 0))))
  3620.     ;; glom a new name, if necessary
  3621.     (irc-remember user 'irc-nicknames)
  3622.     (if (irc-recall user 'irc-ignored-ppl)
  3623.         (irc-send (concat "NOTICE " user " :You are being ignored by \""
  3624.               irc-nick-used
  3625.               "\"."))
  3626.     (progn
  3627.       (irc-insert "%sUser %s invites %s to join channel %s%s"
  3628.               irc-msg-info-pre
  3629.               user
  3630.               (if (string= (downcase to) (downcase irc-nick-used))
  3631.               "you"
  3632.               to)
  3633.               (irc-clean-up-message channel)
  3634.               irc-msg-info-post)
  3635.       (irc-signal user 'invite)))))
  3636.  
  3637.  
  3638. (defun irc-parse-kick (str)
  3639.   "Examine and display a KICK message."
  3640.   (if (not
  3641.        (string-match "^: *\\([^: ]+\\) +KICK +\\([^: ]+\\) +\\([^: ]+\\) *"
  3642.              str))
  3643.       (progn (irc-insert (concat "%%Unknown format on KICK message; please"
  3644.                  " tell %s, it might be a bug:")
  3645.              irc-hacker)
  3646.          (irc-insert "%% \"%s\" (str)." str)
  3647.          (irc-insert "%% Function irc-parse-kick."))
  3648.       (let ((actor (substring str (match-beginning 1) (match-end 1)))
  3649.         (chan (substring str (match-beginning 2) (match-end 2)))
  3650.         (victim (substring str (match-beginning 3) (match-end 3))))
  3651.     (irc-remember actor 'irc-nicknames)
  3652.     (irc-remember victim 'irc-nicknames)
  3653.     (cond ((and (string= (upcase actor) (upcase victim))
  3654.             (string= (upcase actor) (upcase irc-nick-used)))
  3655.            (irc-insert "%sYou kicked yourself from channel %s%s"
  3656.                irc-msg-info-pre chan irc-msg-info-post))
  3657.           ((string= (upcase actor) (upcase victim))
  3658.            (irc-insert "%sUser %s kicked him/herself from channel %s%s"
  3659.                irc-msg-info-pre actor chan irc-msg-info-post))
  3660.           ((string= (upcase victim) (upcase irc-nick-used))
  3661.            (irc-insert (concat "%%You have been kicked out from"
  3662.                    " channel %s by user %s.")
  3663.                chan
  3664.                actor))
  3665.           ((string= (upcase actor) (upcase irc-nick-used))
  3666.            (irc-insert (concat "%sYou have kicked out user %s from"
  3667.                    " channel %s%s")
  3668.                irc-msg-info-pre
  3669.                victim
  3670.                chan
  3671.                irc-msg-info-post))
  3672.           (t (irc-insert (concat "%sUser %s kicked out user %s"
  3673.                      " from channel %s%s")
  3674.                  irc-msg-info-pre
  3675.                  actor
  3676.                  victim
  3677.                  chan
  3678.                  irc-msg-info-post)))
  3679.     (if (string= (upcase victim) (upcase irc-nick-used))
  3680.         ;; No need to irc-maintain the victim, -parse-chan does that.
  3681.         (progn (if (irc-server-has-multijoinable-channels)
  3682.                (irc-parse-channel (concat ":" victim " PART " chan))
  3683.                (irc-parse-channel (concat ":" victim " CHANNEL 0")))
  3684.            t)
  3685.         nil))))
  3686.  
  3687.  
  3688. (defun irc-parse-kill (str)
  3689.   "Examine a KILL message from the IRC server.
  3690. For a client this means its connexion will be closing momentarily.  This rather
  3691. drastic turn of events will always get a signal so this function returns t."
  3692.   (if (not (string-match "\\(:[^: ]+ +\\)?KILL +\\([^: ]+\\) +:" str))
  3693.       (progn
  3694.     (irc-insert "%%Spurios KILL message: \"%s\" (str) in irc-parse-kill."
  3695.             str)
  3696.     (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  3697.       (let* ((s (subfield str 1))
  3698.          (v (subfield str 2))
  3699.          (i (substring str (match-end 0)))
  3700.          (server (irc-nuke-whitespace s))
  3701.          (victim (irc-nuke-whitespace v))
  3702.          (info (irc-nuke-whitespace i)))
  3703.     (cond ((string-match "\\([^!]+\\)!\\([^! ]+\\) +"
  3704.                  info)
  3705.            (let* ((s (subfield info 1))
  3706.               (o (subfield info 2))
  3707.               (m (substring info (match-end 0)))
  3708.               (c (if (and (= ?\050 (aref m 0))
  3709.                   (= ?\051 (aref m (1- (length m)))))
  3710.                  (substring m 1 (1- (length m)))
  3711.                  m)))
  3712.          (if (string= (upcase irc-nick-used) (upcase victim))
  3713.              (irc-insert (concat "%sYou have been /KILL'ed by operator"
  3714.                      " %s@%s (%s)%s")
  3715.                  irc-msg-info-pre
  3716.                  (irc-nuke-whitespace o)
  3717.                  (irc-nuke-whitespace s)
  3718.                  (irc-nuke-whitespace c)
  3719.                  irc-msg-info-post)
  3720.              (irc-insert "%sOperator %s@%s /KILL'ed user %s (%s)%s"
  3721.                  irc-msg-info-pre
  3722.                  (irc-nuke-whitespace o)
  3723.                  (irc-nuke-whitespace s)
  3724.                  victim
  3725.                  (irc-nuke-whitespace m)
  3726.                  irc-msg-info-post))))
  3727.           (t (irc-insert "%sUser %s KILL'ed by %s%s"
  3728.                  irc-msg-info-pre
  3729.                  victim
  3730.                  info
  3731.                  irc-msg-info-post)))))
  3732.   t)
  3733.  
  3734.  
  3735. (defun irc-parse-linreply (str)
  3736.   "Examine a LINREPLY message from the IRC server.
  3737. LINREPLY is used to answer a LINKS request to show all the servers on line.
  3738. \"Links\" is a bit of a misnomer since little information regarding the
  3739. actual structure of the IRCnet can be gained from these messages.
  3740.  
  3741. No signals are issued for lines from the LINREPLY."
  3742.   (if (not (string-match "^LINREPLY +\\([^: ]+\\) +" str))
  3743.       (progn (irc-insert (concat "%%Unkown LINREPLY format in "
  3744.                  "function irc-parse-linreply:"))
  3745.          (irc-insert "%% \"%s\"." str)
  3746.          (irc-insert "%% Please tell %s, it may be a bug." irc-hacker))
  3747.       (let ((old-mark irc-mark)
  3748.         (server-name (substring str (match-beginning 1) (match-end 1)))
  3749.         (server-info (irc-clean-up-message (substring str (match-end 0)))))
  3750.     (irc-remember server-name 'irc-servernames)
  3751.     (if (and (irc-terminal-is-slow)
  3752.          (or (irc-server-has-end-of-links) ;New server version ?
  3753.              (and (= irc-major-version 2) (= irc-minor-version 2))))
  3754.         (progn (irc-remember (format "Server %s: %s"
  3755.                      (upcase server-name)
  3756.                      server-info)
  3757.                  'irc-linksinfo)
  3758.            (if (and (not (irc-terminal-is-slow))
  3759.                 (string= (upcase server-name) (upcase irc-server)))
  3760.                (progn
  3761.              (irc-insert irc-links-header)
  3762.              (irc-insert irc-links-stroke)
  3763.              (set-buffer-modified-p (buffer-modified-p))
  3764.              (irc-recall-all-and-display 'irc-linksinfo
  3765.                              (progn
  3766.                                (string-match
  3767.                             "^[^: ]* ."
  3768.                             irc-links-header)
  3769.                                (match-end 0))
  3770.                              "servers"
  3771.                              "server")
  3772.              (irc-forget-all 'irc-linksinfo))))
  3773.     (progn (irc-insert "Server %s: %s"
  3774.                    (upcase server-name)
  3775.                    server-info)))))
  3776.   nil)
  3777.  
  3778.  
  3779. (defun irc-parse-mode-reply (str)
  3780.   "Examine a MODE reply message from the IRC server.
  3781. MODE replies are used in respnse to the MODE command to indicate the current,
  3782. ie new, status of a specified channel or user.
  3783.  
  3784. No signals are issued for MODE replies."
  3785.   (cond ((string-match (concat "^ *: *\\([^: ]+\\) +MODE +"
  3786.                    "\\([^: ]+\\) +:? *")
  3787.                str)
  3788.      (let ((orig (subfield str 1))
  3789.            (chan (subfield str 2))
  3790.            (mode (irc-nuke-whitespace (substring str (match-end 0)))) )
  3791.        (cond ((irc-is-hostname orig)
  3792.           (irc-remember orig 'irc-servernames))
  3793.          ((irc-is-nickname orig)
  3794.           (irc-remember orig 'irc-nicknames)))
  3795.        (cond ((irc-is-nickname chan)
  3796.           (let ((i (1- (length mode)))
  3797.             (um (upcase mode)))
  3798.             (while (and (>= i 0) (not (= ?O (aref um i))))
  3799.               (setq i (1- i)))
  3800.             (while (and (>= i 0)
  3801.                 (not (= ?- (aref um i)))
  3802.                 (not (= ?+ (aref um i))))
  3803.               (setq i (1- i)))
  3804.             (if (and (>= i 0) (= ?- (aref um i)))
  3805.             (setq irc-operator nil)
  3806.             (set-buffer-modified-p (buffer-modified-p))))
  3807.           (irc-insert "%sMode for user %s changed by %s: %s%s"
  3808.                   irc-msg-info-pre
  3809.                   chan
  3810.                   orig
  3811.                   (irc-explain-user-mode mode)
  3812.                   irc-msg-info-post))
  3813.          ((irc-is-nickname orig)
  3814.           (irc-insert "%sUser %s changed mode for channel %s: %s%s"
  3815.                   irc-msg-info-pre
  3816.                   orig
  3817.                   chan
  3818.                   (irc-explain-channel-mode mode)
  3819.                   irc-msg-info-post))
  3820.          ((irc-is-hostname orig)
  3821.           (irc-remember orig 'irc-servernames))
  3822.          (t (irc-insert "%%Unknown sender in irc-parse-mode-reply:")
  3823.             (irc-insert "%% \"%s\" (str), \"%s\" (orig)." str orig)
  3824.             (irc-insert "%% Please tell %s, this might be a bug."
  3825.                 irc-hacker)))))
  3826.     (t (irc-insert "%%Unkown format on MODE reply; please tell %s:"
  3827.                irc-hacker)
  3828.        (irc-insert "%% \"%s\"." str)
  3829.        (irc-insert "%% Function irc-parse-mode-reply.")))
  3830.   nil)
  3831.  
  3832.  
  3833. (defun irc-parse-namreply (str)
  3834.   "Examine a NAMREPLY message from the IRC server.
  3835. NAMREPLY is used in repsonse to NAMES to indicate what users are on what
  3836. channels.  All users on secret or private channels which the client is not
  3837. on are grouped together on one private channel.
  3838.  
  3839. No signals are issued for NAMREPLYs."
  3840.   (if (not (string-match "^NAMREPLY +[^ ]+ +\\([^ ]+\\) +" str))
  3841.       (progn (irc-insert (concat "%%Unknown format on NAMREPLY message,"
  3842.                  " in function IRC-PARSE-NAMREPLY:"))
  3843.          (irc-insert "%% \"%s\"." str))
  3844.       (let* ((channel (substring str (match-beginning 1) (match-end 1)))
  3845.          (users (substring str (match-end 0)))
  3846.          (count 0)
  3847.          (to-insert "")
  3848.          (nick nil)
  3849.          (format-string "%s  %3d   %s")
  3850.          (irc-msg-cont-used irc-names-cont-msg))
  3851.     ;; yet another source of information for irc-nicknames.
  3852.     (while (string-match "^\\([^ ]+\\)\\( \\|$\\)" users)
  3853.       (setq nick (substring users 0 (match-end 1))
  3854.         users (substring users (match-end 0))
  3855.         count (1+ count)
  3856.         to-insert (concat to-insert " " nick))
  3857.       (irc-remember nick 'irc-nicknames)) 
  3858.     (if (and (irc-terminal-is-slow) (irc-server-has-end-of-names))
  3859.         (let ((lin (format format-string
  3860.                 (irc-format-channel channel)
  3861.                    count
  3862.                    (irc-clean-up-message to-insert))))
  3863.           (setq irc-reply-count (1+ irc-reply-count))
  3864.           (let ((diff (irc-time-diff (irc-current-time)
  3865.                      irc-reply-count-time)))
  3866.         (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since last
  3867.                (> (nth 0 diff) 0)) ; display?
  3868.                (setq irc-reply-count-time (irc-current-time))
  3869.                (message (format " %d channel%s ..."
  3870.                     irc-reply-count
  3871.                     (if (= 1 irc-reply-count) "" "s"))))))
  3872.           (irc-remember lin 'irc-namtree))
  3873.         (irc-insert format-string
  3874.             (irc-format-channel channel)
  3875.             count
  3876.             (irc-clean-up-message to-insert)))))
  3877.   nil)
  3878.  
  3879.  
  3880. (defun irc-parse-nick (str)
  3881.   "Examine a NICK message from the IRC server.
  3882. NICK is sent when a user's nickname is changed, but it is only sent to the
  3883. people on the same channel as the user.  If the person changing names is
  3884. being ignored, this fact is tracked across the change.  If notification
  3885. is not enabled for \"nick\" then no message is inserted.
  3886.  
  3887. This function returns t if a signal should be issued for the \"nick\" event,
  3888. nil otherwise."
  3889.   (cond ((string-match "^: *\\([^ :]+\\) +NICK +:?\\([^ :]+\\) *$" str)
  3890.      (let* ((old (subfield str 1))
  3891.         (new (subfield str 2))
  3892.         (current irc-nick-used))
  3893.        (if (not (irc-recall old 'irc-services)) ;Always keep /services.
  3894.            (irc-forget old 'irc-nicknames))
  3895.        (irc-remember new 'irc-nicknames)
  3896.        (cond ((string= (upcase irc-nick-used) (upcase old))
  3897.           ;; Our own nick has changed.
  3898.           (setq irc-nick-used new)
  3899.           (set-buffer-modified-p (buffer-modified-p))))
  3900.        (cond ((irc-recall old 'irc-ignored-ppl)
  3901.           (irc-forget old 'irc-ignored-ppl)
  3902.           (irc-remember new 'irc-ignored-ppl)
  3903.           nil)            ;Don't signal this.
  3904.          ((and (memq 'nick irc-events)
  3905.                (not (string= (upcase new) (upcase current))))
  3906.           (irc-insert "%s%s is now known as %s%s"
  3907.                   irc-msg-info-pre old new irc-msg-info-post)
  3908.           (irc-signal old 'user))
  3909.          (t nil))))
  3910.     (t (irc-insert "%%Unknown NICK seen in irc-parse-nick:")
  3911.        (irc-insert "%% \"%s\" (str)." str)
  3912.        (irc-insert "%% Please tell %s, this might be a bug." irc-hacker))))
  3913.  
  3914.  
  3915. ;irc-remember
  3916. (defun irc-parse-notice (str)
  3917.   "Examine a NOTICE message from the IRC server.
  3918. NOTICE is the catch-all for IRC messages; if it can't be classified as
  3919. one of the other currently existing messages then the information is
  3920. sent as NOTICE.  This message is overused, even when it another could be
  3921. used instead.  For example, if an attempt is made to send to a nickname
  3922. which is not on IRC the error reply is sent via NOTICE.
  3923.  
  3924. No signal is issued for NOTICE because it is way too random with what it
  3925. means."
  3926.   (let* ((lst (if (string-match (concat "^ *:? *\\([^: ]*\\)? *NOTICE *"
  3927.                     "\\([^: ]*\\)? *:")
  3928.                 str)
  3929.           (list (substring str (match-beginning 1) (match-end 1)) ;srvr
  3930.             (substring str (match-beginning 2) (match-end 2)) ;rcvr
  3931.             (substring str (match-end 0))) ;msg
  3932.           (list "" "" str)))
  3933.      (srvnam (if (string= (car lst) "") irc-server (car lst)))
  3934.      (srvr (if (string= (upcase srvnam) (upcase irc-server)) "" srvnam))
  3935.      (parorg (if (string= "" srvr) "" (concat "(" srvr ") ")))
  3936.      (rcvr (car (cdr lst)))
  3937.      (msg (car (cdr (cdr lst))))
  3938.      (cmsg (irc-clean-up-message msg))
  3939.      (retval nil))            ;Kludge!
  3940.     (if (not (stringp irc-server))
  3941.     (setq irc-server (if (stringp (default-value 'irc-server))
  3942.                  (default-value 'irc-server)
  3943.                  "")))
  3944.     (if (and rcvr (irc-is-nickname rcvr))
  3945.     (setq irc-nick-used rcvr))
  3946.     (irc-remember srvr 'irc-servernames)
  3947.     (cond
  3948.       ((and (string= "POXAV" (upcase srvr))
  3949.         (string-match "weenie" msg))
  3950.        )
  3951.       ((irc-recall srvr 'irc-services)
  3952.        (irc-remember srvr 'irc-services) ;Update spelling.
  3953.        (irc-remember srvr 'irc-nicknames)
  3954.        (irc-insert "%s%s%s %s"
  3955.            irc-msg-info-pre srvr irc-msg-info-post cmsg))
  3956.       ((string-match (concat "^\\*\\*\\* *Notice *-- *Access *denied *"
  3957.                  "(\\(.*\\)) *\\(.*\\) *$")
  3958.              msg)
  3959.        (let ((reason (subfield msg 1))
  3960.          (refused-server (subfield msg 2)))
  3961.      (irc-insert "%%Refused server-link connection from server %s: %s."
  3962.              (upcase refused-server)
  3963.              reason)))
  3964.       ((string-match (concat "^\\*\\*\\* *Notice *-- *Rehashing *Server"
  3965.                  " *config *file *(\\(.*\\)) *$")
  3966.              msg)
  3967.        (let ((file (subfield msg 1)))
  3968.      (irc-insert "%sServer %s has reloaded it's configuration file %s%s"
  3969.              irc-msg-info-pre
  3970.              (upcase srvnam)
  3971.              file
  3972.              irc-msg-info-post)))
  3973.       ((string-match (concat "^\\*\\*\\* *Notice *-- *\\(Hack\\|Fake\\) *:"
  3974.                  " *\\([^ ]+\\) +MODE +\\([^ ]+\\)"
  3975.                  " *\\([^ ]*\\).*$")
  3976.              msg)
  3977.        ;;Ignore this information. It's just a way for enabled operators on 2.7
  3978.        ;; server to see people on 2.6 server as they join channels with initial
  3979.        ;; modes, such as secret or private. Hopefulle this will go away when
  3980.        ;; 2.6 servers go way.
  3981.        (let ((user (subfield msg 2))
  3982.          (channel (subfield msg 3))
  3983.          (mode (irc-nuke-whitespace (subfield msg 4))))
  3984.      (cond ((string-match "\\+[^-]*[sp]" mode)
  3985.         (irc-insert (concat "%sWarning a user about seeing her/his"
  3986.                     " secret channel join%s")
  3987.                 irc-msg-info-pre irc-msg-info-post)
  3988.         (irc-send (concat "NOTICE " user " :<Automatic warning> My"
  3989.                   " client (but not I myself -- I don't even"
  3990.                   " know who you are unless you'll tell me or"
  3991.                   " you happen to be marked as being AWAY)"
  3992.                   " saw you join channel "
  3993.                   channel
  3994.                   " ("
  3995.                   mode
  3996.                   "). The fact was broadcasted to everyone"
  3997.                   " seeing WALLOPS messages on 2.7 (and later)"
  3998.                   " servers. Your channel is probably"
  3999.                   " without any special mode on other servers."
  4000.                   " (But still look \"valid\" at yous site)."
  4001.                   " If you have any questions, then don't send"
  4002.                   " them to "
  4003.                   irc-nick
  4004.                   " but to the channel #Twilight_Zone."
  4005.                   ))
  4006.         (irc-send (concat "NOTICE " user " :<Automatic warning> If"
  4007.                   " you don't care about getting warned, but"
  4008.                   " want to think you're invisible while being"
  4009.                   " visible, and you happen to use a Kiwi"
  4010.                   " client, you can do M-x set-variable RET"
  4011.                   " irc-ignore-automatic-warnings RET t"
  4012.                   " RET. If you're using ircII, instead do"
  4013.                   " /on ^notice \"" irc-nick " <Automatic"
  4014.                   " warning>*\: /^comment"))
  4015.         ))))
  4016.       ((string-match (concat "^\\*\\*\\* Message-of-today is missing"
  4017.                  " on host \\([^: ]+\\)? *$")
  4018.              msg)
  4019.        (let ((host (irc-clean-up-message (subfield msg 1))))
  4020.      (if (not (string= (upcase srvr) (upcase host)))
  4021.          (irc-remember host 'irc-servernames))
  4022.      (irc-insert "%%%sNo message of the day at server %s."
  4023.              (if (or (string= srvr irc-server)
  4024.                  (string= srvr ""))
  4025.              ""
  4026.              (concat "(" srvr ") "))
  4027.              (upcase host))))
  4028.       ((string-match "^MOTD *- ?*\\([^: ]+\\)? *message +of +the +day *-? *$"
  4029.              msg)
  4030.        (let ((server (irc-clean-up-message (substring msg
  4031.                               (match-beginning 1)
  4032.                               (match-end 1)))))
  4033.      (if (not (string= (upcase srvr) (upcase server)))
  4034.          (irc-remember server 'irc-servernames))
  4035.      (irc-insert "")
  4036.      (irc-insert ">>> Message of the day at server %s:" server)
  4037.      (set-buffer-modified-p (buffer-modified-p))))
  4038.       ((string-match "^MOTD *- ?" msg)
  4039.        (setq irc-motd-lines (append irc-motd-lines
  4040.                     (list (irc-clean-up-message
  4041.                        (substring msg (match-end 0)))))))
  4042.       ((string-match "^\\* *end +of +/?motd +command. *$" msg)
  4043.        (while irc-motd-lines
  4044.      (irc-insert ">>> %s" (car irc-motd-lines))
  4045.      (setq irc-motd-lines (cdr irc-motd-lines))))
  4046.       ((string-match (concat "^\\*\\*\\* *Error *: *No +mere +mortals +"
  4047.                  "may +trace +the +nets +of +the +universe *$")
  4048.              msg)
  4049.        (irc-insert (concat "%%%sYou must be an enabled IRC operator to trace"
  4050.                " the IRCnet, use /OPER to enable yourself. An"
  4051.                " alternative is to use /STATS L, do /HELP STATS.")
  4052.            parorg))
  4053.       ((string-match "^Good afternoon, gentleman\\. I am a HAL 9000" msg)
  4054.        (if (string= srvr "")
  4055.        (irc-insert "%sOperator status for %s ENABLED%s"
  4056.                irc-msg-info-pre
  4057.                irc-nick-used
  4058.                irc-msg-info-post)
  4059.        (irc-insert "%sOperator status at %s for %s ENABLED%s"
  4060.                irc-msg-info-pre
  4061.                srvr
  4062.                irc-nick-used
  4063.                irc-msg-info-post))
  4064.        ;; we've been granted operator privileges.  the string is for mode-line
  4065.        (setq irc-operator " IOPR")
  4066.        (set-buffer-modified-p (buffer-modified-p)))
  4067.       ((string-match (concat "^\\*\\*\\* *notice *-- *Received"
  4068.                  " +unauthorized +connection +from +")
  4069.              msg)
  4070.        (irc-insert (concat "%%Something at internet host %s tried to"
  4071.                " establish a connection with us. Refused"
  4072.                " as it isn't enabled in the confiugation file.")
  4073.            (irc-nuke-whitespace (substring msg (match-end 0)))))
  4074.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\) *Link"
  4075.                  " +with +\\([^ ]+\\) +established"
  4076.                  " *.? *$")
  4077.              msg)
  4078.        ;; In a few seconds, we ought to issue a LINKS command to the server,
  4079.        ;; but without displaying the answer, only storing it. Sigh.
  4080.        (let* ((h (irc-extract-hostname
  4081.           (irc-clean-up-message
  4082.            (subfield msg 2))))
  4083.           (host (if (stringp h) h "")))
  4084.      (if (not (string= (upcase srvr) (upcase host)))
  4085.          (irc-remember host 'irc-servernames))
  4086.      (irc-insert "%s%sLink with %s established%s"
  4087.              irc-msg-info-pre
  4088.              (if (string= srvr "") "" (concat "(" srvr ")"))
  4089.              (upcase host)
  4090.              irc-msg-info-post))
  4091.        (irc-later-execute-lusers))
  4092.       ((or (string-match (concat "^\\*\\*\\* *\\([^ ]+\\) +\\([^:]+\\) *"
  4093.                  "==> *\\(.+\\) *$")
  4094.              cmsg)
  4095.        ;; 2.6 following
  4096.        (string-match (concat "^\\*\\*\\* +\\(Connection\\) +\\([^ ]+\\) +"
  4097.                  "==> +\\([^ ]+\\) +\\[\\([^ ]+\\)\\] *$")
  4098.              cmsg)
  4099.        (string-match (concat "^\\*\\*\\* +\\(Connection\\) +\\([^ ]+\\) +"
  4100.                  "==> +\\([^ ]+\\) *$")
  4101.              cmsg)
  4102.        (string-match (concat "^\\*\\*\\* +\\(Link\\) +\\([^ ]+\\) +"
  4103.                  "==> +\\([^ ]+\\) *$")
  4104.              cmsg)
  4105.        (string-match (concat "^\\*\\*\\* +\\(<newtype>\\) +\\([^ ]+\\) +"
  4106.                  "==> +\\([^ ]+\\) *$")
  4107.              cmsg))
  4108.        (let* ((type (substring cmsg (match-beginning 1) (match-end 1)))
  4109.           (lcl (substring cmsg (match-beginning 2) (match-end 2)))
  4110.           (remote (substring cmsg (match-beginning 3) (match-end 3)))
  4111.           (address (if (match-beginning 4)
  4112.                (substring cmsg (match-beginning 4) (match-end 4))
  4113.                remote))
  4114.           (extra (cond
  4115.                ((not (string= (upcase remote) (upcase address)))
  4116.             (concat "(" address ")"))
  4117.                ((string-match
  4118.              "^\\([^ ]+\\) +\\([0-9]+\\)S +\\([0-9]+\\)C$"
  4119.              remote)
  4120.             (let ((x (subfield remote 1))
  4121.                   (s (string-to-int (subfield remote 2)))
  4122.                   (c (string-to-int (subfield remote 3))))
  4123.               (setq remote x)
  4124.               (format " (%d server%s, %d client%s)"
  4125.                   s
  4126.                   (if (= 1 s) "" "s")
  4127.                   c
  4128.                   (if (= 1 c) "" "s"))))
  4129.                (t "")))
  4130.           (p (cond
  4131.            ((string-match "^ *CLASS\\[\\([0-9]+\\)\\] +\\([^: ]+\\) *$"
  4132.                   lcl)
  4133.             (cons (subfield lcl 2) (subfield lcl 1)))
  4134.            ((string-match "^ *CLASS\\[\\([0-9]+\\)\\] *$" lcl)
  4135.             (cons srvr (subfield lcl 1)))
  4136.            (t (cons lcl nil))))
  4137.           (local (irc-nuke-whitespace (car p)))
  4138.           (class (cdr p))
  4139.           (lserv (irc-extract-hostname local))
  4140.           (rserv (irc-extract-hostname remote)))
  4141.      (if (and lserv (not (string= (upcase srvr) (upcase lserv))))
  4142.          (irc-remember lserv 'irc-servernames))
  4143.      (if (and rserv (not (string= (upcase srvr) (upcase rserv))))
  4144.          (irc-remember remote 'irc-servernames))
  4145.      (cond
  4146.        ((string= (upcase type) "LINK")
  4147.         (irc-insert "%s%s to %s%s goes through %s%s"
  4148.             irc-msg-info-pre
  4149.             type
  4150.             (upcase remote)
  4151.             extra
  4152.             (upcase local)
  4153.             irc-msg-info-post))
  4154.        ((and (string-match "\\(CHANOP\\|OPER\\|USER\\)" (upcase type))
  4155.          (numberp (string-match "^\\([^[]*\\)\\[\\([^: ]+\\)\\]$"
  4156.                     remote)))
  4157.         (let ((user (subfield remote 1))
  4158.           (cm (subfield remote 2)))
  4159.           (irc-remember user 'irc-nicknames)
  4160.           (if (stringp class)
  4161.           (irc-insert
  4162.            "%s%s of class %3s at server %s: \"%s\" (client on %s)%s"
  4163.            irc-msg-info-pre
  4164.            type
  4165.            class
  4166.            (upcase local)
  4167.            user
  4168.            (upcase cm)
  4169.            irc-msg-info-post)
  4170.           (irc-insert "%s%s at server %s: \"%s\" (client on %s)%s"
  4171.                   irc-msg-info-pre
  4172.                   type
  4173.                   (upcase local)
  4174.                   user
  4175.                   (upcase cm)
  4176.                   irc-msg-info-post))))
  4177.        ((and (string-match "\\(UNKNOWN\\)" (upcase type))
  4178.          (numberp (string-match "^\\([^[]*\\)\\[\\([^: ]+\\)\\]$"
  4179.                     remote)))
  4180.         (let ((cm (substring remote
  4181.                  (match-beginning 2)
  4182.                  (match-end 2))))
  4183.           (irc-insert (concat "%s%s at server %s from internet"
  4184.                   " host %s%s")
  4185.               irc-msg-info-pre
  4186.               (cond ((string= "UNKNOWN" (upcase type))
  4187.                  "Half open connection")
  4188.                 (t (concat "<Unknown type (%s) in function"
  4189.                        " irc-parse-notice, please"
  4190.                        " tell "
  4191.                        irc-hacker
  4192.                        ">")))
  4193.               (upcase local)
  4194.               (upcase cm)
  4195.               irc-msg-info-post)))
  4196.        (t (irc-insert "%s%s at server %s to%s server %s%s%s"
  4197.               irc-msg-info-pre
  4198.               (cond ((string= (upcase type) "CONNECTION")
  4199.                  "Serverlink")
  4200.                 ((string= (upcase type) "CONNECTING")
  4201.                  "Server-search")
  4202.                 (t type))
  4203.               (upcase local)
  4204.               (if (stringp class)
  4205.                   (format " class %3s" class)
  4206.                   "")
  4207.               (upcase remote)
  4208.               (downcase extra)
  4209.               irc-msg-info-post)))))
  4210.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\)"
  4211.                  " *No +response +from +"
  4212.                  "\\([^ ]+\\) *, *closing +link *$")
  4213.              cmsg)
  4214.        (irc-insert "%%Closed serverlink to %s due to lack of respone."
  4215.            (substring cmsg (match-beginning 2) (match-end 2)))
  4216.        (irc-later-execute-lusers))
  4217.       ((string-match (concat "^\\*\\*\\* *Class +\\([0-9]+\\) *"
  4218.                  "Entries *linked *: *\\([0-9]+\\) *$")
  4219.              cmsg)
  4220.        (let ((class (string-to-int (subfield cmsg 1)))
  4221.          (count (string-to-int (subfield cmsg 2))))
  4222.      (irc-insert "%s%s%d service%s linked for class %3d%s"
  4223.              irc-msg-info-pre
  4224.              parorg
  4225.              count
  4226.              (if (= 1 count) "" "s")
  4227.              class
  4228.              irc-msg-info-post)))
  4229.       ((string-match (concat "^\\([A-Za-z]+\\) +has +been +used +"
  4230.                  "\\([0-9]+\\) +times? +after +"
  4231.                  "startup *$")
  4232.              cmsg)
  4233.        (let ((cmd (substring cmsg (match-beginning 1) (match-end 1)))
  4234.          (cnt (substring cmsg (match-beginning 2) (match-end 2))))
  4235.      (irc-insert "%sServer %s has seen %s%s command%s of type %s%s"
  4236.              irc-msg-info-pre
  4237.              (upcase (if (string= srvr "") irc-server srvr))
  4238.              (make-string (max 0 (- 5 (length cnt))) ? )
  4239.              cnt
  4240.              (if (string= cnt "1") " " "s")
  4241.              cmd
  4242.              irc-msg-info-post)))
  4243.       ((string-match "^\\*\\*\\* *No +such +server *" cmsg)
  4244.        (let ((unknown (substring cmsg (match-end 0))))
  4245.      (irc-forget unknown 'irc-servernames)
  4246.      (irc-insert "%%%sNo such server: \"%s\"."
  4247.              (if (string= "" srvr)
  4248.              ""
  4249.              (concat "(" srvr ")"))
  4250.              unknown)))
  4251.       ((string-match (concat "^\\*\\*\\* *unknown \\([^: ]+\\) *==> *"
  4252.                  "\\([^: ]+\\) *$")
  4253.              cmsg)
  4254.        (irc-insert "%sUnknown connection at server %s to host %s%s"
  4255.            irc-msg-info-pre
  4256.            (upcase (substring cmsg (match-beginning 1) (match-end 1)))
  4257.            (upcase (substring cmsg (match-beginning 2) (match-end 2)))
  4258.            irc-msg-info-post))
  4259.       ((string-match (concat "^\\*\\*\\* *\\(User\\)?\\(ChanOp\\)?"
  4260.                  "\\(Oper\\)? +\\([^: ]+\\) *==> *"
  4261.                  "\\([^: ]*\\) *\\[\\(.\\|\n\\)*\\] *$")
  4262.              cmsg)
  4263.        (let* ((first (substring cmsg
  4264.                 (or (match-beginning 1) 0)
  4265.                 (or (match-end 1) 0)))
  4266.           (second (substring cmsg
  4267.                  (or (match-beginning 2) 0)
  4268.                  (or (match-end 2) 0)))
  4269.           (third (substring cmsg
  4270.                 (or (match-beginning 3) 0)
  4271.                 (or (match-end 3) 0)))
  4272.           (srvr (substring cmsg (match-beginning 4) (match-end 4)))
  4273.           (nick (substring cmsg (match-beginning 5) (match-end 5)))
  4274.           (client (substring cmsg (match-beginning 6) (match-end 6)))
  4275.           (type (cond ((not (string= "" first)) "User")
  4276.               ((not (string= "" second)) "Channel operator")
  4277.               ((not (string= "" third)) "IRC operator")
  4278.               (t "?UNKNOWN?"))))
  4279.      (irc-remember nick 'irc-nicknames)
  4280.      (irc-insert "%s%s at server %s: \"%s\" (client on %s)%s"
  4281.              irc-msg-info-pre
  4282.              type
  4283.              (upcase srvr)
  4284.              nick
  4285.              (upcase client)
  4286.              irc-msg-info-post)))
  4287.       ((string-match (concat "^\\(\\*\\*\\*\\)? *\\([0-9]+\\) +users* +"
  4288.                  "\\(have\\|has\\) +connection +to +the +"
  4289.                  "twilight +zone *$")
  4290.              cmsg)
  4291.        (let ((n (string-to-int (subfield cmsg 2))))
  4292.      (irc-insert "*** There %s %d enabled operator%s online."
  4293.              (if (= 1 n) "is" "are")
  4294.              n
  4295.              (if (= 1 n) "" "s"))))
  4296.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There \\(is\\|are\\) +"
  4297.                   "+\\([0-9]+\\) +channels*. *$")
  4298.               cmsg)
  4299.         (let ((n (string-to-int (subfield cmsg 3))))
  4300.       (irc-insert "*** There %s %d channel%s."
  4301.               (if (= 1 n) "is" "are")
  4302.               n
  4303.               (if (= 1 n) "" "s"))))
  4304.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There \\(is\\|are\\) +"
  4305.                   "+\\([0-9]+\\) +clients* +connected +"
  4306.                   "to +\\([^ ,]+\\).*$")
  4307.               cmsg)
  4308.         (let ((n (string-to-int (subfield cmsg 3)))
  4309.           (s (subfield cmsg 4)))
  4310.       (irc-insert "*** There %s %d client%s on %s."
  4311.               (if (= 1 n) "is" "are")
  4312.               n
  4313.               (if (= 1 n) "" "s")
  4314.               s)))
  4315.       ((string-match "^###" cmsg)
  4316.        (let ((m (substring cmsg (match-end 0))))
  4317.      (irc-insert "###%s%s"
  4318.              (if (or (string= "" srvr)
  4319.                  (string= (upcase srvr) (upcase irc-server)))
  4320.              ""
  4321.              (concat "(" srvr ")"))
  4322.              m)))
  4323.       ((string-match (concat "^\\*\\*\\* *welcome +to +the +internet +"
  4324.                  "relay +network *, *\\([^: ]+\\) *$")
  4325.              cmsg)        ;v2.4 welcome message
  4326.        (let ((user (subfield cmsg 1)))
  4327.      (irc-remember user 'irc-nicknames)))
  4328.       ((string-match (concat "^\\*\\*\\* *Your +host +is +"
  4329.                  "\\([^ ,]+\\) *, *running +version +"
  4330.                  "\\([^: ]+\\) *$")
  4331.              cmsg)
  4332.        (let* ((s (subfield cmsg 1))
  4333.           (vrsn (subfield cmsg 2))
  4334.           (s (downcase (irc-extract-hostname s))) ;REAL GENERIC servername
  4335.           (cur-bufname (buffer-name (current-buffer)))
  4336.           (new-bufname (irc-host+port-to-buffer-name s irc-port))
  4337.           (pre-kludge nil))
  4338.      (setq-default irc-server s)
  4339.      (setq irc-server s)
  4340.      (if (string< cur-bufname new-bufname)
  4341.          (rename-buffer new-bufname))
  4342.      (if (not (string= (upcase srvr) (upcase s)))
  4343.          (irc-remember s 'irc-servernames))
  4344.      (if (or (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4345.                        "[^0-9]+\\([0-9]+\\)\\([^0-9]+\\)"
  4346.                        "\\([0-9]+\\)")
  4347.                    vrsn)
  4348.          (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4349.                        "[^0-9]+\\([0-9]+\\)\\(\\)")
  4350.                    vrsn)
  4351.          (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4352.                        "\\(\\)\\(\\)")
  4353.                    vrsn))
  4354.          (let* ((type nil)
  4355.             (major (subfield vrsn 2))
  4356.             (minor (subfield vrsn 3))
  4357.             (kludge (subfield vrsn 4))
  4358.             (edit (subfield vrsn 5))
  4359.             (minor (if (string= "" minor) 0 (string-to-int minor)))
  4360.             (edit (if (string= "" edit) 0 (string-to-int edit))))
  4361.            (if (string-match "^u" major)
  4362.            (setq type (format "%c" (aref major 0))
  4363.              major (substring major 1)))
  4364.            (setq irc-type-version type
  4365.              irc-major-version (string-to-int major)
  4366.              irc-minor-version minor
  4367.              pre-kludge kludge
  4368.              irc-edit-version edit)
  4369.            )
  4370.          (irc-insert "%%Failed parsing vrsn \"%s\" in irc-parse-notice."
  4371.              vrsn))
  4372.      (if (and (= irc-major-version 2)
  4373.           (= irc-minor-version 6)
  4374.           (not (string= (upcase pre-kludge) "PRE")))
  4375.          (setq irc-edit-version (+ 10000 irc-edit-version)))
  4376.      (irc-insert "")
  4377.      (irc-insert "*** Welcome to the IRC server at %s!" s)
  4378.      (irc-insert "*** The server's version is %s," vrsn)))
  4379.       ((string-match "^\\*\\*\\* *This +server +was +created +"
  4380.              cmsg)
  4381.        (irc-insert "*** and it was created %s."
  4382.            (substring cmsg (match-end 0))))
  4383.       ;; Hello message from a 2.2 server.
  4384.       ((string-match (concat "^\\*\\*\\* *Welcome +to +Internet +Relay +"
  4385.                  "Server *")
  4386.              cmsg)
  4387.        (let ((vrsn (irc-nuke-whitespace (substring cmsg (match-end 0)))))
  4388.      (if (string-match (concat "^[^0-9]*\\([0-9]+\\)\\.\\([0-9]+\\)"
  4389.                    "[^0-9]+\\([0-9]+\\)?.*$")
  4390.                vrsn)
  4391.          (let ((maj (substring vrsn (match-beginning 1) (match-end 1)))
  4392.            (min (substring vrsn (match-beginning 2) (match-end 2)))
  4393.            (edt (substring vrsn (match-beginning 3) (match-end 3))))
  4394.            (setq irc-major-version (string-to-int maj)
  4395.              irc-minor-version (string-to-int min)
  4396.              irc-edit-version (string-to-int edt))))
  4397.      (irc-send "MOTD")
  4398.      (irc-insert (concat "*** Welcome to the Internet Relay Chat server "
  4399.                  "version %s at %s!")
  4400.              vrsn
  4401.              irc-server)
  4402.      (set-buffer-modified-p (buffer-modified-p))))
  4403.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There +are +\\([0-9]+\\) +"
  4404.                  "users +\\(and +\\|(\\)?"
  4405.                  "\\([^0-9]*[0-9]+ invisible\\)?\\()\\)? *"
  4406.                  "on +\\([0-9]+\\) +servers *$")
  4407.              cmsg)
  4408.        (let* ((ucount (subfield cmsg 2))
  4409.           (sdelim (subfield cmsg 3))
  4410.           (invstr (subfield cmsg 4))
  4411.           (edelim (subfield cmsg 5))
  4412.           (scount (subfield cmsg 6))
  4413.           (inv (if (string= "" invstr)
  4414.                ""
  4415.                (concat " "  sdelim invstr edelim)))
  4416.           (n (string-to-int ucount)))
  4417.      (irc-insert "*** There %s %s user%s%s on %s server%s."
  4418.              (if (= n 1) "is" "are")
  4419.              ucount
  4420.              (if (= n 1) "" "s")
  4421.              inv
  4422.              scount
  4423.              (if (= (string-to-int scount) 1) "" "s"))))
  4424.       ((string-match (concat "^\\(\\*\\*\\*\\)? *There +are \\([0-9]+\\) +"
  4425.                  "yet +unknown +connections *$")
  4426.              cmsg)
  4427.        (let ((count (substring cmsg (match-beginning 2) (match-end 2))))
  4428.      (irc-insert "*** There %s yet %s unknown connection%s."
  4429.              (if (string= count "1") "is" "are")
  4430.              count
  4431.              (if (string= count "1") "" "s"))))
  4432.       ((string-match (concat "^\\(\\*\\*\\*\\)? *I +have +\\([0-9]+\\)"
  4433.                  " +clients +and \\([0-9]+\\) +servers *$")
  4434.              cmsg)
  4435.        (let* ((c (subfield cmsg 2))
  4436.           (s (subfield cmsg 3))
  4437.           (cn (string-to-int c))
  4438.           (sn (string-to-int s))
  4439.           (isare (if (= 1 cn) "is" "are"))
  4440.           (cstr (if (= 1 cn) "client" "clients"))
  4441.           (sstr (if (= 1 sn) "server" "servers")))
  4442.      (irc-insert "*** There %s %d %s and %d %s on this server."
  4443.              isare cn cstr sn sstr)))
  4444.       ((string-match (concat "^\\*\\*\\* +Notice *:?-?-? +Received +KILL"
  4445.                  " +message +for +\\([^ ]+\\).\\( +From [^ ]+\\)?"
  4446.                  " +Path: *")
  4447.              cmsg)
  4448.        (let* ((sender (substring cmsg (match-beginning 1) (match-end 1)))
  4449.           (f (subfield cmsg 2))
  4450.           (path (substring cmsg (match-end 0)))
  4451.           (from (cond ((string-match "^From " f)
  4452.                (substring cmsg (match-end 0)))
  4453.               ((irc-is-hostname f) f)
  4454.               (t ""))))
  4455.      (cond ((string-match "\\([^!]+\\)!?(\\([^ ]*\\) *<- *\\([^ ]*\\)) *$"
  4456.                   path)
  4457.         (let* ((at (subfield path 1))
  4458.                (old (subfield path 2))
  4459.                (new (subfield path 3))
  4460.                (local (irc-is-nickname old))
  4461.                (irc-msg-cont-used (make-string
  4462.                        (length (concat irc-msg-info-pre
  4463.                                "User "))
  4464.                        ? )))
  4465.           (irc-insert
  4466.            (concat "%s%s COLLIDED at %s, "
  4467.                (if local
  4468.                    "local user %s seen on link from %s%s"
  4469.                    "was on %s, now from %s%s"))
  4470.            irc-msg-info-pre
  4471.            sender
  4472.            (upcase (irc-nuke-whitespace at))
  4473.            (upcase (irc-nuke-whitespace old))
  4474.            (upcase (irc-nuke-whitespace new))
  4475.            irc-msg-info-post)))
  4476.            ((or (string-match "\\([^!]+\\)!\\([^=][^! ]*\\) +(\\(.*\\))$"
  4477.                   path)
  4478.             (string-match "\\([^!]+\\)!\\([^=][^! ]*\\) *\\(\\)$"
  4479.                   path))
  4480.         (let* ((s (subfield path 1))
  4481.                (o (subfield path 2))
  4482.                (m (subfield path 3))
  4483.                (site (irc-nuke-whitespace s))
  4484.                (oper (irc-nuke-whitespace o))
  4485.                (type (if (string-match "\\." oper)
  4486.                  "Server"
  4487.                  "Operator"))
  4488.                (m2 (irc-nuke-whitespace m))
  4489.                (mesg (if (string= "" m2) "" (concat " (" m2 ")"))))
  4490.           (if (string-match "\\." oper)
  4491.               (irc-remember oper 'irc-servernames)
  4492.               (irc-remember oper 'irc-nicknames))
  4493.           (irc-insert "%sOperator %s (@%s) /KILL'ed user %s%s%s"
  4494.                   irc-msg-info-pre
  4495.                   oper
  4496.                   site
  4497.                   sender
  4498.                   mesg
  4499.                   irc-msg-info-post))
  4500.         (irc-send (concat "WHOWAS :" sender)))
  4501.            (t (irc-insert "%sUser %s KILL'ed, path: %s%s"
  4502.                   irc-msg-info-pre
  4503.                   sender
  4504.                   path
  4505.                   irc-msg-info-post)))))
  4506.       ((or (string-match "^ *You +have +been +marked +as +being +away *$" cmsg)
  4507.        (string-match "^ *You +have +marked +as +being +away *$" cmsg))
  4508.        (if (string= srvr "")
  4509.        (irc-insert (concat "%sYou have been marked as being away,"
  4510.                    " use /HERE to revert the effect%s")
  4511.                irc-msg-info-pre
  4512.                irc-msg-info-post)))
  4513.       ((string-match "^ *You +are +no +longer +marked +as +being +away *$"
  4514.              cmsg)
  4515.        (if (string= srvr "")        ;Only display if from local server.
  4516.        (irc-insert "%sYou are no longer marked as being away%s"
  4517.                irc-msg-info-pre
  4518.                irc-msg-info-post)))
  4519.       ((string-match (concat "^ *\\([^: *]*\\) *"
  4520.                  "\\(tty[^: ]+"
  4521.                  "\\|pty/tty[^: ]+"
  4522.                  "\\|vt[0-9]+"
  4523.                  "\\|pt[^: ]+"
  4524.                  "\\|display"
  4525.                  "\\|console\\) *"
  4526.                  "\\([ -~]+\\)?.*$")
  4527.              cmsg)
  4528.        (let ((user (substring cmsg (match-beginning 1) (match-end 1)))
  4529.          (tty (substring cmsg (match-beginning 2) (match-end 2)))
  4530.          (remote (substring cmsg (match-beginning 3) (match-end 3))))
  4531.      (irc-insert "%s%s %s%s %s"
  4532.              user
  4533.              (make-string (max 0 (- 39 (length user))) ? )
  4534.              tty
  4535.              (make-string (max 0 (- 14 (length tty))) ? )
  4536.              remote)))
  4537.       ((string-match " *Nobody +logged +in +on +\\([^: ]+\\) *$" cmsg)
  4538.        (let* ((s (subfield cmsg 1))
  4539.           (server (irc-extract-hostname s)))
  4540.      (if (and (stringp server)
  4541.           (not (string= (upcase srvr) (upcase server))))
  4542.          (irc-remember server 'irc-servernames))
  4543.      (irc-insert (concat "%%No users logged in on the Internet node"
  4544.                  " which runs the IRC server %s at the moment.")
  4545.              server)))
  4546.       ((string-match "^ *\\(UserId +Terminal +Host\\) *$" cmsg)
  4547.        (let ((m (substring cmsg (match-beginning 1) (match-end 1))))
  4548.      (irc-insert (concat "Login name                              "
  4549.                  "TTY            Logged in from"))
  4550.      (irc-insert (concat "--------------------------------------- "
  4551.                  "-------------- --------------"))))
  4552.       ((string-match (concat "^\\*\\*\\* *\\(Notice\\)? *\\(:\\|--\\)?"
  4553.                  " *Connecti\\(ng\\|on\\) *to"
  4554.                  " +\\(.+\\) +activated.? *$")
  4555.              cmsg)
  4556.        (irc-insert "%s%sTrying to establish a serverlink to %s%s"
  4557.            irc-msg-info-pre
  4558.            parorg
  4559.            (upcase (substring cmsg (match-beginning 4) (match-end 4)))
  4560.            irc-msg-info-post))
  4561.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\)"
  4562.                  " *Failed *in *connecting *to"
  4563.                  " *\\([^: ]+\\) *: *Socket *is"
  4564.                  " *not *connected *.? *$")
  4565.              cmsg)
  4566.        (irc-insert (concat "%%%sFailed to establish a serverlink to %s;"
  4567.                " no active server at other end.")
  4568.            parorg
  4569.            (upcase
  4570.             (substring cmsg (match-beginning 2) (match-end 2)))))
  4571.       ((string-match (concat "^\\*\\*\\* *Notice *: *Connect +"
  4572.                  "to +host +\\(.\\|\n\\)* +failed *:")
  4573.              cmsg)
  4574.        (let* ((host (substring cmsg (match-beginning 1) (match-end 1)))
  4575.           (reason (substring cmsg (match-end 0)))
  4576.           (server (upcase (irc-extract-hostname host))))
  4577.      (irc-forget server 'irc-servernames) ;Just in case.
  4578.      (irc-insert "%%Failed to establish a serverlink to %s; %s."
  4579.              (upcase server)
  4580.              reason)))
  4581.       ((string-match (concat "^\\*\\*\\* Notice: Access denied (no such server"
  4582.                  " enabled) \\([^ ]+\\) *\\(\\[[^ ]+\\]\\)? *$")
  4583.              cmsg)
  4584.        (let ((claimed (substring cmsg (match-beginning 1) (match-end 1)))
  4585.          (truename (substring cmsg
  4586.                   (1+ (or (match-beginning 2) -1))
  4587.                   (1- (or (match-end 2) 1)))))
  4588.      (irc-insert (concat "%%Rejected attemp by internethost \"%s\"%s to"
  4589.                  " establish a serverlink; that host isn't enabled"
  4590.                  " in the configuration file.")
  4591.              (if (string= "" truename) claimed truename)
  4592.              (if (or (string= "" truename)
  4593.                  (string= (upcase claimed) (upcase truename)))
  4594.              ""
  4595.              (concat " (claiming to be \"" claimed "\")")))))
  4596.       ((string-match (concat "^ *\\*\\*\\* +Notice *: +No +"
  4597.                  "response +from +\\([^: ]+\\) +, +"
  4598.                  "closing +link *$")
  4599.              cmsg)
  4600.        (let ((removed-server (substring cmsg
  4601.                     (match-beginning 1)
  4602.                     (match-end 1))))
  4603.      (irc-forget removed-server 'irc-servernames)
  4604.      (irc-insert (concat "%%Failed to get any response whatsoever from"
  4605.                  " server %s, removing the serverlink to it.")
  4606.              removed-server))
  4607.        (irc-later-execute-lusers))
  4608.       ((or (string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4609.                  " *Max +buffering +limit +exceed"
  4610.                  " +for +\\([^ ]+\\)")
  4611.              cmsg)
  4612.        (string-match (concat "^ *\\*\\*\\* *Notice\\ *\\(:\\|--\\)"
  4613.                  " *SendQueued +called +for +a"
  4614.                  " +DEADSOCKET +\\([^: ]*\\) *"
  4615.                  "\\(:-(\\)? *$")
  4616.              cmsg))
  4617.        (let ((host (irc-extract-hostname (substring cmsg
  4618.                             (match-beginning 2)
  4619.                             (match-end 2)))))
  4620.      (irc-forget host 'irc-servernames)
  4621.      (irc-insert (concat "%%Closed serverlink to %s, max buffering limit"
  4622.                  " got exceeded.")
  4623.              (upcase host)))
  4624.        (irc-later-execute-lusers))
  4625.       ((string-match (concat "^ *\\*\\*\\* *Host +\\(.*\\) +is"
  4626.                  " +unknown *\\.* *$")
  4627.              cmsg)
  4628.        (irc-insert "%%Host \"%s\" is unknown."
  4629.            (upcase
  4630.             (substring cmsg (match-beginning 1) (match-end 1)))))
  4631.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *Connect +to +host"
  4632.                  " +\\(.+\\) +failed *: *\\(.+\\) *$")
  4633.              cmsg)
  4634.        (let ((h (subfield cmsg 1))
  4635.          (reason (subfield cmsg 2)))
  4636.      (irc-insert "%%Connect to host %s failed: %s" (upcase h) reason)))
  4637.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR +"
  4638.                  "from +\\(.*\\) *: *SUMMON +No +"
  4639.                  "such +host *( *\\(.\\|\n\\)* *) *found"
  4640.                  " *$")
  4641.              cmsg)
  4642.        (let* ((fld1 (subfield cmsg 1))
  4643.           (fld2 (subfield cmsg 2))
  4644.           (at-server (irc-extract-hostname fld1))
  4645.           (unknown-host (irc-extract-hostname fld2)))
  4646.      (if (and (string< "" at-server)
  4647.           (not (string= (upcase srvr) (upcase at-server))))
  4648.          (irc-remember at-server 'irc-servernames))
  4649.      (irc-insert (concat "%%Summon command failed as server %s doesn't"
  4650.                  " know of any Internet host called \"%s\".")
  4651.              (upcase fld1)
  4652.              fld2)))
  4653.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR"
  4654.                  " +from\\ +\\(.*\\) *: *Access +"
  4655.                  "denied *( *no +such +server +"
  4656.                  "enabled *) *")
  4657.              cmsg)
  4658.        (let ((complainer (subfield cmsg 1))
  4659.          (disabled (substring cmsg (match-end 0))))
  4660.      (if (and (irc-is-hostname complainer)
  4661.           (not (string= (upcase srvr) (upcase complainer))))
  4662.          (irc-remember complainer 'irc-servernames))
  4663.      (irc-insert (concat "%%Server %s refuses to accept serverlink from"
  4664.                  " host %s as that host isn't enabled in the"
  4665.                  " configuration. Use \"/STATS C %s\" to check"
  4666.                  " which hosts ARE enabled.")
  4667.              complainer
  4668.              disabled)))
  4669.       ((string-match (concat "^ *\\([^: ]+\\) +seems +to +have +"
  4670.                  "disabled +summoning")
  4671.              cmsg)
  4672.        (irc-insert "%%User %s@%s has disabled summoning."
  4673.            (substring cmsg (match-beginning 1) (match-end 1))
  4674.            srvnam))
  4675.       ((string-match (concat "^ *Summoning +user *\\([^: ]*\\) +"
  4676.                  "to +irc *$")
  4677.              cmsg)
  4678.        (irc-insert "%sSummoning user %s@%s to IRC%s"
  4679.            irc-msg-info-pre
  4680.            (substring cmsg (match-beginning 1) (match-end 1))
  4681.            srvnam
  4682.            irc-msg-info-post))
  4683.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4684.                  " *Link +\\(.*\\) +cancelled *,"
  4685.                  " *server +\\(.*\\) +already"
  4686.                  " +exists *$")
  4687.              cmsg)
  4688.        (let ((rhost (substring cmsg (match-beginning 2) (match-end 2)))
  4689.          (rsrvr (substring cmsg (match-beginning 3) (match-end 3))))
  4690.      (irc-insert (concat "%%Server %s %s tried to establish a serverlink"
  4691.                  " to us (%s). Refused as we already are linked.")
  4692.              rsrvr rhost irc-server)))
  4693.       ((string-match (concat "^ *Connect *: *Server +\\([^ ]+\\) +already"
  4694.                  " +exists +from +\\([^ ]+\\) *$")
  4695.              cmsg)
  4696.        (let ((other-side (subfield cmsg 1))
  4697.          (trying-side (subfield cmsg 2)))
  4698.      (irc-remember other-side 'irc-servernames)
  4699.      (irc-remember trying-side 'irc-servernames)
  4700.      (irc-insert "%%Server %s is already connected to %s"
  4701.              (upcase other-side)
  4702.              (upcase trying-side))))
  4703.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4704.                  " *ERROR +from +\\(.*\\) *:"
  4705.                  " *Server +\\(.*\\) +already +exists"
  4706.                  " *\\.?\\.?\\.? *$")
  4707.              cmsg)
  4708.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2)))
  4709.          (local (substring cmsg (match-beginning 3) (match-end 3))))
  4710.      (if (not (string= (upcase srvr) (upcase remote)))
  4711.          (irc-remember remote 'irc-servernames))
  4712.      (irc-insert (concat "%%Server %s refused to accept a serverlink from"
  4713.                  " %s, the servers are already connected.")
  4714.              (upcase remote)
  4715.              (if (string= (upcase local) (upcase irc-server))
  4716.              (concat "this server (" local ")")
  4717.              (concat "other server " local))))) 
  4718.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4719.                  " *Server +\\([^: ]+\\) +closed +the"
  4720.                  " +connection *.? *$")
  4721.              cmsg)
  4722.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2))))
  4723.      (irc-forget remote 'irc-servernames)
  4724.      (irc-insert "%%%sServerlink from %s closed by remote side."
  4725.              parorg
  4726.              (upcase remote))))
  4727.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4728.                  " *Access +denied *( *no +such"
  4729.                  " +server +enabled *) *")
  4730.              cmsg)
  4731.        (let* ((remote (substring cmsg (match-end 0)))
  4732.           (s (irc-extract-hostname remote))
  4733.           (server (if (stringp s) s ""))
  4734.           (rest (substring remote (length server)))
  4735.           (h (irc-nuke-whitespace rest))
  4736.           (host (upcase (if (string= "" h) server h))))
  4737.      (irc-insert (concat "%%Server %s (on host %s) tried to set up a"
  4738.                  " server-link to us (%s) but we refused as there"
  4739.                  " is no N line accepting that host/server"
  4740.                  " combination.")
  4741.              server host irc-server)))
  4742.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4743.                  " *Lost +server +connection +to"
  4744.                  " +\\(.*\\) *:")
  4745.              cmsg)
  4746.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2)))
  4747.          (reason (substring cmsg (match-end 0))))
  4748.      (irc-forget remote 'irc-servernames)
  4749.      (irc-insert "%%Lost serverlink to %s (%s)." (upcase remote) reason)
  4750.      (irc-later-execute-lusers)))
  4751.       ((string-match (concat "^ *Connect *: *Host +\\(.\\|\n\\)*"
  4752.                  " +not +listed +in +ircd?.conf *$")
  4753.              cmsg)
  4754.        (let ((host (substring cmsg (match-beginning 1) (match-end 1))))
  4755.      (irc-insert (concat "%%There is no host matching the description"
  4756.                  " \"%s\" in the servers (%s) configuration"
  4757.                  " file.")
  4758.              host irc-server)))
  4759.       ((string-match "^ *\\(.\\|\n\\)* *: *Privileged +command *$"
  4760.              cmsg)
  4761.        (irc-insert (concat "%%You must be an ENABLED IRC operator to use"
  4762.                " command \"%s\". Use /OPER to enable yourself.")
  4763.            (upcase (subfield cmsg 1))))
  4764.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR +"
  4765.                  "from +\\(.*\\) *: *SUMMON +No +"
  4766.                  "such +host *( *\\(.*\\) *) *found"
  4767.                  " *$")
  4768.              cmsg)
  4769.        (let ((complainer (subfield cmsg 1))
  4770.          (nonfound (subfield cmsg 2)))
  4771.      (if (not (string= (upcase srvr) (upcase complainer)))
  4772.          (irc-remember complainer 'irc-servernames))
  4773.      (irc-insert (concat "%%Command /SUMMON found as server \"%s\" doesn't"
  4774.                  " know about any server \"%s\".")
  4775.              complainer nonfound)))
  4776.       ((and (irc-is-hostname srvr)
  4777.         (string-match (concat "^ *User +\\(.\\|\n\\)* +not +logged"
  4778.                   " +in *$")
  4779.               cmsg))
  4780.        (irc-insert (concat "%%Command /SUMMON failed as no user called \"%s\""
  4781.                " is logged in at %s at the moment.")
  4782.            (subfield cmsg 1) (upcase srvr)))
  4783.       ((or (string-match "^\\*\\*\\* *Notice *:?-* *\\([^ ]*\\) *$" cmsg)
  4784.        (string-match "^\\*\\*\\* *\\([^ ]*\\) *$" cmsg)
  4785.        (string-match "^ *Notice *:?-* *\\([^ ]+\\) *$" cmsg)
  4786.        (string-match "^ *\\([CNIYQK] *:.*\\) *$" cmsg) ;/STATS C
  4787.        (string-match "^ *\\*\\*\\* *\\(.*\\) *$" cmsg))
  4788.        (let* ((b (or (match-beginning 1) 0))
  4789.           (e (or (match-end 1) b))
  4790.           (m (substring cmsg b e)))
  4791.      (irc-insert "%s%s%s%s%s%s"
  4792.              irc-msg-info-pre
  4793.              (if (or (string= rcvr "")
  4794.                  (string= (upcase rcvr) (upcase irc-nick-used)))
  4795.              ""
  4796.              (concat
  4797.               "To "
  4798.               (cond ((irc-is-nickname rcvr) "user ")
  4799.                 ((irc-is-channelname rcvr) "channel ")
  4800.                 ((irc-is-broadcastname rcvr) "server "))
  4801.               rcvr
  4802.               " "))
  4803.              (cond ((string= srvr "") "")
  4804.                ((or (string-match "^C:" m) (string-match "^N:" m))
  4805.                 parorg)
  4806.                (t (concat "from "
  4807.                       (if (irc-is-hostname srvr)
  4808.                       "server (user?)"
  4809.                       "user (server?)")
  4810.                       " "
  4811.                       srvr)))
  4812.              (if (and (string= srvr "")
  4813.                   (or (string= rcvr "")
  4814.                   (string= (upcase rcvr)
  4815.                        (upcase irc-nick-used))))
  4816.              ""
  4817.              ": ")
  4818.              m
  4819.              irc-msg-info-post)))
  4820.       ((or (string-match (concat "^[^: ]+ +[0-9]+ *[0-9]+ *[0-9]+ *"
  4821.                  "[0-9]+ *[0-9]+ +\\("
  4822.                  "Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun"
  4823.                  "\\) +")
  4824.              cmsg)
  4825.        (string-match (concat "^ *Link +SendQ +SendM +SendBytes"
  4826.                  " +RcveM +RcveBytes +Open +since"
  4827.                  " *$")
  4828.              cmsg))
  4829.        (irc-insert cmsg))
  4830. ;;;      ((string-match "^ *: *\\([^: ]+\\) +NOTICE +\\([^: ]+\\) *:" str)
  4831. ;;;       (let ((from (substring str (match-beginning 1) (match-end 1)))
  4832. ;;;         (to (substring str (match-beginning 2) (match-end 2)))
  4833. ;;;         (msg (substring str (match-end 0))))
  4834. ;;;     (setq retval (irc-parse-priv (concat ":" from " PRIVMSG " to
  4835. ;;;                          " :" msg)))))
  4836.       ((string-match "^\\(.*\\) +ToolZ V[0-9]+\\.[0-9]+[a-zA-Z]* *$" cmsg)
  4837.        (let ((m (subfield cmsg 1)))
  4838.      (if (string-match "^[ :;\\.?]*" m)
  4839.          (setq m (substring m (match-end 0))))
  4840.      (if (string-match "[ :;\\.?]*$" m)
  4841.          (setq m (substring m 0 (match-beginning 0))))
  4842.      (irc-insert "%sToolZ-notice from %s: %s%s"
  4843.              irc-msg-info-pre
  4844.              srvnam
  4845.              m
  4846.              irc-msg-info-post)))
  4847.       ((and (string= (upcase rcvr) (upcase irc-last-NOTICE-rcv))
  4848.         (string= (upcase srvr) (upcase irc-last-NOTICE-src)))
  4849.        (setq irc-last-NOTICE-rcv rcvr
  4850.          irc-last-NOTICE-src srvr)
  4851.        (let ((irc-msg-cont-used "    "))
  4852.      (irc-insert "*** %s" cmsg)))
  4853.       (t (setq irc-last-NOTICE-rcv rcvr
  4854.            irc-last-NOTICE-src srvr)
  4855.      (cond ((irc-is-nickname srvr)
  4856.         (irc-remember srvr 'irc-nicknames))
  4857.            ((irc-is-hostname srvr)
  4858.         (irc-remember srvr 'irc-servernames)))
  4859.      (irc-insert "")
  4860.      (let ((irc-msg-cont-used "       "))
  4861.        (irc-insert "****** %s %s says to %s:"
  4862.                (cond ((string= "" srvr) "Your")
  4863.                  ((irc-is-nickname srvr)
  4864.                   "User (or possible server)")
  4865.                  (t "Server (or possible user)"))
  4866.                (cond ((string= "" srvr) "server")
  4867.                  (t (concat "\"" srvr "\"")))
  4868.                (if (string= (upcase rcvr) (upcase irc-nick))
  4869.                "you"
  4870.                rcvr))
  4871.        (let ((irc-msg-cont-used "   "))
  4872.          (irc-insert "*** %s" cmsg)))))
  4873.     retval))
  4874.  
  4875.  
  4876. (defun irc-parse-pong (str)
  4877.   "Examine a PONG message from the IRC server.
  4878. Normaly the server should never send such a message, but when it does,
  4879. chances are there's a server name  given."
  4880.   (if (string-match "^PONG *\\([^: ]*\\)? *" str)
  4881.       (let* ((s (subfield str 1))
  4882.          (data (irc-nuke-whitespace (substring str (match-end 0))))
  4883.          (server (irc-extract-hostname s)))
  4884.     (if (irc-is-hostname server)
  4885.         (irc-remember server 'irc-servernames))
  4886.     (if data
  4887.         (irc-insert "%sServer %s says PONG, with message \"%s\"%s"
  4888.             irc-msg-info-pre
  4889.             server
  4890.             data
  4891.             irc-msg-info-post)
  4892.         (irc-insert "%sServer %s says PONG%s"
  4893.             irc-msg-info-pre
  4894.             server
  4895.             irc-msg-info-post)))))
  4896.  
  4897.  
  4898. (defun irc-parse-priv (str)
  4899.   "Examine a PRIVMSG message from the IRC server.
  4900. PRIVMSG is intended to be used for private message sent between users.
  4901. This is not always the case at the moment; servers will use it like either
  4902. NOTICE or MSG on occasion.
  4903.  
  4904. If it really is a private message, this function returns t if a signal should
  4905. be issued for the \"private\" event, nil otherwise."
  4906.   ;; This is really gross because it kludges in the fact that PRIVMSG can
  4907.   ;; be used to send notification of a change of channel topic.
  4908.  
  4909.   (if (not (string-match (concat "^ *: *\\([^: ]*\\) *PRIVMSG"
  4910.                  " *\\([^ ]*\\) +:")
  4911.              str))
  4912.       (progn
  4913.     (irc-insert "%%Unknown PRIVMSG seen in irc-parse-priv:")
  4914.     (irc-insert "%% \"%s\" (str)." str)
  4915.     (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  4916.       (let* ((from (substring str (match-beginning 1) (match-end 1))) 
  4917.          (to (substring str (match-beginning 2) (match-end 2)))
  4918.          (msg (substring str (match-end 0)))
  4919.          (time (if (and irc-message-stamp
  4920.                 (not (eq 'public irc-message-stamp)))
  4921.                (concat " (" (irc-get-time) ") ")
  4922.                ""))
  4923.          (hdr (format (format irc-msg-priv (+ 7 (length irc-channel)))
  4924.               time
  4925.               from
  4926.               "")))
  4927.     (cond ((and (irc-is-nickname from)
  4928.             (not (irc-recall to 'irc-subscribed-channels)))
  4929.            (irc-remember from 'irc-nicknames))
  4930.           ((irc-is-hostname from)
  4931.            (irc-remember from 'irc-servernames)))
  4932.     (cond
  4933.       ((and irc-ignore-automatic-warnings
  4934.         (string-match "^<Automatic +warning> +" msg))
  4935.        nil)
  4936.       ((irc-recall to 'irc-subscribed-channels)
  4937.        (irc-parse-public (concat ":" from " MSG :" msg) to))
  4938.       ((irc-recall from 'irc-ignored-ppl)
  4939.        (if (and (boundp 'irc-abusive-ignore)
  4940.             irc-abusive-ignore)
  4941.            (irc-send (concat "NOTICE "
  4942.                  from
  4943.                  " :You are being ignored by "
  4944.                  irc-nick-used))))
  4945.       ((string= (upcase to) (upcase irc-nick-used))
  4946.        (setq irc-last-private (concat from ":"))
  4947.        (let ((irc-msg-cont-used (make-string
  4948.                      (min (length hdr)
  4949.                       (/ (window-width
  4950.                           (get-buffer-window
  4951.                            (current-buffer)))
  4952.                          2))
  4953.                      ? )))
  4954.          (if (and (boundp 'irc-private-insert)
  4955.               irc-private-insert)
  4956.          (funcall irc-private-insert from to msg)
  4957.          (irc-insert (concat hdr (irc-clean-up-message msg))))
  4958.          (irc-signal from 'private)))
  4959.       ((irc-is-broadcastname to)
  4960.        (let ((irc-msg-cont-used (make-string
  4961.                      (min (length hdr)
  4962.                       (/ (window-width
  4963.                           (get-buffer-window
  4964.                            (current-buffer)))
  4965.                          2))
  4966.                      ? )))
  4967.          (irc-insert (concat hdr
  4968.                  "[BROADCAST to all users on IRC "
  4969.                  (if (= ?$ (aref to 0))
  4970.                      "server(s) "
  4971.                      "clients(s) on Internet host(s) ")
  4972.                  (upcase (substring to 1))
  4973.                  "] "
  4974.                  (irc-clean-up-message msg)))
  4975.          (irc-signal from 'wall)))
  4976.       (t (setq irc-last-private (concat from ":"))
  4977.          (let ((irc-msg-cont-used (make-string
  4978.                        (min (length hdr)
  4979.                         (/ (window-width
  4980.                         (get-buffer-window
  4981.                          (current-buffer)))
  4982.                            2))
  4983.                        ? )))
  4984.            (irc-insert "*** Private message to \"%s\" follows:" to)
  4985.            (if (and (boundp 'irc-private-insert)
  4986.             irc-private-insert)
  4987.            (funcall irc-private-insert from to msg)
  4988.            (irc-insert (concat hdr (irc-clean-up-message msg))))
  4989.            (irc-signal from 'private)))))))
  4990.  
  4991.  
  4992. (defun irc-parse-public (str &optional priv-chan)
  4993.   "Examine a MSG message from the IRC server.
  4994. MSG is sent when someone has sent a message to a channel.  In reality,
  4995. sometimes PRIVMSG is used but irc-parse-private should hand those off to
  4996. here.
  4997.  
  4998. This function returns t if a bell should be issued for the \"public\" or
  4999. \"backtalk\" events, nil otherwise."
  5000.   (let* ((user (substring str 1 (string-match " MSG :" str)))
  5001.      (rcvr (if priv-chan
  5002.            priv-chan
  5003.            (let ((clst (irc-recall-all 'irc-subscribed-channels)))
  5004.              ;; Find out which of the channel's is "MSG:able".
  5005.              (while (and clst (listp clst))
  5006.                (if (irc-is-multijoinable-channel (car clst))
  5007.                (setq clst (cdr clst))
  5008.                (setq clst (car clst))))
  5009.              ;; As THIS function was activated, we are listening to one
  5010.              ;; of the old type channels (42, +glbf) if priv-chan=nil.
  5011.              (if (not clst)
  5012.              "???"
  5013.              clst))))
  5014.      (msg (substring str (match-end 0)))
  5015.      (about-self (numberp (string-match
  5016.                    (concat "\\<"
  5017.                        (regexp-quote irc-nick-used)
  5018.                        "\\>")
  5019.                    msg)))
  5020.      (ismem (irc-recall user 'irc-ignored-ppl))
  5021.      (hdr (if ismem ""
  5022.           (format irc-msg-public
  5023.               (if (and irc-message-stamp
  5024.                    (not (eq 'private irc-message-stamp)))
  5025.                   (concat " (" (irc-get-time) ")")
  5026.                   "")
  5027.               user
  5028.               rcvr)))
  5029.      (irc-msg-cont-used (make-string
  5030.                  (min (length hdr)
  5031.                   (/ (window-width
  5032.                       (get-buffer-window (current-buffer)))
  5033.                      2))
  5034.                  ? )))
  5035.     ;; even here we can't guarantee that the sender has already been noted
  5036.     ;; someplace else like join or nick -- the sender might be someplace
  5037.     ;; else and sending to this channel with PRIVMSG.
  5038.     (irc-remember user 'irc-nicknames)
  5039.     (cond ((not ismem)            ;Not ignored?
  5040.        (progn (if (and (boundp 'irc-public-insert)
  5041.                irc-public-insert)
  5042.               (funcall irc-public-insert user rcvr msg)
  5043.               (irc-insert (concat hdr (irc-clean-up-message msg))))
  5044.           (or (irc-signal user 'public)
  5045.               (and about-self (irc-signal user 'backtalk))))))))
  5046.  
  5047.  
  5048. (defun irc-parse-quit (str)
  5049.   "Examine a QUIT message from the IRC server.
  5050. QUIT is used to tell of a user's departure from IRC.  It is currently sent
  5051. by the servers to those clients which are on the same channel as the
  5052. departing user.
  5053.  
  5054. This function returns t if a signal should be issued for the \"join\" event,
  5055. since it also signals someone leaving the channel.  It returns nil if no
  5056. bell should be issued."
  5057.   (if (not (or (string-match "^:? *\\([^ :]+\\)? +QUIT +\\([^ :]+\\) *: *" str)
  5058.            (string-match "^:? *\\([^ :]+\\)? +QUIT *\\(\\): *" str)))
  5059.       (progn (irc-insert "%%Unknown QUIT message in irc-parse-quit:")
  5060.          (irc-insert "%% \"%s\" (str)." str)
  5061.          (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  5062.       (let* ((u (subfield str 1))
  5063.          (user2 (subfield str 2))
  5064.          (c (irc-clean-up-message (irc-nuke-whitespace
  5065.                        (substring str (match-end 0)))))
  5066.          (user (if (string= "" u) irc-nick-used u))
  5067.          (myself (string= (upcase user) (upcase irc-nick-used)))
  5068.          (uc (upcase c))
  5069.          (comment (cond ((or (string= "" c)
  5070.                  (string= (upcase user) uc))
  5071.                  ": user quit")
  5072.                 ((string= "LEAVING" uc)
  5073.                  ": user quit, one ircII user less on IRC")
  5074.                 ((string= "BAD LINK?" uc)
  5075.                  ": link closed from client's side")
  5076.                 ((string-match "^\\([^.!]+\\)![A-Za-z][^ !]+$" c)
  5077.                  (format ": user quit past %s" (subfield c 1)))
  5078.                 ((string= "KILLED" uc)
  5079.                  ": killed")
  5080.                 ((string= "PING TIMEOUT" uc)
  5081.                  ": killed off due to inactivity")
  5082.                 ((string= "DEAD SOCKET" uc)
  5083.                  ": dead socket")
  5084.                 ((string= "WRITE ERROR" uc)
  5085.                  ": write error")
  5086.                 ((string-match
  5087.                   (concat "^\\([^ ]+\\.[^ .][^ ]*\\)"
  5088.                       " +\\([^ ]+\\.[^ .][^ ]*\\)$")
  5089.                   c)
  5090.                  (format ": netsplit past %s (lost %s)"
  5091.                      (subfield c 1)
  5092.                      (subfield c 2)))
  5093.                 ((string-match "^[^ ]+\\.[^ .][^ ]$" c)
  5094.                  (irc-remember c 'irc-servernames)
  5095.                  (concat ": netsplit just past " c))
  5096.                 (t (concat " (" c ")")))))
  5097.     (if (and (string< "" user2)
  5098.          (not (string= (upcase user) (upcase user2)))
  5099.          (boundp 'debug-on-error)
  5100.          debug-on-error)
  5101.         (irc-insert (concat "%sirc-parse-quit: secondary user to QUIT"
  5102.                 " differed, user=\"%s\", user2=\"%s\"%s")
  5103.             irc-msg-info-pre user user2 irc-msg-info-post))
  5104.     (irc-forget user 'irc-nicknames)
  5105.     (if (and (not (irc-recall user 'irc-ignored-ppl))
  5106.          (memq 'quit irc-events))
  5107.         (progn (irc-insert "%s%s left IRC%s%s"
  5108.                irc-msg-info-pre
  5109.                (if myself "You" user)
  5110.                comment
  5111.                irc-msg-info-post)
  5112.            ;; currently just the join event; some modification will
  5113.            ;; need to be made here when/if Jarkko has QUIT sent to
  5114.            ;; everyone,not just the channel 
  5115.            (irc-signal user 'join))))))
  5116.  
  5117.  
  5118. (defun irc-parse-RPL (str)
  5119.   "Examine a numeric RPL_ message from the IRC server.
  5120. Numeric control messages are used by newer servers to aid in generalized
  5121. client design; while people are converting to the new servers the older
  5122. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5123. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5124. in the IRC source file numeric.h.
  5125.  
  5126. Note well that some things are still going to come out wrong because the
  5127. servers are currently still doing things inconsistently."
  5128.   (if (string-match "^:?[^: ]+ +\\([023]\\)[0-9][0-9] +" str)
  5129.       (let ((n (string-to-int (subfield str 1))))
  5130.     (cond ((= n 3) (irc-parse-RPL-3xx str))
  5131.           ((= n 2) (irc-parse-RPL-2xx str))
  5132.           (t (irc-parse-RPL-0xx str))))
  5133.       (progn 
  5134.     (irc-insert "%%Function irc-parse-RPL called with non-RPL:")
  5135.     (irc-insert "%% \"%s\" (str)" str)
  5136.     (irc-insert "%% Please tell %s." irc-hacker))))
  5137.  
  5138.  
  5139. (defun irc-parse-RPL-0xx (str)
  5140.   "Examine a numeric RPL_ message from the IRC server.
  5141. Numeric control messages are used by newer servers to aid in generalized
  5142. client design; while people are converting to the new servers the older
  5143. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5144. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5145. in the IRC source file numeric.h.
  5146.  
  5147. Note well that some things are still going to come out wrong because the
  5148. servers are currently still doing things inconsistently."
  5149.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5150.                 "\\([^: ]+\\)? +:?")
  5151.             str)
  5152.       ;; we assume that the server and message are consistent for us; just
  5153.       ;; worry about the numeric value and the rest of the line
  5154.       (let* ((origin (subfield str 1))
  5155.          (num (string-to-int (subfield str 2)))
  5156.          (user (subfield str 3))
  5157.          (txt (substring str (match-end 0)))
  5158.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5159.              ""
  5160.              (concat "(" origin ") ")))
  5161.          tmp1 tmp2 tmp3 tmp4)
  5162.     (irc-remember origin 'irc-servernames)
  5163.     (cond
  5164.       ((= num 001)
  5165.        )
  5166.       ((= num 002)
  5167.        (irc-parse-notice (format "NOTICE %s :*** %s" user txt)))
  5168.       ((= num 003)
  5169.        (irc-parse-notice (format "NOTICE %s :*** %s" user txt)))
  5170.       ((= num 004)
  5171.        (irc-insert "*** FEATURES: %s" txt))
  5172.       (t                                 ; default
  5173.        (irc-insert (concat "%%Unrecognized numeric RPL 0xx message; "
  5174.                    "please tell %s:")
  5175.                irc-hacker)
  5176.        (irc-insert "%% str=\"%s\"." str)
  5177.        (irc-insert "%% Function irc-parse-RPL-0xx."))))
  5178.       ;; else
  5179.       (irc-insert (concat "%%Unrecognized nonnumeric RPL 0xx message follows; "
  5180.               "please tell %s:")
  5181.           irc-hacker)
  5182.       (irc-insert "%% \"%s\"." str)
  5183.       (irc-insert "%% Function irc-parse-RPL-0xx."))
  5184.   nil)
  5185.  
  5186.  
  5187. (defun irc-parse-RPL-2xx (str)
  5188.   "Examine a numeric RPL_ message from the IRC server.
  5189. Numeric control messages are used by newer servers to aid in generalized
  5190. client design; while people are converting to the new servers the older
  5191. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5192. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5193. in the IRC source file numeric.h.
  5194.  
  5195. Note well that some things are still going to come out wrong because the
  5196. servers are currently still doing things inconsistently."
  5197.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5198.                 "\\([^: ]+\\)? +:?")
  5199.             str)
  5200.       ;; we assume that the server and message are consistent for us; just
  5201.       ;; worry about the numeric value and the rest of the line
  5202.       (let* ((origin (subfield str 1))
  5203.          (num (string-to-int (subfield str 2)))
  5204.          (user (subfield str 3))
  5205.          (txt (substring str (match-end 0)))
  5206.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5207.              ""
  5208.              (concat "(" origin ") ")))
  5209.          tmp1 tmp2 tmp3 tmp4)
  5210.     (irc-remember origin 'irc-servernames)
  5211.     (cond
  5212.       ((= num 200)
  5213.        (cond ((string-match
  5214.            "^ *Link +\\([^ ]+\\) *:?\\([^ ]+\\) *:?\\([^ ]+\\)? *$"
  5215.            txt)
  5216.           (let ((vrsn (subfield txt 1))
  5217.             (goal (subfield txt 2))
  5218.             (next (subfield txt 3)))
  5219.             (irc-insert "%sLink to %s passes %s<%s>%s%s"
  5220.                 irc-msg-info-pre
  5221.                 (upcase goal)
  5222.                 (upcase origin)
  5223.                 (upcase vrsn)
  5224.                 (if (string= "" next)
  5225.                     ""
  5226.                     (concat "; next:" next))
  5227.                 irc-msg-info-post)))
  5228.          (t (irc-insert "%%Unknown RPL200 received in irc-parse-RPL-2xx:")
  5229.             (irc-insert "%% \"%s\" (txt)." txt)
  5230.             (irc-insert "%% Please tell %s, this might be a bug."
  5231.                 irc-hacker))))
  5232.       ((or (= num 201)        ; RPL_TRACECONNECTING "Try."
  5233.            (= num 202))        ; RPL_TRACEHANDSHAKE
  5234.        (cond ((string-match "^\\([^ ]+\\) +\\([0-9]+\\) +:?\\([^ ]+\\)"
  5235.                 txt)
  5236.           (let* ((type (subfield txt 1))
  5237.              (class (subfield txt 2))
  5238.              (host (subfield txt 3))
  5239.              (utype (upcase type))
  5240.              (state (cond ((string= "TRY." utype)
  5241.                        "trying to connect to it")
  5242.                       ((string= "H.S." utype)
  5243.                        "registering us as server at it")
  5244.                       (t type))))
  5245.             (irc-insert "%s%sClass %3s half: %s (%s)%s"
  5246.                 irc-msg-info-pre
  5247.                 parorg class (upcase host) state
  5248.                 irc-msg-info-post)))
  5249.          (t (irc-insert "%%Received unknown RPL%d in irc-parse-RPL-2xx:"
  5250.                 num)
  5251.             (irc-insert "%% \"%s\" (txt)." txt)
  5252.             (irc-insert "%% Please tell %s, it might be a bug."
  5253.                 irc-hacker))))
  5254.       ((or (= num 203)        ; RPL_TRACEUNKNOWN
  5255.            (= num 204)        ; RPL_TRACEOPERATOR "Oper"
  5256.            (= num 205))        ; RPL_TRACEUSER "User"
  5257.        (cond ((string-match (concat "^\\([^ ]+\\) +\\(-?[0-9]+\\) *:?"
  5258.                     "*\\([^ ]*\\)\\[\\(.+\\)\\] *"
  5259.                     ":?[0-9]*")
  5260.                 txt)
  5261.           (let* ((type (subfield txt 1))
  5262.              (class (subfield txt 2))
  5263.              (u (subfield txt 3))
  5264.              (cm (subfield txt 4))
  5265.              (user (irc-nuke-whitespace u)))
  5266.             (if (string< "" user)
  5267.             (irc-remember user 'irc-nicknames))
  5268.             (irc-insert "%s%sClass %3s %s: \"%s\" (client on %s)%s"
  5269.                 irc-msg-info-pre
  5270.                 parorg
  5271.                 class
  5272.                 (downcase type)
  5273.                 user
  5274.                 (upcase cm)
  5275.                 irc-msg-info-post)))
  5276.          (t (irc-insert
  5277.              "%%Unknown RPL203:205 seen, in irc-parse-RPL-2xx:")
  5278.             (irc-insert "%% \"%s\" (str); \"%s\" (txt)." str txt)
  5279.             (irc-insert "%% Please tell %s, it might be a bug."
  5280.                 irc-hacker))))
  5281.       ((= num 206)            ; RPL_TRACESERVER "Serv"
  5282.        (if (or (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) +\\(\\)"
  5283.                      "\\([0-9]+\\)S +\\([0-9]+\\)C +:? *"
  5284.                      "\\([^ ]+\\) *$")
  5285.                  txt)
  5286.            (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) +"
  5287.                      "\\([^ ]+\\) +\\([0-9]+\\)S *:?"
  5288.                      " *\\([0-9]+\\)C *$")
  5289.                  txt)
  5290.            (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) *"
  5291.                      ":? *\\(.+\\) *\\(\\)\\(\\)$")
  5292.                  txt))
  5293.            (let* ((type (subfield txt 1))
  5294.               (class (subfield txt 2))
  5295.               (r (subfield txt 3))
  5296.               (ns (string-to-int (subfield txt 4)))
  5297.               (nc (string-to-int (subfield txt 5)))
  5298.               (remote (if (string= "" r) (subfield txt 6) r)))
  5299.          (irc-remember remote 'irc-servernames)
  5300.          (irc-insert "%s%sClass %3s %s: %s%s%s"
  5301.                  irc-msg-info-pre
  5302.                  parorg
  5303.                  class
  5304.                  (downcase type)
  5305.                  (upcase remote)
  5306.                  (if (and (= ns 0) (= nc 0))
  5307.                  ""
  5308.                  (format " (%d server%s, %d client%s)%s"
  5309.                      ns
  5310.                      (if (= 1 ns) "" "s")
  5311.                      nc
  5312.                      (if (= 1 nc) "" "s")))
  5313.                  irc-msg-info-post))
  5314.            (progn
  5315.          (irc-insert "%%Unknown RPL206 received in irc-parse-RPL-2xx:")
  5316.          (irc-insert "%% \"%s\" (txt)." txt)
  5317.          (irc-insert "%% Please tell %s, it might be a bug."
  5318.                  irc-hacker))))
  5319.       ;; Missing 207 RPL_TRACESERVICE
  5320.       ;; Missing 208 RPL_TRACENEWTYPE
  5321.       ((= num 209)            ; RPL_TRACECLASS
  5322.        (cond ((string-match (concat "^Class +\\([0-9]+\\) *"
  5323.                     ":? *\\([0-9]+\\) *$")
  5324.                 txt)
  5325.           (let ((class (string-to-int (subfield txt 1)))
  5326.             (count (string-to-int (subfield txt 2))))
  5327.             (irc-insert
  5328.              "%s%s%d service%s linked for class %3d%s"
  5329.              irc-msg-info-pre
  5330.              parorg
  5331.              count
  5332.              (if (= 1 count) "" "s")
  5333.              class
  5334.              irc-msg-info-post)))
  5335.          (t (irc-insert "%%Unknown RPL209 message in irc-parse-RPL-2xx:")
  5336.             (irc-insert "%% \"%s\" (txt)" txt)
  5337.             (irc-insert "%% Please tell %s, it might be a bug."
  5338.                 irc-hacker))))
  5339.       ((= num 211)            ;L-lines
  5340.        (cond ((string-match (concat "^\\([^: ]+\\) +\\([0-9]+\\) +"
  5341.                     "\\([0-9]+\\) +\\([0-9]+\\) +"
  5342.                     "\\([0-9]+\\) +\\([0-9]+\\) +"
  5343.                     ": *\\(.*\\) *$")
  5344.                 txt)
  5345.           (let* ((link (subfield txt 1))
  5346.              (sendq (subfield txt 2))
  5347.              (sendm (subfield txt 3))
  5348.              (sendbytes (subfield txt 4))
  5349.              (rcvem (subfield txt 5))
  5350.              (rcvebytes (subfield txt 6))
  5351.              (rest (subfield txt 7))
  5352.              (irc-msg-cont-used
  5353.               "                                                 "))
  5354.             (irc-insert "%8s %8s %10s %8s %10s %s"
  5355.                 sendq sendm sendbytes rcvem rcvebytes rest)
  5356.             (irc-insert "%s(to %s)" irc-msg-cont-used (upcase link))))
  5357.          ((string-match (concat "^ *\\(Link +\\)?SendQ +SendM"
  5358.                     " +SendBytes +RcveM +RcveBytes"
  5359.                     " +:Open since *$")
  5360.                 txt)
  5361.           (irc-insert (concat
  5362.                    " SendQue   S-Msgs    S-Bytes   R-Msgs"
  5363.                    "    R-Bytes Date (to link)"))
  5364.           (irc-insert (concat
  5365.                    "-------- -------- ---------- --------"
  5366.                    " ---------- --------------")))
  5367.          (t (irc-insert "%%Unknown RPL211, in irc-parse-RPL-2xx:")
  5368.             (irc-insert "%% \"%s\" (txt)." txt)
  5369.             (irc-insert "%% Please tell %s, it might be a bug."
  5370.                 irc-hacker))))
  5371.       ((= num 212)            ;RPL_STATSCOMMANDS (ie non CIKLQY)
  5372.        (cond ((string-match "^\\([^ ]+\\) +:?\\([0-9]+\\) *\\([0-9]+\\)?$"
  5373.                 txt)
  5374.           (let* ((type (subfield txt 1))
  5375.              (count (subfield txt 2))
  5376.              (rcount (subfield txt 3))
  5377.              (n (string-to-int count))
  5378.              (rn (string-to-int rcount))
  5379.              (c (concat (make-string (max 0 (- 5 (length count)))
  5380.                          ? )
  5381.                     count))
  5382.              (cmds (if (= n 1) "command " "commands")))
  5383.             (irc-insert "%sServer %s has seen %s %s of type %s%s%s"
  5384.                 irc-msg-info-pre
  5385.                 (upcase origin)
  5386.                 c
  5387.                 cmds
  5388.                 (upcase type)
  5389.                 (if (string= "" rcount)
  5390.                     ""
  5391.                     (format " %s(%d remote?)"
  5392.                         (make-string (- 7 (length type))
  5393.                              ? )
  5394.                         rn))
  5395.                 irc-msg-info-post)))
  5396.          (t (irc-insert
  5397.              "%%Unknown RPL212 message received in irc-parse-RPL-2xx:")
  5398.             (irc-insert "%% \"%s\" (txt)." txt)
  5399.             (irc-insert "%% Please tell %s, it might be a bug."
  5400.                 irc-hacker))))
  5401.       ((or (= num 213)        ;C-lines
  5402.            (= num 214)        ;N-lines
  5403.            (= num 215)        ;I-lines
  5404.            (= num 216)        ;K-lines
  5405.            (= num 217)        ;Q-lines
  5406.            (= num 241)        ;L-lines
  5407.            (= num 242)        ;Uptime
  5408.            (= num 243)        ;O-lines
  5409.            (= num 244)        ;H-lines
  5410.            (= num 249)        ;other such lines
  5411.            )
  5412.        (cond ((string= (upcase origin) (upcase irc-server))
  5413.           (irc-insert "*** %s" txt))
  5414.          (t (irc-insert "*** (%s): %s" origin txt))))
  5415.       ((= num 218)            ;Y-lines
  5416.        (cond ((string-match
  5417.            (concat "^ *Y +\\([0-9]+\\) +\\([0-9]+\\) +\\([0-9]+\\) +:?"
  5418.                " *\\([0-9]+\\) +:?\\([0-9]+\\)")
  5419.            txt)
  5420.           (let* ((class (subfield txt 1))
  5421.              (ping-freq (subfield txt 2))
  5422.              (conn-freq (subfield txt 3))
  5423.              (max-links (subfield txt 4))
  5424.              (plur (if (= 1 (string-to-int max-links)) "" "s"))
  5425.              (sendq (subfield txt 5))
  5426.              (pre (format (concat "*** %sClass: %s, conn. freq."
  5427.                           " %ss, ping freq. %ss, ")
  5428.                       parorg class conn-freq ping-freq))
  5429.              (irc-msg-cont-used (make-string (length pre) ? )))
  5430.             (irc-insert "%smax# %s link%s, SendQ %s."
  5431.                 pre
  5432.                 max-links
  5433.                 plur
  5434.                 sendq)))
  5435.          (t (irc-insert "%%Unknown RPL218 in irc-parse-RPL-2xx:")
  5436.             (irc-insert "%% \"%s\" (txt)." txt)
  5437.             (irc-insert "%% Please tell %s, it might be a bug."
  5438.                 irc-hacker))))
  5439.       ((= num 219)
  5440.        (irc-insert "%sSTATS listing for server %s done%s"
  5441.                irc-msg-info-pre
  5442.                (upcase origin)
  5443.                irc-msg-info-post)
  5444.        (irc-insert ""))
  5445.       ((= num 221)
  5446.        (let ((i (1- (length txt)))
  5447.          (ut (upcase txt)))
  5448.          (while (and (>= i 0) (not (= ?O (aref ut i))))
  5449.            (setq i (1- i)))
  5450.          (while (and (>= i 0)
  5451.              (not (= ?- (aref ut i)))
  5452.              (not (= ?+ (aref ut i))))
  5453.            (setq i (1- i)))
  5454.          (setq irc-operator (if (and (>= i 0) (= ?+ (aref ut i)))
  5455.                      " IOPR"
  5456.                      nil)))
  5457.        (irc-insert "%sUser %s'%s mode%s: %s%s"
  5458.                irc-msg-info-pre
  5459.                user
  5460.                (if (= ?S (aref (upcase user) (1- (length user))))
  5461.                ""
  5462.                "s")
  5463.                (if (= 2 (length txt)) " is" "s are")
  5464.                (irc-explain-user-mode txt 'no-direction)
  5465.                irc-msg-info-post))
  5466. ;;;      ((= num 232)
  5467. ;;;       (irc-insert "DEBUG: RPL232 txt=\"%s\"." txt))
  5468. ;;;      ((= num 241) SEE RPL213-217
  5469. ;;;       )
  5470. ;;;      ((= num 242) SEE RPL213-217
  5471. ;;;       )
  5472. ;;;      ((= num 243) SEE RPL213-217
  5473. ;;;       )
  5474. ;;;      ((= num 244) SEE RPL213-217
  5475. ;;;       )
  5476. ;;;      ((= num 249) SEE RPL213-217
  5477. ;;;       )
  5478.       ((= num 250)
  5479.        (irc-insert "*** %s" txt))
  5480.       ((= num 251)
  5481.        (irc-insert "*** %s" txt))
  5482.       ((= num 252)
  5483.        (cond ((string-match "^\\([0-9]+\\) +:operator.*online$" txt)
  5484.           (irc-parse-notice (format (concat
  5485.                          "NOTICE %s :*** %s users have"
  5486.                          " connection to the twilight"
  5487.                          " zone")
  5488.                         user (subfield txt 1))))
  5489.          ((string-match "^\\([^ :]+\\) *: *\\(.*\\)$" txt)
  5490.           (irc-insert "*** %s %s" (subfield txt 1) (subfield txt 2)))
  5491.          (t (irc-insert "*** %s" txt))))
  5492.       ((= num 253)
  5493.        (if (string-match "^\\([0-9]+\\) *:unknown connection(?s?)?" txt)
  5494.            (let ((n (string-to-int (subfield txt 1))))
  5495.          (irc-insert "*** There %s %d %s of (yet) unknown %s."
  5496.                  (if (= 1 n) "is" "are")
  5497.                  n
  5498.                  (if (= 1 n) "connection" "connections")
  5499.                  (if (= 1 n) "type" "types")))
  5500.            (progn (irc-insert "%%Unrecognized RPL 253 message seen:")
  5501.               (irc-insert "%% \"%s\" (txt)" txt)
  5502.               (irc-insert "%% Please tell %s" irc-hacker))))
  5503.       ((= num 254)
  5504.        (if (string-match "^\\([0-9]+\\) :channel" txt)
  5505.            (irc-parse-notice (format (concat "NOTICE %s :*** There are %s"
  5506.                          " channels.")
  5507.                      user (subfield txt 1)))
  5508.            (irc-insert "*** %s" txt)))
  5509.       ((= num 255)            ;"I have 77 clients, 0 services and 1 servers"
  5510.        (let ((text (if (string-match "^I have \\(.*\\)" txt)
  5511.                (format "%s has %s"
  5512.                    (upcase origin)
  5513.                    (subfield txt 1))
  5514.              txt)))
  5515.          (irc-insert "*** %s" text)))
  5516.       ((= num 256)            ;RPL admin, first line
  5517.        (irc-insert "### %s" txt))
  5518.       ((= num 257)            ;RPL admin, second line
  5519.        (irc-insert "### %s" txt))
  5520.       ((= num 258)            ;RPL admin, third line
  5521.        (irc-insert "### %s" txt))
  5522.       ((= num 259)            ;RPL admin, fourth and last line
  5523.        (irc-insert "### %s" txt)
  5524.        (irc-insert "%sEnd of ADMIN for %s%s"
  5525.                irc-msg-info-pre origin irc-msg-info-post)
  5526.        (irc-insert ""))
  5527.       ((= num 261)            ;RPL log file
  5528.        (if (string-match "^File +\\(.+\\) +:\\([0-9]+\\)$"
  5529.                  txt)
  5530.            (let ((file (subfield txt 1))
  5531.              (dbglvl (subfield txt 2)))
  5532.          (irc-insert
  5533.           "%s%sThe servers log file for debug level %s is %s%s"
  5534.           irc-msg-info-pre
  5535.           parorg
  5536.           dbglvl
  5537.           file
  5538.           irc-msg-info-post))
  5539.            (progn (irc-insert "%%Unknown RPL 261 seen:")
  5540.               (irc-insert "%% \"%s\" (txt)" txt)
  5541.               (irc-insert "%% Please tell %s" irc-hacker))))
  5542.       ((= num 262)
  5543.        (if (string-match "\\([^ ]+\\) +\\([^ ]+\\)\\.? *: *\\(.*\\)" txt)
  5544.            (irc-insert "%%%s for %s who's using a server of version %s"
  5545.                (subfield txt 3)
  5546.                (subfield txt 1)
  5547.                (subfield txt 2))
  5548.          (irc-insert "%%%s" txt)))
  5549.       ((= num 265)
  5550.        (irc-insert "*** %s" txt))
  5551.       ((= num 266)
  5552.        (irc-insert "*** %s" txt))
  5553.       (t                                 ; default
  5554.        (irc-insert (concat "%%Unrecognized numeric RPL 2xx message; "
  5555.                    "please tell %s:")
  5556.                irc-hacker)
  5557.        (irc-insert "%% str=\"%s\"." str)
  5558.        (irc-insert "%% Function irc-parse-RPL-2xx."))))
  5559.       ;; else
  5560.       (irc-insert (concat "%%Unrecognized nonnumeric RPL 2xx message follows; "
  5561.               "please tell %s:")
  5562.           irc-hacker)
  5563.       (irc-insert "%% \"%s\"." str)
  5564.       (irc-insert "%% Function irc-parse-RPL-2xx."))
  5565.   nil)
  5566.  
  5567.  
  5568. (defun irc-parse-RPL-3xx (str)
  5569.   "Examine a numeric RPL_ message from the IRC server.
  5570. Numeric control messages are used by newer servers to aid in generalized
  5571. client design; while people are converting to the new servers the older
  5572. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5573. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5574. in the IRC source file numeric.h.
  5575.  
  5576. Note well that some things are still going to come out wrong because the
  5577. servers are currently still doing things inconsistently."
  5578.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5579.                 "\\([^: ]+\\)? +:?")
  5580.             str)
  5581.       ;; we assume that the server and message are consistent for us; just
  5582.       ;; worry about the numeric value and the rest of the line
  5583.       (let* ((origin (subfield str 1))
  5584.          (num (string-to-int (subfield str 2)))
  5585.          (user (subfield str 3))
  5586.          (txt (substring str (match-end 0)))
  5587.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5588.              ""
  5589.              (concat "(" origin ") ")))
  5590.          tmp1 tmp2 tmp3 tmp4)
  5591.     (irc-remember origin 'irc-servernames)
  5592.     (cond
  5593.      ((= num 301)                       ; RPL_AWAY
  5594.       (cond ((string-match "^\\([^: ]+\\) :" txt)
  5595.          (let ((nick (subfield txt 1))
  5596.                (msg (substring txt (match-end 0))))
  5597.            (irc-remember nick 'irc-nicknames)
  5598.            (irc-insert "%%User %s is away (%s)."
  5599.                    nick
  5600.                    (irc-clean-up-message msg))))
  5601.         (t (irc-insert (concat "%%One of the last persons you sent to"
  5602.                        " is away, delivered your"
  5603.                        " message anyway.")))))
  5604.      ((= num 302)                 ; RPL_USERHOST
  5605.       (let ((s txt))
  5606.         (while (string-match
  5607.             (concat "^\\([^ =*]+\\)\\(\\*?\\)=\\([+-]\\)"
  5608.                 "\\([^@]+\\)@\\([^ ]+\\) *")
  5609.             s)
  5610.           (let* ((nick (subfield s 1))
  5611.              (oper (subfield s 2))
  5612.              (away (subfield s 3))
  5613.              (user (subfield s 4))
  5614.              (host (subfield s 5))
  5615.              (rest (substring s (match-end 0))))
  5616.         (irc-remember nick 'irc-nicknames)
  5617.         (irc-remember host 'irc-servernames)
  5618.         (irc-insert "%s%s \"%s\" is %s@%s%s%s"
  5619.                 irc-msg-info-pre
  5620.                 (if (string= "*" oper) "Operator" "User")
  5621.                 nick
  5622.                 user
  5623.                 host
  5624.                 (if (string= "-" away) " (AWAY)" "")
  5625.                 irc-msg-info-post)
  5626.         (setq s rest)))))
  5627.      ((= num 303)                 ; RPL_ISON
  5628.       (let ((data (if (and (> (length txt) 0) (= ?: (aref txt 0)))
  5629.               (substring txt 1) txt))
  5630.         (ignored 0)
  5631.         (list ())
  5632.         (found ()))
  5633.         (while (string-match "^ *\\([^ ]+\\)" data)
  5634.           (setq found (cons (subfield data 1) found)
  5635.             data (substring data (match-end 0))))
  5636.         (while (not (null found))
  5637.           (if (irc-recall (car found) 'irc-ignored-ppl)
  5638.           (setq ignored (1+ ignored))
  5639.         (setq list (cons (car found) list)))
  5640.           (setq found (cdr found)))
  5641.         (setq list (reverse list))    ;Keep list sorted.
  5642.         (let ((l list)
  5643.           (arrivers ()))
  5644.           (while (not (null l))
  5645.         (if (not (irc-recall (car l) 'irc-notify-detected))
  5646.             (progn (setq arrivers (cons (car l) arrivers))
  5647.                (irc-send (format "WHOIS %s %s" (car l) (car l)))
  5648.                (irc-remember (car l) 'irc-notify-detected)
  5649.                (irc-remember (car l) 'irc-nicknames)
  5650.                ))
  5651.         (setq l (cdr l)))
  5652.           (let ((l (irc-recall-all 'irc-notify-detected))
  5653.             (gonners ()))
  5654.         (while (not (null l))
  5655.           (if (not (irc-list-recall (car l) list))
  5656.               (progn (setq gonners (cons (car l) gonners))
  5657.                  (irc-forget (car l) 'irc-notify-detected)))
  5658.           (setq l (cdr l)))
  5659.         (if (not (null arrivers))
  5660.             (let ((a arrivers)
  5661.               (as (irc-listify arrivers ", " "and")))
  5662.               (irc-insert "%sDETECTED %s%s on IRC%s"
  5663.                   irc-msg-info-pre
  5664.                   as
  5665.                   (if (> ignored 0)
  5666.                       (format " (also %d ignored person%s)"
  5667.                           ignored
  5668.                           (if (= 1 ignored) "" "s"))
  5669.                     "")
  5670.                   irc-msg-info-post)
  5671.               (if (irc-signal (car a) 'detect)
  5672.               (progn
  5673.                 (message (format "Kiwi: Detected %s on IRC" as))
  5674.                 (ding t)))))
  5675.         (if (not (null gonners))
  5676.             (let ((g gonners)
  5677.               (gs (irc-listify gonners ", " "and")))
  5678.               (irc-insert "%sLOST SIGHT of %s from IRC%s"
  5679.                   irc-msg-info-pre
  5680.                   gs
  5681.                   irc-msg-info-post)
  5682.               (while g
  5683.             (if (irc-signal (car g) 'detect)
  5684.                 (progn
  5685.                   (message (format
  5686.                     "Kiwi: lost sight of %s from IRC"
  5687.                     gs))
  5688.                   (ding t)))
  5689.             (setq g (cdr g)))))))))
  5690.      ((= num 304)                 ; RPL_TEXT
  5691.       (irc-insert "Text: %s" txt))
  5692.      ((= num 305)
  5693.       (irc-insert "%sYou are no longer marked as being away%s"
  5694.               irc-msg-info-pre irc-msg-info-post))
  5695.      ((= num 306)
  5696.       (irc-insert (concat "%sYou have been marked as being away, use"
  5697.                   " /HERE to revert the effect%s")
  5698.               irc-msg-info-pre irc-msg-info-post))
  5699.      ((= num 311)                       ; RPL_WHOISUSER
  5700.       (string-match (concat "^\\([^: ]+\\) +\\([^: ]+\\) +\\([^: ]+\\)"
  5701.                 " \\([^: ]+\\) :")
  5702.             txt)
  5703.       (let* ((nick (subfield txt 1))
  5704.          (rn (substring txt (match-end 0)))
  5705.          (user-name (subfield txt 2))
  5706.          (client (subfield txt 3))
  5707.          (c (subfield txt 4))
  5708.          (channel (if (string= c "*")
  5709.                   ""
  5710.                 (concat " on channel " c)))
  5711.          (cntrl1 (format "%s \"%s\" "
  5712.                  (if (irc-recall nick 'irc-ignored-ppl)
  5713.                      "IGNORED user"
  5714.                    "User")
  5715.                  nick))
  5716.          (real-name (irc-nuke-whitespace rn)))
  5717.         (setq irc-msg-cont-used (make-string (length cntrl1) ? ))
  5718.         (irc-remember nick 'irc-nicknames)
  5719.         (irc-insert (concat cntrl1 "is %s <%s@%s>%s,")
  5720.             (irc-clean-up-message real-name)
  5721.             (irc-clean-up-message user-name)
  5722.             client
  5723.             channel)))
  5724.      ((= num 312)            ; RPL_WHOISSERVER
  5725.       (let ((info-hop-count nil)
  5726.         (info-nick nil)
  5727.         (info-real-server-or-relay-name nil)
  5728.         (info-server-name nil)
  5729.         (info-server-descr nil)
  5730.         (found-info nil))
  5731.         (cond
  5732.          ((string-match "^ *\\([^ :]+\\) +\\([^ :]+\\) *: *" txt)
  5733.           (setq info-nick (subfield txt 1)
  5734.             info-server-name (subfield txt 2))
  5735.           (let ((rst (substring txt (match-end 0))))
  5736.         (cond ((string-match (concat "^... ... +[0-9]+ [0-9]+:"
  5737.                          "[0-9]+:[0-9]+ [0-9]+$")
  5738.                      rst)
  5739.                (setq info-server-descr (format "gone since %s" rst)
  5740.                  found-info t))
  5741.               ((string-match (concat "^\\([0-9]+\\) *: *\\["
  5742.                          "\\([^]]+\\)\\] *\\(.*\\) *$")
  5743.                      rst)
  5744.                (setq info-hop-count (subfield rst 1)
  5745.                  info-real-server-or-relay-name (subfield rst 2)
  5746.                  info-server-descr (subfield rst 3)
  5747.                  found-info t))
  5748.               ((string-match "^\\([0-9]+\\) +:? *\\(.*\\) *$" rst)
  5749.                (setq info-hop-count (subfield rst 1)
  5750.                  info-server-descr (subfield rst 2)
  5751.                  found-info t))
  5752.               ((string-match "^\\[\\([^]]+\\)\\] *\\(.*\\) *$"
  5753.                      rst)
  5754.                (setq info-real-server-or-relay-name (subfield rst 1)
  5755.                  info-server-descr (subfield rst 2)
  5756.                  found-info t))
  5757.               (t (setq info-server-descr rst
  5758.                    found-info t)))))
  5759.          ((string-match (concat "^\\([^ :]+\\) *: *\\([0-9]+\\) *: *"
  5760.                     "\\([^ ].*[^ ]\\) *$")
  5761.                 txt)
  5762.           (setq info-server-name (subfield txt 1)
  5763.             info-hop-count (subfield txt 2)
  5764.             info-server-descr (subfield txt 3)
  5765.             found-info t))
  5766.          ((string-match "^\\([^ :]+\\) *: *\\([^ ].*[^ ]\\) *$" txt)
  5767.           (setq info-server-name (subfield txt 1)
  5768.             info-server-descr (subfield txt 2)
  5769.             found-info t)))
  5770.         (if (not found-info)
  5771.         (progn
  5772.           (irc-insert "%%Found unknown RPL312 in irc-parse-RPL-3xx:")
  5773.           (irc-insert "%% \"%s\" (txt)." txt)
  5774.           (irc-insert "%% Please tell %s, it might be a bug."
  5775.                   irc-hacker))
  5776.           (irc-remember info-server-name 'irc-servernames)
  5777.           (let ((s (format "%s%son %s (%s)%s."
  5778.                    irc-msg-cont-used
  5779.                    (if info-real-server-or-relay-name
  5780.                    (concat "(according to "
  5781.                        info-real-server-or-relay-name
  5782.                        ") ")
  5783.                  "")
  5784.                    info-server-name
  5785.                    (irc-clean-up-message
  5786.                 (irc-nuke-whitespace info-server-descr))
  5787.                    (if info-hop-count
  5788.                    (concat " at least "
  5789.                        info-hop-count
  5790.                        " hops away")
  5791.                  ""))))
  5792.         (irc-insert "%s" s)))))
  5793.      ((= num 313)            ; RPL_WHOISOPERATOR
  5794.       (string-match "^[^: ]+" txt)
  5795.       (irc-insert "%s\"%s\" is an ENABLED operator on IRC."
  5796.               irc-msg-cont-used
  5797.               (substring txt (match-beginning 0) (match-end 0))))
  5798.      ((= num 314)                 ; RPL_WHOWASUSER
  5799.       (if (string-match (concat "^\\([^: ]+\\) \\([^: ]+\\) \\([^: ]+\\)"
  5800.                     " \\([^: ]+\\) *:")
  5801.                 txt)
  5802.           (let* ((nick (subfield txt 1))
  5803.              (rn (substring txt (match-end 0)))
  5804.              (user-name (subfield txt 2))
  5805.              (client (subfield txt 3))
  5806.              (c (subfield txt 4))
  5807.              (channel (if (string= c "*")
  5808.                   ""
  5809.                 (concat " on channel " c)))
  5810.              (real-name (irc-nuke-whitespace rn))
  5811.              (cntrl1 (format "%%User \"%s\" " nick)))
  5812.         (setq irc-msg-cont-used (make-string (length cntrl1) ? ))
  5813.         (if (not (irc-recall nick 'irc-services))
  5814.             (irc-forget nick 'irc-nicknames))
  5815.         (irc-insert (concat "%" cntrl1 "isn't on IRC anymore,"
  5816.                     " was %s <%s@%s>%s,")
  5817.                 (irc-clean-up-message real-name)
  5818.                 (irc-clean-up-message user-name)
  5819.                 client
  5820.                 channel))))
  5821.      ((= num 315)                 ; RPL_WHOEND
  5822.       (if (= 0 irc-reply-count)
  5823.           (irc-insert "%%No users listed")
  5824.         (irc-insert "%s%d user%s listed%s"
  5825.             irc-msg-info-pre
  5826.             irc-reply-count
  5827.             (if (= 1 irc-reply-count) "" "s")
  5828.             irc-msg-info-post))
  5829.       (setq irc-reply-count 0)
  5830.       (if t ()
  5831.         (message "")
  5832.         (if (irc-nothing-remembered-p 'irc-whotree)
  5833.         (let ((c (if (string-match (concat "^ *: *[^ ]+ +315"
  5834.                            " +[^ ]+ +\\([^:]+\\)"
  5835.                            " +:")
  5836.                        str)
  5837.                  (subfield str 1))))
  5838.           (irc-insert (if c "%%No users on \"%s\"." "%%No users.")
  5839.                   c))
  5840.           (irc-recall-all-and-display 'irc-whotree
  5841.                     ;(string-match "-* *$"
  5842.                     ;irc-who-stroke)
  5843.                       31
  5844.                       "users"
  5845.                       "user")
  5846.           (irc-forget-all 'irc-whotree)))
  5847.       )
  5848.      ((= num 316)                 ; RPL_WHOISCHANOP
  5849.       (if (not
  5850.            (string-match (concat "^:\\([^: ]+\\)? +316 +\\([^: ]+\\) +"
  5851.                      "\\([^: ]+\\) +: *has +been +"
  5852.                      "touched +by +magic +forces *$")
  5853.                  str))
  5854.           (progn (irc-insert (concat "%%Unrecognized type 316 reply; "
  5855.                      "please tell %s:")
  5856.                  irc-hacker)
  5857.              (irc-insert "%% \"%s\"." str)
  5858.              (irc-insert " Function irc-parse-RPL-3xx, at 316."))
  5859.         (let ((server (substring str (match-beginning 1) (match-end 1)))
  5860.           (own (substring str (match-beginning 2) (match-end 2)))
  5861.           (other (substring str (match-beginning 3) (match-end 3))))
  5862.           (irc-remember own 'irc-nicknames)
  5863.           (irc-remember other 'irc-nicknames)
  5864.           (irc-insert "%s\"%s\" is a channel operator."
  5865.               irc-msg-cont-used
  5866.               other))))
  5867.      ((= num 317)            ;RPL_IDLETIME
  5868.       (cond ((or (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+"
  5869.                        " +\\([^ ]+\\)"
  5870.                        " +\\([0-9]+\\)"
  5871.                        " +\\([0-9]+\\)"
  5872.                        " *:")
  5873.                    str)
  5874.              (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+"
  5875.                        " +\\([^ ]+\\)"
  5876.                        " +\\([0-9]+\\)"
  5877.                        "\\(\\) *:")
  5878.                    str)
  5879.              (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+\\(\\)\\(\)"
  5880.                        " +\\([0-9]+\\)"
  5881.                        " *:")
  5882.                    str))
  5883.          (let* ((user (subfield str 1))
  5884.             (time (string-to-int (subfield str 2)))
  5885.             (logintime (string-to-int (subfield str 3))))
  5886.            (if (zerop time)
  5887.                (irc-insert "%s\"%s\" is actively typing."
  5888.                    irc-msg-cont-used
  5889.                    user)
  5890.              (irc-insert "%sIdle time for user %s is %d second%s%s."
  5891.                  irc-msg-cont-used
  5892.                  user
  5893.                  time
  5894.                  (if (= 1 time) "" "s")
  5895.                  (if (> 60 time)
  5896.                      ""
  5897.                    (concat " ("
  5898.                        (irc-sec-to-time time)
  5899.                        ")"))))))
  5900.         (t (irc-insert (concat "%%Unknown 317 type reply message in"
  5901.                        " function irc-parse-RPL-3xx."))
  5902.            (irc-insert "%% \"%s\" (str)." str)
  5903.            (irc-insert "%% Please tell %s, it might be a bug."
  5904.                    irc-hacker))))
  5905.      ((= num 318)                 ; RPL_ENDOFWHOIS
  5906.       )
  5907.      ((= num 319)
  5908.       (cond ((string-match "^\\([^:]*:\\)?" txt)
  5909.          (let ((list (irc-listify
  5910.                   (irc-burst-comma
  5911.                    (irc-nuke-whitespace
  5912.                 (substring txt (match-end 0))))
  5913.                   ", " "and")))
  5914.            (irc-insert "%sis listening to channel%s %s,"
  5915.                    irc-msg-cont-used
  5916.                    (if (string-match " [^ ]" list) "s" "")
  5917.                    list)))
  5918.         (t (irc-insert (concat "%%Unknown 319 type reply message in"
  5919.                        " function irc-parse-RPL-3xx."))
  5920.            (irc-insert "%% \"%s\" (txt)." txt)
  5921.            (irc-insert "%% Please tell %s, it might be a bug."
  5922.                    irc-hacker))))
  5923.      ((= num 321)                       ; RPL_LISTSTART
  5924.       (irc-insert irc-list-header)
  5925.       (irc-insert irc-list-stroke)
  5926.       (setq irc-list-stats '(0 0))
  5927.       (set-buffer-modified-p (buffer-modified-p)))
  5928.      ((= num 322)                       ; RPL_LIST
  5929.       (if (not (string-match "^\\([^ ]+\\) \\([^ ]+\\) :" txt))
  5930.           (progn (irc-insert (concat "%%Unknown format on RPL_LIST"
  5931.                      " message; please tell %s.")
  5932.                  irc-hacker)
  5933.              (irc-insert "%% \"%s\" (txt)." txt)
  5934.              (irc-insert "%% Function irc-parse-RPL-3xx, at 322."))
  5935.         (let* ((chan (substring txt (match-beginning 1) (match-end 1)))
  5936.            (count (substring txt (match-beginning 2) (match-end 2)))
  5937.            (topic (irc-nuke-whitespace
  5938.                (substring txt (match-end 0))))
  5939.            (tmpline (format "%s   %2s   "
  5940.                     (irc-format-channel chan)
  5941.                     count))
  5942.            (top (irc-clean-up-message topic))
  5943.            (line (concat tmpline top))
  5944.            (irc-msg-cont-used (make-string (length tmpline) ? )))
  5945.           (if (or t (> (string-to-int count) 10))
  5946.           (let ((irc-msg-cont-used (make-string
  5947.                         (string-match "-* *$"
  5948.                               irc-list-stroke)
  5949.                         ? )))
  5950.             (setq irc-list-stats (list (1+ (car irc-list-stats))
  5951.                            (+ (nth 1 irc-list-stats)
  5952.                           (string-to-int count))))
  5953.             (irc-insert (irc-clean-up-message line)))))))
  5954.      ((= num 323)                       ; RPL_LISTEND
  5955.       (let ((ch (car irc-list-stats))
  5956.         (us (nth 1 irc-list-stats)))
  5957.         (if (and (zerop us) (zerop ch))
  5958.         (irc-insert "%%No visible channels.")
  5959.           (irc-insert (concat "%s%s user%s on the %s channel%s"
  5960.                   " which happen to be visible%s")
  5961.               irc-msg-info-pre
  5962.               (if (zerop us) "No" (int-to-string us))
  5963.               (if (= 1 us) "" "s")
  5964.               (if (zerop ch) "No" (int-to-string ch))
  5965.               (if (= 1 ch) "" "s")
  5966.               irc-msg-info-post)))
  5967.       (setq irc-list-stats '(0 0)))
  5968.      ((= num 324)                 ; RPL_CHANNELMODEIS
  5969.       (let* ((lst (if (irc-server-has-channelname-in-msgs)
  5970.               (if (string-match
  5971.                    (concat "^ *: *\\([^ ]+\\) +324" ;origin
  5972.                        " +\\([^ ]+\\)"    ;nick
  5973.                        " +\\([^ ]+\\)"    ;channel
  5974.                        " +\\(\\+[^ ]*\\)" ;mode
  5975.                        "\\( [-+]?[^ ]+\\)? *$") ;extra
  5976.                    str)
  5977.                   (list (subfield str 1) ;origin
  5978.                     (subfield str 2) ;nick
  5979.                     (subfield str 3) ;channel
  5980.                     (subfield str 4) ;mode (at least a "+")
  5981.                     (subfield str 5)))    ;limit (optional)
  5982.             (if (string-match
  5983.                  (concat "^ *: *\\([^ ]+\\) +324 +"
  5984.                      "\\([^ ]+\\) +\\(+[^ ]*\\)"
  5985.                      "\\( +[0-9]+\\)? *$")
  5986.                  str)
  5987.                 (list (subfield str 1) ;origin
  5988.                   (subfield str 2) ;nick
  5989.                   nil ;channel not given
  5990.                   (subfield str 3) ;mode (at least "+")
  5991.                   (subfield str 4))))) ;limit (optional)
  5992.          (orig (nth 0 lst))
  5993.          (nick (nth 1 lst))
  5994.          (channel (nth 2 lst))
  5995.          (mode (if lst (irc-nuke-whitespace (concat (nth 3 lst)
  5996.                                 (nth 4 lst)))))
  5997.          (expl (if lst (irc-explain-channel-mode mode 'skip-dir)))
  5998.          (chntxt (concat (if channel "The channel " "The channels")
  5999.                  (if channel
  6000.                      (concat
  6001.                       channel
  6002.                       "'"
  6003.                       (if (not (= ?s (aref channel
  6004.                                (1- (length
  6005.                                 channel)))))
  6006.                       "s"))
  6007.                    "")
  6008.                  " "))
  6009.          (irc-msg-cont-used (make-string (+ (length chntxt)
  6010.                             (length irc-msg-info-pre))
  6011.                          ? )))
  6012.         (if (not lst)
  6013.         (progn
  6014.           (irc-insert (concat "%%Received RPL_CHANNELMODEIS reply"
  6015.                       " in unknown format:"))
  6016.           (irc-insert "%% \"%s\" (str)." str)
  6017.           (irc-insert "%% In irc-parse-RPL-3xx at 324. Please tell %s."
  6018.                   irc-hacker))
  6019.           (progn
  6020.         (if (irc-is-nickname orig)
  6021.             (irc-remember orig 'irc-nicknames))
  6022.         (if (and (irc-is-hostname orig)
  6023.              (not (string= (upcase origin) (upcase orig))))
  6024.             (irc-remember orig 'irc-servernames))
  6025.         (irc-remember nick 'irc-nicknames)
  6026.         (if (or t (string= (upcase orig) (upcase irc-server)))
  6027.             (irc-insert "%s%smode%s %s %s%s"
  6028.                 irc-msg-info-pre
  6029.                 chntxt 
  6030.                 (if (string-match " and " expl) "s" "")
  6031.                 (if (string-match " and " expl) "are" "is")
  6032.                 expl
  6033.                 irc-msg-info-post)
  6034.           ;; Ignore MODE replies from remote servers.
  6035.           )))))
  6036.      ((= num 325)
  6037.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6038.      ((= num 329)            ;undernet: time of channe; creation
  6039.       (cond ((string-match "\\([^ ]+\\) +\\([^ ]+\\)$" txt) ;Undernet
  6040.          ;;(let ((chan (subfield txt 1))
  6041.          ;;    (time (subfield txt 2)))
  6042.          ;;(irc-insert "%sNYI: channel %s was created at <%s>%s"
  6043.          ;;        irc-msg-info-pre
  6044.          ;;        chan
  6045.          ;;        time
  6046.          ;;        irc-msg-info-post))
  6047.          )
  6048.         (t (irc-insert "%% Bad 329 message, txt=\"%s\"." txt))))
  6049.      ((= num 331)                       ; RPL_NOTOPIC
  6050.       (if (string= parorg "")    ;Not when message from remote (old)
  6051.           (if (string-match (concat "^\\([^ ]+\\) +: *No +topic"
  6052.                     " +is +set *.? *$")
  6053.                 txt)
  6054.           (irc-insert "%sNo topic is set for channel %s%s"
  6055.                   irc-msg-info-pre
  6056.                   (subfield txt 1)
  6057.                   irc-msg-info-post)
  6058.         (irc-insert "%sNo topic is set%s"
  6059.                 irc-msg-info-pre
  6060.                 irc-msg-info-post))))
  6061.      ((= num 332)                       ; RPL_TOPIC
  6062.       (cond ((and (irc-server-has-end-of-whois)
  6063.               (string-match "^\\([^ ]+\\) *:" txt))
  6064.          (irc-insert "%sThe topic for channel %s is \"%s\"%s"
  6065.                  irc-msg-info-pre
  6066.                  (irc-clean-up-message (subfield txt 1))
  6067.                  (irc-clean-up-message
  6068.                   (irc-nuke-whitespace
  6069.                    (substring txt (match-end 0))))
  6070.                  irc-msg-info-post))
  6071.         ((string-match ":?" txt)
  6072.          (irc-insert "%sThe topic is \"%s\"%s"
  6073.                  irc-msg-info-pre
  6074.                  (irc-clean-up-message (substring txt
  6075.                                   (match-end 0)))
  6076.                  irc-msg-info-post))
  6077.         (t (irc-insert "%sThe topic is \"%s\"%s"
  6078.                    irc-msg-info-pre
  6079.                    (irc-clean-up-message txt)
  6080.                    irc-msg-info-post))))
  6081.      ((= num 333)
  6082.       (cond ((string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([0-9]+\\)$" txt)
  6083.          (irc-insert "%sChannel %s created by %s%s"
  6084.                  irc-msg-info-pre
  6085.                  (subfield txt 1)
  6086.                  (subfield txt 2)
  6087.                  irc-msg-info-post))
  6088.         (t (irc-insert "%% Bad 333 message, txt=\"%s\"." txt))))
  6089.      ((= num 338)
  6090.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6091.      ((= num 339)
  6092.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6093.      ((= num 341)                       ; RPL_INVITING
  6094.       (string-match (concat "^:\\([^: ]+\\) +341 +[^: ]+ +\\([^: ]+\\) +"
  6095.                 "\\([^ ]+\\)")
  6096.             str)
  6097.       (let ((nick (subfield str 2))
  6098.         (channel (subfield str 3)))
  6099.         (irc-remember nick 'irc-nicknames)
  6100.         (irc-insert "%sYou are inviting user \"%s\" to channel %s%s"
  6101.             irc-msg-info-pre
  6102.             nick
  6103.             (irc-clean-up-message channel)
  6104.             irc-msg-info-post)))
  6105.      ((= num 351)                       ; RPL_VERSION | RPL_WHOREPLY
  6106.       (if (string-match "^\\([^: ]+\\) :?\\([^: ]+\\)" txt)
  6107.           (let ((s (substring txt (match-beginning 2) (match-end 2)))
  6108.             (v (substring txt (match-beginning 1) (match-end 1))))
  6109.         (if (not (string= (upcase origin) (upcase s)))
  6110.             (irc-remember s 'irc-servernames))
  6111.         (irc-insert (concat "%sIRC server %s is running version %s,"
  6112.                     " and the client you are using is %s%s")
  6113.                 irc-msg-info-pre
  6114.                 (upcase s)
  6115.                 v
  6116.                 irc-version
  6117.                 irc-msg-info-post))))
  6118.      ((= num 352)
  6119.       ;;(irc-parse-whoreply (format "WHOREPLY %s" txt))
  6120.       (cond ((= 0 irc-reply-count)
  6121.          (irc-insert irc-who-header)
  6122.          (irc-insert irc-who-stroke) 
  6123.          (setq irc-msg-cont-used (make-string
  6124.                       (string-match "-* *$"
  6125.                             irc-who-stroke)
  6126.                       ? ))))
  6127.       (setq irc-reply-count (1+ irc-reply-count))
  6128.       (if (string-match (concat "^\\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\\)"
  6129.                     " \\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\\)"
  6130.                     " :\\([0-9]+\\) \\(.+\\)$")
  6131.                 txt)
  6132.           (let* ((chan (subfield txt 1))
  6133.              (login (subfield txt 2))
  6134.              (client (subfield txt 3))
  6135.              (server (subfield txt 4))
  6136.              (nick (subfield txt 5))
  6137.              (mode (subfield txt 6))
  6138.              (unkn (subfield txt 7))
  6139.              (realname (subfield txt 8))
  6140.              (vsts (cond ((irc-recall nick 'irc-ignored-ppl) "IGNR")
  6141.                  ((string= "H"   mode) "    ") ;Norm
  6142.                  ((string= "G"   mode) "Away") ;Away
  6143.                  ((string= "H*"  mode) "Iopr") ;Iopr
  6144.                  ((string= "G*"  mode) "IoAw") ;IoAw
  6145.                  ((string= "H@"  mode) "Copr") ;Copr
  6146.                  ((string= "G@"  mode) "CoAw") ;CoAw
  6147.                  ((string= "H*@" mode) "ICop") ;ICop
  6148.                  ((string= "G*@" mode) "ICAw") ;ICAw
  6149.                  ((string= "S"   mode) "    ") ;Norm
  6150.                  (t mode))))
  6151.         (irc-insert "%-9s %-4s %-15s %s@%s \"%s\""
  6152.                 nick
  6153.                 vsts
  6154.                 chan
  6155.                 login
  6156.                 client
  6157.                 realname))))
  6158.      ((= num 353)                       ; RPL_NAMREPLY
  6159.       (if (or (string-match "^@ +\\([#&][^ ]+\\) +:?" txt)
  6160.           (string-match "^ *[=*] +\\([^ ]+\\) *:" txt))
  6161.           (let ((c (subfield txt 1))
  6162.             (n (substring txt (match-end 0))))
  6163.         (irc-parse-namreply
  6164.          (format "NAMREPLY placeholder %s %s" c n)))
  6165.         (irc-parse-namreply (format "NAMREPLY %s" txt))))
  6166.      ((= num 354)                       ; RPL_ENDOFNAMES
  6167.       (irc-insert "Names 354: %s" txt))
  6168.      ((= num 361)                       ; RPL_KILLDONE
  6169.       (string-match "^[^: ]+" txt)
  6170.       (irc-insert "%sYou have removed \"%s\" from IRC (/killed)%s"
  6171.               irc-msg-info-pre
  6172.               (substring txt (match-beginning 0) (match-end 0))
  6173.               irc-msg-info-post))
  6174.      ((= num 364)                 ; RPL_LINKS
  6175.       (if (not (or (string-match "^\\([^ ]*\\) \\([^ ]*\\) *:" txt)
  6176.                (string-match "^\\([^ ]*\\) *:" txt)))
  6177.           (progn
  6178.         (irc-insert "%%Error in parsing RPL 364, please tell %s:"
  6179.                 irc-hacker)
  6180.         (irc-insert "%% \"%s\" (txt)." txt)
  6181.         (irc-insert "%% In function irc-parse-RPL-3xx, at 364."))
  6182.         (let ((s (upcase (subfield txt 1)))
  6183.           (f2 (subfield txt 2))
  6184.           (info (irc-nuke-whitespace
  6185.              (irc-clean-up-message
  6186.               (substring txt (match-end 0))))))
  6187.           (setq irc-reply-count (1+ irc-reply-count))
  6188.           (let ((diff (irc-time-diff (irc-current-time)
  6189.                      irc-reply-count-time)))
  6190.         (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since last
  6191.                (> (nth 0 diff) 0)) ; display?
  6192.                (setq irc-reply-count-time (irc-current-time))
  6193.                (message (format " %d server%s ..."
  6194.                     irc-reply-count
  6195.                     (if (= 1 irc-reply-count)
  6196.                         ""
  6197.                       "s"))))))
  6198.           (irc-remember (format "Server %s%s: %s"
  6199.                     s
  6200.                     (if (string= "" f2)
  6201.                     ""
  6202.                       (format " (to %s)" (upcase f2)))
  6203.                     info) 
  6204.                 'irc-linksinfo)
  6205.           (if (not (string= (upcase origin) (upcase s)))
  6206.           (irc-remember s 'irc-servernames)))))
  6207.      ((= num 365)                 ; RPL_ENDOFLINKS
  6208.       (setq irc-reply-count 0)
  6209.       (message "")
  6210.       (irc-insert irc-links-header)
  6211.       (irc-insert irc-links-stroke)
  6212.       (set-buffer-modified-p (buffer-modified-p))
  6213.       (irc-recall-all-and-display 'irc-linksinfo
  6214.                       (progn (string-match "^[^: ]* ."
  6215.                                irc-links-header)
  6216.                          (match-end 0))
  6217.                       "servers"
  6218.                       "server") 
  6219.       (irc-forget-all 'irc-linksinfo))
  6220.      ((= num 366)                 ; RPL_NAMES_END
  6221.       (setq irc-reply-count 0)
  6222.       (message "")
  6223.       (if (irc-terminal-is-slow)
  6224.           (let ((lincnt 0)
  6225.             (usrcnt 0)
  6226.             (adjust 0)
  6227.             (w (irc-recall-all 'irc-namtree))
  6228.             (irc-msg-cont-used irc-names-cont-msg))
  6229.         (irc-insert "Name of channel  Users  Nicknames")
  6230.         (irc-insert "---------------  -----  ---------")
  6231.         (set-buffer-modified-p (buffer-modified-p))
  6232.         (while w
  6233.           (irc-insert "%s" (car w))
  6234.           (let* ((pair (if (string-match (concat "^ *\\([^ ]+\\) +"
  6235.                              "\\([0-9]+\\)")
  6236.                          (car w))
  6237.                    (cons (subfield (car w) 1)
  6238.                      (subfield (car w) 2))
  6239.                  (cons "" "0")))
  6240.              (ldiff (if (string= "PRIVATE" (upcase (car pair)))
  6241.                     1
  6242.                   0))
  6243.              (udiff (string-to-int (cdr pair))))
  6244.             (setq usrcnt (+ usrcnt udiff)
  6245.               lincnt (1+ lincnt)
  6246.               adjust (+ adjust ldiff)
  6247.               w (cdr w))))
  6248.         (let ((adjusted (- lincnt adjust)))
  6249.           (irc-insert (concat "%s%d visible user%s on %d visible"
  6250.                       " channel%s or on some private"
  6251.                       " channel%s")
  6252.                   irc-msg-info-pre
  6253.                   usrcnt
  6254.                   (if (= usrcnt 1) "" "s")
  6255.                   adjusted
  6256.                   (if (= adjusted 1) "" "s")
  6257.                   irc-msg-info-post)
  6258.           (irc-insert ""))
  6259.         (irc-forget-all 'irc-namtree))
  6260.         ;; Else fast terminal.
  6261.         (irc-insert "%sEnd of NAMES list%s"
  6262.             irc-msg-info-pre
  6263.             irc-msg-info-post)))
  6264.      ((= num 367)                       ; RPL_BANLIST
  6265.       (cond
  6266.        ((string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\) +\\(.+\\)$"
  6267.               txt)
  6268.         (let ((chan (subfield txt 1))
  6269.           (banned (subfield txt 2))
  6270.           (banner (subfield txt 3))
  6271.           (time (subfield txt 4)))
  6272.           (irc-insert "%sUser(s) \"%s\" are banned from %s by %s at %s%s"
  6273.               irc-msg-info-pre
  6274.               banned
  6275.               chan
  6276.               banner
  6277.               time
  6278.               irc-msg-info-post)))
  6279.        ((string-match "^\\([^ ]+\\) +\\(.+\\)$" txt)
  6280.         (let ((channel (subfield txt 1))
  6281.           (user (subfield txt 2)))
  6282.           (irc-insert (concat "%sUser(s) matching \"%s\""
  6283.                   " are banned from %s%s")
  6284.               irc-msg-info-pre user channel irc-msg-info-post)))
  6285.        (t (irc-insert "%%Unknown type 367 reply seen in irc-parse-RPL-3xx:")
  6286.           (irc-insert "%% \"%s\" (txt)" txt)
  6287.           (irc-insert "%% Please tell %s, it might be a bug."
  6288.               irc-hacker))))
  6289.      ((= num 368)                       ; RPL_BANLISTEND 
  6290.       (irc-insert (concat "%sEnd of list of banned users (who are"
  6291.                   " prohibited to join)%s")
  6292.               irc-msg-info-pre irc-msg-info-post))
  6293.      ((= num 369)                 ; RPL_ENDOFWHOWAS
  6294.       )
  6295.      ((= num 371)                       ; RPL_INFO
  6296.       (irc-insert "* %s" txt))
  6297.      ((= num 372)                       ; RPL_MOTD
  6298.       (cond
  6299.        ((string-match (concat "^ *: *\\([^: ]+\\)? +372 *\\([^: ]+\\)?"
  6300.                   " *: *Message-of-today +not +found +"
  6301.                   "in +server +\\([^: ]+\\) *$")
  6302.               str)
  6303.         (let* ((f (substring str (match-beginning 1) (match-end 1)))
  6304.            (frm (if (string= (upcase f) (upcase irc-server)) "" f))
  6305.            (at (substring str (match-beginning 3)
  6306.                   (match-end 3))))
  6307.           (if (not (string= (upcase origin) (upcase frm)))
  6308.           (irc-remember frm 'irc-servernames))
  6309.           (if (not (string= (upcase origin) (upcase at)))
  6310.           (irc-remember at 'irc-servernames))
  6311.           (irc-insert "%%%sNo message of the day at server %s."
  6312.               (if (string= frm "")
  6313.                   ""
  6314.                 (concat "(" frm ") "))
  6315.               (upcase at))))
  6316.        ((string-match (concat "^ *: *\\([^: ]+\\)? +372 *"
  6317.                   "\\([^: ]+\\)? *:? *"
  6318.                   "\\(start\\|end\\)?"
  6319.                   "\\( +at +server +\\)?"
  6320.                   "\\([A-Za-z.-.---]*\\|.*\\)"
  6321.                   "\\( *:\\)? *$")
  6322.               str)
  6323.         (let* ((from-1 (irc-non-num-to-0 (match-beginning 1)))
  6324.            (to-1 (irc-non-num-to-0 (match-end 1)))
  6325.            (from-2 (irc-non-num-to-0 (match-beginning 2)))
  6326.            (to-2 (irc-non-num-to-0 (match-end 2)))
  6327.            (from-3 (irc-non-num-to-0 (match-beginning 3)))
  6328.            (to-3 (irc-non-num-to-0 (match-end 3)))
  6329.            (from-4 (irc-non-num-to-0 (match-beginning 4)))
  6330.            (to-4 (irc-non-num-to-0 (match-end 4)))
  6331.            (from-5 (irc-non-num-to-0 (match-beginning 5)))
  6332.            (to-5 (irc-non-num-to-0 (match-end 5)))
  6333.            (from-6 (irc-non-num-to-0 (match-beginning 6)))
  6334.            (to-6 (irc-non-num-to-0 (match-end 6)))
  6335.            (server (substring str from-1 to-1))
  6336.            (user (substring str from-2 to-2))
  6337.            (direction (substring str from-3 to-3))
  6338.            (token (substring str from-4 to-4))
  6339.            (message (substring str from-5 to-5))
  6340.            (colon (substring str from-6 to-6)))
  6341.           (if (and (not (string= "" server))
  6342.                (not (string= (upcase origin) (upcase server))))
  6343.           (irc-remember server 'irc-servernames))
  6344.           (if (not (string= "" user))
  6345.           (irc-remember user 'irc-nicknames))
  6346.           (cond ((and (or (string= (downcase direction) "start")
  6347.                   (string= (downcase direction) "end"))
  6348.               (string-match "^ *at +server *$" token)
  6349.               (not (string= "" message))
  6350.               (string-match "^ *:$" colon)
  6351.               (not (string= (upcase origin)
  6352.                     (upcase message))))
  6353.              (irc-remember message 'irc-servernames))
  6354.             ((string-match "[^: ]" message)
  6355.              (irc-insert ">>> %s" (concat direction
  6356.                           token
  6357.                           message
  6358.                           colon))))))
  6359.        (t (irc-insert (concat "%%Unkown format on MOTD reply,"
  6360.                   " in function irc-parse-RPL-3xx,"
  6361.                   " num 372"))
  6362.           (irc-insert "%% \"%s\"." str))))
  6363. ;;;       ((= num 373)                       ; RPL_VERSION
  6364. ;;;        (irc-insert "DEBUG: RPL373 txt=\"%s\"." txt))
  6365.      ((= num 374)            ;RPL_INFO_END
  6366.       (irc-insert "%sEnd of information about this IRC server%s"
  6367.               irc-msg-info-pre irc-msg-info-post))
  6368.      ((= num 375)            ;RPL, start of MOTD
  6369.       (irc-insert ">>> %s" txt))
  6370.      ((= num 376)            ;RPL, end of MOTD
  6371.       (irc-insert "%sEnd of MOTD at %s%s"
  6372.               irc-msg-info-pre origin irc-msg-info-post))
  6373.      ((= num 377)
  6374.       (irc-insert ">>> %s" txt))
  6375.      ((= num 381)                       ; RPL_YOUREOPER
  6376.       (setq irc-operator " IOPR")
  6377.       (set-buffer-modified-p (buffer-modified-p))
  6378.       (irc-insert "%sOperator status for %s ENABLED%s"
  6379.               irc-msg-info-pre
  6380.               irc-nick-used
  6381.               irc-msg-info-post))
  6382.      ((= num 382)                       ; RPL_REHASHING
  6383.       (irc-insert "%sReread local ircd configuration information%s"
  6384.               irc-msg-info-pre
  6385.               irc-msg-info-post))
  6386. ;;;       ((= num 383)                       ; RPL_YOURESERVICE / Kim
  6387. ;;;        (irc-insert "DEBUG: RPL383, txt=\"%s\"." txt))
  6388. ;;;       ((= num 384)                       ; RPL_MYPORTIS / Kim
  6389. ;;;        (irc-insert "DEBUG: RPL384 txt=\"%s\"." txt))
  6390. ;;;       ((= num 385)            ; deop reply?
  6391. ;;;        (irc-insert "DEBUG: RPL385 txt=\"%s\"." txt))
  6392.      ((= num 391)                       ; RPL_TIME
  6393.       (setq irc-last-time (irc-get-time))
  6394.       (let* ((pair
  6395.           (if (string-match (concat
  6396.                      "^ *\\([^ :]+\\) *: *" ;srvr
  6397.                      "\\([A-Za-z][A-Za-z][A-Za-z]\\)"
  6398.                      "[A-Za-z]*day" ;weekday
  6399.                      " +\\(...\\)[^: ]* +" ;month
  6400.                      "\\([0-9]+\\) +"     ;monthday
  6401.                      "\\([0-9]+\\) +-* *") ;year
  6402.                     txt)
  6403.               (cons (subfield txt 1) 
  6404.                 (format "%s %s %s %s %s"
  6405.                     (substring txt (match-end 0)) ;clock
  6406.                     (subfield txt 2) ;weekday
  6407.                     (subfield txt 4) ;monthday
  6408.                     (subfield txt 3) ;month
  6409.                     (subfield txt 5))) ;year
  6410.             (progn (string-match "^\\([^: ]+\\) :" txt)
  6411.                (cons (subfield txt 1)
  6412.                  (irc-nuke-whitespace
  6413.                   (substring txt (match-end 0)))))))
  6414.          (server (car pair))
  6415.          (server (if (string= "" server) origin server))
  6416.          (date (irc-nuke-whitespace (cdr pair))))
  6417.         (irc-insert "%sLocal time at %s is %s%s%s"
  6418. ;;;             "%s%s%s local time is %s%s%s"
  6419.             irc-msg-info-pre
  6420.             (upcase server)
  6421. ;;;             (if (= ?S (aref (upcase server) (1- (length server))))
  6422. ;;;                 "'"
  6423. ;;;                 "'s")
  6424.             date
  6425.             (if (string= "0" irc-channel)
  6426.                 ""
  6427.               (concat " /" irc-channel))
  6428.             irc-msg-info-post)))
  6429.      ((or (= num 392)
  6430.           (= num 393))
  6431.       (irc-parse-notice (format ":%s NOTICE %s :%s"
  6432.                     origin user txt)))
  6433.      ((= num 394)
  6434.       (irc-insert "%sEnd of USERS at %s%s"
  6435.               irc-msg-info-pre origin irc-msg-info-post))
  6436.      ((= num 395)
  6437.       (irc-insert "%%No one logged in on Internet host %s" origin))
  6438.      (t                                 ; default
  6439.       (irc-insert (concat "%%Unrecognized numeric RPL 3xx message; "
  6440.                   "please tell %s:")
  6441.               irc-hacker)
  6442.       (irc-insert "%% str=\"%s\"." str)
  6443.       (irc-insert "%% Function irc-parse-RPL-3xx."))))
  6444.     ;; else
  6445.     (irc-insert (concat "%%Unrecognized nonnumeric RPL 3xx message follows; "
  6446.             "please tell %s:")
  6447.         irc-hacker)
  6448.     (irc-insert "%% \"%s\"." str)
  6449.     (irc-insert "%% Function irc-parse-RPL-3xx."))
  6450.   nil)
  6451.  
  6452.  
  6453. (defun irc-parse-topic (str)
  6454.   "Examine a TOPIC message from the IRC server.
  6455. TOPIC is sent to all of the users on a channel when someone changes the
  6456. topic of the channel.  Secret channels can not have the topic set.  TOPIC
  6457. messages are displayed as long as 'topic' is in irc-events, even if the user
  6458. changing the topic is being ignored.
  6459.  
  6460. This function returns t if a signal should be issued for the 'topic' event,
  6461. nil otherwise."
  6462.   (if (not (string-match "^:\\([^: ]+\\) +TOPIC +\\([^ ]*\\) *:" str))
  6463.       (progn (irc-insert "%%Unknown TOPIC command in irc-parse-topic:")
  6464.          (irc-insert "%% \"%s\"." str)
  6465.          (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  6466.     (let* ((user (subfield str 1))
  6467.        (chnl (subfield str 2))
  6468.        (topic (substring str (match-end 0)))
  6469.        (old-chnl (let ((l (irc-recall-all 'irc-subscribed-channels)))
  6470.                (while (not (atom l))
  6471.              (setq l (if (irc-is-multijoinable-channel (car l))
  6472.                      (cdr l)
  6473.                    (car l))))
  6474.                (if (listp l) "" l)))
  6475.        (channel (if (string< "" chnl) chnl old-chnl)))
  6476.       (irc-remember user 'irc-nicknames)
  6477.       (irc-remember channel 'irc-subscribed-channels)
  6478.       (irc-insert (concat "%s%s has changed the topic of channel %s to \""
  6479.               (irc-clean-up-message topic)
  6480.               "\"%s")
  6481.           irc-msg-info-pre
  6482.           user
  6483.           channel
  6484.           irc-msg-info-post)
  6485.       (if (memq 'topic irc-events)
  6486.       (irc-signal user 'topic)))))
  6487.  
  6488.  
  6489. (defun irc-parse-wall (str)
  6490.   "Examine a WALL message from the IRC server.
  6491. WALL is sent by IRC operators to everyone on IRC.  A WALL message will
  6492. always be displayed even if the sender is being ignored.
  6493.  
  6494. This function returns t if a signal should be issued for the \"wall\" event,
  6495. nil otherwise."
  6496.   (if (not (string-match "^:? *\\([^: ]*\\) +WALL +:" str))
  6497.       (progn (irc-insert (concat "%%Internal error, function irc-parse-wall"
  6498.                  " called with a non-WALL message:"))
  6499.          (irc-insert "%% \"%s\"." str)
  6500.          (irc-insert "%%Please tell %s about it." irc-hacker)
  6501.          (irc-signal "<internal-error in irc-parse-wall>" 'wall))
  6502.       (let ((user (substring str (match-beginning 1) (match-end 1)))
  6503.         (msg (substring str (match-end 0))))
  6504.     (irc-remember user 'irc-nicknames)
  6505.     (irc-insert (concat (format irc-msg-wall
  6506.                     (concat " (" (irc-get-time) ") ")
  6507.                     user)
  6508.                 msg))
  6509.     (irc-signal user 'wall))))
  6510.  
  6511.  
  6512. (defun irc-parse-wallops (str)
  6513.   "Examine a WALLOPS message from the IRC server.
  6514. WALLOPS are sent by any user to all enabled operators on IRC. A WALLOPS will
  6515. allways be displayed, even if the sender is being ignores.
  6516.  
  6517. This function returns t if a signal should be issued for the \"wall\" event,
  6518. nil otherwise."
  6519.   (if (not (string-match "^: *\\([^: ]*\\) +WALLOPS +:" str))
  6520.       (progn (irc-insert (concat "%%Internal error, function irc-parse-wallops"
  6521.                  " called with a non-WALLOPS message:"))
  6522.          (irc-insert "%% \"%s\"." str)
  6523.          (irc-insert "%%Please tell %s about it." irc-hacker)
  6524.          (irc-signal "<internal-error in irc-parse-wallops>" 'wall))
  6525.       (let* ((sender (substring str (match-beginning 1) (match-end 1)))
  6526.          (msg (substring str (match-end 0))))
  6527.     (cond ((string-match (concat "^Remote 'CONNECT \\([^ ]+\\) +"
  6528.                      "\\([0-9]*\\)' from \\([^ ]+\\) *$")
  6529.                  msg)
  6530.            (let ((nsrv (substring msg (match-beginning 1) (match-end 1)))
  6531.              (port (substring msg (match-beginning 2) (match-end 2)))
  6532.              (user (substring msg (match-beginning 3) (match-end 3))))
  6533.          (cond ((irc-is-nickname user)
  6534.             (irc-remember user 'irc-nicknames))
  6535.                ((irc-is-hostname user)
  6536.             (irc-remember user 'irc-servernames)))
  6537.          (irc-insert (concat "%sTrying to establish a serverlink from"
  6538.                      " %s to %s on port %s on remote command"
  6539.                      " by user \"%s\"%s")
  6540.                  irc-msg-info-pre
  6541.                  (upcase sender)
  6542.                  (upcase nsrv)
  6543.                  port
  6544.                  user
  6545.                  irc-msg-info-post)))
  6546.           ((string-match (concat "Received SQUIT \\([^ ]+\\) +from"
  6547.                      " +\\(.+\\) *$")
  6548.                  msg)
  6549.            (let ((oded (substring msg (match-beginning 1) (match-end 1)))
  6550.              (orig (substring msg (match-beginning 2) (match-end 2))))
  6551.          (cond ((irc-is-nickname orig)
  6552.             (irc-remember orig 'irc-nicknames))
  6553.                ((irc-is-hostname orig)
  6554.             (irc-remember orig 'irc-servernames)))
  6555.          (irc-insert (concat "%sClosing the serverlink from %s to"
  6556.                      " server %s, by order of %s%s")
  6557.                  irc-msg-info-pre
  6558.                  (upcase sender)
  6559.                  (upcase oded) ;OD'ed server
  6560.                  (upcase orig)
  6561.                  irc-msg-info-post)))
  6562.           (t (let* ((head (format "%s%s" (concat
  6563.                           (format (format irc-msg-priv 0) 
  6564.                               (concat " ("
  6565.                                   (irc-get-time)
  6566.                                   ") ")
  6567.                               (concat sender
  6568.                                   " (WALLOPS)")))))
  6569.             (irc-msg-cont-used (make-string
  6570.                         (min
  6571.                          (length head)
  6572.                          (/ (window-width
  6573.                          (get-buffer-window
  6574.                           (current-buffer)))
  6575.                         2))
  6576.                         ? )))
  6577.            (cond ((and (irc-is-hostname sender)
  6578.                    (not (irc-is-nickname sender)))
  6579.               (irc-remember sender 'irc-servernames))
  6580.              ((irc-is-nickname sender)
  6581.               (irc-remember sender 'irc-nicknames)))
  6582.            (irc-insert (concat head (irc-clean-up-message msg))))))
  6583.     (if (irc-is-nickname sender)
  6584.         (irc-signal sender 'wall)
  6585.         (irc-later-execute-lusers)))))
  6586.  
  6587.  
  6588. (defun irc-parse-whoreply (str)
  6589.   "OBSELETE FUNCTION
  6590.  
  6591. Examine a WHOREPLY message from the IRC server.
  6592. The message is formatted into a line that is more easily understood than
  6593. the raw data.  
  6594. The status of the users is shown as a four letter word (:-) according to
  6595. the combination of their attributes. The possible attributes being
  6596. an IRC operator, being a channel operator and being marked away.
  6597.  
  6598.                                           Status field
  6599. A normal user having no attributes set:     (blank)
  6600. A normal user marked as being away:          Away
  6601. An IRC operator with no other attribues:     Iopr
  6602. An IRC operator marked as being away:        IoAw
  6603. A channel operator with no other attributes: Copr
  6604. A channel operator marked as being away:     CoAw
  6605. User being both IRC- and channel operator:   ICop
  6606. As above but also marked as being away:      ICAw
  6607.  
  6608. Being ignored takes precedence over all
  6609. other attributes, always shown as:           IGNR
  6610.  
  6611.  
  6612. No signals are issued for lines from the WHOREPLY."
  6613.   (string-match "^WHOREPLY +" str)
  6614.   (setq str (substring str (match-end 0)))
  6615.   (let ((is-header (or (string-match (concat "^\\* +User +Host +Server"
  6616.                          " +Nickname +S +: *Name *$")
  6617.                      str)
  6618.                (string-match (concat "^Channel +User +Host +Server"
  6619.                          " +Nickname +S +: *Name *$")
  6620.                      str)))
  6621.     (split))          ; make this a list of strings of each data item.
  6622.     ;; the elements of 'split' are:
  6623.     ;; 0 - full name (with possible hop count)
  6624.     ;; 1 - status
  6625.     ;; 2 - nickname
  6626.     ;; 3 - hostname of server
  6627.     ;; 4 - hostname of client
  6628.     ;; 5 - login name
  6629.     ;; 6 - channel
  6630.     (if (or (string-match (concat "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)"
  6631.                   " +\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)"
  6632.                   " +:\\([0-9]+\\)? *\\(.+\\)$")
  6633.               str))
  6634.     (let* ((channel (subfield str 1))
  6635.            (x-login-name (subfield str 2))
  6636.            (x-client-host (subfield str 3))
  6637.            (x-server-host (subfield str 4))
  6638.            (x-nickname (subfield str 5))
  6639.            (x-status (subfield str 6))
  6640.            (hop-count (subfield str 7))
  6641.            (x-full-name (subfield str 8))
  6642.            (name-col (string-match "-* *$" irc-who-stroke)) ;Last stroke
  6643.            (chan-col (string-match "-* +-+ *$" irc-who-stroke)) ;2nd last
  6644.            )
  6645.       (if (not (string= x-status "S")) ;Header?
  6646.           (progn
  6647.         ;; if it isn't the bogus header
  6648.         (irc-remember x-nickname 'irc-nicknames) ; add nick
  6649.         (if (and (not is-header)
  6650.              (irc-terminal-is-slow)
  6651.              (irc-server-has-end-of-who)
  6652.              (irc-nothing-remembered-p 'irc-whotree))
  6653.             (let ((irc-msg-cont-used
  6654.                (make-string name-col ? )))
  6655.               (irc-insert irc-who-header)
  6656.               (irc-insert irc-who-stroke)
  6657.               ;;(sit-for 0)
  6658.               (set-buffer-modified-p (buffer-modified-p))))
  6659.         (irc-remember x-server-host 'irc-servernames) ; hostnames.
  6660.         (irc-remember x-client-host 'irc-servernames)))
  6661.       (let* ((full-name (irc-clean-up-message
  6662.                  x-full-name))
  6663.          (nick-pad (make-string (max 0 (- (1- 10) (length x-nickname)))
  6664.                     ? ))
  6665.          (vsts (cond ((irc-recall x-nickname 'irc-ignored-ppl) "IGNR")
  6666.                  ((string= "H"   x-status) "    ") ;Norm
  6667.                  ((string= "G"   x-status) "Away") ;Away
  6668.                  ((string= "H*"  x-status) "Iopr") ;Iopr
  6669.                  ((string= "G*"  x-status) "IoAw") ;IoAw
  6670.                  ((string= "H@"  x-status) "Copr") ;Copr
  6671.                  ((string= "G@"  x-status) "CoAw") ;CoAw
  6672.                  ((string= "H*@" x-status) "ICop") ;ICop
  6673.                  ((string= "G*@" x-status) "ICAw") ;ICAw
  6674.                  ((string= "S"   x-status) "    ") ;Norm
  6675.                  (t (concat "\"" x-status "\""))))
  6676.          (vchnl (irc-format-channel
  6677.              (cond ((string= "-1" channel) "-")
  6678.                    ((string= "0" channel) "")
  6679.                    ((string= "*" channel) "")
  6680.                    (t channel))))
  6681.          (vusr (irc-clean-up-message x-login-name))
  6682.          (vclt (irc-clean-up-message x-client-host))
  6683.          (vsrv (irc-clean-up-message x-server-host))
  6684.           (line (format "%s%s %s %s <%s> %s@%s \"%s\" SERVER=%s"
  6685.                    x-nickname nick-pad vsts vchnl hop-count vusr
  6686.                    vclt full-name vsrv))
  6687.           (line (format "%s%s %s %s %s@%s \"%s\""
  6688.                    x-nickname nick-pad vsts vchnl vusr
  6689.                    vclt full-name))
  6690. ;         (line (format "%s%s %s %s@%s \"%s\""
  6691. ;                   x-nickname nick-pad vsts vusr vclt full-name))
  6692.          (irc-msg-cont-used (make-string 31 ? )))
  6693.         (if (and (irc-terminal-is-slow) (irc-server-has-end-of-who))
  6694.         (if (not is-header)
  6695.             (progn
  6696.               (setq irc-reply-count (1+ irc-reply-count))
  6697.               (let ((diff (irc-time-diff (irc-current-time)
  6698.                          irc-reply-count-time)))
  6699.             (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since
  6700.                    (> (nth 0 diff) 0)) ; last display?
  6701.                    (setq irc-reply-count-time (irc-current-time))
  6702.                    (message (format " %d nick%s ..."
  6703.                         irc-reply-count
  6704.                         (if (= 1 irc-reply-count)
  6705.                             ""
  6706.                             "s"))))))
  6707.               (irc-remember line 'irc-whotree)))
  6708.         (if is-header        ;No RPL_ENDOFWHO
  6709.             (let ((irc-msg-cont-used
  6710.                (make-string (string-match "-* *$" irc-who-stroke)
  6711.                     ? )))
  6712.               (irc-insert irc-who-header)
  6713.               (irc-insert irc-who-stroke))
  6714.             (irc-insert "%s" (irc-clean-up-message line))))))
  6715.     (irc-insert "%%Unkown WHOREPLY line: \"%s\"." str)))
  6716.     nil)
  6717.  
  6718.  
  6719. (defun irc-explain-channel-mode (mode &optional skip-direction)
  6720.   "Front end to irc-explain-mode."
  6721.   (irc-explain-mode mode 'channel skip-direction))
  6722.  
  6723.  
  6724. (defun irc-explain-user-mode (mode &optional skip-direction)
  6725.   "Front end to irc-explain-mode."
  6726.   (irc-explain-mode mode 'user skip-direction))
  6727.   
  6728.  
  6729. (defun irc-explain-mode (mode type &optional skip-direction)
  6730.   "Translate a channels MODE code into plain text. Use optional FLAG when
  6731. addition / removal information shouldn't be added."
  6732.   (let* ((known-modes '(((?a 0 "anonymous <A>")
  6733.              (?b 1 "ban (from channel) <B>" " of " " of ")
  6734.              (?i 0 "invite only <I>")
  6735.              (?k 1 "channel key <K> ")
  6736.              (?l 1 "limit number of users on channel <L>" " to ")
  6737.              (?m 0 "moderated <M>")
  6738.              (?n 0 "disallow nonlisteners to talk to channel <N>")
  6739.              (?o 1 "channel operator privilege <O>"
  6740.                    " for " " for ")
  6741.              (?p 0 "private <P>")
  6742.              (?s 0 "secret <S>")
  6743.              (?t 0 "topic lock <T>")
  6744.              (?v 1 "voice capability <V>" " to " " to "))
  6745.             .
  6746.             ((?i 0 "invisibility <I>")
  6747.              (?o 0 "IRC-operator <O>")
  6748.              (?s 0
  6749.               "subscription to local server status messages <S>")
  6750.              (?w 0 "subscription to WALLOPS <W>"))))
  6751.      (modes (cond ((eq type 'channel) (car known-modes))
  6752.               ((eq type 'user) (cdr known-modes))
  6753.               (t nil)))
  6754.      (cmds (if (string-match " +" mode) 
  6755.            (substring mode 0 (match-beginning 0))
  6756.            mode))
  6757.      (args (substring mode (length cmds)))
  6758.      (dir "added ")
  6759.      (argl ())
  6760.      (expl ""))
  6761.     (while (string-match "^ *\\([^: ]+\\)" args)
  6762.       (setq argl (append argl (list (subfield args 1)))
  6763.         args (substring args (match-end 1))))
  6764.     (while (not (string= cmds ""))
  6765.       (let ((c (string-to-char (substring cmds 0 1))))
  6766.     (cond ((= ?+ c) (setq dir "added "))
  6767.           ((= ?- c) (setq dir "removed "))
  6768.           (t (let ((p (assoc c modes)))
  6769.            (setq expl (concat expl
  6770.                       ", "
  6771.                       (if (not skip-direction) dir)
  6772.                       (if p
  6773.                       (nth 2 p)
  6774.                       (concat irc-msg-info-pre
  6775.                           "UNKNOWN '"
  6776.                           (char-to-string c)
  6777.                           "'"
  6778.                           irc-msg-info-post))
  6779.                       (cond ((and (string= dir "added ")
  6780.                           (nth 3 p))
  6781.                          (nth 3 p))
  6782.                         ((and (string= dir "removed ")
  6783.                           (nth 4 p))
  6784.                          (nth 4 p))
  6785.                         (t ""))
  6786.                       (let ((n (or (nth 1 p) 0))
  6787.                         (s ""))
  6788.                     (while (and (> n 0) (car argl))
  6789.                       (setq s (concat s (car argl))
  6790.                         argl (cdr argl)
  6791.                         n (1- n)))
  6792.                     s)))))))
  6793.       (setq cmds (substring cmds 1)))
  6794.     (concat (cond ((string-match "^\\(, *\\)[\000-\377]*\\(,\\) [^,]+" expl)
  6795.            (concat (substring expl (match-end 1) (match-beginning 2))
  6796.                " and"
  6797.                (substring expl (match-end 2))))
  6798.           ((string-match "^\\(, *\\)" expl)
  6799.            (substring expl (match-end 1)))
  6800.           ((string= expl "") (if skip-direction "normal" "none"))
  6801.           (t expl))
  6802.         (if (and (= (length argl) 1)
  6803.              (string-match "^[0-9]+$" (car argl)))
  6804.         (concat "; user limit is " (car argl))
  6805.         (progn (if (not (equal argl ()))
  6806.                (progn (irc-insert (concat "%%Warning: parts left"
  6807.                               " unparsed in function"
  6808.                               " irc-explain-mode."))
  6809.                   (irc-insert "%% \"%s\" (mode)." mode)
  6810.                   (irc-insert (concat "%% Please tell %s, it"
  6811.                               " might be a bug.")
  6812.                           irc-hacker))
  6813.                ""))))))
  6814.  
  6815. ;;;(defun irc-explain-who-mode (mode)
  6816. ;;;  ""
  6817. ;;;   (cond ((irc-recall x-nickname 'irc-ignored-ppl) "IGNR")
  6818. ;;;                 ((string= "H"   mode) "    ") ;Norm
  6819. ;;;                 ((string= "G"   mode) "Away") ;Away
  6820. ;;;                 ((string= "H*"  mode) "Iopr") ;Iopr
  6821. ;;;                 ((string= "G*"  mode) "IoAw") ;IoAw
  6822. ;;;                 ((string= "H@"  mode) "Copr") ;Copr
  6823. ;;;                 ((string= "G@"  mode) "CoAw") ;CoAw
  6824. ;;;                 ((string= "H*@" mode) "ICop") ;ICop
  6825. ;;;                 ((string= "G*@" mode) "ICAw") ;ICAw
  6826. ;;;                 ((string= "S"   mode) "    ") ;Norm
  6827. ;;;                 (t (concat "\"" mode "\""))))
  6828.  
  6829. (defun irc-ctcp-dequote (str)
  6830.   "Return STRING with quoted characters changed into the unquoted equivalents."
  6831.   (let ((new ""))
  6832.     (while (string-match "\\\\" str)    ;Get to next backslash, if any
  6833.       (let ((pos (match-beginning 0)))
  6834.     (if (>= (- (length str) pos) 2)
  6835.         (setq new (concat new
  6836.                   (substring str 0 pos)
  6837.                   (irc-ctcp-dequote-char (aref str (1+ pos))))
  6838.           str (substring str (+ 2 pos)))
  6839.         (irc-insert (concat "%%Received badly quoted CTCP string, ignored"
  6840.                 " superfluous backslash."))
  6841.         (setq new (concat new (substring str 0 pos))
  6842.           str (substring str (1+ pos))))))
  6843.     (concat new str)))
  6844.  
  6845.  
  6846. (defun irc-ctcp-dequote-char (char)
  6847.   "Map a two character STRING to it's corresponding character."
  6848.   (char-to-string (cond ((= char ?a) ?\001)
  6849.             ((= char ?\\) ?\\)
  6850.             (t char))))
  6851.  
  6852.  
  6853. (defun irc-ctcp-enquote (str)
  6854.   "Enquote a STRING, exchanging some characters to two character combinations."
  6855.   (let ((d "")
  6856.     (dirty "[\001\\]"))
  6857.     (while (string-match dirty str)
  6858.       (setq d (concat d
  6859.               (substring str 0 (match-beginning 0))
  6860.               (irc-ctcp-enquote-char (aref str (match-beginning 0))))
  6861.         str (substring str (match-end 0))))
  6862.     (concat d str)))
  6863.  
  6864.  
  6865. (defun irc-ctcp-enquote-char (char)
  6866.   "Map a character to it's corresponding one or two character STRING."
  6867.   (cond ((= char ?\001) "\\a")
  6868.     ((= char ?\\) "\\\\")
  6869.     (t (char-to-string char))))
  6870.  
  6871.  
  6872. (defun irc-lowlevel-dequote (str)
  6873.   "Return STRING with quoted characters changed into the unquoted equivalents."
  6874.   (let ((new ""))
  6875.     (while (string-match "\020" str)
  6876.       (let ((pos (match-beginning 0)))
  6877.     (if (< pos (1- (length str)))
  6878.         (setq new (concat new
  6879.                   (substring str 0 pos)
  6880.                   (irc-lowlevel-dequote-char (aref str (1+ pos))))
  6881.           str (substring str (+ 2 pos)))
  6882.         (setq new (concat new
  6883.                   (substring str 0 pos)
  6884.                   "<<ERROR in senders client: unquoted CNTRL/P>>")
  6885.           str "")
  6886.         )))
  6887.     (concat new str)))
  6888.  
  6889.  
  6890. (defun irc-lowlevel-dequote-char (char)
  6891.   "Map the CHARACTER after a \020 to it's corresponding character."
  6892.   (char-to-string (cond ((= char ?0) ?\000)
  6893.             ((= char ?n) ?\n)
  6894.             ((= char ?r) ?\r)
  6895.             ((= char ?\020) ?\020)
  6896.             (t char))))
  6897.  
  6898.  
  6899. (defun irc-lowlevel-enquote (str)
  6900.   "Enquote a STRING, exchanging some characters to two character combinations."
  6901.   (let ((d "")
  6902.     (dirty "[\000\n\r\020]"))
  6903.     (while (string-match dirty str)
  6904.       (setq d (concat
  6905.            d
  6906.            (substring str 0 (match-beginning 0))
  6907.            (irc-lowlevel-enquote-char (aref str (match-beginning 0))))
  6908.         str (substring str (match-end 0))))
  6909.     (concat d str)))
  6910.  
  6911.  
  6912. (defun irc-lowlevel-enquote-char (char)
  6913.   "Map a character to it's corresponding one or two character STRING."
  6914.   (cond ((= char ?\000) "\0200")
  6915.     ((= char ?\n) "\020n")
  6916.     ((= char ?\r) "\020r")
  6917.     ((= char ?\020) "\020\020")
  6918.     (t (char-to-string char))))
  6919.  
  6920.  
  6921. (defun irc-show-subscribed-channels ()
  6922.   "Show which channel's user is listening to, and which one is talked to."
  6923.   (if (not irc-multiple-leave-in-progress)
  6924.       (let ((listen (irc-clean-up-message
  6925.              (irc-listify
  6926.               (irc-recall-all 'irc-subscribed-channels)
  6927.               ", "
  6928.               "and"))))
  6929.     (cond ((irc-nothing-remembered-p 'irc-subscribed-channels)
  6930.            (cond ((string= "0" irc-channel)
  6931.               (irc-insert (concat "%sYou're neither listening nor"
  6932.                       " talking to any channel%s")
  6933.                   irc-msg-info-pre
  6934.                   irc-msg-info-post))
  6935.              (t (irc-insert (concat "%sYou're now talking and"
  6936.                         " listening to channel %s%s")
  6937.                     irc-msg-info-pre
  6938.                     irc-channel
  6939.                     irc-msg-info-post))))
  6940.           ((string= "0" irc-channel)
  6941.            (irc-insert (concat "%sYou're not talking to any channel, but"
  6942.                    " listening to %s%s")
  6943.                irc-msg-info-pre
  6944.                listen
  6945.                irc-msg-info-post))
  6946.           (t (let* ((part-1 (format "%sYou are now talking to channel "
  6947.                     irc-msg-info-pre))
  6948.             (irc-msg-cont-used (make-string (length part-1) ? )))
  6949.            (irc-insert "%s%s, while listening to %s%s"
  6950.                    part-1
  6951.                    irc-channel
  6952.                    listen
  6953.                    irc-msg-info-post)))))
  6954.       (set-buffer-modified-p (buffer-modified-p)))
  6955.   nil)
  6956.  
  6957.  
  6958. (defun irc-server-has-end-of-who ()
  6959.   "True if the current server end WHOREPLY with a \"end of list\" message."
  6960.   (or (> irc-major-version 2)
  6961.       (and (= irc-major-version 2)
  6962.        (>= irc-minor-version 4))))
  6963.  
  6964.  
  6965. (defun irc-server-has-end-of-names ()
  6966.   "True if the current server end NAMREPLY with a \"end of list\" message."
  6967.   (or (> irc-major-version 2)
  6968.       (and (= irc-major-version 2)
  6969.        (>= irc-minor-version 4))))
  6970.  
  6971.  
  6972. (defun irc-server-has-end-of-links ()
  6973.   "True if the current server end LINREPLY with a \"end of list\" message."
  6974.   (or (> irc-major-version 2)
  6975.       (and (= irc-major-version 2)
  6976.        (>= irc-minor-version 4))))
  6977.  
  6978.  
  6979. (defun irc-server-has-non-numeric-channel-names ()
  6980.   "True if the current server supports non nummeric IDs for channels."
  6981.   (or (> irc-major-version 2)
  6982.       (and (= irc-major-version 2)
  6983.        (or (> irc-minor-version 4)
  6984.            (and (= irc-minor-version 4)
  6985.             (>= irc-edit-version 2))))))
  6986.  
  6987.  
  6988. (defun irc-server-has-multijoinable-channels ()
  6989.   "True if the current server supports #-type channels and the commands JOIN
  6990. and PART. Probaly v2.6 or later."
  6991.   (or (> irc-major-version 2)
  6992.       (and (= irc-major-version 2)
  6993.        (>= irc-minor-version 6))))
  6994.  
  6995.  
  6996. (defun irc-server-has-channelname-in-msgs ()
  6997.   "True if the server gives the channels name in a RPL_CHANNELMODEIS message."
  6998.   (or (> irc-major-version 2)
  6999.       (and (>= irc-major-version 2)
  7000.        (or (> irc-minor-version 6)
  7001.            (and (>= irc-minor-version 6)
  7002.             (>= irc-edit-version 19))))))
  7003.  
  7004.  
  7005. (defun irc-server-has-end-of-whois ()
  7006.   "True if the server ends WHOIS replies with an enad marker."
  7007.   (or (> irc-major-version 2)
  7008.       (and (>= irc-major-version 2)
  7009.        (or (> irc-minor-version 6)
  7010.            (and (>= irc-minor-version 6)
  7011.             (>= irc-edit-version 20))))))
  7012.  
  7013.  
  7014. (defun irc-server-has-settable-topic-on-multijoinable-channel ()
  7015.   "True if the server supports setting topic for a multijoinable channel."
  7016.   (or (> irc-major-version 2)
  7017.       (and (>= irc-major-version 2)
  7018.        (>= irc-minor-version 7))))
  7019.  
  7020.  
  7021. (defun irc-active-servers ()
  7022.   "Return list of active IRC processes."
  7023.   (let ((lst (if (boundp 'irc-processes) irc-processes))
  7024.     (act nil))
  7025.     (while (consp lst)
  7026.       (if (and (memq (process-status (car lst)) '(open run))
  7027.            (stringp (buffer-name (process-buffer (car lst)))))
  7028.       (setq act (cons (car lst) act)))
  7029.       (setq lst (cdr lst)))
  7030.     (reverse act)))
  7031.  
  7032.  
  7033. (defun irc-host+port-to-buffer-name (host-name port-number)
  7034.   "Return a legal buffer name for a Kiwi session."
  7035.   (cond ((or (not (numberp port-number))
  7036.          (> 0 port-number)
  7037.          (> port-number 65535))
  7038.      (error (format "Kiwi: \"%s\" illegal TCP-port number" port-number)))
  7039.     (t (format "*Kiwi-%s/%d*" host-name port-number))))
  7040.  
  7041.  
  7042. (defun irc-host+port-to-buffer (host-name port-number)
  7043.   "Return the buffer a HOST-NAME in a Kiwi session is associated with.
  7044. If no such buffer exist, create it.
  7045.  
  7046. See also: irc-host-to-buffer-name <f>"
  7047.   (get-buffer-create (irc-host+port-to-buffer-name host-name port-number)))
  7048.  
  7049.  
  7050. (defun irc-session-to-buffer (session)
  7051.   "Convert a Kiwi SESSION (ie host name) to its associated buffer.
  7052. The buffer must exist."
  7053.   (get-buffer session))
  7054.  
  7055.  
  7056. (defun irc-session-names (proc-list)
  7057.   "Convert a LIST of Kiwi processes to a list of the processes host names."
  7058.   (mapcar (function (lambda (p)
  7059.          (buffer-name (process-buffer p))))
  7060.       proc-list))
  7061.  
  7062.  
  7063. (defun irc-get-host-from-session-name (session-name)
  7064.   "Extract the host name associated with a SESSION-NAME."
  7065.   (if (string-match irc-legal-session-name session-name)
  7066.       (subfield session-name 1)
  7067.       (error (format "Illegal session-name: \"%s\"." session-name))))
  7068.  
  7069.  
  7070. (defun irc-get-port-from-session-name (session-name)
  7071.   "Extract the TCP/IP port number associated with a SESSION-NAME."
  7072.   (if (string-match irc-legal-session-name session-name)
  7073.       (string-to-int (subfield session-name 2))
  7074.       (error (format "Illegal session-name: \"%s\"." session-name))))
  7075.  
  7076.  
  7077. (defun irc-terminal-is-slow ()
  7078.   "True if the terminal's speed (baud-rate) is lower than the variable
  7079. \"search-slow-speed\" (the variable is defined in either file loaddefs.el or
  7080. isearch.el in the lisp subdirectory)."
  7081.   (if (not (boundp 'search-slow-speed))    ;This should never happen.
  7082.       (progn (load "loaddefs"))
  7083.       (if (not (boundp 'search-slow-speed))
  7084.       (load "isearch"))
  7085.       (if (not (boundp 'search-slow-speed))
  7086.       (setq search-slow-speed 1200)))
  7087. ;;;  (if (boundp 'baud-rate)
  7088. ;;;      (<= baud-rate search-slow-speed)
  7089. ;;;    (<= (baud-rate) search-slow-speed))
  7090.   t)                    ;Patched.
  7091.  
  7092.  
  7093. (defun irc-non-num-to-0 (x)
  7094.   (if (numberp x)
  7095.       x
  7096.       0))
  7097.  
  7098.  
  7099. (defun irc-pong ()
  7100.   "Send a PONG message with the hostname as an argument.
  7101. This is usually used to answer a PING message."
  7102.   ;; it's interactive so it can be bound during testing.
  7103.   (interactive)
  7104.   (irc-send (concat "PONG :" (system-name)))
  7105.   (irc-who-is-on)
  7106.   nil)
  7107.  
  7108.  
  7109. (defun irc-new-scroll-step (scroll-step)
  7110.   "Calculate a new scroll-step value based on the current windows height
  7111. if terminal is slow (see function irc-terminal-is-slow)."
  7112.   (cond ((and (boundp 'irc-scroll-step)
  7113.           (numberp irc-scroll-step))
  7114.      irc-scroll-step)
  7115.     ((irc-terminal-is-slow)
  7116.      (let* ((h (- (window-height) 3))
  7117.         (x (- h (/ h 6))))
  7118.        (if (> window-min-height x)
  7119.            1
  7120.            (if (> (* 2 window-min-height) x)
  7121.            (/ x 2)
  7122.            x))))
  7123.     (t scroll-step)))        ;Else use old value.
  7124.  
  7125.  
  7126. (defun irc-last-found (str left-most char)
  7127.   "Search in STRING, position LEFT-MOST to end of string, for a CHARacter.
  7128. Return its position, or nil if not found."
  7129.   (let* ((n (length str))
  7130.      (m (while (and (>= n left-most)
  7131.             (not (= char (string-to-char (substring str n nil)))))
  7132.           (setq n (1- n)))))
  7133.     (if (>= n left-most) (1+ n) nil)))
  7134.  
  7135.  
  7136. (defun irc-choose-break-point (str left-most right-most delimiters)
  7137.   "Choose a nice point to break a string in. Break at a delimiting
  7138. character like space, bang or comma. Return a list of two strings,
  7139. the part before and the part after the breakpoint."
  7140.   (cond
  7141.     ((string-match "\n" str)
  7142.      (irc-split-string str (string-match "\n" str)))
  7143.     ((< (length str) right-most)
  7144.      (irc-split-string str (length str)))
  7145.     (t (let ((s (substring str 0 (1- right-most))))
  7146.      (if (or (null delimiters)
  7147.          (<= (min left-most (length str))
  7148.              0))
  7149.          (irc-split-string str (1- right-most))
  7150.          (let ((possible (irc-last-found s left-most (car delimiters))))
  7151.            (if possible
  7152.            (irc-split-string str possible)
  7153.            (irc-choose-break-point str
  7154.                        left-most
  7155.                        right-most
  7156.                        (cdr delimiters)))))))))
  7157.  
  7158.  
  7159. (defun irc-split-string (str n)
  7160.   "Split string STR into two at position N, trimming all white space
  7161. around the split point."
  7162.   (let* ((x (min n (length str)))
  7163.      (first-half (substring str 0 x))
  7164.      (second-half (substring str x))
  7165.      (a (progn (string-match "[\n\t ]*$" first-half)
  7166.            (match-beginning 0)))
  7167.      (b (progn (string-match "^[\n\t ]*" second-half)
  7168.            (match-end 0))))
  7169.     (cons (substring first-half 0 a)
  7170.       (substring second-half (match-end 0)))))
  7171.  
  7172.  
  7173. (defun irc-insert (format &rest args)
  7174.   "Insert before irc-mark the string created by FORMAT with substituted ARGS.
  7175. Resets the global variable \"scroll-step\" each time. If the string is to long
  7176. to be inserted on one line, insert just first part and give the rest to
  7177. \"irc-insert-more\"."
  7178.   (setq scroll-step (irc-new-scroll-step scroll-step))
  7179.   (let* ((str (apply 'format format args))
  7180.      (strlen (length str))
  7181.      (left-most (* (/ (window-width (get-buffer-window (current-buffer)))
  7182.               3)
  7183.                2))
  7184.      (splitted (irc-choose-break-point
  7185.             str
  7186.             left-most
  7187.             (window-width (get-buffer-window (current-buffer)))
  7188.             '(?, ?  ?\050 ?! ?? ?. ?\051)))
  7189.      (first-half (car splitted))
  7190.      (second-half (cdr splitted)))
  7191.     (save-excursion
  7192.       (goto-char (if (and (boundp 'irc-mark) (markerp irc-mark))
  7193.              irc-mark
  7194.              (point-max)))
  7195.       (insert-before-markers first-half "\n")
  7196.       (if (not (string= "" second-half))
  7197.       (irc-insert-more irc-msg-cont-used left-most second-half)))))
  7198.  
  7199.  
  7200. (defun irc-insert-more (continue left-most str)
  7201.   "Insert before irc-mark the line created by concatenating the CONTINUE string
  7202. and the MESSAGE string. If the line is to long, insert the first part and 
  7203. recurse with the rest."
  7204.   (let* ((cont (substring continue 0 (min (/ (* 3 (window-width
  7205.                            (get-buffer-window
  7206.                             (current-buffer))))
  7207.                          4)
  7208.                       (length continue))))
  7209.      (splitted (irc-choose-break-point str ;;QUICK ugly bug fix.... bleah!
  7210.                        (max 0 (- left-most (length cont)))
  7211.                        (- (window-width (get-buffer-window
  7212.                                  (current-buffer)))
  7213.                           (length cont))
  7214.                        '(?, ?  ?\( ?! ?? ?. ?;)))
  7215.      (first-half (concat cont (car splitted)))
  7216.      (second-half (cdr splitted)))
  7217.     (insert-before-markers first-half "\n")
  7218.     (if (not (string= "" second-half))
  7219.     (irc-insert-more cont left-most second-half))))
  7220.  
  7221.  
  7222. (defun irc-fix-wordwrap (line1 line2)
  7223.   "With arguments LINE1 and LINE2 apply some simple heuristics to see if the
  7224. line which they originally formed was broken in an acceptable place.  Returns
  7225. a dotted pair with LINE1 as the car and LINE2 as the cdr."
  7226.   (cond ((string-match "^ +" line2)
  7227.          ;; broke at whitespace; strip leading space from next line
  7228.          (setq line2 (substring line2 1)))
  7229.         ((string-match " +$" line1)
  7230.          ;; trailing whitespace on line.  might as well just nuke it all.
  7231.          (setq line1 (substring line1 0 (match-beginning 0))))
  7232.         ((string-match "\\( +\\)[^: ]+$" line1)
  7233.          ;; broke in a word, but it's wrappable.  just eat one space.
  7234.          (setq line2 (concat (substring line1 (1+ (match-beginning 1))) line2)
  7235.                line1 (substring line1 0 (match-beginning 0)))))
  7236.   (cons line1 line2))
  7237.  
  7238.  
  7239.  
  7240. ;; simple key functions -- self-insert, tab, destructive backspace
  7241. (defun irc-self-insert (arg)
  7242.   "Normaly just inserts the typed character in the input region.
  7243. If point is in the output region, irc-spacebar-pages is non-nil and a space
  7244. is typed, scroll-up otherwise point moves to end of input region and inserts
  7245. the character.
  7246.  
  7247. If the character to be inserted is a colon or semi-colon and it is the first
  7248. non-white space character on the line then the input region is updated to
  7249. begin with the last explicit sendlist, irc-last-explicit.
  7250.  
  7251. Inserts the character ARG times if self-inserting.  An argument is not
  7252. passed to scroll-up if paging with the spacebar."
  7253.   (interactive "p")
  7254.   (let* ((in-region (>= (point) irc-mark))
  7255.      (mapped (assoc last-command-char
  7256.             '((?\100 . ?\311)
  7257.               (?\133 . ?\304)
  7258.               (?\134 . ?\326)
  7259.               (?\135 . ?\305)
  7260.               (?\136 . ?\334)
  7261.               (?\140 . ?\351)
  7262.               (?\173 . ?\344)
  7263.               (?\174 . ?\366)
  7264.               (?\175 . ?\345)
  7265.               (?\176 . ?\374))))
  7266.      (invmapped (assoc last-command-char
  7267.                '((?\100 . ?\311)
  7268.                  (?\133 . ?\344)
  7269.                  (?\134 . ?\366)
  7270.                  (?\135 . ?\345)
  7271.                  (?\136 . ?\334)
  7272.                  (?\140 . ?\351)
  7273.                  (?\173 . ?\304)
  7274.                  (?\174 . ?\326)
  7275.                  (?\175 . ?\305)
  7276.                  (?\176 . ?\374))))
  7277.      (chr (if (and irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1
  7278.                mapped)
  7279.           (cdr (if (eq t irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1)
  7280.                mapped
  7281.              invmapped))
  7282.           last-command-char))
  7283.          ;; it's times like this that i wish someone would tell me what
  7284.          ;; a good indentation style is for this expression
  7285.          (expand-colon
  7286.           (and
  7287.        (or (= last-command-char ?\;) (= last-command-char ?:))
  7288.            (string-match "^ *$"
  7289.              (buffer-substring
  7290.               irc-mark
  7291.               (if in-region (point) (point-max)))))))
  7292.     (if (not expand-colon)
  7293.         (if in-region
  7294.         (while (> arg 0)
  7295.           (insert chr)
  7296.           (setq arg (1- arg)))
  7297.         ;; else
  7298.         (if (and irc-spacebar-pages
  7299.              (= last-command-char 32))
  7300.         ;; it's nice to be able to return to the input region just by
  7301.         ;; pounding on the spacebar repeatedly.
  7302.         (condition-case EOB (scroll-up nil)
  7303.           (end-of-buffer (goto-char (point-max))))
  7304.         (goto-char (point-max))
  7305.         (while (> arg 0)
  7306.           (insert chr)
  7307.           (setq arg (1- arg)))))
  7308.     (or in-region (goto-char (point-max)))
  7309.     ;; Kill white space. This also takes out previous lines in
  7310.     ;; input region.
  7311.     (delete-region irc-mark (point))
  7312.     (insert (if (= last-command-char ?:) irc-last-private irc-last-explicit))
  7313.     ;; put in the extra characters if need be.
  7314.     (setq arg (1- arg))
  7315.     (while (> arg 0)
  7316.       (insert chr)
  7317.       (setq arg (1- arg))))))
  7318.  
  7319.  
  7320. (defun irc-del-backward-char (arg)
  7321.   "If in the input region, delete ARG characters before point, restricting
  7322. deletion to the input region.  If in the output region and irc-spacebar-pages
  7323. then scroll-down (aka window-back) otherwise do nothing."
  7324.   (interactive "p")
  7325.   (if (> (point) irc-mark)
  7326.       ;; only delete as far back as irc-mark at most
  7327.       (if (> arg (- (point) irc-mark)) (delete-region (point) irc-mark)
  7328.       (delete-backward-char arg))
  7329.       (if (and (<= (point) irc-mark) irc-spacebar-pages) (scroll-down nil)
  7330.       (ding))))
  7331.  
  7332.  
  7333. (defun irc-tab ()
  7334.   "If point is in the input region then tab-to-tab-stop.  If it is in the
  7335. output region, go to the previous line if irc-spacebar-pages; do nothing
  7336. otherwise."
  7337.   (interactive)
  7338.   (if (>= (point) irc-mark) (tab-to-tab-stop)
  7339.       (if irc-spacebar-pages (previous-line 1)
  7340.       (ding))))
  7341.  
  7342.  
  7343.  
  7344. ;; top-level -- entry, sentinel and mode
  7345. (defun irc (&optional universal-argument)
  7346.   "Enter the Internet Relay Chat conferencing system.
  7347. If no connexion to an irc-server is open, then one is started.  If no buffer
  7348. *IRC* exists then it is created otherwise the existing buffer is used.  If
  7349. a connexion is already active then the most recently started IRC session
  7350. is switched to in the current window.  This makes binding 'irc' to a key
  7351. much more convenient.
  7352.  
  7353. With prefix argument NEW-BUFFER, another *IRC* buffer is created and a
  7354. new IRC session is started.  This is provided so that multiple IRC
  7355. sessions can co-exist in one Emacs, which is sometimes a useful thing."
  7356.   (interactive "P")
  7357.   (let* ((act (irc-active-servers))
  7358.      (session-names (irc-session-names act))
  7359.      (number-of-sessions (length session-names))
  7360.      (ask-for-session (> number-of-sessions 1))
  7361.      (session (let ((s (if ask-for-session
  7362.                    (irc-nuke-whitespace
  7363.                 (irc-read-object
  7364.                  "Select which Kiwi session? (RET for new) "
  7365.                  ""
  7366.                  session-names))
  7367.                    "")))
  7368.             (if (or (irc-member-general s
  7369.                         session-names
  7370.                         'string=)
  7371.                 (string= "" s))
  7372.             s
  7373.             (error (format "No such active session: %s" s)))))
  7374.      (ask-for-host (or universal-argument
  7375.                (= 0 number-of-sessions)
  7376.                (and ask-for-session
  7377.                 (string= "" session))))
  7378.      (host (downcase
  7379.         (cond
  7380.           (ask-for-host
  7381.            (let ((h (irc-nuke-whitespace
  7382.                  (read-string
  7383.                   (concat "Connect new Kiwi session to which"
  7384.                       " internet host? (RET for "
  7385.                       irc-server
  7386.                       ") ")))))
  7387.              (if (string= "" h) irc-server h)))
  7388.           (ask-for-session
  7389.            (irc-get-host-from-session-name session))
  7390.           ((= 1 number-of-sessions)
  7391.            (irc-get-host-from-session-name (car session-names)))
  7392.           (t ""))))
  7393.      (port (cond
  7394.          (ask-for-host
  7395.           (let* ((p (irc-nuke-whitespace
  7396.                  (read-string
  7397.                   (concat "Use which TCP port for new connection?"
  7398.                       " (RET for "
  7399.                       (int-to-string irc-port)
  7400.                       ", * for 194) "))))
  7401.              (n (string-to-int p)))
  7402.             (cond ((string= "*" p) 194)
  7403.               ((string= "" p) irc-port)
  7404.               ((and (> n 0) (> 65535 n)) n)
  7405.               (t (error "Illegal TCP port")))))
  7406.          (ask-for-session
  7407.           (irc-get-port-from-session-name session))
  7408.          ((= 1 number-of-sessions)
  7409.           (irc-get-port-from-session-name (car session-names)))
  7410.          (t nil)))
  7411.      (buffer (irc-host+port-to-buffer host port)))
  7412.     (make-variable-buffer-local 'irc-port)
  7413.     (setq irc-port port)
  7414.     (switch-to-buffer buffer)
  7415.     (if (not (get-buffer-process (current-buffer)))
  7416.     (progn
  7417.       (goto-char (point-max))
  7418.       (irc-mode)
  7419.       (irc-insert "")
  7420.       (irc-insert "")
  7421.       (irc-insert "%s for GNU Emacs v18.57 and around...." irc-version)
  7422.       (irc-insert "Comments to %s." irc-hacker)
  7423.       (irc-insert "")
  7424.       (condition-case NOT-IRCED
  7425.           (let ((proc (open-network-stream
  7426.                "irc" buffer host port)))
  7427.         (set-process-filter proc 'irc-filter)
  7428.         (set-process-sentinel proc 'irc-sentinel)
  7429.         (setq irc-server host)
  7430.         (setq-default irc-server host)
  7431.         (irc-send (concat "NICK " irc-nick))
  7432.         (irc-send (format "USER %s %s %s :%s"
  7433.                   (user-login-name)
  7434.                   (system-name)
  7435.                   irc-server
  7436.                   (or (getenv "IRCNAME")
  7437.                       (getenv "NAME")
  7438.                       (user-full-name)
  7439.                       "<<USERNAME UNKNOWN>>")))
  7440.         ;; a new process, so initialize the variables.  they aren't set
  7441.         ;; in irc-mode so that irc-mode can be called at any time.
  7442.         ;; (irc-remember irc-nick 'irc-nicknames)
  7443.         (let ((s (irc-recall-all 'irc-services)))
  7444.           (while (and (listp s) s)
  7445.             (irc-remember (car s) 'irc-nicknames)
  7446.             (setq s (cdr s))))
  7447.         (irc-remember irc-server 'irc-servernames)
  7448.         (setq irc-nick-used ".Not.connected.yet."
  7449.               irc-major-version 0
  7450.               irc-minor-version 0
  7451.               irc-edit-version 0
  7452.               irc-motd-lines nil
  7453.               irc-list-stats '(0 0)
  7454.               irc-away nil
  7455.               irc-channel "0"
  7456.               irc-history-index -1
  7457.               irc-operator nil
  7458.               irc-scratch ""
  7459.               irc-last-command  ""
  7460.               irc-last-explicit "*;"
  7461.               irc-last-private "*;"
  7462.               irc-last-time (irc-get-time)
  7463.               ;; this next bit of messiness just ups irc-last-stamp
  7464.               ;; in an effort to make nice numbers out of the time
  7465.               ;; stamps -- ie, if the time is now 13:53 with an
  7466.               ;; interval of 15 minutes, this makes it 13:45
  7467.               irc-last-stamp 0
  7468.               irc-total-time (string-to-int
  7469.                       (substring irc-last-time 3))
  7470.               irc-last-stamp (if (zerop irc-time-stamp)
  7471.                      0
  7472.                      (while (< (+ irc-last-stamp
  7473.                               irc-time-stamp)
  7474.                            irc-total-time)
  7475.                        (setq irc-last-stamp
  7476.                          (+ irc-last-stamp
  7477.                             irc-time-stamp)))
  7478.                      irc-last-stamp)
  7479.               irc-last-notify irc-last-stamp
  7480.               irc-processes (cons proc irc-processes))
  7481.         (irc-send "CLIENT-START"))
  7482.         (error
  7483.          (irc-insert (concat "%%Couldn't connect to the TCP/IP"
  7484.                  " port %s at the internet host %s --"
  7485.                  " sorry: %s")
  7486.              port
  7487.              host
  7488.              NOT-IRCED)
  7489.          ))))))
  7490.  
  7491.  
  7492. (defun irc-mode ()
  7493.   "To understand some documentation given with irc-mode variables and
  7494. functions, \"output region\" is defined as everything before the irc-mark.
  7495. irc-mark is a marker kept by irc-mode to know where to insert new text
  7496. from IRC.  Text in the output region cannot be modified by the most common
  7497. methods of typing a self-inserting character or pressing delete.
  7498.  
  7499. The input region is everything which follows irc-mark.  It is what
  7500. gets processed by irc-mode when you type LFD or RET.  If irc-spacebar-pages
  7501. is non-nil, the following keys are in effect when the cursor is in the
  7502. output region:
  7503.  
  7504. SPC             scroll-forward       DEL     scroll-backward
  7505. LFD or RET      next-line            TAB     previous-line
  7506.  
  7507. Local keys:
  7508. \\{irc-mode-map}"
  7509.   (interactive)
  7510.   (setq buffer-offer-save t)
  7511.   (kill-all-local-variables)
  7512.   (setq major-mode 'irc-mode
  7513.     mode-name "Kiwi"
  7514.     fill-column (- (window-width (get-buffer-window (current-buffer))) 5))
  7515.   (set (make-local-variable 'irc-away) nil) ; for the mode-line
  7516.   (set (make-local-variable 'irc-channel) nil) ; for sendlists and broken PRIVMSGs
  7517.   (set (make-local-variable 'irc-edit-version) nil) ; edit version number of server
  7518.   (set (make-local-variable 'irc-history-index) nil) ; for the message history
  7519.   (set (make-local-variable 'irc-last-command) nil) ; for the command history
  7520.   (set (make-local-variable 'irc-last-explicit) nil) ; for sendlist ; auto-expansion
  7521.   (set (make-local-variable 'irc-last-private) nil) ; for sendlist : auto-expansion
  7522.   (set (make-local-variable 'irc-last-stamp) nil) ; for time-sentinel
  7523.   (set (make-local-variable 'irc-last-time) nil) ;
  7524.   (set (make-local-variable 'irc-list-stats) nil) ; for RPL_LIST statistics (temp)
  7525.   (set (make-local-variable 'irc-major-version) nil) ; major version number of server
  7526.   (set (make-local-variable 'irc-minor-version) nil) ; major version number of server
  7527.   (set (make-local-variable 'irc-nick-used) nil) ; the nick used at the server
  7528.   (set (make-local-variable 'irc-operator) nil)    ; for special privileges
  7529.   (set (make-local-variable 'irc-scratch) nil) ; for accumulating server messages
  7530.   (set (make-local-variable 'irc-total-time) nil) ;
  7531.   (set (make-local-variable 'irc-count-incoming-messages) 0)
  7532.   (set (make-local-variable 'irc-idle-last-sent) -1)
  7533. ;;;  (set (make-local-variable 'irc-idle-scratch-file)
  7534. ;;;       (expand-file-name
  7535. ;;;    (concat (make-temp-name "/tmp/.Kiwi.")
  7536. ;;;        "."
  7537. ;;;        (user-login-name)
  7538. ;;;        ".may-safely-be-deleted-anytime")))
  7539. ;;;  (if (file-exists-p irc-idle-scratch-file)
  7540. ;;;      (delete-file irc-idle-scratch-file))
  7541.   (set (make-local-variable 'irc-ignored-ppl) ;Nicks actually ignored
  7542.        (irc-create-new-hash-table 7))
  7543.   (set (make-local-variable 'irc-last-NOTICE-rcv) "")
  7544.   (set (make-local-variable 'irc-last-NOTICE-src) "")
  7545.   (set (make-local-variable 'irc-links-header) "Known server links.")
  7546.   (set (make-local-variable 'irc-links-stroke) "-------------------")
  7547.   (set (make-local-variable 'irc-linksinfo) ; for LINREPLY & RPL364 data (temp)
  7548.        (irc-create-new-hash-table 149))    ;2*(65-70 seen links, oct -91)
  7549.   (set (make-local-variable 'irc-list-header) "Name of channel  Users Topic")
  7550.   (set (make-local-variable 'irc-list-stroke) "---------------  ----- -----")
  7551.   (set (make-local-variable 'irc-listtree) ; for RPL_LIST 322 data (temp)
  7552.        (irc-create-new-hash-table 163))    ;2*(50-80 channels, oct -91)
  7553.   (set (make-local-variable 'irc-msg-cont-used) irc-msg-cont)
  7554.   ;; Indentation for continued long lines when displaying NAMREPLY's.
  7555.   (set (make-local-variable 'irc-names-cont-msg) (make-string 24 ? ))
  7556.   (set (make-local-variable 'irc-notify-looked-for)
  7557.        (irc-create-new-hash-table 149))
  7558.   (set (make-local-variable 'irc-notify-detected)
  7559.        (irc-create-new-hash-table 149))
  7560.   (set (make-local-variable 'irc-namtree) ; for NAMREPLY data (temp)
  7561.        (irc-create-new-hash-table 853))    ;2*(200-400 users, oct -91)
  7562.   (set 'irc-nicknames            ; for sendlists
  7563.        (irc-create-new-hash-table 853)) 
  7564.   (set 'irc-servernames            ; for server completion
  7565.        (irc-create-new-hash-table 997))    ;2*((60-70 seen links)+(200-400usrs))
  7566.   (set (make-local-variable 'irc-subscribed-channels) ; channels we listen to
  7567.        (irc-create-new-hash-table 7))    ;max 11
  7568.   (set (make-local-variable 'irc-services) ; for services like NICKSERV
  7569.        (irc-create-new-hash-table 17))
  7570.   (set (make-local-variable 'irc-who-header)
  7571.        (concat "Nickname  Stat Channel name   "
  7572.            " <Hop count> Login@Client \"Real name\" SERVER=srvr"))
  7573.   (set (make-local-variable 'irc-who-header)
  7574.        (concat "Nickname  Stat Random channel  Whatever@clientmachine \"Real name\""))
  7575.   (set (make-local-variable 'irc-who-stroke)
  7576.        (concat "--------  ---- --------------  "
  7577.            "------------------------------------------------"))
  7578.   (set (make-local-variable 'irc-whotree) ; for WHOREPLY data (temp)
  7579.        (irc-create-new-hash-table 853))    ;(200-400 users, oct -91)
  7580.   (set (make-local-variable 'mode-line-format)
  7581.        (list (purecopy "--- %14b ")
  7582.          'global-mode-string
  7583.          (purecopy " %[(")
  7584.          'mode-name 'minor-mode-alist 'irc-operator
  7585.          (purecopy ")%] ")
  7586.          'irc-nick-used ":" 'irc-channel
  7587.          " " 'irc-away (purecopy "-%-")))
  7588.   ;; too many ways to get unbalanced parens (most notably ":-)")
  7589.   (set (make-local-variable 'blink-matching-paren) nil)
  7590.   ;; as closest we can come to "natural" terminal scrolling
  7591.   (set (make-local-variable 'scroll-step) 1) ; Reset in irc.
  7592.   (set-marker (set (make-local-variable 'irc-mark) (make-marker)) (point-max))
  7593.   (let ((nicks irc-ignores))
  7594.     (while (not (null nicks))
  7595.       (irc-remember (car nicks) 'irc-ignored-ppl)
  7596.       (setq nicks (cdr nicks))))
  7597.   (let ((services '(;;"AMIGASERV"
  7598.             ;;"ARSKA"        ;TZoper of #42.
  7599.             ;;"CDSERV"
  7600.             ;;"CONVSERV"    ;Convert from Celsius to Fahrenheit etc
  7601.             ;;"EU-OPER"        ;TZoper of #Eu-opers.
  7602.             "IRCIIHELP"        ;Help automaton for ircII commands
  7603.             ;;"JIRCC"        ;Japanese Kanjii/ASCII translator
  7604.             ;;"MSGSERV"        ;Stores and forwards user-user messages
  7605.             "NICKSERV"        ;Register for nick names
  7606.             ;;"NOTE-NO"
  7607.             ;;"NOTESERV"    ;"Wait for user" and "store messages".
  7608.             ;;"SWEDESERV"
  7609.             ;;"TZOPER"        ;Copr ioprs on #Twilight_Zone
  7610.             ;;"WEBSERV"
  7611.             )))
  7612.     (while services
  7613.       (irc-remember (car services) 'irc-services)
  7614.       (irc-remember (car services) 'irc-nicknames)
  7615.       (setq services (cdr services))))
  7616.   (buffer-enable-undo)
  7617.   (irc-wrap-display-time)
  7618.   (turn-on-auto-fill)
  7619.   ;; "invisible subwindows" or whatever you would like to call them would be
  7620.   ;; nice.  That way I could make the output-region read-only.  The two things
  7621.   ;; most likely to screw up the buffer are backward-kill-word and kill-region
  7622.   (use-local-map irc-mode-map)
  7623.   (run-hooks 'irc-mode-hook))
  7624.  
  7625.  
  7626. (defun irc-sentinel (proc stat)
  7627.   "The sentinel for the IRC connexion.
  7628. Takes the normal sentinel arguments PROCESS and STATUS."
  7629.   ;; ignore anything but finished; i don't know what to do with the others
  7630.   (cond ((or (string= stat "finished\n")
  7631.          (string-match "^exit" stat))
  7632.          (save-excursion
  7633.            (set-buffer (cond ((processp proc) (process-buffer proc))
  7634.                  ((bufferp proc) proc)
  7635.                  (t (get-buffer
  7636.                  (irc-host+port-to-buffer irc-server
  7637.                               irc-port)))))
  7638.            (goto-char (point-max))
  7639.        (ding nil)
  7640.        (ding nil)
  7641.        (ding nil)
  7642.        (irc-insert "")
  7643.        (irc-insert "")
  7644.        (irc-insert (make-string (1- (window-width
  7645.                      (get-buffer-window (current-buffer))))
  7646.                     ?*))
  7647.        (let ((msg (format "Your IRC session ended at %s." (irc-get-time))))
  7648.          (irc-insert "%s%s"
  7649.              (make-string (max (/ (- (window-width
  7650.                           (get-buffer-window
  7651.                            (current-buffer)))
  7652.                          (length msg))
  7653.                           2)
  7654.                        0)
  7655.                       ? )
  7656.              msg))
  7657.        (irc-insert (make-string (1- (window-width
  7658.                      (get-buffer-window (current-buffer))))
  7659.                     ?*))
  7660.        (irc-insert ""))
  7661.          ;; all that needs to be done is a little maintenance ...
  7662.          (setq irc-processes (delq proc irc-processes)))))
  7663.  
  7664.  
  7665.  
  7666. ;; processing input
  7667. (defun irc-process-input ()
  7668.   "If in the input region, parse it for messages and commands.
  7669. In the output region, next-line if irc-spacebar-pages, otherwise do nothing.
  7670.  
  7671. All of the lines in the input region are rejoined during processing to be
  7672. handled as one.  A command is any line starting with a / after leading
  7673. whitespace is stripped away; commands can not exceed 510 characters.  Messages
  7674. can be longer but they will be split into 510 character segments for IRC.  The
  7675. buffer will reflect how the message was sent if it needed to be broken; the
  7676. split(s) will be indicated by \" >>\" to mean that the message is continued."
  7677.   (interactive)
  7678.   ;; do the simple stuff for the output region
  7679.   (if (< (point) irc-mark)
  7680.       (if irc-spacebar-pages
  7681.       (next-line 1)
  7682.       (ding))
  7683.       (if (not (processp (get-buffer-process (current-buffer))))
  7684.       (irc-insert (concat "%%Buffer not connected to any IRC-server, type"
  7685.                   " M-x irc RET to connect to a server."))
  7686.       (irc-check-time)
  7687.       ;; the input region is more work ...
  7688.       ;; first, toast extraneous spaces, tabs and newlines
  7689.       ;; at end of input region
  7690.       (delete-region (goto-char (point-max))
  7691.              (if (re-search-backward "[^ \n]" irc-mark t)
  7692.                  (1+ (point))
  7693.                  (point)))
  7694.       ;; nuke the white space at the beginning of input region, too
  7695.       (delete-region (goto-char irc-mark)
  7696.              (progn (re-search-forward " *")
  7697.                 (point)))
  7698.       (setq irc-history-index -1)    ; reset the history scroll location
  7699.       (let ((txt (buffer-substring irc-mark (point-max)))
  7700.         (maxlen (- irc-max-server-message-length 2))
  7701.         send
  7702.         ass)
  7703.         ;; check to see if the input region is empty
  7704.         (if (string= "" txt)
  7705.         (message "%%Nothing sent to the irc-server.")
  7706.         (while (string-match "\n" txt)
  7707.           (aset txt (match-beginning 0) ? ))
  7708.         (if (string-match "^/" txt)  ; it's a command
  7709.             (if (< (length txt) maxlen)
  7710.             (progn
  7711.               (goto-char (point-max))
  7712.               (insert "\n")
  7713.               (set-marker irc-mark (point))
  7714.               (irc-execute-command
  7715.                (setq irc-last-command (substring txt 1))))
  7716.             ;; can't use error because that kills the function
  7717.             (ding)
  7718.             (message "IRC commands can't exceed %d characters."
  7719.                  maxlen))
  7720.             ;; "a specified sendlist" -- was there one?
  7721.             (setq ass (irc-find-to txt 'explicit))
  7722.             (if (and ass
  7723.                  (string-match "^[^;:]" txt))
  7724.             ;; a real sendlist was specified, so
  7725.             ;; update irc-last-explicit
  7726.             (setq irc-last-explicit (irc-find-to txt)))
  7727.             (irc-add-to-hist (concat (if (not ass)
  7728.                          irc-default-to)
  7729.                          (buffer-substring irc-mark
  7730.                                    (point-max))))
  7731.             (while (> (length txt) maxlen)
  7732.               (setq send (substring txt 0 maxlen)
  7733.                 txt  (substring txt maxlen)
  7734.                 send (irc-fix-wordwrap send txt)
  7735.                 txt  (concat (if ass
  7736.                          irc-last-explicit
  7737.                          irc-default-to)
  7738.                      (cdr send))
  7739.                 send (concat (car send) " >>"))
  7740.               (goto-char (+ irc-mark (- (length send) 3)))
  7741.               (insert " >>\n" (if ass
  7742.                       irc-last-explicit
  7743.                       irc-default-to))
  7744.               (if (looking-at " ")
  7745.               (delete-char 1))
  7746.               (beginning-of-line)
  7747.               (set-marker irc-mark (point))
  7748.               (irc-execute-msg send))
  7749.             (goto-char (point-max))
  7750.             (insert "\n")
  7751.             (set-marker irc-mark (point))
  7752.             (irc-execute-msg txt))))))
  7753.   (setq irc-idle-last-sent (irc-current-time)))
  7754.  
  7755.  
  7756. (defun irc-execute-command (str)
  7757.   "Execute the \"/\" command of STR.  STR should not begin with a slash.
  7758. Commands are first looked up in the irc-alias-alist; if it is found there
  7759. then the alias gets passed recursively with any arguments the original
  7760. had.  The irc-command-alist is checked next and finally the irc-operator-alist.
  7761. A command is considered \"found\" when it matches either exactly or
  7762. unambiguously starting at the first character.  That is, J would match JOIN,
  7763. but OIN would not."
  7764.   (let* ((case-fold-search t)
  7765.          (cmd (substring str 0 (string-match "\\( +\\|$\\)" str)))
  7766.          (text (substring str (match-end 0)))
  7767.          (ambig (irc-check-list
  7768.                  (mapcar 'car (append irc-alias-alist irc-command-alist
  7769.                                       (if irc-operator irc-operator-alist)))
  7770.                  cmd 'start-only))
  7771.          (matches nil)
  7772.      (irc-called-from-buffer t))
  7773.     ;; if no matches are found the command might still be a valid command
  7774.     ;; name hiding behind non-operator status.  i don't like messages that
  7775.     ;; lie and say "Unknown command '/REHASH'" so this should make it not lie.
  7776.     (if (and (not irc-operator) (null ambig))
  7777.         (setq ambig (irc-check-list (mapcar 'car irc-operator-alist) cmd t)))
  7778.     ;; first determine any ambiguities among the lists
  7779.     (if (null ambig)
  7780.         ;; no matches at all were found
  7781.         (irc-insert "%%Unknown command \"/%s\".  Type /HELP for help."
  7782.                     (upcase cmd))
  7783.     ;; this is here for when a regular command gets aliased.  it shows up
  7784.     ;; as being ambiguous but it really isn't later on.
  7785.     (if (irc-member-general (car ambig) (cdr ambig) 'string=)
  7786.         (setq ambig (cdr ambig)))
  7787.     (if (> (length ambig) 1)
  7788.         (irc-insert "%%Ambiguous command \"/%s\".  Could be %s."
  7789.             (upcase cmd)
  7790.             (irc-subst-comma
  7791.              (mapconcat (function (lambda (arg)
  7792.                       (concat "/" arg)))
  7793.                     ambig
  7794.                     ", ")
  7795.              "or"))
  7796.         ;; alias list has highest priority
  7797.         (setq matches (irc-check-list (mapcar 'car irc-alias-alist) cmd t))
  7798.         ;; make sure matches is what we set out to looking for ...
  7799.         (if (and matches (string= (car matches) (car ambig)))
  7800.         ;; call this function again with the text as argument
  7801.         (irc-execute-command
  7802.          (concat (cdr (assoc (car matches) irc-alias-alist))
  7803.              ;; the servers won't grok trailing whitespace for some
  7804.              ;; messages so only use it to separate an argument
  7805.              (if (string< "" text) " ") text))
  7806.         ;; next try the command alist
  7807.         (setq matches (irc-check-list (mapcar 'car irc-command-alist)
  7808.                           cmd
  7809.                           t))
  7810.         (if (and matches
  7811.              (not (irc-check-list (mapcar 'car irc-operator-alist)
  7812.                           cmd
  7813.                           t)))
  7814.             ;; call the appropriate irc-execute-* function
  7815.             (funcall (intern-soft
  7816.                   (concat "irc-execute-"
  7817.                       (cdr (assoc (car matches)
  7818.                           irc-command-alist))))
  7819.                  text)
  7820.             ;; no matches yet.  last resort is the operator alist
  7821.             (setq matches (irc-check-list (mapcar 'car
  7822.                               irc-operator-alist)
  7823.                           cmd
  7824.                           t))
  7825.             (if matches
  7826.             (if irc-operator
  7827.                 (funcall
  7828.                  (intern-soft (concat
  7829.                        "irc-execute-"
  7830.                        (cdr
  7831.                         (assoc (car matches)
  7832.                            irc-operator-alist))))
  7833.                  text)
  7834.                 (irc-insert (concat "%%Only enabled IRC Operators"
  7835.                         " can use the /%s command. Use"
  7836.                         " /OPER to enable yourself.")
  7837.                     (upcase (car matches)))))))))))
  7838.  
  7839.  
  7840. (defun irc-send (str)
  7841.   "Send STR to process in the current buffer.
  7842. A CR-LFD pair is appended automatically as per the 'official' IRC protocol,
  7843. but it seems unnecessary.  Returns its argument STR."
  7844.   (setq str (irc-lowlevel-enquote str))
  7845.   (let* ((proc (get-buffer-process (current-buffer)))
  7846.      (sent (if (processp proc)
  7847.            (condition-case x
  7848.                (send-string proc (concat str "\r\n"))
  7849.              (error x))))
  7850.      (ok (and (processp proc)
  7851.           (eq sent nil))))
  7852.     (if (not ok)
  7853.     (let ((stars (make-string (1- (window-width (get-buffer-window
  7854.                              (current-buffer))))
  7855.                   ?*)))
  7856.       (irc-insert "")
  7857.       (irc-insert "")
  7858.       (irc-insert "%s" stars)
  7859.       (irc-insert "?Failed sending to server!")
  7860.       (cond ((not (processp proc))
  7861.          (irc-insert "?No \"process\" to send to."))
  7862.         ((consp sent)
  7863.          (irc-insert (concat "?Signaled condition is \"%s\" and"
  7864.                      " associated data is \"%s\".")
  7865.                  (car sent)
  7866.                  (cdr sent)))
  7867.         (t (irc-insert "?Unknown reason, proc=%s, sent=%s."
  7868.                    proc
  7869.                    sent)))
  7870.       (irc-insert "?Your IRC session aborted at %s." (irc-get-time))
  7871.       (irc-insert "%s" stars)
  7872.       (if (processp proc) (delete-process proc))
  7873.       (error "IRC aborted"))
  7874.     (irc-log-in-debug-buffer (concat "+ " str)))))
  7875.  
  7876.  
  7877.  
  7878. ;; sending messages to people
  7879. (defun irc-execute-privmsg (str)
  7880.   "Usage: /MSG recipient(s) message
  7881.  
  7882. This command is provided simply for compatability with the C client.
  7883. It is preferable instead to just type the name of the user followed by
  7884. a semi-colon and then the message. That is, \"tale;hi!\" will send the
  7885. message \"hi!\" to the user with the nickname which starts with
  7886. \"tale\".  A semi-colon at the beginning of the line means to send to
  7887. the last recipient explicity specified; typing a semi-colon at the
  7888. beginning of a line expands it to the last recipient(s) specified. The
  7889. recipients for a message can be a comma separated list of users and/or
  7890. channels. Don't use any spaces left of the semi-colon.
  7891.  
  7892. You can send messages to users and channels, and if you are an enabled
  7893. IRC operator, you can also send broadcasts to server machines and
  7894. client machines.
  7895.  
  7896. Examples:
  7897. /msg wiz hi there           send \"hi there\" to user with nickname wiz
  7898. wiz;hi there                send to user wiz
  7899. msa,wiz;hi there            send to the users wiz and msa
  7900. 42;hi there                 send into channel 42
  7901. 42,wiz;hi there             channel 42 and user wiz
  7902.  
  7903. If you are an enabled IRC operator:
  7904. $minsk.docs.uu.se;...       send a message to all users using server minsk
  7905. $*.se;...                   send to all users using swedish servers
  7906. #cia.docs.uu.se;...         send to all users running their clients on cia
  7907. #*.se;...                   all user running their clients on swedish machines"
  7908.   (irc-add-to-hist
  7909.    (irc-execute-msg
  7910.     (concat
  7911.      (setq irc-last-explicit (concat (substring str 0 (string-match " +\\|$"
  7912.                                     str))
  7913.                      ";"))
  7914.      (substring str (match-end 0))))))
  7915.  
  7916.  
  7917. (defun irc-execute-msg (str)
  7918.   "Send a message to a channel or another user.  Returns its argument STR,
  7919. munged slightly to indicate where it was attempted to be sent."
  7920.   ;; this really is an indirect function of the UI (ie, not through a /COMMAND)
  7921.   ;; so it isn't interactive
  7922.   (let ((tolist nil)
  7923.     (orig str)
  7924.     (icw nil)
  7925.     (confirm nil)
  7926.     (on-hash (irc-is-multijoinable-channel irc-channel))
  7927.     (newsrvr (irc-server-has-multijoinable-channels)))
  7928.     (if (string-match "^[:;]" str)
  7929.         ;; a little bit of fill-in-the-blank
  7930.         (setq str (concat irc-last-explicit (substring str 1)))
  7931.     (if (not (irc-find-to str 'explicit))
  7932.         ;; prepend an implicit sendlist if need be
  7933.         (if irc-default-to
  7934.         (setq str (concat irc-default-to str))
  7935.         (irc-insert "%%You have no default sendlist."))))
  7936.     (if (irc-find-to str 'explicit)
  7937.         (setq icw (irc-find-to str)
  7938.               tolist (irc-burst-comma (substring icw 0 (1- (length icw))))
  7939.           tolist (mapcar 'irc-clean-up-message tolist)
  7940.               str (irc-find-message str)
  7941.               ;; kill on leading space if it exists.  ie, "tale: hi" will
  7942.               ;; send "hi" as a message not " hi".
  7943.               str (if (string-match "^ *" str)
  7944.               (substring str (match-end 0)))))
  7945.     (setq confirm (delq            ; whee.  lisp indentation is fun.
  7946.            nil
  7947.            (mapcar
  7948.             (function
  7949.              (lambda (to)
  7950.               (if (not (zerop (string-to-int to)))
  7951.               (if (string= to irc-channel)
  7952.                   (progn
  7953.                 (irc-send
  7954.                  (if (and newsrvr on-hash)
  7955.                      (concat "PRIVMSG " irc-channel " :" str)
  7956.                      (concat "MSG :" str)))
  7957.                 to)
  7958.                   ;; new in 1.2 -- you _can_ send to a channel you
  7959.                   ;; are not on
  7960.                   (irc-send (concat "PRIVMSG " to " :" str))
  7961.                   to)
  7962.               (if (not (or (string= to "*")
  7963.                        (string= to "0")))
  7964.                   (setq icw (irc-check-list (irc-recall-all
  7965.                              'irc-nicknames)
  7966.                             to)))
  7967.               (cond ((string= to "*")
  7968.                  (if (string= "0" irc-channel)
  7969.                      (progn
  7970.                        (irc-insert (concat "%%You are not"
  7971.                                " talking to any"
  7972.                                " channel."))
  7973.                        nil)
  7974.                      (irc-send
  7975.                       (if (and newsrvr on-hash)
  7976.                       (concat "PRIVMSG " irc-channel
  7977.                           " :" str)
  7978.                       (concat "MSG :" str)))
  7979.                      irc-channel))
  7980.                 ((string= to "0")
  7981.                  (irc-insert "%%You can't send to channel 0.")
  7982.                  nil)
  7983.                 ((= (length icw) 1)
  7984.                  (irc-send (concat "PRIVMSG "
  7985.                            (car icw)
  7986.                            " :"
  7987.                            str))
  7988.                  (car icw))
  7989.                 ((not icw)
  7990.                  ;; Wox! No one found, but we'll do a
  7991.                  ;; nonomatching. Try sending it anyway and
  7992.                  ;; let the server bitch if necessary.
  7993.                  ;; So don't remember this "nonmatch".
  7994.                  (irc-send (concat "PRIVMSG " to " :" str))
  7995.                  to)
  7996.                 (t (irc-insert (concat "%%Ambiguous recipient"
  7997.                                " \"%s\"; could be %s.")
  7998.                            to
  7999.                            (irc-subst-comma
  8000.                         (mapconcat
  8001.                          (function
  8002.                           (lambda (arg)
  8003.                            (concat "\"" arg "\"")))
  8004.                          icw
  8005.                          ", ")
  8006.                         "or"))
  8007.                    nil)))))
  8008.             tolist)))
  8009.     (setq confirm (let ((foo ())
  8010.             (bar confirm))
  8011.             (while (> (length bar) 0)
  8012.               (setq foo (cons
  8013.                  (concat
  8014.                   (cond
  8015.                     ((irc-is-nickname (car bar)) "user")
  8016.                     ((irc-is-channelname (car bar)) "channel")
  8017.                     ((irc-is-broadcastname (car bar)) "server")
  8018.                     (t "receiver"))
  8019.                   " "
  8020.                   (car bar))
  8021.                  foo)
  8022.                 bar (cdr bar)))
  8023.             foo))
  8024.     (let* ((rcvr (irc-subst-comma (mapconcat 'eval confirm ", ")
  8025.                   "and"))
  8026.        (data (irc-clean-up-message (format irc-msg-sent rcvr))))
  8027.       (if (and confirm irc-confirm)
  8028.       (let ((c confirm))
  8029.         (while c
  8030.           (let ((r (irc-clean-up-message (format irc-msg-sent (car c)))))
  8031.         (irc-insert "%s%s" (make-string
  8032.                     (max 0 (- (window-width
  8033.                            (get-buffer-window
  8034.                         (current-buffer)))
  8035.                           (length r)
  8036.                           1))
  8037.                     ? )
  8038.                 r)
  8039.         (setq c (cdr c)))))
  8040.       (if (not confirm)
  8041.           (irc-insert "%% Message not sent. Use /HELP for help."))))
  8042.     orig))
  8043.  
  8044.  
  8045. (defun irc-execute-oops (newto)
  8046.   "Usage: /OOPS intended-recipient
  8047. Send irc-oops to recipient(s) of last message and resend message to
  8048. 'intended-recipient'.  This command is handy when you've just sent a message
  8049. to the wrong place and you want the person/people who saw it to know that they
  8050. should just disregard it.  The message which was originally sent then gets
  8051. forwarded to its proper destination."
  8052.   (interactive '(""))
  8053.   (if (not irc-called-from-buffer)
  8054.       (progn (irc-insert "")
  8055.          (irc-insert "/OOPS")))  
  8056.   (let* ((prev (irc-find-to (car irc-history)))
  8057.      (data (concat prev irc-oops)))
  8058.     ;; first do the oops message
  8059.     (irc-execute-msg data)
  8060.     ;; then resend the original
  8061.     (if (and (string= "" newto) irc-called-from-buffer)
  8062.     (irc-insert (concat "%%No new receiver given. Oops said to %s. Not"
  8063.                 " redirected.")
  8064.             prev)
  8065.     (irc-execute-redirect newto)))
  8066.   (setq irc-idle-last-sent (irc-current-time)))
  8067.  
  8068.  
  8069. (defun irc-execute-redirect (newto)
  8070.   "Usage: /REDIRECT additional-recipient
  8071.  
  8072. Send to 'additional-recipient' the last message which you sent.  This 
  8073. command can be fairly easily duplicated using the history mechanism by hand
  8074. but it is provided to make it even easier."
  8075.   (interactive '(""))
  8076.   (if (not irc-history)
  8077.       (irc-insert "%%No message sent yet, nothing to redirect.")
  8078.       (let* ((default (if irc-default-to 
  8079.               (substring irc-default-to 0 (string-match
  8080.                                "[:;]" irc-default-to))
  8081.               ""))
  8082.          (prompt (if (string< "" default)
  8083.              (concat "(RET for "
  8084.                  (irc-nuke-whitespace
  8085.                   (concat
  8086.                    default
  8087.                    (if (string-match "\\*" default)
  8088.                        (concat "; where *=\""
  8089.                            irc-channel
  8090.                            "\""))))
  8091.                  ") ")
  8092.              ""))
  8093.          (n (irc-nuke-whitespace
  8094.          (if (and (string= "" newto) (not irc-called-from-buffer))
  8095.              (irc-read-object
  8096.               (format "Send copy of last message (%s) to whom? %s"
  8097.                   (let ((m (irc-find-message (car irc-history))))
  8098.                 (if (> (length m) 5)
  8099.                     (concat (substring m 0 5) "...")
  8100.                     m))
  8101.                   prompt)
  8102.               ""
  8103.               (irc-recall-all 'irc-nicknames))
  8104.              newto)))
  8105.          (new (if (string= "" n) default n)))
  8106.     (if (not (irc-is-receiver new))
  8107.         (irc-insert (concat "%%\"%s\" is not a valid receiver. Message not"
  8108.                 " redirected.")
  8109.             new)
  8110.         (let ((to (if (string= "" new)
  8111.               default
  8112.               (concat new ";"))))
  8113.           (setq irc-last-explicit to)
  8114.           (irc-add-to-hist
  8115.            (irc-execute-msg
  8116.         (concat to (irc-find-message (car irc-history)))))))))
  8117.   (setq irc-idle-last-sent (irc-current-time)))
  8118.  
  8119.  
  8120.  
  8121. ;; /commands for the server
  8122. (defun irc-execute-quote (msg)
  8123.   "Usage: /QUOTE string
  8124.  
  8125. This command is used to send 'string' directly to the IRC server without
  8126. any local processing.  Warning: this has the potential to screw up some
  8127. things in irc-mode, particularly if it is used to change your nickname or
  8128. to switch channels."
  8129.   (interactive '(""))
  8130.   (let ((m (if (and (string= "" msg) (not irc-called-from-buffer))
  8131.            (read-string "String to send to server: ")
  8132.            msg)))
  8133.     (cond ((string-match "^ *\\([^ ]+\\)" m)
  8134.        (let ((cmd (subfield m 1)))
  8135.          (irc-send m)
  8136.          (irc-send (concat "CLIENT-SYNCH :QUOTE " cmd))))
  8137.       (t (irc-insert "%%Nothing was sent to the IRC server."))))
  8138.   (setq irc-idle-last-sent (irc-current-time)))
  8139.  
  8140.  
  8141. (defun irc-execute-who (channel)
  8142.   "Usage: /WHO { channel | user }
  8143.  
  8144. Get a list of the users on IRC. The argument \"channel\" means to show
  8145. just the users on that channel, with * representing the current channel.
  8146. User can be any mask, ie *.se for current swedish IRCjunkies.
  8147.  
  8148. Each user is indicated on a separate line with their nickname, status,
  8149. channel, login name, host and real name. The second column, \"Stat\"
  8150. gives the status for the user, and is shown as a four letter word (:-)
  8151. according to the combination of their attributes. The possible
  8152. attributes are being an IRC operator, being a channel operator and
  8153. being marked as being away.
  8154.  
  8155.                                           Status field
  8156. A normal user having no attributes set:     (blank)
  8157. A normal user marked as being away:          Away
  8158. An IRC operator with no other attribues:     Iopr
  8159. An IRC operator marked as being away:        IoAw
  8160. A channel operator with no other attributes: Copr
  8161. A channel operator marked as being away:     CoAw
  8162. User being both IRC- and channel operator:   ICop
  8163. As above but also marked as being away:      ICAw
  8164.  
  8165. Being ignored takes precedence over all
  8166. other attributes, always shown as:           IGNR     (cf \"/HELP IGNORE\"). 
  8167.  
  8168. Users being on either no channel at all, or on channels with the mode
  8169. PRIVATE are appear with a blank \"Channel\" field. If you are
  8170. connected to a server of version 2.6, and are requesting a \"general\"
  8171. who listing (ie for users potentially on different channels), all
  8172. users \"Channel\" field will be blank.
  8173.  
  8174. An %-sign is appended to the name or number of your current
  8175. channel.
  8176.  
  8177. BE WARNED: on some servers, the operators CAN see who's on a negative channel.
  8178. On some of these servers, the channel number is disclosed, on others only
  8179. the fact that a user is on a negative channel, but not which one.
  8180. The same goes for \"private\" and \"secret\" channels.
  8181.  
  8182. If a single \"user\" is given as the argument, (ie a word starting with neither
  8183. a + nor a digit) it is taken to be the nickname of a user on IRC and more
  8184. information, if available, is given about the person.
  8185.  
  8186. If this function is called interactively then the prefix argument is used
  8187. as the channel to query.  No argument means all of them and an argument
  8188. of \"-\" or \"*\" means the current channel." 
  8189.   (interactive '(""))
  8190.   (let* ((c (if (and (string= "" channel) (not irc-called-from-buffer))
  8191.         (irc-read-object (concat "Who? "
  8192.                      (if (not (string= "0" irc-channel))
  8193.                          (concat "(Press return for "
  8194.                              irc-channel
  8195.                              ") ")
  8196.                          ""))
  8197.                  ""
  8198.                  (irc-get-channels-and-nicks-and-servers))
  8199.         channel))
  8200.      (c2 (irc-nuke-whitespace c))
  8201.      (chan (cond ((or (string= "" c2)
  8202.               (string= "*" c2))
  8203.               irc-channel)
  8204.              (t c2))))
  8205.     (if (string= "0" chan)
  8206.     (irc-insert (concat "%%No argument (or argument 0) given to /WHO,"
  8207.                 " this would certainly disconnect your"
  8208.                 " IRC-session. You can use /QUOTE WHO 0 if you"
  8209.                 " *really* want to do this."))
  8210.       (let ((s (irc-recall-all 'irc-services)))
  8211.     (irc-forget-all 'irc-nicknames)
  8212.     (irc-remember irc-nick-used 'irc-nicknames)
  8213.     (while (and (listp s) s)
  8214.       (irc-remember (car s) 'irc-nicknames)
  8215.       (setq s (cdr s)))
  8216.     (if (not irc-called-from-buffer)
  8217.         (progn (irc-insert "")
  8218.            (irc-insert "/WHO %s" chan)))
  8219.     (if (and irc-called-from-buffer (irc-is-nickname chan))
  8220.         (irc-execute-whois chan)
  8221.       (irc-send (concat "WHO " chan))))
  8222.       (setq irc-idle-last-sent (irc-current-time)))))
  8223.  
  8224.  
  8225. (defun irc-execute-whois (user)
  8226.   "Usage: /WHOIS user
  8227.  
  8228. Get a two line description of who and where \"user\" is.  If user is not
  8229. provided it is read from the minibuffer with a completing-read.
  8230. If * is given instead of a user name, you will be informed about ALL users.
  8231.  
  8232. BUG: The list of users used when * is given may be somewhat obsolete,
  8233. therefore first give a NAMES command."
  8234.   (interactive '(""))
  8235.   (let ((wholist (irc-recall-all 'irc-nicknames)))
  8236.     (if (and (string-match "^ *$" user) (not irc-called-from-buffer))
  8237.     (setq user (irc-read-object "Who is who? "
  8238.                     user
  8239.                     wholist)))
  8240.     (if (string< "" user)
  8241.     (progn (if (not irc-called-from-buffer)
  8242.            (progn (irc-insert "")
  8243.               (irc-insert "/WHOIS %s" user)))
  8244.            (irc-send (concat "WHOIS " user)))
  8245.     (irc-insert "%%Who is who? No nick given.")))
  8246.   (setq irc-idle-last-sent (irc-current-time)))
  8247.  
  8248.  
  8249. (defun irc-execute-motd (server)
  8250.   "Usage: /MOTD [ server ]
  8251.  
  8252. Tells the message of the day at the server."
  8253.   (interactive '(""))
  8254.   (let ((host (if (string= "" server)
  8255.           (if (not irc-called-from-buffer)
  8256.               (irc-read-object
  8257.                "Get message of the day for which host? "
  8258.                ""
  8259.                (irc-recall-all 'irc-servernames))
  8260.               "")
  8261.           server)))
  8262.     (if (string-match "^ *\\([^: ]*\\)" host)
  8263.     (let ((host (substring host (match-beginning 1) (match-end 1))))
  8264.       (if (not irc-called-from-buffer)
  8265.           (progn (irc-insert "")
  8266.              (irc-insert "/MOTD %s" host)))
  8267.       (irc-send (concat "MOTD " host)))
  8268.     (irc-insert (concat "%%Internal error in function irc-execute-motd,"
  8269.                 " please try another syntax and notify %s"
  8270.                 " by email.")
  8271.             irc-hacker)))
  8272.   (setq irc-idle-last-sent (irc-current-time)))
  8273.  
  8274.  
  8275. (defun irc-execute-version (server)
  8276.   "Usage: /VERSION [ server | user ]
  8277.  
  8278. Shows the version of the server, or of a user. If the argument looks
  8279. like a nickname, that user's client is queried using CTCP (client to
  8280. client protocol) about which client it is and which version of it it
  8281. is. If the queried client doesn't understand CTCP, no answer will
  8282. follow."
  8283.   (interactive '(""))
  8284.   (let* ((host (irc-nuke-whitespace
  8285.         (if (string= "" server)
  8286.             (if (not irc-called-from-buffer)
  8287.             (irc-read-object
  8288.              "Get version of which server/nick? "
  8289.              ""
  8290.              (irc-get-channels-and-nicks-and-servers))
  8291.             "")
  8292.             server)))
  8293.      (host (if (string= "" host) irc-server host))
  8294.      (hst (if (string= "*" host) irc-channel host)))
  8295.     (if (string-match "^ *\\([^: ]*\\)" hst)
  8296.     (let ((h (substring hst (match-beginning 1) (match-end 1))))
  8297.       (cond ((or (irc-is-nickname h)
  8298.              (irc-is-channelname h))
  8299.          (if (not irc-called-from-buffer)
  8300.              (progn (irc-insert "")
  8301.                 (irc-insert (concat "/VERSION " h))))
  8302.          (irc-insert (concat "%sQuerying client of user%s %s for"
  8303.                      " version of client%s")
  8304.                  irc-msg-info-pre
  8305.                  (if (irc-is-channelname h) "s on channel" "")
  8306.                  h
  8307.                  irc-msg-info-post)
  8308.          (irc-send (concat "PRIVMSG " h " :\001"
  8309.                    (irc-ctcp-enquote "VERSION")
  8310.                    "\001")))
  8311.         (t (if (not irc-called-from-buffer)
  8312.                (progn (irc-insert "")
  8313.                   (irc-insert "/VERSION %s" h)))
  8314.            (irc-send (concat "VERSION " h)))))
  8315.     (irc-insert "%%Give only one word please. \"%s\" is not valid."
  8316.             hst)))
  8317.   (setq irc-idle-last-sent (irc-current-time)))
  8318.  
  8319.  
  8320. (defun irc-execute-list (channel)
  8321.   "Usage: /LIST [channel]
  8322.  
  8323. Get a list of the discussions that are on IRC. If a channel is given,
  8324. only the topic for that channel is shown. A * denotes your current
  8325. channel, if any. An %-sign is appended to your current channel's name
  8326. or number."
  8327.   (interactive '(""))
  8328.   (if (not irc-called-from-buffer)
  8329.       (progn (irc-insert "")
  8330.          (irc-insert "/LIST %s" channel)))
  8331.   (irc-send (concat "LIST " channel))
  8332.   (setq irc-idle-last-sent (irc-current-time)))
  8333.  
  8334.  
  8335. (defun irc-execute-links (mask)
  8336.   "Usage: /LINKS [ mask ]
  8337.  
  8338. Show the names of all the servers which can communicate with your server.
  8339. The links can go down isolating different parts of the IRC-net, so this
  8340. is a good way to find out how extensive it is at the moment.
  8341.  
  8342. Given a mask like *.se, only server names matching the mask are displayed."
  8343.   (interactive '(""))
  8344.   (let ((m (if (and (string= "" mask) (not irc-called-from-buffer))
  8345.            (irc-read-object (concat "Check for which servers? (RET for"
  8346.                     " all, *.SE for swedish servers etc) ")
  8347.                 ""
  8348.                 (irc-recall-all 'irc-servernames))
  8349.            mask)))
  8350.     (cond ((string-match "^ *\\*? *$" m)
  8351.        (irc-forget-all 'irc-servernames)
  8352.        (irc-forget-all 'irc-linksinfo)))
  8353.     (if (not irc-called-from-buffer)
  8354.     (progn (irc-insert "")
  8355.            (irc-insert "/LINKS %s" m)))
  8356.     (irc-send (concat "LINKS " m)))
  8357.   (setq irc-idle-last-sent (irc-current-time)))
  8358.  
  8359.  
  8360. (defun irc-execute-lusers (mask)
  8361.   "Usage: /LUSERS [servermask]
  8362.  
  8363. Get the number of users and servers on your IRC network. 
  8364.  
  8365. There is a optional argument you can use if you only want
  8366. to see the count of some part of the IRCnet. For instance,
  8367. to see how many swedish users are on, try /lusers *.se"
  8368.   (interactive '(""))
  8369.   (let* ((mask (irc-nuke-whitespace mask)))
  8370.     (if (not irc-called-from-buffer)
  8371.     (progn (irc-insert "")
  8372.            (irc-insert (format "/LUSERS %s" mask))))
  8373.     (irc-send (concat "LUSERS " mask))
  8374.     (setq irc-idle-last-sent (irc-current-time))))
  8375.  
  8376.  
  8377. (defun irc-execute-admin (server)
  8378.   "Usage: /ADMIN [ server ]
  8379.  
  8380. Get information about the IRC administrator for 'server'; if server is not
  8381. supplied just query for the server to which you are connected."
  8382.   (interactive '(""))
  8383.   (let ((s (if (and (string= "" server) (not irc-called-from-buffer))
  8384.            (irc-read-object "Administrative info about which server? "
  8385.                 ""
  8386.                 (irc-recall-all 'irc-servernames))
  8387.            server)))
  8388.     (if (not irc-called-from-buffer)
  8389.     (progn (irc-insert "")
  8390.            (irc-insert "/ADMIN %s" s)))
  8391.     (irc-send (concat "ADMIN " s)))
  8392.   (setq irc-idle-last-sent (irc-current-time)))
  8393.  
  8394.  
  8395. (defun irc-execute-time (&optional server)
  8396.   "Usage: /TIME [ server ]
  8397.  
  8398. Get the current time on 'server'; is no server is provided use the one to which
  8399. you are connected.  When called with a interactively with a prefix-argument
  8400. the server name is read using the minibuffer.
  8401.  
  8402. Querying other servers can be handy given that people on IRC are spread out
  8403.  from the west coast of the United States to Finland.  The question \"What
  8404. time is it in Finland?\" comes up so frequently that an alias -- /TF -- has
  8405. been provided by default to get the answer.  This alias should work as long
  8406. as tut.fi is connected to your IRC-net."
  8407.   (interactive '(""))
  8408.   (let ((s (if (and (stringp server)
  8409.             (string= "" server)
  8410.             (not irc-called-from-buffer))
  8411.            (irc-read-object "Get the time at which server? "
  8412.                 ""
  8413.                 (irc-recall-all 'irc-servernames))
  8414.            server)))
  8415.     (if (and (stringp server) (not irc-called-from-buffer))
  8416.     (progn (irc-insert "")
  8417.            (irc-insert "/TIME %s" s)))
  8418.     (irc-send (concat "TIME " s)))
  8419.   (setq irc-idle-last-sent (irc-current-time)))
  8420.  
  8421.  
  8422. (defun irc-execute-join (channel)
  8423.   "Usage: /JOIN channel [mode]
  8424.  
  8425. Join \"channel\" on IRC.  If channel is not provided it is requested
  8426. in the minibuffer; when called interactively, the channel is prompted
  8427. for in the minibuffer.  Use /LEAVE to exit the channel.
  8428.  
  8429. You can supply an initial mode for the channel. If the channel didn't
  8430. exist before you joined it, the channel will be sat to the supplied mode.
  8431. If the channel already existed, the mode will be ignored by the server.
  8432.  
  8433. One can be listening on several channels at once. Up to 10 channels
  8434. can be listened to at any single time, either 10 #channels, or 1 old
  8435. style (either a +channel or a nummeric channel) and 9 #channels. Use
  8436. /JOIN to join (ie start listening and talkinging to) a channel and
  8437. /LEAVE to stop listening to a channel. If you /LEAVE the channel you
  8438. were talking to, you will end up not talking to any channel; just use
  8439. /JOIN again to remedy that situation.  There is no way yet to start
  8440. listening to a channel without choosing that channel as the one you
  8441. will talk to. Of course, another /JOIN will help..."
  8442.  
  8443.   (interactive '(""))
  8444.   (let* ((pair (cond
  8445.          ((string-match "^ *\\([^ ]+\\) +\\([^ ]\\)" channel)
  8446.           (cons (subfield channel 1)
  8447.             (concat (subfield channel 2)
  8448.                 (substring channel (match-end 0)))))
  8449.          ((string-match "^ *\\([^ ]+\\) *$" channel)
  8450.           (cons (subfield channel 1) ""))
  8451.          (t (cons "" ""))))
  8452.      (c (car pair))
  8453.      (m (cdr pair))
  8454.      (subchnls (irc-recall-all 'irc-subscribed-channels))
  8455.      (chn (irc-nuke-whitespace
  8456.            (if (and (string= c "")
  8457.             (not irc-called-from-buffer))
  8458.            (irc-read-object "Channel to join? "
  8459.                     ""
  8460.                     subchnls)
  8461.            c)))
  8462.      (mode (irc-nuke-whitespace
  8463.         (if (and (string= m "")
  8464.              (not irc-called-from-buffer)
  8465.              (not (irc-recall chn 'irc-subscribed-channels)))
  8466.             (irc-read-object (format
  8467.                       "Initial mode for channel \"%s\"? "
  8468.                       chn)
  8469.                      ""
  8470.                      '("A combination of +-bilmnopst"))
  8471.             m)))
  8472.      (digit-start (string-match "^-?[0-9]" chn)))
  8473.     (if (string= "" chn) ; well, so much for that 
  8474.     (irc-insert "%%No channel given. continuing talking to %s."
  8475.             irc-channel)
  8476.     (let* ((newsrvr (irc-server-has-multijoinable-channels)) 
  8477.            (mtch (irc-recall chn 'irc-subscribed-channels)))
  8478.       (cond ((string= "0" chn) 
  8479.          (setq irc-channel "0")
  8480.          (irc-show-subscribed-channels)) 
  8481.         ((and (not mtch)
  8482.               (not (irc-is-channelname chn)))
  8483.          (irc-insert (concat "%%Warning, that channel name (%s) looks" 
  8484.                      " strange, but will try to /join it"
  8485.                      " anyway. You might be in for a surprise,"
  8486.                      " thought.")
  8487.                  chn)
  8488.          (if (not irc-called-from-buffer) 
  8489.              (progn (irc-insert "")
  8490.                 (irc-insert "/JOIN %s %s" chn mode))) 
  8491.          (irc-send (format "%s %s %s"
  8492.                    (if newsrvr "JOIN " "CHANNEL ")
  8493.                    chn
  8494.                    mode)))
  8495.         (mtch (setq irc-channel mtch)
  8496.               (if (not irc-called-from-buffer) 
  8497.               (progn (irc-insert "")
  8498.                  (irc-insert "/JOIN %s" mtch)))
  8499.               (irc-show-subscribed-channels))
  8500.         (t (if (not irc-called-from-buffer)
  8501.                (progn (irc-insert "")
  8502.                   (irc-insert "/JOIN %s %s" chn mode)))
  8503.            (irc-send (format "%s %s %s"
  8504.                      (if newsrvr "JOIN " "CHANNEL ")
  8505.                      chn
  8506.                      mode))))))
  8507.     (setq irc-msg-cont-used
  8508.       (if (string= "0" chn) ;On private?
  8509.           irc-msg-cont 
  8510.           (make-string (1- (length (concat irc-msg-cont chn)))
  8511.                (string-to-char " ")))) )
  8512.   (setq irc-idle-last-sent (irc-current-time)))
  8513.  
  8514.  
  8515. (defun irc-execute-leave (channel)
  8516.   "Usage: /LEAVE [channel]
  8517.  
  8518. Leave your current channel (or a selected one from the set of joined channels,
  8519. if you're using a v2.6 or later server). Don't join another channel.
  8520.  
  8521. Also see /HELP JOIN."
  8522.   (interactive '(""))
  8523.   (let* ((c (if (and (string-match "^ *$" channel)
  8524.              (not irc-called-from-buffer))
  8525.         (irc-read-object (concat "Leave which channel? (0 for ALL"
  8526.                      (if (string= "0" irc-channel)
  8527.                          ") "
  8528.                          (concat ", RET for "
  8529.                              irc-channel
  8530.                              ") ")))
  8531.                  ""
  8532.                  (irc-recall-all 'irc-subscribed-channels))
  8533.         channel))
  8534.      (chan (irc-nuke-whitespace
  8535.         (if (and (not (string= "0" irc-channel))
  8536.              (or (string= "*" c) (string= "" c)))
  8537.             irc-channel
  8538.           (if (and (string= "" c)
  8539.                (not irc-called-from-buffer))
  8540.               (message "%%No channel chosen"))
  8541.           c))))
  8542.     (if (string= "0" chan)
  8543.     (progn
  8544.       (let ((lst (irc-recall-all 'irc-subscribed-channels))
  8545.         (irc-multiple-leave-in-progress t)
  8546.         (irc-called-from-buffer t))
  8547.         (while (not (null lst))
  8548.           (irc-send (concat "PART " (car lst)))
  8549.           (setq lst (cdr lst))))
  8550.       (irc-show-subscribed-channels))
  8551.     (if (not irc-called-from-buffer)
  8552.         (progn (irc-insert "")
  8553.            (irc-insert "/LEAVE %s" chan)))
  8554.     (if (string< "" chan)
  8555.         (progn (irc-insert "%sLeaving channel %s%s"
  8556.                    irc-msg-info-pre chan irc-msg-info-post)
  8557.            (if (irc-server-has-multijoinable-channels)
  8558.                (irc-send (concat "PART " chan))
  8559.                (irc-send "CHANNEL 0")))
  8560.         (irc-insert (concat "%%Leave which channel? No channel given. Try"
  8561.                 " /MEMBERSHIPS")))))
  8562.   (setq irc-idle-last-sent (irc-current-time)))
  8563.  
  8564.  
  8565. (defun irc-execute-nick (name)
  8566.   "Usage: /NICKNAME name
  8567.  
  8568. Change your nickname in IRC.  A nickname can contain alphanumeric characters,
  8569. underscores (_), hyphens (-) or the special characters left brace ({), right
  8570. brace (}), vertical bar (|), left bracket ([), right bracket (]) and back
  8571. slash (\\). These special character are alphabetic characters in some
  8572. languages like the scandinavian ones.  The name cannot start with a hyphen or
  8573. number and only the first nine characters are used.
  8574.  
  8575. Unfortunately, due to the way confirmation from the servers work, it might be
  8576. falsely reported that your nickname was successfully changed when it was not.
  8577. The server will come back and say so and finally irc-mode will wise-up and
  8578. note that your nickname was not changed.
  8579.  
  8580. All the above things change from server version to server version, so they may
  8581. or may not work. Try it."
  8582.   (interactive '(""))
  8583.   (let ((newnick (if (and (string= "" name) (not irc-called-from-buffer))
  8584.              (irc-nuke-whitespace (read-string "New nickname? "))
  8585.              name)))
  8586.     (if (string= "" newnick)
  8587.     (irc-insert "%sNickname not changed%s"
  8588.             irc-msg-info-pre
  8589.             irc-msg-info-post)
  8590.     (progn
  8591.       (if (not irc-called-from-buffer)
  8592.           (progn (irc-insert "")
  8593.              (irc-insert "/NICK %s" newnick)))
  8594.       (irc-insert "%sTrying to change your nickname to \"%s\"%s"
  8595.               irc-msg-info-pre
  8596.               newnick
  8597.               irc-msg-info-post)
  8598.       (set-buffer-modified-p (buffer-modified-p))
  8599.       (irc-send (concat "NICK " newnick)))))
  8600.   (setq irc-idle-last-sent (irc-current-time)))
  8601.  
  8602.  
  8603. (defun irc-execute-quit (text)
  8604.   "Usage: /QUIT [reason]
  8605.  
  8606. Exit IRC.  The connection is closed but the buffer is left behind.
  8607. If you want, you can give a reason for quitting IRC."
  8608.   (interactive '(""))
  8609.   (if (not irc-called-from-buffer)
  8610.       (progn (if (string-match "^ *$" text)
  8611.          (setq text (yow)))
  8612.          (let ((parias '("\n" "  " "\t"))
  8613.            (ok nil)
  8614.            (n 0))
  8615.            (while (not ok)
  8616.          (let ((p parias))
  8617.            (while p
  8618.              (while (string-match (car p) text)
  8619.                (setq text (concat (substring text
  8620.                              0
  8621.                              (match-beginning 0))
  8622.                       " "
  8623.                       (substring text (match-end 0)))))
  8624.              (setq p (cdr p))))
  8625.          (setq n (1+ n))
  8626.          (if (> n 10)
  8627.              (setq text ""))
  8628.          (if (< (length text) 80)
  8629.              (setq ok t)
  8630.              (setq text (yow)))))
  8631.          (irc-insert "")
  8632.          (irc-insert "/QUIT %s" text)))
  8633.   (irc-send (concat "QUIT :" text))
  8634.   (sit-for 2)                ;Give server a chance to react.
  8635.   (let ((proc (get-buffer-process (current-buffer))))
  8636.     (cond ((processp proc)
  8637.        (irc-sentinel proc "finished\n")
  8638.        (delete-process proc))))
  8639.   (setq irc-idle-last-sent (irc-current-time)))
  8640.  
  8641.  
  8642. (defun irc-execute-away (text)
  8643.   "Usage: /AWAY [message]
  8644.  
  8645. Mark yourself as away, giving TEXT to people who send you private messages.
  8646. Without any arguments it will just insert a message about your current status."
  8647.   (interactive '(""))
  8648.   (let ((reason (if (and (string= "" text) (not irc-called-from-buffer))
  8649.             (read-string "Reason to be away? ")
  8650.             text)))
  8651.     (if (string= "" reason)
  8652.     (if irc-away
  8653.         (let ((pre (concat irc-msg-info-pre "You are ")))
  8654.           (irc-insert (concat "%smarked as being away: \"%s\", "
  8655.                   "use /HERE to remove the mark%s")
  8656.               pre
  8657.               (substring irc-away 2 -1)
  8658.               irc-msg-info-post))
  8659.         (irc-insert "%sYou are not currently marked as being away%s"
  8660.             irc-msg-info-pre
  8661.             irc-msg-info-post))
  8662.     (if (not irc-called-from-buffer)
  8663.         (progn (irc-insert "")
  8664.            (irc-insert "/AWAY %s" reason)))
  8665.     (irc-send (concat "AWAY :" reason))
  8666.     (setq irc-away (concat " [" reason "]")))
  8667.     (set-buffer-modified-p (buffer-modified-p)))
  8668.   (setq irc-idle-last-sent (irc-current-time)))
  8669.  
  8670.  
  8671. (defun irc-execute-here (cruft)
  8672.   "Usage: /HERE
  8673.  
  8674. Mark yourself as present (ie, not \"away\") on IRC.  Any arguments to this
  8675. command are ignored."
  8676.   (interactive '(""))
  8677.   (if (not irc-called-from-buffer)
  8678.       (progn (irc-insert "")
  8679.          (irc-insert "/HERE")))
  8680.   (irc-send "AWAY")
  8681.   (setq irc-away nil)
  8682.   (set-buffer-modified-p (buffer-modified-p))
  8683.   (setq irc-idle-last-sent (irc-current-time)))
  8684.  
  8685.  
  8686. (defun irc-execute-topic (topic)
  8687.   "Usage: /TOPIC channel [topic ...]
  8688.       or: /TOPIC [topic ...]
  8689.  
  8690. Make 'topic' the description of the named channel; * for channelname means
  8691. the current channel you're talking to.
  8692.  
  8693. With no topic, doesn't change the topic but only inspects it.
  8694.  
  8695. If no channel is given (and the first word of the topic doesn't looks like
  8696. a channel name), the command operates on the current channel you're talking to.
  8697. "
  8698.   (interactive '(""))
  8699.   (let* ((top1 (cond ((and (string= "" topic) (not irc-called-from-buffer))
  8700.               (read-string (concat "Topic for channel "
  8701.                        irc-channel
  8702.                        "? (RET to check) ")))
  8703.              (t topic)))
  8704.      (top (if (string-match "^\\([#&][^ :]+\\) *" top1)
  8705.           (substring top1 (match-end 0))
  8706.           top1))
  8707.      (chn (if (string-match "^\\([#&][^ :]+\\) *" top1)
  8708.           (subfield top1 1)
  8709.           irc-channel)))
  8710.     (if (not irc-called-from-buffer)
  8711.     (progn (irc-insert "")
  8712.            (irc-insert "/TOPIC %s %s" chn top)))
  8713.     (cond ((string= "0" chn)
  8714.        (irc-insert "%%You aren't on any channel."))
  8715.       ((and (irc-is-multijoinable-channel chn)
  8716.         (irc-server-has-settable-topic-on-multijoinable-channel))
  8717.        (if (string-match "^ *$" top)
  8718.            (irc-send (concat "TOPIC " chn))
  8719.            (irc-send (concat "TOPIC " chn " :" top))))
  8720.       ((irc-is-multijoinable-channel irc-channel)
  8721.        (irc-insert "%%Can't set the topic of a #channel."))
  8722.       (t (irc-send (concat "TOPIC :" top)))))
  8723.   (setq irc-idle-last-sent (irc-current-time)))
  8724.  
  8725.  
  8726. (defun irc-execute-oper (oper)
  8727.   "Usage: /OPER [ name [ password ]]
  8728.  
  8729. Attempt to become an IRC Operator.  Can take the name of the operator
  8730. and the password as arguments.  If name is missing then it will be read
  8731. from the minibuffer; if password is missing it will be read and hidden
  8732. in the minibuffer.
  8733.  
  8734. If you become an operator then the word \"operator\" will appear in the
  8735. minibuffer along with the mode name."
  8736.   (interactive '(""))
  8737.   (let* ((pair (cond
  8738.          ((string-match "^ *\\([^: ]+\\) +" oper)
  8739.           (cons (subfield oper 1) (substring oper (match-end 0))))
  8740.          ((string-match "^ *\\([^: ]+\\) *$" oper)
  8741.           (cons (subfield oper 1) ""))
  8742.          (t (cons "" ""))))
  8743.      (n (car pair))
  8744.      (n1 (if (string= "" n)
  8745.          (read-string (concat "Operator name at server "
  8746.                       (upcase irc-server)
  8747.                       "? "))
  8748.          n))
  8749.      (name (irc-nuke-whitespace n1))
  8750.      (p (irc-nuke-whitespace (cdr pair)))
  8751.      (p1 (if (and (string= "" p) (string< "" name))
  8752.          (irc-read-passwd (concat "Password for operator "
  8753.                       name
  8754.                       " at server "
  8755.                       (upcase irc-server)
  8756.                       "? "))
  8757.          p))
  8758.      (password (irc-nuke-whitespace p1)))
  8759.     (cond ((string= "" name)
  8760.        (irc-insert "%%No operator name given."))
  8761.       ((string= "" password)
  8762.        (irc-insert "%%No password given."))
  8763.       (t (if (not irc-called-from-buffer)
  8764.          (progn (irc-insert "")
  8765.             (irc-insert "/OPER ...")))
  8766.          (irc-send (concat "OPER " name " " password)))))
  8767.   (setq irc-idle-last-sent (irc-current-time)))
  8768.  
  8769.  
  8770. (defun irc-execute-summon (user)
  8771.   "Usage: /SUMMON login-name@server
  8772.  
  8773. Summon a user not on IRC to join IRC.  The argument provided may either be
  8774. a user name on the local machine or user@server, where server is another
  8775. machine on the IRC-net.  The user must be signed on to the specified server."
  8776.   (interactive '(""))
  8777.   (let* ((pair (cond ((string-match (concat "^ *\\([^ @]*\\) *@ *"
  8778.                         "\\([^ @]*\\) *$")
  8779.                     user)
  8780.               (cons
  8781.                (substring user (match-beginning 1) (match-end 1))
  8782.                (substring user (match-beginning 2) (match-end 2))))
  8783.              ((string-match "^ *\\([^ @]*\\) *$" user)
  8784.               (cons
  8785.                (substring user (match-beginning 1) (match-end 1))
  8786.                ""))
  8787.              (t (cons "" ""))))
  8788.      (login (irc-nuke-whitespace
  8789.          (if (and (string= "" (car pair)) (not irc-called-from-buffer))
  8790.              (read-string "Login-name of person to summon? ")
  8791.              (car pair))))
  8792.      (s (irc-nuke-whitespace
  8793.          (if (and (not (string= "" login))
  8794.               (string= "" (cdr pair))
  8795.               (not irc-called-from-buffer))
  8796.          (irc-read-object (format "Server \"%s\" is on? " login)
  8797.                   ""
  8798.                   (irc-recall-all 'irc-servernames))
  8799.          (cdr pair))))
  8800.      (server (if (string= "" s) irc-server s)))
  8801.     (if (string= "" login)
  8802.     (irc-insert "%%No login name given.")
  8803.     (progn (if (not irc-called-from-buffer)
  8804.            (progn (irc-insert "")
  8805.               (irc-insert "/SUMMON %s@%s" login server)))
  8806.            (irc-send (concat "SUMMON " login "@" server)))))
  8807.   (setq irc-idle-last-sent (irc-current-time)))
  8808.  
  8809.  
  8810. (defun irc-execute-users (host)
  8811.   "Usage: /USERS [ server ]
  8812.  
  8813. Get a list of the users signed on to \"server\".  If no server name is provided
  8814. then the server to which you are connected is used.  When called interactively
  8815. a prefix argument means to prompt for the server to query."
  8816.   (interactive '(""))
  8817.   (let* ((h (irc-nuke-whitespace
  8818.          (if (and (string= "" host) (not irc-called-from-buffer))
  8819.          (irc-read-object (format (concat "List users on which host?"
  8820.                           " (RET for %s) ")
  8821.                       irc-server)
  8822.                   ""
  8823.                   (irc-recall-all 'irc-servernames))
  8824.          host)))
  8825.      (hst (if (string= "" h) irc-server h)))
  8826.     (if (not irc-called-from-buffer)
  8827.     (progn (irc-insert "")
  8828.            (irc-insert "/USERS %s" hst)))
  8829.     (irc-send (concat "USERS " hst)))
  8830.   (setq irc-idle-last-sent (irc-current-time)))
  8831.  
  8832.  
  8833. (defun irc-execute-ignore (user)
  8834.   "Usage: /IGNORE username@host [event]
  8835.  
  8836. Used to ignore a user. The first argument is a specification of whose messages
  8837. to ignore. The second specifies which kind of messages should be ignored from
  8838. that particular user.
  8839.  
  8840. When specifying a user, you can give either just the user's login name at the
  8841. remote site (you can see what it is by doing a /whois), or you can give the
  8842. user's login name followed by a @ and the name of the user's and the host of
  8843. the user (i.e. the name of host the user's client is running on). You can give
  8844. a * instead of a username to ignore everyone at the given client machine.
  8845.  
  8846. One can either ignore all signs of the user, or just certain events. The events
  8847. include
  8848.     CTCP-ANSWER = Don't display any client to client protocol answers (they
  8849.                   *might* be spurios). Also, don't react on erronous answers.
  8850.     CTCP-QUERY  = Neither display nor answer any client to client protocoll
  8851.                   questions from the user.
  8852.     INVITE      = Don't display 
  8853.     JOIN
  8854.     NICK
  8855.     NOTICE
  8856.     PART
  8857.     PRIVMSG
  8858.     QUIT
  8859.     channel
  8860.     
  8861. THIS IS ALL NOT YET IMPLEMENTED.
  8862.  
  8863. "
  8864.   (interactive '(""))
  8865.   (let ((usr (irc-nuke-whitespace
  8866.           (if (and (string= "" user) (not irc-called-from-buffer))
  8867.           (irc-read-object "Ignore which user? (RET to view) "
  8868.                    user
  8869.                    (irc-recall-all 'irc-nicknames))
  8870.           user))))
  8871.     (if (string= "" usr)
  8872.     (if (not (irc-nothing-remembered-p 'irc-ignored-ppl))
  8873.         (irc-insert "%sYou are currently ignoring %s%s"
  8874.             irc-msg-info-pre
  8875.             (irc-subst-comma (mapconcat
  8876.                       'eval
  8877.                       (irc-recall-all 'irc-ignored-ppl)
  8878.                       ", ")
  8879.                      "and")
  8880.             irc-msg-info-post)
  8881.         (irc-insert "%sYou are not ignoring anyone%s"
  8882.             irc-msg-info-pre
  8883.             irc-msg-info-post))
  8884.     (progn (irc-remember usr 'irc-ignored-ppl)
  8885.            (irc-insert "%sYou are now ignoring %s%s"
  8886.                irc-msg-info-pre
  8887.                usr
  8888.                irc-msg-info-post))))
  8889.   (setq irc-idle-last-sent (irc-current-time)))
  8890.  
  8891.  
  8892. (defun irc-execute-info (nick)
  8893.   "Usage: /INFO nick
  8894.  
  8895. With * as the argument, show some information about who built IRC.
  8896. Else query a users client and show the information she/he has given
  8897. about her/himself. With no argument, show the information you have
  8898. given about yourself. You can set the information with the command
  8899. /USERINFO."
  8900.   (interactive '(""))
  8901.   (let* ((name (irc-nuke-whitespace
  8902.         (if (and (string= "" nick) (not irc-called-from-buffer))
  8903.             (irc-read-object
  8904.              (concat "Info for which user or server? (RET"
  8905.                  " for yourself, * for server program)"
  8906.                  " ")
  8907.              ""
  8908.              (irc-get-names-and-servers))
  8909.             nick))))
  8910.     (cond ((and (string= "" name)
  8911.         (stringp irc-userinfo))
  8912.        (let* ((pre (concat irc-msg-info-pre "You have "))
  8913.           (irc-msg-cont-used (make-string (length pre) ? )))
  8914.          (irc-insert (concat "%sgiven the information \"%s\" about"
  8915.                  " yourself. Use /USERINFO to change it."
  8916.                  " (Warning: /USERINFO with no argument will"
  8917.                  " clear the information)%s")
  8918.              pre
  8919.              irc-userinfo
  8920.              irc-msg-info-post)))
  8921.       ((string= "" name)
  8922.        (let* ((pre (concat irc-msg-info-pre "You haven't "))
  8923.           (irc-msg-cont-used (make-string (length pre) ? )))
  8924.          (irc-insert (concat "%sgiven any information about"
  8925.                  " yourself yet. Use /USERINFO to do so%s")
  8926.              pre
  8927.              irc-msg-info-post)))
  8928.       ((string= "*" name)
  8929.        (if (not irc-called-from-buffer)
  8930.            (progn (irc-insert "")
  8931.               (irc-insert "/INFO *")))
  8932.        (irc-send "INFO"))
  8933.       ((irc-is-receiver name)
  8934.        (if (not irc-called-from-buffer)
  8935.            (progn (irc-insert "")
  8936.               (irc-insert (concat "/INFO " name))))
  8937.        (irc-insert (concat "%sQuerying client of user %s for user supplied"
  8938.                    " information%s")
  8939.                irc-msg-info-pre name irc-msg-info-post)
  8940.        (irc-send (format "WHOIS %s %s" name name)) ;Get names servers idea
  8941.                     ;of names idle time.
  8942.        (irc-send
  8943.         (concat "PRIVMSG "
  8944.             name
  8945.             " :\001FINGER\001"
  8946.             "\001VERSION\001"
  8947.             "\001USERINFO\001"
  8948.             "\001SOURCE\001")))
  8949.       ((irc-is-hostname name)
  8950.        (if (not irc-called-from-buffer)
  8951.            (progn (irc-insert "")
  8952.               (irc-insert (concat "/ADMIN " name))))
  8953.        (irc-send (concat "ADMIN " name)))
  8954.       (t (irc-insert "%%Can't be a users nickname: \"%s\"." name))))
  8955.   (setq irc-idle-last-sent (irc-current-time)))
  8956.  
  8957.  
  8958. (defun irc-execute-userinfo (information)
  8959.   "Usage: /USERINFO [information]
  8960.  
  8961. Set some information (any text you want) to be given out to anybody
  8962. querying this client for it. With no argument, remove all information
  8963. you have given about yourself, making further queries \"draw a
  8964. blank\". You can use /INFO to query other clients. Be warned though,
  8965. other clients may or may not know of this query so you may sometimes
  8966. get back no answer or strange responses."
  8967.   (interactive '(""))
  8968.   (let ((info (if (and (string= "" information) (not irc-called-from-buffer))
  8969.           (read-string (concat "What information do you wish to"
  8970.                        " disclose? (RET to remove) "))
  8971.           information)))
  8972.     (let ((inf (irc-nuke-whitespace info)))
  8973.       (cond ((string= "" inf)
  8974.          (setq irc-userinfo nil)
  8975.          (irc-insert "%sCleared your information string%s"
  8976.              irc-msg-info-pre irc-msg-info-post))
  8977.         (t (setq irc-userinfo inf)
  8978.            (irc-insert "%sThe information string is: \"%s\"%s"
  8979.                irc-msg-info-pre
  8980.                irc-userinfo
  8981.                irc-msg-info-post)))))
  8982.   (setq irc-idle-last-sent (irc-current-time)))
  8983.  
  8984.  
  8985. (defun irc-execute-kill (user-etc)
  8986.   "Usage: /KILL user comment
  8987.  
  8988. Forcibly remove a user from IRC. The mandotory comment will be displayed to
  8989. the victim and to all the IRC operators online. The topic should be in English,
  8990. which after all is the lingua franca of IRC.
  8991.  
  8992. This command is reserved for IRC operators."
  8993.   (interactive '(""))
  8994.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\(.\\|\n\\)+ *$"
  8995.                     user-etc)
  8996.               (cons (subfield user-etc 1) (subfield user-etc 2)))
  8997.              ((string-match "^ *\\([^ ]+\\) *$" user-etc)
  8998.               (cons (subfield user-etc 1) ""))
  8999.              (t (cons "" ""))))
  9000.      (u (irc-nuke-whitespace (car pair)))
  9001.      (user (irc-nuke-whitespace
  9002.         (if (and (string= "" u) (not irc-called-from-buffer))
  9003.             (irc-read-object "Nuke which user? "
  9004.                      ""
  9005.                      (irc-recall-all 'irc-nicknames))
  9006.             u)))
  9007.      (c (irc-nuke-whitespace (cdr pair)))
  9008.      (comm (irc-nuke-whitespace
  9009.         (if (and (string= "" c)
  9010.              (string< "" user)
  9011.              (not irc-called-from-buffer))
  9012.             (read-string "Comment? (In English please) ")
  9013.             c))))
  9014.     (if (string< "" user)
  9015.     (if (string< "" comm)
  9016.         (progn (if (not irc-called-from-buffer)
  9017.                (progn (irc-insert "")
  9018.                   (irc-insert "/KILL %s %s" user comm)))
  9019.            (irc-send (concat "KILL " user " " comm)))
  9020.         (irc-insert "%%No comment given to /KILL command."))
  9021.     (irc-insert "%%No user given, no killing take place.")))
  9022.   (setq irc-idle-last-sent (irc-current-time)))
  9023.  
  9024.  
  9025. (defun irc-execute-invite (user)
  9026.   "Usage: /INVITE user [ channel ]
  9027.  
  9028. Ask \"user\" on IRC to join \"channel\".  If channel is 0, * or not provided
  9029. then the invitation de faults to your current channel, ie the on you're talking
  9030. to. If you are not talking to any channel and channel is 0 or not provided then
  9031. no invitation is sent -- you can't invite someone to \"go private\". When
  9032. called interactively, channel is set to the prefix argument; with no argument
  9033. or - the current channel is assumed."
  9034.   (interactive '(""))
  9035.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$"
  9036.                     user)
  9037.               (cons
  9038.                (substring user (match-beginning 1) (match-end 1))
  9039.                (substring user (match-beginning 2) (match-end 2))))
  9040.              ((string-match " *\\([^ ]+\\) *$" user)
  9041.               (cons (substring user (match-beginning 1) (match-end 1))
  9042.                 ""))
  9043.              (t (cons "" ""))))
  9044.      (usr (irc-nuke-whitespace
  9045.            (if (and (string= "" (car pair)) (not irc-called-from-buffer))
  9046.            (irc-read-object "Invite which user? "
  9047.                     ""
  9048.                     (irc-recall-all 'irc-nicknames))
  9049.            (car pair))))
  9050.      (c1 (irc-nuke-whitespace
  9051.           (if (and (string= "" (cdr pair))
  9052.                (string< "" usr)
  9053.                (not irc-called-from-buffer))
  9054.           (irc-read-object
  9055.            (if (string= "0" irc-channel)
  9056.                (format "Invite \"%s\" to which channel? " usr)
  9057.                (format "Invite \"%s\" %s \"%s\") "
  9058.                    usr
  9059.                    "to which channel? (RET for"
  9060.                    irc-channel))
  9061.            ""
  9062.            (irc-recall-all 'irc-subscribed-channels))
  9063.           (cdr pair))))
  9064.      (chn (if (string= "" c1) irc-channel c1)))
  9065.     (cond ((string= "" usr) (irc-insert "%%No users nick given."))
  9066.       ((string= "0" chn) (irc-insert "%%Can't invite to \"channel\" 0."))
  9067.       (t (if (not irc-called-from-buffer)
  9068.          (progn (irc-insert "")
  9069.             (irc-insert "/INVITE %s %s"
  9070.                     usr
  9071.                     (irc-clean-up-message chn))))
  9072.          (irc-send (format "INVITE %s %s" usr chn)))))
  9073.   (setq irc-idle-last-sent (irc-current-time)))
  9074.  
  9075.  
  9076. (defun irc-execute-names (channel)
  9077.   "Usage: /NAMES [ channel ]
  9078.  
  9079. Show which channels everyone is on.  Optional argument \"channel\" means
  9080. to show just the users on that channel.  * means to show people on the
  9081. current channel.
  9082.  
  9083. Each line starts with a column for the channel number and is followed
  9084. by the nicknames of the people on that channel.  Users who are on
  9085. private channels or who are not on any channel are listed as
  9086. \"Private\".  Users who are on secret channels (channels less than 0)
  9087. are not shown at all.  A %-sign is appended to the current channel's
  9088. name or number."
  9089.   (interactive '(""))
  9090.   (let* ((c (if (and (string= "" channel) (not irc-called-from-buffer))
  9091.          (irc-read-object (format
  9092.                   "Names of persons on which channel? (%s) "
  9093.                   (if (string= "0" irc-channel)
  9094.                       "RET for all"
  9095.                       (concat "RET for all, * for "
  9096.                           irc-channel)))
  9097.                  ""
  9098.                  (irc-recall-all 'irc-subscribed-channels))
  9099.         channel))
  9100.      (chn (if (string= "*" c) irc-channel c)))
  9101.     (if (string= "" chn)
  9102.      (let ((lst (irc-recall-all 'irc-services)))
  9103.       (irc-forget-all 'irc-nicknames)
  9104.       (while lst
  9105.         (irc-remember (car lst) 'irc-nicknames)
  9106.         (setq lst (cdr lst)))))
  9107.     (if (not irc-called-from-buffer)
  9108.      (progn (irc-insert "")
  9109.            (irc-insert "/NAMES %s" chn)))
  9110.     (irc-send (concat "NAMES " chn))
  9111.     (if (not (and (irc-terminal-is-slow)
  9112.           (irc-server-has-end-of-names)))
  9113.     (progn (irc-insert "")
  9114.            (irc-insert "Name of channel Users Nicknames")
  9115.            (irc-insert "--------------- ----- ---------")
  9116.            (set-buffer-modified-p (buffer-modified-p)))))
  9117.   (setq irc-idle-last-sent (irc-current-time)))
  9118.  
  9119.  
  9120. (defun irc-execute-wall (message)
  9121.   "Usage: /WALL message
  9122.  
  9123. Send 'message' to everyone on IRC.  This can only be done by IRC Operators."
  9124.   (interactive '(""))
  9125.   (let ((msg (if (and (string= "" message) (not irc-called-from-buffer))
  9126.          (read-string "Message to send to everyone? ")
  9127.          message)))
  9128.     (if (string= "" msg)
  9129.     (irc-insert "%%No message.")
  9130.     (if (not irc-called-from-buffer)
  9131.         (progn (irc-insert "")
  9132.            (irc-insert "/WALL %s" msg)))
  9133.     (irc-send (concat "WALL " msg))))
  9134.   (setq irc-idle-last-sent (irc-current-time)))
  9135.  
  9136.  
  9137. (defun irc-execute-wallops (message)
  9138.   "Usage: /WALLOPS message
  9139.  
  9140. Send 'message' to every enabled IRC-operator on IRC.
  9141. If you got any problems you think an enabled IRC operator might be the right
  9142. person to help you with, *use* /WALLOPS. (But please don't *ABuse* it)."
  9143.   (interactive '(""))
  9144.   (let ((msg (if (and (string= "" message) (not irc-called-from-buffer))
  9145.          (read-string "Message to send to all enabled IRC operators? ")
  9146.          message)))
  9147.     (if (string< "" msg)
  9148.     (let ((data (format irc-msg-sent "all ENABLED operators of IRC")))
  9149.       (if (not irc-called-from-buffer)
  9150.           (progn (irc-insert "")
  9151.              (irc-insert "/WALLOPS %s" msg)))
  9152.       (irc-send (concat "WALLOPS " msg))
  9153.       (if irc-confirm
  9154.           (irc-insert "%s%s" (make-string
  9155.                   (max 0 (- (window-width
  9156.                          (get-buffer-window
  9157.                           (current-buffer)))
  9158.                         (length data)
  9159.                         1))
  9160.                   ? )
  9161.               data)))
  9162.     (irc-insert "%%No message given, no message sent.")))
  9163.   (setq irc-idle-last-sent (irc-current-time)))
  9164.  
  9165.  
  9166. (defun irc-execute-rehash (cruft)
  9167.   "Usage: /REHASH
  9168.  
  9169. Force the server to which you are connected to reread it's irc.conf file.
  9170. Arguments are ignored.  This command is only available to IRC Operators."
  9171.   (interactive '(""))
  9172.   (if (not irc-called-from-buffer)
  9173.       (progn (irc-insert "")
  9174.          (irc-insert "/REHASH")))
  9175.   (irc-send "REHASH")
  9176.   (setq irc-idle-last-sent (irc-current-time)))
  9177.  
  9178.  
  9179. (defun irc-execute-trace (server)
  9180.   "Usage: /TRACE [ server ]
  9181.  
  9182. Find the route from the server to which you are attached to 'server'; if the
  9183. server argument is not provided then the servers to which the current server
  9184. is directly connected are listed.  This command is only available to IRC
  9185. Operators."
  9186.   (interactive '(""))
  9187.   (let ((srvr (if (and (string= "" server) (not irc-called-from-buffer))
  9188.           (irc-read-object (concat "Trace route to server/user?"
  9189.                        " (RET for " irc-server ") ")
  9190.                    ""
  9191.                    (irc-get-names-and-servers))
  9192.           server)))
  9193.     (if (not irc-called-from-buffer)
  9194.     (progn (irc-insert "")
  9195.            (irc-insert "/TRACE %s" srvr)))
  9196.     (irc-send (concat "TRACE " srvr)))
  9197.   (setq irc-idle-last-sent (irc-current-time)))
  9198.  
  9199.  
  9200. (defun irc-execute-squit (server)
  9201.   "Usage: /SQUIT [ server ]
  9202.  
  9203. Shut down a server-to-server link.
  9204. The link shut down is the the one next farest away from you, ie if you do a
  9205. /SQUIT BYE.EDU and the path to it is your.server.edu!a!b!bye.edu, then the
  9206. link between b and bye.edu will be disconnected.
  9207.  
  9208. You have to be an enabled IRC operator to issue this conmmand."
  9209.   (interactive '(""))
  9210.   (let ((srvr (if (and (string= "" server) (not irc-called-from-buffer))
  9211.           (irc-read-object "Shut down link to which server? "
  9212.                    ""
  9213.                    (irc-recall-all 'irc-servernames))
  9214.           server)))
  9215.     (if (not irc-called-from-buffer)
  9216.     (progn (irc-insert "")
  9217.            (irc-insert "/SQUIT %s" srvr)))
  9218.     (irc-send (concat "SQUIT " srvr))
  9219.     (irc-insert "%sClosing the link to server %s%s"
  9220.         irc-msg-info-pre srvr irc-msg-info-post))
  9221.   (setq irc-idle-last-sent (irc-current-time)))
  9222.  
  9223.  
  9224. (defun irc-execute-connect (new)
  9225.   "Usage: /CONNECT [ newhost [ port [remoteserver ] ] ]
  9226.  
  9227. Connect the local server to SERVER on tcp-port PORT.
  9228.  
  9229. You have to be an enabled IRC operator to issue this conmmand."
  9230.   (interactive '(""))
  9231.   (let* ((tri (cond ((string-match
  9232.               (concat "^ *\\([^ ]+\\) +\\([^ ]+\\) +"
  9233.                   "\\([^ ]+\\) *$")
  9234.               new)
  9235.              (cons (subfield new 1)
  9236.                (cons (subfield new 2)
  9237.                  (subfield new 3))))
  9238.             ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$"
  9239.                    new)
  9240.              (cons (subfield new 1)
  9241.                (cons (subfield new 2)
  9242.                  "")))
  9243.             ((string-match "^ *\\([^ ]+\\) *$" new)
  9244.              (cons (subfield new 1) (cons "" "")))
  9245.             (t (cons "" (cons "" "")))))
  9246.      (h1 (car tri))
  9247.      (h2 (if (and (string= "" h1) (not irc-called-from-buffer))
  9248.          (irc-read-object (concat "Connect server-link to which"
  9249.                       " internet host? ")
  9250.                   ""
  9251.                   (irc-recall-all 'irc-servernames))
  9252.          h1))
  9253.      (new-host (irc-nuke-whitespace h2))
  9254.      (p1 (car (cdr tri)))
  9255.      (p2 (if (and (string= "" p1)
  9256.               (string< "" new-host)
  9257.               (not irc-called-from-buffer))
  9258.          (irc-read-object (concat "Use which TCP-port for"
  9259.                       " server-link? (RET for 6667) ")
  9260.                   ""
  9261.                   (list "194" "6667"))
  9262.          p1))
  9263.      (p3 (irc-nuke-whitespace p2))
  9264.      (new-port (if (string= "" p3)
  9265.                6667 
  9266.                (string-to-int p3)))
  9267.      (s1 (cdr (cdr tri)))
  9268.      (s2 (if (and (string= "" s1)
  9269.               (string< "" new-host)
  9270.               (not irc-called-from-buffer))
  9271.          (irc-read-object (concat "Execute connect command at which"
  9272.                       " (reachable) server? (RET for"
  9273.                       " local) ")
  9274.                   ""
  9275.                   (irc-recall-all 'irc-servernames))
  9276.          s1))
  9277.      (s3 (irc-nuke-whitespace s2))
  9278.      (remote-server (if (string= "" s3) irc-server s3)))
  9279.     (cond ((string-match " " new-host)
  9280.        (irc-insert "%%Spaces aren't allowed in hostnames (%s)." new-host))
  9281.       ((string-match " " remote-server)
  9282.        (irc-insert "%%Spaces aren't allowed in servername (%s)."
  9283.                remote-server))
  9284.       (t (if (not irc-called-from-buffer)
  9285.          (progn (irc-insert "")
  9286.             (if (string= "" new-host)
  9287.                 (irc-insert "/CONNECT")
  9288.                 (irc-insert "/CONNECT %s %d %s"
  9289.                     new-host new-port remote-server))))
  9290.          (if (string= "" new-host)
  9291.          (irc-insert "%%No host to connect too given.")
  9292.          (irc-send (format "CONNECT %s %d %s"
  9293.                    new-host new-port remote-server))
  9294.          (irc-insert (concat "%sConnecting a server-link to host %s on"
  9295.                      " port %d from server %s%s")
  9296.                  irc-msg-info-pre
  9297.                  (upcase new-host)
  9298.                  new-port
  9299.                  (upcase remote-server)
  9300.                  irc-msg-info-post)))
  9301.       (setq irc-idle-last-sent (irc-current-time)))))
  9302.  
  9303. ;; /command just for the client  (need /stamp /alias /unalias)
  9304. (defun irc-execute-send (slist)
  9305.   "Usage: /SEND [ sendlist | - ]
  9306.  
  9307. Set the default sendlist for IRC messages.  This is a comma separated list
  9308. of the intended recipient(s) of messages which do not have an explicit
  9309. sendlist.  '-' as an argument means to disable the default sendlist; every
  9310. message sent then must have an explicit recipient provided with the message.
  9311. Without any arguments this command just displays the current default sendlist.
  9312.  
  9313. Each item specified is checked to see whether you can send there; ambiguous
  9314. references to users are not allowed.
  9315.  
  9316. \"*\" is always allowed and means to send to the current channel, ie the
  9317. channel you are talking to.
  9318. If no item in the new list can be set then the sendlist is not changed."
  9319.   (interactive "sDefault recipient(s) for messages? ")
  9320.   ;; blast some whitespace
  9321.   (setq slist (irc-nuke-whitespace slist))
  9322.   (let (matches)
  9323.     ;; first the easiest case
  9324.     (if (string= "-" slist) (setq irc-default-to nil)
  9325.     (setq matches
  9326.           (delq nil                   ; more indentation fun.  can someone
  9327.             (mapcar               ; recommend a good style manual?
  9328.              (function (lambda (arg)
  9329.                (setq matches (irc-check-list
  9330.                       (irc-recall-all 'irc-nicknames)
  9331.                       arg))
  9332.                (cond
  9333.              ((string= arg "*") arg)
  9334.              ((string= arg "0")
  9335.               (irc-insert "%%You can't send to channel 0.")
  9336.               nil)
  9337.              ((= (length matches) 1) (car matches))
  9338.              ((eq matches nil)
  9339.               (irc-insert "%%No names found to match \"%s\"." arg)
  9340.               nil)
  9341.              (t (irc-insert (concat "%%Ambiguous recipient %s;"
  9342.                         " could be %s.")
  9343.                     arg
  9344.                     (irc-subst-comma
  9345.                      (mapconcat (function (lambda (arg)
  9346.                               (concat "\"" arg "\"")))
  9347.                             matches
  9348.                             ", ")
  9349.                      "or"))
  9350.                 nil))))
  9351.              (irc-burst-comma slist))))
  9352.     (if matches
  9353.         (setq irc-default-to (concat (mapconcat 'eval matches ",") ";"))
  9354.         (or (string= "" slist)  ; only print the error if tried to set it.
  9355.         (irc-insert "%%No matches -- sendlist not changed."))))
  9356.     (cond ((not irc-default-to)
  9357.        (irc-insert (concat "%%Your default sendlist is disabled. (Ie you"
  9358.                    " are not sending to anyone when failing to"
  9359.                    " give an explicit receiver)")))
  9360.       ((string= irc-default-to "*;")
  9361.        (irc-insert (concat "%sYou are now using the default send list (ie"
  9362.                    " sending to the current channel (%s) when"
  9363.                    " failing to give an explicit receiver)%s")
  9364.                irc-msg-info-pre
  9365.                (if (string= "0" irc-channel) "none" irc-channel)
  9366.                irc-msg-info-post))
  9367.       (t (irc-insert (concat "%sYou are sending to %s, use /SEND * to"
  9368.                  " get back default sendlist%s")
  9369.              irc-msg-info-pre
  9370.              (irc-subst-comma
  9371.               (mapconcat 'eval
  9372.                      (irc-burst-comma
  9373.                       (substring irc-default-to 0
  9374.                          (1- (length irc-default-to))))
  9375.                      ", ")
  9376.               "and")
  9377.              irc-msg-info-post))))
  9378.   (setq irc-idle-last-sent (irc-current-time)))
  9379.  
  9380.  
  9381. (defun irc-execute-service (service)
  9382.   "Usage: /SERVICE [ [+]nick | -nick ]
  9383.  
  9384. Show or update list of services. A service is an automaton which looks
  9385. like a normal user, ie it has a nickname. It doesn't act as a normal
  9386. user though; normaly you can ask it for some service. For instance, at
  9387. NICKSERV you can register your nick name (do \"nickserv; help\" for
  9388. more information). Services often talk to you with so called NOTICE's.
  9389. When a service isn't marked as being one, these messages will be
  9390. displayed in a somewhat annoying format. Use this command to get a
  9391. nicer display.
  9392.  
  9393. With no argument, show which nicknames are assumed to be services."
  9394.   (interactive '(""))
  9395.   (let* ((pair (cond ((string-match (concat "^ *\\(+\\|-\\) *"
  9396.                         "\\([^ ]+\\) *$")
  9397.                     service)
  9398.               (cons (subfield service 1) (subfield service 2)))
  9399.              ((string-match "^ *\\([^ ]+\\) *$" service)
  9400.               (cons "+" (subfield service 1)))
  9401.              (t (cons "" ""))))
  9402.      (a (car pair))
  9403.      (a2 (irc-nuke-whitespace
  9404.           (if (and (string= "" a) (not irc-called-from-buffer))
  9405.           (irc-read-object (concat "Mark or unmark nick as"
  9406.                        " service? (RET to mark) ")
  9407.                    ""
  9408.                    '("mark" "unmark"))
  9409.           a)))
  9410.      (action (if (string-match "\\(unmark\\|-\\)" (downcase a2)) nil t))
  9411.      (n (cdr pair))
  9412.      (nick (irc-nuke-whitespace
  9413.         (if (and (string= "" n) (not irc-called-from-buffer))
  9414.             (irc-read-object (format "%sark which %s as service? (%s) "
  9415.                          (if action "M" "Unm")
  9416.                          (if action "nick" "service")
  9417.                          "RET to view existing")
  9418.                      ""
  9419.                      (if action
  9420.                      (irc-recall-all 'irc-nicknames)
  9421.                      (irc-recall-all 'irc-services)))
  9422.             n)))
  9423.      (s-list (irc-recall-all 'irc-services))
  9424.      (s-len (length s-list))
  9425.      (plural (if (= 1 s-len) "" "s"))
  9426.      (lst (irc-listify s-list ", " "and")))
  9427.     (if (not irc-called-from-buffer)
  9428.     (progn (irc-insert "")
  9429.            (irc-insert "/SERVICE %s%s" (if action "+" "-") nick)))
  9430.     (if (string= "" nick)
  9431.     (if (irc-nothing-remembered-p 'irc-services)
  9432.         (irc-insert "%sNo users marked as automatons%s"
  9433.             irc-msg-info-pre irc-msg-info-post)
  9434.         (irc-insert (concat "%s%d \"user%s\" marked as being"
  9435.                 " automaton%s (which provide some service):"
  9436.                 " %s%s")
  9437.             irc-msg-info-pre s-len plural plural lst
  9438.             irc-msg-info-post))
  9439.     (let ((irc-called-from-buffer t))
  9440.       (irc-insert "%s%sing \"%s\" %s being treated as a service%s"
  9441.               irc-msg-info-pre
  9442.               (if action "Add" "Remov")
  9443.               nick
  9444.               (if action "as" "from")
  9445.               irc-msg-info-post)
  9446.       (if action
  9447.           (irc-remember nick 'irc-services)
  9448.           (irc-forget nick 'irc-services))
  9449.       (irc-execute-service ""))))
  9450.   (setq irc-idle-last-sent (irc-current-time)))
  9451.  
  9452.  
  9453. (defun irc-execute-event (events)
  9454.   "Usage: /EVENT [ [+]event | -event ] [...]
  9455.  
  9456. Set the list of events to notify you about with a message.  Notification
  9457. is a one-line message inserted when someone causes that event to occur.
  9458. Events are added with +event or simply event; they are removed with -event.
  9459. + adds all supported events and - removes all supported events.  More than
  9460. one event can be specified in the arguments.  In case of conflict, the argument
  9461. which appears later overrides the argument with which it conflicts.
  9462.  
  9463. Currently supported by /EVENT are the \"ctcp\", \"join\", \"nick\", \"quit\"
  9464. and \"topic\" events.
  9465.  
  9466. CTCP happens whenever someone send you a CTCP query.
  9467. Join happens whenever someone enters or leaves a channel which you are on.
  9468. Nick occurs when someone changes nicknames; recognition of this event is
  9469. currently limited to when the person making the change is on the same channel
  9470. as you.
  9471. Quit happens when someone quits from IRC and you see it.
  9472. Topic happens when the topic of a channel you listen to is changed.
  9473.  
  9474.  
  9475. "
  9476.   (interactive "sNotify for events: ")
  9477.   ;; die scurvy whitespace
  9478.   (setq events (irc-nuke-whitespace events))
  9479.   (let ((recog '(ctcp join nick quit topic))
  9480.     (str events)
  9481.     sym
  9482.     off
  9483.     event
  9484.     (count 0))
  9485.     (while (string< "" events)
  9486.       ;; multiple args are okay.  we'll do one at a time.
  9487.       (setq str (substring events 0 (or (string-match " +" events)
  9488.                     (string-match "$" events)))
  9489.         events (substring events (match-end 0)))
  9490.       (string-match "^\\([---+]?\\)" str)
  9491.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  9492.         event (substring str (match-end 0))
  9493.         sym (if (string= "" event) nil
  9494.             (car (delq nil    ; do some minor pattern matching
  9495.                    (mapcar    ; to find the intended event
  9496.                 (function
  9497.                  (lambda (arg)
  9498.                   (if (string-match
  9499.                        (concat "^" (regexp-quote event))
  9500.                        (prin1-to-string arg))
  9501.                       arg))) recog)))))
  9502.       (cond
  9503.     ((and (string= "" event) off) (setq irc-events nil))
  9504.     ;; the only way for this to happen and not the above is str == "+"
  9505.     ((string= "" event) (setq irc-events recog))
  9506.     ((null sym)
  9507.      (irc-insert "%sEvent: Unknown argument \"%s\"%s"
  9508.              irc-msg-info-pre
  9509.              event
  9510.              irc-msg-info-post))
  9511.     (t (setq irc-events (if off (delq sym irc-events)
  9512.                   (if (not (memq sym irc-events)) ; avoid
  9513.                       (cons sym irc-events) ; redundancy
  9514.                       irc-events))))))
  9515.     (if irc-events
  9516.     (irc-insert "%sEvent notification is currently enabled for %s%s"
  9517.             irc-msg-info-pre
  9518.             (irc-subst-comma (mapconcat 'prin1-to-string irc-events
  9519.                         ", ") "and")
  9520.             irc-msg-info-post)
  9521.     (irc-insert "%sNotification is currently disabled%s"
  9522.             irc-msg-info-pre
  9523.             irc-msg-info-post)))
  9524.   (setq irc-idle-last-sent (irc-current-time)))
  9525.  
  9526.  
  9527. (defun irc-execute-confirm (str)
  9528.   "Usage: /CONFIRM [ + | - ]
  9529.  
  9530. Turn on message confirmation with + or off with -.  Any other arguments or no
  9531. arguments just gives a message about the current setting.
  9532.  
  9533. Message confirmation is a line indicating to whom a message was sent.
  9534. Occasionally this will say that a message has been sent to someone who
  9535. was not present but another message soon after will set the record straight."
  9536.   (interactive '(""))
  9537.   (let* ((c1 (irc-nuke-whitespace
  9538.           (if (and (string= "" str) (not irc-called-from-buffer))
  9539.           (irc-read-object "Turn confirm on or off? (RET to view) "
  9540.                    ""
  9541.                    '("+" "on" "-" "off"))
  9542.           str)))
  9543.      (conf (cond ((string-match "^\\(on\\|+\\)$" c1) "+")
  9544.              ((string-match "^\\(off\\|-\\)$" c1) "-")
  9545.              ((string= "" c1) "")
  9546.              (t nil))))
  9547.     (if (not conf)
  9548.     (irc-insert "%Huh? Try /HELP CONFIRM.")
  9549.     (progn (if (string= "+" conf) (setq irc-confirm t))
  9550.            (if (string= "-" conf) (setq irc-confirm nil))
  9551.            (irc-insert "%sMessage confirmation is %s%s"
  9552.                irc-msg-info-pre
  9553.                (if irc-confirm "on" "off")
  9554.                irc-msg-info-post))))
  9555.   (setq irc-idle-last-sent (irc-current-time)))
  9556.  
  9557.  
  9558. (defun irc-execute-notify (users)
  9559.   "Usage: /NOTIFY [ + | [-]nick ... ]
  9560.  
  9561. Add and delete nicknames from your notifylist. When people on the list get
  9562. detected, you will be notified. When they quit IRC, you will be notified of
  9563. this fact too.
  9564.  
  9565. With no argument, show the people on list, no matter if they've been
  9566. detected or not.
  9567.  
  9568. With a list of nicknames as the argument (each optionally prepended by
  9569. a \"-\"), add those nicknames to the list, unless a \"-\" was
  9570. prepended, in which case the nickname is removed."
  9571.   (interactive '(""))
  9572.   (let* ((str (irc-nuke-whitespace
  9573.            (if (and (string= "" users) (not irc-called-from-buffer))
  9574.            (irc-read-object
  9575.             "Notify when detecting whom? (RET to show list) "
  9576.             ""
  9577.             (irc-recall-all 'irc-nicknames))
  9578.            users)))
  9579.      (list (mapcar 'irc-nuke-whitespace (reverse (irc-burst-comma str))))
  9580.      (added ())
  9581.      (removed ())
  9582.      (show-current (null list)))
  9583.     (while (not (null list))
  9584.       (let* ((subtract (= ?- (aref (car list) 0)))
  9585.          (name (if subtract (substring (car list) 1) (car list)))
  9586.          (is-in-list (irc-recall name 'irc-notify-looked-for)))
  9587.     (cond ((not (irc-is-nickname name))
  9588.            (irc-insert "%%This doesn't look like a nickname: \"%s\"."
  9589.                name))
  9590.           (subtract
  9591.            (if is-in-list
  9592.            (setq removed (cons name removed)))
  9593.            (irc-forget (substring (car list) 1) 'irc-notify-looked-for))
  9594.           (t (if (not is-in-list)
  9595.              (setq added (cons name added)))
  9596.          (irc-remember (car list) 'irc-notify-looked-for))))
  9597.       (setq list (cdr list)))
  9598.     (irc-who-is-on (irc-recall-all 'irc-notify-looked-for))
  9599.     (if show-current
  9600.     (let* ((detected (irc-recall-all 'irc-notify-detected))
  9601.            (looked-for (irc-recall-all 'irc-notify-looked-for))
  9602.            (pre (format "%sOf the persons "
  9603.                 irc-msg-info-pre))
  9604.            (irc-msg-cont-used (make-string (length pre) ? )))
  9605.       (if (null looked-for)
  9606.           (irc-insert "%sYou're not looking for anybody%s"
  9607.               irc-msg-info-pre irc-msg-info-post)
  9608.           (progn
  9609.         (irc-insert "%syou want notifications for (%s),"
  9610.                 pre
  9611.                 (irc-listify looked-for ", " "and"))
  9612.         (setq irc-msg-cont-used (substring
  9613.                      irc-msg-cont-used
  9614.                      0
  9615.                      (- (length "the persons "))))
  9616.         (irc-insert "%s%s on IRC at the moment%s"
  9617.                 irc-msg-cont-used
  9618.                 (if (null detected)
  9619.                 "no one is"
  9620.                 (concat
  9621.                  "the person"
  9622.                  (if (= 1 (length detected)) " " "s ")
  9623.                  (irc-listify detected ", " "and")
  9624.                  (if (= 1 (length detected)) " is" " are")))
  9625.                 irc-msg-info-post))))
  9626.     (let* ((a (if added
  9627.               (format "Added %s to"
  9628.                   (irc-listify (reverse added) ", " "and"))))
  9629.            (r (if removed
  9630.               (format "%semoved %s from"
  9631.                   (if added ", and r" "R")
  9632.                   (irc-listify (reverse removed) ", " "and"))))
  9633.            (str (cond ((and added removed) (format "%s%s" a r))
  9634.               (added a)
  9635.               (removed r)
  9636.               (t "No change to")))
  9637.            (indent (or (and (string-match " " str) (1+ (match-end 0)))
  9638.                irc-msg-cont-used))
  9639.            (irc-msg-cont-used (make-string indent ? )))
  9640.       (irc-insert "%s%s the notification list%s"
  9641.               irc-msg-info-pre str irc-msg-info-post)))))
  9642.  
  9643.  
  9644. (defun irc-execute-unignore (user)
  9645.   "Usage: /UNIGNORE user | + | -
  9646.  
  9647. Stop ignoring a user who has been /IGNOREd.  The special arguments + or -
  9648. mean to stop ignoring everyone who is being ignored."
  9649.   (interactive '(""))
  9650.   (let ((usr (irc-nuke-whitespace
  9651.           (if (and (string= "" user) (not irc-called-from-buffer))
  9652.           (irc-read-object "Stop ignoring whom? (RET to view) "
  9653.                    ""
  9654.                    (irc-recall-all 'irc-ignored-ppl))
  9655.           user))))
  9656.     (if (string= "" usr)
  9657.     (if (irc-nothing-remembered-p 'irc-ignored-ppl)
  9658.         (irc-insert "%sYou are not ignoring anyone%s"
  9659.             irc-msg-info-pre
  9660.             irc-msg-info-post)
  9661.         (irc-insert "%sYou are currently ignoring %s%s"
  9662.             irc-msg-info-pre
  9663.             (irc-subst-comma
  9664.              (mapconcat 'eval
  9665.                     (irc-recall-all 'irc-ignored-ppl)
  9666.                     ", ")
  9667.              "and")
  9668.             irc-msg-info-post))
  9669.     (if (string-match "^[---+]$" usr)
  9670.         (progn (irc-forget-all 'irc-ignored-ppl)
  9671.            (irc-insert "%sYou are no longer ignoring anyone%s"
  9672.                    irc-msg-info-pre
  9673.                    irc-msg-info-post))
  9674.         (if (string< "" user)
  9675.         (progn (irc-forget user 'irc-ignored-ppl)
  9676.                (irc-insert "%sYou are no longer ignoring %s%s"
  9677.                    irc-msg-info-pre
  9678.                    user
  9679.                    irc-msg-info-post))))))
  9680.   (setq irc-idle-last-sent (irc-current-time)))
  9681.  
  9682.  
  9683. (defun irc-execute-kick (kick)
  9684.   "Usage: /KICK user [channel]
  9685.    or: /KICK channel user
  9686.  
  9687. Kick user out from a channel. If no channel is given, defaults to the channel
  9688. you are currently talking to."
  9689.   (interactive)
  9690.   (let* ((c (if (string-match "^ *[^: ]+ +\\([^: ]+\\) *$" kick)
  9691.         (substring kick (match-beginning 1) (match-end 1))
  9692.         irc-channel))
  9693.      (chn (if (string= c "*") irc-channel c))
  9694.      (usr (if (string-match "^ *\\([^: ]+\\) +[^: ]+ *$" kick)
  9695.            (substring kick (match-beginning 1) (match-end 1))
  9696.            kick))
  9697.      (reversed (and (or (irc-is-channelname usr)
  9698.                 (string= usr "*"))
  9699.             (irc-is-nickname chn)))
  9700.      (chan (if reversed (if (string= "*" usr) irc-channel usr) chn))
  9701.      (user (if reversed chn usr)))
  9702.     (if (string-match "^ *$" user)
  9703.     (irc-insert "%%No user given, use /HELP KICK for help.")
  9704.     (if (not irc-called-from-buffer)
  9705.         (progn (irc-insert "")
  9706.            (irc-insert "/KICK %s %s" user chan)))
  9707.     (irc-send (concat "KICK " chan " :" user))))
  9708.   (setq irc-idle-last-sent (irc-current-time)))
  9709.  
  9710.  
  9711. (defun irc-execute-mail (m)
  9712.   "Usage: /MAIL [command [arguments]]
  9713.  
  9714. Give commands to the MAIL subsystem of IRC. This has nothing to do with
  9715. \"regular email\".
  9716. Do \"/MAIL HELP\" for seeing what commands are supported and how to use them.
  9717. Be warned though, the syntax in the help is somewhat ... nonstandard."
  9718.   (interactive)
  9719.   (if (not irc-called-from-buffer)
  9720.       (progn (irc-insert "")
  9721.          (irc-insert "/MAIL %s" m)))
  9722.   (irc-send (concat "MAIL " m))
  9723.   (setq irc-idle-last-sent (irc-current-time)))
  9724.  
  9725.  
  9726. (defun irc-execute-stats (args)
  9727.   "Usage: /STATS [ type [ server ] ]
  9728.  
  9729. Get statistics from a server. There are different kind of statistics
  9730. one can obtain:
  9731.     C    tells which other servers etc a server will accept
  9732.         connections from and will connect to
  9733.     H    tells which servers are treated as HUBS and LEAVES
  9734.     I    tells which masks are used to allow client connections
  9735.         at a server
  9736.     K    tells which user isn't allowed to use a specific server
  9737.     L    tells how much data has passed over the currently
  9738.         active links
  9739.         M       tells how many times the different (server level) commands
  9740.                 has been seen by the server
  9741.         N       same as C
  9742.     Q    tells which servers are in quarantine, ie for which servers
  9743.         a server disconnects its local link in that direction
  9744.         R       tells some internal resource statistics regarding traffic on
  9745.                 the server
  9746.         S       tells which services are connected to a server
  9747.         U       tells the uptime of a server
  9748.     Y    tells the connection classes in effect at a server
  9749.         Z       tells some internal resource statistics regarding the servers
  9750.                 memory usage
  9751.  
  9752. If no server is given, the current server (ie the one your client is
  9753. connected to at the time of the command) is used."
  9754.   (interactive '(""))
  9755.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$" args)
  9756.               (cons (subfield args 1) (subfield args 2)))
  9757.              ((string-match "^ *\\([^ ]+\\) *$" args)
  9758.               (cons (subfield args 1) ""))
  9759.              (t (cons "" ""))))
  9760.      (c (car pair))
  9761.      (s (cdr pair))
  9762.      (cmd (irc-nuke-whitespace
  9763.            (if (and (string= "" c) (not irc-called-from-buffer))
  9764.            (irc-read-object (concat "Which STATS command? (C, I, K, L,"
  9765.                         " M, Q, R, S, U, Y or Z) ")
  9766.                     ""
  9767.                     '("C" "I" "K" "L" "M" "Q" "R" "S" "U" "Y"
  9768.                       "Z"))
  9769.            c)))
  9770.      (server (irc-nuke-whitespace
  9771.           (if (and (string= "" s) (not irc-called-from-buffer))
  9772.               (irc-read-object (concat "STATS at which server? "
  9773.                            "(RET for "
  9774.                            irc-server
  9775.                            ") ")
  9776.                        ""
  9777.                        (irc-recall-all 'irc-servernames))
  9778.               s))))
  9779.     (if (not irc-called-from-buffer)
  9780.     (progn (irc-insert "")
  9781.            (irc-insert "/STATS %s"
  9782.                (concat (upcase cmd)
  9783.                    (if (not (string= "" cmd))
  9784.                        " "
  9785.                        "")
  9786.                    server))))
  9787.     (irc-send (concat "STATS " (concat cmd " " server)))
  9788.     (setq irc-idle-last-sent (irc-current-time))))
  9789.  
  9790.  
  9791. (defun irc-execute-mode (mode)
  9792.   "Usage: /MODE [channel [commands [arguments]]]
  9793.    or: /MODE nick [commands [arguments]]
  9794.  
  9795. Change or inspect the mode of a channel or a user.
  9796. The following modes exist for channels:
  9797.    a      Make channel anonymous (not supported by any servers yet)
  9798.    b      Manipulate a channels list of banned people
  9799.    i      Make channel joinable only with an invitation
  9800.    k      Add or remove channel key (password)
  9801.    l      Limit the number of users on the channel (argument: count)
  9802.    m      Make channel moderated
  9803.    n      Forbid /MSG's into channel
  9804.    o      Make someone a channel operator of this channel (argument: user)
  9805.    p      Make the channel private (ie channel invisible, users shown as being
  9806.           on some private channel)
  9807.    s      Make the channel secret (ie both channel and users invisible)
  9808.    t      Lock the topic of the channel (only settable by channel operators)
  9809.    v      Gives a user a voice on a moderated channel
  9810.  
  9811. The following modes exist for a user:
  9812.    i      Invisible
  9813.    o      Operator on IRC - can only be set with /OPER command
  9814.    s      Statusmessages, receive from server
  9815.    w      WALLOPS, receive from server
  9816. At the moment, only one self can be manipulated, and only i, s and w
  9817. can be set.
  9818.  
  9819. Prepend the mode command character with a + to turn the correspending
  9820. mode on, or with a - to turn it off.
  9821.  
  9822. Examples:
  9823.     /mode                    Show the mode of the current channel.
  9824.     /mode #foo               Show the mode of the channel named \"#foo\".
  9825.     /mode #foo +t            Locks the topic of channel \"#foo\".
  9826.     /mode * +i+o WiZ         Makes the current channel invite only and
  9827.                              gives user WiZ channel operator status.
  9828.     /mode * -o+l+o WiZ 3 `   Removes channel operator status for the
  9829.                              current channel from user WiZ, sets the
  9830.                              maximum number of users to 3 and makes
  9831.                              user ` a channel operator.
  9832.  
  9833.     /mode WiZ                Show the mode of user WiZ.
  9834.     /mode WiZ +s             Start receiving local status messages, such as
  9835.                              other servers connecting to this server etc.
  9836.     /mode WiZ +i-w           Become invisible and stop receiving WALLOPS.
  9837.  
  9838. "
  9839.   (interactive '(""))
  9840.   (let* ((tri (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]\\)"
  9841.                    mode)
  9842.              (cons (subfield mode 1)
  9843.                (cons (subfield mode 2)
  9844.                  (concat (subfield mode 3)
  9845.                      (substring mode (match-end 0))))))
  9846.             ((string-match "^ *\\([^ ]+\\) +\\([^ ]\\)" mode)
  9847.              (cons (subfield mode 1)
  9848.                (cons (concat (subfield mode 2)
  9849.                      (substring mode (match-end 0)))
  9850.                  "")))
  9851.             ((string-match "^ *[^ ]" mode)
  9852.              (cons (irc-nuke-whitespace mode) (cons "" "")))
  9853.             (t (cons "" (cons "" "")))))
  9854.      (ch1 (irc-nuke-whitespace (car tri)))
  9855.      (ch2 (irc-nuke-whitespace
  9856.            (if (and (string= "" ch1) (not irc-called-from-buffer))
  9857.            (irc-read-object (concat "Get/set mode of what channel/user"
  9858.                         "? "
  9859.                         (if (not (string= "0" irc-channel))
  9860.                         (format "(RET for %s) "
  9861.                             irc-channel)))
  9862.                     ""
  9863.                     (append
  9864.                      (irc-recall-all 'irc-subscribed-channels)
  9865.                      (list irc-nick)))
  9866.            ch1)))
  9867.      (channel (if (or (string= "" ch2) (string= "*" ch2)) irc-channel ch2))
  9868.      (is-nick (irc-is-nickname channel))
  9869.      (cmd1 (irc-nuke-whitespace (car (cdr tri))))
  9870.      (command (irc-nuke-whitespace
  9871.            (if (and (string= "" cmd1)
  9872.                 (string< "" channel)
  9873.                 (not irc-called-from-buffer))
  9874.                (irc-read-object (format (concat "Mode commands for"
  9875.                             " channel %s? (RET to"
  9876.                             " view) ")
  9877.                         channel)
  9878.                     ""
  9879.                     (if is-nick
  9880.                         '("+" "-" "i" "o" "s" "w")
  9881.                         '("+" "-" "b" "i" "k" "l" "m" "n"
  9882.                           "o" "p" "s" "t" "v")))
  9883.                cmd1)))
  9884.      (a1 (irc-nuke-whitespace (cdr (cdr tri))))
  9885.      (arg (irc-nuke-whitespace
  9886.            (if (and (string= "" a1)
  9887.             (string< "" channel)
  9888.             (string-match "[LOlo]" command)    ;Needs arguments?
  9889.             (not irc-called-from-buffer))
  9890.            (irc-read-object (format "Arguments to \"/MODE %s %s\"? "
  9891.                         channel command)
  9892.                     ""
  9893.                     (irc-recall-all 'irc-nicknames))
  9894.            a1))))
  9895.     (if (not irc-called-from-buffer)
  9896.     (progn (irc-insert "")
  9897.            (irc-insert "/MODE %s %s %s" channel command arg))) 
  9898.     (irc-send (format "MODE %s %s %s" channel command arg)))
  9899.   (setq irc-idle-last-sent (irc-current-time)))
  9900.  
  9901.  
  9902. (defun irc-execute-die (&optional dummy)
  9903.   "Usage: /DIE
  9904.  
  9905. Tells your local server to go belly-up."
  9906.   (interactive)
  9907.   (if (not irc-called-from-buffer)
  9908.       (progn (irc-insert "")
  9909.          (irc-insert "/DIE")))
  9910.   (irc-send (concat "DIE"))
  9911.   (setq irc-idle-last-sent (irc-current-time)))
  9912.  
  9913.  
  9914. (defun irc-execute-finger (nick)
  9915.   "Usage: /FINGER user
  9916.  
  9917. Query a users client to get users finger information. As some clients don't
  9918. understand this query, you might or might not get back a valid answer.
  9919. Sometime you'll get back a confused \"What?\" from user instead."
  9920.   (interactive '(""))
  9921.   (let* ((u (irc-nuke-whitespace nick))
  9922.      (user (irc-nuke-whitespace
  9923.         (if (and (string= "" u) (not irc-called-from-buffer))
  9924.             (irc-read-object "Get FINGER info from whom? "
  9925.                      ""
  9926.                      (irc-recall-all 'irc-nicknames))
  9927.             u))))
  9928.     (if (string= "" user)
  9929.     (irc-insert "%%No nick name given.")
  9930.     (if (not irc-called-from-buffer)
  9931.         (progn (irc-insert "")
  9932.            (irc-insert "/FINGER %s" user)))
  9933.     (irc-send (concat "PRIVMSG " user " :\001FINGER\001"))))
  9934.   (setq irc-idle-last-sent (irc-current-time)))
  9935.  
  9936.  
  9937. (defun irc-execute-describe (str)
  9938.    "Usage: /DESCRIBE user action
  9939.  
  9940. Send a CTCP ACTION message to a user. As some clients don't understand
  9941. this message, you might get back a confused \"What?\" from user instead.
  9942.  
  9943. See also: /ME"
  9944.    (interactive '(""))
  9945.    (let* ((nick (substring str 0 (string-match " +\\|$" str)))
  9946.       (action (substring str (match-end 0)))
  9947.       (u (irc-nuke-whitespace nick))
  9948.       (user (irc-nuke-whitespace
  9949.          (if (and (string= "" u) (not irc-called-from-buffer))
  9950.              (irc-read-object "Send a ACTION message to whom? "
  9951.                       ""
  9952.                       (irc-recall-all 'irc-nicknames))
  9953.              u)))
  9954.       (m (irc-nuke-whitespace action))
  9955.       (msg (irc-nuke-whitespace
  9956.             (if (and (string= "" m) (not irc-called-from-buffer))
  9957.             (irc-read-object "What is your action? "
  9958.                      ""
  9959.                     nil)
  9960.            m))))
  9961.      (if (string= "" user)
  9962.      (irc-insert "%%No nick name given.")
  9963.     (if (string= "" msg)
  9964.        (irc-insert "%%No action given.")
  9965.       (if (not irc-called-from-buffer)
  9966.          (progn (irc-insert "")
  9967.             (irc-insert "/DESCRIBE %s %s" user msg)))
  9968.      (irc-send (concat "PRIVMSG " user " :\001ACTION " msg "\001")))))
  9969.    (setq irc-idle-last-sent (irc-current-time)))
  9970.  
  9971.  
  9972. (defun irc-execute-me (action)
  9973.    "Usage: /ME action
  9974.  
  9975. Send a CTCP ACTION message to current channel. As some clients don't
  9976. understand this message, you might get back a confused \"What?\" from
  9977. some users.
  9978.  
  9979. See also: /DESCRIBE"
  9980.    (interactive '(""))
  9981.    (let* ((m (irc-nuke-whitespace action))
  9982.       (msg (irc-nuke-whitespace
  9983.             (if (and (string= "" m) (not irc-called-from-buffer))
  9984.             (irc-read-object "What is your action? "
  9985.                     ""
  9986.                     nil)
  9987.            m)))
  9988.       (on-hash (irc-is-multijoinable-channel irc-channel))
  9989.       (newsrvr (irc-server-has-multijoinable-channels)))
  9990.      (if (string= "" msg)
  9991.      (irc-insert "%%No action given.")
  9992.     (if (not irc-called-from-buffer)
  9993.        (progn (irc-insert "")
  9994.           (irc-insert "/ME %s" msg)))
  9995.        (irc-send (concat (if (and newsrvr on-hash)
  9996.                  (concat "PRIVMSG " irc-channel)
  9997.                 "MSG")
  9998.              " :\001ACTION " msg "\001"))
  9999.        (let* ((confirm (format "(Description sent to channel %s)" irc-channel))
  10000.           (padding (make-string (max 0 (- (window-width
  10001.                            (get-buffer-window
  10002.                         (current-buffer)))
  10003.                           (length confirm)
  10004.                           1))
  10005.                     ? )))
  10006.      (irc-insert "%s%s" padding confirm))
  10007.        ))
  10008.    (setq irc-idle-last-sent (irc-current-time)))
  10009.  
  10010.  
  10011. (defun irc-execute-ping (nicks)
  10012.   "Usage: /PING nick ...
  10013.  
  10014. Query a user's client (using CTCP) and calculate the distance between
  10015. the two of you in tenth of seconds. As some clients don't understans this
  10016. query, you might or might not get back a valid answer. Sometimes you
  10017. might even get back a confused \"What?\" from the user of the client.
  10018.  
  10019. Due to some technical limits and sojges laziness, the measurment isn't
  10020. foolproof. If the result seems to be totally wrong, resubmit the query.
  10021.  
  10022. The granularity is 500 ms."
  10023.   (interactive '(""))
  10024.   (while (string-match "^ *\\([^ :]+\\) *" nicks)
  10025.     (sit-for 0)
  10026.     (let* ((nick (subfield nicks 1))
  10027.        (dummy (setq nicks (substring nicks (match-end 1))))
  10028.        (n (irc-nuke-whitespace nick))
  10029.        (v (irc-nuke-whitespace
  10030.            (if (and (string= "" n) (not irc-called-from-buffer))
  10031.            (irc-read-object "Get PING distance to whom? "
  10032.                     ""
  10033.                     (irc-recall-all 'irc-nicknames))
  10034.            n)))
  10035.        (victim (if (string= "*" v) irc-channel v)))
  10036.       (if (string= "" victim)
  10037.       (irc-insert "%%No name given.")
  10038.       (if (not irc-called-from-buffer)
  10039.           (progn (irc-insert "")
  10040.              (irc-insert "/PING %s" victim)))
  10041.       (irc-send (format (concat "PRIVMSG %s :"
  10042.                     "\001ERRMSG PING RELAY %d\001"
  10043.                     "\001PING %d\001")
  10044.                 victim
  10045.                 (car (cdr (irc-current-time)))
  10046.                 (car (cdr (irc-current-time))))))))
  10047.   (setq irc-idle-last-sent (irc-current-time)))
  10048.  
  10049.  
  10050. (defun irc-execute-memberships (&optional dummy)
  10051.   "Usage: /MEMBERSHIPS
  10052.  
  10053. Show which channels you're listening to, and which one you're talking to.
  10054.  
  10055. Use /JOIN to join more or other channels, /LEAVE to leave some."
  10056.   (interactive '(""))
  10057.   (if (not irc-called-from-buffer)
  10058.       (progn (irc-insert "")
  10059.          (irc-insert "/MEMBERSHIPS")))
  10060.   (irc-show-subscribed-channels)
  10061.   (setq irc-idle-last-sent (irc-current-time)))
  10062.  
  10063.  
  10064. (defun irc-execute-signal (sigs)
  10065.   "Usage: /SIGNAL [ + | - | [+]event | -event ] [...]
  10066.  
  10067. Set the events which will get signals (aks bells or dings) when they
  10068. occur.  Events supported are:
  10069.  
  10070. backtalk -- your nick is mentioned            private  -- private messages
  10071. detect   -- nick in notify list seen/gone     public   -- public messages
  10072. invite   -- invitations                       topic    -- channel topic changes
  10073. join     -- channel changes                   wall     -- broadcast messages
  10074. nick     -- nickname changes                  
  10075.  
  10076. Without any arguments /SIGNAL simply prints a message about what signals
  10077. are currently enabled.  With event or +event turn on all signalling for that
  10078. event.  Remove all signals for an event with -event.  /SIGNAL + or /SIGNAL -
  10079. adds or removes all signals respectively.  Multiple arguments are accepted;
  10080. later ones take precedence over the ones which came before them.  For example,
  10081. \"/SIGNAL - +w +i\" would turn off all signals and then turn on signalling only
  10082. for wall messages and invitations."
  10083.   (interactive "sSet signal: ")
  10084.   ;; blow some whitespace away.  curiously this doesn't work correctly in debug
  10085.   (setq sigs (irc-nuke-whitespace sigs))
  10086.   (let ((recog '(backtalk
  10087.          detect
  10088.          invite
  10089.          join
  10090.          nick
  10091.          private
  10092.          public
  10093.          wall
  10094.          topic))
  10095.     str
  10096.     sym
  10097.     on
  10098.     off
  10099.     event)
  10100.     (while (string< "" sigs)
  10101.       ;; take one argument at a time
  10102.       (setq str  (substring sigs 0 (string-match " +\\|$" sigs))
  10103.         sigs (substring sigs (match-end 0)))
  10104.       (string-match "^\\([---+]?\\)" str)
  10105.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  10106.         event (substring str (match-end 0))
  10107.         sym (if (string= "" event) nil
  10108.             (car (delq nil
  10109.                    (mapcar
  10110.                 (function
  10111.                  (lambda (arg)
  10112.                   (if (string-match
  10113.                        (concat "^" (regexp-quote event))
  10114.                        (prin1-to-string arg))
  10115.                       arg))) recog)))))
  10116.       (cond
  10117.     ((and (string= "" event) off)
  10118.      (setq irc-signals (mapcar 'list recog)))
  10119.     ((string= "" event)
  10120.      (setq irc-signals (mapcar
  10121.                 (function (lambda (arg) (list arg t))) recog)))
  10122.     ((null sym)
  10123.      (irc-insert "%%Signal: Unknown argument %s."
  10124.              irc-msg-info-pre
  10125.              event
  10126.              irc-msg-info-post))
  10127.     (t (if off (setcdr (assoc sym irc-signals) nil)
  10128.            (setcdr (assoc sym irc-signals) '(t))))))
  10129.     (setq on (delq nil
  10130.            (mapcar        ; test against t because I have plans
  10131.             (function     ; to couple users and events
  10132.              (lambda (arg)
  10133.               (if (eq (nth 1 (assoc arg irc-signals)) t)
  10134.               arg))) recog)))
  10135.     (if on
  10136.     (irc-insert "%sSignalling is enabled for %s%s"
  10137.             irc-msg-info-pre
  10138.             (irc-subst-comma
  10139.              (mapconcat 'prin1-to-string on ", ") "and")
  10140.             irc-msg-info-post)
  10141.     (irc-insert "%sAll signalling is currently disabled%s"
  10142.             irc-msg-info-pre
  10143.             irc-msg-info-post)))
  10144.   (setq irc-idle-last-sent (irc-current-time)))
  10145.  
  10146.  
  10147. (defun irc-execute-stamp (stamp)
  10148.   "Usage: /STAMP [ + | - | [+]event | -event | interval ] [...]
  10149.  
  10150. Set time-stamping for IRC.  + means to turn it on for all messages from users
  10151. and - means to turn it off for them.  +event or just event will turn it on for
  10152. that class of message and -event means to disable it for those messages.  An
  10153. integer interval means to insert a message indicating the time every N minutes,
  10154. where N is the interval.  With no arguments simply insert a message indicating
  10155. the current time-stamps.
  10156.  
  10157. The current time in HH:MM format can appear two different ways in IRC.  One is
  10158. to have it associate with 'event'; two events, 'private' and 'public' messages,
  10159. are supported this way.  The other is to have it as a stand-alone message
  10160. indicating the current time.  Both can be very useful in noting when someone
  10161. actually sent you a message or when another event happened if you happen to be
  10162. away for a while.  The accuracy of the interval timer is currently limited to
  10163. 0-2 minutes beyond the interval if display-time is not running; accuracy is
  10164. greatly improved if it is.  It can be turned off by setting the interval
  10165. to 0."
  10166.   (interactive "sSet time-stamp: ")
  10167.   ;; whee.  napalm would feel particularly good here.
  10168.   (setq stamp (irc-nuke-whitespace stamp))
  10169.   (let (str sym event off)
  10170.     (while (string< "" stamp)
  10171.       ;; as the args go marching one by one the last one stopped ... <ahem>
  10172.       (setq str   (substring stamp 0 (string-match " +\\|$" stamp))
  10173.         stamp (substring stamp (match-end 0)))
  10174.       (string-match "^\\([---+]?\\)" str)
  10175.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  10176.         event (substring str (match-end 1))
  10177.         sym (cond ((string= "" event) nil)
  10178.               ((string-match (concat "^" (regexp-quote event))
  10179.                      "private") 'private)
  10180.               ((string-match (concat "^" (regexp-quote event))
  10181.                      "public")  'public)
  10182.               ((natnump (car (read-from-string event)))
  10183.                (car (read-from-string event)))))
  10184.       ;; the following cond is really what sets eveything
  10185.       (cond ((and (string= "" event) off) (setq irc-message-stamp nil))
  10186.         ((string= "" event) (setq irc-message-stamp t))
  10187.         ((null sym) (irc-insert "%%Stamp: Unknown argument %s."
  10188.                     irc-msg-info-pre
  10189.                     event
  10190.                     irc-msg-info-post))
  10191.         ((natnump sym) (setq irc-time-stamp sym))
  10192.         (off (setq irc-message-stamp
  10193.                (car (delq sym (if (eq irc-message-stamp t)
  10194.                       '(private public)
  10195.                       (list irc-message-stamp))))))
  10196.         (t (setq irc-message-stamp
  10197.              (cond ((null irc-message-stamp) sym)
  10198.                ((or (eq irc-message-stamp t)
  10199.                 (eq irc-message-stamp sym)) irc-message-stamp)
  10200.                (t t)))))))
  10201.   (irc-insert "%s%s messages get time-stamps.%s%s"
  10202.           irc-msg-info-pre
  10203.           (cond ((eq irc-message-stamp t) "Private and public")
  10204.             ((null irc-message-stamp) "No")
  10205.             (t (capitalize (prin1-to-string irc-message-stamp))))
  10206.           (if (zerop irc-time-stamp) ""
  10207.           (format "  The time interval is %d minutes."
  10208.               irc-time-stamp))
  10209.           irc-msg-info-post)
  10210.   (setq irc-idle-last-sent (irc-current-time)))
  10211.  
  10212.  
  10213. (defun irc-execute-alias (alias)
  10214.   "Usage: /ALIAS alias [command] [args for command]]]
  10215.  
  10216. Allow 'alias' to be equivalent to 'command'.
  10217. For example, \"/ALIAS tf time tut.fi\" will make typing \"/tf\" be equivalent
  10218. to having issued the command \"/time tut.fi\".  Aliases can only be made
  10219. to existing commands, not other aliases.  They are also only recognized when
  10220. in the command name position of a line.  If given with no arguments then
  10221. all aliases are displayed; if given with just an alias name then the alias
  10222. with that name will be shown.  Aliases can be removed with /UNALIAS."
  10223.   (interactive "sWhat name should the new alias have? (RET to view all) ")
  10224.   (if (and (interactive-p) (string-match "[^: ]+" alias))
  10225.       (setq alias (concat
  10226.            alias
  10227.            " "
  10228.            (irc-read-object
  10229.             (format (concat "Alias \"%s\" to which command? "
  10230.                     "(Including optional arguments) ")
  10231.                 alias)
  10232.             ""
  10233.             (mapcar (function (lambda (pair)
  10234.                   (upcase (cdr pair))))
  10235.                 (append irc-alias-alist
  10236.                     (append irc-command-alist
  10237.                         irc-operator-alist)))))))
  10238.   (setq alias (irc-nuke-whitespace alias))
  10239.   (string-match "^/?\\([^: ]*\\) */?\\([^: ]*\\) *" alias)
  10240.   (let ((new (upcase (subfield alias 1)))
  10241.     (cmd (upcase (subfield alias 2)))
  10242.     (arg (irc-nuke-whitespace (substring alias (match-end 2))))
  10243.     match)
  10244.     (cond
  10245.       ((string= "" new)
  10246.        (let ((aliases irc-alias-alist))
  10247.      (cond ((> (length aliases) 0)
  10248.         (while aliases
  10249.           (irc-insert "%s/%s is aliased to mean \"/%s\"%s"
  10250.                   irc-msg-info-pre
  10251.                   (car (car aliases))
  10252.                   (cdr (car aliases))
  10253.                   irc-msg-info-post)
  10254.           (setq aliases (cdr aliases)))
  10255.         (irc-insert "%sListed all aliases%s"
  10256.                 irc-msg-info-pre
  10257.                 irc-msg-info-post))
  10258.            (t (irc-insert "%sYou don't have any aliases%s"
  10259.                   irc-msg-info-pre
  10260.                   irc-msg-info-post)))))
  10261.       ((string= "" cmd)
  10262.        (let ((alias (assoc new irc-alias-alist)))
  10263.      (if alias
  10264.          (irc-insert "%s/%s is aliased to mean \"/%s\"%s"
  10265.              irc-msg-info-pre
  10266.              (car alias)
  10267.              (cdr alias)
  10268.              irc-msg-info-post)
  10269.          ;; this could possibly have done some matching to see whether
  10270.          ;; just an abbrev was being given, but we'll just take it as given
  10271.          (irc-insert "%s\"/%s\" is not aliased%s"
  10272.              irc-msg-info-pre
  10273.              new
  10274.              irc-msg-info-post))))
  10275.       (t
  10276.        ;; Okay, we've got at least a command.  let's try and make this as
  10277.        ;; painless as possible. 
  10278.        (setq match (irc-check-list
  10279.             (mapcar 'car (append irc-command-alist
  10280.                      irc-operator-alist))
  10281.             cmd
  10282.             'start-only))
  10283.        (if (/= (length match) 1)
  10284.        (if match
  10285.            (irc-insert "%%Ambiguous command /%s; could be %s."
  10286.                cmd
  10287.                (irc-subst-comma
  10288.                 (mapconcat (function (lambda (arg)
  10289.                      (concat "\"" arg "\"")))
  10290.                        match
  10291.                        ", ")
  10292.                 "or"))
  10293.            (irc-insert "%%Command not found: /%s." cmd))
  10294.        (irc-change-alias new
  10295.                  (concat (downcase (car match))
  10296.                      ;; no trailing space if no arg
  10297.                      (if (string= "" arg)
  10298.                      ""
  10299.                      " ")
  10300.                      arg)
  10301.                  'add)
  10302.        (irc-insert "%s\"/%s\" has been aliased to mean \"/%s\"%s"
  10303.                irc-msg-info-pre
  10304.                new 
  10305.                (cdr (assoc new irc-alias-alist))
  10306.                irc-msg-info-post)))))
  10307.   (setq irc-idle-last-sent (irc-current-time)))
  10308.  
  10309.  
  10310. (defun irc-execute-unalias (alias)
  10311.   "Usage: /UNALIAS alias
  10312.  
  10313. Remove the 'alias' for a command."
  10314.   (interactive '(""))
  10315.   (let* ((tmpalias (if (and (string= "" alias) (not irc-called-from-buffer))
  10316.                (irc-read-object "Remove which alias? "
  10317.                     ""
  10318.                     (mapcar (function (lambda (p)
  10319.                           (upcase (car p))))
  10320.                         (irc-recall-all
  10321.                          'irc-alias-alist)))
  10322.                alias))
  10323.      (a (irc-nuke-whitespace tmpalias)) 
  10324.      (match (irc-check-list (mapcar 'car irc-alias-alist) a t)))
  10325.     (if (/= (length match) 1)
  10326.     (if match (irc-insert "%%%s is an ambiguous alias. Could be %s."
  10327.                   (upcase alias)
  10328.                   (irc-subst-comma
  10329.                    (mapconcat (function (lambda (arg)
  10330.                         (concat "\"" arg "\"")))
  10331.                       match
  10332.                       ", ")
  10333.                    "or"))
  10334.         (irc-insert "%%No alias found to match %s." (upcase alias)))
  10335.     (irc-change-alias (car match) nil 'remove)
  10336.     (irc-insert "%s\"%s\" is no longer aliased%s"
  10337.             irc-msg-info-pre (car match) irc-msg-info-post)))
  10338.   (setq irc-idle-last-sent (irc-current-time)))
  10339.  
  10340.  
  10341. ;;START of code by Per StarbΣck (starback@Student.DoCS.UU.SE)
  10342. (defun irc-execute-help (topic)
  10343.   "Usage: /HELP topic
  10344.  
  10345. Get the documentation for \"command\".  If no command is given then a list
  10346. of the possible topics is shown.  Note that commands for IRC Operators will
  10347. not appear in the help topics when not an IRC Operator."
  10348.   (interactive '(""))
  10349.   (let* ((normal-commands (mapcar (function car) irc-command-alist))
  10350.      (oper-commands (mapcar (function car) irc-operator-alist))
  10351.      (alias-commands (mapcar (function car) irc-alias-alist))
  10352.      (help-topics (mapcar (function car) irc-help-topic-alist))
  10353.      (top (irc-nuke-whitespace
  10354.            (if (and (string= "" topic) (not irc-called-from-buffer))
  10355.            (irc-read-object
  10356.             "Help for which command or topic? "
  10357.             ""
  10358.             (append normal-commands
  10359.                 (if irc-operator oper-commands '())
  10360.                 alias-commands
  10361.                 help-topics))
  10362.          topic))))
  10363.     (if (not irc-called-from-buffer)
  10364.     (progn (irc-insert "")
  10365.            (irc-insert "/HELP %s" top)))
  10366.     (if (string= top "")
  10367.     (let* ((str (concat "Help is available for the following IRC-mode"
  10368.                 " commands:\n"))
  10369.            (topics (sort (append normal-commands
  10370.                      (if irc-operator oper-commands nil)
  10371.                      alias-commands
  10372.                      help-topics)
  10373.                  (function string<))))
  10374.       (while topics
  10375.         (setq str (concat str
  10376.                   (format "\n%14s%14s%14s%14s%14s"
  10377.                       (nth 0 topics)
  10378.                       (or (nth 1 topics) "")
  10379.                       (or (nth 2 topics) "")
  10380.                       (or (nth 3 topics) "")
  10381.                       (or (nth 4 topics) "")))
  10382.           topics (nthcdr 5 topics)))
  10383.       (with-output-to-temp-buffer "*Help*" (princ str)))
  10384.       (let* ((matches (irc-check-list
  10385.                (append normal-commands
  10386.                    (if irc-operator oper-commands '())
  10387.                    alias-commands
  10388.                    help-topics)
  10389.                top t))
  10390.          ;;(matches-normal (irc-common-element matches normal-commands))
  10391.          (matches-oper (irc-common-element matches oper-commands))
  10392.          (matches-alias (irc-common-element matches alias-commands))
  10393.          (matches-topic (irc-common-element matches help-topics))
  10394.          (shadowingalias nil))
  10395.     ;; If there is an alias with the same name as a command,
  10396.     ;; the alias is preferred.  Other collisions shouldn't be possible.
  10397.     (if (and (cdr matches)        ;== (> (length matches) 1)
  10398.          (irc-all-true (mapcar (function (lambda (x)
  10399.                            (string= x (car matches))))
  10400.                        (cdr matches))))
  10401.         (if matches-alias
  10402.         (setq matches (list (car matches))
  10403.               shadowingalias (concat
  10404.                       "\n\nThis shadows the "
  10405.                       (cond (matches-topic
  10406.                          "general help on the topic")
  10407.                         (matches-oper "operator command")
  10408.                         (t "command"))
  10409.                       " with the same name."))
  10410.           (with-output-to-temp-buffer "*Help*"
  10411.         (princ (format (concat "There are several things called %s, "
  10412.                        "and no way to know \nwhich one you "
  10413.                        "want help on.  This is a bug--please "
  10414.                        "contact \n%s.")
  10415.                    (car matches) irc-hacker)))))
  10416.     ;; If nothing else matches even a non-oper gets to see
  10417.     ;; help on oper commands.
  10418.     (if (and (null matches) (not irc-operator))
  10419.         (setq matches (irc-check-list oper-commands top t)
  10420.           matches-oper matches))
  10421.     (cond ((null matches)
  10422.            (irc-insert "%%No help is available for \"%s\"."
  10423.                (upcase top)))
  10424.           ((cdr matches)        ;== (> (length matches) 1)
  10425.            (irc-insert "%%Ambiguous help topic %s; could be %s."
  10426.                (upcase top)
  10427.                (irc-subst-comma
  10428.                 (mapconcat (function (lambda (arg)
  10429.                            (concat "\"" arg "\"")))
  10430.                        matches
  10431.                        ", ")
  10432.                 "or")))
  10433.           (t ;;Exactly one match:
  10434.            (let ((match (car matches)))
  10435.          (with-output-to-temp-buffer "*Help*"
  10436.            (cond (matches-alias
  10437.               (let ((aliasfor (cdr (assoc match irc-alias-alist))))
  10438.                 (princ (format "%s is an alias for \"/%s\"."
  10439.                        match aliasfor))
  10440.                 (if shadowingalias (princ shadowingalias))
  10441.                 (princ (format "\n\n%s"
  10442.                        (irc-help-for-command
  10443.                         (upcase
  10444.                          (substring 
  10445.                           aliasfor 0
  10446.                           (string-match " "
  10447.                                 aliasfor))))))))
  10448.              (matches-topic
  10449.               (princ (cdr (assoc match irc-help-topic-alist))))
  10450.              (t (princ (irc-help-for-command match))))))))))))
  10451.  
  10452.  
  10453. (defun irc-help-for-command (command)
  10454.   "Returns the documentation string for the irc command COMMAND."
  10455.   (documentation
  10456.    (or (intern-soft (concat "irc-execute-"
  10457.                 (or (cdr (assoc command irc-command-alist))
  10458.                 (cdr (assoc command irc-operator-alist)))))
  10459.        'irc-internal-error-dummy)))
  10460.  
  10461.  
  10462. (defun irc-common-element (list1 list2)
  10463.   "True if two lists have at least one common element.
  10464. The predicate eq is used for the comparisions."
  10465.   (cond ((null list1) nil)
  10466.     ((memq (car list1) list2) t)
  10467.     (t (irc-common-element (cdr list1) list2))))
  10468.  
  10469.  
  10470. (defun irc-all-true (list)
  10471.   "Is true if all args in LIST are true."
  10472.   ;; This is needed as special forms (like AND) can't be given to FUNCALL.
  10473.   (if (null list) t (and (car list) (irc-all-true (cdr list)))))
  10474. ;;;END of code by Per StarbΣck.
  10475.  
  10476.  
  10477. (defun irc-later-execute-lusers ()
  10478.   "Dummy function. Used when it's desired to do a irc-execute-lusers in a
  10479. little while. Not implemented yet."
  10480.   nil)
  10481.  
  10482.  
  10483. (defun irc-internal-error-dummy ()
  10484.   "Internal error.
  10485.  
  10486. No internal function associated with this command. This should never happen.
  10487. Please report this to the person mentioned in variable irc-hacker."
  10488.   nil)
  10489.  
  10490.  
  10491.  
  10492. ;; miscellaneous irc-* commands
  10493. (defun irc-truncate-buffer (max min)
  10494.   "Remove as many lines from the beginning of the buffer as is
  10495. necessary to get it under MAX number of characters, downto MIN number
  10496. of characters. This function is used by irc-mode to prevent an
  10497. irc-session from consuming gross amounts of space.
  10498.  
  10499. See irc-filter about not truncating the Kiwi buffer at all."
  10500.   (if (>= (buffer-size) max)
  10501.       (save-excursion
  10502.     ;; first go to the lowest point posssible that would do it
  10503.     (goto-char min)
  10504.     ;; get to the end of this line
  10505.     (end-of-line)
  10506.     (if (< (point) irc-mark)
  10507.         ;; just to make sure we don't toast pending input
  10508.         (delete-region 1 (1+ (point)))
  10509.         (message "Warning: %s exceeding %s characters.  Couldn't truncate."
  10510.              (buffer-name (current-buffer)) max)))))
  10511.  
  10512.  
  10513. (defun irc-read-passwd (&optional prompt)
  10514.   "Allow user to type a string without it showing.  Returns string.
  10515. If optional PROMPT non-nil, use it as the prompt string in the minibuffer."
  10516.   ;; this is based on a similar function in telnet.el
  10517.   ;; the major drawback is that while being prompted for a password
  10518.   ;; it stays in this routine until C-g, RET or LFD is typed.
  10519.   (let ((passwd "") (echo-keystrokes 0) char)
  10520.     (if prompt (message prompt))
  10521.     (while (not (or (= (setq char (read-char)) 13) (= char 10)))
  10522.       ;; naughty bit.  take C-h to mean DEL.
  10523.       (if (or (= char 8) (= char 127))
  10524.       (if (> (length passwd) 0)
  10525.           (setq passwd (substring passwd 0 (1- (length passwd)))))
  10526.       (setq passwd (concat passwd (char-to-string char))))
  10527.       (if prompt (message (concat prompt (make-string (length passwd) ?*)))))
  10528.     (if prompt (message ""))
  10529.     passwd))
  10530.  
  10531.  
  10532. (defun irc-read-object (prompt object list)
  10533.   "Prompting with PROMPT, read an IRC objects name from the minibuffer.
  10534. Second argument OBJECT is a string which is checked for a non-ambiguous match
  10535. before the minibuffer read is done.  Optional third argument LIST is a
  10536. list to use for checking rather than the irc-nicknames.
  10537.  
  10538. It returns either the name of a object or an empty string (\"\")."
  10539.   (if (not (string-match "^ *\\([^: ]*\\)" object)) ; just want one name
  10540.       "" 
  10541.       (let ((completion-ignore-case t)
  10542.         (object (substring object (match-beginning 1) (match-end 1)))
  10543.         (match nil))
  10544.     (if (or (string= "" object)
  10545.         (/= (length (setq match (irc-check-list list object))) 1))
  10546.         (completing-read (format "%s%s"
  10547.                      (if (string= "" object)
  10548.                      ""
  10549.                      (format (if (zerop (length match))
  10550.                              "No names match %s.  "
  10551.                              "\"%s\" is ambiguous.  ")
  10552.                          object))
  10553.                      prompt)
  10554.                  ;; build the list for completing-read.  a
  10555.                  ;; null string is there so that it can exit
  10556.                  ;; without anything, since we require matches
  10557.                  (mapcar 'list (cons "" list))
  10558.                  nil
  10559.                  nil        ;Also non exact matches are OK.
  10560.                  object)
  10561.         (car match)))))
  10562.  
  10563. (defun irc-nuke-whitespace (str)
  10564.   "One string argument.  Returns it with surrounding whitespace removed."
  10565.   (let* ((tmp (and (string-match "^ *" str)
  10566.            (substring str (match-end 0)))))
  10567.     (if (not tmp)
  10568.     str
  10569.     (and (string-match " *$" tmp)
  10570.          (substring tmp 0 (match-beginning 0))))))
  10571.  
  10572.  
  10573. (defun irc-stringlist-to-string (list &optional sep)
  10574.   "Take a LIST of strings and concate all string into one single string.
  10575. Optionally takes as a second argument a string to use as a seperator."
  10576.   (mapconcat (function (lambda (arg) arg)) list sep))
  10577.  
  10578.  
  10579. (defun irc-subst-comma (str newsep)
  10580.   "Return the string formed by substituting for the last \", \" in STR
  10581. the string NEWSEP followed by a space.  For example:
  10582.   (irc-subst-comma \"1, 2, 3\" \"or\") => \"1, 2 or 3\"
  10583.  
  10584. This function is especially designed for making message from irc-mode
  10585. more grammatically correct and the strings which it operates on should
  10586. be carefully chosen so as to avoid possibly blowing away a comma that
  10587. really wasn't separating elements in a list."
  10588.   ;; did you know that example up there can't appear starting in column 0
  10589.   ;; without screwing up lisp-indent-line?
  10590.   (if (string-match ", [^,]*$" str)
  10591.       (concat (substring str 0 (match-beginning 0)) " " newsep
  10592.           (substring str (1+ (match-beginning 0))))
  10593.       str))
  10594.  
  10595.  
  10596. (defun irc-listify (list sep conn)
  10597.   "Take a LIST of strings, and put them together into one single string, using
  10598. the SEPerator string between every pair of string, except the last pair where
  10599. the CONNector is used.
  10600. Example: (irc-listify '(\"a\" \"b\" \"c\") \", \" \"and\") returns
  10601. \"a, b and c\"."
  10602.   (irc-subst-comma (irc-stringlist-to-string list sep) conn))
  10603.  
  10604.  
  10605. (defun irc-get-time ()
  10606.   "Return the hour and minutes of the current time in the form \"HH:MM\"."
  10607.   (let ((time (current-time-string)))
  10608.     (substring time
  10609.            (string-match "[0-2][0-9]:[0-5][0-9]" time)
  10610.            (match-end 0))))
  10611.  
  10612.  
  10613. ;;;(defun irc-current-time ()
  10614. ;;;  "Return current time as number of seconds since 1-jan-1970 0:00:00.
  10615. ;;;As this is a 32 bit number but GNU Emacs only handles 16 bit numbers, split
  10616. ;;;it up in a cons with the car being the high order 16 bit numer and th cdr
  10617. ;;;the low order 16 bit number."
  10618. ;;;  (if (= 0 (buffer-size))
  10619. ;;;      (irc-insert ""))
  10620. ;;;  (write-region (point-max) (1- (point-max)) irc-idle-scratch-file nil 'silent)
  10621. ;;;  (nth 6 (file-attributes irc-idle-scratch-file)))
  10622.  
  10623.  
  10624. (defun irc-current-time ()
  10625.   "Return current time as number of seconds since 1-jan-1970 0:00:00.
  10626. As this is a 32 bit number but GNU Emacs only handles 16 bit numbers, split
  10627. it up in a cons with the car being the high order 16 bit numer and the cdr
  10628. the low order 16 bit number.
  10629.  
  10630. Written by Stephen Ma <ma_s@maths.su.oz.au>"
  10631.   (irc-time-to-int (current-time-string)))
  10632.  
  10633.  
  10634. (defun irc-time-to-int (timestr)
  10635.   "Convert from time in string format as returned by current-time-string
  10636. to a double integer format, as returned by file-attributes.
  10637.  
  10638. Written by Stephen Ma <ma_s@maths.su.oz.au>"
  10639.   (let* ((norm+ '(lambda (num1 num2)
  10640.           (let ((sumh (+ (car num1) (car num2)))
  10641.             (suml (+ (car (cdr num1)) (car (cdr num2)))))
  10642.             (list (+ sumh (/ suml 65536)) (% suml 65536)))))
  10643.      (norm* '(lambda (num1 num2)
  10644.           (let ((prodh (* num1 (car num2)))
  10645.             (prodl (* num1 (car (cdr num2)))))
  10646.             (list (+ prodh (/ prodl 65536)) (% prodl 65536)))))
  10647.      (seconds (string-to-int (substring timestr 17 19)))
  10648.      (minutes (string-to-int (substring timestr 14 16)))
  10649.      (hours (string-to-int (substring timestr 11 13)))
  10650.      (partdays (1- (string-to-int (substring timestr 8 10))))
  10651.      (years (string-to-int (substring timestr 20 24)))
  10652.      (days (+ partdays
  10653.           (cond ((and (= (% years 4) 0)
  10654.                   (/= (% years 100) 0))
  10655.              (cdr (assoc (substring timestr 4 7)
  10656.                      '(("Jan" . 0)
  10657.                        ("Feb" . 31)
  10658.                        ("Mar" . 60)
  10659.                        ("Apr" . 91)
  10660.                        ("May" . 121)
  10661.                        ("Jun" . 152)
  10662.                        ("Jul" . 182)
  10663.                        ("Aug" . 213)
  10664.                        ("Sep" . 244)
  10665.                        ("Oct" . 274)
  10666.                        ("Nov" . 305)
  10667.                        ("Dec" . 335)))))
  10668.             (t (cdr (assoc (substring timestr 4 7)
  10669.                        '(("Jan" . 0)
  10670.                      ("Feb" . 31)
  10671.                      ("Mar" . 59)
  10672.                      ("Apr" . 90)
  10673.                      ("May" . 120)
  10674.                      ("Jun" . 151)
  10675.                      ("Jul" . 181)
  10676.                      ("Aug" . 212)
  10677.                      ("Sep" . 243)
  10678.                      ("Oct" . 273)
  10679.                      ("Nov" . 304)
  10680.                      ("Dec" . 334))))))
  10681.           (* (- years 1970) 365)
  10682.           (/ (- years 1969) 4)
  10683.           (- (/ (- years 1901) 100)))))
  10684.     (funcall norm+
  10685.          (funcall norm*
  10686.               60
  10687.               (funcall norm+
  10688.                    (funcall norm*
  10689.                     60
  10690.                     (funcall norm+
  10691.                          (funcall norm*
  10692.                               24
  10693.                               (list 0 days))
  10694.                          (list 0 hours)))
  10695.                    (list 0 minutes)))
  10696.          (list 0 seconds))))
  10697.  
  10698.  
  10699. (defun irc-time= (a b)
  10700.   "Compare two time, return true if they're equal."
  10701.   (and (= (nth 0 a) (nth 0 b))
  10702.        (= (nth 1 a) (nth 1 b))))
  10703.  
  10704.  
  10705. (defun irc-time< (a b)
  10706.   "Compare two times, return t if the first is earlier than the second."
  10707.   (or (< (nth 0 a) (nth 0 b))
  10708.       (and (= (nth 0 a) (nth 0 b))
  10709.        (< (nth 1 a) (nth 1 b)))))
  10710.  
  10711.  
  10712. (defun irc-time-diff (a b)
  10713.   "Return the difference between two times. This functions requires
  10714. the first argument to be later in time than the second argument."
  10715.   (cond ((= (nth 0 a) (nth 0 b)) (list 0 (- (nth 1 a) (nth 1  b))))
  10716.     ((> (nth 1 b) (nth 1 a)) (list (- (nth 0 a) (nth 0 b) 1)
  10717.                        (- (+ 65536 (nth 1 a)) (nth 1 b))))
  10718.     (t (list (- (nth 0 a) (nth 0 b))
  10719.          (- (nth 1 a) (nth 1 b))))))
  10720.  
  10721.  
  10722. (defun irc-idle-time ()
  10723.   "Return a approximation of the idle time. The time is the number of seconds
  10724. which have passed since the last write to the server. If a valid idle-time
  10725. can't be returned, -1 is returned instead."
  10726.   (let ((now (irc-current-time))
  10727.     (then irc-idle-last-sent))
  10728.     (if (or (numberp irc-idle-last-sent)
  10729.         (not (= (car now) (car then))))
  10730.     -1
  10731.     (- (car (cdr now))
  10732.        (car (cdr then))))))
  10733.  
  10734.  
  10735. (defun irc-internal-time ()
  10736.   "Return a new value every time irc-internal-time is called. The new value is
  10737. larger than the latest returned, starting at 0."
  10738.   (if (not (boundp 'irc-internal-time))
  10739.       (set (make-local-variable 'irc-internal-time) nil))
  10740.   (if (not (integerp irc-internal-time))
  10741.       (setq irc-internal-time 0)
  10742.       (setq irc-internal-time (1+ irc-internal-time))))
  10743.  
  10744.  
  10745. (defun irc-check-time ()
  10746.   "Check to see whether it is time to insert a current-time message into
  10747. the *IRC* buffer."
  10748.   (if (null irc-last-time)
  10749.       (setq irc-last-time 0))
  10750.   (let* ((time (irc-get-time))
  10751.      (last (if (and (boundp 'irc-last-time) (stringp irc-last-time))
  10752.            irc-last-time
  10753.            time))
  10754.       (old-minute (string-to-int (substring last 3)))
  10755.       (new-minute (string-to-int (substring time 3)))
  10756.       (total-time (if (numberp irc-total-time) irc-total-time 0)))
  10757.     (if (and (zerop irc-time-stamp) (zerop irc-notify-interval))
  10758.      ()
  10759.     ;; check the time sentinel
  10760.     (if (string= irc-last-time time)
  10761.         ()
  10762.         ;; time has gone stomping on by ...
  10763.         (setq new-minute (+ new-minute (if (< new-minute old-minute) 60 0))
  10764.           irc-last-time time
  10765.           irc-total-time (+ total-time (- new-minute old-minute)))
  10766.         (if (not (zerop irc-time-stamp))
  10767.         (if (not (< (- irc-total-time irc-last-stamp) irc-time-stamp))
  10768.             (progn (irc-wrap-display-time)
  10769.                (irc-send "TIME")
  10770.                (setq irc-last-stamp irc-total-time))))
  10771.         (if (not (zerop irc-notify-interval))
  10772.         (if (not (< (- irc-total-time irc-last-notify)
  10773.                 irc-notify-interval))
  10774.             (progn (irc-wrap-display-time)
  10775.                (irc-who-is-on
  10776.                 (irc-recall-all 'irc-notify-looked-for))
  10777.                (setq irc-last-notify irc-total-time))))))))
  10778.  
  10779.  
  10780. (defun irc-wrap-display-time ()
  10781.   "Set up a wrapper around the display-time-filter to hopefully provide a
  10782. little better accuracy for the time stamps."
  10783.   (if (and (fboundp 'display-time-filter)
  10784.            (not (fboundp 'original-display-time-filter)))
  10785.       (progn
  10786.         (fset 'original-display-time-filter
  10787.               (symbol-function 'display-time-filter))
  10788.         ;; a nested defun seems to do funny things to the byte-compiler, so
  10789.         ;; instead we find a way around it.
  10790.         (fset 'display-time-filter
  10791.               (function
  10792.                (lambda (proc str)
  10793.         "
  10794. The filter for the display-time-process.  This function has been modified
  10795. for IRC-mode to call irc-check-time before calling the original
  10796. display-time-filter."
  10797.         (save-excursion
  10798.           (let ((procs (irc-active-servers)))
  10799.             (while procs
  10800.               (let ((buf (buffer-name (process-buffer (car procs)))))
  10801.             (if buf (progn (set-buffer buf) (irc-check-time)))
  10802.             (setq procs (cdr procs))))))
  10803.         (original-display-time-filter proc str)))))))
  10804.  
  10805.  
  10806. (defun irc-who-is-on (&optional list)
  10807.   (if (or (not (boundp 'irc-last-who-is-on))
  10808.       (not (and (listp irc-last-who-is-on)
  10809.             (numberp (nth 0 irc-last-who-is-on))
  10810.             (numberp (nth 1 irc-last-who-is-on)))))
  10811.       (set (make-local-variable 'irc-last-who-is-on) '(0 0)))
  10812.   (let* ((now (irc-current-time))
  10813.      (diff (irc-time-diff now irc-last-who-is-on)))
  10814.     (cond ((or (not (= 0 (nth 0 diff)))
  10815.            (> (nth 1 diff) 60))
  10816.        (setq irc-last-who-is-on (irc-current-time))
  10817.        (let ((str "")
  10818.          (namelist (if (null list)
  10819.                    (irc-recall-all 'irc-notify-looked-for)
  10820.                    list)))
  10821.          (while (not (null namelist))
  10822.            (setq str (concat str " " (car namelist))
  10823.              namelist (cdr namelist)))
  10824.          (irc-send (format "ISON :%s" str)))))))
  10825.  
  10826.  
  10827. (defun irc-change-alias (alias cmd add)
  10828.   "Modify ALIAS for CMD in the irc-alias-alist.  ADD non-nil means to put the
  10829. alias in the list, nil (or the symbol \"remove\") means to clear it.  This
  10830. function does no hand-holding like /ALIAS; its intended use is in
  10831. irc-mode-hook."
  10832.   (let ((entry (assoc (upcase alias) irc-alias-alist)))
  10833.     (if (or (null add) (eq add 'remove))
  10834.         (setq irc-alias-alist (delq entry irc-alias-alist))
  10835.     (if entry (setcdr entry cmd)
  10836.         (setq irc-alias-alist
  10837.           (cons (cons (upcase alias) cmd) irc-alias-alist))))))
  10838.  
  10839.  
  10840. (defun irc-signal (user event)
  10841.   "Return t if a ding should be issued for a USER/EVENT pair.
  10842. Currently only the event part of things is supported by /SIGNAL."
  10843.   (let ((signal (cdr (assoc event irc-signals))))
  10844.     (or (memq t signal)
  10845.     (irc-member-general user signal 'string=)
  10846.         (irc-member-general user
  10847.                 (cdr (assoc 'user irc-signals))
  10848.                 'string=))))
  10849.  
  10850.  
  10851. (defun irc-check-list (list item &optional start-only)
  10852.   "See if LIST has string ITEM.  Returns a list of possible matches.  The list
  10853. returned is based on the following precedence rules:  if there is an exact
  10854. match, it is returned.  If there are any strings in the list whose beginning
  10855. match the item, they are returned.  If that fails and optional argument
  10856. START-ONLY is missing or nil, strings which have the item match anywhere are
  10857. returned.  As a last resort, nil is returned.
  10858. This function is not case-sensitive."
  10859.   (let ((return nil)
  10860.     (case-fold-search t)
  10861.     (item (regexp-quote item)))
  10862.     (if (setq return
  10863.               (delq nil                         ; whole words
  10864.                     (mapcar (function   
  10865.                              (lambda (arg)
  10866.                   (if (string-match (concat "^" item "$") arg)
  10867.                   arg))) list)))
  10868.         return
  10869.     (if (setq return
  10870.           (delq nil                       ; beginnings
  10871.             (mapcar (function
  10872.                  (lambda (arg)
  10873.                   (if (string-match (concat "^" item) arg)
  10874.                       arg))) list)))
  10875.         return
  10876.         (if start-only
  10877.         nil
  10878.         (delq nil
  10879.               (mapcar (function               ; anywhere
  10880.                    (lambda (arg)        
  10881.                 (if (string-match (concat "." item) arg) arg)))
  10882.                   list)))))))
  10883.  
  10884.  
  10885. (defun irc-list-remember (item list)
  10886.   "Add string ITEM to ordered LIST destructivly, returning the new list in
  10887. reversed order. The intended way to call this is like:
  10888.   (setq lst (irc-list-remember \"foo\" lst)).
  10889.  
  10890. This function is case insensitive."
  10891.   (let ((ui (upcase item)))
  10892.     (cond ((null list) (cons item nil))
  10893.       ((string< (upcase (car list)) ui) (cons item list))
  10894.       ((string= (upcase (car list)) ui)
  10895.        (rplaca list item)
  10896.        list)
  10897.       (t (let ((ptr list))
  10898.            (while (and (not (null (cdr ptr)))
  10899.                (string< ui (upcase (car (cdr ptr)))))
  10900.          (setq ptr (cdr ptr)))
  10901.            (cond ((null (cdr ptr)) (rplacd ptr (cons item nil)))
  10902.              ((string= (upcase (car (cdr ptr))) ui)
  10903.               (rplaca (cdr ptr) item))
  10904.              ((string< (upcase (car (cdr ptr))) ui)
  10905.               (rplacd ptr (cons item (cdr ptr))))
  10906.              (t (error
  10907.              (format "NOT possible! item=%s, list=%s, ptr=%s."
  10908.                  item list ptr)))))
  10909.          list))))
  10910.          
  10911.          
  10912. (defun irc-hash-value (str tbl-size)
  10913.   "Return a hash value (index into a hash table) for string ITEM according to
  10914. a table of size SIZE."
  10915.   (let ((h 0)
  10916.     (i 0)
  10917.     (l (min 4 (length str))))
  10918.     (while (< i l)
  10919.       (setq h (% (+ (* h 256) (upcase (aref str i))) tbl-size)
  10920.         i (1+ i)))
  10921.     h))
  10922.  
  10923.  
  10924. (defconst irc-hash-index-size 0
  10925.   "Index of size field in a Kiwi hash table.")
  10926. (defconst irc-hash-index-timestamp 1
  10927.   "Index of timestamp field in a Kiwi hash table.")
  10928. (defconst irc-hash-index-cleanflag 2
  10929.   "Index of cleanstamp in a Kiwi hash table. Either a symbol or a list.")
  10930. (defconst irc-hash-index-bucketarray 3
  10931.   "Index of bucketarray in a Kiwi hash table.")
  10932.  
  10933.  
  10934. (defun irc-create-new-hash-table (size)
  10935.   "Create a empty hash table of size SIZE." 
  10936.   ;; [size write-date cleanflag bucketarray]
  10937.   ;; cleanflag is a list = non-dirty, valid sorted list representation of
  10938.   ;; the hashed data. Else only data to be found is in the hashtable. The hash
  10939.   ;; table is always clean.
  10940.   (let ((htbl (make-vector 4 nil)))
  10941.     (aset htbl irc-hash-index-size size)
  10942.     (aset htbl irc-hash-index-timestamp (irc-internal-time))
  10943.     (aset htbl irc-hash-index-cleanflag 'empty)
  10944.     (aset htbl irc-hash-index-bucketarray (make-vector size nil))
  10945.     htbl))
  10946.  
  10947.  
  10948. (defun irc-nothing-remembered-p (bag)
  10949.   "True if the BAG is empty."
  10950.   (let* ((htbl (symbol-value bag))
  10951.      (flg (aref htbl irc-hash-index-cleanflag)))
  10952.     (cond ((and (symbolp flg) (eq 'empty flg)) flg)
  10953.       (t (let* ((a (aref htbl irc-hash-index-bucketarray))
  10954.             (size (aref htbl irc-hash-index-size))
  10955.             (i size)
  10956.             (empty t))
  10957.            (while (and empty (> i 0))
  10958.          (setq i (1- i)
  10959.                empty (null (aref a i))))
  10960.            (if empty
  10961.            (irc-forget-all bag))
  10962.            empty)))))
  10963.  
  10964.  
  10965. (defun irc-remember (item bag)
  10966.   "Store a string ITEM in the named BAG."
  10967.   (let* ((htbl (symbol-value bag))
  10968.      (a (aref htbl irc-hash-index-bucketarray))
  10969.      (fixed (cond ((eq bag 'irc-servernames)
  10970.                (let ((i (irc-extract-hostname (upcase item))))
  10971.              (cond ((not i) nil)
  10972.                    ((string-match "^ *$" i)
  10973.                 (irc-insert (concat "%%Function irc-remember"
  10974.                             " found a space in"
  10975.                             " a hostname %s).")
  10976.                         item)
  10977.                 (if debug-on-error
  10978.                     (error "SPC in hostname"))
  10979.                 nil)
  10980.                    (t i))))
  10981.               ((or (eq bag 'irc-linksinfo)
  10982.                (eq bag 'irc-namtree)
  10983.                (eq bag 'irc-whotree)
  10984.                (eq bag 'irc-listtree))
  10985.                item)
  10986.               ((or (eq bag 'irc-nicknames)
  10987.                (eq bag 'irc-notify-detected)
  10988.                (eq bag 'irc-notify-looked-for))
  10989.                (cond ((string= "" item)
  10990.                   (irc-insert "%%Skipped \"\" in irc-nicknames.")
  10991.                   nil)
  10992.                  ((= ?@ (aref item 0))
  10993.                   (substring item 1))
  10994.                  ((string-match " " item)
  10995.                   (irc-insert (concat "%%Function irc-remember"
  10996.                           " found a space in a"
  10997.                           " nickname (%s).")
  10998.                       item)
  10999.                   (if debug-on-error
  11000.                   (error "SPC in nickname"))
  11001.                   nil)
  11002.                  ((string-match "\\." item)
  11003.                   (irc-insert (concat "%%Function irc-remember"
  11004.                           " found a dot in a"
  11005.                           " nickname (%s).")
  11006.                       item)
  11007.                   (if debug-on-error
  11008.                   (error "Dot in nickname"))
  11009.                   nil)
  11010.                  (t item)))
  11011.               ((string-match " " item)
  11012.                (irc-insert (concat "%%Function irc-remember"
  11013.                        " found a space in an item"
  11014.                        " (%s).")
  11015.                    item)
  11016.                (if debug-on-error
  11017.                (error "SPC in item"))
  11018.                nil)
  11019.               (t item))))
  11020.     (cond (fixed
  11021.        (let* ((idx (irc-hash-value fixed (aref htbl irc-hash-index-size)))
  11022.           (oldlen (length (aref a idx))))
  11023.          (aset a idx (irc-list-remember fixed (aref a idx)))
  11024.          (cond ((not (= oldlen (length (aref a idx))))
  11025.             (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11026.             (aset htbl irc-hash-index-cleanflag 'dirty)))
  11027.          (if (and (eq bag 'irc-nicknames)
  11028.               (not (irc-recall fixed 'irc-notify-detected))
  11029.               (irc-recall fixed 'irc-notify-looked-for))
  11030.          (irc-who-is-on (irc-recall-all 'irc-notify-looked-for))))))))
  11031.  
  11032.  
  11033. (defun irc-debug-check-all-hashtables ()
  11034.   ""
  11035.   (let ((n (irc-internal-time)))
  11036.     (setq irc-userinfo (format "DEBUGGING CLIENT -- %s." n))
  11037.     (mapcar (function (lambda (p)
  11038.           (irc-debug-check-hashtable (car p) (cdr p) n)))
  11039.         '((irc-nicknames . irc-is-nickname)
  11040.           (irc-ignored-ppl . irc-is-nickname)
  11041.           (irc-linksinfo . nil)
  11042.           (irc-listtree . nil)
  11043.           (irc-notify-looked-for . irc-is-nickname)
  11044.           (irc-notify-detected . irc-is-nickname)
  11045.           (irc-namtree . nil)
  11046.           (irc-servernames . irc-is-hostname)
  11047.           (irc-subscribed-channels . irc-is-channelname)
  11048.           (irc-services . irc-is-nickname)
  11049.           (irc-whotree . nil)))))
  11050.  
  11051.  
  11052. (defun irc-debug-check-hashtable (bag chkfcn &optional mark)
  11053.   ""
  11054.   (let* ((data (irc-recall-all bag))
  11055.      (lst data)
  11056.      (id (if (null mark) "" mark))
  11057.      (consistent t)
  11058.      (doublettes nil))
  11059.     (sit-for 0)
  11060.     (irc-insert "DEBUG: %s checking if hashtable %s is consistent using %s."
  11061.         id bag chkfcn)
  11062.     (irc-insert "DEBUG: %s = %s." bag data)
  11063.     (while (not (null lst))
  11064.       (let* ((matches (irc-check-list data (car lst)))
  11065.          (l (length matches)))
  11066.     (cond ((= 1 l) (irc-insert "DEBUG: %s  OK, \"%s\" found once."
  11067.                    id (car lst)))
  11068.           ((= 0 l)
  11069.            (irc-insert "DEBUG: %s Huh? \"%s\" not found."
  11070.                id (car lst))
  11071.            (setq doublettes t))
  11072.           (t (irc-insert "DEBUG: %s ERROR \"%s\" FOUND %d TIMES."
  11073.                  id (car lst) l)
  11074.          (setq doublettes t)))
  11075.     (setq lst (cdr lst))))
  11076.     (irc-insert "DEBUG: %s checked for doublettes, done." id)
  11077.     (sit-for 0)
  11078.     (if (not (null chkfcn))
  11079.     (let ((lst data))
  11080.       (while (not (null lst))
  11081.         (cond ((funcall chkfcn (car lst))
  11082.            (irc-insert "DEBUG: %s item \"%s\" of %s -- OK."
  11083.                    id (car lst) bag))
  11084.           (t (irc-insert "DEBUG: %s item \"%s\" of %s FAILED CHECK."
  11085.                  id (car lst) bag)
  11086.              (setq consistent nil)))
  11087.         (setq lst (cdr lst)))))
  11088.     (irc-insert "DEBUG: %s done checking: doublettes %s, consistent %s"
  11089.         id (if doublettes "FAILED" "OK") (if consistent "OK" "FAILED"))
  11090.     (irc-insert "DEBUG: %s --------------" id)
  11091.     (sit-for 0)))
  11092.  
  11093.  
  11094. (defun irc-list-recall (item list)
  11095.   "Check if a string ITEM is in the LIST. The comparsion is not case
  11096. sensitive. If the item is found, return the stored spelling, else nil."
  11097.   (let ((ui (upcase item)))
  11098.     (while (and (not (null list))
  11099.         (string< ui (upcase (car list))))
  11100.       (setq list (cdr list)))
  11101.     (if (and (not (null list)) (string= (upcase (car list)) ui))
  11102.     (car list)
  11103.     nil)))
  11104.  
  11105.  
  11106. (defun irc-recall (item bag)
  11107.   "Check if a string ITEM is in the BAG. If so, return the stored spelling,
  11108. else ni. All checking is done without being case sensitive."
  11109.   (let* ((htbl (symbol-value bag))
  11110.      (idx (irc-hash-value item (aref htbl irc-hash-index-size))))
  11111.     (irc-list-recall item (aref (aref htbl irc-hash-index-bucketarray)
  11112.         (irc-hash-value item (aref htbl irc-hash-index-size))))))
  11113.  
  11114.  
  11115. (defun irc-recall-all (bag)
  11116.   "Return a sorted list representation of all strings in the BAG."
  11117.   ;; [size write-date cleanflag bucketarray]
  11118.   (let* ((htbl (symbol-value bag))
  11119.      (cached-data (aref htbl irc-hash-index-cleanflag))
  11120.      (is-clean (listp cached-data))
  11121.      (buckets (aref htbl irc-hash-index-bucketarray))
  11122.      (size (aref htbl irc-hash-index-size)))
  11123.     (cond ((not (= size (length buckets)))
  11124.        (irc-insert "%%Bad hash list %s, size != length bucketarray." bag)))
  11125.     (cond (is-clean cached-data)
  11126.       (t (let ((r nil)
  11127.            (i size)
  11128.            (a nil))
  11129.            (while (> i 0)
  11130.          (setq i (1- i)
  11131.                a (aref buckets i))
  11132.          (while (not (null a))
  11133.            (setq r (cons (car a) r)
  11134.              a (cdr a))))
  11135.            (let ((s (sort r '(lambda (a b)
  11136.                   (string< (upcase a) (upcase b))))))
  11137.          (aset htbl irc-hash-index-cleanflag s)
  11138.          s))))))
  11139.  
  11140.  
  11141. (defun irc-recall-all-and-display (bag ind &optional plur sing)
  11142.   "Enter the nodes in the BAG as seperate lines in the irc buffer. Entries
  11143. longer than 1 line are continued with an indentation of IND, a number.
  11144.  
  11145. If you supply the optional arguments PLUR and SING, then after the lines
  11146. a short message of the form \"[%d %s]\" is printed. If only PLUR is supplied,
  11147. it is always used. If both PLUS and SING is supplied, then SING is used if
  11148. exactly one line was printed, else PLUR is used."
  11149.   (let ((lst (irc-recall-all bag))
  11150.     (n 0)
  11151.     (irc-msg-cont-used (make-string ind ? )))
  11152.     (while lst
  11153.       (irc-insert "%s" (car lst))
  11154.       (setq n (1+ n)
  11155.         lst (cdr lst)))
  11156.     (if (stringp plur)
  11157.     (if (zerop n)            ;List empty?
  11158.         (if (irc-terminal-is-slow) ;When on a slow terminal, no list
  11159.         (irc-insert "%%No %s." plur) ; is kept.
  11160.         (irc-insert "%sEnd of (unsorted) %s list%s"
  11161.                 irc-msg-info-pre
  11162.                 plur
  11163.                 irc-msg-info-post))
  11164.         (irc-insert "%s%d %s%s"
  11165.             irc-msg-info-pre
  11166.             n
  11167.             (if (= n 1)
  11168.                 (if (stringp sing) sing plur)
  11169.                 plur)
  11170.             irc-msg-info-post))
  11171.     (irc-insert "%sEnd of (unsorted) list%s"
  11172.             irc-msg-info-pre
  11173.             irc-msg-info-post)))
  11174.   (irc-insert ""))
  11175.  
  11176.  
  11177. (defun irc-list-forget (item list)
  11178.   "Remove a string ITEM from a LIST of string, if it's found. The comparsions
  11179. are not case sensitive."
  11180.   (let ((ui (upcase item)))
  11181.     (cond ((null list) list)
  11182.       ((string< (upcase (car list)) ui) list)
  11183.       ((string= (upcase (car list)) ui) (cdr list))
  11184.       (t (let ((ptr list))
  11185.            (while (and (not (null (cdr ptr)))
  11186.                (string< ui (upcase (car (cdr ptr)))))
  11187.          (setq ptr (cdr ptr)))
  11188.            (cond ((null (cdr ptr)) nil)
  11189.              ((string< (upcase (car (cdr ptr))) ui) nil)
  11190.              ((string= (upcase (car (cdr ptr))) ui)
  11191.               (rplacd ptr (cdr (cdr ptr))))
  11192.              (t (error (concat  "irc-list-forget: NOT possible!"
  11193.                     " item=%s, list=%s, ptr=%s.")
  11194.                    item list ptr))))
  11195.          list))))
  11196.  
  11197.  
  11198. (defun irc-forget (item bag)
  11199.   "Remove a string ITEM from the BAG, if the item was there. Not case
  11200. sensitive."
  11201.   (let* ((htbl (symbol-value bag))
  11202.      (idx (irc-hash-value item (aref htbl irc-hash-index-size)))
  11203.      (a (aref htbl irc-hash-index-bucketarray))
  11204.      (oldlen (length (aref a idx))))
  11205.     (aset a idx (irc-list-forget item (aref a idx)))
  11206.     (if (and (eq bag 'irc-nicknames)
  11207.          (irc-recall item 'irc-notify-detected)
  11208.          (irc-recall item 'irc-notify-looked-for))
  11209.     (irc-who-is-on (irc-recall-all 'irc-notify-looked-for)))
  11210.     (cond ((not (= oldlen (length (aref a idx))))
  11211.        (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11212.        (aset htbl irc-hash-index-cleanflag 'dirty)))))
  11213.  
  11214.  
  11215. (defun irc-forget-all (bag)
  11216.   "Empty BAG."
  11217.   (let* ((htbl (symbol-value bag))
  11218.      (size (aref htbl irc-hash-index-size))
  11219.      (a (aref htbl irc-hash-index-bucketarray))
  11220.      (i 0))
  11221.     (while (< i size)
  11222.       (aset a i nil)
  11223.       (setq i (1+ i)))
  11224.     (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11225.     (aset htbl irc-hash-index-cleanflag 'empty)))
  11226.  
  11227.  
  11228. (defun irc-get-names-and-servers ()
  11229.   "Return a alphabetically sorted list of all the nick- and servernames which
  11230. are known by the client."
  11231.   (if (not (boundp 'irc-cache-n+s))
  11232.       (set (make-local-variable 'irc-cache-n+s) nil))
  11233.   (if (or (null irc-cache-n+s)        ;No data yet?
  11234.       (< (car irc-cache-n+s)    ;Nicknames updated?
  11235.          (aref irc-nicknames irc-hash-index-timestamp))
  11236.       (< (car irc-cache-n+s)    ;Servernames updated?
  11237.          (aref irc-servernames irc-hash-index-timestamp)))
  11238.       (let* ((servers (irc-recall-all 'irc-servernames))
  11239.          (names (irc-recall-all 'irc-nicknames))
  11240.          (data nil))
  11241.     (while (not (null servers))
  11242.       (setq data (cons (car servers) data)
  11243.         servers (cdr servers)))
  11244.     (while (not (null names))
  11245.       (setq data (cons (car names) data)
  11246.         names (cdr names)))
  11247.     (let ((s (sort data '(lambda (a b) (string< (upcase a) (upcase b))))))
  11248.       (setq irc-cache-n+s (cons (irc-internal-time) s)))))
  11249.   (cdr irc-cache-n+s))
  11250.  
  11251.  
  11252. (defun irc-get-channels-and-nicks-and-servers ()
  11253.   "Return a alphabetically sorted list of all the channel-, nick- and server-
  11254. names which are known by the client."
  11255.   (if (not (boundp 'irc-cache-c+n+s))
  11256.       (set (make-local-variable 'irc-cache-c+n+s) nil))
  11257.   (if (or (null irc-cache-c+n+s)
  11258.       (< (car irc-cache-c+n+s)
  11259.          (aref irc-subscribed-channels irc-hash-index-timestamp))
  11260.       (< (car irc-cache-c+n+s)
  11261.          (aref irc-nicknames irc-hash-index-timestamp))
  11262.       (< (car irc-cache-c+n+s)
  11263.          (aref irc-servernames irc-hash-index-timestamp)))
  11264.       (let* ((channels (irc-recall-all 'irc-subscribed-channels))
  11265.          (nicks (irc-recall-all 'irc-nicknames))
  11266.          (servers (irc-recall-all 'irc-servernames))
  11267.          (data nil))
  11268.     (while (not (null channels))
  11269.       (setq data (cons (car channels) data)
  11270.         channels (cdr channels)))
  11271.     (while (not (null nicks))
  11272.       (setq data (cons (car nicks) data)
  11273.         nicks (cdr nicks)))
  11274.     (while (not (null servers))
  11275.       (setq data (cons (car servers) data)
  11276.         servers (cdr servers)))
  11277.     (let ((s (sort data '(lambda (a b) (string< (upcase a) (upcase b))))))
  11278.       (setq irc-cache-c+n+s (cons (irc-internal-time) s)))))
  11279.   (cdr irc-cache-c+n+s))
  11280.  
  11281.  
  11282. (defun irc-sec-to-time (n)
  11283.   "Convert number of SECONDS into a time string of one of the following
  11284. formats \"SS seconds\" or \"MM minutes and SS seconds\"
  11285. or \"HH hours, MM minutes and SS seconds\"
  11286. or \"DD days, HH hourse, MM minutes and SS seconds\"."
  11287.   (let* ((one-minute 60)
  11288.      (one-hour (* 60 one-minute))
  11289.      (one-day (* 24 one-hour))
  11290.      (days (/ n one-day))
  11291.      (day-string (cond ((= 0 days) "")
  11292.                ((= 1 days) "1 day")
  11293.                (t (format "%d days" days))))
  11294.      (m (% n one-day))
  11295.      (hours (/ m one-hour))
  11296.      (hour-string (cond ((= 0 hours) "")
  11297.                 ((= 1 hours) "1 hour")
  11298.                 (t (format "%d hours" hours))))
  11299.      (l (% m one-hour))
  11300.      (minutes (/ l one-minute))
  11301.      (min-string (cond ((= 0 minutes) "")
  11302.                ((= 1 minutes) "1 minute")
  11303.                (t (format "%d minutes" minutes))))
  11304.      (seconds (% l one-minute))
  11305.      (sec-string (cond ((= 0 seconds) "")
  11306.                ((= 1 seconds) "1 second")
  11307.                (t (format "%d seconds" seconds)))))
  11308.     ;; Possible combinations:
  11309.     ;; D H M S
  11310.     ;; 0 0 0 0 = none
  11311.     ;; 0 0 0 1 = S
  11312.     ;; 0 0 1 0 = M
  11313.     ;; 0 0 1 1 = MS
  11314.     ;; 0 1 0 0 = H
  11315.     ;; 0 1 0 1 = HS
  11316.     ;; 0 1 1 0 = HM
  11317.     ;; 0 1 1 1 = HMS
  11318.     ;; 1 0 0 0 = D
  11319.     ;; 1 0 0 1 = DS
  11320.     ;; 1 0 1 0 = DM
  11321.     (let ((acc nil))
  11322.       (if (not (string= "" sec-string)) (setq acc (cons sec-string acc)))
  11323.       (if (not (string= "" min-string)) (setq acc (cons min-string acc)))
  11324.       (if (not (string= "" hour-string)) (setq acc (cons hour-string acc)))
  11325.       (if (not (string= "" day-string)) (setq acc (cons day-string acc)))
  11326.       (cond ((= 0 (length acc)) "0 seconds")
  11327.         ((= 1 (length acc)) (car acc))
  11328.         ((= 2 (length acc)) (format "%s and %s" (nth 0 acc) (nth 1 acc)))
  11329.         ((= 3 (length acc))
  11330.          (format "%s, %s and %s" (nth 0 acc) (nth 1 acc) (nth 2 acc)))
  11331.         (t (format "%s, %s, %s and %s"
  11332.                (nth 0 acc) (nth 1 acc) (nth 2 acc) (nth 3 acc)))))))
  11333.  
  11334.  
  11335. (defun irc-burst-comma (str)
  11336.   "Take a comma or space separated STR and turn it into a list of its elements.
  11337. Example: \"1, 2,3,4,  6  7\" becomes the list
  11338. (\"7\" \"6\" \"4\" \"3\" \"2\" \"1\")."
  11339.   (let (list sub (beg 0))
  11340.     (string-match "" str)
  11341.     (while (string-match ",+\\| +\\|,+ +" str beg)
  11342.       (if (not (string= (setq sub (substring str beg (match-beginning 0))) ""))
  11343.           (setq list (cons sub list)))
  11344.       (setq beg (match-end 0)))
  11345.     (if (/= (length str) beg) (cons (substring str beg) list) list)))
  11346.  
  11347.  
  11348.  
  11349. ;; miscellaneous other commands (usually from other sources)
  11350.  
  11351. ;; this makes up for not being able to provide a :test to memq.
  11352. ;; irc-member-general by Bard Bloom <bard@theory.lcs.mit.com>
  11353. (defun irc-member-general (x l comparison)
  11354.   "Is X a member of L under COMPARISON?"
  11355.   (let ((not-found t))
  11356.     (while (and l not-found)
  11357.       (setq not-found (not (funcall comparison x (car l)))
  11358.             l         (cdr-safe l)))
  11359.     (not not-found)))
  11360.  
  11361.  
  11362. ;; wish i could remember who I got this from; I had to patch it to work
  11363. ;; with the minibuffer correctly but it is mostly untouched.
  11364. (defun irc-walk-windows (proc &optional no-mini)
  11365.   "Applies PROC to each visible window (after selecting it, for convenience).
  11366. Optional arg NO-MINI non-nil means don't apply PROC to the minibuffer
  11367. even if it is active."
  11368.   (let* ((real-start (selected-window))
  11369.      (start (next-window real-start no-mini))
  11370.      (current start) done)
  11371.     (while (not done)
  11372.       (select-window current)
  11373.       (funcall proc)
  11374.       (setq current (next-window current no-mini))
  11375.       (setq done (eq current start)))
  11376.     (select-window real-start)))
  11377.  
  11378.  
  11379. (defun irc-count-windows (&optional no-mini)
  11380.   "Returns the number of visible windows.
  11381. Optional arg NO-MINI non-nil means don't count the minibuffer
  11382. even if it is active."
  11383.   (let ((count 0))
  11384.     (irc-walk-windows (function (lambda () (setq count (1+ count)))) no-mini)
  11385.     count))
  11386.  
  11387.  
  11388. ;; swiped from minibuf.el, but made exclusive to * Minibuf-n*.
  11389. (defun irc-minibuffer-message (format &rest args)
  11390.   "Print a temporary message at the end of the Minibuffer.
  11391. After 2 seconds or when a key is typed, erase it."
  11392.   (if (zerop (minibuffer-depth)) (apply 'message format args)
  11393.       (let (p)
  11394.     (save-excursion
  11395.       (set-buffer (concat " *Minibuf-" (1- (minibuffer-depth)) "*"))
  11396.       (unwind-protect
  11397.            (progn
  11398.          (setq p (goto-char (point-max)))
  11399.          (insert (apply 'format format args))
  11400.          (sit-for 2))
  11401.         (delete-region p (point-max)))))))
  11402.  
  11403.  
  11404. (defun irc-find-to (str &optional explicit)
  11405.   "Find the part of STRING that IRC-mode will interpret as the sendlist.
  11406. If no explicit list is found, irc-default-to is returned.  The string returned
  11407. is either : or ; terminated.
  11408.  
  11409. If optional EXPLICIT is non-nil, then return t if a sendlist was explicitly
  11410. specified, nil if the sendlist was implicit."
  11411.   (let* ((part (if (string-match "^ *\\([^;:]*\\) *\\([:;]\\)" str)
  11412.            (subfield str 1)
  11413.            nil))
  11414.      (retval (if (not part)
  11415.              ""
  11416.              (concat part (subfield str 2))))
  11417.      (matched (and part
  11418.                (or (string= "" part)
  11419.                (let ((s part))
  11420.                  (while (string-match (concat "^ *\\([^ ,]+\\)"
  11421.                               " *, *")
  11422.                           s)
  11423.                    (let ((b1 (match-beginning 1))
  11424.                      (e0 (match-end 0))
  11425.                      (e1 (match-end 1)))
  11426.                  (if (irc-is-receiver (substring s b1 e1))
  11427.                      (setq s (substring s e0))
  11428.                      (setq s ":"))))
  11429.                  (irc-is-receiver s))))))
  11430.     (if explicit matched (if matched retval irc-default-to))))
  11431.  
  11432.  
  11433. (defun irc-find-message (string)
  11434.   "Find the message that IRC will see if STR were sent.  For messages
  11435. sent with explicit lists, this is everything following the colon or
  11436. semi-colon.  For everything else, it is just the string."
  11437.   (substring string (length (irc-find-to string))))
  11438.  
  11439.  
  11440.  
  11441. ;; functions for the irc-history list
  11442. (defun irc-add-to-hist (str)
  11443.   "Put STRING at the head of the irc-history list."
  11444.   (if (string-match "^[;:]" str)
  11445.       (setq str
  11446.             (concat irc-last-explicit (substring str 1 (length str)))))
  11447.   (setq irc-history (append (list str) irc-history))
  11448.   (and (> (length irc-history) irc-max-history)
  11449.        (setq irc-history (reverse (cdr (reverse irc-history))))))
  11450.  
  11451.  
  11452. (defun irc-yank-prev-command ()
  11453.   "Put the last IRC /command in the input-region."
  11454.   (interactive)
  11455.   (delete-region irc-mark (goto-char (point-max)))
  11456.   (insert "/" irc-last-command)
  11457.   (goto-char (1+ irc-mark)))
  11458.  
  11459.  
  11460. (defun irc-history-prev (arg)
  11461.   "Select the previous message in the IRC history list.  ARG means
  11462. select that message out of the list (0 is the first)."
  11463.   (interactive "P")
  11464.   (let ((str (nth (or arg (1+ (or irc-history-index 0))) irc-history)))
  11465.     (if (not str)
  11466.         (message "No message %d in history." (or arg (1+ irc-history-index)))
  11467.     (delete-region irc-mark (goto-char (point-max)))
  11468.     (insert str)
  11469.     (goto-char irc-mark)
  11470.     (setq irc-history-index (or arg (1+ irc-history-index))))))
  11471.  
  11472.  
  11473. (defun irc-history-next (arg)
  11474.   "Select the next message in the IRC history list.  With prefix ARG
  11475. select that message out of the list (same as irc-history-prev if
  11476. called with a prefix arg)."
  11477.   (interactive "P")
  11478.   (if arg (irc-history-prev arg)
  11479.       (if (= irc-history-index -1)
  11480.       (message "No next message in history.")
  11481.       (delete-region irc-mark (goto-char (point-max)))
  11482.       (insert (if (zerop irc-history-index) ""
  11483.               (nth (1- irc-history-index) irc-history)))
  11484.       (setq irc-history-index (1- irc-history-index)))))
  11485.  
  11486.  
  11487. (defun irc-kill-input ()
  11488.   "Delete the input region and start out fresh.  This function is recommended
  11489. over any other way of killing the input-region interactively because it
  11490. also resets the index for the history list."
  11491.   (interactive)
  11492.   (delete-region irc-mark (goto-char (point-max)))
  11493.   (setq irc-history-index -1))
  11494.  
  11495.  
  11496. (defun irc-complete-name ()
  11497.   "Not completed yet."
  11498.   (interactive)
  11499.   (let* ((end (point))
  11500.      (beg (save-excursion
  11501.         (while
  11502.             (and (not (= (point) (point-min)))
  11503.              (irc-is-receiver (buffer-substring (1- (point)) end)))
  11504.           (backward-char 1))
  11505.         (point)))
  11506.      (pattern (downcase (buffer-substring beg end)))
  11507.      (alist (mapcar (function (lambda (s)
  11508.               (list (downcase s))))
  11509.             (irc-get-names-and-servers)))
  11510.      (completion (try-completion pattern alist)))
  11511.     (cond ((eq completion t))        ;Exact match.
  11512.       ((null completion)        ;No match at all.
  11513.        (ding)
  11514.        (message "Can't find completion for \"%s\"" pattern))
  11515.       ((not (string= pattern completion)) ;Complete (but maybe not unique).
  11516.        (delete-region beg end)
  11517.        (insert completion)) 
  11518.       (t (let* ((name (irc-nuke-whitespace
  11519.                (completing-read "Who? "
  11520.                         alist
  11521.                         nil
  11522.                         nil
  11523.                         pattern))))
  11524.            (delete-region beg end)
  11525.            (insert name))))))
  11526.  
  11527.  
  11528. (defun irc-line-count (buf)
  11529.   "Returns the size of the buffer BUF."
  11530.   (save-excursion (set-buffer buf)
  11531.           (goto-line 1)
  11532.           (count-lines (point-min) (1+ (buffer-size)))))
  11533.  
  11534.  
  11535. (defun irc-log-in-debug-buffer (line)
  11536.   "Append a LINE to the debug buffer associated with a session, appending a
  11537. newline to the line. If the debug buffer doesn't exist, do nothing."
  11538.   (let ((debug-buffer (concat (buffer-name (current-buffer))
  11539.                   "-*debug*")))
  11540.     (if (get-buffer debug-buffer)
  11541.     (irc-append-string-to-buffer line (get-buffer debug-buffer)))))
  11542.  
  11543.  
  11544. (defun irc-append-string-to-buffer (str buf)
  11545.   "Append the string STR to the buffer BUF as a line."
  11546.   (save-excursion (set-buffer buf)
  11547.           (goto-char (1+ (buffer-size)))
  11548.           (insert str "\n")))
  11549.  
  11550.  
  11551. (defun irc-get-buffers-nth-line (n buf)
  11552.   "Returns the line number N in the buffer BUF as a string.
  11553. The first line inb the buffer is line number 1.
  11554. If the buffer is empty, returns \"\"."
  11555.   (if (>= (irc-line-count buf) n)
  11556.       (save-excursion (set-buffer buf)
  11557.               (goto-line n)
  11558.               (let ((p (point)))
  11559.             (search-forward "\n" (1+ (buffer-size)) 'non-nil-non-t)
  11560.             (buffer-substring p (1- (point)))))
  11561.     ""))
  11562.  
  11563.  
  11564. (defun irc-sort-lines-in-buffer (buf &optional reverse)
  11565.   "Sort the lines in buffer BUF.
  11566. An optional argument REVERSE can be supplied as non-nil to sort the buffer
  11567. in reversed order."
  11568.   (save-excursion (set-buffer buf)
  11569.           (sort-lines reverse (point-min) (1+ (buffer-size)))))
  11570.  
  11571.  
  11572. (defun irc-history-menu ()
  11573.   "List the history of messages kept by irc-mode in another buffer."
  11574.   (interactive)
  11575.   (let ((pop-up-windows t) (hist irc-history) (line 0))
  11576.     (save-excursion
  11577.       (set-buffer (get-buffer-create "*IRC History*"))
  11578.       (fundamental-mode)
  11579.       (erase-buffer)
  11580.       (while hist
  11581.         (insert (format "%2d: %s\n" line (car hist)))
  11582.         (setq hist (cdr hist))
  11583.         (setq line (1+ line)))
  11584.       (if (zerop line)
  11585.           (insert "No messages have been sent to IRC yet."))
  11586.       (set-buffer-modified-p nil)
  11587.       (goto-char (point-min)))
  11588.     (display-buffer "*IRC History*")))
  11589.  
  11590.  
  11591.  
  11592. ;; stuff about irc-mode
  11593. (defun irc-version (&optional arg)
  11594.   "Print the current version of irc.el in the minibuffer.  With optional
  11595. ARG, insert it in the current buffer."
  11596.   (interactive "P")
  11597.   (if arg
  11598.       (insert irc-version)
  11599.       (princ irc-version)))
  11600.  
  11601.  
  11602. (defun irc-fatal (msg item)
  11603.   (irc-insert "FATAL ERROR: \"%s\" \"%s\"." msg item))
  11604.  
  11605.  
  11606. ;;; Force GC to prevent GC bug in older (pre 18.57) GNU Emacs'es.
  11607. (garbage-collect)
  11608.  
  11609. (defun irc-execute-news (dummy)
  11610.   "Shows news about latest changes to this GNU Emacs client.
  11611. Even shows news about old changes -- what a wonderous function indeed.
  11612.  
  11613. Latest changes to IRC mode, oldest at bottom, newest at top:
  11614.  
  11615. *** NEEDS TO BE UPDATED ***"
  11616.   (interactive '(""))
  11617.   (save-excursion
  11618.     (set-buffer (get-buffer-create "*IRC-mode News*"))
  11619.     (erase-buffer)
  11620.     (insert (documentation 'irc-execute-news))
  11621.     (goto-char (point-min)))
  11622.   (display-buffer "*IRC-mode News*"))
  11623.  
  11624.  
  11625. (defun irc-report-bug (client-message server-message type)
  11626.   ""
  11627.   (irc-insert "%%%s" client-message)
  11628.   (irc-insert "%% \"%s\" (%s)." server-message type)
  11629.   (irc-insert "%% Please tell %s, it might be a bug." irc-hacker)
  11630.   (irc-insert "%% (Client \"%s\", server %s version %d.%d)."
  11631.           irc-version irc-major-version irc-minor-version))
  11632.  
  11633.  
  11634. ;; We're done defining an irc mode, so let's provide it.
  11635. (provide 'irc)
  11636.