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.38.el < prev    next >
Text File  |  1996-11-11  |  429KB  |  11,668 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.38 for GNU Emacs" "Current Kiwi version.")
  5. (defconst irc-ftp-version "4.38" "Current FTP'able version.")
  6. (defconst irc-ftp-file-names (list (format "Kiwi.%s.el" irc-ftp-version)
  7.                    (format "Kiwi.%s.elc" irc-ftp-version)
  8.                    "Kiwi.README"))
  9. (defconst irc-ftp-source (list (list "FTP.Update.UU.SE" "pub/irc"
  10.                      irc-ftp-file-names)
  11.                    (list "FTP.FUNet.FI" "pub/unix/irc/Emacs"
  12.                      irc-ftp-file-names)))
  13. (defconst irc-hacker "Klaus.Zeuge@Student.DoCS.UU.SE"
  14.   "Email address of the person to send complaints and ideas too.")
  15. ;;;;;;;;;
  16. ;; v4.38 Tue Nov 12 00:49:51 1996    sojge@Student.DoCS.UU.SE
  17. ;;    - Add w3.el support, bind url loader to RET in read area
  18. ;;    - Understand UNDERNET PING xxx arguments
  19. ;;    - Display CTCP SOURCE replies URL stylish
  20. ;;    - Added RPL 437 (channel/nick temporary unavailable)
  21. ;; v4.37 Sun Sep  8 21:33:43 1996    sojge@Student.DoCS.UU.SE
  22. ;;    - Changed FTP sites.
  23. ;; v4.36 Fri Sep  6 19:21:56 1996    sojge@Student.DoCS.UU.SE
  24. ;;    - Message 325 (channel creation time), 338 (login time for a
  25. ;;      user) and 339 (time when the topic of a channel was set)
  26. ;; v4.35 Mon Aug 26 00:07:03 1996    sojge@Student.DoCS.UU.SE
  27. ;;    - Better Undernet handling in various places.
  28. ;;    - BUGFIX: make it harder to issue /WHO command w/o arument.
  29. ;;    - New value for irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1.
  30. ;; v4.34 Fri Feb  9 19:38:02 1996    sojge@Student.DoCS.UU.SE
  31. ;;    - Use last-command-char instead of last-input-char.
  32. ;;    - Obsoleted irc-explain-who-mode, moved to code to 352 handler.
  33. ;;    - Added undernet message 329, 333.
  34. ;;    - If emacs-version > 18, assume irc-emacs-knows-ISO8859-1 to t.
  35. ;;    - Added RPL262.
  36. ;;    - Made irc-startup-hook non-depended on LUSERS commands, moved it to
  37. ;;      CLIENT-SYNCH like mechanism (CLIENT-START)
  38. ;;      - Added 250 highest connect count.
  39. ;;    - Added a "whois x x" in irc-execute-info.
  40. ;;    - Added ignore stuff in notify detector, RPL303.
  41. ;;    - Added 409 no origin spec'ed (from /quo ping).
  42. ;;    - Reply 442 keeps changing, more kludging added.
  43. ;;    - BUGFIX, now understands 002 message "ircd2.8/dog3-super.pl7"
  44. ;; v4.33 Tue Dec 13 18:59:10 1994    sojge@Student.DoCS.UU.SE
  45. ;;    - Added new variable irc-scroll-step.
  46. ;;    - Added better knoweldge of &channels.
  47. ;;    - Show own nickname in ping replies on screen from others.
  48. ;;    - Cleaned up server informatio in /LINKS reply.
  49. ;;    - Better regexp when parsing 203:205 messages.
  50. ;;    - Put \< and \> around nick regexp for backtalk.
  51. ;;    - IRC-servers now understands command "TOPIC #C"
  52. ;;    - BUGFIX: 2.8.20 has a new 204 format with funky timer.
  53. ;; v4.32 Mon Aug  8 02:53:16 1994    sojge@Student.DoCS.UU.SE
  54. ;;    - BUGFIX: server 2.8.20 has new 317 message.
  55. ;;    - Added status line counter irc-reply-count for /who, /names, /links.
  56. ;;    - Added new /signal detect for /notify detect/lost sight messages.
  57. ;;    - Added new variable irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1
  58. ;;      to be used if one wants irc-self-insert to map certain keystrokes.
  59. ;;    - Changed irc-self-insert to be able to map from ISO 646-SE2 to
  60. ;;      ISO 8859-1.
  61. ;;    - Fixed typo in docstring of irc-time-diff.
  62. ;;    - Use irc-userhost in irc-parse-channel.
  63. ;; v4.31 Tue Oct 19 20:59:11 1993    sojge@Student.DoCS.UU.SE
  64. ;;    - BUGFIX: don't crash if CTCP quote is last in string.
  65. ;;    - BUGFIX: name buffer accoring to connected TCP-port, not default
  66. ;;      TCP-port.
  67. ;;    - Better handling of channel topic display.
  68. ;;    - Added handling of ERR 422 and 443, and RPL 249.
  69. ;;    - Clean up CTCP VERSION reply before displaying it.
  70. ;; v4.30 Tue Aug 24 20:52:21 1993    sojge@Student.DoCS.UU.SE
  71. ;;    - BUG FIX: erroneous format string fixed when handling CTCP ECHO reply.
  72. ;;    - Bug fix in irc-execute-notify, don't try to irc-forget a non nick.
  73. ;;    - Added backtalk to documentation of /signal.
  74. ;;    - Made variable irc-port (ie the TCP port used to connect to an IRC
  75. ;;      server) buffer local so different sessions can use diffferent ports.
  76. ;;    - Added handling of RPL 392.
  77. ;;    - Better handling of RPL 322.
  78. ;;    - Now cleans up QUIT messages.
  79. ;;    - Added handling ERR 422, no MOTD file.
  80. ;;    - Minor betterification in character mapping.
  81. ;; v4.29 Thu Aug 12 03:24:57 1993    sojge@Student.DoCS.UU.SE
  82. ;;    - If DEL pressed while point is at first postion in input region,
  83. ;;      scroll down page instead of beep.
  84. ;;    - More channel modes explained in irc-explain-mode (k and v).
  85. ;;    - Force emacs to offer to save the Kiwi buffer before exiting emacs.
  86. ;;    - Splitted up irc-parse-RPL so it's byte-compile'able with v18 emacs.
  87. ;;    - Remove the CTCP MOOD command as no one else used it.
  88. ;;    - As there are a lot of old clients out there, send several CTCP pings.
  89. ;;    - Unless debug-on-error is non-nil, don't crash when finding dots in
  90. ;;      host names, nicks etc.
  91. ;;    - New function irc-time-diff used to not send ISON commands more often
  92. ;;      than every 60 second.
  93. ;;    - New handling of topic, see /HELP TOPIC.
  94. ;;    - Don't care what user tries to /VERSION, let server decide if it
  95. ;;      makes sense.
  96. ;;    - Added handling of RPL 305, 306, 371, 374, 392, 394.
  97. ;;    - Added handling of RPL 242, 243, 244, 253, 261.
  98. ;;    - New format in TRACE output in RPL 200, 211.
  99. ;;    - Better parsing of "hello this is ircd version xxx" string at startup.
  100. ;;    - Added handling of ERR 436, 444, 445, 446, 467, 475.
  101. ;;    - Some minor changes in the CTCP handling. Nothing important.
  102. ;;    - make-local-variable doesn't set the variable in emacs v19, so needed
  103. ;;      to add a set in several places. NOW RUNS WITH GNU EMACS VERSION 19.
  104. ;;    - Fumbled around some more with character set convertings. Should go
  105. ;;      the v19 way, in the future.
  106. ;; v4.28 Mon Apr 19 15:48:45 1993    sojge@Student.DoCS.UU.SE
  107. ;;    - Made client somewhat compliant to ircd 2.8.
  108. ;;    - Added some (as of yet incomplete) support for different character
  109. ;;      sets like ISO 8859-1 and SIS E47.
  110. ;;    - Changed output of /WHO
  111. ;;    - Bugfixed irc-lowlevel-dequote to not crash when getting erroneous
  112. ;;      messages breaking the CNTRL/P quoting.
  113. ;;    - Bugfixed irc-execute-event.
  114. ;;    - Added CTCP MOOD. No /MOOD command yet, though.
  115. ;;    - Clean up a users full name in WHO replies.
  116. ;; v4.27 Mon Sep 14 19:17:23 1992    sojge@Student.DoCS.UU.SE
  117. ;;    - Better handling of versions through irc-ftp-* variables.
  118. ;;    - Added variable irc-show-japanese-characters to get better control
  119. ;;      about in what way japanese characters are inserted into buffer.
  120. ;;    - Spiffed up CTCP VERSION handling to comply to CTCP.mem v13.
  121. ;;    - Added flag irc-drop-ircII-text-kludge-control-characters for those
  122. ;;      users who WANT to see ^B, ^V and ^_ in text.
  123. ;;    - Ignore CNTRL/B, CNTRL/V and CNTRL/_ in incoming messages, as those
  124. ;;      are used by the ircII client to toggle reverse, underline and bold
  125. ;;      attributes of text.
  126. ;;    - Added variable irc-emacs-knows-ISO8859-1.
  127. ;;    - Fixed timing problem when receiving a PRIVMSG just after changing
  128. ;;      the nickname of oneself.
  129. ;; v4.26 Thu Aug 20 05:17:00 1992    sojge@Student.DoCS.UU.SE
  130. ;;    - Assorted small fixes.
  131. ;;    - Some new table headers (like for WHO).
  132. ;;    - Added RPL369, end of WHOWAS.
  133. ;;    - Added L line reply handling (RPL241).
  134. ;;    - Be nicer when sending automatic warnings.
  135. ;;    - Better handling of CTCP PING replies.
  136. ;;    - Reordered most global variable initialisations.
  137. ;; v4.25 Fri May 29 21:00:32 1992    sojge@Student.DoCS.UU.SE
  138. ;;    - Added user modes (eg /mode sojge -o)
  139. ;;    - Handles display of a channel's ban list (ie reply to /mode #x -b).
  140. ;;    - Better handling of some STATS replies.
  141. ;;    - Fixed irc-parse-quit.
  142. ;;    - Fixed irc-parse-kick.
  143. ;;    - Take care of v2.7.2 message ERROR: Closing Link.
  144. ;;    - Added CTCP commands ECHO, PING, SOURCE.
  145. ;;    - Started on a crude but better /IGNORE command.
  146. ;;    - Made Kiwi display unknown NOTICE's in block style.
  147. ;;    - Added /PING command, based on CTCP. Coded by Kimmo.Suominen@lut.fi.
  148. ;;    - Started on inout and output convertion tables to displat different
  149. ;;      character sets on different equipment.
  150. ;; 4.24 Mon Feb 24 17:01:09 1992    Klaus-Zeuge@DoCS.UU.SE
  151. ;;    - Still more RPL312 hacking. Hopefully looks OK on a 2.6.2 server now.
  152. ;; 4.23 Sat Feb 22 20:57:27 1992    Klaus.Zeuge@DoCS.UU.SE
  153. ;;    - Added real version number and edit history.
  154. ;; 4.22 Sat Feb 22 17:23:41 1992    Klaus.Zeuge@DoCS.UU.SE
  155. ;;    - Bugfixed CTCP VERSION reply from ircII.
  156. ;; 4.21 Sat Feb 22 16:38:05 1992    Klaus.Zeuge@DoCS.UU.SE
  157. ;;    - Removed annoying bug which mixed up different hash tables.
  158. ;;    - /mode can set modes for a user.
  159. ;;    - Added Q and Y to /stats.
  160. ;;    - /notify, a new command helping to see when your friends enter IRC.
  161. ;;    - /topic understands #channels, both when querying and setting.
  162. ;;    - /whois takes an optional first argument with name of server which
  163. ;;      should answer the whois question.
  164. ;;    - /quit now takes an optional reason.
  165. ;;    - Made /quote send an illegal command to server to help synchronizing.
  166. ;;    - Created variables irc-notify-looked-for and irc-notify-detected.
  167. ;;    - Added user mode in irc-explain-mode, added frontend functions
  168. ;;      irc-explain-user-mode and irc-explain-channel-mode.
  169. ;;    - Cope with different RPL312 styles.
  170. ;;    - Doing a somewhat better job at parsing ircII's ugly CTCP VERSION
  171. ;;      replies.
  172. ;;    - Cope with new RPL201-209, 211, 212, 213-219, 221.
  173. ;;    - Cope with some new NOTICE's.
  174. ;;    - Cope with new format of "Received SQUIT" NOTICE.
  175. ;;    - Cosmetic change in presenting other persons QUIT reasons.
  176. ;;    - Renamed irc-notifies into irc-events (lessens confusion with /notify)
  177. ;;    - Recognize the 500 series of ERR's from server.
  178. ;;    - Do a a sleep-for after EVERY received line from server.
  179. ;;    - Moved logging in *debug* buffer into irc-log-in-debug-buffer.
  180. ;; v4.20 Wed Dec 18 06:33:57 1991    Klaus.Zeuge@DoCS.UU.SE
  181. ;;    - Change a!b@c on incoming messages into a in irc-parse-server-msg.
  182. ;;      (Can you say kludge? I *knew* you could!)
  183. ;;    - Added RPL353 and RPL352 as front ends for NAMREPLY and WHOREPLY.
  184. ;;    - Parse 2.7(.0) version string correctly.
  185. ;;    - Better value for irc-msg-cont-used when reporting a channels mode.
  186. ;;    - Added Kimmo's code for detecting people on IRC using the ISON
  187. ;;      mechanism, irc-execute-notify. Also his irc-notify-list etc.
  188. ;;    - Added Kimmo's code for /ME and /DESCRIBE commands for CTCP ACTION.
  189. ;;    - Added Kimmo's code for recognizing CTCP ACTION commands.
  190. ;;    - Added fixes to keep Kiwi.el from choking on 2.7 messages.
  191. ;;      Fixed RPL messages are: 206, 209, 301, 304, 352, 353, 354,
  192. ;;      367, 368, 371, 373, 383, 384. Thank you Kimmo Suominen <kim@lut.fi>
  193. ;;      for supplying fixes.
  194. ;;    - Made comand "/join #channel +p" and friends kosher.
  195. ;;    - Added : as /MSG like command again after getting requests for it.
  196. ;;    - Threw out my irc-current-time based on writing irc-idle-scratch-file
  197. ;;      and replaced it by one donated by Stephen Ma <ma_s@maths.su.oz.au>.
  198. ;;    - Removed bug in irc-execute-signal.
  199. ;;    - Fixed parse error in irc-parse-pong.
  200. ;;    - More defensive handling of RPL319.
  201. ;; v4.19 Wed Nov 13 15:18:00 1991    Klaus.Zeuge@DoCS.UU.SE
  202. ;;    - Removed forgotten disabling of /KILL command. Ehum...
  203. ;;    - Use function make-temp-name when naming irc-idle-scratch-file.
  204. ;;    - Better formatting in /membership display.
  205. ;;    - Made irc-nuke-whitespace remove trailing spaces too.
  206. ;;    - Understand USERHOST replies (RPL302).
  207. ;;    - More 442 messages understood. Sigh.
  208. ;;    - Incoming TOPIC messages might contain channel name field.
  209. ;;    - USERS reply might contain word "display". Still valid.
  210. ;;    - Cope with 2.6.2e type of TRACE link lines.
  211. ;;    - "Understand" reason field in incoming QUIT messages.
  212. ;;    - Added Kims (kim@lut.fi) fix for 2.6.2e type of LUSER reply.
  213. ;;    - Fixed bug wtih dropped first character when user says "/mode * o u".
  214. ;; v4.18 Tue Oct 22 06:46:49 1991    Klaus.Zeuge@DoCS.UU.SE
  215. ;;    - Moved creation of irc-count-incoming-messages to irc-mode from
  216. ;;      irc-parse-server-msg.
  217. ;;    - Changed irc-truncate-buffer to chop down to irc-minimum-size whenever
  218. ;;      buffer has grown to irc-maximum-size.
  219. ;;    - Made irc-maximum-size = 64KB.
  220. ;;    - Added irc-minimum-size = 32KB.
  221. ;;    - Made most hash table twice as big.
  222. ;; v4.17 Sun Oct 20 17:05:01 1991    Klaus.Zeuge@DoCS.UU.SE
  223. ;;    - Rewrote most calls to string-match so they don't depend on . in
  224. ;;      regexps, as . doesn't match \n.
  225. ;;    - Made CTCP handling more iterative (recursive handling turned out
  226. ;;      to exhaust stacks in worst cases).
  227. ;;    - Made a few more variables buffer local.
  228. ;;    - Added low level quoting of \000, \n, \r, \020 and changed CTCP level
  229. ;;      quoting to use only \001 and \\.
  230. ;;    - Better irc-execute-stats.
  231. ;;    - Replaced all "\\s " by " " and all "\\S " by "[^: ]". Hopefully
  232. ;;      works better.
  233. ;;    - Crude RPL303 handling (reply to ISON).
  234. ;;    - Ripped out irc-maintain-tree! Hooray! Replaced by hash table code
  235. ;;      BUT named the new functions irc-remember, irc-recall, irc-forget.
  236. ;;      This speeded up /NAMES from some 5 minutes to some 10 seconds.
  237. ;; v4.16 Tue Sep 17 21:07:01 1991    Klaus.Zeuge@DoCS.UU.SE
  238. ;;    - When seeing idle time from IrcII clients, translate the large number
  239. ;;      of seconds into days, hours, minutes and seconds.
  240. ;;    - Writing to /dev/null to keep track of idle isn't portable. Use a
  241. ;;      temporary file in the users home directory instead.
  242. ;; v4.15 Thu Aug 22 13:46:03 1991    sojge@mizar.docs.uu.se
  243. ;;    - If user connects to server at host foo.bar.se and foo.se is an
  244. ;;      alias for rela.name.se, Kiwi gets confused. Now irc-server is
  245. ;;      set to real (ie generic) name from the servers Welcome message.
  246. ;;    - Fixed the macro subfield so it won't evaluate at compile time.
  247. ;;      Sigh. Stupid sojge. Thank you Lennart Staflin, Link|ping.
  248. ;;    - Fixed irc-parse-RPL: 317 does NOT give victims nick.
  249. ;;    - Fixed irc-maintain-tree to not crash when removing a service.
  250. ;;    - Added "Notice unauthorized connect" in irc-parse-notice.
  251. ;;    - Added CTCP query and reply for "FINGER". Hopefully this is added in
  252. ;;      a portable way, but I don't really KNOW ... :-(
  253. ;;    - Made irc-is-receiver recognize foo@bar.dom as valid receiver.
  254. ;; v4.14 Mon Aug 12 10:15:05 1991    sojge@mizar.docs.uu.se
  255. ;;    - Fixed /MODE command to work even when saying "/mode ..." in the
  256. ;;      buffer, not only when using C-c m.
  257. ;;    - Fixed some ERR-reply parsing code to grok new format.
  258. ;;    - Added /LEAVE 0 to leave all channels, and made /JOIN 0 just stop
  259. ;;      talking to the current channel.
  260. ;;    - Better nickname control, new scheme with irc-nick-used to keep track
  261. ;;      of what nick we have.
  262. ;;    - Renamed irc-linkstree into irc-linksinfo.
  263. ;;    - Kludged the mess with 2.6 servers first being names 2.6pre19,
  264. ;;      later 2.6.1a so the latter gets a HIGHER irc-edit-version number.
  265. ;;    - Parse RPL 364 messages, ie answers to /LINKS in 2.6.1 servers.
  266. ;;    - For now, ignore message 318.
  267. ;; v4.13 Thu Jun 13 10:28:31 1991    sojge@mizar.docs.uu.se
  268. ;;    - Handle ERR_NICKNAMEINUSE (433) at "login" time.
  269. ;;    - More homogenous command parsing (both /-style and keybound).
  270. ;;    - Cache subscribed channel names.
  271. ;;    - Name  Kiwi buffer "*Kiwi-<server>*".
  272. ;;    - Always run in "slow speed terminal" mode.
  273. ;;    - Shorter messages displayed when seeing a KILL, skipped path.
  274. ;;    - Renamed irc-hosttree into irc-servernames.
  275. ;;    - Added code to put communication in -*debug* buffer IFF it exists.
  276. ;;    - Changed regexp for host names yet again.
  277. ;;    - When getting the windows width, make sure it's the Kiwi window.
  278. ;;    - Prepared function irc to handle several sessions.
  279. ;;    - Handle some 2.6pre19 messages (324, MODE, 403).
  280. ;;    - Bound C-c i to /info.
  281. ;;    - Changed C-c m from /motd to /mode.
  282. ;;    - Fixed misfeature for v18.57 GNU Emacs. Several return values from
  283. ;;      function process-status are valid. Don't start a new session when
  284. ;;      an old one is running.
  285. ;;    - Fixed bug in showing LIST or NAMES reply of Kanjii channel.
  286. ;;    - Clean up channel names as they can contain cntrl-chars too.
  287. ;;    - Fixed display of time to be nicer.
  288. ;;    - Make the (interactive)-part of the irc-execute-* commands more alike
  289. ;;      each other.
  290. ;;    - Bugfix: understand ESC in channel names in a few more places.
  291. ;;    - Bugfix: understand "i" etc, not only "+i" when parsing MODE.
  292. ;;    - Made /COMMAND be shown in buffer when doing command by keys.
  293. ;;    - Amazingly how yours truly can mess up code! Fixed /LEAVE again :-)
  294. ;; v4.12 Sun Mar  3 02:45:21 1991    sojge@mizar.docs.uu.se
  295. ;;    - Changed wording on ctcp (client-to-client protocol) answer for
  296. ;;      a VERSION query.
  297. ;;    - Added C-c C-k to do irc-execute-kill.
  298. ;;    - Bugfixed irc-execute-leave so it works when typing /LEAVE not just
  299. ;;      when typing C-c q.
  300. ;;    - Better handling of /STATS C replies from remote servers.
  301. ;;    - Handle error after /kick user when user's not on channel.
  302. ;; v4.11 Fri Mar  1 16:31:04 1991    sojge@mizar.docs.uu.se
  303. ;;    - Bugfix, corrected misspelled variable for when replying to unkown
  304. ;;      client-to-client PRIVMSG.
  305. ;; v4.10 Thu Feb 28 20:06:05 1991    sojge@mizar.docs.uu.se
  306. ;;    - New behaivour of /WHO, see /HELP WHO.
  307. ;;    - Various bugfixes. (Mostly due to bound keys).
  308. ;;    - Replaced irc-read-user/host by irc-read-object.
  309. ;; v4.9 Wed Feb 27 20:29:58 1991    sojge@mizar.docs.uu.se
  310. ;;    - Added quoting of messages between CNTRL/A:s.
  311. ;;    - Better grok of WALLOPS.
  312. ;;    - Remember correct spelling of a services nickname when seeing
  313. ;;      NOTICES's from one.
  314. ;;    - Bugfixed /CONNECT which w/o "remoteserver" goofed.
  315. ;; v4.8 Wed Feb 27 03:57:50 1991    sojge@mizar.docs.uu.se
  316. ;;    - More initialisation help.
  317. ;;    - Changed client-to-client protocol in non-backward compatible way.
  318. ;;    - OK'ed "/version mizar*".
  319. ;;    - Better handling of /join 0 when on #channel. Updates irc-channel.
  320. ;;    - Changed handling of unknown NOTICE's to be treated as PRIVMSG's.
  321. ;;    - Fixed bug when replying to CLIENT ERRMSG.
  322. ;;    - Show irc-channel in status line.
  323. ;;    - Always send two ^A's, even if to queries/answers are in a row.
  324. ;;    - Made /msg grok broadcast addresses ($server, #host) when enabled.
  325. ;;    - Fixed bugs in /kick.
  326. ;;    - Better help for how to install your personal IRC initiation.
  327. ;; v4.7 Sun Feb  3 03:51:59 1991    sojge@mizar.docs.uu.se
  328. ;;    - Take care of some new styled NOTICE's from the server.
  329. ;;    - Cleaned up the code of irc-parse-priv.
  330. ;;    - Bugfixed irc-parse-kick to keep better track of where we are.
  331. ;;    - Added command /SERVICE.
  332. ;; v4.6 Fri Feb  1 04:03:31 1991    sojge@mizar.docs.uu.se
  333. ;;    - Better handling of /WHOWAS.
  334. ;;    - Changed string from "Kiwi Operator" into "Kiwi, Operator" while
  335. ;;      enabled.
  336. ;; v4.5 Fri Feb  1 02:24:00 1991    sojge@mizar.docs.uu.se
  337. ;;    - Added command /USERINFO to set a string which can be queried by other
  338. ;;      users. Augmented commands /INFO and /VERSION to query the user
  339. ;;      settable string and to query some client version from a users client.
  340. ;;    - Added knowledge of some more NOTICE's from the server.
  341. ;;    - Better handling of STATS, both in giving command (/STATS) and
  342. ;;      parsing L type replies (ie how much data). Added /HELP STATS.
  343. ;;    - Display another field in WHOIS/WHOWAS replies, showing servers text
  344. ;;      field from message 312.
  345. ;;    - Added in irc-parse-notice case for "*** ..." messages.
  346. ;;    - Bugfixed irc-execute-help, so it deals with aliases and topics which
  347. ;;      aren't commands.
  348. ;;    - Changed clients name from sojge-irc.el to Kiwi.el
  349. ;;      (Kiwi initially was irc.el).
  350. ;;    - Added varibales irc-msg-info-pre and -post for letting user select
  351. ;;      how information (default eg: [Foo has joined channel +Bar], the [
  352. ;;      and ] characters) messages start and end.
  353. ;;    - Statistics display nicyfied.
  354. ;; v4.4 Mon Dec 17 17:51:24 1990    sojge@mizar.docs.uu.se
  355. ;;    - Added column alignment (irc-msg-cont-used) for RPL322 and RPL323
  356. ;;      messages (RPL_LIST and RPL_LISTEND).
  357. ;;    - Bugfix: prevents client from crashing (when connected to a 2.6-server
  358. ;;      and doing a TRACE for a nonexistent server) by adding some
  359. ;;      code the for 402 ERR reply (ERR_NOSUCHSERVER).
  360. ;; v4.3 Sun Dec 16 19:19:00 1990    sojge@mizar.docs.uu.se
  361. ;;    - Added case for trace reply "UNKNOWN" in irc-parse-notice.
  362. ;;    - Added key C-c = to do a /MEMBER command.
  363. ;;    - Bugfix: changed general regexp in irc-parse-server-msg to not allow
  364. ;;      spaces in the server part.
  365. ;;    - Made irc-execute-whois handle the /WHOWAS command.
  366. ;;    - Tell the clients version too, after a /VERSION.
  367. ;;    - Bugfix: rewrote irc-execute-topic to put the (interactive) "command"
  368. ;;      in "topmode".
  369. ;;    - Save username in 2.6 kind of USER-traces.
  370. ;;    - Bugfix: Don't remove bogus irc-nick from irc-nicknames on startup
  371. ;;      when setting first nick after default nick failed.
  372. ;; v4.2 Sat Dec 15 04:14:22 1990    sojge@mizar.docs.uu.se
  373. ;;    - Bugfix in irc-parse-server-msg: NOTICE's don't have a : before them
  374. ;;      (except the optional :server part).
  375. ;;    - Can't set topic of a #channel, changed irc-execute-topic.
  376. ;;    - Bugfix: irc-parse-notice now recognizes IRC OPERs as users in traces.
  377. ;;    - Made "NOTICE -- Received kill" equivalente to older
  378. ;;      "NOTICE: Received kill".
  379. ;; v4.1 Thu Dec 13 13:35:43 1990    sojge@mizar.docs.uu.se
  380. ;;    - Zapped irc-news to contain little, but current, information.
  381. ;;    - Corrected bug in alignment of output of who-replies for
  382. ;;      servers w/o end-of-who markes (hello 2.6.pre14!) in
  383. ;;      irc-parse-whoreply.
  384. ;;    - Added knowledge of some trace messages in irc-parse-notice.
  385. ;;    - Fixed bug in irc-parse-notice, so the number of invisble users
  386. ;;      will be displayed if you're an enabled irc operator.
  387. ;;      Thank's heu@byron.u.washington.edu.
  388. ;;    - Fixed irc-execute-links to only reset list of known hosts on
  389. ;;      a LINKS of all the world. (Ie don't reset on LINKS *.SE).
  390. ;;    - Spiffed up sojge-irc's grok of which privmsg go where, changed
  391. ;;      way irc-parse-priv talks to irc-parse-public.
  392. ;;    - Added /MEMBER to show which channels the user's listening and
  393. ;;      talking to.
  394. ;;    - Indicate ircII's CNTRL/B's by *'s.
  395. ;;    - Scrapped [You have joined/left]-messages, instead tell user which
  396. ;;      she's listening and writing to, if any.
  397. ;;    - Added NOTICE-pattern matching of OPER to be analogous to USER
  398. ;;      and CHANOP.
  399. ;;      Thank's kim@lut.fi.
  400. ;;    - Swapped key definitions of C-c C-q and C-c q.
  401. ;;      Thank's kim@lut.fi.
  402. ;;    - Made irc-parse-public look for single old channel in
  403. ;;      irc-subscribed-channels.
  404. ;;    - Added better support for irc-subscribed-channels.
  405. ;;    - irc-parse-RPL, 472: s/inventation/invitation/.
  406. ;;    - Made /WHOWASRPL's be written correctly.
  407. ;;    - Rewrote irc-parse-channel to be better in coping with #channels.
  408. ;;    - Added #channels to be recognized in irc-is-named-channel and in
  409. ;;      irc-is-channelname.
  410. ;;    - Fixed typo in irc-parse-notice.
  411. ;; v4.0 Fri Nov 16 07:06:02 1990    sojge@mizar.docs.uu.se
  412. ;;      Seems to work with both v2.5.1 and v2.6pre14 servers.
  413. ;;    - Made irc-execute-msg send with PRIVMSG is irc-channel is a #channel.
  414. ;;    - Added PART when on 2.6 server in irc-execute-leave.
  415. ;;    - Added JOIN when on 2.6 server in irc-execute-join.
  416. ;;    - Added 2.6 level reply message 317 in irc-parse-RPL.
  417. ;;    - Added 2.6 level commands JOIN and PART in irc-parse-server-msg and
  418. ;;      irc-parse-channel.
  419. ;;    - On nonmatcher NOTICE, just give the notice to the user with out
  420. ;;      frightening her with big WARNING signs.
  421. ;;    - Removed buggy string-match in irc-parse-notice for svarte being
  422. ;;      matched against a terminal (rt).
  423. ;;    - irc-parse-RPL: set irc-msg-cont-used when receiving message 314
  424. ;;      (RPL_WHOWASUSER).
  425. ;;    - Made confirmation when sending to several users/channels at once
  426. ;;      being written one confirmation per line.
  427. ;; v3.14 Thu Nov  1 19:47:09 1990    sojge@mizar.docs.uu.se
  428. ;;    - Made /OOPS work without an argument, if non given, ask for one.
  429. ;;    - Added possible bugfix in irc-parse-RPL for message 322.
  430. ;;    - irc-execute-command: don't put "'s around help w/ possible commands.
  431. ;;    - irc-insert-most: use right-most argument of irc-choose-break-point.
  432. ;;    - irc-insert: use right-most argument of irc-choose-break-point.
  433. ;;    - irc-choose-break-point: use parameter right-most, not (window-width).
  434. ;;    - irc-parse-notice: slightly new "no users logged in" message.
  435. ;;    - irc-parse-notice: write "serverlink", not "connection" in /TRACES.
  436. ;;    - irc-parse-wallops: set irc-msg-cont-used to max window-width / 2.
  437. ;;    - irc-parse-priv: set irc-msg-cont-used to max window-width / 2.
  438. ;;    - irc-parse-public: set irc-msg-cont-used to max window-width / 2.
  439. ;;    - irc-parse-channel: prevent negative string length in pd.
  440. ;; v3.13 Tue Oct  9 04:35:51 1990    sojge@mizar.docs.uu.se
  441. ;;    - Sigh, when do I learn not to release code when being ++tired?
  442. ;;      Fixed a newborn bug in irc-execute-msg.
  443. ;; v3.12 Tue Oct  9 03:49:14 1990    sojge@mizar.docs.uu.se
  444. ;;    - Made a quick and dirty bugfix to prevent crashing in irc-insert-more.
  445. ;;      Sort of works. Sigh.
  446. ;;    - Fixed bug in irc-parse-server-msg, do accept NOTICEs from "strange"
  447. ;;      origins...
  448. ;;    - Set global irc-msg-cont-used in irc-parse-RPL while parsing WHOIS
  449. ;;      replies.
  450. ;;    - Removed two bugs in irc-insert-more.
  451. ;;    - Made /WHOIS STRING trying to get information even if STRING isn't
  452. ;;      remembered in irc-nicknames as being present.
  453. ;;    - Made /WHO USER do a WHOIS USER, while /WHO CHANNEL does a
  454. ;;      WHO CHANNEL.
  455. ;;    - Made irc-execute-wallops confirm if irc-confirm is non-nil.
  456. ;; v3.11 Thu Aug 30 17:41:18 1990    sojge@mizar.docs.uu.se
  457. ;;    - Sigh, fixed bug in irc-execute-whowas. I'd better do a RPLACA...
  458. ;; v3.10 Thu Aug 30 15:47:36 1990    sojge@mizar.docs.uu.se
  459. ;;    - Added irc-execute-whowas (long due).
  460. ;;    - Fixed som other minor bugs. I hope.
  461. ;;    - BUGFIX in irc-remove-from-tree, do comparsion in upcase.
  462. ;;    - Made irc-execute-msg tell if receivers are users or channels.
  463. ;;    - Fixed bug in irc-is-channel. ("-77?" is NOT a channel ID).
  464. ;;    - Recognize Kanji message and replace with generic string.
  465. ;; v3.9 Wed Aug 22 08:07:21 1990    sojge@mizar.docs.uu.se
  466. ;;    - Added a rudimentary function irc-execute-kick.
  467. ;;    - Wrote predicate irc-is-channelname.
  468. ;;    - Updated predicate irc-is-nickname to better reflect reality.
  469. ;;    - Made irc-execute-msg grok channel's as receipants.
  470. ;;    - Added simplistic irc-execute-mode function.
  471. ;;    - FIXED BUG in irc-find-to by rewriting it.
  472. ;;    - Made message 421 grok 2.5 messages too.
  473. ;;    - Added function irc-parse-kick.
  474. ;;    - Added some more (let ((irc-msg-cont-used ...) around irc-insert's.
  475. ;;    - Made irc-explain-mode work.
  476. ;;    - Changed count in irc-execute-send so irc-msg-sent is right justified.
  477. ;; v3.8 Sun Aug 19 04:55:31 1990    sojge@mizar.docs.uu.se
  478. ;;    - BUGFIX: v3.6 introduced bug making it hard to join negative channels,
  479. ;;      now it's easy again.
  480. ;; v3.7 Sat Aug 18 23:48:56 1990    sojge@mizar.docs.uu.se
  481. ;;    - Set irc-msg-cont-used before calling irc-insert for some lists.
  482. ;;    - Understand ERR_NOTONCHANNEL message.
  483. ;;    - Don't explecitly request MOTD (message of the day) when connected
  484. ;;      to v2.5 servers or later. They give it anyway.
  485. ;;    - Don't show the "no topic set" messages from remote old server
  486. ;;      at topic changes.
  487. ;;    - Collect server names in irc-parse-RPL.
  488. ;;    - Added irc-split-lines to make better line splits in irc-insert.
  489. ;; v3.6 Fri Aug 17 04:41:19 1990    sojge@mizar.docs.uu.se
  490. ;;    - Changed format of how the status in a WHO listing appears.
  491. ;;    - Ignore error messages from other old server complaining MODE being
  492. ;;      an unknown command.
  493. ;;    - Understands the WHO-reply statuses "channel operator"
  494. ;;      and "channe operator and IRC operator".
  495. ;;    - Sort of understands reply message 316 .
  496. ;;    - Join channel 007, not +007 at "/join 007" (ie no prepending of + when
  497. ;;      first letter in channelname is a digit).
  498. ;;    - Understand reply message 324.
  499. ;;    - Say "using default" after a "/query *".
  500. ;; v3.5 Thu Jun 14 07:23:51 1990    sojge@emil.csd.uu.se
  501. ;;    - Teached /KILL to understand comments.
  502. ;;    - Added a simplistic header to linreply display.
  503. ;;    - Make it possible for away messages to start with :.
  504. ;;    - Save nickname in irc-parse-wallops.
  505. ;; v3.4 Mon Jun 11 03:55:08 1990    sojge@emil.csd.uu.se
  506. ;;    - Added operator level command /CONNECT.
  507. ;;    - Remapped C-C C-S to be irc-execute-squit.
  508. ;;    - Added operator level command /SQUIT.
  509. ;;    - Added operator level command /WALLOPS.
  510. ;;    - Added some support for mnemonic channel ID's, ie not only numbers
  511. ;;      but also strings can identify a channel. Probaly a bit buggy.
  512. ;;      Problem: How long can an ID be?
  513. ;;    - Made irc-channel into a string, from being a number.
  514. ;;    - Made /WHO SOJGE show a one line WHO reply (plus header) about SOJGE,
  515. ;;      ie not doing a WHOIS for SOJGE. Will probaly change.
  516. ;; v3.3 Wed Jun  6 07:26:57 1990    sojge@emil.csd.uu.se
  517. ;;    - Keep statistics on LIST replies in a new way.
  518. ;;    - Made irc-add-to-tree do it's string comparsions in upper case, this
  519. ;;      prevents the same name in two different cases to be stored.
  520. ;;    - Corrected minor bug in irc-parse-notice about reconizing USERS
  521. ;;      replies.
  522. ;;    - Changed (irc-insert "foo\nbar") into 
  523. ;;      (irc-insert "foo") (irc-insert "bar")
  524. ;;    - Made the "IRC halted" message a bit more flashy.
  525. ;; v3.2 Mon Jun  4 19:59:00 1990    sojge@emil.csd.uu.se
  526. ;;    - When on a fast terminal (see irc-terminal-is-slow), don't bother
  527. ;;      to collect various replies in temporary storage lists. Display the
  528. ;;      unsorted entrys as fast as they come in.
  529. ;;    - Improved handling of /USERS replies.
  530. ;; v3.1 Sat May 26 03:05:46 1990    sojge@emil.csd.uu.se
  531. ;;    - Corrected bug which prevented LINK to actually display any data...
  532. ;; v3.0 Sat May 26 02:21:52 1990    sojge@emil.csd.uu.se
  533. ;;    - Changed version from 1.9 to 3.0 in one step.
  534. ;;    - Set irc-nick according to incoming NOTICE messages.
  535. ;;    - Made the WHOREPLY header be displayed when the first reply comes in.
  536. ;;    - Understand message 314, RPL_WHOWASUSER.
  537. ;;    - Renamed irc-nameslist (former irc-whotree) into irc-nicknames.
  538. ;;    - Added case for "no motd at server", both for 2.4 and pre 2.4 servers.
  539. ;;    - Beautified "IRC server xx runs version yy" message.
  540. ;;    - Added irc-execute-version.
  541. ;;    - Added irc-execute-motd.
  542. ;; v1.9 Sat May 19 14:44:58 1990    sojge@emil.csd.uu.se
  543. ;;    - Wrote irc-parse-pong to collect host name from ping messages.
  544. ;;    - Made irc-extract-hosts skip parts between between nodename and "!".
  545. ;;    - Made WHO lists more mnemonic.
  546. ;;    - Made LINREPLYs be gathered in a variable before sorting and
  547. ;;      displaying it even for 2.2 type servers.
  548. ;;    - Make client ask for the message of the day (MOTD) when seeing
  549. ;;      the (final line of the) servers welcome message, not at "start up".
  550. ;;    - Look as far as 1/3 of the line from the right when choosing a
  551. ;;      break point in irc-insert. Makes a few listing look better on
  552. ;;      a 80 column screen.
  553. ;;    - Take care of "unknown connection" message in irc-parse-notice.
  554. ;; v1.8 Thu May 17 00:53:20 1990    sojge@emil.csd.uu.se
  555. ;;    - Say "use /HELP" if user seems totaly confused on channel 0.
  556. ;;    - Fixed bug in irc-parse-whoreply, don't add header to irc-whotree.
  557. ;;    - Say "no users" on a 2.4 (or later) server if user issued /who 
  558. ;;      for an empty channel.
  559. ;; v1.7 Wed May 16 23:34:01 1990    sojge@emil.csd.uu.se
  560. ;;    - Show time when being pinged, not every x minutes.
  561. ;;    - Don't crash if server closed connection, reopen it,
  562. ;;    - Skip some messages like START OF MOTD ...
  563. ;;    - Show what remote server, if any, a message came from.
  564. ;;    - Take care of a bunch of new NOTICE messages.
  565. ;;    - Understand new (server v2.4) type of welcome message.
  566. ;;    - Ignore empty lines from server.
  567. ;;    - Moved logic about format of different information keeping trees
  568. ;;      into irc-maintain-tree.
  569. ;;    - Made (most) error messages start with a % sign.
  570. ;;    - Renamed IRC-WHOTREE into IRC-NAMESTREE.
  571. ;;    - Keeps track of what version the used server is, and depending on it
  572. ;;      uses (or not) the fact that it's possible to gather WHOREPLYs and
  573. ;;      LINREPLYs before displaying it. Exploits the "end of who/links"
  574. ;;      message from the server.
  575. ;;    - Understands new MOTD notices, collects data until end-of-motd-list.
  576. ;;    - Better handling of extracting hostnames from different places.
  577. ;;      Uses irc-extract-hostname.
  578. ;;    - Made irc-maintain-tree use upcase and irc-extract-hostname on items
  579. ;;      for irc-hosttree.
  580. ;;    - Now extracts info from MOTD replies.
  581. ;; v1.6 Mon Apr  9 22:25:22 1990    sojge@emil.csd.uu.se
  582. ;;    - Improved handling of %-signs in messages (data part so to say) by
  583. ;;      doing a s/%/%%/ in functions irc-parse-public and irc-parse-privmsg.
  584. ;; v1.5 Mon Apr  9 17:32:51 1990    sojge@emil.csd.uu.se
  585. ;;    - Extract server names from KILL messages paths.
  586. ;; v1.4 Fri Apr  6 01:30:46 1990    sojge@emil.csd.uu.se
  587. ;;    - Removed s/%/%%/ from irc-parse-server-msg.
  588. ;;    - Let function irc check that the *IRC* buffer has an open stream
  589. ;;      "process" associated with it before trying to switch to the buffer.
  590. ;;      This is handy when the stream has been closed.
  591. ;; v1.3 Tue Apr  3 23:51:38 1990    sojge@emil.csd.uu.se
  592. ;;    - Made irc.el cope with new format on some NOTICE messages.
  593. ;;      (:server NOTICE ...)
  594. ;; v1.2 Fri Mar 30 03:42:31 1990    sojge@emil.csd.uu.se
  595. ;;    - Changed protocol, initiate with USER <username> * * <realname> now.
  596. ;;    - Changed misc. error messages to start with %.
  597. ;;    - Made a few "server message unkown" messages tell where they are
  598. ;;      in the code.
  599. ;;    - Added code to make WHOIS * invokde WHOIS for all users.
  600. ;;    - Made irc-parse-channel set irc-msg-cont-used.
  601. ;;    - Added and removed code for automatic greeting of new joiners to
  602. ;;      channels, in irc-parse-channel. But this doesn't seem to be enough.
  603. ;;      More debugging needed ...
  604. ;;    - Made irc.el understand MOTD messages from server, not reliying on
  605. ;;      all lines in MOTD file starting with a blank.
  606. ;; v1.1 Mon Mar 26 03:37:03 1990    sojge@emil.csd.uu.se
  607. ;;    - Cleaned up some more, in how things are displayed. Servers
  608. ;;      domain names are displayed in upper case, in
  609. ;;      irc-parse-linrpl and their information text "as is". Some
  610. ;;      headers  are underlined.
  611. ;;    - Corrected (?) bug in irc-parse-RPL which handled RPL_MOTD
  612. ;;      messages incorrectly.
  613. ;; v1.0 Wed Feb 28 21:53:49 1990    sojge@emil.csd.uu.se
  614. ;;    - Changed look and feel by introducing a couple of variables
  615. ;;      and removing the conserve-space kludge. Apperence is now user
  616. ;;      settable.
  617. ;;    - Rewritten buggy irc-insert so it works. No more infinite looping.
  618. ;;    - Added a few key bindings.
  619. ;;    - Made irc-parse-RPL (at RPL_WHOISSERVER) and irc-parse-notice add
  620. ;;      information to the irc-hostlist, just like irc-parse-linreply does.
  621. ;; v0.9 Sometime 1989    flax@mizar.docs.uu.se
  622. ;;    - Made irc-linreply add to a list of known hosts so completion of
  623. ;;      host names in irc-execute-admin and others will work. Neat.
  624. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  625. ;; Author          : David C Lawrence           <tale@pawl.rpi.edu>
  626. ;; Created On      : Wed Jun 14 22:22:57 1989
  627. ;; Last major modification: Jonas Flygare
  628. ;; Last minor modification: Klaus Zeuge
  629. ;; Last Modified On: Wed Jan 24 00:54:29 1990
  630. ;; Update Count    : 100
  631. ;; Status          : Stable
  632. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  633. ;;  Copyright (C) 1989  David C Lawrence
  634.  
  635. ;;  This program is free software; you can redistribute it and/or modify
  636. ;;  it under the terms of the GNU General Public License as published by
  637. ;;  the Free Software Foundation; either version 1, or (at your option)
  638. ;;  any later version.
  639.  
  640. ;;  This program is distributed in the hope that it will be useful,
  641. ;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
  642. ;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  643. ;;  GNU General Public License for more details.
  644.  
  645. ;;  You should have received a copy of the GNU General Public License
  646. ;;  along with this program; if not, write to the Free Software
  647. ;;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  648.  
  649. ;; Comments and/or bug reports about this interface should be directed to:
  650. ;;     Dave Lawrence          <tale@{pawl,itsgw}.rpi.edu>
  651. ;;     76 1/2 13th Street     +1 518 273 5385
  652. ;;     Troy NY 12180          Generally available on IRC as "tale"
  653.  
  654. ;; History         
  655. ;; 27-Sep-1989        Gnu Maint Acct    (gnu at life.pawl.rpi.edu)
  656. ;;    Last Modified: Wed Sep 27 18:56:19 1989 #6
  657. ;;    * Fixed a misrefenced variable in irc-parse-server-msg so that lines
  658. ;;      which can't be parsed insert only that unparsable line.
  659. ;;    * Added irc-parse-topic and changed irc-signals and irc-notifies
  660. ;;      appropriately.
  661. ;;    * Moved setting of irc-channel to irc-parse-channel from irc-execute-join
  662. ;;      because a channel change isn't guaranteed (ie, trying to change to
  663. ;;      a channel not in 0-10 which has ten users on it).
  664. ;;    * Made irc-message-stamp 'private by default. (Geoff)
  665. ;;    * Made irc-time-stamp 0 by default.      (Also Geoff)
  666. ;;      This tickled an unseen bug in the start-up function which incremented
  667. ;;      irc-last-stamp.  It's fixed now.
  668. ;;    * Fixed a bug with interactive irc-execute-names -- prefix arg was being
  669. ;;      (list ...)ed.
  670. ;;    * Fixed a bug in irc-parse-namreply that dropped a name in the output
  671. ;;      when a line got wrapped.
  672. ;;    * Added /lusers.  I really dislike the name.
  673. ;;    * Added irc-parse-kill.
  674. ;;    * Made irc-execute-msg strip one space after the colon in messages;
  675. ;;      ie, "tale: hi" will send "hi" as a message not " hi".
  676. ;;    * Took out hardcoded width numbers for word-wrapping.  Uses
  677. ;;      (window-width) instead.
  678. ;;    * Added to the regexp for failed nickname changes in irc-parse-error;
  679. ;;      the sentences got changed in the newer servers.
  680. ;;    * Wrapped irc-check-time around display-time-filter for better accuracy
  681. ;;      if a display-time process is running.
  682. ;;    * Made the "IRC Session finished" message include the time.
  683. ;;    * Added irc-conserve-space to imitate the C client message style.  I
  684. ;;      really dislike it aesthetically, but it is handy for people running
  685. ;;      on 24 line screens and at slow baud rates. (Kimmel & others)
  686. ;;    * Support IRCNICK and IRCSERVER environment variables at load time. (Kim)
  687. ;;    * Made /WHO call /WHOIS if given a non-numeric argument.  (Nate)
  688. ;;    * Fixed a bug where an alias would be executed before an exactly matching
  689. ;;      command; ie, alias /WHOALIAS whould execute when /WHO was entered.
  690. ;;    * Runs things in auto-fill-mode with a fill-column of 75 by default.
  691. ;;    * Processes the whole input region as one line instead of line-at-a-time.
  692. ;;    * Made irc-change-alias for non-interactive setting/removing of aliases;
  693. ;;      ie, via irc-mode-hook.  No frills.  (Chris & Nate)
  694. ;;    * _Finally_ got around to adding parsing of numeric notices for new
  695. ;;      servers.
  696.  
  697. ;; Need backquote.el for our macros.
  698. (require 'backquote)
  699.  
  700.  
  701. ;; Defined variables
  702.  
  703. (defvar irc-abusive-ignore nil
  704.   "If non nil, send back a message to persons being ignored, instead of
  705. being silent, while throwing away messages from them.")
  706.  
  707.  
  708. (defvar irc-alias-alist
  709.   '(
  710.     ("?" . "help")            ; Abbrevation
  711.     ("BYE" . "quit")
  712.     ("CHANNEL" . "join")
  713.     ("END" . "quit")            ; Plenty of ways out
  714.     ("EXIT" . "quit")
  715.     ("IDLE" . "who")            ; for people too used to Connect
  716.     ("L" . "list")            ; Abbrevation
  717.     ("M" . "msg")            ; Abbrevation
  718.     ("MS" . "msg")            ; Abbrevation
  719.     ("N" . "names")            ; Abbrevation
  720.     ("QUERY" . "send")            ; For people used to the C client
  721.     ("STOP" . "quit")            ; Plenty of ways out
  722.     ("U". "users")            ; Abbrevation
  723.     ("US". "users")            ; Abbrevation
  724.     ("USE". "users")            ; Abbrevation
  725.     ("USER". "users")            ; Abbrevation
  726.     ("W" . "who")            ; Abbrevation
  727.     ("WHAT" . "list")            ; /WHAT from Connect
  728.     )
  729.   "An association list of command aliases used in irc-mode.
  730. This is the first list checked when irc-mode is looking for a command and it
  731. is maintained with the /ALIAS and /UNALIAS commands.")
  732.  
  733.  
  734. (make-variable-buffer-local
  735.  (defvar irc-cache-n+s nil
  736.    "Cache of known nicks and servers"))
  737.  
  738.  
  739. (make-variable-buffer-local
  740.  (defvar irc-cache-c+n+s nil
  741.    "Cache of known channels, nicks and servers"))
  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. (make-variable-buffer-local
  751.  (defvar irc-called-from-buffer nil
  752.    "Flag saying whether a command is called from the irc buffer with /names
  753. or invoked through pressing a key like C-c C-c."))
  754.  
  755.  
  756. (defconst irc-command-alist
  757.     '(("ADMIN" . "admin")        ; Get information about IRC admins
  758.       ("ALIAS" . "alias")        ; Add command aliases
  759.       ("AWAY" . "away")            ; Give som indication of your presenc
  760.       ("CONFIRM" . "confirm")        ; Set message confirmation on or off
  761.       ("DESCRIBE" . "describe")        ; CTCP action.
  762.       ("DIE" . "die")            ; Tell server to die.
  763.       ("EVENT" . "event")        ; Change which events give notification
  764.       ("FINGER" . "finger")        ; CTCP finger.
  765.       ("HELP" . "help")            ; Get help on the /COMMANDs
  766.       ("HERE" . "here")            ; Remove the away mark
  767.       ("IGNORE" . "ignore")        ; Ignore messages from a specified user
  768.       ("INFO" . "info")            ; Information about users and authors
  769.       ("INVITE" . "invite")        ; Ask another user to join your channel
  770.       ("JOIN" . "join")            ; Join a channel
  771.       ("KICK" . "kick")            ; Boot a user from a channel
  772.       ("LEAVE" . "leave")        ; Leave a channel
  773.       ("LINKS" . "links")        ; Show which servers are in the IRC-net
  774.       ("LIST" . "list")            ; Show a list of channels and topics
  775.       ("LUSERS" . "lusers")        ; Get the number of users and servers
  776.       ("MAIL" . "mail")            ; Give commands to the mail subsystem.
  777.       ("ME" . "me")            ; Send a CTCP ACTION message to channel
  778.       ("MEMBERSHIPS" . "memberships")    ; Show subscribed channels.
  779.       ("MODE" . "mode")            ; Change or inspect the mode of a chan
  780.       ("MOTD" . "motd")            ; Message of the day
  781.       ("MSG" . "privmsg")        ; Send a private message to someone
  782.       ("NAMES" . "names")        ; Display nick names on each channel
  783.       ("NEWS" . "news")            ; Show news about client.
  784.       ("NICKNAME" . "nick")        ; Change your IRC nickname
  785.       ("NOTIFY" . "notify")        ; Notify when selected nicks are seen
  786.       ("OOPS" . "oops")            ; Resend a misdirected message
  787.       ("OPER" . "oper")            ; Login as an IRC operator
  788.       ("QUIT" . "quit")            ; Exit IRC
  789.       ("QUOTE" . "quote")        ; Send raw text to the server
  790.       ("PING" . "ping")            ; Send CTCP PING to another user
  791.       ("REDIRECT" . "redirect")        ; Send the last message to someone else
  792.       ("SEND" . "send")            ; Set the implicit send list for msgs's
  793.       ("SERVICE" . "service")        ; Add and subtract to list of automates
  794.       ("SIGNAL" . "signal")        ; Change which events give a signal
  795.       ("STAMP" . "stamp")        ; Set time notification interval
  796.       ("STATS" . "stats")        ; Get statistics from server.
  797.       ("SUMMON" . "summon")        ; Ask a user not on IRC to join it
  798.       ("TIME" . "time")            ; Get the current time from a server
  799.       ("TOPIC" . "topic")        ; Change the topic of the channel
  800.       ("TRACE" . "trace")        ; Show the links between servers
  801.       ("UNALIAS" . "unalias")        ; Remove command aliases
  802.       ("UNIGNORE" . "unignore")        ; Stop ignoring user
  803.       ("USERINFO" . "userinfo")        ; Set information about oneself
  804.       ("USERS" . "users")        ; Show users logged in at a server
  805.       ("VERSION" . "version")        ; Version of a server or a users client
  806.       ("WALLOPS" . "wallops")        ; Send a message to all operators
  807.       ("WHO" . "who")            ; Get list of users and their channels
  808.       ("WHOIS" . "whois")        ; Get longer information about a user
  809.       ("WHOWAS" . "whois"))        ; Check who user who has left IRC was.
  810.   "An association list of the regular commands to which all users have access.
  811. Form is (\"COMMAND\" . \"function\") where \"function\" is that last element in
  812. an irc-execute-* symbol.  See also irc-alias-alist and irc-operator-alist.")
  813.  
  814.  
  815. (defvar irc-confirm t
  816.   "*If non-nil, provide confirmation for messages sent on IRC.
  817. It should be noted that confirmation only indicates where irc-mode
  818. tried to send the message, not whether it was actually received.
  819. Use the /CONFIRM command to change.")
  820.  
  821.  
  822. (make-variable-buffer-local
  823.  (defvar irc-default-to "*;"
  824.    "The default recipient of a message if no : or ; is provided.
  825. \"*\" means the current channel, no matter what it is."))
  826.  
  827.  
  828. (make-variable-buffer-local
  829.  (defvar irc-drop-ircII-text-kludge-control-characters t
  830.    "*If nil, show CNTRL/B, CNTRL/V and CNTRL/_ as ^B. ^V and ^_ in text. These
  831. characters are used as a kludge by the client ircII to toggle the attributes
  832. reverse, underline and bold respectivly in text. If non-nil, drop those three
  833. characters."))
  834.  
  835.  
  836. (defvar irc-emacs-knows-ISO8859-1 (>= (string-to-int emacs-version) 19)
  837.   "*Non-nil if Kiwi shouldn't translate octets in incoming messages with
  838. the high bit set to \xyz strings; nil if translation for such characters
  839. (0240 - 0377) should occur.")
  840.  
  841.  
  842. (make-variable-buffer-local
  843.  (defvar irc-events '(ctcp join nick quit topic)
  844.    "Events in IRC that should get notification messages.
  845. A notification message is just one line to indicate that the event has
  846. occurred.  The \"ctcp\", \"join\", \"nick\", \"quit\" and \"topic\"
  847. events are currently supported by the /EVENT command."))
  848.  
  849.  
  850. (defconst irc-help-topic-alist
  851.     '((";" . "Usage: RECEIVER[,RECEIVER]...; MESSAGE
  852.  
  853. Send a message to one or several receivers.
  854. About the same as /MSG and :, see /HELP : and /HELP MSG.
  855.  
  856. When no receiver is given yet, on a line, and you press ; first on that line,
  857. the last receiver is inserted (this may be a users nickname, a channelname,
  858. a list of receivers, etc)
  859.  
  860. Don't use any spaces left of the ;.")
  861.       (":" . "Usage: RECEIVER [, RECEIVER] ... ; MESSAGE
  862.  
  863. Send a message to one or several receivers.
  864. About the same as /MSG and ;, see /HELP ; and /HELP MSG
  865.  
  866. When no receiver was given yet, and : is inserted first on the line, the
  867. last person you sent to will be the default receiver.
  868.  
  869. Don't use any spaces left of the :.")
  870.       ("STARTUP" . "Initiation and startup
  871.  
  872. To make your GNU Emacs know of this IRC user interface, you can add
  873. the following command to your GNU Emacs initialisation file (normaly
  874. .emacs) in your home directory:
  875.         (autoload 'irc \"Kiwi\"
  876.             \"Internet Relay Chat user interface.\" t nil)
  877.  
  878. This will make your Emacs to load the library file Kiwi.elc or Kiwi.el
  879. when you typing M-x irc RET. The file must be in one of the
  880. directories mentioned in the variable load-path. (You can check this
  881. variables value by typing C-h v load-path RET). You can compile the
  882. file Kiwi.el by typing M-x byte-compile-file RET Kiwi.el RET to get
  883. Kiwi.elc.
  884.  
  885. At startup time of IRC, you may want to initiate some settings and
  886. give some commands. This can be done by setting some variables in your
  887. GNU Emacs initialisation file (normaly called .emacs). Some typical
  888. initialisations may be
  889.  
  890.        (setq irc-server \"minsk.docs.uu.se\"      ;Which server to use.
  891.              irc-msg-public \"%s%9s/%s:  \"       ;How to display public msgs
  892.              irc-pop-on-signal 3                ;Use about 1/3 of screen when
  893.                                                 ; popping up a Kiwi buffer.
  894.              ;; Give some information about yourself, whatever you want.
  895.              irc-userinfo (concat
  896.                            \"Studying computer science at the university of\"
  897.                            \" Uppsala. Call me on +46 18 463253.\")
  898.              ;; Commands to be executed when seeing the Welcome message
  899.              ;; from a server we just connected to.
  900.              irc-startup-hook '(lambda ()
  901.                                 (irc-execute-command \"links *.se\")
  902.                                 (irc-execute-command \"who *.se\")))
  903.  
  904. This will make IRC use about 1/3 of the screen when popping up a
  905. window (this happens for instance when you have deselcted all IRC
  906. windows and someone sends you a message). Also, the information string
  907. for you (which can contain any information you choose) is initiated.
  908. When a server says \"welcome\", you will be shown all active servers
  909. in Sweden (SE) and all active users using IRC in Sweden.
  910.  
  911. Don't give the leading / in the arguments to irc-execute-command.
  912.  
  913. If you want more control over how to display public and/or private messages
  914. (at the time exluding WALLs and WALLOPSs) you can use this clumsy way (be
  915. patient, a more user friendly method is on it's way) of setting the variables
  916. irc-public-insert and irc-private-insert to functions taking 3 strings as
  917. arguments, namely the name of the sender, name of the receiver (user or channel
  918. name normaly) and the message itself (in raw format, after extracting the
  919. client-to-client protocol stuff). All this sums up to, that if you don't know
  920. elisp, you probaly don't want to use this method, or else just change the
  921. control string constants in the examples below.
  922. Examples:
  923.   (setq
  924.    irc-public-insert '(lambda (from to msg)
  925.                (let* ((same-chan (string= (upcase irc-channel)
  926.                           (upcase to)))
  927.                   (hdr
  928.                    (format (if same-chan
  929.                        \"%s %9s:  \"
  930.                        \"%s %9s/%s:  \")
  931.                        (if (and irc-message-stamp
  932.                         (not (eq irc-message-stamp
  933.                              'private)))
  934.                        (irc-get-time)
  935.                        \"\")
  936.                        from
  937.                        to))
  938.                   (irc-msg-cont-used
  939.                    (make-string 
  940.                 (min (length hdr)
  941.                      (/ (window-width (get-buffer-window
  942.                                (current-buffer)))
  943.                     2))
  944.                 ? )))
  945.              (irc-insert
  946.               (concat hdr (irc-clean-up-message msg)))))
  947.    irc-private-insert '(lambda (from to msg)
  948.             (let* ((to-whom
  949.                 (cond ((string= (upcase irc-nick-used)
  950.                         (upcase to))
  951.                        \"*%s %s*  \")
  952.                       ((irc-is-broadcastname to)
  953.                        (concat \"=%s %s BROADCAST to all\"
  954.                            \"users on IRC server(s)\"
  955.                            \" \\\"%s\\\"=  \"))
  956.                       (t \"*%s %s/%s*  \")))
  957.                    (hdr
  958.                 (format to-whom
  959.                     (if (and
  960.                          irc-message-stamp
  961.                          (eq irc-message-stamp
  962.                          'private))
  963.                         (irc-get-time)
  964.                         \"\")
  965.                     from
  966.                     to))
  967.                    (irc-msg-cont-used (make-string 
  968.                            (min (length hdr)
  969.                             (/ (window-width (get-buffer-window (current-buffer)))
  970.                                2))
  971.                            ? )))
  972.               (irc-insert
  973.                (concat hdr (irc-clean-up-message msg))))))
  974.  
  975. Hint: the internal control strings uses 2 or 3 of the %s to write the time,
  976. the senders name and the receivers name. If only 2 %s are given, the receivers
  977. name won't be written.
  978.  
  979. [Note: this is a preliminary version of the help text, please send mail
  980. to Klaus.Zeuge@Student.DoCS.UU.SE if you think it needs to be changed.]"))
  981.   "A-list with car = keyword-string for a topic and cdr = descriptions string
  982. of the keyword.")
  983.  
  984.  
  985. (make-variable-buffer-local
  986.  (defvar irc-history nil
  987.    "A list of messages which irc-mode has processed.
  988. This includes both successfully and unsuccessfully sent messages, starting
  989. with the most recent first.  irc-max-history limits the number of items
  990. that can appear in the list when using irc-add-to-history."))
  991.  
  992.  
  993. (make-variable-buffer-local
  994.  (defvar irc-ignore-automatic-warnings nil
  995.    "*Variable to say whether to to display or not display automatic warnings
  996. from users. Such warnings start with the marker \"<Automatic warning> \" in
  997. a message either directly to to, or on a channel. The default and RECOMMENDED
  998. value is nil, ie to display. Set to non-nil to supress such messages."))
  999.  
  1000.  
  1001. (make-variable-buffer-local
  1002.  (defvar irc-ignores nil
  1003.    "A list of NICKNAMES whose events will be ignored.
  1004. Messages or other actions (like joining a channel) generated by anyone in
  1005. the list will not be displayed or signalled.  This list is maintained with
  1006. the /IGNORE and /UNIGNORE commands."))
  1007.  
  1008.  
  1009. (make-variable-buffer-local
  1010.  (defvar irc-ignore-trunk nil
  1011.    "A trunk (for now an array of hash tables) of events and nicks to ignore."))
  1012.  
  1013.  
  1014. (defvar irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1 nil
  1015.   "*Set to true if you want the sevenbit ISO 646-SE2 characters @[\]^`{|}~ to
  1016. be mapped into the corrosponding eightbith ISO 8859-1 characters when
  1017. being typed.
  1018.  
  1019. Set to nil to get no such mapping.
  1020.  
  1021. Set to neither t or nil if you want to get the mapping with the case
  1022. for ], [, \\ reversed, i.e. want to have the [ key treated as \344 and
  1023. the { key treated as \304.")
  1024.  
  1025.  
  1026. (defvar irc-max-history 40
  1027.   "*The maximum number of messages retained by irc-mode.
  1028. This limits messages sent, not messages received.  They are stored to be
  1029. easily recalled by irc-history-prev and irc-history-next (C-c C-p and C-c C-n
  1030. by default).")
  1031.  
  1032.  
  1033. (defvar irc-max-server-message-length 512
  1034.   "The maximum length of a message one can send to a server. This include the
  1035. trailing CRLF, so the \"real\" message length is 2 less.")
  1036.  
  1037.  
  1038. (defvar irc-maximum-size (* 64 1024)
  1039.   "*Maximum size that the *Kiwi-server* buffer can attain, in bytes.
  1040. The default value of 64KB represents an average of about 1500 lines, or roughly
  1041. 65 screens on a standard 24 line monitor. See also irc-minimum-size.")
  1042.  
  1043.  
  1044. (defvar irc-message-stamp 'private
  1045.   "*Mark messages received in IRC with the time of their arrival if non-nil.
  1046. If this is the symbol \"private\" or \"public\" then only messages of the
  1047. specified type are marked with the time.  WALL messages are always
  1048. time-stamped.")
  1049.  
  1050.  
  1051. (defvar irc-minimum-size (* 32 1024)
  1052.   "*Minimum size that the *Kiwi-server* buffer will get truncated to after
  1053. hitting the size in irc-maximum-size.")
  1054.  
  1055. (defvar irc-mode-hook nil
  1056.   "*Hook to run after starting irc-mode but before connecting to the server.")
  1057.  
  1058.  
  1059. (defvar irc-mode-map nil
  1060.   "The keymap which irc-mode uses.
  1061.  
  1062. Currently set to: \\{irc-mode-map}")
  1063.  
  1064.  
  1065. (make-variable-buffer-local
  1066.  (defvar irc-msg-info-post (if (boundp 'irc-msg-info-post)
  1067.                    irc-msg-info-post
  1068.                  "]")
  1069.    "*String to end an information message with."))
  1070.  
  1071.  
  1072. (make-variable-buffer-local
  1073.  (defvar irc-msg-info-pre (if (boundp 'irc-msg-info-pre)
  1074.                   irc-msg-info-pre
  1075.                 "[")
  1076.    "*String to start an information message with."))
  1077.  
  1078.  
  1079. (make-variable-buffer-local
  1080.  (defvar irc-msg-cont (if (boundp 'irc-msg-cont)
  1081.               irc-msg-cont
  1082.             (make-string 23 (string-to-char " ")))
  1083.    "*The string put first on a continued line."))
  1084.  
  1085.  
  1086. (make-variable-buffer-local
  1087.  (defvar irc-msg-priv (if (boundp 'irc-msg-priv)
  1088.               irc-msg-priv
  1089.             "==%%s%%%ds == ")
  1090.    "*The string put first on a line where a private message begins,
  1091. using TIME and SENDER strings, and EXTRA string."))
  1092.  
  1093.  
  1094. (make-variable-buffer-local
  1095.  (defvar irc-msg-public (if (boundp 'irc-msg-public)
  1096.                 irc-msg-public
  1097.               "-- %s%9s (on %s) -- ")
  1098.    "*The string put first on a line where a public message begins,
  1099. using TIME string, SENDER string and CHANNEL number"))
  1100.  
  1101.  
  1102. (make-variable-buffer-local
  1103.  (defvar irc-msg-sent (if (boundp 'irc-msg-sent)
  1104.               irc-msg-sent
  1105.             "(Message sent to %s)")
  1106.    "*Message displayed after sending a string to the server.
  1107. Contains TYPE (ie \"channel\" or \"person\") and RECEIVER (ie channel name or
  1108. users nick)."))
  1109.  
  1110.  
  1111. (make-variable-buffer-local
  1112.  (defvar irc-msg-wall (if (boundp 'irc-msg-wall)
  1113.               irc-msg-wall
  1114.             "##%s%s ## ")
  1115.    "*The string put first on a line where awrite all (wall) message begins,
  1116. using TIME and SENDER strings."))
  1117.  
  1118.  
  1119. (make-variable-buffer-local
  1120.  (defvar irc-multiple-leave-in-progress nil
  1121.    "Flag saying whether a multiple /LEAVE command is in progress, so that
  1122. irc-parse-channel shouldn't call irc-show-subscribed-channels."))
  1123.  
  1124.  
  1125. (make-variable-buffer-local
  1126.  (defvar irc-nick (or (getenv "IRCNICK") (user-login-name))
  1127.    "*The nickname with which to enter IRC.
  1128. The default value is set from your login name.  Using /NICKNAME changes it."))
  1129.  
  1130.  
  1131. (defconst irc-legal-session-name "^\\*Kiwi-\\([^/]+\\)/\\([0-9]+\\)\\*$"
  1132.   "A regexp describing a legal session-name. (See irc-get-*-from-session-name).
  1133. Two fields are extracted, the first being a host name, and the second a
  1134. TCP port number.")
  1135.  
  1136.  
  1137. (defvar irc-notify-interval 2
  1138.   "*How often to check for people. The time is in minutes.")
  1139.  
  1140.  
  1141. (defvar irc-oops "Oops ... please ignore that."
  1142.   "*The text to send to the original IRC message recipient when using /OOPS.")
  1143.  
  1144.  
  1145. (defconst irc-operator-alist
  1146.   '(("CONNECT" . "connect")        ; Establish links between servers
  1147.     ("KILL" . "kill")            ; Forcibly remove a user
  1148.     ("REHASH" . "rehash")        ; Reread irc.conf
  1149.     ("SQUIT" . "squit")        ; Quit links between servers
  1150.     ("WALL" . "wall"))        ; Send a message to everyone on IRC
  1151.   "As association list of commands which only an IRC Operator can use.
  1152. It is kept as a separate list so that regular users won't wonder how
  1153. come the commands don't work for them.")
  1154.  
  1155.  
  1156. (make-variable-buffer-local
  1157.  (defvar irc-output-character-set (if (boundp 'irc-output-character-set)
  1158.                       irc-output-character-set
  1159.                     (if irc-emacs-knows-ISO8859-1
  1160.                     'ISO-8859-1
  1161.                       'ASCII))
  1162.    "*Specifies whether the Emacs understands just ASCII (seven bit characters),
  1163. ISO-8859/1 (8 bits) or Kanjii (16 bits). The value is one of the following
  1164. atoms: ASCII ISO-8859-1 KANJII"))
  1165.  
  1166.  
  1167. (defvar irc-pop-on-signal 4
  1168.   "*An integer value means to display the *IRC* buffer when a signal is issued.
  1169. The number represents roughly how much of the Emacs screen to use when
  1170. popping up the IRC window if only one window is visible.  The reciprocal
  1171. is used, so a value of 1 causes the window to appear full-screen, 2 makes
  1172. the window half of the screen, 3 makes it one third, et cetera.  If the value
  1173. is not an integer then no attempt is made to show the *IRC* buffer if it
  1174. is not already visible.")
  1175.  
  1176.  
  1177. (make-variable-buffer-local
  1178.  (defvar irc-port (if (boundp 'irc-port)
  1179.               irc-port
  1180.             (let* ((p (getenv "IRCPORT"))
  1181.                (np (and p (string-to-int p))))
  1182.               (if (and (numberp np) (> np 0) (< np 16384)) np 6667)))
  1183.    "*The port on which the IRC server responds.
  1184. Many sites don't have irc as a named service (ie, it has no entry in
  1185. /etc/inetd.conf) so you might have to set this to a number; the most
  1186. common configuration is to have IRC respond on port 6667. If there is
  1187. an enviroment variable called IRCPORT and it's value is nummeric
  1188. between 1 and 16387, that value is used instead."))
  1189.  
  1190.  
  1191. (defvar irc-private-insert nil
  1192.   "*Hook to be used to insert private messages (PRIVMSG) sent to you.")
  1193.  
  1194.  
  1195. (defvar irc-processes nil
  1196.   "All currently open streams to irc-servers are kept in this list.
  1197. It is used so that the \"irc\" function knows whether to start a new process
  1198. by default.")
  1199.  
  1200.  
  1201. (defvar irc-public-insert nil
  1202.   "*Hook to be used to insert public messages (MSG) sent to channel.")
  1203.  
  1204.  
  1205. (make-variable-buffer-local
  1206.  (defvar irc-reply-count 0
  1207.    "Internal Kiwi variable to keep track of number of replies to /LINKS,
  1208. /NAMES, or /WHO."))
  1209.  
  1210.  
  1211. (make-variable-buffer-local
  1212.  (defvar irc-reply-count-interval 1
  1213.    "Internal Kiwi variable to keep track of how many seconds should
  1214. pass at least between each display of irc-reply-count when waiting
  1215. for the reply of a /LINKS, /NAMES, or /WHO to finnish."))
  1216.  
  1217.  
  1218. (make-variable-buffer-local
  1219.  (defvar irc-reply-count-time '(0 0)
  1220.    "Internal Kiwi variable to keep track of en irc-reply-count was displayed
  1221. last."))
  1222.  
  1223.  
  1224. (make-variable-buffer-local
  1225.  (defvar irc-scroll-step (if (boundp 'irc-scroll-step)
  1226.                  irc-scroll-step
  1227.                  nil)
  1228.    "*The scroll step used by irc-insert. Set to non-number to get
  1229. the nice automatic behaivour you get by default."))
  1230.  
  1231.  
  1232. (make-variable-buffer-local
  1233.  (defvar irc-server (if (boundp 'irc-server)
  1234.             irc-server
  1235.               (or (getenv "IRCSERVER") "irc.ludd.luth.se"))
  1236.    "*The name of the internet host running the IRC daemon.
  1237. IRC servers generally restrict which machines can maintain connetions with
  1238. them, so you'll probably have to find a server in your local domain.
  1239. Initiated from enviroment variable IRCSERVER."))
  1240.  
  1241.  
  1242. (make-variable-buffer-local
  1243.  (defvar irc-show-japanese-characters nil
  1244.    "*If nil, replace Kanjii characters in text by a marker like \"Old Kanjii\"
  1245. followed by a list of integers denoting the 16 bit values of the characters.
  1246. If t, enter the text \"as is\" e.i., keep even the ESCape characters.
  1247. If neither nil nor t, enter the text in \"raw\" mode e.i., replace the ESCapes
  1248. by ^[ and insert the resulting text in the buffer.
  1249. The default is nil."))
  1250.  
  1251.  
  1252. (make-variable-buffer-local
  1253.  (defvar irc-signals '((backtalk t)
  1254.                (detect nil)
  1255.                (invite t)
  1256.                (join nil)
  1257.                (nick nil)
  1258.                (private t)
  1259.                (topic nil)
  1260.                (wall t)
  1261.                        (public nil)
  1262.                (user nil))
  1263.    "Events in IRC that should get signalled when they occur.
  1264. Generally the signal is an audible beep.  The value of irc-signals is an
  1265. association list of events recognized by irc-mode and is maintained with
  1266. the /SIGNAL command."))
  1267.  
  1268.  
  1269. (defvar irc-spacebar-pages t
  1270.   "*When this variable is non-nil, the following keys are in effect when
  1271. point is in the output region.
  1272.  
  1273. SPC      scroll-forward    DEL           scroll-backward
  1274. TAB      previous-line     LFD or RET    next-line")
  1275.  
  1276.  
  1277. (defvar irc-time-stamp 5
  1278.   "*How often to insert a time-stamp into *IRC* buffers.
  1279. The first time one is based from the hour the IRC process was started so that
  1280. values which divide evenly into 60 minutes (like the default of 10) will split
  1281. the hour evenly (as in 13:10, 13:20, 13:30, et cetera).  To disable the
  1282. time-stamping set this variable to 0.  This can be set with the /STAMP command.
  1283.  
  1284. The accuracy of the time-stamping can be improved greatly by running
  1285. M-x display-time; with default settings this guarantees that Emacs will have
  1286. some sort of predictable activity every minute.  If display-time is not running
  1287. and the IRC session is idle, the time-stamp can be up to two minutes late.")
  1288.  
  1289. (defvar irc-translation-table-incoming
  1290.   (cond
  1291.    ((and (boundp 'irc-translation-table-incoming)
  1292.      (arrayp irc-translation-table-incoming)
  1293.      (= 256 (length irc-translation-table-incoming)))
  1294.     irc-translation-table-incoming)
  1295.    ((and (boundp 'irc-translation-table-incoming)
  1296.      (symbolp irc-translation-table-incoming)
  1297.      (eq 'scandinavian irc-translation-table-incoming))
  1298.     irc-translation-table-incoming-scandinavian7)
  1299.    (t nil)
  1300.    (t 'scandinavian7))            ;Obsolete default
  1301.   "*Translation table for incoming characters.
  1302. If non-nil, single characters are translated one by one according to
  1303. this table. The table consists of a 256 elements long array, where each
  1304. element is either a string or nil. If the element is nil, the character
  1305. with the corresponding code is dropped, if the element is a string, the
  1306. string is inserted instead of the character.")
  1307.  
  1308. (defvar irc-translation-table-incoming-scandinavian7
  1309.   '["^@"                ;000
  1310.     "^A"                ;001
  1311.     ""                    ;002    ircII kludge
  1312.     "^C"                ;003
  1313.     "^D"                ;004
  1314.     "^E"                ;005
  1315.     "^F"                ;006
  1316.     "^G"                ;007
  1317.     "^H"                ;010
  1318.     "^I"                ;011
  1319.     "^J\n"                ;012
  1320.     "^K"                ;013
  1321.     "^L"                ;014
  1322.     "^M"                ;015
  1323.     "^N"                ;016
  1324.     ""                    ;017    ircII kludge
  1325.     "^P"                ;020
  1326.     "^Q"                ;021
  1327.     "^R"                ;022
  1328.     "^S"                ;023
  1329.     "^T"                ;024
  1330.     "^U"                ;025
  1331.     ""                    ;026    ircII kludge
  1332.     "^W"                ;027
  1333.     "^X"                ;030
  1334.     "^Y"                ;031
  1335.     "^Z"                ;032
  1336.     "^["                ;033
  1337.     "^\\"                ;034
  1338.     "^]"                ;035
  1339.     "^^"                ;036
  1340.     ""                    ;037    ircII kludge
  1341.     " "                    ;040
  1342.     "!"                    ;041
  1343.     "\""                ;042
  1344.     "#"                    ;043
  1345.     "$"                    ;044
  1346.     "%%"                ;045    Need %% to not disturb format.
  1347.     "&"                    ;046
  1348.     "'"                    ;047
  1349.     "("                    ;050
  1350.     ")"                    ;051
  1351.     "*"                    ;052
  1352.     "+"                    ;053
  1353.     ","                    ;054
  1354.     "-"                    ;055
  1355.     "."                    ;056
  1356.     "/"                    ;057
  1357.     "0"                    ;060
  1358.     "1"                    ;061
  1359.     "2"                    ;062
  1360.     "3"                    ;063
  1361.     "4"                    ;064
  1362.     "5"                    ;065
  1363.     "6"                    ;066
  1364.     "7"                    ;067
  1365.     "8"                    ;070
  1366.     "9"                    ;071
  1367.     ":"                    ;072
  1368.     ";"                    ;073
  1369.     "<"                    ;074
  1370.     "="                    ;075
  1371.     ">"                    ;076
  1372.     "?"                    ;077
  1373.     "@"                    ;100
  1374.     "A"                    ;101
  1375.     "B"                    ;102
  1376.     "C"                    ;103
  1377.     "D"                    ;104
  1378.     "E"                    ;105
  1379.     "F"                    ;106
  1380.     "G"                    ;107
  1381.     "H"                    ;110
  1382.     "I"                    ;111
  1383.     "J"                    ;112
  1384.     "K"                    ;113
  1385.     "L"                    ;114
  1386.     "M"                    ;115
  1387.     "N"                    ;116
  1388.     "O"                    ;117
  1389.     "P"                    ;120
  1390.     "Q"                    ;121
  1391.     "R"                    ;122
  1392.     "S"                    ;123
  1393.     "T"                    ;124
  1394.     "U"                    ;125
  1395.     "V"                    ;126
  1396.     "W"                    ;127
  1397.     "X"                    ;130
  1398.     "Y"                    ;131
  1399.     "Z"                    ;132
  1400.     "["                    ;133
  1401.     "\\"                ;134
  1402.     "]"                    ;135
  1403.     "^"                    ;136
  1404.     "_"                    ;137
  1405.     "`"                    ;140
  1406.     "a"                    ;141
  1407.     "b"                    ;142
  1408.     "c"                    ;143
  1409.     "d"                    ;144
  1410.     "e"                    ;145
  1411.     "f"                    ;146
  1412.     "g"                    ;147
  1413.     "h"                    ;150
  1414.     "i"                    ;151
  1415.     "j"                    ;152
  1416.     "k"                    ;153
  1417.     "l"                    ;154
  1418.     "m"                    ;155
  1419.     "n"                    ;156
  1420.     "o"                    ;157
  1421.     "p"                    ;160
  1422.     "q"                    ;161
  1423.     "r"                    ;162
  1424.     "s"                    ;163
  1425.     "t"                    ;164
  1426.     "u"                    ;165
  1427.     "v"                    ;166
  1428.     "w"                    ;167
  1429.     "x"                    ;170
  1430.     "y"                    ;171
  1431.     "z"                    ;172
  1432.     "{"                    ;173
  1433.     "|"                    ;174
  1434.     "}"                    ;175
  1435.     "~"                    ;176
  1436.     "^?"                ;177
  1437.     "\200"                ;200
  1438.     "~"                    ;201 MSDOS
  1439.     "\202"                ;202
  1440.     "\203"                ;203
  1441.     "{"                    ;204 MSDOS
  1442.     "\205"                ;205
  1443.     "}"                    ;206 MSDOS
  1444.     "\207"                ;207
  1445.     "\210"                ;210
  1446.     "\211"                ;211
  1447.     "\212"                ;212
  1448.     "\213"                ;213
  1449.     "\214"                ;214
  1450.     "\215"                ;215
  1451.     "["                    ;216 MSDOS
  1452.     "]"                    ;217 MSDOS
  1453.     "\220"                ;220
  1454.     "\221"                ;221
  1455.     "\222"                ;222
  1456.     "\223"                ;223
  1457.     "|"                    ;224 MSDOS
  1458.     "\225"                ;225
  1459.     "\226"                ;226
  1460.     "\227"                ;227
  1461.     "\230"                ;230
  1462.     "\\"                ;231 MSDOS
  1463.     "^"                    ;232 MSDOS
  1464.     "\233"                ;233
  1465.     "\234"                ;234
  1466.     "\235"                ;235
  1467.     "\236"                ;236
  1468.     "\237"                ;237
  1469.     " "                    ;240
  1470.     "!"                    ;241
  1471.     "c"                    ;242
  1472.     "#"                    ;243
  1473.     "$"                    ;244
  1474.     "Y"                    ;245
  1475.     "|"                    ;246
  1476.     "$"                    ;247
  1477.     "\""                ;250
  1478.     "c"                    ;251
  1479.     "+"                    ;252
  1480.     "<<"                ;253
  1481.     "!"                    ;254
  1482.     "-"                    ;255
  1483.     "R"                    ;256
  1484.     "~"                    ;257
  1485.     "C"                    ;260
  1486.     "+"                    ;261
  1487.     "2"                    ;262
  1488.     "3"                    ;263
  1489.     "'"                    ;264
  1490.     "u"                    ;265
  1491.     "$"                    ;266
  1492.     "-"                    ;267
  1493.     ","                    ;270
  1494.     "1"                    ;271
  1495.     "0"                    ;272
  1496.     ">>"                ;273
  1497.     "?"                    ;274
  1498.     "?"                    ;275
  1499.     "?"                    ;276
  1500.     "?"                    ;277
  1501.     "A"                    ;300
  1502.     "A"                    ;301
  1503.     "A"                    ;302
  1504.     "A"                    ;303
  1505.     "["                    ;304
  1506.     "]"                    ;305
  1507.     "["                    ;306
  1508.     "C"                    ;307
  1509.     "E"                    ;310
  1510.     "@"                    ;311
  1511.     "E"                    ;312
  1512.     "E"                    ;313
  1513.     "I"                    ;314
  1514.     "I"                    ;315
  1515.     "I"                    ;316
  1516.     "I"                    ;317
  1517.     "D"                    ;320
  1518.     "N"                    ;321
  1519.     "O"                    ;322
  1520.     "O"                    ;323
  1521.     "O"                    ;324
  1522.     "O"                    ;325
  1523.     "\\"                ;326
  1524.     "*"                    ;327
  1525.     "\\"                ;330
  1526.     "U"                    ;331
  1527.     "U"                    ;332
  1528.     "U"                    ;333
  1529.     "^"                    ;334
  1530.     "Y"                    ;335
  1531.     "T"                    ;336
  1532.     "ss"                ;337
  1533.     "a"                    ;340
  1534.     "a"                    ;341
  1535.     "a"                    ;342
  1536.     "a"                    ;343
  1537.     "{"                    ;344
  1538.     "}"                    ;345
  1539.     "{"                    ;346
  1540.     "c"                    ;347
  1541.     "e"                    ;350
  1542.     "`"                    ;351
  1543.     "e"                    ;352
  1544.     "e"                    ;353
  1545.     "i"                    ;354
  1546.     "i"                    ;355
  1547.     "i"                    ;356
  1548.     "i"                    ;357
  1549.     "d"                    ;360
  1550.     "n"                    ;361
  1551.     "o"                    ;362
  1552.     "o"                    ;363
  1553.     "o"                    ;364
  1554.     "o"                    ;365
  1555.     "|"                    ;366
  1556.     "/"                    ;367
  1557.     "|"                    ;370
  1558.     "u"                    ;371
  1559.     "u"                    ;372
  1560.     "u"                    ;373
  1561.     "~"                    ;374
  1562.     "y"                    ;375
  1563.     "t"                    ;376
  1564.     "y"]                ;377
  1565.   "*Translation table for incoming characters to translate from ISO 8859-1
  1566. to SIS E47. Also handles some MSDOS characters.")
  1567.  
  1568.  
  1569. (defvar irc-translation-table-incoming-scandinavian8
  1570.   '["^@"                ;000
  1571.     "^A"                ;001
  1572.     ""                    ;002    ircII kludge
  1573.     "^C"                ;003
  1574.     "^D"                ;004
  1575.     "^E"                ;005
  1576.     "^F"                ;006
  1577.     "^G"                ;007
  1578.     "^H"                ;010
  1579.     "^I"                ;011
  1580.     "^J\n"                ;012
  1581.     "^K"                ;013
  1582.     "^L"                ;014
  1583.     "^M"                ;015
  1584.     "^N"                ;016
  1585.     ""                    ;017    ircII kludge
  1586.     "^P"                ;020
  1587.     "^Q"                ;021
  1588.     "^R"                ;022
  1589.     "^S"                ;023
  1590.     "^T"                ;024
  1591.     "^U"                ;025
  1592.     ""                    ;026    ircII kludge
  1593.     "^W"                ;027
  1594.     "^X"                ;030
  1595.     "^Y"                ;031
  1596.     "^Z"                ;032
  1597.     "^["                ;033
  1598.     "^\\"                ;034
  1599.     "^]"                ;035
  1600.     "^^"                ;036
  1601.     ""                    ;037    ircII kludge
  1602.     " "                    ;040
  1603.     "!"                    ;041
  1604.     "\""                ;042
  1605.     "#"                    ;043
  1606.     "$"                    ;044
  1607.     "%%"                ;045    Need %% to not disturb format.
  1608.     "&"                    ;046
  1609.     "'"                    ;047
  1610.     "("                    ;050
  1611.     ")"                    ;051
  1612.     "*"                    ;052
  1613.     "+"                    ;053
  1614.     ","                    ;054
  1615.     "-"                    ;055
  1616.     "."                    ;056
  1617.     "/"                    ;057
  1618.     "0"                    ;060
  1619.     "1"                    ;061
  1620.     "2"                    ;062
  1621.     "3"                    ;063
  1622.     "4"                    ;064
  1623.     "5"                    ;065
  1624.     "6"                    ;066
  1625.     "7"                    ;067
  1626.     "8"                    ;070
  1627.     "9"                    ;071
  1628.     ":"                    ;072
  1629.     ";"                    ;073
  1630.     "<"                    ;074
  1631.     "="                    ;075
  1632.     ">"                    ;076
  1633.     "?"                    ;077
  1634.     "\311"                ;100
  1635.     "A"                    ;101
  1636.     "B"                    ;102
  1637.     "C"                    ;103
  1638.     "D"                    ;104
  1639.     "E"                    ;105
  1640.     "F"                    ;106
  1641.     "G"                    ;107
  1642.     "H"                    ;110
  1643.     "I"                    ;111
  1644.     "J"                    ;112
  1645.     "K"                    ;113
  1646.     "L"                    ;114
  1647.     "M"                    ;115
  1648.     "N"                    ;116
  1649.     "O"                    ;117
  1650.     "P"                    ;120
  1651.     "Q"                    ;121
  1652.     "R"                    ;122
  1653.     "S"                    ;123
  1654.     "T"                    ;124
  1655.     "U"                    ;125
  1656.     "V"                    ;126
  1657.     "W"                    ;127
  1658.     "X"                    ;130
  1659.     "Y"                    ;131
  1660.     "Z"                    ;132
  1661.     "\304"                ;133
  1662.     "\326"                ;134
  1663.     "\305"                ;135
  1664.     "\334"                ;136
  1665.     "_"                    ;137
  1666.     "\351"                ;140
  1667.     "a"                    ;141
  1668.     "b"                    ;142
  1669.     "c"                    ;143
  1670.     "d"                    ;144
  1671.     "e"                    ;145
  1672.     "f"                    ;146
  1673.     "g"                    ;147
  1674.     "h"                    ;150
  1675.     "i"                    ;151
  1676.     "j"                    ;152
  1677.     "k"                    ;153
  1678.     "l"                    ;154
  1679.     "m"                    ;155
  1680.     "n"                    ;156
  1681.     "o"                    ;157
  1682.     "p"                    ;160
  1683.     "q"                    ;161
  1684.     "r"                    ;162
  1685.     "s"                    ;163
  1686.     "t"                    ;164
  1687.     "u"                    ;165
  1688.     "v"                    ;166
  1689.     "w"                    ;167
  1690.     "x"                    ;170
  1691.     "y"                    ;171
  1692.     "z"                    ;172
  1693.     "\344"                ;173
  1694.     "\366"                ;174
  1695.     "\345"                ;175
  1696.     "\374"                ;176
  1697.     "^?"                ;177
  1698.     "\200"                ;200
  1699.     "\374"                ;201 MSDOS
  1700.     "\202"                ;202
  1701.     "\203"                ;203
  1702.     "\344"                ;204 MSDOS
  1703.     "\205"                ;205
  1704.     "\345"                ;206 MSDOS
  1705.     "\207"                ;207
  1706.     "\210"                ;210
  1707.     "\211"                ;211
  1708.     "\212"                ;212
  1709.     "\213"                ;213
  1710.     "\214"                ;214
  1711.     "\215"                ;215
  1712.     "\305"                ;216 MSDOS
  1713.     "\304"                ;217 MSDOS
  1714.     "\220"                ;220
  1715.     "\221"                ;221
  1716.     "\222"                ;222
  1717.     "\223"                ;223
  1718.     "\366"                ;224 MSDOS
  1719.     "\225"                ;225
  1720.     "\226"                ;226
  1721.     "\227"                ;227
  1722.     "\230"                ;230
  1723.     "\326"                ;231 MSDOS
  1724.     "\334"                ;232 MSDOS
  1725.     "\233"                ;233
  1726.     "\234"                ;234
  1727.     "\235"                ;235
  1728.     "\236"                ;236
  1729.     "\237"                ;237
  1730.     "\240"                ;240
  1731.     "\241"                ;241
  1732.     "\242"                ;242
  1733.     "\243"                ;243
  1734.     "\244"                ;244
  1735.     "\245"                ;245
  1736.     "\246"                ;246
  1737.     "\247"                ;247
  1738.     "\250"                ;250
  1739.     "\251"                ;251
  1740.     "\252"                ;252
  1741.     "\253"                ;253
  1742.     "\254"                ;254
  1743.     "\255"                ;255
  1744.     "\256"                ;256
  1745.     "\257"                ;257
  1746.     "\260"                ;260
  1747.     "\261"                ;261
  1748.     "\262"                ;262
  1749.     "\263"                ;263
  1750.     "\264"                ;264
  1751.     "\265"                ;265
  1752.     "\266"                ;266
  1753.     "\267"                ;267
  1754.     "\270"                ;270
  1755.     "\271"                ;271
  1756.     "\272"                ;272
  1757.     "\273"                ;273
  1758.     "\274"                ;274
  1759.     "\275"                ;275
  1760.     "\276"                ;276
  1761.     "\277"                ;277
  1762.     "\300"                ;300
  1763.     "\301"                ;301
  1764.     "\302"                ;302
  1765.     "\303"                ;303
  1766.     "\304"                ;304
  1767.     "\305"                ;305
  1768.     "\306"                ;306
  1769.     "\307"                ;307
  1770.     "\310"                ;310
  1771.     "\311"                ;311
  1772.     "\312"                ;312
  1773.     "\313"                ;313
  1774.     "\314"                ;314
  1775.     "\315"                ;315
  1776.     "\316"                ;316
  1777.     "\317"                ;317
  1778.     "\320"                ;320
  1779.     "\321"                ;321
  1780.     "\322"                ;322
  1781.     "\323"                ;323
  1782.     "\324"                ;324
  1783.     "\325"                ;325
  1784.     "\326"                ;326
  1785.     "\327"                ;327
  1786.     "\330"                ;330
  1787.     "\331"                ;331
  1788.     "\332"                ;332
  1789.     "\333"                ;333
  1790.     "\334"                ;334
  1791.     "\335"                ;335
  1792.     "\336"                ;336
  1793.     "\337"                ;337
  1794.     "\340"                ;340
  1795.     "\341"                ;341
  1796.     "\342"                ;342
  1797.     "\343"                ;343
  1798.     "\344"                ;344
  1799.     "\345"                ;345
  1800.     "\346"                ;346
  1801.     "\347"                ;347
  1802.     "\350"                ;350
  1803.     "\351"                ;351
  1804.     "\352"                ;352
  1805.     "\353"                ;353
  1806.     "\354"                ;354
  1807.     "\355"                ;355
  1808.     "\356"                ;356
  1809.     "\357"                ;357
  1810.     "\360"                ;360
  1811.     "\361"                ;361
  1812.     "\362"                ;362
  1813.     "\363"                ;363
  1814.     "\364"                ;364
  1815.     "\365"                ;365
  1816.     "\366"                ;366
  1817.     "\367"                ;367
  1818.     "\370"                ;370
  1819.     "\371"                ;371
  1820.     "\372"                ;372
  1821.     "\373"                ;373
  1822.     "\374"                ;374
  1823.     "\375"                ;375
  1824.     "\376"                ;376
  1825.     "\377"]                ;377
  1826.   "*Translation table for incoming characters to translate from SIS E47
  1827. to ISO 8859-1. Also handles some MSDOS characters.")
  1828.  
  1829.  
  1830. (make-variable-buffer-local
  1831.  (defvar irc-userinfo (if (boundp 'irc-userinfo)
  1832.               irc-userinfo
  1833.               nil)
  1834.    "*If non-nil, a user settable string to be replied with when the client is
  1835. queried by some other user."))
  1836.  
  1837.  
  1838.  
  1839.  
  1840. ;;; Macros
  1841. ;;;
  1842. (defmacro subfield (str n)
  1843.   "Return a substring of STR. The substring is field N, as used in the latest
  1844. string-match."
  1845.   (` (if (and (numberp (match-beginning (, n)))
  1846.           (numberp (match-end (, n))))
  1847.      (substring (, str) (match-beginning (, n)) (match-end (, n)))
  1848.      "")))
  1849.  
  1850.  
  1851. ;;; Handle host names.
  1852. ;;;
  1853. ;;; First a constant regular expression string matching only host names.
  1854. ;;;
  1855. (defconst irc-hostname "^[A-Za-z][A-Za-z0-9.-.---]*$"
  1856.   "A regexp matching a string if and only if the string is a hostname.")
  1857.  
  1858.  
  1859. (defconst irc-hostname-complement "\\(^\\.\\|\\.$\\)")
  1860.  
  1861.  
  1862. ;;; See RFC 952
  1863. (defconst irc-hostname-chars '(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m
  1864.                    ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
  1865.                    ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M
  1866.                    ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
  1867.                    ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?- ?.))
  1868.  
  1869.  
  1870. (defun irc-is-hostname (name)
  1871.   "Returns t if the NAME is a hostname, nil else.
  1872. This functions is more paranoid (Hello RFC 952!) than the IRC servers."
  1873.   (and (stringp name)
  1874.        (not (not (and (string-match irc-hostname name)
  1875.               (string-match "\\." name)
  1876.               (not (string-match (regexp-quote irc-hostname-complement)
  1877.                      name)))))))
  1878.  
  1879.  
  1880. (defun irc-is-nickname (name)
  1881.   "Returns t if the NAME is a valid nick name in IRC."
  1882.   (and (numberp (string-match (concat "^[]A-Z[\\^_a-z{|}~`]"
  1883.                       "[]A-Z0-9[\\_^a-z{|}~`-`---]*$")
  1884.                   name))
  1885.        (not (numberp (string-match "\n" name)))))
  1886.  
  1887.  
  1888. (defun irc-is-channelname (name)
  1889.   "Returns t if NAME is a valid channel identification."
  1890.   (or (and (irc-server-has-multijoinable-channels)
  1891.        (or (= ?# (aref name 0))
  1892.            (= ?& (aref name 0)))
  1893.        (irc-is-named-channel name))
  1894.       (and (irc-server-has-non-numeric-channel-names)
  1895.        (= ?+ (aref name 0))
  1896.        (irc-is-named-channel name))
  1897.       (and (numberp (string-match "^ *-?[0-9]+ *$" name))
  1898.        (irc-is-named-channel (concat "+" name)))))
  1899.  
  1900.  
  1901. (defun irc-is-broadcastname (name)
  1902.   "Return t if NAME is a valid broadcast address, ie is a server- or hostname
  1903. containing wildcards prepended by $ (server) or # (host). Broadcasts came at
  1904. the same time as #channels."
  1905.   (and (irc-server-has-multijoinable-channels)
  1906.        (or (= ?$ (aref name 0)) (= ?# (aref name 0)))))
  1907.  
  1908.  
  1909. (defun irc-is-named-channel (name)
  1910.   "Return t if NAME is a valid nummeric channel identification."
  1911.   (or (and (irc-server-has-multijoinable-channels)
  1912.        (numberp (string-match "^[&#+][]/a-zA-Z#+{}[^~()*!@.,0-9_-_---]*$"
  1913.                   name)))
  1914.       (and (irc-server-has-non-numeric-channel-names)
  1915.        (numberp (string-match "^+[]/a-zA-Z+{}[^~()*!@.,0-9_-_---]*$"
  1916.                   name)))))
  1917.  
  1918.  
  1919. (defun irc-is-multijoinable-channel (channel)
  1920.   "True if CHANNEL is a multijoinable channel, ie a channel one can listen
  1921. to along several other multijoinable channels. This feature was introduced in
  1922. server version 2.6."
  1923.   (and (stringp channel)
  1924.        (or (= (aref channel 0) ?#)
  1925.        (= (aref channel 0) ?&))))
  1926.  
  1927.  
  1928. (defun irc-is-receiver (obj)
  1929.   "True if STR could be either a nick or channel name.
  1930. If user is an enabled irc operator, broadcast addresses are OK too."
  1931.   (or (string= "*" obj)
  1932.       (irc-is-nickname obj)
  1933.       (and (string-match "^\\([^@]+\\)@\\([^@]+\\)$" obj)
  1934.        (let ((pre (subfield obj 1))
  1935.          (post (subfield obj 2)))
  1936.          (and (irc-is-nickname pre)
  1937.           (irc-is-hostname post))))
  1938.       (irc-is-channelname obj)
  1939.       (and irc-operator (irc-is-broadcastname obj))))
  1940.  
  1941.  
  1942. (defun irc-format-channel (channel &optional width)
  1943.   "Format a CHANNEL identification (name, number or * (ie private)) to be left
  1944. justified in a 15 character wide field. Ie make what the format string %-15s
  1945. SHOULD do. If the channel equals irc-channel, ie the current channel, it is
  1946. postpended with a %.
  1947.  
  1948. Arguments are a string with the channel ID, and optional a number saying how
  1949. wide the resulting string should be at least. If none is given, 15 is used as
  1950. the default."
  1951.   (let* ((w (max 0 (or (and (numberp width) width) 15)))
  1952.      (isnamed (irc-is-named-channel channel))
  1953.      (c (cond ((string= "*" channel) "Private")
  1954.           ((string= channel irc-channel) (concat channel "%"))
  1955.           (t channel)))
  1956.      (rpad (make-string (max 0 (- w (length c))) ? )))
  1957.     (concat c rpad)))
  1958.  
  1959.  
  1960. (defun irc-extract-hostname (s)
  1961.   "Extract the hostname part from the STRING, ignoring a trailing comment.
  1962. The string doesn't start with a host name, return nil."
  1963.   (let ((i 0)
  1964.     (len (length s)))
  1965.     (while (and (< i len)
  1966.         (memq (string-to-char (substring s i))
  1967.               irc-hostname-chars))
  1968.       (setq i (1+ i)))
  1969.     (if (irc-is-hostname (substring s 0 i))
  1970.     (substring s 0 i)
  1971.     nil)))
  1972.  
  1973.  
  1974. (defun irc-extract-hosts (path)
  1975.   "Extract and remember the different hosts mentioned in the path string,
  1976. \"h1!h2!h3!x\" where x is either a host or a nick name."
  1977.   (let* ((first-host (irc-extract-hostname path))
  1978.      (first-! (string-match "!" path))
  1979.      (len (length first-host)))
  1980.     (cond ((string= path "") nil)
  1981.       ((and (not first-host) first-!)
  1982.        (irc-extract-hosts (substring path (1+ first-!))))
  1983.       ((not first-host) nil)
  1984.       (t (irc-extract-hosts (substring path len))))))
  1985.  
  1986. ;; keymap
  1987. ;; what i tend to like for keys might be very different from what most people
  1988. ;; find useful; in fact i tend to type the /COMMANDs more than use any bindings
  1989.  
  1990. ;; there are more things bound here just so people can see the different
  1991. ;; things available to them
  1992. (or irc-mode-map
  1993.     (progn
  1994.       (setq irc-mode-map (make-keymap))
  1995.       (define-key irc-mode-map "\C-j"        'irc-process-input)
  1996.       (define-key irc-mode-map "\C-m"        'irc-process-input)
  1997.       (define-key irc-mode-map "\C-i"        'irc-tab)
  1998.       (define-key irc-mode-map "\C-c\C-a"    'irc-execute-alias)
  1999.       (define-key irc-mode-map "\C-c\C-c"    'irc-execute-names)
  2000.       (define-key irc-mode-map "\C-c\C-h"    'irc-execute-help)
  2001.       (define-key irc-mode-map "\C-c\C-i"    'irc-execute-invite)
  2002.       (define-key irc-mode-map "\C-c\C-j"    'irc-execute-join)
  2003.       (define-key irc-mode-map "\C-c\C-k"    'irc-execute-kill)
  2004.       (define-key irc-mode-map "\C-c\C-l"    'irc-execute-list)
  2005.       (define-key irc-mode-map "\C-c\C-m"    'irc-history-menu)
  2006.       (define-key irc-mode-map "\C-c\C-n"    'irc-history-next)
  2007.       (define-key irc-mode-map "\C-c\C-o"    'irc-execute-oops)
  2008.       (define-key irc-mode-map "\C-c\C-p"    'irc-history-prev)
  2009.       (define-key irc-mode-map "\C-c\C-q"    'irc-execute-quote)
  2010.       (define-key irc-mode-map "\C-c\C-r"    'irc-execute-redirect)
  2011.       (define-key irc-mode-map "\C-c\C-s"    'irc-execute-squit)
  2012.       (define-key irc-mode-map "\C-c\C-t"    'irc-execute-topic)
  2013.       (define-key irc-mode-map "\C-c\C-u"    'irc-kill-input)
  2014.       (define-key irc-mode-map "\C-c\C-v"    'irc-execute-version)
  2015.       (define-key irc-mode-map "\C-c\C-w"    'irc-execute-who)
  2016.       (define-key irc-mode-map "\C-c\C-?"    'irc-kill-input)
  2017.       ;; it's nice to bind to a key while in development, but regular users
  2018.       ;; wonder about it in production.
  2019.       ;; (define-key irc-mode-map "\C-c " 'irc-pong)
  2020.       (define-key irc-mode-map "\C-c#" 'irc-execute-lusers)
  2021.       (define-key irc-mode-map "\C-c=" 'irc-execute-memberships)
  2022.       (define-key irc-mode-map "\C-c?" 'describe-mode)
  2023.       (define-key irc-mode-map "\C-ca" 'irc-execute-admin)
  2024.       (define-key irc-mode-map "\C-cc" 'irc-execute-connect)
  2025.       (define-key irc-mode-map "\C-cf" 'irc-execute-finger)
  2026.       (define-key irc-mode-map "\C-ci" 'irc-execute-info)
  2027.       (define-key irc-mode-map "\C-ck" 'irc-execute-quit)
  2028.       (define-key irc-mode-map "\C-cl" 'irc-execute-links)
  2029.       (define-key irc-mode-map "\C-cm" 'irc-execute-mode)
  2030.       (define-key irc-mode-map "\C-cn" 'irc-execute-news)
  2031.       (define-key irc-mode-map "\C-co" 'irc-execute-oper)
  2032.       (define-key irc-mode-map "\C-cp" 'irc-yank-prev-command)
  2033.       (define-key irc-mode-map "\C-cq"    'irc-execute-leave)
  2034.       (define-key irc-mode-map "\C-cs" 'irc-execute-summon)
  2035.       (define-key irc-mode-map "\C-ct" 'irc-execute-trace)
  2036.       (define-key irc-mode-map "\C-cu" 'irc-execute-users)
  2037.       (define-key irc-mode-map "\C-cv" 'irc-version)
  2038.       (define-key irc-mode-map "\C-cw" 'irc-execute-whois)
  2039.       (define-key irc-mode-map "\C-?"  'irc-del-backward-char)
  2040.       ;; make any self-inserting keys call irc-self-insert
  2041.       (mapcar (function
  2042.                (lambda (key)
  2043.         (define-key irc-mode-map key 'irc-self-insert)))
  2044.           (append
  2045.            (where-is-internal 'self-insert-command nil nil)
  2046.            '(" " "!" "\"" "#" "$" "%" "&" "'"
  2047.          "(" ")" "*" "+" "," "-" "." "/"
  2048.          "0" "1" "2" "3" "4" "5" "6" "7"
  2049.          "8" "9" ":" ";" "<" "=" ">" "?"
  2050.          "@" "A" "B" "C" "D" "E" "F" "G"
  2051.          "H" "I" "J" "K" "L" "M" "N" "O"
  2052.          "P" "Q" "R" "S" "T" "U" "V" "W"
  2053.          "X" "Y" "Z" "[" "\\" "]" "^" "_"
  2054.          "`" "a" "b" "c" "d" "e" "f" "g"
  2055.          "h" "i" "j" "k" "l" "m" "n" "o"
  2056.          "p" "q" "r" "s" "t" "u" "v" "w"
  2057.          "x" "y" "z" "{" "|" "}" "~")))))
  2058.  
  2059. ;; filters (mostly irc-parse-*)
  2060. ;; Filtering of server messages from reception to insertion in the buffer
  2061. ;; are all done on this page.  In particular, if a new server message has
  2062. ;; to be dealt with, it should be added in the irc-parse-server-msg function.
  2063. (defun irc-filter (proc str)
  2064.   "Filtering procedure for IRC server messages.
  2065. It waits until everything up to a newline is accumulated before handing the
  2066. string over to irc-parse-server-msg to be processed.  If irc-pop-on-signal
  2067. is an integer and a signal is issued then the *IRC* buffer will be displayed.
  2068.  
  2069. Unless irc-maximum-size is zero or negative, truncate the Kiwi buffer to
  2070. be no larger than irc-maximum-size. If it is larger, truncate it to
  2071. the size irc-minimum-size."
  2072.   (let* ((ibuf (process-buffer proc))
  2073.          bell irc-mark-to-point new-point old-irc-mark win)
  2074.     (save-excursion
  2075.       (set-buffer ibuf)
  2076.       ;; still can't tell why i need this; sure, i probably change point
  2077.       ;; in ibuf.  but so what?  set-window-point should clean up after that.
  2078.       ;; it works with it though and not without it, so it stays.
  2079.       (save-excursion 
  2080.     ;; trim buffer if needed
  2081.     (if (> irc-maximum-size 0)
  2082.         (irc-truncate-buffer irc-maximum-size irc-minimum-size))
  2083.         (setq irc-mark-to-point   ; so we can restore relative position later
  2084.               (- (point) (setq old-irc-mark (goto-char irc-mark)))
  2085.               ;; just glue str to the end of any partial line that's there
  2086.               irc-scratch (concat irc-scratch str))
  2087.         ;; see if it is time for a message
  2088.         (irc-check-time)
  2089.         (while (string-match "\n" irc-scratch) ; do as many lines as possible
  2090.           ;; first use irc-scratch for the dp returned by irc-parse-server-msg
  2091.           (setq irc-scratch (irc-parse-server-msg irc-scratch)
  2092.         bell (cdr irc-scratch) ; issue a signal?
  2093.                 ;; now irc-scratch is what it was, minus the line parsed
  2094.                 irc-scratch (car irc-scratch))
  2095.           (if bell
  2096.           (progn
  2097.         ;; issue a signal; no need to trash someone's kbd-macro over it
  2098.         (ding 'no-terminate)
  2099.         (irc-minibuffer-message "%sBell in %s%s"
  2100.                     irc-msg-info-pre
  2101.                     (buffer-name ibuf)
  2102.                     irc-msg-info-post))))
  2103.         ;; if point was in front of the irc-mark, new-point is figured relative
  2104.         ;; to the old mark, otherwise it is relative to the new one
  2105.         (setq new-point (+ (if (< irc-mark-to-point 0) old-irc-mark irc-mark)
  2106.                            irc-mark-to-point))))
  2107.     ;; update point based on whether the buffer is visible
  2108.     ;; we have a real problem here if there is more than one window displaying
  2109.     ;; the process-buffer and the user is not in the first canonical one.
  2110.     ;; i haven't yet determined a nice way to solve this
  2111.     (if (setq win (if (eq (window-buffer) ibuf)    ;930224/PS: Use selected
  2112.               (selected-window)    ; window if it shows that buffer.
  2113.               (get-buffer-window ibuf)))
  2114.     (set-window-point win new-point)
  2115.     (save-excursion (set-buffer ibuf) (goto-char new-point)))
  2116.     ;; if *IRC* isn't visible, a bell was issued and irc-pop-on-signal is an
  2117.     ;; integer then show the buffer.
  2118.     (if (and (integerp irc-pop-on-signal) bell (not win))
  2119.     (progn
  2120.       (setq win (selected-window))
  2121.       (if (/= (irc-count-windows 'no-mini) 1)
  2122.           (display-buffer ibuf) ;don't futz with sizes if more than 1 win's
  2123.           ;; we might be in the mininbuffer at the moment, so insure that
  2124.           ;; this happens starting in the current regular window
  2125.           (select-window (next-window win 'no-mini))
  2126.           ;; full screen doesn't get handled well by the algorithm
  2127.           ;; for the rest
  2128.           (if (= irc-pop-on-signal 1)
  2129.           (set-window-buffer (selected-window) ibuf)
  2130.           (split-window nil
  2131.                 (if (fboundp 'frame-height)
  2132.                     (- (frame-height)
  2133.                        (/ (frame-height) irc-pop-on-signal))
  2134.                   (- (screen-height)
  2135.                      (/ (screen-height) irc-pop-on-signal))))
  2136.           (display-buffer ibuf)
  2137.           ;; perhaps we need to go back to the minibuffer
  2138.           (select-window win)))))))
  2139.  
  2140.  
  2141. (defun irc-string-display-length (str)
  2142.   "Return the number of display positions a string would take when
  2143. being displayed by GNU-emacs. A character can be displayed in 1, 2 or
  2144. 4 positions. Also a TAB can be 1 to 8 positions wide.
  2145.  
  2146. This function is pessimistic, and will rather return a too large count than a
  2147. too small."
  2148.   (let ((len 0)
  2149.     (i (length str))
  2150.     (x 0))
  2151.     (while (> i 0)
  2152.       (setq i (1- i)
  2153.         x (+ x (let ((c (aref i str)))
  2154.              (cond
  2155.                ((= c \t) 8)    ;TAB.
  2156.                ((or (< c ?\040) (= c ?\177)) ;Normal CNTRL character.
  2157.             (if ctl-arrow 2 4)) ;^X or \030 notation.
  2158.                ((< c ?\177) 1) ;Regular character.
  2159.                ((< c ?\240) 4) ;Eight bit "CNTRL" chararacter.
  2160.                ((< c ?\400)
  2161.             (cond ((eq irc-output-character-set 'ASCII) 4)
  2162.                   ((eq irc-output-character-set 'ISO-8859-1) 1)
  2163.                   (t 4)))
  2164.                (t 4))))))
  2165.     x))
  2166.  
  2167.  
  2168. (defun irc-clean-up-message (str)
  2169.   "Exchange all \"%\" with \"%%\" in STR. Also exchange CNTRL/X in STR
  2170. with ^X. Substitute a ^B for CNTRL/B (which is used by ircII to togle the
  2171. boldness of text) if irc-drop-ircII-text-kludge-control-characters is true,
  2172. or else drop the character. As a further kudo, replace japanese characters
  2173. coded with JIS etc unless irc-show-japanese-characters is nil."
  2174.   (let* ((clean "")
  2175.      (dirty-chars (concat "%"
  2176.                   "\000\001\002\003\004\005\006\007"
  2177.                   "\010\011\012\013\014\015\016\017"
  2178.                   "\020\021\022\023\024\025\026\027"
  2179.                   "\030\031\032\033\034\035\036\037"
  2180.  
  2181.                   "\177"
  2182.                   
  2183.                   "\200\201\202\203\204\205\206\207"
  2184.                   "\210\211\212\213\214\215\216\217"
  2185.                   "\220\221\222\223\224\225\226\227"
  2186.                   "\230\231\232\233\234\235\236\237"
  2187.  
  2188.                   (if irc-emacs-knows-ISO8859-1
  2189.                   ""
  2190.                   (concat "\240\241\242\243\244\245\246\247"
  2191.                       "\250\251\252\253\254\255\256\257"
  2192.                       "\260\261\262\263\264\265\266\267"
  2193.                       "\270\271\272\273\274\275\276\277"
  2194.                       "\300\301\302\303\304\305\306\307"
  2195.                       "\310\311\312\313\314\315\316\317"
  2196.                       "\320\321\322\323\324\325\326\327"
  2197.                       "\330\331\332\333\334\335\336\337"
  2198.                       "\340\341\342\343\344\345\346\347"
  2199.                       "\350\351\352\353\354\355\356\357"
  2200.                       "\360\361\362\363\364\365\366\367"
  2201.                       "\370\371\372\373\374\375\376\377"))
  2202.                   ""))
  2203.      (dirty (concat "[" dirty-chars "]"))
  2204.      (non-dirty (concat "[^" dirty-chars "]")))
  2205.     (if (symbolp irc-translation-table-incoming)
  2206.     (cond ((eq 'scandinavian7 irc-translation-table-incoming)
  2207.            (setq irc-translation-table-incoming
  2208.              irc-translation-table-incoming-scandinavian7))
  2209.           ((eq 'scandinavian8 irc-translation-table-incoming)
  2210.            (setq irc-translation-table-incoming
  2211.              irc-translation-table-incoming-scandinavian8))))
  2212.     (while (or (string-match dirty str)
  2213.            (and irc-translation-table-incoming
  2214.             (string< "" str)))
  2215.       (let ((split (cond ((and (or (eq irc-show-japanese-characters t)
  2216.                    (eq irc-show-japanese-characters nil))
  2217.                    (string-match (concat
  2218.                           "^ ?\033$\\([@AB]\\)\\([^\033]*"
  2219.                           "\\)\033\\([()]. ?\\)")
  2220.                          str))
  2221.               (cond
  2222.                 ((eq irc-show-japanese-characters t)
  2223.                  (let* ((pre (subfield str 1))
  2224.                     (msg (subfield str 2))
  2225.                     (trail (subfield str 3)))
  2226.                  (cons (concat "\033$"
  2227.                        pre
  2228.                        (irc-clean-up-message msg)
  2229.                        trail))
  2230.                    (substring str (match-end 0))))
  2231.                 ((eq irc-show-japanese-characters nil)
  2232.                  (let ((msgend (match-end 0))
  2233.                    (type (substring str
  2234.                             (match-beginning 1)
  2235.                             (match-end 1))))
  2236.                    (cons (concat irc-msg-info-pre
  2237.                          (cond ((string= type "@")
  2238.                             "Old Kanjii: ")
  2239.                            ((string= type "A")
  2240.                             "Probaly chinese: ")
  2241.                            ((string= type "B")
  2242.                             "Modern Kanjii: ")
  2243.                            (t "Unkown 16-bit: "))
  2244.                          (irc-clean-up-message
  2245.                           (irc-translate-kanji
  2246.                            (substring str
  2247.                               (match-beginning 2)
  2248.                               (match-end 2))))
  2249.                          irc-msg-info-post
  2250.                          " ")
  2251.                      (substring str msgend))))
  2252.                 (t (irc-insert (concat "%%Bug in japanese part of"
  2253.                            " irc-clean-up-message."))
  2254.                    (cons (substring str 0 (match-end 0))
  2255.                      (substring str (match-end 0))))))
  2256.              ((not (null irc-translation-table-incoming))
  2257.               (cons (aref irc-translation-table-incoming
  2258.                       (aref str 0))
  2259.                 (substring str 1)))
  2260.              ((and (>= (aref str 0) ?\200) ;8 bit?
  2261.                    (or (< (aref str 0) ?\240)
  2262.                    (not (eq irc-output-character-set
  2263.                         'ISO-8859-1))))
  2264.               (cons (concat (format "\\%o" (aref str 0)))
  2265.                 (substring str 1)))
  2266.              ((string-match (concat "^" non-dirty "*%") str)
  2267.               (cons (concat (substring str 0 (1- (match-end 0)))
  2268.                     "%%")
  2269.                 (substring str (match-end 0))))
  2270.              ((= (aref str 0) ?\t)
  2271.               (cons "^I" (substring str 1)))
  2272.              ((= (aref str 0) ?\177)
  2273.               (cons "^?" (substring str 1)))
  2274.              ((and irc-drop-ircII-text-kludge-control-characters
  2275.                    (irc-member-general (aref str 0)
  2276.                            '(?\002 ?\017 ?\026 ?\037)
  2277.                            '=))
  2278.               (cons "" (substring str 1)))
  2279.              ((and (>= (aref str 0) ?\000)
  2280.                    (<= (aref str 0) ?\037))
  2281.               (cons
  2282.                (concat "^" (char-to-string (+ ?@ (aref str 0))))
  2283.                (substring str 1)))
  2284.              ((string-match (concat "^" non-dirty "+") str)
  2285.               (cons (substring str
  2286.                        (match-beginning 0)
  2287.                        (match-end 0))
  2288.                 (substring str (match-end 0))))
  2289.              (t (cons (substring str 0 1) (substring str 1))))))
  2290.     (setq clean (concat clean (car split))
  2291.           str (cdr split))))
  2292.     (concat clean str)))
  2293.  
  2294.  
  2295. (defun irc-translate-kanji (str)
  2296.   "Translate a japanese Kanjicoded message in STR into nummeric codes.
  2297. Just exchange every two octet sequence into their nummeric codes."
  2298.   (let ((retval ""))
  2299.     (while (>= (length str) 2)
  2300.       (let ((double (+ (* (aref str 0) 256) (aref str 1))))
  2301.     (setq retval (format "%s%s%d"
  2302.                  retval
  2303.                  (if (string= "" retval) "" " ")
  2304.                  double)
  2305.           str (substring str 2))))
  2306.     (if (> (length str) 0)
  2307.     (format "ODD %d" (aref str 0))
  2308.     retval)))
  2309.  
  2310.  
  2311. (defun irc-parse-server-msg (str)
  2312.   "Take the first line from STR and pass it on to the appropriate irc-parse-*
  2313. function.  If the message is one which irc-mode doesn't recognize, just display
  2314. it as the raw server message.
  2315.  
  2316. It returns a dotted-pair whose car is the remainder of STR after the first
  2317. newline and whose cdr is either t or nil, indicating whether a signal should
  2318. be issued."
  2319.   (let ((n (string-match "\r" str)))
  2320.     (while n
  2321.       (setq str (concat (substring str 0 n)
  2322.             (substring str (1+ n)))
  2323.         n (string-match "\r" str))))
  2324.   (let* ((nl (string-match "\n" str)) 
  2325.      (eol (or nl (length str)))
  2326.      (line (substring str 0 eol))
  2327.      (dummy (irc-log-in-debug-buffer (concat "  " line)))
  2328.      (new (or (string-match "^:\\([^! :]+\\)!\\([^@ :]+\\)@\\([^ :]+\\)"
  2329.                 line)))
  2330.      (triple (if new (cons (subfield line 1)
  2331.                    (cons (subfield line 2)
  2332.                      (subfield line 3)))))
  2333.      (rest (if new (substring line (match-end 0))))
  2334.      (irc-userhost (if new
  2335.                (format " <%s@%s>"
  2336.                    (car (cdr triple)) (cdr (cdr triple)))
  2337.                ""))
  2338.      (line (if new (format ":%s%s" (car triple) rest) line))
  2339.      (last-NOTICE-rcv irc-last-NOTICE-rcv)
  2340.      (last-NOTICE-src irc-last-NOTICE-src))
  2341.     (if (not nl)
  2342.     (irc-insert "%%WARNING: got incomplete line from server! No newline."))
  2343.     (setq irc-last-NOTICE-rcv ""
  2344.       irc-last-NOTICE-src "")
  2345.     (if (not (boundp 'irc-count-incoming-messages))
  2346.     (progn
  2347.       (message "?Kiwi: Variable irc-count-incoming-messages unbound")
  2348.       (set (make-local-variable 'irc-count-incoming-messages) nil)))
  2349.     (if (not (numberp irc-count-incoming-messages))
  2350.     (progn
  2351.       (message "?Kiwi: irc-count-incoming-messages=%d, not a number"
  2352.            irc-count-incoming-messages)
  2353.       (setq irc-count-incoming-messages 0)))
  2354.     (setq line (irc-lowlevel-dequote line)
  2355.       irc-count-incoming-messages (1+ irc-count-incoming-messages))
  2356.     (if (= 0 (% irc-count-incoming-messages 50))
  2357.     (irc-send (concat "PONG " irc-server)))
  2358.     (cons
  2359.      ;; the part of str not being parsed.
  2360.      (substring str (1+ (string-match "\n" str)))
  2361.      (cond
  2362.        ;; each function here should return t or nil indicating whether
  2363.        ;; to issue a signal.  Some of these regexps are fugly because
  2364.        ;; of inconsistent protocol use by the servers.  Fortunately Jarkko
  2365.        ;; is fixing that.
  2366.        ((string-match "^ *$" line) nil)    ;Ignore empty lines.
  2367.        ((string-match "^:[^: ]+ +MSG " line) (irc-parse-public line))
  2368.        ((string-match "^:[^: ]+ +CHANNEL " line) (irc-parse-channel line))
  2369.        ((string-match "^:[^ ]+ +JOIN " line) (irc-parse-channel line))
  2370.        ((string-match "^:[^: ]+ +PART " line) (irc-parse-channel line))
  2371.        ((string-match "^:[^: ]+ +INVITE " line) (irc-parse-invite line))
  2372.        ((string-match "^:[^: ]+ +NICK " line) (irc-parse-nick line))
  2373.        ((string-match "^:[^: ]+ +WALL " line) (irc-parse-wall line))
  2374.        ((string-match "^:[^: ]+ +WALLOPS " line) (irc-parse-wallops line))
  2375.        ((string-match "^:[^: ]+ +QUIT " line) (irc-parse-quit line))
  2376.        ((string-match "^:[^: ]+ +KICK " line) (irc-parse-kick line))
  2377.        ((string-match "^:[^: ]+ +KILL " line) (irc-parse-kill line))
  2378.        ((string-match "^:[^: ]+ +TOPIC " line) (irc-parse-topic line))
  2379.        ((string-match "^:[^: ]+ +MODE " line) (irc-parse-mode-reply line))
  2380.        ((string-match "^:[^: ]+ +[023][0-9][0-9][^0-9]" line)
  2381.     (irc-parse-RPL line))
  2382.        ((string-match "^:[^: ]+ +[4-5][0-9][0-9][^0-9]" line)
  2383.     (irc-parse-ERR line))
  2384.        ((string-match (concat "^\\(:?\\)\\([^: ]*\\) *NOTICE"
  2385.                   " +\\([^: ]+\\) *:"
  2386.                   "\\([^\001]*\001[^\001]*\001\\)")
  2387.               line)
  2388.     (setq irc-last-NOTICE-rcv last-NOTICE-rcv
  2389.           irc-last-NOTICE-src last-NOTICE-src)
  2390.     (let* ((colon (subfield line 1))
  2391.            (from (subfield line 2))
  2392.            (to (subfield line 3))
  2393.            (msg (concat (subfield line 4)
  2394.                 (substring line (match-end 0))))
  2395.            (frm (if (string= "" from) irc-server from)))
  2396.       (if (irc-is-nickname frm)
  2397.           (irc-remember frm 'irc-nicknames))
  2398.       (while (string-match "^\\([^\001]*\\)\\(\001[^\001]*\001\\)" msg)
  2399.         (let ((start (subfield msg 1))
  2400.           (ctcp (subfield msg 2))
  2401.           (end (substring msg (match-end 0))))
  2402.           (setq msg (concat start end))
  2403.           (if (string= "\001\001" ctcp)
  2404.           (setq msg (concat msg "\001"))
  2405.           (irc-parse-CLIENT-answer frm to ctcp))))
  2406.       (if (not (string-match "^ *$" msg))
  2407.           (irc-parse-server-msg
  2408.            (concat colon from " NOTICE " to " :" msg "\n")))))
  2409.        ((string-match "^\\(:[^: ]* +\\)?NOTICE " line)
  2410.     (setq irc-last-NOTICE-rcv last-NOTICE-rcv
  2411.           irc-last-NOTICE-src last-NOTICE-src)
  2412.     (irc-parse-notice line))
  2413.        ((string-match (concat "^\\(:?\\)\\([^: ]*\\) *PRIVMSG"
  2414.                   " +\\([^ ]+\\) +:"
  2415.                   "\\([^\001]*\001[^\001]*\001\\)") 
  2416.               line)
  2417.     (let* ((colon (subfield line 1))
  2418.            (from (subfield line 2))
  2419.            (to (subfield line 3))
  2420.            (msg (concat (subfield line 4)
  2421.                 (substring line (match-end 0))))
  2422.            (frm (if (string= "" from) irc-server from)))
  2423.       (if (irc-is-nickname frm)
  2424.           (irc-remember frm 'irc-nicknames))
  2425.       (while (string-match "^\\([^\001]*\\)\\(\001[^\001]*\001\\)" msg)
  2426.         (let ((start (subfield msg 1))
  2427.           (ctcp (subfield msg 2))
  2428.           (end (substring msg (match-end 0))))
  2429.           (setq msg (concat start end))
  2430.           (if (string= "\001\001" ctcp)
  2431.           (setq msg (concat msg "\001"))
  2432.           (irc-parse-CLIENT-query frm to ctcp))))
  2433.       (if (not (string-match "^ *$" msg))
  2434.           (irc-parse-server-msg
  2435.            (concat colon from " PRIVMSG " to " :" msg "\n")))))
  2436.        ((string-match "^\\(:[^: ]* +\\)?PRIVMSG " line)
  2437.     (irc-parse-priv line))
  2438.        ((string-match "^PING " line) (irc-pong line))
  2439.        ((string-match "^\\(:[^: ^]* +\\)?PONG " line)
  2440.     (irc-parse-pong line))
  2441.        ((string-match "^ERROR " line) (irc-parse-error line))
  2442.        ((string-match "^WHOREPLY " line) (irc-parse-whoreply line))
  2443.        ((string-match "^NAMREPLY " line) (irc-parse-namreply line))
  2444.        ((string-match "^LINREPLY " line) (irc-parse-linreply line))
  2445.        (t (irc-insert (concat "%%Received unkown message from server,"
  2446.                   " in function irc-parse-server-msg:"))
  2447.       (irc-insert "%% \"%s\" (cleaned up line)."
  2448.               (irc-clean-up-message line))
  2449.       (irc-insert (concat "%% Please let %s know about this;"
  2450.                   " it might be a bug.")
  2451.               irc-hacker)
  2452.       nil)))))
  2453.  
  2454.  
  2455. (defun irc-parse-channel (str)
  2456.   "Examine CHANNEL, JOIN and PART messages from the IRC server.
  2457. CHANNEL indicates a user entering or leaving the channel which you are
  2458. on, JOIN indicates a user entering a channel and PART indicates a user
  2459. leaving the channel. If the user is not being ignored and \"join\" is
  2460. in irc-events, a message is inserted indicating the change.  A
  2461. message is always provided as confirmation if the user is the irc-mode
  2462. user.
  2463.  
  2464. This function returns t if a bell should be issued for the \"join\" event,
  2465. nil otherwise."
  2466.   (if (not (or (string-match (concat "^: *\\([^ ]+\\) +\\(JOIN\\)"
  2467.                      " +:?\\([^ ]+\\) +\\([^ ]*\\) *$")
  2468.                  str)
  2469.            (string-match (concat "^: *\\([^ ]+\\) +\\(JOIN\\)"
  2470.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2471.                  str)
  2472.            (string-match (concat "^: *\\([^ ]+\\) +\\(PART\\)"
  2473.                      " +:?\\([^ ]+\\) +\\([^ ]*\\) *$")
  2474.                  str)
  2475.            (string-match (concat "^: *\\([^ ]+\\) +\\(PART\\)"
  2476.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2477.                  str)
  2478.            (string-match (concat "^: *\\([^ ]+\\) +\\(CHANNEL\\)"
  2479.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2480.                  str)))
  2481.       (progn (irc-insert (concat "%%Unknown format on command from server,"
  2482.                  " please notify %s, it migh be a bug.")
  2483.              irc-hacker)
  2484.          (irc-insert "%% str=\"%s\"." str)
  2485.          (irc-insert "%% Function irc-parse-channel."))
  2486.       (let* ((user (subfield str 1))
  2487.          (type (subfield str 2))
  2488.          (channel (subfield str 3))
  2489.          (mode (subfield str 4))
  2490.          (left (or (string= type "PART")
  2491.                (and (string= type "CHANNEL") (string= channel "0"))))
  2492.          (pd (make-string (max 0 (1- (length channel))) ? ))
  2493.          (cont (concat irc-msg-cont pd)))
  2494.     (if (string= user irc-nick-used)
  2495.         (progn
  2496.           (if left
  2497.           (irc-forget channel 'irc-subscribed-channels)
  2498.           (irc-remember channel 'irc-subscribed-channels)))
  2499.         )
  2500.     (if (string= user irc-nick-used)
  2501.         (progn
  2502.           (if left
  2503.           (if (irc-server-has-multijoinable-channels)
  2504.               (if (or (string= (upcase channel) (upcase irc-channel))
  2505.                   (string= irc-channel "0"))
  2506.               (progn
  2507.                 (setq irc-channel "0")
  2508.                 (irc-show-subscribed-channels))
  2509.               (progn
  2510.                 (if nil
  2511.                 (irc-remember channel
  2512.                           'irc-subscribed-channels))
  2513.                 (irc-show-subscribed-channels)))
  2514.               (progn
  2515.             (if nil
  2516.                 (irc-remember irc-channel
  2517.                       'irc-subscribed-channels))
  2518.             (setq irc-channel "0")
  2519.             (irc-show-subscribed-channels)))
  2520.           (progn (setq irc-channel channel)
  2521.              (if nil
  2522.                  (irc-remember channel 'irc-subscribed-channels))
  2523.              (irc-send (concat "MODE " irc-channel))
  2524.              (irc-show-subscribed-channels))))
  2525.         (if (and (not (irc-recall user 'irc-ignored-ppl))
  2526.              (memq 'join irc-events))
  2527.         (progn
  2528.           (if left
  2529.               (irc-insert "%s%s%s has LEFT channel %s%s"
  2530.                   irc-msg-info-pre
  2531.                   user
  2532.                   irc-userhost
  2533.                   (if (irc-server-has-multijoinable-channels)
  2534.                       channel
  2535.                       irc-channel)
  2536.                   irc-msg-info-post)
  2537.               (progn
  2538.             (irc-remember user 'irc-nicknames)
  2539.             (irc-insert "%s%s%s has JOINED channel %s%s"
  2540.                     irc-msg-info-pre
  2541.                     user
  2542.                     irc-userhost
  2543.                     channel
  2544.                     irc-msg-info-post)))
  2545.           )
  2546.         (irc-signal user 'join)))))) ; check for signal for join
  2547.  
  2548.  
  2549. (defun irc-parse-CLIENT-answer (sndr rcvr str)
  2550.   "Examine a client answer message from another client.
  2551.  
  2552. Generally, incoming message will look like \"^ACLIENT keyword arg1 .. argN^A\"
  2553. one or several pasted together."
  2554.   (if (irc-recall sndr 'irc-ignored-ppl)
  2555.       ;; Ignored person.
  2556.       (setq str ""))
  2557.   (if (not (string-match "^\001\\([^\001]*\\)\001$" str))
  2558.       (progn (irc-insert "%%Got non-clientmessage in irc-parse-CLIENT-answer:")
  2559.          (irc-insert "%% \"%s\" (str)." str)
  2560.          (irc-insert "%% Please tell %s, probaly en internal error."
  2561.              irc-hacker))
  2562.     (setq str (irc-ctcp-dequote
  2563.            (substring str (match-beginning 1) (match-end 1)))))
  2564.   (if (not (string-match (concat " *\\([^\001 \t]+\\)"    ;1 keyword
  2565.                  " *:?"            ;optional colon
  2566.                  " *\\([^\001]*\\)"        ;2 data
  2567.                  " *$")
  2568.              str))
  2569.       (if (string< "" str)
  2570.       (progn (irc-insert "%%Received unknown CTCP answer message:")
  2571.          (irc-insert "%% \"%s\" (str)." (irc-clean-up-message str))
  2572.          (irc-insert "%% This is probaly NOT a bug.")))
  2573.       (let* ((keyw (subfield str 1))
  2574.          (args (subfield str 2))
  2575.          (pre (concat irc-msg-info-pre "User \"" sndr "\" "))
  2576.          (irc-msg-cont-used (make-string (length pre) ? )))
  2577.     (cond
  2578.       ((string= keyw "ACTION")    ;Ignore ACTION replies.
  2579.        )
  2580.       ((string= keyw "CLIENTINFO")
  2581.        (irc-insert (concat "%sis using a client which is using the"
  2582.                    " client-to-client-protocol keyword %s in the"
  2583.                    " following way: %s%s")
  2584.                pre keyw args irc-msg-info-post))
  2585.       ((string= keyw "ECHO")
  2586.        (irc-insert "%sechoed back \"%s\" to us with (CTCP) ECHO%s"
  2587.                pre args irc-msg-info-post))
  2588.       ((string= keyw "PING")
  2589.        (cond ((not (string-match "^[0-9]+$" args))
  2590.           (irc-insert (concat "%%Received bogus (CTCP) PING reply from"
  2591.                       " user %s: \"%s\".")
  2592.                   sndr args))
  2593.          (t (let* ((cur (car (cdr (irc-current-time))))
  2594.                (rep (string-to-int args))
  2595.                (ans (- cur rep))
  2596.                (tos (/ (* 10 (if (< ans 0)
  2597.                          (+ cur (- 65536 rep))
  2598.                          ans))
  2599.                    2))
  2600.                (int-part (/ tos 10))
  2601.                (dec-part  (- tos (* 10 int-part))))
  2602.               (irc-insert (concat "%sis about %d.%d seconds"
  2603.                       " away from you, %s%s")
  2604.                   pre int-part dec-part irc-nick-used
  2605.                   irc-msg-info-post)))))
  2606.       ((string= keyw "ERRMSG")
  2607.        (cond ((string-match "^PING +RELAY +\\([0-9]+\\)\\( +:.*\\)? *$"
  2608.                 args)
  2609.           (irc-parse-CLIENT-answer sndr
  2610.                        rcvr
  2611.                        (format "\001PING %s\001"
  2612.                            (subfield args 1))))
  2613.          ((string-match "^ACTION " args)
  2614.           ;; Ignore complaints about CTCP ACTION.
  2615.           )
  2616.          (t (irc-insert (concat "%%Errormessage from client of"
  2617.                     " user %s: \"%s\".")
  2618.                 sndr args))))
  2619.       ((string= keyw "FINGER")
  2620.        (let* ((data (if (string-match (concat "^ *Please +check +"
  2621.                           "my +USERINFO +instead"
  2622.                           " *:")
  2623.                       args)
  2624.                 (substring args (match-end 0))
  2625.                 args)))
  2626.          (if (string-match (concat "^\\(.* +Idle *\\)\\(for +\\)?"
  2627.                        "\\([0-9]+\\) *seconds? *$")
  2628.                    data)
  2629.          (let* ((m (subfield data 1))
  2630.             (idle (subfield data 3))
  2631.             (xpre (concat "\"" (irc-clean-up-message m)))
  2632.             (idle-time (string-to-int idle))
  2633.             (xpost (if (= 1 idle-time) "second" "seconds"))
  2634.             (idle-string (if (>= idle-time 60)
  2635.                      (format "%s %s\" (%s)"
  2636.                          idle
  2637.                          xpost
  2638.                          (irc-sec-to-time idle-time))
  2639.                      (concat idle " " xpost "\""))))
  2640.            (irc-insert "%shas FINGER-info %s%s"
  2641.                    pre
  2642.                    (concat xpre idle-string)
  2643.                    irc-msg-info-post))
  2644.          (irc-insert "%shas fingerinfo \"%s\"%s"
  2645.                  pre data irc-msg-info-post))))
  2646.       ((string= keyw "SOURCE")
  2647.        (cond
  2648.          ((string-match "^ *$" args)
  2649.           (irc-insert "%sEnd of source site listing%s"
  2650.               irc-msg-info-pre irc-msg-info-post))
  2651.          ((string-match "^ *\\([^: ]+\\) *: *\\([^: ]+\\) *: *\\(.*\\) *"
  2652.                 args)
  2653.           (let ((site (subfield args 1))
  2654.             (dir (subfield args 2))
  2655.             (files (subfield args 3)))
  2656.         (let ((x files)
  2657.               (y ""))
  2658.           (while (string-match "^ *\\([^ ]+\\)\\(.*\\)$" x)
  2659.             (let ((hd (subfield x 1))
  2660.               (tl (subfield x 2)))
  2661.               (setq y (format "%s, ftp://%s/%s" y dir hd)
  2662.                 x tl)))
  2663.           (setq y (substring y 1)) 
  2664.           (irc-insert "%sSource at%s%s"
  2665.                   irc-msg-info-pre
  2666.                   y                
  2667.                   irc-msg-info-post))
  2668.         ))
  2669.          (t (irc-insert "%%Received unknown CTCP %s reply from %s: %s"
  2670.                 keyw sndr args))))
  2671.       ((string= keyw "USERINFO")
  2672.        (if (or (string-match "^ *$" args)
  2673.            (string-match
  2674.             "^ *\\(HUH *\\?\\) *WHO +WANTS +TO +KNOW *\\? *$"
  2675.             (upcase args))
  2676.            (string= "<None Supplied>" args)
  2677.            (string= "And what you want to know?" args)
  2678.            (string= "No user info given." args)
  2679.            )
  2680.            (irc-insert (concat "%shasn't given any information"
  2681.                    " about him/herself%s")
  2682.                pre irc-msg-info-post)
  2683.            (progn
  2684.          (string-match "\\(\\.?\\)$" args)
  2685.          (let ((info (substring args 0 (match-beginning 0)))
  2686.                (dot (subfield args 2)))
  2687.            (irc-insert (concat "%shas given the information"
  2688.                        " \"%s\"%s about him/herself%s")
  2689.                    pre
  2690.                    (irc-clean-up-message info)
  2691.                    dot
  2692.                    irc-msg-info-post)))))
  2693.       ((or (string= keyw "VERSION")    ;CLIENT_VERSION
  2694.            (string= keyw "VRSN"))
  2695.        (if (string-match "^ *\\([^:]+\\) *: *\\([^:]+\\) *: *\\(.*\\) *$"
  2696.                  args)
  2697.            (let ((name (subfield args 1))
  2698.              (vrsn (subfield args 2))
  2699.              (env (subfield args 3)))
  2700.          (irc-insert (concat "%sUser \"%s\" claims to be using"
  2701.                      " client %s version %s (%s)%s")
  2702.                  irc-msg-info-pre
  2703.                  sndr name (irc-clean-up-message vrsn) env
  2704.                  irc-msg-info-post))
  2705.            (irc-insert "%sclaims to be using client %s%s"
  2706.                pre
  2707.                (irc-clean-up-message
  2708.                 (let ((c (cond
  2709.                        ((or (string-match
  2710.                          (concat
  2711.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2712.                           "\\([0-9]+\\.[0-9]+[^:]+\\) *:"
  2713.                           "[^0-9]*\\([0-9]\\.[0-9][^ \\.]+"
  2714.                           "*\\).*$")
  2715.                          args)
  2716.                         (string-match
  2717.                          (concat
  2718.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2719.                           "[^:]*: *\\(.*[0-9]\\."
  2720.                           "[0-9].*\\) *\\(\\)$")
  2721.                          args)
  2722.                         (string-match
  2723.                          (concat
  2724.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2725.                           "\\([^:]+\\) *:.*\\(\\)$")
  2726.                          args))
  2727.                     (concat "ircII "
  2728.                         (subfield args 1)
  2729.                         (subfield args 2)))
  2730.                        ((string-match
  2731.                      (concat "^[^:]*: *\\(.*[0-9]+\\."
  2732.                          "[0-9]+.*.*\\) *$")
  2733.                      args)
  2734.                     (subfield args 1))
  2735.                        ((string-match
  2736.                      "^[^:]*[0-9]+\\.[0-9]+[^:]*"
  2737.                      args)
  2738.                     (substring args 0 (match-end 0)))
  2739.                        (t args))))
  2740.                   (irc-nuke-whitespace
  2741.                    (progn
  2742.                  (while
  2743.                      (or (string-match
  2744.                       " The one true client\\." c)
  2745.                      (string-match (concat
  2746.                             " Who could ask for"
  2747.                             " anything more\\.")
  2748.                                c)
  2749.                      (string-match "SIAWPIO!" c))
  2750.                    (setq c (concat
  2751.                         (substring c 0 (match-beginning 0))
  2752.                         (substring c (match-end 0)))))
  2753.                  c))))
  2754.                irc-msg-info-post)))
  2755.       ((string= keyw "VRSN")
  2756.        (if (string-match "^ *\\([^:]+\\) *: *\\([^:]+\\) *: *\\(.*\\) *$"
  2757.                  args)
  2758.            (let ((name (subfield args 1))
  2759.              (vrsn (subfield args 2))
  2760.              (env (subfield args 3)))
  2761.          (irc-insert (concat "%sUser \"%s\" claims to be using"
  2762.                      " client %s version %s (%s)%s")
  2763.                  irc-msg-info-pre
  2764.                  sndr name vrsn env
  2765.                  irc-msg-info-post))
  2766.            (irc-insert "%%Received unknown (CTCP) %s reply from %s: %s"
  2767.                keyw sndr args)))
  2768.       (t (irc-insert (concat "%%Received unknown answer with keyword"
  2769.                  " \"%s\" from client of user \"%s\":"
  2770.                  " \"%s\".")
  2771.              keyw sndr args))))))
  2772.  
  2773.  
  2774. (defun irc-parse-CLIENT-query (sndr rcvr str)
  2775.   "Examine a client query message from another client.
  2776.  
  2777. Generally, incoming message will look like \"^A CLIENT keyword data
  2778. ... ^A\" where sndr is nick of client query is comming from, rcvr is
  2779. nick of receiver (either one self or a channel or a broadcast), and
  2780. keyword being a token in the set VERSION, USERINFO, ERRMSG etc. Arg1
  2781. to argN are optional." 
  2782.   (cond
  2783.     ((irc-recall sndr 'irc-ignored-ppl)
  2784.      ;; Ignored person.
  2785.      nil)
  2786.     ((not (string-match "^\001\\([^\001]*\\)\001$" str))
  2787.      (progn (irc-insert "%%Got non-CTCP query in irc-parse-CLIENT-query:")
  2788.         (irc-insert "%% \"%s\" (str)." str)
  2789.         (irc-insert "%% Please tell %s, probaly an internal error."
  2790.             irc-hacker)))
  2791.     (t (setq str (irc-ctcp-dequote
  2792.           (substring str (match-beginning 1) (match-end 1))))
  2793.        (if (not (string-match (concat " *\\([^\001 \t]+\\)" ;1 keyword
  2794.                       " *\\([^\001]*\\)" ;2 data
  2795.                       " *$")
  2796.                   str))
  2797.        (if (and debug-on-error
  2798.             (string< "" str))
  2799.            (progn
  2800.          (irc-insert "%%Received unknown CTCP request:")
  2801.          (irc-insert "%% \"%s\" (str)." (irc-clean-up-message str))
  2802.          (irc-insert "%% This is probaly not a bug.")))
  2803.        (let ((keyw (substring str (match-beginning 1) (match-end 1)))
  2804.          (args (substring str (match-beginning 2) (match-end 2)))
  2805.          (tell (memq 'ctcp irc-events)))
  2806.          (cond
  2807.            ((string= keyw "ACTION") ;CLIENT_ACTION
  2808.         (if (string= "" args)
  2809.             (irc-send (format "NOTICE %s :\001ERRMSG ACTION :%s\001"
  2810.                       sndr
  2811.                       "No argument supplied."))
  2812.             (irc-insert ">>> (To %s) User %s %s"
  2813.                 rcvr
  2814.                 sndr
  2815.                 (irc-clean-up-message args))))
  2816.            ((string= keyw "CLIENTINFO")
  2817.         (cond ((string-match "^ *$" args) ;No arguments
  2818.                (irc-send
  2819.             (concat "NOTICE " sndr " :\001"
  2820.                 (irc-ctcp-enquote
  2821.                  (concat
  2822.                   "CLIENTINFO :You can request help of the"
  2823.                   " commands ACTION CLIENTINFO ECHO ERRMSG"
  2824.                   " FINGER PING SOURCE USERINFO VERSION"
  2825.                   " by giving an argument to CLIENTINFO."))
  2826.                 "\001"))
  2827.                (if tell
  2828.                (irc-insert
  2829.                 "%sAnswered (CTCP) CLIENTINFO query to %s by %s%s"
  2830.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)) )
  2831.               ((string-match "^ *\\([^: ]+\\) *$" args) ;1 arg
  2832.                (let* ((w (substring args
  2833.                         (match-beginning 1)
  2834.                         (match-end 1)))
  2835.                   (uw (upcase w))
  2836.                   (info (cond
  2837.                       ((string= uw "ACTION")
  2838.                        (concat
  2839.                     "ACTION takes one or more arguments,"
  2840.                     " and displayes them as a \"MUD like"
  2841.                     " feeling\" to this user. If nick"
  2842.                     " sojge sends \"falls down\", this"
  2843.                     " user gets a message looking more or"
  2844.                     " less like \"User sojge falls"
  2845.                     " down\"."))
  2846.                       ((string= uw "CLIENTINFO")
  2847.                        (concat
  2848.                     "CLIENTINFO with 0 arguments gives"
  2849.                     " a list of known client query"
  2850.                     " keywords. With 1 argument,"
  2851.                     " a description of the client query"
  2852.                     " keyword is returned."))
  2853.                       ((string= uw "ECHO")
  2854.                        (concat
  2855.                     "ECHO returns whatever argument is"
  2856.                     " given."))
  2857.                       ((string= uw "ERRMSG")
  2858.                        (concat
  2859.                     "ERRMSG is returned either when the"
  2860.                     " query keyword is ERRMSG (in which"
  2861.                     " case all arguments are echoed) or"
  2862.                     " when an error in a query is"
  2863.                     " detected or some other error"
  2864.                     " happens in connection to CTCP (in"
  2865.                     " which case the query is returned as"
  2866.                     " the replies arguments, with a short"
  2867.                     " error message added)."))
  2868.                       ((string= uw "FINGER")
  2869.                        (concat
  2870.                     "FINGER shows user's real name, login"
  2871.                     " name, client machine and idle"
  2872.                     " time."))
  2873.                       ((string= uw "PING")
  2874.                        (concat
  2875.                     "PING takes a integer number as its"
  2876.                     " argument and echoes it back to the"
  2877.                     " sender."))
  2878.                       ((string= uw "SOURCE")
  2879.                        (concat
  2880.                     "SOURCE takes 0 arguments and returns"
  2881.                     " a description of where to find the"
  2882.                     " source code of the client. The"
  2883.                     " description is made up out of zero"
  2884.                     " or more lines followed by an end"
  2885.                     " marker. Every line is a CTCP"
  2886.                     " reply with the SOURCE keyword,"
  2887.                     " a space, the name of a FTP-server, a"
  2888.                     " colon, a directory name, a colon,"
  2889.                     " and 0 or more file names."
  2890.                     " If no file names are given, all the"
  2891.                     " files in the named directory are"
  2892.                     " needed. The end marker contains just"
  2893.                     " the keyword."))
  2894.                       ((string= uw "VERSION")
  2895.                        (concat
  2896.                     "VERSION takes 0 arguments and"
  2897.                     " returns a list of words consisting"
  2898.                     " of clients name, any number of"
  2899.                     " versions (starting with the major"
  2900.                     " version), and ending with the"
  2901.                     " enviroment the client runs in. A"
  2902.                     " colon and a plain text descrpition"
  2903.                     " of the clients version is appended"
  2904.                     " after the list."))
  2905.                       ((string= uw "USERINFO")
  2906.                        (concat
  2907.                     "USERINFO takes no arguments and"
  2908.                     " returns a user settable"
  2909.                     " string."))
  2910.                       (t nil))))
  2911.              (cond ((stringp info)
  2912.                 (irc-send
  2913.                  (concat "NOTICE " sndr " :\001"
  2914.                      (irc-ctcp-enquote
  2915.                       (concat "CLIENTINFO :" info))
  2916.                      "\001"))
  2917.                 (if tell
  2918.                     (irc-insert
  2919.                      (concat "%sAnswered (CTCP)"
  2920.                          " CLIENTINFO %s to %s by %s%s")
  2921.                      irc-msg-info-pre
  2922.                      uw
  2923.                      rcvr
  2924.                      sndr
  2925.                      irc-msg-info-post)))
  2926.                    (t (irc-send
  2927.                    (concat
  2928.                     "NOTICE " sndr " :\001"
  2929.                     (irc-ctcp-enquote
  2930.                      (concat
  2931.                       "ERRMSG " keyw
  2932.                       (if args
  2933.                       (concat " " args)
  2934.                       "")
  2935.                       " :Unknown keyword in CLIENTINFO"
  2936.                       " client query. Send CLIENTINFO"
  2937.                       " CLIENTINFO for help."))
  2938.                     "\001"))))))
  2939.               (t (irc-send
  2940.               (concat "NOTICE " sndr " :\001"
  2941.                   (irc-ctcp-enquote
  2942.                    (concat "ERRMSG " keyw " " args " :"
  2943.                        "CLIENTINFO takes 0 or 1"
  2944.                        " argument. Send"
  2945.                        " CLIENTINFO CLIENTINFO"
  2946.                        " for help."))
  2947.                   "\001"))
  2948.              (if tell
  2949.                  (irc-insert (concat
  2950.                       "%sComplained about user %s's"
  2951.                       " corrupted CTCP CLIENTINFO query to"
  2952.                       " %s%s")
  2953.                      irc-msg-info-pre
  2954.                      sndr
  2955.                      rcvr
  2956.                      irc-msg-info-post)))))
  2957.            ((string= keyw "ECHO") 
  2958.         (irc-send (format "NOTICE %s :\001ECHO %s\001"
  2959.                   sndr
  2960.                   (irc-ctcp-enquote args)))
  2961.         (if tell
  2962.             (irc-insert (concat "%sAnswered to (CTCP) ECHO request"
  2963.                     " from %s to %s, echoed back \"%s\"%s")
  2964.                 irc-msg-info-pre rcvr sndr args
  2965.                 irc-msg-info-post)))
  2966.            ((string= keyw "ERRMSG")
  2967.         (irc-send (format "NOTICE %s :\001ERRMSG %s :No errors.\001"
  2968.                   sndr args))
  2969.         (cond ((not tell)
  2970.                )
  2971.               ((string-match "^ *PING +RELAY +[0-9]+ *$" args)
  2972.                (irc-insert (concat "%sAnswered to (CTCP) ERRMSG PING"
  2973.                        " RELAY request to %s from %s%s")
  2974.                    irc-msg-info-pre rcvr sndr
  2975.                    irc-msg-info-post))
  2976.               (t (irc-insert (concat "%sAnswered to (CTCP) ERRMSG"
  2977.                          " request to %s from %s, echoed"
  2978.                          " back \"%s\"%s")
  2979.                      irc-msg-info-pre
  2980.                      rcvr sndr (concat args " :No errors")
  2981.                      irc-msg-info-post))))
  2982.            ((string= keyw "FINGER")
  2983.         (let* ((idle (irc-idle-time))
  2984.                (verbose-idle (concat "(" (irc-sec-to-time idle) ") "))
  2985.                (plur (not (= 1 idle))))
  2986.           (irc-send (format (concat "NOTICE %s :\001FINGER :Please"
  2987.                         " check my USERINFO instead :%s"
  2988.                         " (%s@%s) %d second%s %sha%s"
  2989.                         " passed since %s gave a command"
  2990.                         " last.\001")
  2991.                     sndr
  2992.                     (user-full-name)
  2993.                     (user-real-login-name)
  2994.                     (system-name)
  2995.                     idle
  2996.                     (if plur "s" "")
  2997.                     (if (>= idle 60) verbose-idle "")
  2998.                     (if plur "ve" "s")
  2999.                     irc-nick-used)))
  3000.         (if tell
  3001.             (irc-insert "%sAnswered (CTCP) FINGER query to %s by %s%s"
  3002.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  3003.            ((string= keyw "PING")
  3004.         (cond ((string-match "^[0-9]+$" args)
  3005.                (irc-send (format "NOTICE %s :\001PING %s\001"
  3006.                      sndr
  3007.                      (irc-ctcp-enquote args)))
  3008.                (if tell
  3009.                (irc-insert
  3010.                 "%sAnswered to (CTCP) PING query to %s from %s%s"
  3011.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  3012.               (t (irc-send (format "NOTICE %s :\001%s %s :%s\001"
  3013.                        sndr
  3014.                        "ERRMSG PING"
  3015.                        (irc-ctcp-enquote args)
  3016.                        "Argument was not a number"))
  3017.              (cond
  3018.                (tell
  3019.                 (irc-insert (concat "%%Received unknown CTCP PING"
  3020.                         " query to %s from user"
  3021.                         " \"%s\":")
  3022.                     rcvr sndr)
  3023.                 (irc-insert "%% \"%s\" (args)." args)
  3024.                 (irc-insert "%% This is probaly NOT a bug."))))))
  3025.            ((string= keyw "SOURCE")
  3026.         (let ((s irc-ftp-source))
  3027.           (while (not (null s))
  3028.             (let* ((r (car s))
  3029.                (site (nth 0 r))
  3030.                (dir (nth 1 r))
  3031.                (files (nth 2 r)))
  3032.               (irc-send
  3033.                (concat "NOTICE " sndr " :\001"
  3034.                    (irc-ctcp-enquote
  3035.                 (format "SOURCE %s:%s:%s"
  3036.                     site
  3037.                     dir
  3038.                     (irc-listify files " " "")))
  3039.                    "\001"))
  3040.               (setq s (cdr s))))
  3041.           (irc-send (concat "NOTICE " sndr " :\001SOURCE\001"))
  3042.           (if tell
  3043.               (irc-insert
  3044.                "%sAnswered (CTCP) SOURCE query to %s by %s%s"
  3045.                irc-msg-info-pre
  3046.                rcvr sndr
  3047.                irc-msg-info-post))))
  3048.            ((string= keyw "USERINFO") ;CLIENT_USERINFO
  3049.         (irc-send (concat "NOTICE " sndr " :\001"
  3050.                   (irc-ctcp-enquote
  3051.                    (concat "USERINFO :"
  3052.                        (if (stringp irc-userinfo)
  3053.                            irc-userinfo
  3054.                            "")))
  3055.                   "\001"))
  3056.         (if tell
  3057.             (irc-insert
  3058.              "%sAnswered (CTCP) USERINFO query to %s by %s%s"
  3059.              irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  3060.            ((string= keyw "VERSION")
  3061.         (cond ((string-match (concat
  3062.                       "^ *\\([^: ]+\\) +v?\\([0-9]+[^ ]+\\)"
  3063.                       " +\\(.*\\) *$")
  3064.                      irc-version)
  3065.                (irc-send
  3066.             (concat "NOTICE " sndr " :\001"
  3067.                 (irc-ctcp-enquote
  3068.                  (format "%s %s:%s:%s, %s, emacs %s"
  3069.                      keyw
  3070.                      (subfield irc-version 1)
  3071.                      (subfield irc-version 2)
  3072.                      (subfield irc-version 3)
  3073.                      (cond
  3074.                        (irc-emacs-knows-ISO8859-1
  3075.                         "8bit ISO 8859-1 characters")
  3076.                        (irc-translation-table-incoming
  3077.                         "8bit characters")
  3078.                        (t (concat "7bit ISO 646 characters"
  3079.                               " (ie ASCII with"
  3080.                               " friends)")))
  3081.                      emacs-version))
  3082.                 "\001"))
  3083.                (if tell
  3084.                (irc-insert
  3085.                 "%sAnswered (CTCP) %s query to %s by %s%s"
  3086.                 irc-msg-info-pre keyw rcvr sndr
  3087.                 irc-msg-info-post)))
  3088.               (t (irc-send (concat "NOTICE " sndr " :\001"
  3089.                        (irc-ctcp-enquote
  3090.                         (format "%s Kiwi::%s"
  3091.                             keyw
  3092.                             irc-version))
  3093.                        "\001"))
  3094.              (cond
  3095.                (tell
  3096.                 (irc-insert
  3097.                  "%sAnswered (CTCP) %s query to %s by %s%s"
  3098.                  irc-msg-info-pre keyw rcvr sndr irc-msg-info-post)
  3099.                 (irc-insert "%% Client doesn't know who it is!")
  3100.                 (irc-insert "%% Please tell %s." irc-hacker))))))
  3101.            (t (and nil
  3102.                (irc-send
  3103.            (concat "NOTICE " sndr " :\001"
  3104.                (irc-ctcp-enquote
  3105.                 (concat "ERRMSG "
  3106.                     keyw
  3107.                     (if args
  3108.                     (concat " " args)
  3109.                     "")
  3110.                     " :Query is unknown"))
  3111.                "\001"))
  3112.                )
  3113.           (cond
  3114.             (tell
  3115.              (irc-insert (concat "%%Received unknown CTCP \"%s\" to %s"
  3116.                      " from user \"%s\".")
  3117.                  str rcvr sndr))))))))))
  3118.  
  3119.  
  3120. (defun irc-parse-ERR (str)
  3121.   "Examine a numeric ERR_ message from the IRC server. Numeric
  3122. control messages are used by newer servers to aid in generalized
  3123. client design; while people are converting to the new servers the
  3124. older irc-parse-error, irc-parse-notice, et al, functions are
  3125. redundant with irc-parse-ERR and irc-parse-RPL.  Values used by this
  3126. function are found in the IRC source file numeric.h.
  3127.  
  3128. Note well that some things are still going to come out wrong because the
  3129. servers are currently still doing things inconsistently."
  3130.   (if (not (string-match (concat "^:\\(.*\\) +\\([4-5][0-9][0-9]\\) +"
  3131.                  "\\([^: ]*\\)? *:? *\\(.*\\) *$")
  3132.              str))
  3133.       (progn
  3134.     (irc-insert (concat "%%Received an ERR message with unknown format in"
  3135.                 " function irc-parse-ERR:"))
  3136.     (irc-insert "%% \"%s\"." str)
  3137.     (irc-insert "%%Please report this to %s." irc-hacker))
  3138.       (let*
  3139.       ;; we assume that the server and message are consistent for us; just
  3140.       ;; worry about the numeric value and the rest of the line
  3141.       ((srvr (subfield str 1))
  3142.        (code (subfield str 2))
  3143.        (txt (subfield str 4))
  3144.        (num (string-to-int code))
  3145.        (parorg (if (string= (upcase srvr) (upcase irc-server))
  3146.                ""
  3147.                (concat "(" srvr ") ")))
  3148.        (tmp1 nil))
  3149.     (if (not (string= "" srvr))
  3150.         (irc-remember srvr 'irc-servernames))
  3151.     (cond
  3152.       ((= num 401)        ; ERR_NOSUCHNICK
  3153.        (cond ((string-match (concat "^[^: ]+ +401 +[^: ]+ +"
  3154.                     ":Hunting +for +ghosts +?.*$")
  3155.                 str)
  3156.           nil)        ;Ignore "Hunting for ghosts ?" message.
  3157.          ((string-match (concat "^[^: ]+ +401 +[^: ]+ +"
  3158.                     ":Cannot +kick +user +off +"
  3159.                     "channel *$")
  3160.                 str)
  3161.           (irc-insert "%%%sCan't boot that user from that channel."
  3162.                   parorg))
  3163.          ((string-match "^@?[^:@ ]+" txt)
  3164.           (let* ((user (substring txt
  3165.                       (match-beginning 0)
  3166.                       (match-end 0)))
  3167.              (is-service (irc-recall user 'irc-services)))
  3168.             (if is-service
  3169.             (irc-insert (concat "%%Service %s isn't reachable at"
  3170.                         " the moment, please try again"
  3171.                         " later.")
  3172.                     is-service)
  3173.             (progn
  3174.               (if (irc-is-nickname user)
  3175.                   (irc-forget user 'irc-nicknames))
  3176.               (irc-insert (concat
  3177.                        "%%%sThere is no user called"
  3178.                        " \"%s\" on IRC at the moment.")
  3179.                       parorg
  3180.                       user)))
  3181.             (if (and (>= irc-major-version 2)
  3182.                  (>= irc-minor-version 6))
  3183.             (irc-send (concat "WHOWAS :" user))
  3184.             )))
  3185.          (t (irc-insert (concat "%%%sUnrecognized NO SUCH NICK"
  3186.                     " message follows; please tell %s:")
  3187.                 parorg
  3188.                 irc-hacker)
  3189.             (irc-insert "%% \"%s\"." str)
  3190.             (irc-insert "%%Function irc-parse-err, at 401."))))
  3191.       ((= num 402)        ; ERR_NOSUCHSERVER
  3192.        (cond ((or (string-match (concat "^ *\\(.+\\) *: *"
  3193.                         "\\(\\*\\*\\* * \\)?No +such +"
  3194.                         "server *.? *$")
  3195.                     txt)
  3196.               (string-match (concat "^:? *\\** *No +such"
  3197.                         " +server *( *"
  3198.                         "\\([^: ]+\\) *) *.?"
  3199.                         " *$")
  3200.                     txt))
  3201.           (irc-insert (concat "%%%sThere is no server \"%s\" on the"
  3202.                       " IRCnet at the moment.")
  3203.                   parorg
  3204.                   (irc-nuke-whitespace (subfield txt 1))))
  3205.          (t (irc-insert (concat "%%Unknown ERR 402 message received"
  3206.                     " in function irc-parse-ERR:"))
  3207.             (irc-insert "%% txt=\"%s\"." txt)
  3208.             (irc-insert "%% Please tell %s, it might be a bug."
  3209.                 irc-hacker))))
  3210.       ((= num 403)        ; ERR_NOSUCHCHANNEL
  3211.        (if (string= (upcase srvr) (upcase irc-server))
  3212.            (let ((chn (if (string-match "^\\([^: ]+\\) *:.*$" txt)
  3213.                   (subfield txt 1))))
  3214.          (if chn
  3215.              (irc-insert (concat "%%%sThere is no channel called"
  3216.                      " \"%s\" in use right now.")
  3217.                  parorg chn)
  3218.              (irc-insert "%%%sNo such channel in use." parorg)))))
  3219.       ((= num 404)        ; ERR_CANNOTSENDTOCHAN
  3220.        (if (string-match "^ *\\([^ :]+\\) *:" txt)
  3221.            (irc-insert "%%%sChannel %s rejected the message."
  3222.                parorg (subfield txt 1))
  3223.            (irc-insert "%%%sChannel rejected the message." parorg)))
  3224.       ((= num 405)
  3225.        (cond ((string-match (concat "^ *\\([^ ]+\\) *: *You +have +joined"
  3226.                     " +too +many +channels.? *$")
  3227.                 txt)
  3228.           (irc-insert (concat "%%Failed joining channel %s, as you're"
  3229.                       " already listening to too many"
  3230.                       " channels.")
  3231.                   (subfield txt 1)))
  3232.          (t (irc-insert "*** %s %s." parorg txt))))
  3233.       ((= num 406)
  3234.        (if (string-match "^ *\\([^: ]+\\) *: *\\(.*\\) *$"
  3235.                  txt)
  3236.            (let ((m (substring txt (match-beginning 2) (match-end 2)))
  3237.              (n (substring txt (match-beginning 1) (match-end 1))))
  3238.          (irc-insert
  3239.           "%%No trace left about \"%s\" in history of server %s."
  3240.           n srvr))
  3241.            (progn
  3242.          (irc-insert "%%Unknown type 406 error message from server:")
  3243.          (irc-insert "%% \"%s\" (str)." str)
  3244.          (irc-insert "%% Please tell %s, it migth be a bug."
  3245.                  irc-hacker))))
  3246.       ((= num 409)
  3247.        ;txt="No origin specified"
  3248.        (irc-insert "%%%s%s" parorg txt))
  3249.       ((= num 411)        ; ERR_NORECIPIENT
  3250.        (irc-insert "%%%sThe last message had no recipient." parorg))
  3251.       ((= num 412)        ; ERR_NOTEXTTOSEND
  3252.        (irc-insert "%%%sThe last message had no text to send." parorg))
  3253.       ((= num 413)
  3254.        (irc-insert "%%%sNo top level domain specified (no such receiver)."
  3255.                parorg))
  3256.       ((= num 421)        ; ERR_UNKNOWNCOMMAND
  3257.        (cond ((string-match "^CLIENT-SYNCH :?\\(.*\\) *:Unknown command$"
  3258.                 txt)
  3259.           (let* ((cmd (irc-nuke-whitespace (subfield txt 1)))
  3260.              (ucmd (upcase cmd)))
  3261.             (cond 
  3262.              ((or t (string-match "^QUOTE " ucmd))
  3263.               (irc-insert "%sEnd of quoted command%s"
  3264.                   irc-msg-info-pre irc-msg-info-post))
  3265.              (t (irc-insert (concat "%%Unknown internal"
  3266.                         " synchronisation in"
  3267.                         " irc-parse-ERR at 421:"))
  3268.             (irc-insert "%% \"%s\" (txt)." txt)
  3269.             (irc-insert "%% Please tell %s, this *is* a bug."
  3270.                     irc-hacker)))))
  3271.          ((string-match (concat "^\\(MODE\\|KICK\\|JOIN\\|PART\\)"
  3272.                     ".*Unknown :?command *$")
  3273.                 txt)
  3274.           nil)
  3275.          ((string-match "^CLIENT-START *: *Unknown *command *$" txt)
  3276.           (run-hooks 'irc-startup-hook))
  3277.          ((or (string-match "^\\(.*\\) :?Unknown :?command$" txt)
  3278.               (string-match "^:?Unknown command \\(.*[^ ].*\\) *$"
  3279.                     txt))
  3280.           (if (string= (upcase irc-server) (upcase srvr))
  3281.               (irc-insert "%%%sUnknown server command: %s."
  3282.                   parorg
  3283.                   (subfield txt 1))))
  3284.          (t (irc-insert (concat "%%%sUnkown server command,"
  3285.                     " reported in unknown format:")
  3286.                 parorg)
  3287.             (irc-insert "%% \"%s\" (txt)." txt)
  3288.             (irc-insert "%% Function irc-parse-err, at 421."))))
  3289.       ((or (= num 422)        ;ERR_NOMOTD
  3290.            (= num 423))        ;ERR_NOADMIN
  3291.        (irc-insert "%%%s%s" parorg txt))
  3292.       ((= num 431)        ; ERR_NONICKNAMEGIVEN
  3293.        (irc-insert "%%%sNo nickname give to change to." parorg))
  3294.       ((= num 432)        ; ERR_ERRONEUSNICKNAME
  3295.        (irc-insert (concat "%%%sBad format for nickname change. Your"
  3296.                    " nickname is \"%s\".")
  3297.                parorg irc-nick-used))
  3298.       ((= num 433)        ; ERR_NICKNAMEINUSE
  3299.        (if (or (string-match (concat "^:[^: \t]+ +433 +"
  3300.                      "\\([^: \t]+\\) +"
  3301.                      "\\([^: \t]+\\) +:")
  3302.                  str)
  3303.            (string-match (concat "^:[^: \t]+ +433 +\\(\\)"
  3304.                      "\\([^: \t]+\\) +:")
  3305.                  str))
  3306.            (let ((current (subfield str 1))
  3307.              (failed (subfield str 2)))
  3308.          (irc-insert (concat "%%%sNickname \"%s\" is already being"
  3309.                      " used, please choose another one.")
  3310.                  parorg
  3311.                  failed)
  3312.          (irc-insert "%sHmmm ... looks like you're still %s%s"
  3313.                  irc-msg-info-pre
  3314.                  (if (string= current "")
  3315.                  (concat "without a nickname, use \"/HELP"
  3316.                      " NICK\" to get help about how to"
  3317.                      " set one")
  3318.                  (concat "\"" current "\""))
  3319.                  irc-msg-info-post))
  3320.            (irc-insert "%%Unknown ERR 433 type message received:")
  3321.            (irc-insert "%% \"%s\" (str)." str)
  3322.            (irc-insert "%% Please tell %s." irc-hacker)))
  3323.       ((= num 436)
  3324.        (cond ((string-match "^\\([^ :]+\\) :Nickname collision KILL$" txt)
  3325.           (let ((nick (subfield txt 1)))
  3326.             (irc-insert "%sUser %s killed due to NAMECLASH at %s%s"
  3327.                 irc-msg-info-pre
  3328.                 nick
  3329.                 srvr
  3330.                 irc-msg-info-post)
  3331.             (irc-forget nick 'irc-nicknames)))
  3332.          (t (irc-insert "%%Unknown ERR 436 type message received:")
  3333.             (irc-insert "%% \"%s\" (txt)." txt)
  3334.             (irc-insert "%% Please tell %s." irc-hacker))))
  3335.       ((= num 437) 
  3336.        (if (string-match "^\\([^:]+\\) : *\\(.+\\)" txt)
  3337.            (irc-insert "%%%s: %s" (subfield txt 2) (subfield txt 1))
  3338.          (irc-insert "%%Unknown ERR 436 type message received:")
  3339.          (irc-insert "%% \"%s\" (txt)." txt)
  3340.          (irc-insert "%% Please tell %s." irc-hacker)))
  3341.       ((= num 441)        ; ERR_USERNOTINCHANNEL
  3342.        (if (string= (upcase irc-server) (upcase srvr))
  3343.            (irc-insert "%%%sYou're not on any channel." parorg)))
  3344.       ((= num 442)        ; ERR_NOTONCHANNEL
  3345.        (cond ((or (string-match (concat "^ *\\([^ :]+\\) +"
  3346.                         "\\([^ :]+\\) *: *"
  3347.                         "\\([^ :]+\\) +is +not"
  3348.                         " +here *.? *$")
  3349.                     txt)
  3350.               (string-match (concat "^ *\\([^: ]+\\) *\\(\\):\\"
  3351.                         "([^: ]+\\) +is +not +here *$")
  3352.                     str))
  3353.           (let* ((o1 (subfield txt 1))
  3354.              (c (subfield txt 2))
  3355.              (o2 (subfield txt 3))
  3356.              (chn (if (string= c "") irc-channel c))
  3357.              (name (if (string= o1 o2)
  3358.                    o1
  3359.                    (concat o2 " (" o1 ")"))))
  3360.             (irc-insert (concat "%%You can't change the channel"
  3361.                     " operator status of %s while s/he"
  3362.                     " isn't here on %s.")
  3363.                 name chn)))
  3364.          ((string-match (concat "^ *\\([^ :]+\\) +\\([^ :]+\\)"
  3365.                     " *: *\\(isn't +on +your"
  3366.                     " +channel\\|Cannot +kick"
  3367.                     " +user +off\\ +channel\\)")
  3368.                 txt)
  3369.           (let ((who (subfield txt 1))
  3370.             (chn (subfield txt 2))
  3371.             (msg (subfield txt 3)))
  3372.             (cond ((string-match "^isn't" msg)
  3373.                (irc-insert (concat "%%Can't /KICK %s while"
  3374.                            " s/he's not on your"
  3375.                            " channel %s.")
  3376.                        who chn))
  3377.               (t (irc-insert (concat "%%Failed to /KICK %s from"
  3378.                          " channel %s.")
  3379.                      who chn)))))
  3380.          ((string-match (concat "^: *[^: ]+ +442 +[^: ]+"
  3381.                     " +\\([^: ]+\\) *: *"
  3382.                     "isn't *on *your *"
  3383.                     "channel *!* *$")
  3384.                 str)
  3385.           (let ((u (subfield str 1)))
  3386.             (irc-insert (concat "%%Can't /kick user %s while s/he's"
  3387.                     " not on this channel.")
  3388.                 u)))
  3389.          ((or (string-match (concat ":[^: ]+ +442 +[^: ]+"
  3390.                         " +\\([^: ]+\\) +: *You're +not"
  3391.                         " +on *\\(that\\)? +channel *$")
  3392.                     str)
  3393.               (string-match
  3394.                (concat "^:[^: ]+ +442 +[^: ]+ +\\([^ ]+\\) *: *Not"
  3395.                    " *On *Channel$")
  3396.                str)
  3397.               (string-match (concat "^[^: ]+ +442 +[^: ]+"
  3398.                         " +\\([^ ]+\\): *You're +not +on"
  3399.                         " +channel +\\([^ ]+\\) *$")
  3400.                     str)
  3401.               (string-match (concat "^:[^: ]+ +442 +[^: ]+"
  3402.                         " *: *You're +not on"
  3403.                         " +channel +\\([^ ]+\\) *$")
  3404.                     str))
  3405.           (let ((c (subfield str 1)))
  3406.             (irc-insert "%%You're not on channel %s." c)))
  3407.          ((string-match "^\\([^ :]+\\) *:\\(.*\\)$" txt)
  3408.           (irc-insert "%%%s: %s" (subfield txt 2) (subfield txt 1)))
  3409.          ((string= (upcase irc-server) (upcase srvr))
  3410.           (irc-insert (concat "%%Unknown format on"
  3411.                       " ERR_NOTONCHANNEL message;"
  3412.                       " please tell %s, it might be"
  3413.                       " a bug:")
  3414.                   irc-hacker)
  3415.           (irc-insert "%% \"%s\" (str)." str)
  3416.           (irc-insert "%% Function irc-parse-ERR, at 442."))))
  3417.       ((= num 443)
  3418.        (if (string-match (concat "^\\([^: ]+\\) +\\([^: ]+\\) +"
  3419.                      ":is already on channel.?$")
  3420.                  txt)
  3421.            (let ((nick (subfield txt 1))
  3422.              (chan (subfield txt 2)))
  3423.          (irc-insert "%%User %s is already on channel %s." nick chan))
  3424.            (irc-insert "%%Unknown ERR433 message seen in irc-parse-ERR:")
  3425.            (irc-insert "%% \"%s\" (txt)." txt)
  3426.            (irc-insert "%% Please tell %s." irc-hacker)))
  3427.       ((= num 444)
  3428.        (if (string-match "^\\([^: ]+\\) +:\\(.*\\)$" txt)
  3429.            (let ((user (subfield txt 1))
  3430.              (mesg (subfield txt 2)))
  3431.          (irc-insert "%%%sNo such user as \"%s\" logged in."
  3432.                  parorg user))
  3433.            (irc-insert "%%%sNo such user logged in." parorg)))
  3434.       ((= num 445)
  3435.        (irc-insert "%%%s%s" parorg txt))
  3436.       ((= num 446)
  3437.        (irc-insert "%%%sCommand /%s" parorg txt))
  3438.       ((= num 451)        ; ERR_NOTREGISTERED
  3439.        (irc-insert "%%%sYou haven't checked in yet.  Choose a nickname."
  3440.                parorg))
  3441.       ((= num 461)        ; ERR_NEEDMOREPARAMS
  3442.        (if (or (string= "" srvr)
  3443.            (string= (upcase irc-server) (upcase srvr)))
  3444.            (irc-insert (concat "%%%sThere weren't enough arguments for"
  3445.                    " the last command.")
  3446.                parorg)))
  3447.       ((= num 462)        ; ERR_ALREADYREGISTRED
  3448.        (irc-insert "%%%sYou've already registered." parorg))
  3449.       ((= num 463)        ; ERR_NOPERMFORHOST
  3450.        (irc-insert "%%%sYour host isn't permitted." parorg))
  3451.       ((= num 464)        ; ERR_PASSWDMISMATCH
  3452.        (irc-insert "%%%sThat password is incorrect." parorg))
  3453.       ((= num 465)        ; ERR_YOUREBANNEDCREEP
  3454.        (irc-insert "%%%sYou've been banned from IRC." parorg))
  3455.       ((= num 466)        ; ERR_YOUWILLBEBANNED
  3456.        (irc-insert "%%%sYou will be banned from IRC (%s)." parorg str))
  3457.       ((= num 467)
  3458.        (if (string-match "^\\([^ :]+\\) :" txt)
  3459.            (irc-insert (concat "%%%sChannel %s already has a key, use"
  3460.                    " /MODE %s to see it.")
  3461.                parorg
  3462.                (subfield txt 1)
  3463.                (subfield txt 1))
  3464.            (irc-insert (concat "%%%sChannel already has a key, use /MODE"
  3465.                    " to see it.")
  3466.                parorg)))
  3467.       ((= num 471)        ; ERR_CHANNELISFULL
  3468.        (string-match "^[^: ]+" txt)
  3469.        (let ((s (substring txt (match-beginning 0) (match-end 0))))
  3470.          (irc-insert (concat "%%%sChannel %s is full. (Check limit with"
  3471.                  " /MODE %s)")
  3472.              parorg s s)))
  3473.       ((= num 472)        ; ERR_UNKNOWNMODE
  3474.        (if (not (string-match (concat "^: *\\([^: ]+\\) +472 +"
  3475.                       "\\([^: ]+\\) +\\(.*\\) +:?is +"
  3476.                       "unknown +mode +char +to +me *$")
  3477.                   str))
  3478.            (progn (irc-insert (concat "%%Unrecognized type 472 message;"
  3479.                       " please tell %s:")
  3480.                   irc-hacker)
  3481.               (irc-insert "%% \"%s\"." str)
  3482.               (irc-insert "%% Function irc-parse-ERR, at 472."))
  3483.            (let ((srv (substring str (match-beginning 1) (match-end 1)))
  3484.              (nick (substring str (match-beginning 2) (match-end 2)))
  3485.              (chr (substring str (match-beginning 3) (match-end 3))))
  3486.          (if (not (string= (upcase srvr) (upcase srv)))
  3487.              (irc-remember srv 'irc-servernames))
  3488.          (irc-remember nick 'irc-nicknames)
  3489.          (irc-insert "%%Character \"%s\" is not a MODE character."
  3490.                  chr))))
  3491.       ((= num 473)        ; ERR_INVITEONLYCHAN
  3492.        (if (not (string-match (concat "^:[^: ]+ +473 +[^: ]+ +"
  3493.                       "\\([^ ]+\\) +.*")
  3494.                   str))
  3495.            (progn (irc-insert (concat "%%%sUnknown format on"
  3496.                       " ERR_INVITEONLYCHAN; please tell"
  3497.                       " %s, it might be a bug:")
  3498.                   parorg
  3499.                   irc-hacker)
  3500.               (irc-insert "%% \"%s\" (str)." str)
  3501.               (irc-insert "%% Function irc-parse-ERR, at 473."))
  3502.            (let ((chn (substring str (match-beginning 1) (match-end 1))))
  3503.          (irc-insert (concat "%%%sYou need an invitation to join"
  3504.                      " invitation-only channel \"%s\".")
  3505.                  parorg
  3506.                  chn))))
  3507.       ((= num 474)
  3508.        (cond
  3509.          ((string-match "^\\([^ ]+\\) +:" txt)
  3510.           (let ((channel (subfield txt 1)))
  3511.         (irc-insert (concat "%%Can't join channel %s -- you're"
  3512.                     " banned from it.")
  3513.                 channel)))
  3514.          (t (irc-insert "%%Unknown ERR474 seen in irc-parse-ERR:")
  3515.         (irc-insert "%% \"%s\" (txt)" txt)
  3516.         (irc-insert "%% Please tell %s, it might be a bug."
  3517.                 irc-hacker))))
  3518.       ((= num 475)            ;ERR_CANT_JOIN
  3519.        (cond ((string-match "^\\([^ ]+\\) +:" txt)
  3520.           (let ((channel (subfield txt 1)))
  3521.             (irc-insert (concat "%%Can't join channel %s -- you"
  3522.                     " haven't supplied the right channel"
  3523.                     " key/password."))))
  3524.          (t (irc-insert "%%Unknown ERR475 seen in irc-parse-ERR:")
  3525.             (irc-insert "%% \"%s\" (txt)" txt)
  3526.             (irc-insert "%% Please tell %s, it might be a bug."
  3527.                 irc-hacker))))
  3528.       ((= num 481)        ; ERR_NOPRIVILEGES
  3529.        (if (string= (upcase irc-server) (upcase srvr))
  3530.            (if (string-match "CHANNEL" str)
  3531.            (irc-insert
  3532.             (concat "%%%sYou must be a channel operator"
  3533.                 " to "
  3534.                 (cond
  3535.                   ((string-match (concat ":Cannot set topic, not"
  3536.                              " channel OPER$")
  3537.                          str)
  3538.                    "set the channels topic.")
  3539.                   (t "do that.")))
  3540.             parorg)
  3541.            (irc-insert (concat "%%%sYou must be an enabled IRC"
  3542.                        " Operator to do THAT!")
  3543.                    parorg))))
  3544.       ((= num 482)        ; ERR_NOOPERHOST
  3545.        (if (and (irc-server-has-channelname-in-msgs)
  3546.             (string-match "^\\([^ ]+\\) *:.*$" txt))
  3547.            (irc-insert "%%%sYou're not a channel operator for %s!"
  3548.                parorg
  3549.                (subfield txt 1))
  3550.            (irc-insert (concat "%%%sYou're not a channel operator on"
  3551.                    " that channel!")
  3552.                parorg)))
  3553.       ((= num 491)        ; ERR_NOOPERHOST
  3554.        (irc-insert (concat "%%Password check failed at server %s,"
  3555.                    " you're still a disabled luser.")
  3556.                (upcase srvr)))
  3557.       ((= num 501)        ; ERR_UMODEUNKNOWNFLAG
  3558.        (irc-insert "%%%s." txt))
  3559.       ((= num 502)        ; ERR_USERSDONTMATCH
  3560.        (irc-insert (concat "%%You can't change, not even look at, other"
  3561.                    " user's modes.")))
  3562.       ((= num 513)
  3563.        (if (string-match "^To connect, type /QUOTE PONG \\([1-9][0-9]*\\)$"
  3564.                  txt)
  3565.            (irc-send (format "PONG :%s" (subfield txt 1)))
  3566.          (irc-insert "%%Unknown MSG 513 \"%s\"" txt)))
  3567.       (t                                 ; default
  3568.        (irc-insert (concat "%%%sUnrecognized numeric ERR message"
  3569.                    " follows; please tell %s:")
  3570.                parorg
  3571.                irc-hacker)
  3572.        (irc-insert "%% \"%s\" (str)." str)
  3573.        (irc-insert "%%Function irc-parse-err, at catch all.")))))
  3574.   nil)
  3575.  
  3576.  
  3577. (defun irc-parse-error (str)
  3578.   "Examine an ERROR message from the IRC server.
  3579. ERROR is used when something bogus happens like an unparsable command
  3580. is issued to the server.  Usually this will not happen unless something
  3581. like /QUOTE is used.  This message is also used when a user attempts to
  3582. change to a name that already exists.
  3583.  
  3584. Returns nil; currently no signals are issued for an error."
  3585.   (string-match " +:" str)        ;Skip "^ERROR :"
  3586.   (setq str (substring str (match-end 0)))
  3587.   (cond
  3588.     ((string-match (concat "^ *Nickname +[^: ]* +\\(is \\)?"
  3589.                "\\(already\\|not +chan\\|in use\\) *$")
  3590.            str)
  3591.      (irc-insert "%%%s" str)
  3592.      ;; either we couldn't change the current nickname
  3593.      (setq irc-nick (or (and irc-nick (get 'irc-nick 'o-nick))
  3594.             ;; or we never even had one
  3595.             "NO NAME YET (/NICK to set one)"))
  3596.      (set-buffer-modified-p (buffer-modified-p))
  3597.      (irc-insert (if (get 'irc-nick 'o-nick)
  3598.              "%sHmmm ... looks like you're still \"%s\"%s" 
  3599.              "%s%s%s")
  3600.          irc-msg-info-pre
  3601.          irc-nick
  3602.          irc-msg-info-post))
  3603.     ((string-match " *No +option +specified. *Try +MAIL +HELP *$" str)
  3604.      (irc-insert "%%No option specified; try /HELP MAIL and /MAIL HELP."))
  3605.     ((or (string-match (concat "Closing +Link *: *\\([^[ :]+\\[[^]]+\\]\\)"
  3606.                    " *\\(\\)(\\(.*\\)) *$")
  3607.                str)
  3608.      (string-match (concat "Closing +Link *: *\\([^ :]+\\) +\\([^ :]+\\)"
  3609.                    " *\\(.\\|\n\\)+$")
  3610.                str))
  3611.      (let* ((id (subfield str 1))
  3612.         (srce (subfield str 2))
  3613.         (preason (subfield str 3))
  3614.         (reason (if (and (> (length preason) 0)
  3615.                  (= ?\050 (aref preason 0))
  3616.                  (= ?\051 (aref preason (1- (length preason)))))
  3617.             (substring preason 1 (1- (length preason)))
  3618.             preason))
  3619.         (matches (string-match "^\\([^[]+\\)\\[\\([^]]+\\)\\]$" id))
  3620.         (nick (if matches (subfield id 1) ""))
  3621.         (host (if matches (subfield id 2) "")))
  3622.        (irc-parse-quit (format ":%s QUIT %s :%s"
  3623.                    nick
  3624.                    nick
  3625.                    reason))))
  3626.     (t (irc-insert "%%%s" str)))
  3627.   nil)
  3628.  
  3629.  
  3630. (defun irc-parse-invite (str)
  3631.   "Examine an INVITE message from the IRC server.
  3632. INVITE is sent when one user invites another to a channel.
  3633. If the inviter is not being ignored a message is inserted in the buffer.
  3634.  
  3635. This function returns t if a bell should be issued for the \"invite\" event,
  3636. nil otherwise."
  3637.   (let ((user (substring str 1 (string-match " +INVITE " str)))
  3638.         (to (substring str (match-end 0)
  3639.                        (string-match " +:?" str (match-end 0))))
  3640.         (channel (substring str (match-end 0))))
  3641.     ;; glom a new name, if necessary
  3642.     (irc-remember user 'irc-nicknames)
  3643.     (if (irc-recall user 'irc-ignored-ppl)
  3644.         (irc-send (concat "NOTICE " user " :You are being ignored by \""
  3645.               irc-nick-used
  3646.               "\"."))
  3647.     (progn
  3648.       (irc-insert "%sUser %s invites %s to join channel %s%s"
  3649.               irc-msg-info-pre
  3650.               user
  3651.               (if (string= (downcase to) (downcase irc-nick-used))
  3652.               "you"
  3653.               to)
  3654.               (irc-clean-up-message channel)
  3655.               irc-msg-info-post)
  3656.       (irc-signal user 'invite)))))
  3657.  
  3658.  
  3659. (defun irc-parse-kick (str)
  3660.   "Examine and display a KICK message."
  3661.   (if (not
  3662.        (string-match "^: *\\([^: ]+\\) +KICK +\\([^: ]+\\) +\\([^: ]+\\) *"
  3663.              str))
  3664.       (progn (irc-insert (concat "%%Unknown format on KICK message; please"
  3665.                  " tell %s, it might be a bug:")
  3666.              irc-hacker)
  3667.          (irc-insert "%% \"%s\" (str)." str)
  3668.          (irc-insert "%% Function irc-parse-kick."))
  3669.       (let ((actor (substring str (match-beginning 1) (match-end 1)))
  3670.         (chan (substring str (match-beginning 2) (match-end 2)))
  3671.         (victim (substring str (match-beginning 3) (match-end 3))))
  3672.     (irc-remember actor 'irc-nicknames)
  3673.     (irc-remember victim 'irc-nicknames)
  3674.     (cond ((and (string= (upcase actor) (upcase victim))
  3675.             (string= (upcase actor) (upcase irc-nick-used)))
  3676.            (irc-insert "%sYou kicked yourself from channel %s%s"
  3677.                irc-msg-info-pre chan irc-msg-info-post))
  3678.           ((string= (upcase actor) (upcase victim))
  3679.            (irc-insert "%sUser %s kicked him/herself from channel %s%s"
  3680.                irc-msg-info-pre actor chan irc-msg-info-post))
  3681.           ((string= (upcase victim) (upcase irc-nick-used))
  3682.            (irc-insert (concat "%%You have been kicked out from"
  3683.                    " channel %s by user %s.")
  3684.                chan
  3685.                actor))
  3686.           ((string= (upcase actor) (upcase irc-nick-used))
  3687.            (irc-insert (concat "%sYou have kicked out user %s from"
  3688.                    " channel %s%s")
  3689.                irc-msg-info-pre
  3690.                victim
  3691.                chan
  3692.                irc-msg-info-post))
  3693.           (t (irc-insert (concat "%sUser %s kicked out user %s"
  3694.                      " from channel %s%s")
  3695.                  irc-msg-info-pre
  3696.                  actor
  3697.                  victim
  3698.                  chan
  3699.                  irc-msg-info-post)))
  3700.     (if (string= (upcase victim) (upcase irc-nick-used))
  3701.         ;; No need to irc-maintain the victim, -parse-chan does that.
  3702.         (progn (if (irc-server-has-multijoinable-channels)
  3703.                (irc-parse-channel (concat ":" victim " PART " chan))
  3704.                (irc-parse-channel (concat ":" victim " CHANNEL 0")))
  3705.            t)
  3706.         nil))))
  3707.  
  3708.  
  3709. (defun irc-parse-kill (str)
  3710.   "Examine a KILL message from the IRC server.
  3711. For a client this means its connexion will be closing momentarily.  This rather
  3712. drastic turn of events will always get a signal so this function returns t."
  3713.   (if (not (string-match "\\(:[^: ]+ +\\)?KILL +\\([^: ]+\\) +:" str))
  3714.       (progn
  3715.     (irc-insert "%%Spurios KILL message: \"%s\" (str) in irc-parse-kill."
  3716.             str)
  3717.     (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  3718.       (let* ((s (subfield str 1))
  3719.          (v (subfield str 2))
  3720.          (i (substring str (match-end 0)))
  3721.          (server (irc-nuke-whitespace s))
  3722.          (victim (irc-nuke-whitespace v))
  3723.          (info (irc-nuke-whitespace i)))
  3724.     (cond ((string-match "\\([^!]+\\)!\\([^! ]+\\) +"
  3725.                  info)
  3726.            (let* ((s (subfield info 1))
  3727.               (o (subfield info 2))
  3728.               (m (substring info (match-end 0)))
  3729.               (c (if (and (= ?\050 (aref m 0))
  3730.                   (= ?\051 (aref m (1- (length m)))))
  3731.                  (substring m 1 (1- (length m)))
  3732.                  m)))
  3733.          (if (string= (upcase irc-nick-used) (upcase victim))
  3734.              (irc-insert (concat "%sYou have been /KILL'ed by operator"
  3735.                      " %s@%s (%s)%s")
  3736.                  irc-msg-info-pre
  3737.                  (irc-nuke-whitespace o)
  3738.                  (irc-nuke-whitespace s)
  3739.                  (irc-nuke-whitespace c)
  3740.                  irc-msg-info-post)
  3741.              (irc-insert "%sOperator %s@%s /KILL'ed user %s (%s)%s"
  3742.                  irc-msg-info-pre
  3743.                  (irc-nuke-whitespace o)
  3744.                  (irc-nuke-whitespace s)
  3745.                  victim
  3746.                  (irc-nuke-whitespace m)
  3747.                  irc-msg-info-post))))
  3748.           (t (irc-insert "%sUser %s KILL'ed by %s%s"
  3749.                  irc-msg-info-pre
  3750.                  victim
  3751.                  info
  3752.                  irc-msg-info-post)))))
  3753.   t)
  3754.  
  3755.  
  3756. (defun irc-parse-linreply (str)
  3757.   "Examine a LINREPLY message from the IRC server.
  3758. LINREPLY is used to answer a LINKS request to show all the servers on line.
  3759. \"Links\" is a bit of a misnomer since little information regarding the
  3760. actual structure of the IRCnet can be gained from these messages.
  3761.  
  3762. No signals are issued for lines from the LINREPLY."
  3763.   (if (not (string-match "^LINREPLY +\\([^: ]+\\) +" str))
  3764.       (progn (irc-insert (concat "%%Unkown LINREPLY format in "
  3765.                  "function irc-parse-linreply:"))
  3766.          (irc-insert "%% \"%s\"." str)
  3767.          (irc-insert "%% Please tell %s, it may be a bug." irc-hacker))
  3768.       (let ((old-mark irc-mark)
  3769.         (server-name (substring str (match-beginning 1) (match-end 1)))
  3770.         (server-info (irc-clean-up-message (substring str (match-end 0)))))
  3771.     (irc-remember server-name 'irc-servernames)
  3772.     (if (and (irc-terminal-is-slow)
  3773.          (or (irc-server-has-end-of-links) ;New server version ?
  3774.              (and (= irc-major-version 2) (= irc-minor-version 2))))
  3775.         (progn (irc-remember (format "Server %s: %s"
  3776.                      (upcase server-name)
  3777.                      server-info)
  3778.                  'irc-linksinfo)
  3779.            (if (and (not (irc-terminal-is-slow))
  3780.                 (string= (upcase server-name) (upcase irc-server)))
  3781.                (progn
  3782.              (irc-insert irc-links-header)
  3783.              (irc-insert irc-links-stroke)
  3784.              (set-buffer-modified-p (buffer-modified-p))
  3785.              (irc-recall-all-and-display 'irc-linksinfo
  3786.                              (progn
  3787.                                (string-match
  3788.                             "^[^: ]* ."
  3789.                             irc-links-header)
  3790.                                (match-end 0))
  3791.                              "servers"
  3792.                              "server")
  3793.              (irc-forget-all 'irc-linksinfo))))
  3794.     (progn (irc-insert "Server %s: %s"
  3795.                    (upcase server-name)
  3796.                    server-info)))))
  3797.   nil)
  3798.  
  3799.  
  3800. (defun irc-parse-mode-reply (str)
  3801.   "Examine a MODE reply message from the IRC server.
  3802. MODE replies are used in respnse to the MODE command to indicate the current,
  3803. ie new, status of a specified channel or user.
  3804.  
  3805. No signals are issued for MODE replies."
  3806.   (cond ((string-match (concat "^ *: *\\([^: ]+\\) +MODE +"
  3807.                    "\\([^: ]+\\) +:? *")
  3808.                str)
  3809.      (let ((orig (subfield str 1))
  3810.            (chan (subfield str 2))
  3811.            (mode (irc-nuke-whitespace (substring str (match-end 0)))) )
  3812.        (cond ((irc-is-hostname orig)
  3813.           (irc-remember orig 'irc-servernames))
  3814.          ((irc-is-nickname orig)
  3815.           (irc-remember orig 'irc-nicknames)))
  3816.        (cond ((irc-is-nickname chan)
  3817.           (let ((i (1- (length mode)))
  3818.             (um (upcase mode)))
  3819.             (while (and (>= i 0) (not (= ?O (aref um i))))
  3820.               (setq i (1- i)))
  3821.             (while (and (>= i 0)
  3822.                 (not (= ?- (aref um i)))
  3823.                 (not (= ?+ (aref um i))))
  3824.               (setq i (1- i)))
  3825.             (if (and (>= i 0) (= ?- (aref um i)))
  3826.             (setq irc-operator nil)
  3827.             (set-buffer-modified-p (buffer-modified-p))))
  3828.           (irc-insert "%sMode for user %s changed by %s: %s%s"
  3829.                   irc-msg-info-pre
  3830.                   chan
  3831.                   orig
  3832.                   (irc-explain-user-mode mode)
  3833.                   irc-msg-info-post))
  3834.          ((irc-is-nickname orig)
  3835.           (irc-insert "%sUser %s changed mode for channel %s: %s%s"
  3836.                   irc-msg-info-pre
  3837.                   orig
  3838.                   chan
  3839.                   (irc-explain-channel-mode mode)
  3840.                   irc-msg-info-post))
  3841.          ((irc-is-hostname orig)
  3842.           (irc-remember orig 'irc-servernames))
  3843.          (t (irc-insert "%%Unknown sender in irc-parse-mode-reply:")
  3844.             (irc-insert "%% \"%s\" (str), \"%s\" (orig)." str orig)
  3845.             (irc-insert "%% Please tell %s, this might be a bug."
  3846.                 irc-hacker)))))
  3847.     (t (irc-insert "%%Unkown format on MODE reply; please tell %s:"
  3848.                irc-hacker)
  3849.        (irc-insert "%% \"%s\"." str)
  3850.        (irc-insert "%% Function irc-parse-mode-reply.")))
  3851.   nil)
  3852.  
  3853.  
  3854. (defun irc-parse-namreply (str)
  3855.   "Examine a NAMREPLY message from the IRC server.
  3856. NAMREPLY is used in repsonse to NAMES to indicate what users are on what
  3857. channels.  All users on secret or private channels which the client is not
  3858. on are grouped together on one private channel.
  3859.  
  3860. No signals are issued for NAMREPLYs."
  3861.   (if (not (string-match "^NAMREPLY +[^ ]+ +\\([^ ]+\\) +" str))
  3862.       (progn (irc-insert (concat "%%Unknown format on NAMREPLY message,"
  3863.                  " in function IRC-PARSE-NAMREPLY:"))
  3864.          (irc-insert "%% \"%s\"." str))
  3865.       (let* ((channel (substring str (match-beginning 1) (match-end 1)))
  3866.          (users (substring str (match-end 0)))
  3867.          (count 0)
  3868.          (to-insert "")
  3869.          (nick nil)
  3870.          (format-string "%s  %3d   %s")
  3871.          (irc-msg-cont-used irc-names-cont-msg))
  3872.     ;; yet another source of information for irc-nicknames.
  3873.     (while (string-match "^\\([^ ]+\\)\\( \\|$\\)" users)
  3874.       (setq nick (substring users 0 (match-end 1))
  3875.         users (substring users (match-end 0))
  3876.         count (1+ count)
  3877.         to-insert (concat to-insert " " nick))
  3878.       (irc-remember nick 'irc-nicknames)) 
  3879.     (if (and (irc-terminal-is-slow) (irc-server-has-end-of-names))
  3880.         (let ((lin (format format-string
  3881.                 (irc-format-channel channel)
  3882.                    count
  3883.                    (irc-clean-up-message to-insert))))
  3884.           (setq irc-reply-count (1+ irc-reply-count))
  3885.           (let ((diff (irc-time-diff (irc-current-time)
  3886.                      irc-reply-count-time)))
  3887.         (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since last
  3888.                (> (nth 0 diff) 0)) ; display?
  3889.                (setq irc-reply-count-time (irc-current-time))
  3890.                (message (format " %d channel%s ..."
  3891.                     irc-reply-count
  3892.                     (if (= 1 irc-reply-count) "" "s"))))))
  3893.           (irc-remember lin 'irc-namtree))
  3894.         (irc-insert format-string
  3895.             (irc-format-channel channel)
  3896.             count
  3897.             (irc-clean-up-message to-insert)))))
  3898.   nil)
  3899.  
  3900.  
  3901. (defun irc-parse-nick (str)
  3902.   "Examine a NICK message from the IRC server.
  3903. NICK is sent when a user's nickname is changed, but it is only sent to the
  3904. people on the same channel as the user.  If the person changing names is
  3905. being ignored, this fact is tracked across the change.  If notification
  3906. is not enabled for \"nick\" then no message is inserted.
  3907.  
  3908. This function returns t if a signal should be issued for the \"nick\" event,
  3909. nil otherwise."
  3910.   (cond ((string-match "^: *\\([^ :]+\\) +NICK +:?\\([^ :]+\\) *$" str)
  3911.      (let* ((old (subfield str 1))
  3912.         (new (subfield str 2))
  3913.         (current irc-nick-used))
  3914.        (if (not (irc-recall old 'irc-services)) ;Always keep /services.
  3915.            (irc-forget old 'irc-nicknames))
  3916.        (irc-remember new 'irc-nicknames)
  3917.        (cond ((string= (upcase irc-nick-used) (upcase old))
  3918.           ;; Our own nick has changed.
  3919.           (setq irc-nick-used new)
  3920.           (set-buffer-modified-p (buffer-modified-p))))
  3921.        (cond ((irc-recall old 'irc-ignored-ppl)
  3922.           (irc-forget old 'irc-ignored-ppl)
  3923.           (irc-remember new 'irc-ignored-ppl)
  3924.           nil)            ;Don't signal this.
  3925.          ((and (memq 'nick irc-events)
  3926.                (not (string= (upcase new) (upcase current))))
  3927.           (irc-insert "%s%s is now known as %s%s"
  3928.                   irc-msg-info-pre old new irc-msg-info-post)
  3929.           (irc-signal old 'user))
  3930.          (t nil))))
  3931.     (t (irc-insert "%%Unknown NICK seen in irc-parse-nick:")
  3932.        (irc-insert "%% \"%s\" (str)." str)
  3933.        (irc-insert "%% Please tell %s, this might be a bug." irc-hacker))))
  3934.  
  3935.  
  3936. ;irc-remember
  3937. (defun irc-parse-notice (str)
  3938.   "Examine a NOTICE message from the IRC server.
  3939. NOTICE is the catch-all for IRC messages; if it can't be classified as
  3940. one of the other currently existing messages then the information is
  3941. sent as NOTICE.  This message is overused, even when it another could be
  3942. used instead.  For example, if an attempt is made to send to a nickname
  3943. which is not on IRC the error reply is sent via NOTICE.
  3944.  
  3945. No signal is issued for NOTICE because it is way too random with what it
  3946. means."
  3947.   (let* ((lst (if (string-match (concat "^ *:? *\\([^: ]*\\)? *NOTICE *"
  3948.                     "\\([^: ]*\\)? *:")
  3949.                 str)
  3950.           (list (substring str (match-beginning 1) (match-end 1)) ;srvr
  3951.             (substring str (match-beginning 2) (match-end 2)) ;rcvr
  3952.             (substring str (match-end 0))) ;msg
  3953.           (list "" "" str)))
  3954.      (srvnam (if (string= (car lst) "") irc-server (car lst)))
  3955.      (srvr (if (string= (upcase srvnam) (upcase irc-server)) "" srvnam))
  3956.      (parorg (if (string= "" srvr) "" (concat "(" srvr ") ")))
  3957.      (rcvr (car (cdr lst)))
  3958.      (msg (car (cdr (cdr lst))))
  3959.      (cmsg (irc-clean-up-message msg))
  3960.      (retval nil))            ;Kludge!
  3961.     (if (not (stringp irc-server))
  3962.     (setq irc-server (if (stringp (default-value 'irc-server))
  3963.                  (default-value 'irc-server)
  3964.                  "")))
  3965.     (if (and rcvr (irc-is-nickname rcvr))
  3966.     (setq irc-nick-used rcvr))
  3967.     (irc-remember srvr 'irc-servernames)
  3968.     (cond
  3969.       ((and (string= "POXAV" (upcase srvr))
  3970.         (string-match "weenie" msg))
  3971.        )
  3972.       ((irc-recall srvr 'irc-services)
  3973.        (irc-remember srvr 'irc-services) ;Update spelling.
  3974.        (irc-remember srvr 'irc-nicknames)
  3975.        (irc-insert "%s%s%s %s"
  3976.            irc-msg-info-pre srvr irc-msg-info-post cmsg))
  3977.       ((string-match (concat "^\\*\\*\\* *Notice *-- *Access *denied *"
  3978.                  "(\\(.*\\)) *\\(.*\\) *$")
  3979.              msg)
  3980.        (let ((reason (subfield msg 1))
  3981.          (refused-server (subfield msg 2)))
  3982.      (irc-insert "%%Refused server-link connection from server %s: %s."
  3983.              (upcase refused-server)
  3984.              reason)))
  3985.       ((string-match (concat "^\\*\\*\\* *Notice *-- *Rehashing *Server"
  3986.                  " *config *file *(\\(.*\\)) *$")
  3987.              msg)
  3988.        (let ((file (subfield msg 1)))
  3989.      (irc-insert "%sServer %s has reloaded it's configuration file %s%s"
  3990.              irc-msg-info-pre
  3991.              (upcase srvnam)
  3992.              file
  3993.              irc-msg-info-post)))
  3994.       ((string-match (concat "^\\*\\*\\* *Notice *-- *\\(Hack\\|Fake\\) *:"
  3995.                  " *\\([^ ]+\\) +MODE +\\([^ ]+\\)"
  3996.                  " *\\([^ ]*\\).*$")
  3997.              msg)
  3998.        ;;Ignore this information. It's just a way for enabled operators on 2.7
  3999.        ;; server to see people on 2.6 server as they join channels with initial
  4000.        ;; modes, such as secret or private. Hopefulle this will go away when
  4001.        ;; 2.6 servers go way.
  4002.        (let ((user (subfield msg 2))
  4003.          (channel (subfield msg 3))
  4004.          (mode (irc-nuke-whitespace (subfield msg 4))))
  4005.      (cond ((string-match "\\+[^-]*[sp]" mode)
  4006.         (irc-insert (concat "%sWarning a user about seeing her/his"
  4007.                     " secret channel join%s")
  4008.                 irc-msg-info-pre irc-msg-info-post)
  4009.         (irc-send (concat "NOTICE " user " :<Automatic warning> My"
  4010.                   " client (but not I myself -- I don't even"
  4011.                   " know who you are unless you'll tell me or"
  4012.                   " you happen to be marked as being AWAY)"
  4013.                   " saw you join channel "
  4014.                   channel
  4015.                   " ("
  4016.                   mode
  4017.                   "). The fact was broadcasted to everyone"
  4018.                   " seeing WALLOPS messages on 2.7 (and later)"
  4019.                   " servers. Your channel is probably"
  4020.                   " without any special mode on other servers."
  4021.                   " (But still look \"valid\" at yous site)."
  4022.                   " If you have any questions, then don't send"
  4023.                   " them to "
  4024.                   irc-nick
  4025.                   " but to the channel #Twilight_Zone."
  4026.                   ))
  4027.         (irc-send (concat "NOTICE " user " :<Automatic warning> If"
  4028.                   " you don't care about getting warned, but"
  4029.                   " want to think you're invisible while being"
  4030.                   " visible, and you happen to use a Kiwi"
  4031.                   " client, you can do M-x set-variable RET"
  4032.                   " irc-ignore-automatic-warnings RET t"
  4033.                   " RET. If you're using ircII, instead do"
  4034.                   " /on ^notice \"" irc-nick " <Automatic"
  4035.                   " warning>*\: /^comment"))
  4036.         ))))
  4037.       ((string-match (concat "^\\*\\*\\* Message-of-today is missing"
  4038.                  " on host \\([^: ]+\\)? *$")
  4039.              msg)
  4040.        (let ((host (irc-clean-up-message (subfield msg 1))))
  4041.      (if (not (string= (upcase srvr) (upcase host)))
  4042.          (irc-remember host 'irc-servernames))
  4043.      (irc-insert "%%%sNo message of the day at server %s."
  4044.              (if (or (string= srvr irc-server)
  4045.                  (string= srvr ""))
  4046.              ""
  4047.              (concat "(" srvr ") "))
  4048.              (upcase host))))
  4049.       ((string-match "^MOTD *- ?*\\([^: ]+\\)? *message +of +the +day *-? *$"
  4050.              msg)
  4051.        (let ((server (irc-clean-up-message (substring msg
  4052.                               (match-beginning 1)
  4053.                               (match-end 1)))))
  4054.      (if (not (string= (upcase srvr) (upcase server)))
  4055.          (irc-remember server 'irc-servernames))
  4056.      (irc-insert "")
  4057.      (irc-insert ">>> Message of the day at server %s:" server)
  4058.      (set-buffer-modified-p (buffer-modified-p))))
  4059.       ((string-match "^MOTD *- ?" msg)
  4060.        (setq irc-motd-lines (append irc-motd-lines
  4061.                     (list (irc-clean-up-message
  4062.                        (substring msg (match-end 0)))))))
  4063.       ((string-match "^\\* *end +of +/?motd +command. *$" msg)
  4064.        (while irc-motd-lines
  4065.      (irc-insert ">>> %s" (car irc-motd-lines))
  4066.      (setq irc-motd-lines (cdr irc-motd-lines))))
  4067.       ((string-match (concat "^\\*\\*\\* *Error *: *No +mere +mortals +"
  4068.                  "may +trace +the +nets +of +the +universe *$")
  4069.              msg)
  4070.        (irc-insert (concat "%%%sYou must be an enabled IRC operator to trace"
  4071.                " the IRCnet, use /OPER to enable yourself. An"
  4072.                " alternative is to use /STATS L, do /HELP STATS.")
  4073.            parorg))
  4074.       ((string-match "^Good afternoon, gentleman\\. I am a HAL 9000" msg)
  4075.        (if (string= srvr "")
  4076.        (irc-insert "%sOperator status for %s ENABLED%s"
  4077.                irc-msg-info-pre
  4078.                irc-nick-used
  4079.                irc-msg-info-post)
  4080.        (irc-insert "%sOperator status at %s for %s ENABLED%s"
  4081.                irc-msg-info-pre
  4082.                srvr
  4083.                irc-nick-used
  4084.                irc-msg-info-post))
  4085.        ;; we've been granted operator privileges.  the string is for mode-line
  4086.        (setq irc-operator " IOPR")
  4087.        (set-buffer-modified-p (buffer-modified-p)))
  4088.       ((string-match (concat "^\\*\\*\\* *notice *-- *Received"
  4089.                  " +unauthorized +connection +from +")
  4090.              msg)
  4091.        (irc-insert (concat "%%Something at internet host %s tried to"
  4092.                " establish a connection with us. Refused"
  4093.                " as it isn't enabled in the confiugation file.")
  4094.            (irc-nuke-whitespace (substring msg (match-end 0)))))
  4095.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\) *Link"
  4096.                  " +with +\\([^ ]+\\) +established"
  4097.                  " *.? *$")
  4098.              msg)
  4099.        ;; In a few seconds, we ought to issue a LINKS command to the server,
  4100.        ;; but without displaying the answer, only storing it. Sigh.
  4101.        (let* ((h (irc-extract-hostname
  4102.           (irc-clean-up-message
  4103.            (subfield msg 2))))
  4104.           (host (if (stringp h) h "")))
  4105.      (if (not (string= (upcase srvr) (upcase host)))
  4106.          (irc-remember host 'irc-servernames))
  4107.      (irc-insert "%s%sLink with %s established%s"
  4108.              irc-msg-info-pre
  4109.              (if (string= srvr "") "" (concat "(" srvr ")"))
  4110.              (upcase host)
  4111.              irc-msg-info-post))
  4112.        (irc-later-execute-lusers))
  4113.       ((or (string-match (concat "^\\*\\*\\* *\\([^ ]+\\) +\\([^:]+\\) *"
  4114.                  "==> *\\(.+\\) *$")
  4115.              cmsg)
  4116.        ;; 2.6 following
  4117.        (string-match (concat "^\\*\\*\\* +\\(Connection\\) +\\([^ ]+\\) +"
  4118.                  "==> +\\([^ ]+\\) +\\[\\([^ ]+\\)\\] *$")
  4119.              cmsg)
  4120.        (string-match (concat "^\\*\\*\\* +\\(Connection\\) +\\([^ ]+\\) +"
  4121.                  "==> +\\([^ ]+\\) *$")
  4122.              cmsg)
  4123.        (string-match (concat "^\\*\\*\\* +\\(Link\\) +\\([^ ]+\\) +"
  4124.                  "==> +\\([^ ]+\\) *$")
  4125.              cmsg)
  4126.        (string-match (concat "^\\*\\*\\* +\\(<newtype>\\) +\\([^ ]+\\) +"
  4127.                  "==> +\\([^ ]+\\) *$")
  4128.              cmsg))
  4129.        (let* ((type (substring cmsg (match-beginning 1) (match-end 1)))
  4130.           (lcl (substring cmsg (match-beginning 2) (match-end 2)))
  4131.           (remote (substring cmsg (match-beginning 3) (match-end 3)))
  4132.           (address (if (match-beginning 4)
  4133.                (substring cmsg (match-beginning 4) (match-end 4))
  4134.                remote))
  4135.           (extra (cond
  4136.                ((not (string= (upcase remote) (upcase address)))
  4137.             (concat "(" address ")"))
  4138.                ((string-match
  4139.              "^\\([^ ]+\\) +\\([0-9]+\\)S +\\([0-9]+\\)C$"
  4140.              remote)
  4141.             (let ((x (subfield remote 1))
  4142.                   (s (string-to-int (subfield remote 2)))
  4143.                   (c (string-to-int (subfield remote 3))))
  4144.               (setq remote x)
  4145.               (format " (%d server%s, %d client%s)"
  4146.                   s
  4147.                   (if (= 1 s) "" "s")
  4148.                   c
  4149.                   (if (= 1 c) "" "s"))))
  4150.                (t "")))
  4151.           (p (cond
  4152.            ((string-match "^ *CLASS\\[\\([0-9]+\\)\\] +\\([^: ]+\\) *$"
  4153.                   lcl)
  4154.             (cons (subfield lcl 2) (subfield lcl 1)))
  4155.            ((string-match "^ *CLASS\\[\\([0-9]+\\)\\] *$" lcl)
  4156.             (cons srvr (subfield lcl 1)))
  4157.            (t (cons lcl nil))))
  4158.           (local (irc-nuke-whitespace (car p)))
  4159.           (class (cdr p))
  4160.           (lserv (irc-extract-hostname local))
  4161.           (rserv (irc-extract-hostname remote)))
  4162.      (if (and lserv (not (string= (upcase srvr) (upcase lserv))))
  4163.          (irc-remember lserv 'irc-servernames))
  4164.      (if (and rserv (not (string= (upcase srvr) (upcase rserv))))
  4165.          (irc-remember remote 'irc-servernames))
  4166.      (cond
  4167.        ((string= (upcase type) "LINK")
  4168.         (irc-insert "%s%s to %s%s goes through %s%s"
  4169.             irc-msg-info-pre
  4170.             type
  4171.             (upcase remote)
  4172.             extra
  4173.             (upcase local)
  4174.             irc-msg-info-post))
  4175.        ((and (string-match "\\(CHANOP\\|OPER\\|USER\\)" (upcase type))
  4176.          (numberp (string-match "^\\([^[]*\\)\\[\\([^: ]+\\)\\]$"
  4177.                     remote)))
  4178.         (let ((user (subfield remote 1))
  4179.           (cm (subfield remote 2)))
  4180.           (irc-remember user 'irc-nicknames)
  4181.           (if (stringp class)
  4182.           (irc-insert
  4183.            "%s%s of class %3s at server %s: \"%s\" (client on %s)%s"
  4184.            irc-msg-info-pre
  4185.            type
  4186.            class
  4187.            (upcase local)
  4188.            user
  4189.            (upcase cm)
  4190.            irc-msg-info-post)
  4191.           (irc-insert "%s%s at server %s: \"%s\" (client on %s)%s"
  4192.                   irc-msg-info-pre
  4193.                   type
  4194.                   (upcase local)
  4195.                   user
  4196.                   (upcase cm)
  4197.                   irc-msg-info-post))))
  4198.        ((and (string-match "\\(UNKNOWN\\)" (upcase type))
  4199.          (numberp (string-match "^\\([^[]*\\)\\[\\([^: ]+\\)\\]$"
  4200.                     remote)))
  4201.         (let ((cm (substring remote
  4202.                  (match-beginning 2)
  4203.                  (match-end 2))))
  4204.           (irc-insert (concat "%s%s at server %s from internet"
  4205.                   " host %s%s")
  4206.               irc-msg-info-pre
  4207.               (cond ((string= "UNKNOWN" (upcase type))
  4208.                  "Half open connection")
  4209.                 (t (concat "<Unknown type (%s) in function"
  4210.                        " irc-parse-notice, please"
  4211.                        " tell "
  4212.                        irc-hacker
  4213.                        ">")))
  4214.               (upcase local)
  4215.               (upcase cm)
  4216.               irc-msg-info-post)))
  4217.        (t (irc-insert "%s%s at server %s to%s server %s%s%s"
  4218.               irc-msg-info-pre
  4219.               (cond ((string= (upcase type) "CONNECTION")
  4220.                  "Serverlink")
  4221.                 ((string= (upcase type) "CONNECTING")
  4222.                  "Server-search")
  4223.                 (t type))
  4224.               (upcase local)
  4225.               (if (stringp class)
  4226.                   (format " class %3s" class)
  4227.                   "")
  4228.               (upcase remote)
  4229.               (downcase extra)
  4230.               irc-msg-info-post)))))
  4231.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\)"
  4232.                  " *No +response +from +"
  4233.                  "\\([^ ]+\\) *, *closing +link *$")
  4234.              cmsg)
  4235.        (irc-insert "%%Closed serverlink to %s due to lack of respone."
  4236.            (substring cmsg (match-beginning 2) (match-end 2)))
  4237.        (irc-later-execute-lusers))
  4238.       ((string-match (concat "^\\*\\*\\* *Class +\\([0-9]+\\) *"
  4239.                  "Entries *linked *: *\\([0-9]+\\) *$")
  4240.              cmsg)
  4241.        (let ((class (string-to-int (subfield cmsg 1)))
  4242.          (count (string-to-int (subfield cmsg 2))))
  4243.      (irc-insert "%s%s%d service%s linked for class %3d%s"
  4244.              irc-msg-info-pre
  4245.              parorg
  4246.              count
  4247.              (if (= 1 count) "" "s")
  4248.              class
  4249.              irc-msg-info-post)))
  4250.       ((string-match (concat "^\\([A-Za-z]+\\) +has +been +used +"
  4251.                  "\\([0-9]+\\) +times? +after +"
  4252.                  "startup *$")
  4253.              cmsg)
  4254.        (let ((cmd (substring cmsg (match-beginning 1) (match-end 1)))
  4255.          (cnt (substring cmsg (match-beginning 2) (match-end 2))))
  4256.      (irc-insert "%sServer %s has seen %s%s command%s of type %s%s"
  4257.              irc-msg-info-pre
  4258.              (upcase (if (string= srvr "") irc-server srvr))
  4259.              (make-string (max 0 (- 5 (length cnt))) ? )
  4260.              cnt
  4261.              (if (string= cnt "1") " " "s")
  4262.              cmd
  4263.              irc-msg-info-post)))
  4264.       ((string-match "^\\*\\*\\* *No +such +server *" cmsg)
  4265.        (let ((unknown (substring cmsg (match-end 0))))
  4266.      (irc-forget unknown 'irc-servernames)
  4267.      (irc-insert "%%%sNo such server: \"%s\"."
  4268.              (if (string= "" srvr)
  4269.              ""
  4270.              (concat "(" srvr ")"))
  4271.              unknown)))
  4272.       ((string-match (concat "^\\*\\*\\* *unknown \\([^: ]+\\) *==> *"
  4273.                  "\\([^: ]+\\) *$")
  4274.              cmsg)
  4275.        (irc-insert "%sUnknown connection at server %s to host %s%s"
  4276.            irc-msg-info-pre
  4277.            (upcase (substring cmsg (match-beginning 1) (match-end 1)))
  4278.            (upcase (substring cmsg (match-beginning 2) (match-end 2)))
  4279.            irc-msg-info-post))
  4280.       ((string-match (concat "^\\*\\*\\* *\\(User\\)?\\(ChanOp\\)?"
  4281.                  "\\(Oper\\)? +\\([^: ]+\\) *==> *"
  4282.                  "\\([^: ]*\\) *\\[\\(.\\|\n\\)*\\] *$")
  4283.              cmsg)
  4284.        (let* ((first (substring cmsg
  4285.                 (or (match-beginning 1) 0)
  4286.                 (or (match-end 1) 0)))
  4287.           (second (substring cmsg
  4288.                  (or (match-beginning 2) 0)
  4289.                  (or (match-end 2) 0)))
  4290.           (third (substring cmsg
  4291.                 (or (match-beginning 3) 0)
  4292.                 (or (match-end 3) 0)))
  4293.           (srvr (substring cmsg (match-beginning 4) (match-end 4)))
  4294.           (nick (substring cmsg (match-beginning 5) (match-end 5)))
  4295.           (client (substring cmsg (match-beginning 6) (match-end 6)))
  4296.           (type (cond ((not (string= "" first)) "User")
  4297.               ((not (string= "" second)) "Channel operator")
  4298.               ((not (string= "" third)) "IRC operator")
  4299.               (t "?UNKNOWN?"))))
  4300.      (irc-remember nick 'irc-nicknames)
  4301.      (irc-insert "%s%s at server %s: \"%s\" (client on %s)%s"
  4302.              irc-msg-info-pre
  4303.              type
  4304.              (upcase srvr)
  4305.              nick
  4306.              (upcase client)
  4307.              irc-msg-info-post)))
  4308.       ((string-match (concat "^\\(\\*\\*\\*\\)? *\\([0-9]+\\) +users* +"
  4309.                  "\\(have\\|has\\) +connection +to +the +"
  4310.                  "twilight +zone *$")
  4311.              cmsg)
  4312.        (let ((n (string-to-int (subfield cmsg 2))))
  4313.      (irc-insert "*** There %s %d enabled operator%s online."
  4314.              (if (= 1 n) "is" "are")
  4315.              n
  4316.              (if (= 1 n) "" "s"))))
  4317.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There \\(is\\|are\\) +"
  4318.                   "+\\([0-9]+\\) +channels*. *$")
  4319.               cmsg)
  4320.         (let ((n (string-to-int (subfield cmsg 3))))
  4321.       (irc-insert "*** There %s %d channel%s."
  4322.               (if (= 1 n) "is" "are")
  4323.               n
  4324.               (if (= 1 n) "" "s"))))
  4325.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There \\(is\\|are\\) +"
  4326.                   "+\\([0-9]+\\) +clients* +connected +"
  4327.                   "to +\\([^ ,]+\\).*$")
  4328.               cmsg)
  4329.         (let ((n (string-to-int (subfield cmsg 3)))
  4330.           (s (subfield cmsg 4)))
  4331.       (irc-insert "*** There %s %d client%s on %s."
  4332.               (if (= 1 n) "is" "are")
  4333.               n
  4334.               (if (= 1 n) "" "s")
  4335.               s)))
  4336.       ((string-match "^###" cmsg)
  4337.        (let ((m (substring cmsg (match-end 0))))
  4338.      (irc-insert "###%s%s"
  4339.              (if (or (string= "" srvr)
  4340.                  (string= (upcase srvr) (upcase irc-server)))
  4341.              ""
  4342.              (concat "(" srvr ")"))
  4343.              m)))
  4344.       ((string-match (concat "^\\*\\*\\* *welcome +to +the +internet +"
  4345.                  "relay +network *, *\\([^: ]+\\) *$")
  4346.              cmsg)        ;v2.4 welcome message
  4347.        (let ((user (subfield cmsg 1)))
  4348.      (irc-remember user 'irc-nicknames)))
  4349.       ((string-match (concat "^\\*\\*\\* *Your +host +is +"
  4350.                  "\\([^ ,]+\\) *, *running +version +"
  4351.                  "\\([^: ]+\\) *$")
  4352.              cmsg)
  4353.        (let* ((s (subfield cmsg 1))
  4354.           (vrsn (subfield cmsg 2))
  4355.           (s (downcase (irc-extract-hostname s))) ;REAL GENERIC servername
  4356.           (cur-bufname (buffer-name (current-buffer)))
  4357.           (new-bufname (irc-host+port-to-buffer-name s irc-port))
  4358.           (pre-kludge nil))
  4359.      (setq-default irc-server s)
  4360.      (setq irc-server s)
  4361.      (if (string< cur-bufname new-bufname)
  4362.          (rename-buffer new-bufname))
  4363.      (if (not (string= (upcase srvr) (upcase s)))
  4364.          (irc-remember s 'irc-servernames))
  4365.      (if (or (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4366.                        "[^0-9]+\\([0-9]+\\)\\([^0-9]+\\)"
  4367.                        "\\([0-9]+\\)")
  4368.                    vrsn)
  4369.          (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4370.                        "[^0-9]+\\([0-9]+\\)\\(\\)")
  4371.                    vrsn)
  4372.          (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4373.                        "\\(\\)\\(\\)")
  4374.                    vrsn))
  4375.          (let* ((type nil)
  4376.             (major (subfield vrsn 2))
  4377.             (minor (subfield vrsn 3))
  4378.             (kludge (subfield vrsn 4))
  4379.             (edit (subfield vrsn 5))
  4380.             (minor (if (string= "" minor) 0 (string-to-int minor)))
  4381.             (edit (if (string= "" edit) 0 (string-to-int edit))))
  4382.            (if (string-match "^u" major)
  4383.            (setq type (format "%c" (aref major 0))
  4384.              major (substring major 1)))
  4385.            (setq irc-type-version type
  4386.              irc-major-version (string-to-int major)
  4387.              irc-minor-version minor
  4388.              pre-kludge kludge
  4389.              irc-edit-version edit)
  4390.            )
  4391.          (irc-insert "%%Failed parsing vrsn \"%s\" in irc-parse-notice."
  4392.              vrsn))
  4393.      (if (and (= irc-major-version 2)
  4394.           (= irc-minor-version 6)
  4395.           (not (string= (upcase pre-kludge) "PRE")))
  4396.          (setq irc-edit-version (+ 10000 irc-edit-version)))
  4397.      (irc-insert "")
  4398.      (irc-insert "*** Welcome to the IRC server at %s!" s)
  4399.      (irc-insert "*** The server's version is %s," vrsn)))
  4400.       ((string-match "^\\*\\*\\* *This +server +was +created +"
  4401.              cmsg)
  4402.        (irc-insert "*** and it was created %s."
  4403.            (substring cmsg (match-end 0))))
  4404.       ;; Hello message from a 2.2 server.
  4405.       ((string-match (concat "^\\*\\*\\* *Welcome +to +Internet +Relay +"
  4406.                  "Server *")
  4407.              cmsg)
  4408.        (let ((vrsn (irc-nuke-whitespace (substring cmsg (match-end 0)))))
  4409.      (if (string-match (concat "^[^0-9]*\\([0-9]+\\)\\.\\([0-9]+\\)"
  4410.                    "[^0-9]+\\([0-9]+\\)?.*$")
  4411.                vrsn)
  4412.          (let ((maj (substring vrsn (match-beginning 1) (match-end 1)))
  4413.            (min (substring vrsn (match-beginning 2) (match-end 2)))
  4414.            (edt (substring vrsn (match-beginning 3) (match-end 3))))
  4415.            (setq irc-major-version (string-to-int maj)
  4416.              irc-minor-version (string-to-int min)
  4417.              irc-edit-version (string-to-int edt))))
  4418.      (irc-send "MOTD")
  4419.      (irc-insert (concat "*** Welcome to the Internet Relay Chat server "
  4420.                  "version %s at %s!")
  4421.              vrsn
  4422.              irc-server)
  4423.      (set-buffer-modified-p (buffer-modified-p))))
  4424.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There +are +\\([0-9]+\\) +"
  4425.                  "users +\\(and +\\|(\\)?"
  4426.                  "\\([^0-9]*[0-9]+ invisible\\)?\\()\\)? *"
  4427.                  "on +\\([0-9]+\\) +servers *$")
  4428.              cmsg)
  4429.        (let* ((ucount (subfield cmsg 2))
  4430.           (sdelim (subfield cmsg 3))
  4431.           (invstr (subfield cmsg 4))
  4432.           (edelim (subfield cmsg 5))
  4433.           (scount (subfield cmsg 6))
  4434.           (inv (if (string= "" invstr)
  4435.                ""
  4436.                (concat " "  sdelim invstr edelim)))
  4437.           (n (string-to-int ucount)))
  4438.      (irc-insert "*** There %s %s user%s%s on %s server%s."
  4439.              (if (= n 1) "is" "are")
  4440.              ucount
  4441.              (if (= n 1) "" "s")
  4442.              inv
  4443.              scount
  4444.              (if (= (string-to-int scount) 1) "" "s"))))
  4445.       ((string-match (concat "^\\(\\*\\*\\*\\)? *There +are \\([0-9]+\\) +"
  4446.                  "yet +unknown +connections *$")
  4447.              cmsg)
  4448.        (let ((count (substring cmsg (match-beginning 2) (match-end 2))))
  4449.      (irc-insert "*** There %s yet %s unknown connection%s."
  4450.              (if (string= count "1") "is" "are")
  4451.              count
  4452.              (if (string= count "1") "" "s"))))
  4453.       ((string-match (concat "^\\(\\*\\*\\*\\)? *I +have +\\([0-9]+\\)"
  4454.                  " +clients +and \\([0-9]+\\) +servers *$")
  4455.              cmsg)
  4456.        (let* ((c (subfield cmsg 2))
  4457.           (s (subfield cmsg 3))
  4458.           (cn (string-to-int c))
  4459.           (sn (string-to-int s))
  4460.           (isare (if (= 1 cn) "is" "are"))
  4461.           (cstr (if (= 1 cn) "client" "clients"))
  4462.           (sstr (if (= 1 sn) "server" "servers")))
  4463.      (irc-insert "*** There %s %d %s and %d %s on this server."
  4464.              isare cn cstr sn sstr)))
  4465.       ((string-match (concat "^\\*\\*\\* +Notice *:?-?-? +Received +KILL"
  4466.                  " +message +for +\\([^ ]+\\).\\( +From [^ ]+\\)?"
  4467.                  " +Path: *")
  4468.              cmsg)
  4469.        (let* ((sender (substring cmsg (match-beginning 1) (match-end 1)))
  4470.           (f (subfield cmsg 2))
  4471.           (path (substring cmsg (match-end 0)))
  4472.           (from (cond ((string-match "^From " f)
  4473.                (substring cmsg (match-end 0)))
  4474.               ((irc-is-hostname f) f)
  4475.               (t ""))))
  4476.      (cond ((string-match "\\([^!]+\\)!?(\\([^ ]*\\) *<- *\\([^ ]*\\)) *$"
  4477.                   path)
  4478.         (let* ((at (subfield path 1))
  4479.                (old (subfield path 2))
  4480.                (new (subfield path 3))
  4481.                (local (irc-is-nickname old))
  4482.                (irc-msg-cont-used (make-string
  4483.                        (length (concat irc-msg-info-pre
  4484.                                "User "))
  4485.                        ? )))
  4486.           (irc-insert
  4487.            (concat "%s%s COLLIDED at %s, "
  4488.                (if local
  4489.                    "local user %s seen on link from %s%s"
  4490.                    "was on %s, now from %s%s"))
  4491.            irc-msg-info-pre
  4492.            sender
  4493.            (upcase (irc-nuke-whitespace at))
  4494.            (upcase (irc-nuke-whitespace old))
  4495.            (upcase (irc-nuke-whitespace new))
  4496.            irc-msg-info-post)))
  4497.            ((or (string-match "\\([^!]+\\)!\\([^=][^! ]*\\) +(\\(.*\\))$"
  4498.                   path)
  4499.             (string-match "\\([^!]+\\)!\\([^=][^! ]*\\) *\\(\\)$"
  4500.                   path))
  4501.         (let* ((s (subfield path 1))
  4502.                (o (subfield path 2))
  4503.                (m (subfield path 3))
  4504.                (site (irc-nuke-whitespace s))
  4505.                (oper (irc-nuke-whitespace o))
  4506.                (type (if (string-match "\\." oper)
  4507.                  "Server"
  4508.                  "Operator"))
  4509.                (m2 (irc-nuke-whitespace m))
  4510.                (mesg (if (string= "" m2) "" (concat " (" m2 ")"))))
  4511.           (if (string-match "\\." oper)
  4512.               (irc-remember oper 'irc-servernames)
  4513.               (irc-remember oper 'irc-nicknames))
  4514.           (irc-insert "%sOperator %s (@%s) /KILL'ed user %s%s%s"
  4515.                   irc-msg-info-pre
  4516.                   oper
  4517.                   site
  4518.                   sender
  4519.                   mesg
  4520.                   irc-msg-info-post))
  4521.         (irc-send (concat "WHOWAS :" sender)))
  4522.            (t (irc-insert "%sUser %s KILL'ed, path: %s%s"
  4523.                   irc-msg-info-pre
  4524.                   sender
  4525.                   path
  4526.                   irc-msg-info-post)))))
  4527.       ((or (string-match "^ *You +have +been +marked +as +being +away *$" cmsg)
  4528.        (string-match "^ *You +have +marked +as +being +away *$" cmsg))
  4529.        (if (string= srvr "")
  4530.        (irc-insert (concat "%sYou have been marked as being away,"
  4531.                    " use /HERE to revert the effect%s")
  4532.                irc-msg-info-pre
  4533.                irc-msg-info-post)))
  4534.       ((string-match "^ *You +are +no +longer +marked +as +being +away *$"
  4535.              cmsg)
  4536.        (if (string= srvr "")        ;Only display if from local server.
  4537.        (irc-insert "%sYou are no longer marked as being away%s"
  4538.                irc-msg-info-pre
  4539.                irc-msg-info-post)))
  4540.       ((string-match (concat "^ *\\([^: *]*\\) *"
  4541.                  "\\(tty[^: ]+"
  4542.                  "\\|pty/tty[^: ]+"
  4543.                  "\\|vt[0-9]+"
  4544.                  "\\|pt[^: ]+"
  4545.                  "\\|display"
  4546.                  "\\|console\\) *"
  4547.                  "\\([ -~]+\\)?.*$")
  4548.              cmsg)
  4549.        (let ((user (substring cmsg (match-beginning 1) (match-end 1)))
  4550.          (tty (substring cmsg (match-beginning 2) (match-end 2)))
  4551.          (remote (substring cmsg (match-beginning 3) (match-end 3))))
  4552.      (irc-insert "%s%s %s%s %s"
  4553.              user
  4554.              (make-string (max 0 (- 39 (length user))) ? )
  4555.              tty
  4556.              (make-string (max 0 (- 14 (length tty))) ? )
  4557.              remote)))
  4558.       ((string-match " *Nobody +logged +in +on +\\([^: ]+\\) *$" cmsg)
  4559.        (let* ((s (subfield cmsg 1))
  4560.           (server (irc-extract-hostname s)))
  4561.      (if (and (stringp server)
  4562.           (not (string= (upcase srvr) (upcase server))))
  4563.          (irc-remember server 'irc-servernames))
  4564.      (irc-insert (concat "%%No users logged in on the Internet node"
  4565.                  " which runs the IRC server %s at the moment.")
  4566.              server)))
  4567.       ((string-match "^ *\\(UserId +Terminal +Host\\) *$" cmsg)
  4568.        (let ((m (substring cmsg (match-beginning 1) (match-end 1))))
  4569.      (irc-insert (concat "Login name                              "
  4570.                  "TTY            Logged in from"))
  4571.      (irc-insert (concat "--------------------------------------- "
  4572.                  "-------------- --------------"))))
  4573.       ((string-match (concat "^\\*\\*\\* *\\(Notice\\)? *\\(:\\|--\\)?"
  4574.                  " *Connecti\\(ng\\|on\\) *to"
  4575.                  " +\\(.+\\) +activated.? *$")
  4576.              cmsg)
  4577.        (irc-insert "%s%sTrying to establish a serverlink to %s%s"
  4578.            irc-msg-info-pre
  4579.            parorg
  4580.            (upcase (substring cmsg (match-beginning 4) (match-end 4)))
  4581.            irc-msg-info-post))
  4582.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\)"
  4583.                  " *Failed *in *connecting *to"
  4584.                  " *\\([^: ]+\\) *: *Socket *is"
  4585.                  " *not *connected *.? *$")
  4586.              cmsg)
  4587.        (irc-insert (concat "%%%sFailed to establish a serverlink to %s;"
  4588.                " no active server at other end.")
  4589.            parorg
  4590.            (upcase
  4591.             (substring cmsg (match-beginning 2) (match-end 2)))))
  4592.       ((string-match (concat "^\\*\\*\\* *Notice *: *Connect +"
  4593.                  "to +host +\\(.\\|\n\\)* +failed *:")
  4594.              cmsg)
  4595.        (let* ((host (substring cmsg (match-beginning 1) (match-end 1)))
  4596.           (reason (substring cmsg (match-end 0)))
  4597.           (server (upcase (irc-extract-hostname host))))
  4598.      (irc-forget server 'irc-servernames) ;Just in case.
  4599.      (irc-insert "%%Failed to establish a serverlink to %s; %s."
  4600.              (upcase server)
  4601.              reason)))
  4602.       ((string-match (concat "^\\*\\*\\* Notice: Access denied (no such server"
  4603.                  " enabled) \\([^ ]+\\) *\\(\\[[^ ]+\\]\\)? *$")
  4604.              cmsg)
  4605.        (let ((claimed (substring cmsg (match-beginning 1) (match-end 1)))
  4606.          (truename (substring cmsg
  4607.                   (1+ (or (match-beginning 2) -1))
  4608.                   (1- (or (match-end 2) 1)))))
  4609.      (irc-insert (concat "%%Rejected attemp by internethost \"%s\"%s to"
  4610.                  " establish a serverlink; that host isn't enabled"
  4611.                  " in the configuration file.")
  4612.              (if (string= "" truename) claimed truename)
  4613.              (if (or (string= "" truename)
  4614.                  (string= (upcase claimed) (upcase truename)))
  4615.              ""
  4616.              (concat " (claiming to be \"" claimed "\")")))))
  4617.       ((string-match (concat "^ *\\*\\*\\* +Notice *: +No +"
  4618.                  "response +from +\\([^: ]+\\) +, +"
  4619.                  "closing +link *$")
  4620.              cmsg)
  4621.        (let ((removed-server (substring cmsg
  4622.                     (match-beginning 1)
  4623.                     (match-end 1))))
  4624.      (irc-forget removed-server 'irc-servernames)
  4625.      (irc-insert (concat "%%Failed to get any response whatsoever from"
  4626.                  " server %s, removing the serverlink to it.")
  4627.              removed-server))
  4628.        (irc-later-execute-lusers))
  4629.       ((or (string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4630.                  " *Max +buffering +limit +exceed"
  4631.                  " +for +\\([^ ]+\\)")
  4632.              cmsg)
  4633.        (string-match (concat "^ *\\*\\*\\* *Notice\\ *\\(:\\|--\\)"
  4634.                  " *SendQueued +called +for +a"
  4635.                  " +DEADSOCKET +\\([^: ]*\\) *"
  4636.                  "\\(:-(\\)? *$")
  4637.              cmsg))
  4638.        (let ((host (irc-extract-hostname (substring cmsg
  4639.                             (match-beginning 2)
  4640.                             (match-end 2)))))
  4641.      (irc-forget host 'irc-servernames)
  4642.      (irc-insert (concat "%%Closed serverlink to %s, max buffering limit"
  4643.                  " got exceeded.")
  4644.              (upcase host)))
  4645.        (irc-later-execute-lusers))
  4646.       ((string-match (concat "^ *\\*\\*\\* *Host +\\(.*\\) +is"
  4647.                  " +unknown *\\.* *$")
  4648.              cmsg)
  4649.        (irc-insert "%%Host \"%s\" is unknown."
  4650.            (upcase
  4651.             (substring cmsg (match-beginning 1) (match-end 1)))))
  4652.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *Connect +to +host"
  4653.                  " +\\(.+\\) +failed *: *\\(.+\\) *$")
  4654.              cmsg)
  4655.        (let ((h (subfield cmsg 1))
  4656.          (reason (subfield cmsg 2)))
  4657.      (irc-insert "%%Connect to host %s failed: %s" (upcase h) reason)))
  4658.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR +"
  4659.                  "from +\\(.*\\) *: *SUMMON +No +"
  4660.                  "such +host *( *\\(.\\|\n\\)* *) *found"
  4661.                  " *$")
  4662.              cmsg)
  4663.        (let* ((fld1 (subfield cmsg 1))
  4664.           (fld2 (subfield cmsg 2))
  4665.           (at-server (irc-extract-hostname fld1))
  4666.           (unknown-host (irc-extract-hostname fld2)))
  4667.      (if (and (string< "" at-server)
  4668.           (not (string= (upcase srvr) (upcase at-server))))
  4669.          (irc-remember at-server 'irc-servernames))
  4670.      (irc-insert (concat "%%Summon command failed as server %s doesn't"
  4671.                  " know of any Internet host called \"%s\".")
  4672.              (upcase fld1)
  4673.              fld2)))
  4674.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR"
  4675.                  " +from\\ +\\(.*\\) *: *Access +"
  4676.                  "denied *( *no +such +server +"
  4677.                  "enabled *) *")
  4678.              cmsg)
  4679.        (let ((complainer (subfield cmsg 1))
  4680.          (disabled (substring cmsg (match-end 0))))
  4681.      (if (and (irc-is-hostname complainer)
  4682.           (not (string= (upcase srvr) (upcase complainer))))
  4683.          (irc-remember complainer 'irc-servernames))
  4684.      (irc-insert (concat "%%Server %s refuses to accept serverlink from"
  4685.                  " host %s as that host isn't enabled in the"
  4686.                  " configuration. Use \"/STATS C %s\" to check"
  4687.                  " which hosts ARE enabled.")
  4688.              complainer
  4689.              disabled)))
  4690.       ((string-match (concat "^ *\\([^: ]+\\) +seems +to +have +"
  4691.                  "disabled +summoning")
  4692.              cmsg)
  4693.        (irc-insert "%%User %s@%s has disabled summoning."
  4694.            (substring cmsg (match-beginning 1) (match-end 1))
  4695.            srvnam))
  4696.       ((string-match (concat "^ *Summoning +user *\\([^: ]*\\) +"
  4697.                  "to +irc *$")
  4698.              cmsg)
  4699.        (irc-insert "%sSummoning user %s@%s to IRC%s"
  4700.            irc-msg-info-pre
  4701.            (substring cmsg (match-beginning 1) (match-end 1))
  4702.            srvnam
  4703.            irc-msg-info-post))
  4704.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4705.                  " *Link +\\(.*\\) +cancelled *,"
  4706.                  " *server +\\(.*\\) +already"
  4707.                  " +exists *$")
  4708.              cmsg)
  4709.        (let ((rhost (substring cmsg (match-beginning 2) (match-end 2)))
  4710.          (rsrvr (substring cmsg (match-beginning 3) (match-end 3))))
  4711.      (irc-insert (concat "%%Server %s %s tried to establish a serverlink"
  4712.                  " to us (%s). Refused as we already are linked.")
  4713.              rsrvr rhost irc-server)))
  4714.       ((string-match (concat "^ *Connect *: *Server +\\([^ ]+\\) +already"
  4715.                  " +exists +from +\\([^ ]+\\) *$")
  4716.              cmsg)
  4717.        (let ((other-side (subfield cmsg 1))
  4718.          (trying-side (subfield cmsg 2)))
  4719.      (irc-remember other-side 'irc-servernames)
  4720.      (irc-remember trying-side 'irc-servernames)
  4721.      (irc-insert "%%Server %s is already connected to %s"
  4722.              (upcase other-side)
  4723.              (upcase trying-side))))
  4724.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4725.                  " *ERROR +from +\\(.*\\) *:"
  4726.                  " *Server +\\(.*\\) +already +exists"
  4727.                  " *\\.?\\.?\\.? *$")
  4728.              cmsg)
  4729.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2)))
  4730.          (local (substring cmsg (match-beginning 3) (match-end 3))))
  4731.      (if (not (string= (upcase srvr) (upcase remote)))
  4732.          (irc-remember remote 'irc-servernames))
  4733.      (irc-insert (concat "%%Server %s refused to accept a serverlink from"
  4734.                  " %s, the servers are already connected.")
  4735.              (upcase remote)
  4736.              (if (string= (upcase local) (upcase irc-server))
  4737.              (concat "this server (" local ")")
  4738.              (concat "other server " local))))) 
  4739.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4740.                  " *Server +\\([^: ]+\\) +closed +the"
  4741.                  " +connection *.? *$")
  4742.              cmsg)
  4743.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2))))
  4744.      (irc-forget remote 'irc-servernames)
  4745.      (irc-insert "%%%sServerlink from %s closed by remote side."
  4746.              parorg
  4747.              (upcase remote))))
  4748.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4749.                  " *Access +denied *( *no +such"
  4750.                  " +server +enabled *) *")
  4751.              cmsg)
  4752.        (let* ((remote (substring cmsg (match-end 0)))
  4753.           (s (irc-extract-hostname remote))
  4754.           (server (if (stringp s) s ""))
  4755.           (rest (substring remote (length server)))
  4756.           (h (irc-nuke-whitespace rest))
  4757.           (host (upcase (if (string= "" h) server h))))
  4758.      (irc-insert (concat "%%Server %s (on host %s) tried to set up a"
  4759.                  " server-link to us (%s) but we refused as there"
  4760.                  " is no N line accepting that host/server"
  4761.                  " combination.")
  4762.              server host irc-server)))
  4763.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4764.                  " *Lost +server +connection +to"
  4765.                  " +\\(.*\\) *:")
  4766.              cmsg)
  4767.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2)))
  4768.          (reason (substring cmsg (match-end 0))))
  4769.      (irc-forget remote 'irc-servernames)
  4770.      (irc-insert "%%Lost serverlink to %s (%s)." (upcase remote) reason)
  4771.      (irc-later-execute-lusers)))
  4772.       ((string-match (concat "^ *Connect *: *Host +\\(.\\|\n\\)*"
  4773.                  " +not +listed +in +ircd?.conf *$")
  4774.              cmsg)
  4775.        (let ((host (substring cmsg (match-beginning 1) (match-end 1))))
  4776.      (irc-insert (concat "%%There is no host matching the description"
  4777.                  " \"%s\" in the servers (%s) configuration"
  4778.                  " file.")
  4779.              host irc-server)))
  4780.       ((string-match "^ *\\(.\\|\n\\)* *: *Privileged +command *$"
  4781.              cmsg)
  4782.        (irc-insert (concat "%%You must be an ENABLED IRC operator to use"
  4783.                " command \"%s\". Use /OPER to enable yourself.")
  4784.            (upcase (subfield cmsg 1))))
  4785.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR +"
  4786.                  "from +\\(.*\\) *: *SUMMON +No +"
  4787.                  "such +host *( *\\(.*\\) *) *found"
  4788.                  " *$")
  4789.              cmsg)
  4790.        (let ((complainer (subfield cmsg 1))
  4791.          (nonfound (subfield cmsg 2)))
  4792.      (if (not (string= (upcase srvr) (upcase complainer)))
  4793.          (irc-remember complainer 'irc-servernames))
  4794.      (irc-insert (concat "%%Command /SUMMON found as server \"%s\" doesn't"
  4795.                  " know about any server \"%s\".")
  4796.              complainer nonfound)))
  4797.       ((and (irc-is-hostname srvr)
  4798.         (string-match (concat "^ *User +\\(.\\|\n\\)* +not +logged"
  4799.                   " +in *$")
  4800.               cmsg))
  4801.        (irc-insert (concat "%%Command /SUMMON failed as no user called \"%s\""
  4802.                " is logged in at %s at the moment.")
  4803.            (subfield cmsg 1) (upcase srvr)))
  4804.       ((or (string-match "^\\*\\*\\* *Notice *:?-* *\\([^ ]*\\) *$" cmsg)
  4805.        (string-match "^\\*\\*\\* *\\([^ ]*\\) *$" cmsg)
  4806.        (string-match "^ *Notice *:?-* *\\([^ ]+\\) *$" cmsg)
  4807.        (string-match "^ *\\([CNIYQK] *:.*\\) *$" cmsg) ;/STATS C
  4808.        (string-match "^ *\\*\\*\\* *\\(.*\\) *$" cmsg))
  4809.        (let* ((b (or (match-beginning 1) 0))
  4810.           (e (or (match-end 1) b))
  4811.           (m (substring cmsg b e)))
  4812.      (irc-insert "%s%s%s%s%s%s"
  4813.              irc-msg-info-pre
  4814.              (if (or (string= rcvr "")
  4815.                  (string= (upcase rcvr) (upcase irc-nick-used)))
  4816.              ""
  4817.              (concat
  4818.               "To "
  4819.               (cond ((irc-is-nickname rcvr) "user ")
  4820.                 ((irc-is-channelname rcvr) "channel ")
  4821.                 ((irc-is-broadcastname rcvr) "server "))
  4822.               rcvr
  4823.               " "))
  4824.              (cond ((string= srvr "") "")
  4825.                ((or (string-match "^C:" m) (string-match "^N:" m))
  4826.                 parorg)
  4827.                (t (concat "from "
  4828.                       (if (irc-is-hostname srvr)
  4829.                       "server (user?)"
  4830.                       "user (server?)")
  4831.                       " "
  4832.                       srvr)))
  4833.              (if (and (string= srvr "")
  4834.                   (or (string= rcvr "")
  4835.                   (string= (upcase rcvr)
  4836.                        (upcase irc-nick-used))))
  4837.              ""
  4838.              ": ")
  4839.              m
  4840.              irc-msg-info-post)))
  4841.       ((or (string-match (concat "^[^: ]+ +[0-9]+ *[0-9]+ *[0-9]+ *"
  4842.                  "[0-9]+ *[0-9]+ +\\("
  4843.                  "Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun"
  4844.                  "\\) +")
  4845.              cmsg)
  4846.        (string-match (concat "^ *Link +SendQ +SendM +SendBytes"
  4847.                  " +RcveM +RcveBytes +Open +since"
  4848.                  " *$")
  4849.              cmsg))
  4850.        (irc-insert cmsg))
  4851. ;;;      ((string-match "^ *: *\\([^: ]+\\) +NOTICE +\\([^: ]+\\) *:" str)
  4852. ;;;       (let ((from (substring str (match-beginning 1) (match-end 1)))
  4853. ;;;         (to (substring str (match-beginning 2) (match-end 2)))
  4854. ;;;         (msg (substring str (match-end 0))))
  4855. ;;;     (setq retval (irc-parse-priv (concat ":" from " PRIVMSG " to
  4856. ;;;                          " :" msg)))))
  4857.       ((string-match "^\\(.*\\) +ToolZ V[0-9]+\\.[0-9]+[a-zA-Z]* *$" cmsg)
  4858.        (let ((m (subfield cmsg 1)))
  4859.      (if (string-match "^[ :;\\.?]*" m)
  4860.          (setq m (substring m (match-end 0))))
  4861.      (if (string-match "[ :;\\.?]*$" m)
  4862.          (setq m (substring m 0 (match-beginning 0))))
  4863.      (irc-insert "%sToolZ-notice from %s: %s%s"
  4864.              irc-msg-info-pre
  4865.              srvnam
  4866.              m
  4867.              irc-msg-info-post)))
  4868.       ((and (string= (upcase rcvr) (upcase irc-last-NOTICE-rcv))
  4869.         (string= (upcase srvr) (upcase irc-last-NOTICE-src)))
  4870.        (setq irc-last-NOTICE-rcv rcvr
  4871.          irc-last-NOTICE-src srvr)
  4872.        (let ((irc-msg-cont-used "    "))
  4873.      (irc-insert "*** %s" cmsg)))
  4874.       (t (setq irc-last-NOTICE-rcv rcvr
  4875.            irc-last-NOTICE-src srvr)
  4876.      (cond ((irc-is-nickname srvr)
  4877.         (irc-remember srvr 'irc-nicknames))
  4878.            ((irc-is-hostname srvr)
  4879.         (irc-remember srvr 'irc-servernames)))
  4880.      (irc-insert "")
  4881.      (let ((irc-msg-cont-used "       "))
  4882.        (irc-insert "****** %s %s says to %s:"
  4883.                (cond ((string= "" srvr) "Your")
  4884.                  ((irc-is-nickname srvr)
  4885.                   "User (or possible server)")
  4886.                  (t "Server (or possible user)"))
  4887.                (cond ((string= "" srvr) "server")
  4888.                  (t (concat "\"" srvr "\"")))
  4889.                (if (string= (upcase rcvr) (upcase irc-nick))
  4890.                "you"
  4891.                rcvr))
  4892.        (let ((irc-msg-cont-used "   "))
  4893.          (irc-insert "*** %s" cmsg)))))
  4894.     retval))
  4895.  
  4896.  
  4897. (defun irc-parse-pong (str)
  4898.   "Examine a PONG message from the IRC server.
  4899. Normaly the server should never send such a message, but when it does,
  4900. chances are there's a server name  given."
  4901.   (if (string-match "^PONG *\\([^: ]*\\)? *" str)
  4902.       (let* ((s (subfield str 1))
  4903.          (data (irc-nuke-whitespace (substring str (match-end 0))))
  4904.          (server (irc-extract-hostname s)))
  4905.     (if (irc-is-hostname server)
  4906.         (irc-remember server 'irc-servernames))
  4907.     (if data
  4908.         (irc-insert "%sServer %s says PONG, with message \"%s\"%s"
  4909.             irc-msg-info-pre
  4910.             server
  4911.             data
  4912.             irc-msg-info-post)
  4913.         (irc-insert "%sServer %s says PONG%s"
  4914.             irc-msg-info-pre
  4915.             server
  4916.             irc-msg-info-post)))))
  4917.  
  4918.  
  4919. (defun irc-parse-priv (str)
  4920.   "Examine a PRIVMSG message from the IRC server.
  4921. PRIVMSG is intended to be used for private message sent between users.
  4922. This is not always the case at the moment; servers will use it like either
  4923. NOTICE or MSG on occasion.
  4924.  
  4925. If it really is a private message, this function returns t if a signal should
  4926. be issued for the \"private\" event, nil otherwise."
  4927.   ;; This is really gross because it kludges in the fact that PRIVMSG can
  4928.   ;; be used to send notification of a change of channel topic.
  4929.  
  4930.   (if (not (string-match (concat "^ *: *\\([^: ]*\\) *PRIVMSG"
  4931.                  " *\\([^ ]*\\) +:")
  4932.              str))
  4933.       (progn
  4934.     (irc-insert "%%Unknown PRIVMSG seen in irc-parse-priv:")
  4935.     (irc-insert "%% \"%s\" (str)." str)
  4936.     (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  4937.       (let* ((from (substring str (match-beginning 1) (match-end 1))) 
  4938.          (to (substring str (match-beginning 2) (match-end 2)))
  4939.          (msg (substring str (match-end 0)))
  4940.          (time (if (and irc-message-stamp
  4941.                 (not (eq 'public irc-message-stamp)))
  4942.                (concat " (" (irc-get-time) ") ")
  4943.                ""))
  4944.          (hdr (format (format irc-msg-priv (+ 7 (length irc-channel)))
  4945.               time
  4946.               from
  4947.               "")))
  4948.     (cond ((and (irc-is-nickname from)
  4949.             (not (irc-recall to 'irc-subscribed-channels)))
  4950.            (irc-remember from 'irc-nicknames))
  4951.           ((irc-is-hostname from)
  4952.            (irc-remember from 'irc-servernames)))
  4953.     (cond
  4954.       ((and irc-ignore-automatic-warnings
  4955.         (string-match "^<Automatic +warning> +" msg))
  4956.        nil)
  4957.       ((irc-recall to 'irc-subscribed-channels)
  4958.        (irc-parse-public (concat ":" from " MSG :" msg) to))
  4959.       ((irc-recall from 'irc-ignored-ppl)
  4960.        (if (and (boundp 'irc-abusive-ignore)
  4961.             irc-abusive-ignore)
  4962.            (irc-send (concat "NOTICE "
  4963.                  from
  4964.                  " :You are being ignored by "
  4965.                  irc-nick-used))))
  4966.       ((string= (upcase to) (upcase irc-nick-used))
  4967.        (setq irc-last-private (concat from ":"))
  4968.        (let ((irc-msg-cont-used (make-string
  4969.                      (min (length hdr)
  4970.                       (/ (window-width
  4971.                           (get-buffer-window
  4972.                            (current-buffer)))
  4973.                          2))
  4974.                      ? )))
  4975.          (if (and (boundp 'irc-private-insert)
  4976.               irc-private-insert)
  4977.          (funcall irc-private-insert from to msg)
  4978.          (irc-insert (concat hdr (irc-clean-up-message msg))))
  4979.          (irc-signal from 'private)))
  4980.       ((irc-is-broadcastname to)
  4981.        (let ((irc-msg-cont-used (make-string
  4982.                      (min (length hdr)
  4983.                       (/ (window-width
  4984.                           (get-buffer-window
  4985.                            (current-buffer)))
  4986.                          2))
  4987.                      ? )))
  4988.          (irc-insert (concat hdr
  4989.                  "[BROADCAST to all users on IRC "
  4990.                  (if (= ?$ (aref to 0))
  4991.                      "server(s) "
  4992.                      "clients(s) on Internet host(s) ")
  4993.                  (upcase (substring to 1))
  4994.                  "] "
  4995.                  (irc-clean-up-message msg)))
  4996.          (irc-signal from 'wall)))
  4997.       (t (setq irc-last-private (concat from ":"))
  4998.          (let ((irc-msg-cont-used (make-string
  4999.                        (min (length hdr)
  5000.                         (/ (window-width
  5001.                         (get-buffer-window
  5002.                          (current-buffer)))
  5003.                            2))
  5004.                        ? )))
  5005.            (irc-insert "*** Private message to \"%s\" follows:" to)
  5006.            (if (and (boundp 'irc-private-insert)
  5007.             irc-private-insert)
  5008.            (funcall irc-private-insert from to msg)
  5009.            (irc-insert (concat hdr (irc-clean-up-message msg))))
  5010.            (irc-signal from 'private)))))))
  5011.  
  5012.  
  5013. (defun irc-parse-public (str &optional priv-chan)
  5014.   "Examine a MSG message from the IRC server.
  5015. MSG is sent when someone has sent a message to a channel.  In reality,
  5016. sometimes PRIVMSG is used but irc-parse-private should hand those off to
  5017. here.
  5018.  
  5019. This function returns t if a bell should be issued for the \"public\" or
  5020. \"backtalk\" events, nil otherwise."
  5021.   (let* ((user (substring str 1 (string-match " MSG :" str)))
  5022.      (rcvr (if priv-chan
  5023.            priv-chan
  5024.            (let ((clst (irc-recall-all 'irc-subscribed-channels)))
  5025.              ;; Find out which of the channel's is "MSG:able".
  5026.              (while (and clst (listp clst))
  5027.                (if (irc-is-multijoinable-channel (car clst))
  5028.                (setq clst (cdr clst))
  5029.                (setq clst (car clst))))
  5030.              ;; As THIS function was activated, we are listening to one
  5031.              ;; of the old type channels (42, +glbf) if priv-chan=nil.
  5032.              (if (not clst)
  5033.              "???"
  5034.              clst))))
  5035.      (msg (substring str (match-end 0)))
  5036.      (about-self (numberp (string-match
  5037.                    (concat "\\<"
  5038.                        (regexp-quote irc-nick-used)
  5039.                        "\\>")
  5040.                    msg)))
  5041.      (ismem (irc-recall user 'irc-ignored-ppl))
  5042.      (hdr (if ismem ""
  5043.           (format irc-msg-public
  5044.               (if (and irc-message-stamp
  5045.                    (not (eq 'private irc-message-stamp)))
  5046.                   (concat " (" (irc-get-time) ")")
  5047.                   "")
  5048.               user
  5049.               rcvr)))
  5050.      (irc-msg-cont-used (make-string
  5051.                  (min (length hdr)
  5052.                   (/ (window-width
  5053.                       (get-buffer-window (current-buffer)))
  5054.                      2))
  5055.                  ? )))
  5056.     ;; even here we can't guarantee that the sender has already been noted
  5057.     ;; someplace else like join or nick -- the sender might be someplace
  5058.     ;; else and sending to this channel with PRIVMSG.
  5059.     (irc-remember user 'irc-nicknames)
  5060.     (cond ((not ismem)            ;Not ignored?
  5061.        (progn (if (and (boundp 'irc-public-insert)
  5062.                irc-public-insert)
  5063.               (funcall irc-public-insert user rcvr msg)
  5064.               (irc-insert (concat hdr (irc-clean-up-message msg))))
  5065.           (or (irc-signal user 'public)
  5066.               (and about-self (irc-signal user 'backtalk))))))))
  5067.  
  5068.  
  5069. (defun irc-parse-quit (str)
  5070.   "Examine a QUIT message from the IRC server.
  5071. QUIT is used to tell of a user's departure from IRC.  It is currently sent
  5072. by the servers to those clients which are on the same channel as the
  5073. departing user.
  5074.  
  5075. This function returns t if a signal should be issued for the \"join\" event,
  5076. since it also signals someone leaving the channel.  It returns nil if no
  5077. bell should be issued."
  5078.   (if (not (or (string-match "^:? *\\([^ :]+\\)? +QUIT +\\([^ :]+\\) *: *" str)
  5079.            (string-match "^:? *\\([^ :]+\\)? +QUIT *\\(\\): *" str)))
  5080.       (progn (irc-insert "%%Unknown QUIT message in irc-parse-quit:")
  5081.          (irc-insert "%% \"%s\" (str)." str)
  5082.          (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  5083.       (let* ((u (subfield str 1))
  5084.          (user2 (subfield str 2))
  5085.          (c (irc-clean-up-message (irc-nuke-whitespace
  5086.                        (substring str (match-end 0)))))
  5087.          (user (if (string= "" u) irc-nick-used u))
  5088.          (myself (string= (upcase user) (upcase irc-nick-used)))
  5089.          (uc (upcase c))
  5090.          (comment (cond ((or (string= "" c)
  5091.                  (string= (upcase user) uc))
  5092.                  ": user quit")
  5093.                 ((string= "LEAVING" uc)
  5094.                  ": user quit, one ircII user less on IRC")
  5095.                 ((string= "BAD LINK?" uc)
  5096.                  ": link closed from client's side")
  5097.                 ((string-match "^\\([^.!]+\\)![A-Za-z][^ !]+$" c)
  5098.                  (format ": user quit past %s" (subfield c 1)))
  5099.                 ((string= "KILLED" uc)
  5100.                  ": killed")
  5101.                 ((string= "PING TIMEOUT" uc)
  5102.                  ": killed off due to inactivity")
  5103.                 ((string= "DEAD SOCKET" uc)
  5104.                  ": dead socket")
  5105.                 ((string= "WRITE ERROR" uc)
  5106.                  ": write error")
  5107.                 ((string-match
  5108.                   (concat "^\\([^ ]+\\.[^ .][^ ]*\\)"
  5109.                       " +\\([^ ]+\\.[^ .][^ ]*\\)$")
  5110.                   c)
  5111.                  (format ": netsplit past %s (lost %s)"
  5112.                      (subfield c 1)
  5113.                      (subfield c 2)))
  5114.                 ((string-match "^[^ ]+\\.[^ .][^ ]$" c)
  5115.                  (irc-remember c 'irc-servernames)
  5116.                  (concat ": netsplit just past " c))
  5117.                 (t (concat " (" c ")")))))
  5118.     (if (and (string< "" user2)
  5119.          (not (string= (upcase user) (upcase user2)))
  5120.          (boundp 'debug-on-error)
  5121.          debug-on-error)
  5122.         (irc-insert (concat "%sirc-parse-quit: secondary user to QUIT"
  5123.                 " differed, user=\"%s\", user2=\"%s\"%s")
  5124.             irc-msg-info-pre user user2 irc-msg-info-post))
  5125.     (irc-forget user 'irc-nicknames)
  5126.     (if (and (not (irc-recall user 'irc-ignored-ppl))
  5127.          (memq 'quit irc-events))
  5128.         (progn (irc-insert "%s%s left IRC%s%s"
  5129.                irc-msg-info-pre
  5130.                (if myself "You" user)
  5131.                comment
  5132.                irc-msg-info-post)
  5133.            ;; currently just the join event; some modification will
  5134.            ;; need to be made here when/if Jarkko has QUIT sent to
  5135.            ;; everyone,not just the channel 
  5136.            (irc-signal user 'join))))))
  5137.  
  5138.  
  5139. (defun irc-parse-RPL (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 "^:?[^: ]+ +\\([023]\\)[0-9][0-9] +" str)
  5150.       (let ((n (string-to-int (subfield str 1))))
  5151.     (cond ((= n 3) (irc-parse-RPL-3xx str))
  5152.           ((= n 2) (irc-parse-RPL-2xx str))
  5153.           (t (irc-parse-RPL-0xx str))))
  5154.       (progn 
  5155.     (irc-insert "%%Function irc-parse-RPL called with non-RPL:")
  5156.     (irc-insert "%% \"%s\" (str)" str)
  5157.     (irc-insert "%% Please tell %s." irc-hacker))))
  5158.  
  5159.  
  5160. (defun irc-parse-RPL-0xx (str)
  5161.   "Examine a numeric RPL_ message from the IRC server.
  5162. Numeric control messages are used by newer servers to aid in generalized
  5163. client design; while people are converting to the new servers the older
  5164. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5165. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5166. in the IRC source file numeric.h.
  5167.  
  5168. Note well that some things are still going to come out wrong because the
  5169. servers are currently still doing things inconsistently."
  5170.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5171.                 "\\([^: ]+\\)? +:?")
  5172.             str)
  5173.       ;; we assume that the server and message are consistent for us; just
  5174.       ;; worry about the numeric value and the rest of the line
  5175.       (let* ((origin (subfield str 1))
  5176.          (num (string-to-int (subfield str 2)))
  5177.          (user (subfield str 3))
  5178.          (txt (substring str (match-end 0)))
  5179.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5180.              ""
  5181.              (concat "(" origin ") ")))
  5182.          tmp1 tmp2 tmp3 tmp4)
  5183.     (irc-remember origin 'irc-servernames)
  5184.     (cond
  5185.       ((= num 001)
  5186.        )
  5187.       ((= num 002)
  5188.        (irc-parse-notice (format "NOTICE %s :*** %s" user txt)))
  5189.       ((= num 003)
  5190.        (irc-parse-notice (format "NOTICE %s :*** %s" user txt)))
  5191.       ((= num 004)
  5192.        (irc-insert "*** FEATURES: %s" txt))
  5193.       (t                                 ; default
  5194.        (irc-insert (concat "%%Unrecognized numeric RPL 0xx message; "
  5195.                    "please tell %s:")
  5196.                irc-hacker)
  5197.        (irc-insert "%% str=\"%s\"." str)
  5198.        (irc-insert "%% Function irc-parse-RPL-0xx."))))
  5199.       ;; else
  5200.       (irc-insert (concat "%%Unrecognized nonnumeric RPL 0xx message follows; "
  5201.               "please tell %s:")
  5202.           irc-hacker)
  5203.       (irc-insert "%% \"%s\"." str)
  5204.       (irc-insert "%% Function irc-parse-RPL-0xx."))
  5205.   nil)
  5206.  
  5207.  
  5208. (defun irc-parse-RPL-2xx (str)
  5209.   "Examine a numeric RPL_ message from the IRC server.
  5210. Numeric control messages are used by newer servers to aid in generalized
  5211. client design; while people are converting to the new servers the older
  5212. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5213. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5214. in the IRC source file numeric.h.
  5215.  
  5216. Note well that some things are still going to come out wrong because the
  5217. servers are currently still doing things inconsistently."
  5218.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5219.                 "\\([^: ]+\\)? +:?")
  5220.             str)
  5221.       ;; we assume that the server and message are consistent for us; just
  5222.       ;; worry about the numeric value and the rest of the line
  5223.       (let* ((origin (subfield str 1))
  5224.          (num (string-to-int (subfield str 2)))
  5225.          (user (subfield str 3))
  5226.          (txt (substring str (match-end 0)))
  5227.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5228.              ""
  5229.              (concat "(" origin ") ")))
  5230.          tmp1 tmp2 tmp3 tmp4)
  5231.     (irc-remember origin 'irc-servernames)
  5232.     (cond
  5233.       ((= num 200)
  5234.        (cond ((string-match
  5235.            "^ *Link +\\([^ ]+\\) *:?\\([^ ]+\\) *:?\\([^ ]+\\)? *$"
  5236.            txt)
  5237.           (let ((vrsn (subfield txt 1))
  5238.             (goal (subfield txt 2))
  5239.             (next (subfield txt 3)))
  5240.             (irc-insert "%sLink to %s passes %s<%s>%s%s"
  5241.                 irc-msg-info-pre
  5242.                 (upcase goal)
  5243.                 (upcase origin)
  5244.                 (upcase vrsn)
  5245.                 (if (string= "" next)
  5246.                     ""
  5247.                     (concat "; next:" next))
  5248.                 irc-msg-info-post)))
  5249.          (t (irc-insert "%%Unknown RPL200 received in irc-parse-RPL-2xx:")
  5250.             (irc-insert "%% \"%s\" (txt)." txt)
  5251.             (irc-insert "%% Please tell %s, this might be a bug."
  5252.                 irc-hacker))))
  5253.       ((or (= num 201)        ; RPL_TRACECONNECTING "Try."
  5254.            (= num 202))        ; RPL_TRACEHANDSHAKE
  5255.        (cond ((string-match "^\\([^ ]+\\) +\\([0-9]+\\) +:?\\([^ ]+\\)"
  5256.                 txt)
  5257.           (let* ((type (subfield txt 1))
  5258.              (class (subfield txt 2))
  5259.              (host (subfield txt 3))
  5260.              (utype (upcase type))
  5261.              (state (cond ((string= "TRY." utype)
  5262.                        "trying to connect to it")
  5263.                       ((string= "H.S." utype)
  5264.                        "registering us as server at it")
  5265.                       (t type))))
  5266.             (irc-insert "%s%sClass %3s half: %s (%s)%s"
  5267.                 irc-msg-info-pre
  5268.                 parorg class (upcase host) state
  5269.                 irc-msg-info-post)))
  5270.          (t (irc-insert "%%Received unknown RPL%d in irc-parse-RPL-2xx:"
  5271.                 num)
  5272.             (irc-insert "%% \"%s\" (txt)." txt)
  5273.             (irc-insert "%% Please tell %s, it might be a bug."
  5274.                 irc-hacker))))
  5275.       ((or (= num 203)        ; RPL_TRACEUNKNOWN
  5276.            (= num 204)        ; RPL_TRACEOPERATOR "Oper"
  5277.            (= num 205))        ; RPL_TRACEUSER "User"
  5278.        (cond ((string-match (concat "^\\([^ ]+\\) +\\(-?[0-9]+\\) *:?"
  5279.                     "*\\([^ ]*\\)\\[\\(.+\\)\\] *"
  5280.                     ":?[0-9]*")
  5281.                 txt)
  5282.           (let* ((type (subfield txt 1))
  5283.              (class (subfield txt 2))
  5284.              (u (subfield txt 3))
  5285.              (cm (subfield txt 4))
  5286.              (user (irc-nuke-whitespace u)))
  5287.             (if (string< "" user)
  5288.             (irc-remember user 'irc-nicknames))
  5289.             (irc-insert "%s%sClass %3s %s: \"%s\" (client on %s)%s"
  5290.                 irc-msg-info-pre
  5291.                 parorg
  5292.                 class
  5293.                 (downcase type)
  5294.                 user
  5295.                 (upcase cm)
  5296.                 irc-msg-info-post)))
  5297.          (t (irc-insert
  5298.              "%%Unknown RPL203:205 seen, in irc-parse-RPL-2xx:")
  5299.             (irc-insert "%% \"%s\" (str); \"%s\" (txt)." str txt)
  5300.             (irc-insert "%% Please tell %s, it might be a bug."
  5301.                 irc-hacker))))
  5302.       ((= num 206)            ; RPL_TRACESERVER "Serv"
  5303.        (if (or (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) +\\(\\)"
  5304.                      "\\([0-9]+\\)S +\\([0-9]+\\)C +:? *"
  5305.                      "\\([^ ]+\\) *$")
  5306.                  txt)
  5307.            (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) +"
  5308.                      "\\([^ ]+\\) +\\([0-9]+\\)S *:?"
  5309.                      " *\\([0-9]+\\)C *$")
  5310.                  txt)
  5311.            (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) *"
  5312.                      ":? *\\(.+\\) *\\(\\)\\(\\)$")
  5313.                  txt))
  5314.            (let* ((type (subfield txt 1))
  5315.               (class (subfield txt 2))
  5316.               (r (subfield txt 3))
  5317.               (ns (string-to-int (subfield txt 4)))
  5318.               (nc (string-to-int (subfield txt 5)))
  5319.               (remote (if (string= "" r) (subfield txt 6) r)))
  5320.          (irc-remember remote 'irc-servernames)
  5321.          (irc-insert "%s%sClass %3s %s: %s%s%s"
  5322.                  irc-msg-info-pre
  5323.                  parorg
  5324.                  class
  5325.                  (downcase type)
  5326.                  (upcase remote)
  5327.                  (if (and (= ns 0) (= nc 0))
  5328.                  ""
  5329.                  (format " (%d server%s, %d client%s)%s"
  5330.                      ns
  5331.                      (if (= 1 ns) "" "s")
  5332.                      nc
  5333.                      (if (= 1 nc) "" "s")))
  5334.                  irc-msg-info-post))
  5335.            (progn
  5336.          (irc-insert "%%Unknown RPL206 received in irc-parse-RPL-2xx:")
  5337.          (irc-insert "%% \"%s\" (txt)." txt)
  5338.          (irc-insert "%% Please tell %s, it might be a bug."
  5339.                  irc-hacker))))
  5340.       ;; Missing 207 RPL_TRACESERVICE
  5341.       ;; Missing 208 RPL_TRACENEWTYPE
  5342.       ((= num 209)            ; RPL_TRACECLASS
  5343.        (cond ((string-match (concat "^Class +\\([0-9]+\\) *"
  5344.                     ":? *\\([0-9]+\\) *$")
  5345.                 txt)
  5346.           (let ((class (string-to-int (subfield txt 1)))
  5347.             (count (string-to-int (subfield txt 2))))
  5348.             (irc-insert
  5349.              "%s%s%d service%s linked for class %3d%s"
  5350.              irc-msg-info-pre
  5351.              parorg
  5352.              count
  5353.              (if (= 1 count) "" "s")
  5354.              class
  5355.              irc-msg-info-post)))
  5356.          (t (irc-insert "%%Unknown RPL209 message in irc-parse-RPL-2xx:")
  5357.             (irc-insert "%% \"%s\" (txt)" txt)
  5358.             (irc-insert "%% Please tell %s, it might be a bug."
  5359.                 irc-hacker))))
  5360.       ((= num 211)            ;L-lines
  5361.        (cond ((string-match (concat "^\\([^: ]+\\) +\\([0-9]+\\) +"
  5362.                     "\\([0-9]+\\) +\\([0-9]+\\) +"
  5363.                     "\\([0-9]+\\) +\\([0-9]+\\) +"
  5364.                     ": *\\(.*\\) *$")
  5365.                 txt)
  5366.           (let* ((link (subfield txt 1))
  5367.              (sendq (subfield txt 2))
  5368.              (sendm (subfield txt 3))
  5369.              (sendbytes (subfield txt 4))
  5370.              (rcvem (subfield txt 5))
  5371.              (rcvebytes (subfield txt 6))
  5372.              (rest (subfield txt 7))
  5373.              (irc-msg-cont-used
  5374.               "                                                 "))
  5375.             (irc-insert "%8s %8s %10s %8s %10s %s"
  5376.                 sendq sendm sendbytes rcvem rcvebytes rest)
  5377.             (irc-insert "%s(to %s)" irc-msg-cont-used (upcase link))))
  5378.          ((string-match (concat "^ *\\(Link +\\)?SendQ +SendM"
  5379.                     " +SendBytes +RcveM +RcveBytes"
  5380.                     " +:Open since *$")
  5381.                 txt)
  5382.           (irc-insert (concat
  5383.                    " SendQue   S-Msgs    S-Bytes   R-Msgs"
  5384.                    "    R-Bytes Date (to link)"))
  5385.           (irc-insert (concat
  5386.                    "-------- -------- ---------- --------"
  5387.                    " ---------- --------------")))
  5388.          (t (irc-insert "%%Unknown RPL211, in irc-parse-RPL-2xx:")
  5389.             (irc-insert "%% \"%s\" (txt)." txt)
  5390.             (irc-insert "%% Please tell %s, it might be a bug."
  5391.                 irc-hacker))))
  5392.       ((= num 212)            ;RPL_STATSCOMMANDS (ie non CIKLQY)
  5393.        (cond ((string-match "^\\([^ ]+\\) +:?\\([0-9]+\\) *\\([0-9]+\\)?$"
  5394.                 txt)
  5395.           (let* ((type (subfield txt 1))
  5396.              (count (subfield txt 2))
  5397.              (rcount (subfield txt 3))
  5398.              (n (string-to-int count))
  5399.              (rn (string-to-int rcount))
  5400.              (c (concat (make-string (max 0 (- 5 (length count)))
  5401.                          ? )
  5402.                     count))
  5403.              (cmds (if (= n 1) "command " "commands")))
  5404.             (irc-insert "%sServer %s has seen %s %s of type %s%s%s"
  5405.                 irc-msg-info-pre
  5406.                 (upcase origin)
  5407.                 c
  5408.                 cmds
  5409.                 (upcase type)
  5410.                 (if (string= "" rcount)
  5411.                     ""
  5412.                     (format " %s(%d remote?)"
  5413.                         (make-string (- 7 (length type))
  5414.                              ? )
  5415.                         rn))
  5416.                 irc-msg-info-post)))
  5417.          (t (irc-insert
  5418.              "%%Unknown RPL212 message received in irc-parse-RPL-2xx:")
  5419.             (irc-insert "%% \"%s\" (txt)." txt)
  5420.             (irc-insert "%% Please tell %s, it might be a bug."
  5421.                 irc-hacker))))
  5422.       ((or (= num 213)        ;C-lines
  5423.            (= num 214)        ;N-lines
  5424.            (= num 215)        ;I-lines
  5425.            (= num 216)        ;K-lines
  5426.            (= num 217)        ;Q-lines
  5427.            (= num 241)        ;L-lines
  5428.            (= num 242)        ;Uptime
  5429.            (= num 243)        ;O-lines
  5430.            (= num 244)        ;H-lines
  5431.            (= num 249)        ;other such lines
  5432.            )
  5433.        (cond ((string= (upcase origin) (upcase irc-server))
  5434.           (irc-insert "*** %s" txt))
  5435.          (t (irc-insert "*** (%s): %s" origin txt))))
  5436.       ((= num 218)            ;Y-lines
  5437.        (cond ((string-match
  5438.            (concat "^ *Y +\\([0-9]+\\) +\\([0-9]+\\) +\\([0-9]+\\) +:?"
  5439.                " *\\([0-9]+\\) +:?\\([0-9]+\\)")
  5440.            txt)
  5441.           (let* ((class (subfield txt 1))
  5442.              (ping-freq (subfield txt 2))
  5443.              (conn-freq (subfield txt 3))
  5444.              (max-links (subfield txt 4))
  5445.              (plur (if (= 1 (string-to-int max-links)) "" "s"))
  5446.              (sendq (subfield txt 5))
  5447.              (pre (format (concat "*** %sClass: %s, conn. freq."
  5448.                           " %ss, ping freq. %ss, ")
  5449.                       parorg class conn-freq ping-freq))
  5450.              (irc-msg-cont-used (make-string (length pre) ? )))
  5451.             (irc-insert "%smax# %s link%s, SendQ %s."
  5452.                 pre
  5453.                 max-links
  5454.                 plur
  5455.                 sendq)))
  5456.          (t (irc-insert "%%Unknown RPL218 in irc-parse-RPL-2xx:")
  5457.             (irc-insert "%% \"%s\" (txt)." txt)
  5458.             (irc-insert "%% Please tell %s, it might be a bug."
  5459.                 irc-hacker))))
  5460.       ((= num 219)
  5461.        (irc-insert "%sSTATS listing for server %s done%s"
  5462.                irc-msg-info-pre
  5463.                (upcase origin)
  5464.                irc-msg-info-post)
  5465.        (irc-insert ""))
  5466.       ((= num 221)
  5467.        (let ((i (1- (length txt)))
  5468.          (ut (upcase txt)))
  5469.          (while (and (>= i 0) (not (= ?O (aref ut i))))
  5470.            (setq i (1- i)))
  5471.          (while (and (>= i 0)
  5472.              (not (= ?- (aref ut i)))
  5473.              (not (= ?+ (aref ut i))))
  5474.            (setq i (1- i)))
  5475.          (setq irc-operator (if (and (>= i 0) (= ?+ (aref ut i)))
  5476.                      " IOPR"
  5477.                      nil)))
  5478.        (irc-insert "%sUser %s'%s mode%s: %s%s"
  5479.                irc-msg-info-pre
  5480.                user
  5481.                (if (= ?S (aref (upcase user) (1- (length user))))
  5482.                ""
  5483.                "s")
  5484.                (if (= 2 (length txt)) " is" "s are")
  5485.                (irc-explain-user-mode txt 'no-direction)
  5486.                irc-msg-info-post))
  5487. ;;;      ((= num 232)
  5488. ;;;       (irc-insert "DEBUG: RPL232 txt=\"%s\"." txt))
  5489. ;;;      ((= num 241) SEE RPL213-217
  5490. ;;;       )
  5491. ;;;      ((= num 242) SEE RPL213-217
  5492. ;;;       )
  5493. ;;;      ((= num 243) SEE RPL213-217
  5494. ;;;       )
  5495. ;;;      ((= num 244) SEE RPL213-217
  5496. ;;;       )
  5497. ;;;      ((= num 249) SEE RPL213-217
  5498. ;;;       )
  5499.       ((= num 250)
  5500.        (irc-insert "*** %s" txt))
  5501.       ((= num 251)
  5502.        (irc-insert "*** %s" txt))
  5503.       ((= num 252)
  5504.        (cond ((string-match "^\\([0-9]+\\) +:operator.*online$" txt)
  5505.           (irc-parse-notice (format (concat
  5506.                          "NOTICE %s :*** %s users have"
  5507.                          " connection to the twilight"
  5508.                          " zone")
  5509.                         user (subfield txt 1))))
  5510.          ((string-match "^\\([^ :]+\\) *: *\\(.*\\)$" txt)
  5511.           (irc-insert "*** %s %s" (subfield txt 1) (subfield txt 2)))
  5512.          (t (irc-insert "*** %s" txt))))
  5513.       ((= num 253)
  5514.        (if (string-match "^\\([0-9]+\\) *:unknown connection(?s?)?" txt)
  5515.            (let ((n (string-to-int (subfield txt 1))))
  5516.          (irc-insert "*** There %s %d %s of (yet) unknown %s."
  5517.                  (if (= 1 n) "is" "are")
  5518.                  n
  5519.                  (if (= 1 n) "connection" "connections")
  5520.                  (if (= 1 n) "type" "types")))
  5521.            (progn (irc-insert "%%Unrecognized RPL 253 message seen:")
  5522.               (irc-insert "%% \"%s\" (txt)" txt)
  5523.               (irc-insert "%% Please tell %s" irc-hacker))))
  5524.       ((= num 254)
  5525.        (if (string-match "^\\([0-9]+\\) :channel" txt)
  5526.            (irc-parse-notice (format (concat "NOTICE %s :*** There are %s"
  5527.                          " channels.")
  5528.                      user (subfield txt 1)))
  5529.            (irc-insert "*** %s" txt)))
  5530.       ((= num 255)            ;"I have 77 clients, 0 services and 1 servers"
  5531.        (let ((text (if (string-match "^I have \\(.*\\)" txt)
  5532.                (format "%s has %s"
  5533.                    (upcase origin)
  5534.                    (subfield txt 1))
  5535.              txt)))
  5536.          (irc-insert "*** %s" text)))
  5537.       ((= num 256)            ;RPL admin, first line
  5538.        (irc-insert "### %s" txt))
  5539.       ((= num 257)            ;RPL admin, second line
  5540.        (irc-insert "### %s" txt))
  5541.       ((= num 258)            ;RPL admin, third line
  5542.        (irc-insert "### %s" txt))
  5543.       ((= num 259)            ;RPL admin, fourth and last line
  5544.        (irc-insert "### %s" txt)
  5545.        (irc-insert "%sEnd of ADMIN for %s%s"
  5546.                irc-msg-info-pre origin irc-msg-info-post)
  5547.        (irc-insert ""))
  5548.       ((= num 261)            ;RPL log file
  5549.        (if (string-match "^File +\\(.+\\) +:\\([0-9]+\\)$"
  5550.                  txt)
  5551.            (let ((file (subfield txt 1))
  5552.              (dbglvl (subfield txt 2)))
  5553.          (irc-insert
  5554.           "%s%sThe servers log file for debug level %s is %s%s"
  5555.           irc-msg-info-pre
  5556.           parorg
  5557.           dbglvl
  5558.           file
  5559.           irc-msg-info-post))
  5560.            (progn (irc-insert "%%Unknown RPL 261 seen:")
  5561.               (irc-insert "%% \"%s\" (txt)" txt)
  5562.               (irc-insert "%% Please tell %s" irc-hacker))))
  5563.       ((= num 262)
  5564.        (if (string-match "\\([^ ]+\\) +\\([^ ]+\\)\\.? *: *\\(.*\\)" txt)
  5565.            (irc-insert "%%%s for %s who's using a server of version %s"
  5566.                (subfield txt 3)
  5567.                (subfield txt 1)
  5568.                (subfield txt 2))
  5569.          (irc-insert "%%%s" txt)))
  5570.       ((= num 265)
  5571.        (irc-insert "*** %s" txt))
  5572.       ((= num 266)
  5573.        (irc-insert "*** %s" txt))
  5574.       (t                                 ; default
  5575.        (irc-insert (concat "%%Unrecognized numeric RPL 2xx message; "
  5576.                    "please tell %s:")
  5577.                irc-hacker)
  5578.        (irc-insert "%% str=\"%s\"." str)
  5579.        (irc-insert "%% Function irc-parse-RPL-2xx."))))
  5580.       ;; else
  5581.       (irc-insert (concat "%%Unrecognized nonnumeric RPL 2xx message follows; "
  5582.               "please tell %s:")
  5583.           irc-hacker)
  5584.       (irc-insert "%% \"%s\"." str)
  5585.       (irc-insert "%% Function irc-parse-RPL-2xx."))
  5586.   nil)
  5587.  
  5588.  
  5589. (defun irc-parse-RPL-3xx (str)
  5590.   "Examine a numeric RPL_ message from the IRC server.
  5591. Numeric control messages are used by newer servers to aid in generalized
  5592. client design; while people are converting to the new servers the older
  5593. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5594. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5595. in the IRC source file numeric.h.
  5596.  
  5597. Note well that some things are still going to come out wrong because the
  5598. servers are currently still doing things inconsistently."
  5599.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5600.                 "\\([^: ]+\\)? +:?")
  5601.             str)
  5602.       ;; we assume that the server and message are consistent for us; just
  5603.       ;; worry about the numeric value and the rest of the line
  5604.       (let* ((origin (subfield str 1))
  5605.          (num (string-to-int (subfield str 2)))
  5606.          (user (subfield str 3))
  5607.          (txt (substring str (match-end 0)))
  5608.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5609.              ""
  5610.              (concat "(" origin ") ")))
  5611.          tmp1 tmp2 tmp3 tmp4)
  5612.     (irc-remember origin 'irc-servernames)
  5613.     (cond
  5614.      ((= num 301)                       ; RPL_AWAY
  5615.       (cond ((string-match "^\\([^: ]+\\) :" txt)
  5616.          (let ((nick (subfield txt 1))
  5617.                (msg (substring txt (match-end 0))))
  5618.            (irc-remember nick 'irc-nicknames)
  5619.            (irc-insert "%%User %s is away (%s)."
  5620.                    nick
  5621.                    (irc-clean-up-message msg))))
  5622.         (t (irc-insert (concat "%%One of the last persons you sent to"
  5623.                        " is away, delivered your"
  5624.                        " message anyway.")))))
  5625.      ((= num 302)                 ; RPL_USERHOST
  5626.       (let ((s txt))
  5627.         (while (string-match
  5628.             (concat "^\\([^ =*]+\\)\\(\\*?\\)=\\([+-]\\)"
  5629.                 "\\([^@]+\\)@\\([^ ]+\\) *")
  5630.             s)
  5631.           (let* ((nick (subfield s 1))
  5632.              (oper (subfield s 2))
  5633.              (away (subfield s 3))
  5634.              (user (subfield s 4))
  5635.              (host (subfield s 5))
  5636.              (rest (substring s (match-end 0))))
  5637.         (irc-remember nick 'irc-nicknames)
  5638.         (irc-remember host 'irc-servernames)
  5639.         (irc-insert "%s%s \"%s\" is %s@%s%s%s"
  5640.                 irc-msg-info-pre
  5641.                 (if (string= "*" oper) "Operator" "User")
  5642.                 nick
  5643.                 user
  5644.                 host
  5645.                 (if (string= "-" away) " (AWAY)" "")
  5646.                 irc-msg-info-post)
  5647.         (setq s rest)))))
  5648.      ((= num 303)                 ; RPL_ISON
  5649.       (let ((data (if (and (> (length txt) 0) (= ?: (aref txt 0)))
  5650.               (substring txt 1) txt))
  5651.         (ignored 0)
  5652.         (list ())
  5653.         (found ()))
  5654.         (while (string-match "^ *\\([^ ]+\\)" data)
  5655.           (setq found (cons (subfield data 1) found)
  5656.             data (substring data (match-end 0))))
  5657.         (while (not (null found))
  5658.           (if (irc-recall (car found) 'irc-ignored-ppl)
  5659.           (setq ignored (1+ ignored))
  5660.         (setq list (cons (car found) list)))
  5661.           (setq found (cdr found)))
  5662.         (setq list (reverse list))    ;Keep list sorted.
  5663.         (let ((l list)
  5664.           (arrivers ()))
  5665.           (while (not (null l))
  5666.         (if (not (irc-recall (car l) 'irc-notify-detected))
  5667.             (progn (setq arrivers (cons (car l) arrivers))
  5668.                (irc-send (format "WHOIS %s %s" (car l) (car l)))
  5669.                (irc-remember (car l) 'irc-notify-detected)
  5670.                (irc-remember (car l) 'irc-nicknames)
  5671.                ))
  5672.         (setq l (cdr l)))
  5673.           (let ((l (irc-recall-all 'irc-notify-detected))
  5674.             (gonners ()))
  5675.         (while (not (null l))
  5676.           (if (not (irc-list-recall (car l) list))
  5677.               (progn (setq gonners (cons (car l) gonners))
  5678.                  (irc-forget (car l) 'irc-notify-detected)))
  5679.           (setq l (cdr l)))
  5680.         (if (not (null arrivers))
  5681.             (let ((a arrivers)
  5682.               (as (irc-listify arrivers ", " "and")))
  5683.               (irc-insert "%sDETECTED %s%s on IRC%s"
  5684.                   irc-msg-info-pre
  5685.                   as
  5686.                   (if (> ignored 0)
  5687.                       (format " (also %d ignored person%s)"
  5688.                           ignored
  5689.                           (if (= 1 ignored) "" "s"))
  5690.                     "")
  5691.                   irc-msg-info-post)
  5692.               (if (irc-signal (car a) 'detect)
  5693.               (progn
  5694.                 (message (format "Kiwi: Detected %s on IRC" as))
  5695.                 (ding t)))))
  5696.         (if (not (null gonners))
  5697.             (let ((g gonners)
  5698.               (gs (irc-listify gonners ", " "and")))
  5699.               (irc-insert "%sLOST SIGHT of %s from IRC%s"
  5700.                   irc-msg-info-pre
  5701.                   gs
  5702.                   irc-msg-info-post)
  5703.               (while g
  5704.             (if (irc-signal (car g) 'detect)
  5705.                 (progn
  5706.                   (message (format
  5707.                     "Kiwi: lost sight of %s from IRC"
  5708.                     gs))
  5709.                   (ding t)))
  5710.             (setq g (cdr g)))))))))
  5711.      ((= num 304)                 ; RPL_TEXT
  5712.       (irc-insert "Text: %s" txt))
  5713.      ((= num 305)
  5714.       (irc-insert "%sYou are no longer marked as being away%s"
  5715.               irc-msg-info-pre irc-msg-info-post))
  5716.      ((= num 306)
  5717.       (irc-insert (concat "%sYou have been marked as being away, use"
  5718.                   " /HERE to revert the effect%s")
  5719.               irc-msg-info-pre irc-msg-info-post))
  5720.      ((= num 311)                       ; RPL_WHOISUSER
  5721.       (string-match (concat "^\\([^: ]+\\) +\\([^: ]+\\) +\\([^: ]+\\)"
  5722.                 " \\([^: ]+\\) :")
  5723.             txt)
  5724.       (let* ((nick (subfield txt 1))
  5725.          (rn (substring txt (match-end 0)))
  5726.          (user-name (subfield txt 2))
  5727.          (client (subfield txt 3))
  5728.          (c (subfield txt 4))
  5729.          (channel (if (string= c "*")
  5730.                   ""
  5731.                 (concat " on channel " c)))
  5732.          (cntrl1 (format "%s \"%s\" "
  5733.                  (if (irc-recall nick 'irc-ignored-ppl)
  5734.                      "IGNORED user"
  5735.                    "User")
  5736.                  nick))
  5737.          (real-name (irc-nuke-whitespace rn)))
  5738.         (setq irc-msg-cont-used (make-string (length cntrl1) ? ))
  5739.         (irc-remember nick 'irc-nicknames)
  5740.         (irc-insert (concat cntrl1 "is %s <%s@%s>%s,")
  5741.             (irc-clean-up-message real-name)
  5742.             (irc-clean-up-message user-name)
  5743.             client
  5744.             channel)))
  5745.      ((= num 312)            ; RPL_WHOISSERVER
  5746.       (let ((info-hop-count nil)
  5747.         (info-nick nil)
  5748.         (info-real-server-or-relay-name nil)
  5749.         (info-server-name nil)
  5750.         (info-server-descr nil)
  5751.         (found-info nil))
  5752.         (cond
  5753.          ((string-match "^ *\\([^ :]+\\) +\\([^ :]+\\) *: *" txt)
  5754.           (setq info-nick (subfield txt 1)
  5755.             info-server-name (subfield txt 2))
  5756.           (let ((rst (substring txt (match-end 0))))
  5757.         (cond ((string-match (concat "^... ... +[0-9]+ [0-9]+:"
  5758.                          "[0-9]+:[0-9]+ [0-9]+$")
  5759.                      rst)
  5760.                (setq info-server-descr (format "gone since %s" rst)
  5761.                  found-info t))
  5762.               ((string-match (concat "^\\([0-9]+\\) *: *\\["
  5763.                          "\\([^]]+\\)\\] *\\(.*\\) *$")
  5764.                      rst)
  5765.                (setq info-hop-count (subfield rst 1)
  5766.                  info-real-server-or-relay-name (subfield rst 2)
  5767.                  info-server-descr (subfield rst 3)
  5768.                  found-info t))
  5769.               ((string-match "^\\([0-9]+\\) +:? *\\(.*\\) *$" rst)
  5770.                (setq info-hop-count (subfield rst 1)
  5771.                  info-server-descr (subfield rst 2)
  5772.                  found-info t))
  5773.               ((string-match "^\\[\\([^]]+\\)\\] *\\(.*\\) *$"
  5774.                      rst)
  5775.                (setq info-real-server-or-relay-name (subfield rst 1)
  5776.                  info-server-descr (subfield rst 2)
  5777.                  found-info t))
  5778.               (t (setq info-server-descr rst
  5779.                    found-info t)))))
  5780.          ((string-match (concat "^\\([^ :]+\\) *: *\\([0-9]+\\) *: *"
  5781.                     "\\([^ ].*[^ ]\\) *$")
  5782.                 txt)
  5783.           (setq info-server-name (subfield txt 1)
  5784.             info-hop-count (subfield txt 2)
  5785.             info-server-descr (subfield txt 3)
  5786.             found-info t))
  5787.          ((string-match "^\\([^ :]+\\) *: *\\([^ ].*[^ ]\\) *$" txt)
  5788.           (setq info-server-name (subfield txt 1)
  5789.             info-server-descr (subfield txt 2)
  5790.             found-info t)))
  5791.         (if (not found-info)
  5792.         (progn
  5793.           (irc-insert "%%Found unknown RPL312 in irc-parse-RPL-3xx:")
  5794.           (irc-insert "%% \"%s\" (txt)." txt)
  5795.           (irc-insert "%% Please tell %s, it might be a bug."
  5796.                   irc-hacker))
  5797.           (irc-remember info-server-name 'irc-servernames)
  5798.           (let ((s (format "%s%son %s (%s)%s."
  5799.                    irc-msg-cont-used
  5800.                    (if info-real-server-or-relay-name
  5801.                    (concat "(according to "
  5802.                        info-real-server-or-relay-name
  5803.                        ") ")
  5804.                  "")
  5805.                    info-server-name
  5806.                    (irc-clean-up-message
  5807.                 (irc-nuke-whitespace info-server-descr))
  5808.                    (if info-hop-count
  5809.                    (concat " at least "
  5810.                        info-hop-count
  5811.                        " hops away")
  5812.                  ""))))
  5813.         (irc-insert "%s" s)))))
  5814.      ((= num 313)            ; RPL_WHOISOPERATOR
  5815.       (string-match "^[^: ]+" txt)
  5816.       (irc-insert "%s\"%s\" is an ENABLED operator on IRC."
  5817.               irc-msg-cont-used
  5818.               (substring txt (match-beginning 0) (match-end 0))))
  5819.      ((= num 314)                 ; RPL_WHOWASUSER
  5820.       (if (string-match (concat "^\\([^: ]+\\) \\([^: ]+\\) \\([^: ]+\\)"
  5821.                     " \\([^: ]+\\) *:")
  5822.                 txt)
  5823.           (let* ((nick (subfield txt 1))
  5824.              (rn (substring txt (match-end 0)))
  5825.              (user-name (subfield txt 2))
  5826.              (client (subfield txt 3))
  5827.              (c (subfield txt 4))
  5828.              (channel (if (string= c "*")
  5829.                   ""
  5830.                 (concat " on channel " c)))
  5831.              (real-name (irc-nuke-whitespace rn))
  5832.              (cntrl1 (format "%%User \"%s\" " nick)))
  5833.         (setq irc-msg-cont-used (make-string (length cntrl1) ? ))
  5834.         (if (not (irc-recall nick 'irc-services))
  5835.             (irc-forget nick 'irc-nicknames))
  5836.         (irc-insert (concat "%" cntrl1 "isn't on IRC anymore,"
  5837.                     " was %s <%s@%s>%s,")
  5838.                 (irc-clean-up-message real-name)
  5839.                 (irc-clean-up-message user-name)
  5840.                 client
  5841.                 channel))))
  5842.      ((= num 315)                 ; RPL_WHOEND
  5843.       (if (= 0 irc-reply-count)
  5844.           (irc-insert "%%No users listed")
  5845.         (irc-insert "%s%d user%s listed%s"
  5846.             irc-msg-info-pre
  5847.             irc-reply-count
  5848.             (if (= 1 irc-reply-count) "" "s")
  5849.             irc-msg-info-post))
  5850.       (setq irc-reply-count 0)
  5851.       (if t ()
  5852.         (message "")
  5853.         (if (irc-nothing-remembered-p 'irc-whotree)
  5854.         (let ((c (if (string-match (concat "^ *: *[^ ]+ +315"
  5855.                            " +[^ ]+ +\\([^:]+\\)"
  5856.                            " +:")
  5857.                        str)
  5858.                  (subfield str 1))))
  5859.           (irc-insert (if c "%%No users on \"%s\"." "%%No users.")
  5860.                   c))
  5861.           (irc-recall-all-and-display 'irc-whotree
  5862.                     ;(string-match "-* *$"
  5863.                     ;irc-who-stroke)
  5864.                       31
  5865.                       "users"
  5866.                       "user")
  5867.           (irc-forget-all 'irc-whotree)))
  5868.       )
  5869.      ((= num 316)                 ; RPL_WHOISCHANOP
  5870.       (if (not
  5871.            (string-match (concat "^:\\([^: ]+\\)? +316 +\\([^: ]+\\) +"
  5872.                      "\\([^: ]+\\) +: *has +been +"
  5873.                      "touched +by +magic +forces *$")
  5874.                  str))
  5875.           (progn (irc-insert (concat "%%Unrecognized type 316 reply; "
  5876.                      "please tell %s:")
  5877.                  irc-hacker)
  5878.              (irc-insert "%% \"%s\"." str)
  5879.              (irc-insert " Function irc-parse-RPL-3xx, at 316."))
  5880.         (let ((server (substring str (match-beginning 1) (match-end 1)))
  5881.           (own (substring str (match-beginning 2) (match-end 2)))
  5882.           (other (substring str (match-beginning 3) (match-end 3))))
  5883.           (irc-remember own 'irc-nicknames)
  5884.           (irc-remember other 'irc-nicknames)
  5885.           (irc-insert "%s\"%s\" is a channel operator."
  5886.               irc-msg-cont-used
  5887.               other))))
  5888.      ((= num 317)            ;RPL_IDLETIME
  5889.       (cond ((or (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+"
  5890.                        " +\\([^ ]+\\)"
  5891.                        " +\\([0-9]+\\)"
  5892.                        " +\\([0-9]+\\)"
  5893.                        " *:")
  5894.                    str)
  5895.              (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+"
  5896.                        " +\\([^ ]+\\)"
  5897.                        " +\\([0-9]+\\)"
  5898.                        "\\(\\) *:")
  5899.                    str)
  5900.              (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+\\(\\)\\(\)"
  5901.                        " +\\([0-9]+\\)"
  5902.                        " *:")
  5903.                    str))
  5904.          (let* ((user (subfield str 1))
  5905.             (time (string-to-int (subfield str 2)))
  5906.             (logintime (string-to-int (subfield str 3))))
  5907.            (if (zerop time)
  5908.                (irc-insert "%s\"%s\" is actively typing."
  5909.                    irc-msg-cont-used
  5910.                    user)
  5911.              (irc-insert "%sIdle time for user %s is %d second%s%s."
  5912.                  irc-msg-cont-used
  5913.                  user
  5914.                  time
  5915.                  (if (= 1 time) "" "s")
  5916.                  (if (> 60 time)
  5917.                      ""
  5918.                    (concat " ("
  5919.                        (irc-sec-to-time time)
  5920.                        ")"))))))
  5921.         (t (irc-insert (concat "%%Unknown 317 type reply message in"
  5922.                        " function irc-parse-RPL-3xx."))
  5923.            (irc-insert "%% \"%s\" (str)." str)
  5924.            (irc-insert "%% Please tell %s, it might be a bug."
  5925.                    irc-hacker))))
  5926.      ((= num 318)                 ; RPL_ENDOFWHOIS
  5927.       )
  5928.      ((= num 319)
  5929.       (cond ((string-match "^\\([^:]*:\\)?" txt)
  5930.          (let ((list (irc-listify
  5931.                   (irc-burst-comma
  5932.                    (irc-nuke-whitespace
  5933.                 (substring txt (match-end 0))))
  5934.                   ", " "and")))
  5935.            (irc-insert "%sis listening to channel%s %s,"
  5936.                    irc-msg-cont-used
  5937.                    (if (string-match " [^ ]" list) "s" "")
  5938.                    list)))
  5939.         (t (irc-insert (concat "%%Unknown 319 type reply message in"
  5940.                        " function irc-parse-RPL-3xx."))
  5941.            (irc-insert "%% \"%s\" (txt)." txt)
  5942.            (irc-insert "%% Please tell %s, it might be a bug."
  5943.                    irc-hacker))))
  5944.      ((= num 321)                       ; RPL_LISTSTART
  5945.       (irc-insert irc-list-header)
  5946.       (irc-insert irc-list-stroke)
  5947.       (setq irc-list-stats '(0 0))
  5948.       (set-buffer-modified-p (buffer-modified-p)))
  5949.      ((= num 322)                       ; RPL_LIST
  5950.       (if (not (string-match "^\\([^ ]+\\) \\([^ ]+\\) :" txt))
  5951.           (progn (irc-insert (concat "%%Unknown format on RPL_LIST"
  5952.                      " message; please tell %s.")
  5953.                  irc-hacker)
  5954.              (irc-insert "%% \"%s\" (txt)." txt)
  5955.              (irc-insert "%% Function irc-parse-RPL-3xx, at 322."))
  5956.         (let* ((chan (substring txt (match-beginning 1) (match-end 1)))
  5957.            (count (substring txt (match-beginning 2) (match-end 2)))
  5958.            (topic (irc-nuke-whitespace
  5959.                (substring txt (match-end 0))))
  5960.            (tmpline (format "%s   %2s   "
  5961.                     (irc-format-channel chan)
  5962.                     count))
  5963.            (top (irc-clean-up-message topic))
  5964.            (line (concat tmpline top))
  5965.            (irc-msg-cont-used (make-string (length tmpline) ? )))
  5966.           (if (or t (> (string-to-int count) 10))
  5967.           (let ((irc-msg-cont-used (make-string
  5968.                         (string-match "-* *$"
  5969.                               irc-list-stroke)
  5970.                         ? )))
  5971.             (setq irc-list-stats (list (1+ (car irc-list-stats))
  5972.                            (+ (nth 1 irc-list-stats)
  5973.                           (string-to-int count))))
  5974.             (irc-insert (irc-clean-up-message line)))))))
  5975.      ((= num 323)                       ; RPL_LISTEND
  5976.       (let ((ch (car irc-list-stats))
  5977.         (us (nth 1 irc-list-stats)))
  5978.         (if (and (zerop us) (zerop ch))
  5979.         (irc-insert "%%No visible channels.")
  5980.           (irc-insert (concat "%s%s user%s on the %s channel%s"
  5981.                   " which happen to be visible%s")
  5982.               irc-msg-info-pre
  5983.               (if (zerop us) "No" (int-to-string us))
  5984.               (if (= 1 us) "" "s")
  5985.               (if (zerop ch) "No" (int-to-string ch))
  5986.               (if (= 1 ch) "" "s")
  5987.               irc-msg-info-post)))
  5988.       (setq irc-list-stats '(0 0)))
  5989.      ((= num 324)                 ; RPL_CHANNELMODEIS
  5990.       (let* ((lst (if (irc-server-has-channelname-in-msgs)
  5991.               (if (string-match
  5992.                    (concat "^ *: *\\([^ ]+\\) +324" ;origin
  5993.                        " +\\([^ ]+\\)"    ;nick
  5994.                        " +\\([^ ]+\\)"    ;channel
  5995.                        " +\\(\\+[^ ]*\\)" ;mode
  5996.                        "\\( [-+]?[^ ]+\\)? *$") ;extra
  5997.                    str)
  5998.                   (list (subfield str 1) ;origin
  5999.                     (subfield str 2) ;nick
  6000.                     (subfield str 3) ;channel
  6001.                     (subfield str 4) ;mode (at least a "+")
  6002.                     (subfield str 5)))    ;limit (optional)
  6003.             (if (string-match
  6004.                  (concat "^ *: *\\([^ ]+\\) +324 +"
  6005.                      "\\([^ ]+\\) +\\(+[^ ]*\\)"
  6006.                      "\\( +[0-9]+\\)? *$")
  6007.                  str)
  6008.                 (list (subfield str 1) ;origin
  6009.                   (subfield str 2) ;nick
  6010.                   nil ;channel not given
  6011.                   (subfield str 3) ;mode (at least "+")
  6012.                   (subfield str 4))))) ;limit (optional)
  6013.          (orig (nth 0 lst))
  6014.          (nick (nth 1 lst))
  6015.          (channel (nth 2 lst))
  6016.          (mode (if lst (irc-nuke-whitespace (concat (nth 3 lst)
  6017.                                 (nth 4 lst)))))
  6018.          (expl (if lst (irc-explain-channel-mode mode 'skip-dir)))
  6019.          (chntxt (concat (if channel "The channel " "The channels")
  6020.                  (if channel
  6021.                      (concat
  6022.                       channel
  6023.                       "'"
  6024.                       (if (not (= ?s (aref channel
  6025.                                (1- (length
  6026.                                 channel)))))
  6027.                       "s"))
  6028.                    "")
  6029.                  " "))
  6030.          (irc-msg-cont-used (make-string (+ (length chntxt)
  6031.                             (length irc-msg-info-pre))
  6032.                          ? )))
  6033.         (if (not lst)
  6034.         (progn
  6035.           (irc-insert (concat "%%Received RPL_CHANNELMODEIS reply"
  6036.                       " in unknown format:"))
  6037.           (irc-insert "%% \"%s\" (str)." str)
  6038.           (irc-insert "%% In irc-parse-RPL-3xx at 324. Please tell %s."
  6039.                   irc-hacker))
  6040.           (progn
  6041.         (if (irc-is-nickname orig)
  6042.             (irc-remember orig 'irc-nicknames))
  6043.         (if (and (irc-is-hostname orig)
  6044.              (not (string= (upcase origin) (upcase orig))))
  6045.             (irc-remember orig 'irc-servernames))
  6046.         (irc-remember nick 'irc-nicknames)
  6047.         (if (or t (string= (upcase orig) (upcase irc-server)))
  6048.             (irc-insert "%s%smode%s %s %s%s"
  6049.                 irc-msg-info-pre
  6050.                 chntxt 
  6051.                 (if (string-match " and " expl) "s" "")
  6052.                 (if (string-match " and " expl) "are" "is")
  6053.                 expl
  6054.                 irc-msg-info-post)
  6055.           ;; Ignore MODE replies from remote servers.
  6056.           )))))
  6057.      ((= num 325)
  6058.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6059.      ((= num 329)            ;undernet: time of channe; creation
  6060.       (cond ((string-match "\\([^ ]+\\) +\\([^ ]+\\)$" txt) ;Undernet
  6061.          ;;(let ((chan (subfield txt 1))
  6062.          ;;    (time (subfield txt 2)))
  6063.          ;;(irc-insert "%sNYI: channel %s was created at <%s>%s"
  6064.          ;;        irc-msg-info-pre
  6065.          ;;        chan
  6066.          ;;        time
  6067.          ;;        irc-msg-info-post))
  6068.          )
  6069.         (t (irc-insert "%% Bad 329 message, txt=\"%s\"." txt))))
  6070.      ((= num 331)                       ; RPL_NOTOPIC
  6071.       (if (string= parorg "")    ;Not when message from remote (old)
  6072.           (if (string-match (concat "^\\([^ ]+\\) +: *No +topic"
  6073.                     " +is +set *.? *$")
  6074.                 txt)
  6075.           (irc-insert "%sNo topic is set for channel %s%s"
  6076.                   irc-msg-info-pre
  6077.                   (subfield txt 1)
  6078.                   irc-msg-info-post)
  6079.         (irc-insert "%sNo topic is set%s"
  6080.                 irc-msg-info-pre
  6081.                 irc-msg-info-post))))
  6082.      ((= num 332)                       ; RPL_TOPIC
  6083.       (cond ((and (irc-server-has-end-of-whois)
  6084.               (string-match "^\\([^ ]+\\) *:" txt))
  6085.          (irc-insert "%sThe topic for channel %s is \"%s\"%s"
  6086.                  irc-msg-info-pre
  6087.                  (irc-clean-up-message (subfield txt 1))
  6088.                  (irc-clean-up-message
  6089.                   (irc-nuke-whitespace
  6090.                    (substring txt (match-end 0))))
  6091.                  irc-msg-info-post))
  6092.         ((string-match ":?" txt)
  6093.          (irc-insert "%sThe topic is \"%s\"%s"
  6094.                  irc-msg-info-pre
  6095.                  (irc-clean-up-message (substring txt
  6096.                                   (match-end 0)))
  6097.                  irc-msg-info-post))
  6098.         (t (irc-insert "%sThe topic is \"%s\"%s"
  6099.                    irc-msg-info-pre
  6100.                    (irc-clean-up-message txt)
  6101.                    irc-msg-info-post))))
  6102.      ((= num 333)
  6103.       (cond ((string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([0-9]+\\)$" txt)
  6104.          (irc-insert "%sChannel %s created by %s%s"
  6105.                  irc-msg-info-pre
  6106.                  (subfield txt 1)
  6107.                  (subfield txt 2)
  6108.                  irc-msg-info-post))
  6109.         (t (irc-insert "%% Bad 333 message, txt=\"%s\"." txt))))
  6110.      ((= num 338)
  6111.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6112.      ((= num 339)
  6113.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6114.      ((= num 341)                       ; RPL_INVITING
  6115.       (string-match (concat "^:\\([^: ]+\\) +341 +[^: ]+ +\\([^: ]+\\) +"
  6116.                 "\\([^ ]+\\)")
  6117.             str)
  6118.       (let ((nick (subfield str 2))
  6119.         (channel (subfield str 3)))
  6120.         (irc-remember nick 'irc-nicknames)
  6121.         (irc-insert "%sYou are inviting user \"%s\" to channel %s%s"
  6122.             irc-msg-info-pre
  6123.             nick
  6124.             (irc-clean-up-message channel)
  6125.             irc-msg-info-post)))
  6126.      ((= num 351)                       ; RPL_VERSION | RPL_WHOREPLY
  6127.       (if (string-match "^\\([^: ]+\\) :?\\([^: ]+\\)" txt)
  6128.           (let ((s (substring txt (match-beginning 2) (match-end 2)))
  6129.             (v (substring txt (match-beginning 1) (match-end 1))))
  6130.         (if (not (string= (upcase origin) (upcase s)))
  6131.             (irc-remember s 'irc-servernames))
  6132.         (irc-insert (concat "%sIRC server %s is running version %s,"
  6133.                     " and the client you are using is %s%s")
  6134.                 irc-msg-info-pre
  6135.                 (upcase s)
  6136.                 v
  6137.                 irc-version
  6138.                 irc-msg-info-post))))
  6139.      ((= num 352)
  6140.       ;;(irc-parse-whoreply (format "WHOREPLY %s" txt))
  6141.       (cond ((= 0 irc-reply-count)
  6142.          (irc-insert irc-who-header)
  6143.          (irc-insert irc-who-stroke) 
  6144.          (setq irc-msg-cont-used (make-string
  6145.                       (string-match "-* *$"
  6146.                             irc-who-stroke)
  6147.                       ? ))))
  6148.       (setq irc-reply-count (1+ irc-reply-count))
  6149.       (if (string-match (concat "^\\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\\)"
  6150.                     " \\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\\)"
  6151.                     " :\\([0-9]+\\) \\(.+\\)$")
  6152.                 txt)
  6153.           (let* ((chan (subfield txt 1))
  6154.              (login (subfield txt 2))
  6155.              (client (subfield txt 3))
  6156.              (server (subfield txt 4))
  6157.              (nick (subfield txt 5))
  6158.              (mode (subfield txt 6))
  6159.              (unkn (subfield txt 7))
  6160.              (realname (subfield txt 8))
  6161.              (vsts (cond ((irc-recall nick 'irc-ignored-ppl) "IGNR")
  6162.                  ((string= "H"   mode) "    ") ;Norm
  6163.                  ((string= "G"   mode) "Away") ;Away
  6164.                  ((string= "H*"  mode) "Iopr") ;Iopr
  6165.                  ((string= "G*"  mode) "IoAw") ;IoAw
  6166.                  ((string= "H@"  mode) "Copr") ;Copr
  6167.                  ((string= "G@"  mode) "CoAw") ;CoAw
  6168.                  ((string= "H*@" mode) "ICop") ;ICop
  6169.                  ((string= "G*@" mode) "ICAw") ;ICAw
  6170.                  ((string= "S"   mode) "    ") ;Norm
  6171.                  (t mode))))
  6172.         (irc-insert "%-9s %-4s %-15s %s@%s \"%s\""
  6173.                 nick
  6174.                 vsts
  6175.                 chan
  6176.                 login
  6177.                 client
  6178.                 realname))))
  6179.      ((= num 353)                       ; RPL_NAMREPLY
  6180.       (if (or (string-match "^@ +\\([#&][^ ]+\\) +:?" txt)
  6181.           (string-match "^ *[=*] +\\([^ ]+\\) *:" txt))
  6182.           (let ((c (subfield txt 1))
  6183.             (n (substring txt (match-end 0))))
  6184.         (irc-parse-namreply
  6185.          (format "NAMREPLY placeholder %s %s" c n)))
  6186.         (irc-parse-namreply (format "NAMREPLY %s" txt))))
  6187.      ((= num 354)                       ; RPL_ENDOFNAMES
  6188.       (irc-insert "Names 354: %s" txt))
  6189.      ((= num 361)                       ; RPL_KILLDONE
  6190.       (string-match "^[^: ]+" txt)
  6191.       (irc-insert "%sYou have removed \"%s\" from IRC (/killed)%s"
  6192.               irc-msg-info-pre
  6193.               (substring txt (match-beginning 0) (match-end 0))
  6194.               irc-msg-info-post))
  6195.      ((= num 364)                 ; RPL_LINKS
  6196.       (if (not (or (string-match "^\\([^ ]*\\) \\([^ ]*\\) *:" txt)
  6197.                (string-match "^\\([^ ]*\\) *:" txt)))
  6198.           (progn
  6199.         (irc-insert "%%Error in parsing RPL 364, please tell %s:"
  6200.                 irc-hacker)
  6201.         (irc-insert "%% \"%s\" (txt)." txt)
  6202.         (irc-insert "%% In function irc-parse-RPL-3xx, at 364."))
  6203.         (let ((s (upcase (subfield txt 1)))
  6204.           (f2 (subfield txt 2))
  6205.           (info (irc-nuke-whitespace
  6206.              (irc-clean-up-message
  6207.               (substring txt (match-end 0))))))
  6208.           (setq irc-reply-count (1+ irc-reply-count))
  6209.           (let ((diff (irc-time-diff (irc-current-time)
  6210.                      irc-reply-count-time)))
  6211.         (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since last
  6212.                (> (nth 0 diff) 0)) ; display?
  6213.                (setq irc-reply-count-time (irc-current-time))
  6214.                (message (format " %d server%s ..."
  6215.                     irc-reply-count
  6216.                     (if (= 1 irc-reply-count)
  6217.                         ""
  6218.                       "s"))))))
  6219.           (irc-remember (format "Server %s%s: %s"
  6220.                     s
  6221.                     (if (string= "" f2)
  6222.                     ""
  6223.                       (format " (to %s)" (upcase f2)))
  6224.                     info) 
  6225.                 'irc-linksinfo)
  6226.           (if (not (string= (upcase origin) (upcase s)))
  6227.           (irc-remember s 'irc-servernames)))))
  6228.      ((= num 365)                 ; RPL_ENDOFLINKS
  6229.       (setq irc-reply-count 0)
  6230.       (message "")
  6231.       (irc-insert irc-links-header)
  6232.       (irc-insert irc-links-stroke)
  6233.       (set-buffer-modified-p (buffer-modified-p))
  6234.       (irc-recall-all-and-display 'irc-linksinfo
  6235.                       (progn (string-match "^[^: ]* ."
  6236.                                irc-links-header)
  6237.                          (match-end 0))
  6238.                       "servers"
  6239.                       "server") 
  6240.       (irc-forget-all 'irc-linksinfo))
  6241.      ((= num 366)                 ; RPL_NAMES_END
  6242.       (setq irc-reply-count 0)
  6243.       (message "")
  6244.       (if (irc-terminal-is-slow)
  6245.           (let ((lincnt 0)
  6246.             (usrcnt 0)
  6247.             (adjust 0)
  6248.             (w (irc-recall-all 'irc-namtree))
  6249.             (irc-msg-cont-used irc-names-cont-msg))
  6250.         (irc-insert "Name of channel  Users  Nicknames")
  6251.         (irc-insert "---------------  -----  ---------")
  6252.         (set-buffer-modified-p (buffer-modified-p))
  6253.         (while w
  6254.           (irc-insert "%s" (car w))
  6255.           (let* ((pair (if (string-match (concat "^ *\\([^ ]+\\) +"
  6256.                              "\\([0-9]+\\)")
  6257.                          (car w))
  6258.                    (cons (subfield (car w) 1)
  6259.                      (subfield (car w) 2))
  6260.                  (cons "" "0")))
  6261.              (ldiff (if (string= "PRIVATE" (upcase (car pair)))
  6262.                     1
  6263.                   0))
  6264.              (udiff (string-to-int (cdr pair))))
  6265.             (setq usrcnt (+ usrcnt udiff)
  6266.               lincnt (1+ lincnt)
  6267.               adjust (+ adjust ldiff)
  6268.               w (cdr w))))
  6269.         (let ((adjusted (- lincnt adjust)))
  6270.           (irc-insert (concat "%s%d visible user%s on %d visible"
  6271.                       " channel%s or on some private"
  6272.                       " channel%s")
  6273.                   irc-msg-info-pre
  6274.                   usrcnt
  6275.                   (if (= usrcnt 1) "" "s")
  6276.                   adjusted
  6277.                   (if (= adjusted 1) "" "s")
  6278.                   irc-msg-info-post)
  6279.           (irc-insert ""))
  6280.         (irc-forget-all 'irc-namtree))
  6281.         ;; Else fast terminal.
  6282.         (irc-insert "%sEnd of NAMES list%s"
  6283.             irc-msg-info-pre
  6284.             irc-msg-info-post)))
  6285.      ((= num 367)                       ; RPL_BANLIST
  6286.       (cond
  6287.        ((string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\) +\\(.+\\)$"
  6288.               txt)
  6289.         (let ((chan (subfield txt 1))
  6290.           (banned (subfield txt 2))
  6291.           (banner (subfield txt 3))
  6292.           (time (subfield txt 4)))
  6293.           (irc-insert "%sUser(s) \"%s\" are banned from %s by %s at %s%s"
  6294.               irc-msg-info-pre
  6295.               banned
  6296.               chan
  6297.               banner
  6298.               time
  6299.               irc-msg-info-post)))
  6300.        ((string-match "^\\([^ ]+\\) +\\(.+\\)$" txt)
  6301.         (let ((channel (subfield txt 1))
  6302.           (user (subfield txt 2)))
  6303.           (irc-insert (concat "%sUser(s) matching \"%s\""
  6304.                   " are banned from %s%s")
  6305.               irc-msg-info-pre user channel irc-msg-info-post)))
  6306.        (t (irc-insert "%%Unknown type 367 reply seen in irc-parse-RPL-3xx:")
  6307.           (irc-insert "%% \"%s\" (txt)" txt)
  6308.           (irc-insert "%% Please tell %s, it might be a bug."
  6309.               irc-hacker))))
  6310.      ((= num 368)                       ; RPL_BANLISTEND 
  6311.       (irc-insert (concat "%sEnd of list of banned users (who are"
  6312.                   " prohibited to join)%s")
  6313.               irc-msg-info-pre irc-msg-info-post))
  6314.      ((= num 369)                 ; RPL_ENDOFWHOWAS
  6315.       )
  6316.      ((= num 371)                       ; RPL_INFO
  6317.       (irc-insert "* %s" txt))
  6318.      ((= num 372)                       ; RPL_MOTD
  6319.       (cond
  6320.        ((string-match (concat "^ *: *\\([^: ]+\\)? +372 *\\([^: ]+\\)?"
  6321.                   " *: *Message-of-today +not +found +"
  6322.                   "in +server +\\([^: ]+\\) *$")
  6323.               str)
  6324.         (let* ((f (substring str (match-beginning 1) (match-end 1)))
  6325.            (frm (if (string= (upcase f) (upcase irc-server)) "" f))
  6326.            (at (substring str (match-beginning 3)
  6327.                   (match-end 3))))
  6328.           (if (not (string= (upcase origin) (upcase frm)))
  6329.           (irc-remember frm 'irc-servernames))
  6330.           (if (not (string= (upcase origin) (upcase at)))
  6331.           (irc-remember at 'irc-servernames))
  6332.           (irc-insert "%%%sNo message of the day at server %s."
  6333.               (if (string= frm "")
  6334.                   ""
  6335.                 (concat "(" frm ") "))
  6336.               (upcase at))))
  6337.        ((string-match (concat "^ *: *\\([^: ]+\\)? +372 *"
  6338.                   "\\([^: ]+\\)? *:? *"
  6339.                   "\\(start\\|end\\)?"
  6340.                   "\\( +at +server +\\)?"
  6341.                   "\\([A-Za-z.-.---]*\\|.*\\)"
  6342.                   "\\( *:\\)? *$")
  6343.               str)
  6344.         (let* ((from-1 (irc-non-num-to-0 (match-beginning 1)))
  6345.            (to-1 (irc-non-num-to-0 (match-end 1)))
  6346.            (from-2 (irc-non-num-to-0 (match-beginning 2)))
  6347.            (to-2 (irc-non-num-to-0 (match-end 2)))
  6348.            (from-3 (irc-non-num-to-0 (match-beginning 3)))
  6349.            (to-3 (irc-non-num-to-0 (match-end 3)))
  6350.            (from-4 (irc-non-num-to-0 (match-beginning 4)))
  6351.            (to-4 (irc-non-num-to-0 (match-end 4)))
  6352.            (from-5 (irc-non-num-to-0 (match-beginning 5)))
  6353.            (to-5 (irc-non-num-to-0 (match-end 5)))
  6354.            (from-6 (irc-non-num-to-0 (match-beginning 6)))
  6355.            (to-6 (irc-non-num-to-0 (match-end 6)))
  6356.            (server (substring str from-1 to-1))
  6357.            (user (substring str from-2 to-2))
  6358.            (direction (substring str from-3 to-3))
  6359.            (token (substring str from-4 to-4))
  6360.            (message (substring str from-5 to-5))
  6361.            (colon (substring str from-6 to-6)))
  6362.           (if (and (not (string= "" server))
  6363.                (not (string= (upcase origin) (upcase server))))
  6364.           (irc-remember server 'irc-servernames))
  6365.           (if (not (string= "" user))
  6366.           (irc-remember user 'irc-nicknames))
  6367.           (cond ((and (or (string= (downcase direction) "start")
  6368.                   (string= (downcase direction) "end"))
  6369.               (string-match "^ *at +server *$" token)
  6370.               (not (string= "" message))
  6371.               (string-match "^ *:$" colon)
  6372.               (not (string= (upcase origin)
  6373.                     (upcase message))))
  6374.              (irc-remember message 'irc-servernames))
  6375.             ((string-match "[^: ]" message)
  6376.              (irc-insert ">>> %s" (concat direction
  6377.                           token
  6378.                           message
  6379.                           colon))))))
  6380.        (t (irc-insert (concat "%%Unkown format on MOTD reply,"
  6381.                   " in function irc-parse-RPL-3xx,"
  6382.                   " num 372"))
  6383.           (irc-insert "%% \"%s\"." str))))
  6384. ;;;       ((= num 373)                       ; RPL_VERSION
  6385. ;;;        (irc-insert "DEBUG: RPL373 txt=\"%s\"." txt))
  6386.      ((= num 374)            ;RPL_INFO_END
  6387.       (irc-insert "%sEnd of information about this IRC server%s"
  6388.               irc-msg-info-pre irc-msg-info-post))
  6389.      ((= num 375)            ;RPL, start of MOTD
  6390.       (irc-insert ">>> %s" txt))
  6391.      ((= num 376)            ;RPL, end of MOTD
  6392.       (irc-insert "%sEnd of MOTD at %s%s"
  6393.               irc-msg-info-pre origin irc-msg-info-post))
  6394.      ((= num 377)
  6395.       (irc-insert ">>> %s" txt))
  6396.      ((= num 381)                       ; RPL_YOUREOPER
  6397.       (setq irc-operator " IOPR")
  6398.       (set-buffer-modified-p (buffer-modified-p))
  6399.       (irc-insert "%sOperator status for %s ENABLED%s"
  6400.               irc-msg-info-pre
  6401.               irc-nick-used
  6402.               irc-msg-info-post))
  6403.      ((= num 382)                       ; RPL_REHASHING
  6404.       (irc-insert "%sReread local ircd configuration information%s"
  6405.               irc-msg-info-pre
  6406.               irc-msg-info-post))
  6407. ;;;       ((= num 383)                       ; RPL_YOURESERVICE / Kim
  6408. ;;;        (irc-insert "DEBUG: RPL383, txt=\"%s\"." txt))
  6409. ;;;       ((= num 384)                       ; RPL_MYPORTIS / Kim
  6410. ;;;        (irc-insert "DEBUG: RPL384 txt=\"%s\"." txt))
  6411. ;;;       ((= num 385)            ; deop reply?
  6412. ;;;        (irc-insert "DEBUG: RPL385 txt=\"%s\"." txt))
  6413.      ((= num 391)                       ; RPL_TIME
  6414.       (setq irc-last-time (irc-get-time))
  6415.       (let* ((pair
  6416.           (if (string-match (concat
  6417.                      "^ *\\([^ :]+\\) *: *" ;srvr
  6418.                      "\\([A-Za-z][A-Za-z][A-Za-z]\\)"
  6419.                      "[A-Za-z]*day" ;weekday
  6420.                      " +\\(...\\)[^: ]* +" ;month
  6421.                      "\\([0-9]+\\) +"     ;monthday
  6422.                      "\\([0-9]+\\) +-* *") ;year
  6423.                     txt)
  6424.               (cons (subfield txt 1) 
  6425.                 (format "%s %s %s %s %s"
  6426.                     (substring txt (match-end 0)) ;clock
  6427.                     (subfield txt 2) ;weekday
  6428.                     (subfield txt 4) ;monthday
  6429.                     (subfield txt 3) ;month
  6430.                     (subfield txt 5))) ;year
  6431.             (progn (string-match "^\\([^: ]+\\) :" txt)
  6432.                (cons (subfield txt 1)
  6433.                  (irc-nuke-whitespace
  6434.                   (substring txt (match-end 0)))))))
  6435.          (server (car pair))
  6436.          (server (if (string= "" server) origin server))
  6437.          (date (irc-nuke-whitespace (cdr pair))))
  6438.         (irc-insert "%sLocal time at %s is %s%s%s"
  6439. ;;;             "%s%s%s local time is %s%s%s"
  6440.             irc-msg-info-pre
  6441.             (upcase server)
  6442. ;;;             (if (= ?S (aref (upcase server) (1- (length server))))
  6443. ;;;                 "'"
  6444. ;;;                 "'s")
  6445.             date
  6446.             (if (string= "0" irc-channel)
  6447.                 ""
  6448.               (concat " /" irc-channel))
  6449.             irc-msg-info-post)))
  6450.      ((or (= num 392)
  6451.           (= num 393))
  6452.       (irc-parse-notice (format ":%s NOTICE %s :%s"
  6453.                     origin user txt)))
  6454.      ((= num 394)
  6455.       (irc-insert "%sEnd of USERS at %s%s"
  6456.               irc-msg-info-pre origin irc-msg-info-post))
  6457.      ((= num 395)
  6458.       (irc-insert "%%No one logged in on Internet host %s" origin))
  6459.      (t                                 ; default
  6460.       (irc-insert (concat "%%Unrecognized numeric RPL 3xx message; "
  6461.                   "please tell %s:")
  6462.               irc-hacker)
  6463.       (irc-insert "%% str=\"%s\"." str)
  6464.       (irc-insert "%% Function irc-parse-RPL-3xx."))))
  6465.     ;; else
  6466.     (irc-insert (concat "%%Unrecognized nonnumeric RPL 3xx message follows; "
  6467.             "please tell %s:")
  6468.         irc-hacker)
  6469.     (irc-insert "%% \"%s\"." str)
  6470.     (irc-insert "%% Function irc-parse-RPL-3xx."))
  6471.   nil)
  6472.  
  6473.  
  6474. (defun irc-parse-topic (str)
  6475.   "Examine a TOPIC message from the IRC server.
  6476. TOPIC is sent to all of the users on a channel when someone changes the
  6477. topic of the channel.  Secret channels can not have the topic set.  TOPIC
  6478. messages are displayed as long as 'topic' is in irc-events, even if the user
  6479. changing the topic is being ignored.
  6480.  
  6481. This function returns t if a signal should be issued for the 'topic' event,
  6482. nil otherwise."
  6483.   (if (not (string-match "^:\\([^: ]+\\) +TOPIC +\\([^ ]*\\) *:" str))
  6484.       (progn (irc-insert "%%Unknown TOPIC command in irc-parse-topic:")
  6485.          (irc-insert "%% \"%s\"." str)
  6486.          (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  6487.     (let* ((user (subfield str 1))
  6488.        (chnl (subfield str 2))
  6489.        (topic (substring str (match-end 0)))
  6490.        (old-chnl (let ((l (irc-recall-all 'irc-subscribed-channels)))
  6491.                (while (not (atom l))
  6492.              (setq l (if (irc-is-multijoinable-channel (car l))
  6493.                      (cdr l)
  6494.                    (car l))))
  6495.                (if (listp l) "" l)))
  6496.        (channel (if (string< "" chnl) chnl old-chnl)))
  6497.       (irc-remember user 'irc-nicknames)
  6498.       (irc-remember channel 'irc-subscribed-channels)
  6499.       (irc-insert (concat "%s%s has changed the topic of channel %s to \""
  6500.               (irc-clean-up-message topic)
  6501.               "\"%s")
  6502.           irc-msg-info-pre
  6503.           user
  6504.           channel
  6505.           irc-msg-info-post)
  6506.       (if (memq 'topic irc-events)
  6507.       (irc-signal user 'topic)))))
  6508.  
  6509.  
  6510. (defun irc-parse-wall (str)
  6511.   "Examine a WALL message from the IRC server.
  6512. WALL is sent by IRC operators to everyone on IRC.  A WALL message will
  6513. always be displayed even if the sender is being ignored.
  6514.  
  6515. This function returns t if a signal should be issued for the \"wall\" event,
  6516. nil otherwise."
  6517.   (if (not (string-match "^:? *\\([^: ]*\\) +WALL +:" str))
  6518.       (progn (irc-insert (concat "%%Internal error, function irc-parse-wall"
  6519.                  " called with a non-WALL message:"))
  6520.          (irc-insert "%% \"%s\"." str)
  6521.          (irc-insert "%%Please tell %s about it." irc-hacker)
  6522.          (irc-signal "<internal-error in irc-parse-wall>" 'wall))
  6523.       (let ((user (substring str (match-beginning 1) (match-end 1)))
  6524.         (msg (substring str (match-end 0))))
  6525.     (irc-remember user 'irc-nicknames)
  6526.     (irc-insert (concat (format irc-msg-wall
  6527.                     (concat " (" (irc-get-time) ") ")
  6528.                     user)
  6529.                 msg))
  6530.     (irc-signal user 'wall))))
  6531.  
  6532.  
  6533. (defun irc-parse-wallops (str)
  6534.   "Examine a WALLOPS message from the IRC server.
  6535. WALLOPS are sent by any user to all enabled operators on IRC. A WALLOPS will
  6536. allways be displayed, even if the sender is being ignores.
  6537.  
  6538. This function returns t if a signal should be issued for the \"wall\" event,
  6539. nil otherwise."
  6540.   (if (not (string-match "^: *\\([^: ]*\\) +WALLOPS +:" str))
  6541.       (progn (irc-insert (concat "%%Internal error, function irc-parse-wallops"
  6542.                  " called with a non-WALLOPS message:"))
  6543.          (irc-insert "%% \"%s\"." str)
  6544.          (irc-insert "%%Please tell %s about it." irc-hacker)
  6545.          (irc-signal "<internal-error in irc-parse-wallops>" 'wall))
  6546.       (let* ((sender (substring str (match-beginning 1) (match-end 1)))
  6547.          (msg (substring str (match-end 0))))
  6548.     (cond ((string-match (concat "^Remote 'CONNECT \\([^ ]+\\) +"
  6549.                      "\\([0-9]*\\)' from \\([^ ]+\\) *$")
  6550.                  msg)
  6551.            (let ((nsrv (substring msg (match-beginning 1) (match-end 1)))
  6552.              (port (substring msg (match-beginning 2) (match-end 2)))
  6553.              (user (substring msg (match-beginning 3) (match-end 3))))
  6554.          (cond ((irc-is-nickname user)
  6555.             (irc-remember user 'irc-nicknames))
  6556.                ((irc-is-hostname user)
  6557.             (irc-remember user 'irc-servernames)))
  6558.          (irc-insert (concat "%sTrying to establish a serverlink from"
  6559.                      " %s to %s on port %s on remote command"
  6560.                      " by user \"%s\"%s")
  6561.                  irc-msg-info-pre
  6562.                  (upcase sender)
  6563.                  (upcase nsrv)
  6564.                  port
  6565.                  user
  6566.                  irc-msg-info-post)))
  6567.           ((string-match (concat "Received SQUIT \\([^ ]+\\) +from"
  6568.                      " +\\(.+\\) *$")
  6569.                  msg)
  6570.            (let ((oded (substring msg (match-beginning 1) (match-end 1)))
  6571.              (orig (substring msg (match-beginning 2) (match-end 2))))
  6572.          (cond ((irc-is-nickname orig)
  6573.             (irc-remember orig 'irc-nicknames))
  6574.                ((irc-is-hostname orig)
  6575.             (irc-remember orig 'irc-servernames)))
  6576.          (irc-insert (concat "%sClosing the serverlink from %s to"
  6577.                      " server %s, by order of %s%s")
  6578.                  irc-msg-info-pre
  6579.                  (upcase sender)
  6580.                  (upcase oded) ;OD'ed server
  6581.                  (upcase orig)
  6582.                  irc-msg-info-post)))
  6583.           (t (let* ((head (format "%s%s" (concat
  6584.                           (format (format irc-msg-priv 0) 
  6585.                               (concat " ("
  6586.                                   (irc-get-time)
  6587.                                   ") ")
  6588.                               (concat sender
  6589.                                   " (WALLOPS)")))))
  6590.             (irc-msg-cont-used (make-string
  6591.                         (min
  6592.                          (length head)
  6593.                          (/ (window-width
  6594.                          (get-buffer-window
  6595.                           (current-buffer)))
  6596.                         2))
  6597.                         ? )))
  6598.            (cond ((and (irc-is-hostname sender)
  6599.                    (not (irc-is-nickname sender)))
  6600.               (irc-remember sender 'irc-servernames))
  6601.              ((irc-is-nickname sender)
  6602.               (irc-remember sender 'irc-nicknames)))
  6603.            (irc-insert (concat head (irc-clean-up-message msg))))))
  6604.     (if (irc-is-nickname sender)
  6605.         (irc-signal sender 'wall)
  6606.         (irc-later-execute-lusers)))))
  6607.  
  6608.  
  6609. (defun irc-parse-whoreply (str)
  6610.   "OBSELETE FUNCTION
  6611.  
  6612. Examine a WHOREPLY message from the IRC server.
  6613. The message is formatted into a line that is more easily understood than
  6614. the raw data.  
  6615. The status of the users is shown as a four letter word (:-) according to
  6616. the combination of their attributes. The possible attributes being
  6617. an IRC operator, being a channel operator and being marked away.
  6618.  
  6619.                                           Status field
  6620. A normal user having no attributes set:     (blank)
  6621. A normal user marked as being away:          Away
  6622. An IRC operator with no other attribues:     Iopr
  6623. An IRC operator marked as being away:        IoAw
  6624. A channel operator with no other attributes: Copr
  6625. A channel operator marked as being away:     CoAw
  6626. User being both IRC- and channel operator:   ICop
  6627. As above but also marked as being away:      ICAw
  6628.  
  6629. Being ignored takes precedence over all
  6630. other attributes, always shown as:           IGNR
  6631.  
  6632.  
  6633. No signals are issued for lines from the WHOREPLY."
  6634.   (string-match "^WHOREPLY +" str)
  6635.   (setq str (substring str (match-end 0)))
  6636.   (let ((is-header (or (string-match (concat "^\\* +User +Host +Server"
  6637.                          " +Nickname +S +: *Name *$")
  6638.                      str)
  6639.                (string-match (concat "^Channel +User +Host +Server"
  6640.                          " +Nickname +S +: *Name *$")
  6641.                      str)))
  6642.     (split))          ; make this a list of strings of each data item.
  6643.     ;; the elements of 'split' are:
  6644.     ;; 0 - full name (with possible hop count)
  6645.     ;; 1 - status
  6646.     ;; 2 - nickname
  6647.     ;; 3 - hostname of server
  6648.     ;; 4 - hostname of client
  6649.     ;; 5 - login name
  6650.     ;; 6 - channel
  6651.     (if (or (string-match (concat "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)"
  6652.                   " +\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)"
  6653.                   " +:\\([0-9]+\\)? *\\(.+\\)$")
  6654.               str))
  6655.     (let* ((channel (subfield str 1))
  6656.            (x-login-name (subfield str 2))
  6657.            (x-client-host (subfield str 3))
  6658.            (x-server-host (subfield str 4))
  6659.            (x-nickname (subfield str 5))
  6660.            (x-status (subfield str 6))
  6661.            (hop-count (subfield str 7))
  6662.            (x-full-name (subfield str 8))
  6663.            (name-col (string-match "-* *$" irc-who-stroke)) ;Last stroke
  6664.            (chan-col (string-match "-* +-+ *$" irc-who-stroke)) ;2nd last
  6665.            )
  6666.       (if (not (string= x-status "S")) ;Header?
  6667.           (progn
  6668.         ;; if it isn't the bogus header
  6669.         (irc-remember x-nickname 'irc-nicknames) ; add nick
  6670.         (if (and (not is-header)
  6671.              (irc-terminal-is-slow)
  6672.              (irc-server-has-end-of-who)
  6673.              (irc-nothing-remembered-p 'irc-whotree))
  6674.             (let ((irc-msg-cont-used
  6675.                (make-string name-col ? )))
  6676.               (irc-insert irc-who-header)
  6677.               (irc-insert irc-who-stroke)
  6678.               ;;(sit-for 0)
  6679.               (set-buffer-modified-p (buffer-modified-p))))
  6680.         (irc-remember x-server-host 'irc-servernames) ; hostnames.
  6681.         (irc-remember x-client-host 'irc-servernames)))
  6682.       (let* ((full-name (irc-clean-up-message
  6683.                  x-full-name))
  6684.          (nick-pad (make-string (max 0 (- (1- 10) (length x-nickname)))
  6685.                     ? ))
  6686.          (vsts (cond ((irc-recall x-nickname 'irc-ignored-ppl) "IGNR")
  6687.                  ((string= "H"   x-status) "    ") ;Norm
  6688.                  ((string= "G"   x-status) "Away") ;Away
  6689.                  ((string= "H*"  x-status) "Iopr") ;Iopr
  6690.                  ((string= "G*"  x-status) "IoAw") ;IoAw
  6691.                  ((string= "H@"  x-status) "Copr") ;Copr
  6692.                  ((string= "G@"  x-status) "CoAw") ;CoAw
  6693.                  ((string= "H*@" x-status) "ICop") ;ICop
  6694.                  ((string= "G*@" x-status) "ICAw") ;ICAw
  6695.                  ((string= "S"   x-status) "    ") ;Norm
  6696.                  (t (concat "\"" x-status "\""))))
  6697.          (vchnl (irc-format-channel
  6698.              (cond ((string= "-1" channel) "-")
  6699.                    ((string= "0" channel) "")
  6700.                    ((string= "*" channel) "")
  6701.                    (t channel))))
  6702.          (vusr (irc-clean-up-message x-login-name))
  6703.          (vclt (irc-clean-up-message x-client-host))
  6704.          (vsrv (irc-clean-up-message x-server-host))
  6705.           (line (format "%s%s %s %s <%s> %s@%s \"%s\" SERVER=%s"
  6706.                    x-nickname nick-pad vsts vchnl hop-count vusr
  6707.                    vclt full-name vsrv))
  6708.           (line (format "%s%s %s %s %s@%s \"%s\""
  6709.                    x-nickname nick-pad vsts vchnl vusr
  6710.                    vclt full-name))
  6711. ;         (line (format "%s%s %s %s@%s \"%s\""
  6712. ;                   x-nickname nick-pad vsts vusr vclt full-name))
  6713.          (irc-msg-cont-used (make-string 31 ? )))
  6714.         (if (and (irc-terminal-is-slow) (irc-server-has-end-of-who))
  6715.         (if (not is-header)
  6716.             (progn
  6717.               (setq irc-reply-count (1+ irc-reply-count))
  6718.               (let ((diff (irc-time-diff (irc-current-time)
  6719.                          irc-reply-count-time)))
  6720.             (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since
  6721.                    (> (nth 0 diff) 0)) ; last display?
  6722.                    (setq irc-reply-count-time (irc-current-time))
  6723.                    (message (format " %d nick%s ..."
  6724.                         irc-reply-count
  6725.                         (if (= 1 irc-reply-count)
  6726.                             ""
  6727.                             "s"))))))
  6728.               (irc-remember line 'irc-whotree)))
  6729.         (if is-header        ;No RPL_ENDOFWHO
  6730.             (let ((irc-msg-cont-used
  6731.                (make-string (string-match "-* *$" irc-who-stroke)
  6732.                     ? )))
  6733.               (irc-insert irc-who-header)
  6734.               (irc-insert irc-who-stroke))
  6735.             (irc-insert "%s" (irc-clean-up-message line))))))
  6736.     (irc-insert "%%Unkown WHOREPLY line: \"%s\"." str)))
  6737.     nil)
  6738.  
  6739.  
  6740. (defun irc-explain-channel-mode (mode &optional skip-direction)
  6741.   "Front end to irc-explain-mode."
  6742.   (irc-explain-mode mode 'channel skip-direction))
  6743.  
  6744.  
  6745. (defun irc-explain-user-mode (mode &optional skip-direction)
  6746.   "Front end to irc-explain-mode."
  6747.   (irc-explain-mode mode 'user skip-direction))
  6748.   
  6749.  
  6750. (defun irc-explain-mode (mode type &optional skip-direction)
  6751.   "Translate a channels MODE code into plain text. Use optional FLAG when
  6752. addition / removal information shouldn't be added."
  6753.   (let* ((known-modes '(((?a 0 "anonymous <A>")
  6754.              (?b 1 "ban (from channel) <B>" " of " " of ")
  6755.              (?i 0 "invite only <I>")
  6756.              (?k 1 "channel key <K> ")
  6757.              (?l 1 "limit number of users on channel <L>" " to ")
  6758.              (?m 0 "moderated <M>")
  6759.              (?n 0 "disallow nonlisteners to talk to channel <N>")
  6760.              (?o 1 "channel operator privilege <O>"
  6761.                    " for " " for ")
  6762.              (?p 0 "private <P>")
  6763.              (?s 0 "secret <S>")
  6764.              (?t 0 "topic lock <T>")
  6765.              (?v 1 "voice capability <V>" " to " " to "))
  6766.             .
  6767.             ((?i 0 "invisibility <I>")
  6768.              (?o 0 "IRC-operator <O>")
  6769.              (?s 0
  6770.               "subscription to local server status messages <S>")
  6771.              (?w 0 "subscription to WALLOPS <W>"))))
  6772.      (modes (cond ((eq type 'channel) (car known-modes))
  6773.               ((eq type 'user) (cdr known-modes))
  6774.               (t nil)))
  6775.      (cmds (if (string-match " +" mode) 
  6776.            (substring mode 0 (match-beginning 0))
  6777.            mode))
  6778.      (args (substring mode (length cmds)))
  6779.      (dir "added ")
  6780.      (argl ())
  6781.      (expl ""))
  6782.     (while (string-match "^ *\\([^: ]+\\)" args)
  6783.       (setq argl (append argl (list (subfield args 1)))
  6784.         args (substring args (match-end 1))))
  6785.     (while (not (string= cmds ""))
  6786.       (let ((c (string-to-char (substring cmds 0 1))))
  6787.     (cond ((= ?+ c) (setq dir "added "))
  6788.           ((= ?- c) (setq dir "removed "))
  6789.           (t (let ((p (assoc c modes)))
  6790.            (setq expl (concat expl
  6791.                       ", "
  6792.                       (if (not skip-direction) dir)
  6793.                       (if p
  6794.                       (nth 2 p)
  6795.                       (concat irc-msg-info-pre
  6796.                           "UNKNOWN '"
  6797.                           (char-to-string c)
  6798.                           "'"
  6799.                           irc-msg-info-post))
  6800.                       (cond ((and (string= dir "added ")
  6801.                           (nth 3 p))
  6802.                          (nth 3 p))
  6803.                         ((and (string= dir "removed ")
  6804.                           (nth 4 p))
  6805.                          (nth 4 p))
  6806.                         (t ""))
  6807.                       (let ((n (or (nth 1 p) 0))
  6808.                         (s ""))
  6809.                     (while (and (> n 0) (car argl))
  6810.                       (setq s (concat s (car argl))
  6811.                         argl (cdr argl)
  6812.                         n (1- n)))
  6813.                     s)))))))
  6814.       (setq cmds (substring cmds 1)))
  6815.     (concat (cond ((string-match "^\\(, *\\)[\000-\377]*\\(,\\) [^,]+" expl)
  6816.            (concat (substring expl (match-end 1) (match-beginning 2))
  6817.                " and"
  6818.                (substring expl (match-end 2))))
  6819.           ((string-match "^\\(, *\\)" expl)
  6820.            (substring expl (match-end 1)))
  6821.           ((string= expl "") (if skip-direction "normal" "none"))
  6822.           (t expl))
  6823.         (if (and (= (length argl) 1)
  6824.              (string-match "^[0-9]+$" (car argl)))
  6825.         (concat "; user limit is " (car argl))
  6826.         (progn (if (not (equal argl ()))
  6827.                (progn (irc-insert (concat "%%Warning: parts left"
  6828.                               " unparsed in function"
  6829.                               " irc-explain-mode."))
  6830.                   (irc-insert "%% \"%s\" (mode)." mode)
  6831.                   (irc-insert (concat "%% Please tell %s, it"
  6832.                               " might be a bug.")
  6833.                           irc-hacker))
  6834.                ""))))))
  6835.  
  6836. ;;;(defun irc-explain-who-mode (mode)
  6837. ;;;  ""
  6838. ;;;   (cond ((irc-recall x-nickname 'irc-ignored-ppl) "IGNR")
  6839. ;;;                 ((string= "H"   mode) "    ") ;Norm
  6840. ;;;                 ((string= "G"   mode) "Away") ;Away
  6841. ;;;                 ((string= "H*"  mode) "Iopr") ;Iopr
  6842. ;;;                 ((string= "G*"  mode) "IoAw") ;IoAw
  6843. ;;;                 ((string= "H@"  mode) "Copr") ;Copr
  6844. ;;;                 ((string= "G@"  mode) "CoAw") ;CoAw
  6845. ;;;                 ((string= "H*@" mode) "ICop") ;ICop
  6846. ;;;                 ((string= "G*@" mode) "ICAw") ;ICAw
  6847. ;;;                 ((string= "S"   mode) "    ") ;Norm
  6848. ;;;                 (t (concat "\"" mode "\""))))
  6849.  
  6850. (defun irc-ctcp-dequote (str)
  6851.   "Return STRING with quoted characters changed into the unquoted equivalents."
  6852.   (let ((new ""))
  6853.     (while (string-match "\\\\" str)    ;Get to next backslash, if any
  6854.       (let ((pos (match-beginning 0)))
  6855.     (if (>= (- (length str) pos) 2)
  6856.         (setq new (concat new
  6857.                   (substring str 0 pos)
  6858.                   (irc-ctcp-dequote-char (aref str (1+ pos))))
  6859.           str (substring str (+ 2 pos)))
  6860.         (irc-insert (concat "%%Received badly quoted CTCP string, ignored"
  6861.                 " superfluous backslash."))
  6862.         (setq new (concat new (substring str 0 pos))
  6863.           str (substring str (1+ pos))))))
  6864.     (concat new str)))
  6865.  
  6866.  
  6867. (defun irc-ctcp-dequote-char (char)
  6868.   "Map a two character STRING to it's corresponding character."
  6869.   (char-to-string (cond ((= char ?a) ?\001)
  6870.             ((= char ?\\) ?\\)
  6871.             (t char))))
  6872.  
  6873.  
  6874. (defun irc-ctcp-enquote (str)
  6875.   "Enquote a STRING, exchanging some characters to two character combinations."
  6876.   (let ((d "")
  6877.     (dirty "[\001\\]"))
  6878.     (while (string-match dirty str)
  6879.       (setq d (concat d
  6880.               (substring str 0 (match-beginning 0))
  6881.               (irc-ctcp-enquote-char (aref str (match-beginning 0))))
  6882.         str (substring str (match-end 0))))
  6883.     (concat d str)))
  6884.  
  6885.  
  6886. (defun irc-ctcp-enquote-char (char)
  6887.   "Map a character to it's corresponding one or two character STRING."
  6888.   (cond ((= char ?\001) "\\a")
  6889.     ((= char ?\\) "\\\\")
  6890.     (t (char-to-string char))))
  6891.  
  6892.  
  6893. (defun irc-lowlevel-dequote (str)
  6894.   "Return STRING with quoted characters changed into the unquoted equivalents."
  6895.   (let ((new ""))
  6896.     (while (string-match "\020" str)
  6897.       (let ((pos (match-beginning 0)))
  6898.     (if (< pos (1- (length str)))
  6899.         (setq new (concat new
  6900.                   (substring str 0 pos)
  6901.                   (irc-lowlevel-dequote-char (aref str (1+ pos))))
  6902.           str (substring str (+ 2 pos)))
  6903.         (setq new (concat new
  6904.                   (substring str 0 pos)
  6905.                   "<<ERROR in senders client: unquoted CNTRL/P>>")
  6906.           str "")
  6907.         )))
  6908.     (concat new str)))
  6909.  
  6910.  
  6911. (defun irc-lowlevel-dequote-char (char)
  6912.   "Map the CHARACTER after a \020 to it's corresponding character."
  6913.   (char-to-string (cond ((= char ?0) ?\000)
  6914.             ((= char ?n) ?\n)
  6915.             ((= char ?r) ?\r)
  6916.             ((= char ?\020) ?\020)
  6917.             (t char))))
  6918.  
  6919.  
  6920. (defun irc-lowlevel-enquote (str)
  6921.   "Enquote a STRING, exchanging some characters to two character combinations."
  6922.   (let ((d "")
  6923.     (dirty "[\000\n\r\020]"))
  6924.     (while (string-match dirty str)
  6925.       (setq d (concat
  6926.            d
  6927.            (substring str 0 (match-beginning 0))
  6928.            (irc-lowlevel-enquote-char (aref str (match-beginning 0))))
  6929.         str (substring str (match-end 0))))
  6930.     (concat d str)))
  6931.  
  6932.  
  6933. (defun irc-lowlevel-enquote-char (char)
  6934.   "Map a character to it's corresponding one or two character STRING."
  6935.   (cond ((= char ?\000) "\0200")
  6936.     ((= char ?\n) "\020n")
  6937.     ((= char ?\r) "\020r")
  6938.     ((= char ?\020) "\020\020")
  6939.     (t (char-to-string char))))
  6940.  
  6941.  
  6942. (defun irc-show-subscribed-channels ()
  6943.   "Show which channel's user is listening to, and which one is talked to."
  6944.   (if (not irc-multiple-leave-in-progress)
  6945.       (let ((listen (irc-clean-up-message
  6946.              (irc-listify
  6947.               (irc-recall-all 'irc-subscribed-channels)
  6948.               ", "
  6949.               "and"))))
  6950.     (cond ((irc-nothing-remembered-p 'irc-subscribed-channels)
  6951.            (cond ((string= "0" irc-channel)
  6952.               (irc-insert (concat "%sYou're neither listening nor"
  6953.                       " talking to any channel%s")
  6954.                   irc-msg-info-pre
  6955.                   irc-msg-info-post))
  6956.              (t (irc-insert (concat "%sYou're now talking and"
  6957.                         " listening to channel %s%s")
  6958.                     irc-msg-info-pre
  6959.                     irc-channel
  6960.                     irc-msg-info-post))))
  6961.           ((string= "0" irc-channel)
  6962.            (irc-insert (concat "%sYou're not talking to any channel, but"
  6963.                    " listening to %s%s")
  6964.                irc-msg-info-pre
  6965.                listen
  6966.                irc-msg-info-post))
  6967.           (t (let* ((part-1 (format "%sYou are now talking to channel "
  6968.                     irc-msg-info-pre))
  6969.             (irc-msg-cont-used (make-string (length part-1) ? )))
  6970.            (irc-insert "%s%s, while listening to %s%s"
  6971.                    part-1
  6972.                    irc-channel
  6973.                    listen
  6974.                    irc-msg-info-post)))))
  6975.       (set-buffer-modified-p (buffer-modified-p)))
  6976.   nil)
  6977.  
  6978.  
  6979. (defun irc-server-has-end-of-who ()
  6980.   "True if the current server end WHOREPLY with a \"end of list\" message."
  6981.   (or (> irc-major-version 2)
  6982.       (and (= irc-major-version 2)
  6983.        (>= irc-minor-version 4))))
  6984.  
  6985.  
  6986. (defun irc-server-has-end-of-names ()
  6987.   "True if the current server end NAMREPLY with a \"end of list\" message."
  6988.   (or (> irc-major-version 2)
  6989.       (and (= irc-major-version 2)
  6990.        (>= irc-minor-version 4))))
  6991.  
  6992.  
  6993. (defun irc-server-has-end-of-links ()
  6994.   "True if the current server end LINREPLY with a \"end of list\" message."
  6995.   (or (> irc-major-version 2)
  6996.       (and (= irc-major-version 2)
  6997.        (>= irc-minor-version 4))))
  6998.  
  6999.  
  7000. (defun irc-server-has-non-numeric-channel-names ()
  7001.   "True if the current server supports non nummeric IDs for channels."
  7002.   (or (> irc-major-version 2)
  7003.       (and (= irc-major-version 2)
  7004.        (or (> irc-minor-version 4)
  7005.            (and (= irc-minor-version 4)
  7006.             (>= irc-edit-version 2))))))
  7007.  
  7008.  
  7009. (defun irc-server-has-multijoinable-channels ()
  7010.   "True if the current server supports #-type channels and the commands JOIN
  7011. and PART. Probaly v2.6 or later."
  7012.   (or (> irc-major-version 2)
  7013.       (and (= irc-major-version 2)
  7014.        (>= irc-minor-version 6))))
  7015.  
  7016.  
  7017. (defun irc-server-has-channelname-in-msgs ()
  7018.   "True if the server gives the channels name in a RPL_CHANNELMODEIS message."
  7019.   (or (> irc-major-version 2)
  7020.       (and (>= irc-major-version 2)
  7021.        (or (> irc-minor-version 6)
  7022.            (and (>= irc-minor-version 6)
  7023.             (>= irc-edit-version 19))))))
  7024.  
  7025.  
  7026. (defun irc-server-has-end-of-whois ()
  7027.   "True if the server ends WHOIS replies with an enad marker."
  7028.   (or (> irc-major-version 2)
  7029.       (and (>= irc-major-version 2)
  7030.        (or (> irc-minor-version 6)
  7031.            (and (>= irc-minor-version 6)
  7032.             (>= irc-edit-version 20))))))
  7033.  
  7034.  
  7035. (defun irc-server-has-settable-topic-on-multijoinable-channel ()
  7036.   "True if the server supports setting topic for a multijoinable channel."
  7037.   (or (> irc-major-version 2)
  7038.       (and (>= irc-major-version 2)
  7039.        (>= irc-minor-version 7))))
  7040.  
  7041.  
  7042. (defun irc-active-servers ()
  7043.   "Return list of active IRC processes."
  7044.   (let ((lst (if (boundp 'irc-processes) irc-processes))
  7045.     (act nil))
  7046.     (while (consp lst)
  7047.       (if (and (memq (process-status (car lst)) '(open run))
  7048.            (stringp (buffer-name (process-buffer (car lst)))))
  7049.       (setq act (cons (car lst) act)))
  7050.       (setq lst (cdr lst)))
  7051.     (reverse act)))
  7052.  
  7053.  
  7054. (defun irc-host+port-to-buffer-name (host-name port-number)
  7055.   "Return a legal buffer name for a Kiwi session."
  7056.   (cond ((or (not (numberp port-number))
  7057.          (> 0 port-number)
  7058.          (> port-number 65535))
  7059.      (error (format "Kiwi: \"%s\" illegal TCP-port number" port-number)))
  7060.     (t (format "*Kiwi-%s/%d*" host-name port-number))))
  7061.  
  7062.  
  7063. (defun irc-host+port-to-buffer (host-name port-number)
  7064.   "Return the buffer a HOST-NAME in a Kiwi session is associated with.
  7065. If no such buffer exist, create it.
  7066.  
  7067. See also: irc-host-to-buffer-name <f>"
  7068.   (get-buffer-create (irc-host+port-to-buffer-name host-name port-number)))
  7069.  
  7070.  
  7071. (defun irc-session-to-buffer (session)
  7072.   "Convert a Kiwi SESSION (ie host name) to its associated buffer.
  7073. The buffer must exist."
  7074.   (get-buffer session))
  7075.  
  7076.  
  7077. (defun irc-session-names (proc-list)
  7078.   "Convert a LIST of Kiwi processes to a list of the processes host names."
  7079.   (mapcar (function (lambda (p)
  7080.          (buffer-name (process-buffer p))))
  7081.       proc-list))
  7082.  
  7083.  
  7084. (defun irc-get-host-from-session-name (session-name)
  7085.   "Extract the host name associated with a SESSION-NAME."
  7086.   (if (string-match irc-legal-session-name session-name)
  7087.       (subfield session-name 1)
  7088.       (error (format "Illegal session-name: \"%s\"." session-name))))
  7089.  
  7090.  
  7091. (defun irc-get-port-from-session-name (session-name)
  7092.   "Extract the TCP/IP port number associated with a SESSION-NAME."
  7093.   (if (string-match irc-legal-session-name session-name)
  7094.       (string-to-int (subfield session-name 2))
  7095.       (error (format "Illegal session-name: \"%s\"." session-name))))
  7096.  
  7097.  
  7098. (defun irc-terminal-is-slow ()
  7099.   "True if the terminal's speed (baud-rate) is lower than the variable
  7100. \"search-slow-speed\" (the variable is defined in either file loaddefs.el or
  7101. isearch.el in the lisp subdirectory)."
  7102.   (if (not (boundp 'search-slow-speed))    ;This should never happen.
  7103.       (progn (load "loaddefs"))
  7104.       (if (not (boundp 'search-slow-speed))
  7105.       (load "isearch"))
  7106.       (if (not (boundp 'search-slow-speed))
  7107.       (setq search-slow-speed 1200)))
  7108. ;;;  (if (boundp 'baud-rate)
  7109. ;;;      (<= baud-rate search-slow-speed)
  7110. ;;;    (<= (baud-rate) search-slow-speed))
  7111.   t)                    ;Patched.
  7112.  
  7113.  
  7114. (defun irc-non-num-to-0 (x)
  7115.   (if (numberp x)
  7116.       x
  7117.       0))
  7118.  
  7119.  
  7120. (defun irc-pong (&optional line)
  7121.   "Send a PONG message with the hostname as an argument.
  7122. This is usually used to answer a PING message."
  7123.   ;; it's interactive so it can be bound during testing.
  7124.   (interactive)
  7125.   (cond ((string-match "^PING +: *\\([0-9]+\\)$" line)
  7126.      (irc-send (concat "PONG :" (subfield line 1))))
  7127.     (t (irc-send (concat "PONG :" (system-name)))))
  7128.   (irc-who-is-on)
  7129.   nil)
  7130.  
  7131.  
  7132. (defun irc-new-scroll-step (scroll-step)
  7133.   "Calculate a new scroll-step value based on the current windows height
  7134. if terminal is slow (see function irc-terminal-is-slow)."
  7135.   (cond ((and (boundp 'irc-scroll-step)
  7136.           (numberp irc-scroll-step))
  7137.      irc-scroll-step)
  7138.     ((irc-terminal-is-slow)
  7139.      (let* ((h (- (window-height) 3))
  7140.         (x (- h (/ h 6))))
  7141.        (if (> window-min-height x)
  7142.            1
  7143.            (if (> (* 2 window-min-height) x)
  7144.            (/ x 2)
  7145.            x))))
  7146.     (t scroll-step)))        ;Else use old value.
  7147.  
  7148.  
  7149. (defun irc-last-found (str left-most char)
  7150.   "Search in STRING, position LEFT-MOST to end of string, for a CHARacter.
  7151. Return its position, or nil if not found."
  7152.   (let* ((n (length str))
  7153.      (m (while (and (>= n left-most)
  7154.             (not (= char (string-to-char (substring str n nil)))))
  7155.           (setq n (1- n)))))
  7156.     (if (>= n left-most) (1+ n) nil)))
  7157.  
  7158.  
  7159. (defun irc-choose-break-point (str left-most right-most delimiters)
  7160.   "Choose a nice point to break a string in. Break at a delimiting
  7161. character like space, bang or comma. Return a list of two strings,
  7162. the part before and the part after the breakpoint."
  7163.   (cond
  7164.     ((string-match "\n" str)
  7165.      (irc-split-string str (string-match "\n" str)))
  7166.     ((< (length str) right-most)
  7167.      (irc-split-string str (length str)))
  7168.     (t (let ((s (substring str 0 (1- right-most))))
  7169.      (if (or (null delimiters)
  7170.          (<= (min left-most (length str))
  7171.              0))
  7172.          (irc-split-string str (1- right-most))
  7173.          (let ((possible (irc-last-found s left-most (car delimiters))))
  7174.            (if possible
  7175.            (irc-split-string str possible)
  7176.            (irc-choose-break-point str
  7177.                        left-most
  7178.                        right-most
  7179.                        (cdr delimiters)))))))))
  7180.  
  7181.  
  7182. (defun irc-split-string (str n)
  7183.   "Split string STR into two at position N, trimming all white space
  7184. around the split point."
  7185.   (let* ((x (min n (length str)))
  7186.      (first-half (substring str 0 x))
  7187.      (second-half (substring str x))
  7188.      (a (progn (string-match "[\n\t ]*$" first-half)
  7189.            (match-beginning 0)))
  7190.      (b (progn (string-match "^[\n\t ]*" second-half)
  7191.            (match-end 0))))
  7192.     (cons (substring first-half 0 a)
  7193.       (substring second-half (match-end 0)))))
  7194.  
  7195.  
  7196. (defun irc-insert (format &rest args)
  7197.   "Insert before irc-mark the string created by FORMAT with substituted ARGS.
  7198. Resets the global variable \"scroll-step\" each time. If the string is to long
  7199. to be inserted on one line, insert just first part and give the rest to
  7200. \"irc-insert-more\"."
  7201.   (setq scroll-step (irc-new-scroll-step scroll-step))
  7202.   (let* ((str (apply 'format format args))
  7203.      (strlen (length str))
  7204.      (left-most (* (/ (window-width (get-buffer-window (current-buffer)))
  7205.               3)
  7206.                2))
  7207.      (splitted (irc-choose-break-point
  7208.             str
  7209.             left-most
  7210.             (window-width (get-buffer-window (current-buffer)))
  7211.             '(?, ?  ?\050 ?! ?? ?. ?\051)))
  7212.      (first-half (car splitted))
  7213.      (second-half (cdr splitted)))
  7214.     (save-excursion
  7215.       (goto-char (if (and (boundp 'irc-mark) (markerp irc-mark))
  7216.              irc-mark
  7217.              (point-max)))
  7218.       (insert-before-markers first-half "\n")
  7219.       (if (not (string= "" second-half))
  7220.       (irc-insert-more irc-msg-cont-used left-most second-half)))))
  7221.  
  7222.  
  7223. (defun irc-insert-more (continue left-most str)
  7224.   "Insert before irc-mark the line created by concatenating the CONTINUE string
  7225. and the MESSAGE string. If the line is to long, insert the first part and 
  7226. recurse with the rest."
  7227.   (let* ((cont (substring continue 0 (min (/ (* 3 (window-width
  7228.                            (get-buffer-window
  7229.                             (current-buffer))))
  7230.                          4)
  7231.                       (length continue))))
  7232.      (splitted (irc-choose-break-point str ;;QUICK ugly bug fix.... bleah!
  7233.                        (max 0 (- left-most (length cont)))
  7234.                        (- (window-width (get-buffer-window
  7235.                                  (current-buffer)))
  7236.                           (length cont))
  7237.                        '(?, ?  ?\( ?! ?? ?. ?;)))
  7238.      (first-half (concat cont (car splitted)))
  7239.      (second-half (cdr splitted)))
  7240.     (insert-before-markers first-half "\n")
  7241.     (if (not (string= "" second-half))
  7242.     (irc-insert-more cont left-most second-half))))
  7243.  
  7244.  
  7245. (defun irc-fix-wordwrap (line1 line2)
  7246.   "With arguments LINE1 and LINE2 apply some simple heuristics to see if the
  7247. line which they originally formed was broken in an acceptable place.  Returns
  7248. a dotted pair with LINE1 as the car and LINE2 as the cdr."
  7249.   (cond ((string-match "^ +" line2)
  7250.          ;; broke at whitespace; strip leading space from next line
  7251.          (setq line2 (substring line2 1)))
  7252.         ((string-match " +$" line1)
  7253.          ;; trailing whitespace on line.  might as well just nuke it all.
  7254.          (setq line1 (substring line1 0 (match-beginning 0))))
  7255.         ((string-match "\\( +\\)[^: ]+$" line1)
  7256.          ;; broke in a word, but it's wrappable.  just eat one space.
  7257.          (setq line2 (concat (substring line1 (1+ (match-beginning 1))) line2)
  7258.                line1 (substring line1 0 (match-beginning 0)))))
  7259.   (cons line1 line2))
  7260.  
  7261.  
  7262.  
  7263. ;; simple key functions -- self-insert, tab, destructive backspace
  7264. (defun irc-self-insert (arg)
  7265.   "Normaly just inserts the typed character in the input region.
  7266. If point is in the output region, irc-spacebar-pages is non-nil and a space
  7267. is typed, scroll-up otherwise point moves to end of input region and inserts
  7268. the character.
  7269.  
  7270. If the character to be inserted is a colon or semi-colon and it is the first
  7271. non-white space character on the line then the input region is updated to
  7272. begin with the last explicit sendlist, irc-last-explicit.
  7273.  
  7274. Inserts the character ARG times if self-inserting.  An argument is not
  7275. passed to scroll-up if paging with the spacebar."
  7276.   (interactive "p")
  7277.   (let* ((in-region (>= (point) irc-mark))
  7278.      (mapped (assoc last-command-char
  7279.             '((?\100 . ?\311)
  7280.               (?\133 . ?\304)
  7281.               (?\134 . ?\326)
  7282.               (?\135 . ?\305)
  7283.               (?\136 . ?\334)
  7284.               (?\140 . ?\351)
  7285.               (?\173 . ?\344)
  7286.               (?\174 . ?\366)
  7287.               (?\175 . ?\345)
  7288.               (?\176 . ?\374))))
  7289.      (invmapped (assoc last-command-char
  7290.                '((?\100 . ?\311)
  7291.                  (?\133 . ?\344)
  7292.                  (?\134 . ?\366)
  7293.                  (?\135 . ?\345)
  7294.                  (?\136 . ?\334)
  7295.                  (?\140 . ?\351)
  7296.                  (?\173 . ?\304)
  7297.                  (?\174 . ?\326)
  7298.                  (?\175 . ?\305)
  7299.                  (?\176 . ?\374))))
  7300.      (chr (if (and irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1
  7301.                mapped)
  7302.           (cdr (if (eq t irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1)
  7303.                mapped
  7304.              invmapped))
  7305.           last-command-char))
  7306.          ;; it's times like this that i wish someone would tell me what
  7307.          ;; a good indentation style is for this expression
  7308.          (expand-colon
  7309.           (and
  7310.        (or (= last-command-char ?\;) (= last-command-char ?:))
  7311.            (string-match "^ *$"
  7312.              (buffer-substring
  7313.               irc-mark
  7314.               (if in-region (point) (point-max)))))))
  7315.     (if (not expand-colon)
  7316.         (if in-region
  7317.         (while (> arg 0)
  7318.           (insert chr)
  7319.           (setq arg (1- arg)))
  7320.         ;; else
  7321.         (if (and irc-spacebar-pages
  7322.              (= last-command-char 32))
  7323.         ;; it's nice to be able to return to the input region just by
  7324.         ;; pounding on the spacebar repeatedly.
  7325.         (condition-case EOB (scroll-up nil)
  7326.           (end-of-buffer (goto-char (point-max))))
  7327.         (goto-char (point-max))
  7328.         (while (> arg 0)
  7329.           (insert chr)
  7330.           (setq arg (1- arg)))))
  7331.     (or in-region (goto-char (point-max)))
  7332.     ;; Kill white space. This also takes out previous lines in
  7333.     ;; input region.
  7334.     (delete-region irc-mark (point))
  7335.     (insert (if (= last-command-char ?:) irc-last-private irc-last-explicit))
  7336.     ;; put in the extra characters if need be.
  7337.     (setq arg (1- arg))
  7338.     (while (> arg 0)
  7339.       (insert chr)
  7340.       (setq arg (1- arg))))))
  7341.  
  7342.  
  7343. (defun irc-del-backward-char (arg)
  7344.   "If in the input region, delete ARG characters before point, restricting
  7345. deletion to the input region.  If in the output region and irc-spacebar-pages
  7346. then scroll-down (aka window-back) otherwise do nothing."
  7347.   (interactive "p")
  7348.   (if (> (point) irc-mark)
  7349.       ;; only delete as far back as irc-mark at most
  7350.       (if (> arg (- (point) irc-mark)) (delete-region (point) irc-mark)
  7351.       (delete-backward-char arg))
  7352.       (if (and (<= (point) irc-mark) irc-spacebar-pages) (scroll-down nil)
  7353.       (ding))))
  7354.  
  7355.  
  7356. (defun irc-tab ()
  7357.   "If point is in the input region then tab-to-tab-stop.  If it is in the
  7358. output region, go to the previous line if irc-spacebar-pages; do nothing
  7359. otherwise."
  7360.   (interactive)
  7361.   (if (>= (point) irc-mark) (tab-to-tab-stop)
  7362.       (if irc-spacebar-pages (previous-line 1)
  7363.       (ding))))
  7364.  
  7365.  
  7366.  
  7367. ;; top-level -- entry, sentinel and mode
  7368. (defun irc (&optional universal-argument)
  7369.   "Enter the Internet Relay Chat conferencing system.
  7370. If no connexion to an irc-server is open, then one is started.  If no buffer
  7371. *IRC* exists then it is created otherwise the existing buffer is used.  If
  7372. a connexion is already active then the most recently started IRC session
  7373. is switched to in the current window.  This makes binding 'irc' to a key
  7374. much more convenient.
  7375.  
  7376. With prefix argument NEW-BUFFER, another *IRC* buffer is created and a
  7377. new IRC session is started.  This is provided so that multiple IRC
  7378. sessions can co-exist in one Emacs, which is sometimes a useful thing."
  7379.   (interactive "P")
  7380.   (load "w3" 'noerr)
  7381.   (let* ((act (irc-active-servers))
  7382.      (session-names (irc-session-names act))
  7383.      (number-of-sessions (length session-names))
  7384.      (ask-for-session (> number-of-sessions 1))
  7385.      (session (let ((s (if ask-for-session
  7386.                    (irc-nuke-whitespace
  7387.                 (irc-read-object
  7388.                  "Select which Kiwi session? (RET for new) "
  7389.                  ""
  7390.                  session-names))
  7391.                    "")))
  7392.             (if (or (irc-member-general s
  7393.                         session-names
  7394.                         'string=)
  7395.                 (string= "" s))
  7396.             s
  7397.             (error (format "No such active session: %s" s)))))
  7398.      (ask-for-host (or universal-argument
  7399.                (= 0 number-of-sessions)
  7400.                (and ask-for-session
  7401.                 (string= "" session))))
  7402.      (host (downcase
  7403.         (cond
  7404.           (ask-for-host
  7405.            (let ((h (irc-nuke-whitespace
  7406.                  (read-string
  7407.                   (concat "Connect new Kiwi session to which"
  7408.                       " internet host? (RET for "
  7409.                       irc-server
  7410.                       ") ")))))
  7411.              (if (string= "" h) irc-server h)))
  7412.           (ask-for-session
  7413.            (irc-get-host-from-session-name session))
  7414.           ((= 1 number-of-sessions)
  7415.            (irc-get-host-from-session-name (car session-names)))
  7416.           (t ""))))
  7417.      (port (cond
  7418.          (ask-for-host
  7419.           (let* ((p (irc-nuke-whitespace
  7420.                  (read-string
  7421.                   (concat "Use which TCP port for new connection?"
  7422.                       " (RET for "
  7423.                       (int-to-string irc-port)
  7424.                       ", * for 194) "))))
  7425.              (n (string-to-int p)))
  7426.             (cond ((string= "*" p) 194)
  7427.               ((string= "" p) irc-port)
  7428.               ((and (> n 0) (> 65535 n)) n)
  7429.               (t (error "Illegal TCP port")))))
  7430.          (ask-for-session
  7431.           (irc-get-port-from-session-name session))
  7432.          ((= 1 number-of-sessions)
  7433.           (irc-get-port-from-session-name (car session-names)))
  7434.          (t nil)))
  7435.      (buffer (irc-host+port-to-buffer host port)))
  7436.     (make-variable-buffer-local 'irc-port)
  7437.     (setq irc-port port)
  7438.     (switch-to-buffer buffer)
  7439.     (if (not (get-buffer-process (current-buffer)))
  7440.     (progn
  7441.       (goto-char (point-max))
  7442.       (irc-mode)
  7443.       (irc-insert "")
  7444.       (irc-insert "")
  7445.       (irc-insert "%s for GNU Emacs v18.57 and around...." irc-version)
  7446.       (irc-insert "Comments to %s." irc-hacker)
  7447.       (irc-insert "")
  7448.       (condition-case NOT-IRCED
  7449.           (let ((proc (open-network-stream
  7450.                "irc" buffer host port)))
  7451.         (set-process-filter proc 'irc-filter)
  7452.         (set-process-sentinel proc 'irc-sentinel)
  7453.         (setq irc-server host)
  7454.         (setq-default irc-server host)
  7455.         (irc-send (concat "NICK " irc-nick))
  7456.         (irc-send (format "USER %s %s %s :%s"
  7457.                   (user-login-name)
  7458.                   (system-name)
  7459.                   irc-server
  7460.                   (or (getenv "IRCNAME")
  7461.                       (getenv "NAME")
  7462.                       (user-full-name)
  7463.                       "<<USERNAME UNKNOWN>>")))
  7464.         ;; a new process, so initialize the variables.  they aren't set
  7465.         ;; in irc-mode so that irc-mode can be called at any time.
  7466.         ;; (irc-remember irc-nick 'irc-nicknames)
  7467.         (let ((s (irc-recall-all 'irc-services)))
  7468.           (while (and (listp s) s)
  7469.             (irc-remember (car s) 'irc-nicknames)
  7470.             (setq s (cdr s))))
  7471.         (irc-remember irc-server 'irc-servernames)
  7472.         (setq irc-nick-used ".Not.connected.yet."
  7473.               irc-major-version 0
  7474.               irc-minor-version 0
  7475.               irc-edit-version 0
  7476.               irc-motd-lines nil
  7477.               irc-list-stats '(0 0)
  7478.               irc-away nil
  7479.               irc-channel "0"
  7480.               irc-history-index -1
  7481.               irc-operator nil
  7482.               irc-scratch ""
  7483.               irc-last-command  ""
  7484.               irc-last-explicit "*;"
  7485.               irc-last-private "*;"
  7486.               irc-last-time (irc-get-time)
  7487.               ;; this next bit of messiness just ups irc-last-stamp
  7488.               ;; in an effort to make nice numbers out of the time
  7489.               ;; stamps -- ie, if the time is now 13:53 with an
  7490.               ;; interval of 15 minutes, this makes it 13:45
  7491.               irc-last-stamp 0
  7492.               irc-total-time (string-to-int
  7493.                       (substring irc-last-time 3))
  7494.               irc-last-stamp (if (zerop irc-time-stamp)
  7495.                      0
  7496.                      (while (< (+ irc-last-stamp
  7497.                               irc-time-stamp)
  7498.                            irc-total-time)
  7499.                        (setq irc-last-stamp
  7500.                          (+ irc-last-stamp
  7501.                             irc-time-stamp)))
  7502.                      irc-last-stamp)
  7503.               irc-last-notify irc-last-stamp
  7504.               irc-processes (cons proc irc-processes))
  7505.         (irc-send "CLIENT-START"))
  7506.         (error
  7507.          (irc-insert (concat "%%Couldn't connect to the TCP/IP"
  7508.                  " port %s at the internet host %s --"
  7509.                  " sorry: %s")
  7510.              port
  7511.              host
  7512.              NOT-IRCED)
  7513.          ))))))
  7514.  
  7515.  
  7516. (defun irc-mode ()
  7517.   "To understand some documentation given with irc-mode variables and
  7518. functions, \"output region\" is defined as everything before the irc-mark.
  7519. irc-mark is a marker kept by irc-mode to know where to insert new text
  7520. from IRC.  Text in the output region cannot be modified by the most common
  7521. methods of typing a self-inserting character or pressing delete.
  7522.  
  7523. The input region is everything which follows irc-mark.  It is what
  7524. gets processed by irc-mode when you type LFD or RET.  If irc-spacebar-pages
  7525. is non-nil, the following keys are in effect when the cursor is in the
  7526. output region:
  7527.  
  7528. SPC             scroll-forward       DEL     scroll-backward
  7529. LFD or RET      next-line            TAB     previous-line
  7530.  
  7531. Local keys:
  7532. \\{irc-mode-map}"
  7533.   (interactive)
  7534.   (setq buffer-offer-save t)
  7535.   (kill-all-local-variables)
  7536.   (setq major-mode 'irc-mode
  7537.     mode-name "Kiwi"
  7538.     fill-column (- (window-width (get-buffer-window (current-buffer))) 5))
  7539.   (set (make-local-variable 'irc-away) nil) ; for the mode-line
  7540.   (set (make-local-variable 'irc-channel) nil) ; for sendlists and broken PRIVMSGs
  7541.   (set (make-local-variable 'irc-edit-version) nil) ; edit version number of server
  7542.   (set (make-local-variable 'irc-history-index) nil) ; for the message history
  7543.   (set (make-local-variable 'irc-last-command) nil) ; for the command history
  7544.   (set (make-local-variable 'irc-last-explicit) nil) ; for sendlist ; auto-expansion
  7545.   (set (make-local-variable 'irc-last-private) nil) ; for sendlist : auto-expansion
  7546.   (set (make-local-variable 'irc-last-stamp) nil) ; for time-sentinel
  7547.   (set (make-local-variable 'irc-last-time) nil) ;
  7548.   (set (make-local-variable 'irc-list-stats) nil) ; for RPL_LIST statistics (temp)
  7549.   (set (make-local-variable 'irc-major-version) nil) ; major version number of server
  7550.   (set (make-local-variable 'irc-minor-version) nil) ; major version number of server
  7551.   (set (make-local-variable 'irc-nick-used) nil) ; the nick used at the server
  7552.   (set (make-local-variable 'irc-operator) nil)    ; for special privileges
  7553.   (set (make-local-variable 'irc-scratch) nil) ; for accumulating server messages
  7554.   (set (make-local-variable 'irc-total-time) nil) ;
  7555.   (set (make-local-variable 'irc-count-incoming-messages) 0)
  7556.   (set (make-local-variable 'irc-idle-last-sent) -1)
  7557. ;;;  (set (make-local-variable 'irc-idle-scratch-file)
  7558. ;;;       (expand-file-name
  7559. ;;;    (concat (make-temp-name "/tmp/.Kiwi.")
  7560. ;;;        "."
  7561. ;;;        (user-login-name)
  7562. ;;;        ".may-safely-be-deleted-anytime")))
  7563. ;;;  (if (file-exists-p irc-idle-scratch-file)
  7564. ;;;      (delete-file irc-idle-scratch-file))
  7565.   (set (make-local-variable 'irc-ignored-ppl) ;Nicks actually ignored
  7566.        (irc-create-new-hash-table 7))
  7567.   (set (make-local-variable 'irc-last-NOTICE-rcv) "")
  7568.   (set (make-local-variable 'irc-last-NOTICE-src) "")
  7569.   (set (make-local-variable 'irc-links-header) "Known server links.")
  7570.   (set (make-local-variable 'irc-links-stroke) "-------------------")
  7571.   (set (make-local-variable 'irc-linksinfo) ; for LINREPLY & RPL364 data (temp)
  7572.        (irc-create-new-hash-table 149))    ;2*(65-70 seen links, oct -91)
  7573.   (set (make-local-variable 'irc-list-header) "Name of channel  Users Topic")
  7574.   (set (make-local-variable 'irc-list-stroke) "---------------  ----- -----")
  7575.   (set (make-local-variable 'irc-listtree) ; for RPL_LIST 322 data (temp)
  7576.        (irc-create-new-hash-table 163))    ;2*(50-80 channels, oct -91)
  7577.   (set (make-local-variable 'irc-msg-cont-used) irc-msg-cont)
  7578.   ;; Indentation for continued long lines when displaying NAMREPLY's.
  7579.   (set (make-local-variable 'irc-names-cont-msg) (make-string 24 ? ))
  7580.   (set (make-local-variable 'irc-notify-looked-for)
  7581.        (irc-create-new-hash-table 149))
  7582.   (set (make-local-variable 'irc-notify-detected)
  7583.        (irc-create-new-hash-table 149))
  7584.   (set (make-local-variable 'irc-namtree) ; for NAMREPLY data (temp)
  7585.        (irc-create-new-hash-table 853))    ;2*(200-400 users, oct -91)
  7586.   (set 'irc-nicknames            ; for sendlists
  7587.        (irc-create-new-hash-table 853)) 
  7588.   (set 'irc-servernames            ; for server completion
  7589.        (irc-create-new-hash-table 997))    ;2*((60-70 seen links)+(200-400usrs))
  7590.   (set (make-local-variable 'irc-subscribed-channels) ; channels we listen to
  7591.        (irc-create-new-hash-table 7))    ;max 11
  7592.   (set (make-local-variable 'irc-services) ; for services like NICKSERV
  7593.        (irc-create-new-hash-table 17))
  7594.   (set (make-local-variable 'irc-who-header)
  7595.        (concat "Nickname  Stat Channel name   "
  7596.            " <Hop count> Login@Client \"Real name\" SERVER=srvr"))
  7597.   (set (make-local-variable 'irc-who-header)
  7598.        (concat "Nickname  Stat Random channel  Whatever@clientmachine \"Real name\""))
  7599.   (set (make-local-variable 'irc-who-stroke)
  7600.        (concat "--------  ---- --------------  "
  7601.            "------------------------------------------------"))
  7602.   (set (make-local-variable 'irc-whotree) ; for WHOREPLY data (temp)
  7603.        (irc-create-new-hash-table 853))    ;(200-400 users, oct -91)
  7604.   (set (make-local-variable 'mode-line-format)
  7605.        (list (purecopy "--- %14b ")
  7606.          'global-mode-string
  7607.          (purecopy " %[(")
  7608.          'mode-name 'minor-mode-alist 'irc-operator
  7609.          (purecopy ")%] ")
  7610.          'irc-nick-used ":" 'irc-channel
  7611.          " " 'irc-away (purecopy "-%-")))
  7612.   ;; too many ways to get unbalanced parens (most notably ":-)")
  7613.   (set (make-local-variable 'blink-matching-paren) nil)
  7614.   ;; as closest we can come to "natural" terminal scrolling
  7615.   (set (make-local-variable 'scroll-step) 1) ; Reset in irc.
  7616.   (set-marker (set (make-local-variable 'irc-mark) (make-marker)) (point-max))
  7617.   (let ((nicks irc-ignores))
  7618.     (while (not (null nicks))
  7619.       (irc-remember (car nicks) 'irc-ignored-ppl)
  7620.       (setq nicks (cdr nicks))))
  7621.   (let ((services '(;;"AMIGASERV"
  7622.             ;;"ARSKA"        ;TZoper of #42.
  7623.             ;;"CDSERV"
  7624.             ;;"CONVSERV"    ;Convert from Celsius to Fahrenheit etc
  7625.             ;;"EU-OPER"        ;TZoper of #Eu-opers.
  7626.             "IRCIIHELP"        ;Help automaton for ircII commands
  7627.             ;;"JIRCC"        ;Japanese Kanjii/ASCII translator
  7628.             ;;"MSGSERV"        ;Stores and forwards user-user messages
  7629.             "NICKSERV"        ;Register for nick names
  7630.             ;;"NOTE-NO"
  7631.             ;;"NOTESERV"    ;"Wait for user" and "store messages".
  7632.             ;;"SWEDESERV"
  7633.             ;;"TZOPER"        ;Copr ioprs on #Twilight_Zone
  7634.             ;;"WEBSERV"
  7635.             )))
  7636.     (while services
  7637.       (irc-remember (car services) 'irc-services)
  7638.       (irc-remember (car services) 'irc-nicknames)
  7639.       (setq services (cdr services))))
  7640.   (buffer-enable-undo)
  7641.   (irc-wrap-display-time)
  7642.   (turn-on-auto-fill)
  7643.   ;; "invisible subwindows" or whatever you would like to call them would be
  7644.   ;; nice.  That way I could make the output-region read-only.  The two things
  7645.   ;; most likely to screw up the buffer are backward-kill-word and kill-region
  7646.   (use-local-map irc-mode-map)
  7647.   (run-hooks 'irc-mode-hook))
  7648.  
  7649.  
  7650. (defun irc-sentinel (proc stat)
  7651.   "The sentinel for the IRC connexion.
  7652. Takes the normal sentinel arguments PROCESS and STATUS."
  7653.   ;; ignore anything but finished; i don't know what to do with the others
  7654.   (cond ((or (string= stat "finished\n")
  7655.          (string-match "^exit" stat))
  7656.          (save-excursion
  7657.            (set-buffer (cond ((processp proc) (process-buffer proc))
  7658.                  ((bufferp proc) proc)
  7659.                  (t (get-buffer
  7660.                  (irc-host+port-to-buffer irc-server
  7661.                               irc-port)))))
  7662.            (goto-char (point-max))
  7663.        (ding nil)
  7664.        (ding nil)
  7665.        (ding nil)
  7666.        (irc-insert "")
  7667.        (irc-insert "")
  7668.        (irc-insert (make-string (1- (window-width
  7669.                      (get-buffer-window (current-buffer))))
  7670.                     ?*))
  7671.        (let ((msg (format "Your IRC session ended at %s." (irc-get-time))))
  7672.          (irc-insert "%s%s"
  7673.              (make-string (max (/ (- (window-width
  7674.                           (get-buffer-window
  7675.                            (current-buffer)))
  7676.                          (length msg))
  7677.                           2)
  7678.                        0)
  7679.                       ? )
  7680.              msg))
  7681.        (irc-insert (make-string (1- (window-width
  7682.                      (get-buffer-window (current-buffer))))
  7683.                     ?*))
  7684.        (irc-insert ""))
  7685.          ;; all that needs to be done is a little maintenance ...
  7686.          (setq irc-processes (delq proc irc-processes)))))
  7687.  
  7688.  
  7689.  
  7690. ;; processing input
  7691.  
  7692. (defun irc-process-input ()
  7693.   "If in the input region, parse it for messages and commands.
  7694. In the output region, next-line if irc-spacebar-pages, otherwise do nothing.
  7695.  
  7696. All of the lines in the input region are rejoined during processing to be
  7697. handled as one.  A command is any line starting with a / after leading
  7698. whitespace is stripped away; commands can not exceed 510 characters.  Messages
  7699. can be longer but they will be split into 510 character segments for IRC.  The
  7700. buffer will reflect how the message was sent if it needed to be broken; the
  7701. split(s) will be indicated by \" >>\" to mean that the message is continued."
  7702.   (interactive)
  7703.   ;; do the simple stuff for the output region
  7704.   (if (< (point) irc-mark)
  7705.       (if (and (fboundp 'url-get-url-at-point)
  7706.            (fboundp 'w3-follow-url-at-point-other-frame)
  7707.            (stringp (url-get-url-at-point)))
  7708.       (let ((p (point)))
  7709.         (next-line 1)
  7710.         (w3-follow-url-at-point-other-frame p))
  7711.     (if irc-spacebar-pages
  7712.         (next-line 1)
  7713.       (ding)))
  7714.     (if (not (processp (get-buffer-process (current-buffer))))
  7715.     (irc-insert (concat "%%Buffer not connected to any IRC-server, type"
  7716.                 " M-x irc RET to connect to a server."))
  7717.       (irc-check-time)
  7718.       ;; the input region is more work ...
  7719.       ;; first, toast extraneous spaces, tabs and newlines
  7720.       ;; at end of input region
  7721.       (delete-region (goto-char (point-max))
  7722.              (if (re-search-backward "[^ \n]" irc-mark t)
  7723.              (1+ (point))
  7724.                (point)))
  7725.       ;; nuke the white space at the beginning of input region, too
  7726.       (delete-region (goto-char irc-mark)
  7727.              (progn (re-search-forward " *")
  7728.                 (point)))
  7729.       (setq irc-history-index -1)    ; reset the history scroll location
  7730.       (let ((txt (buffer-substring irc-mark (point-max)))
  7731.         (maxlen (- irc-max-server-message-length 2))
  7732.         send
  7733.         ass)
  7734.     ;; check to see if the input region is empty
  7735.     (if (string= "" txt)
  7736.         (message "%%Nothing sent to the irc-server.")
  7737.       (while (string-match "\n" txt)
  7738.         (aset txt (match-beginning 0) ? ))
  7739.       (if (string-match "^/" txt)  ; it's a command
  7740.           (if (< (length txt) maxlen)
  7741.           (progn
  7742.             (goto-char (point-max))
  7743.             (insert "\n")
  7744.             (set-marker irc-mark (point))
  7745.             (irc-execute-command
  7746.              (setq irc-last-command (substring txt 1))))
  7747.         ;; can't use error because that kills the function
  7748.         (ding)
  7749.         (message "IRC commands can't exceed %d characters."
  7750.              maxlen))
  7751.         ;; "a specified sendlist" -- was there one?
  7752.         (setq ass (irc-find-to txt 'explicit))
  7753.         (if (and ass
  7754.              (string-match "^[^;:]" txt))
  7755.         ;; a real sendlist was specified, so
  7756.         ;; update irc-last-explicit
  7757.         (setq irc-last-explicit (irc-find-to txt)))
  7758.         (irc-add-to-hist (concat (if (not ass)
  7759.                      irc-default-to)
  7760.                      (buffer-substring irc-mark
  7761.                                (point-max))))
  7762.         (while (> (length txt) maxlen)
  7763.           (setq send (substring txt 0 maxlen)
  7764.             txt  (substring txt maxlen)
  7765.             send (irc-fix-wordwrap send txt)
  7766.             txt  (concat (if ass
  7767.                      irc-last-explicit
  7768.                    irc-default-to)
  7769.                     z
  7770.                     (cdr send))
  7771.             send (concat (car send) " >>"))
  7772.           (goto-char (+ irc-mark (- (length send) 3)))
  7773.           (insert " >>\n" (if ass
  7774.                   irc-last-explicit
  7775.                 irc-default-to))
  7776.           (if (looking-at " ")
  7777.           (delete-char 1))
  7778.           (beginning-of-line)
  7779.           (set-marker irc-mark (point))
  7780.           (irc-execute-msg send))
  7781.         (goto-char (point-max))
  7782.         (insert "\n")
  7783.         (set-marker irc-mark (point))
  7784.         (irc-execute-msg txt))))))
  7785.   (setq irc-idle-last-sent (irc-current-time)))
  7786.  
  7787.  
  7788. (defun irc-execute-command (str)
  7789.   "Execute the \"/\" command of STR.  STR should not begin with a slash.
  7790. Commands are first looked up in the irc-alias-alist; if it is found there
  7791. then the alias gets passed recursively with any arguments the original
  7792. had.  The irc-command-alist is checked next and finally the irc-operator-alist.
  7793. A command is considered \"found\" when it matches either exactly or
  7794. unambiguously starting at the first character.  That is, J would match JOIN,
  7795. but OIN would not."
  7796.   (let* ((case-fold-search t)
  7797.          (cmd (substring str 0 (string-match "\\( +\\|$\\)" str)))
  7798.          (text (substring str (match-end 0)))
  7799.          (ambig (irc-check-list
  7800.                  (mapcar 'car (append irc-alias-alist irc-command-alist
  7801.                                       (if irc-operator irc-operator-alist)))
  7802.                  cmd 'start-only))
  7803.          (matches nil)
  7804.      (irc-called-from-buffer t))
  7805.     ;; if no matches are found the command might still be a valid command
  7806.     ;; name hiding behind non-operator status.  i don't like messages that
  7807.     ;; lie and say "Unknown command '/REHASH'" so this should make it not lie.
  7808.     (if (and (not irc-operator) (null ambig))
  7809.         (setq ambig (irc-check-list (mapcar 'car irc-operator-alist) cmd t)))
  7810.     ;; first determine any ambiguities among the lists
  7811.     (if (null ambig)
  7812.         ;; no matches at all were found
  7813.         (irc-insert "%%Unknown command \"/%s\".  Type /HELP for help."
  7814.                     (upcase cmd))
  7815.     ;; this is here for when a regular command gets aliased.  it shows up
  7816.     ;; as being ambiguous but it really isn't later on.
  7817.     (if (irc-member-general (car ambig) (cdr ambig) 'string=)
  7818.         (setq ambig (cdr ambig)))
  7819.     (if (> (length ambig) 1)
  7820.         (irc-insert "%%Ambiguous command \"/%s\".  Could be %s."
  7821.             (upcase cmd)
  7822.             (irc-subst-comma
  7823.              (mapconcat (function (lambda (arg)
  7824.                       (concat "/" arg)))
  7825.                     ambig
  7826.                     ", ")
  7827.              "or"))
  7828.         ;; alias list has highest priority
  7829.         (setq matches (irc-check-list (mapcar 'car irc-alias-alist) cmd t))
  7830.         ;; make sure matches is what we set out to looking for ...
  7831.         (if (and matches (string= (car matches) (car ambig)))
  7832.         ;; call this function again with the text as argument
  7833.         (irc-execute-command
  7834.          (concat (cdr (assoc (car matches) irc-alias-alist))
  7835.              ;; the servers won't grok trailing whitespace for some
  7836.              ;; messages so only use it to separate an argument
  7837.              (if (string< "" text) " ") text))
  7838.         ;; next try the command alist
  7839.         (setq matches (irc-check-list (mapcar 'car irc-command-alist)
  7840.                           cmd
  7841.                           t))
  7842.         (if (and matches
  7843.              (not (irc-check-list (mapcar 'car irc-operator-alist)
  7844.                           cmd
  7845.                           t)))
  7846.             ;; call the appropriate irc-execute-* function
  7847.             (funcall (intern-soft
  7848.                   (concat "irc-execute-"
  7849.                       (cdr (assoc (car matches)
  7850.                           irc-command-alist))))
  7851.                  text)
  7852.             ;; no matches yet.  last resort is the operator alist
  7853.             (setq matches (irc-check-list (mapcar 'car
  7854.                               irc-operator-alist)
  7855.                           cmd
  7856.                           t))
  7857.             (if matches
  7858.             (if irc-operator
  7859.                 (funcall
  7860.                  (intern-soft (concat
  7861.                        "irc-execute-"
  7862.                        (cdr
  7863.                         (assoc (car matches)
  7864.                            irc-operator-alist))))
  7865.                  text)
  7866.                 (irc-insert (concat "%%Only enabled IRC Operators"
  7867.                         " can use the /%s command. Use"
  7868.                         " /OPER to enable yourself.")
  7869.                     (upcase (car matches)))))))))))
  7870.  
  7871.  
  7872. (defun irc-send (str)
  7873.   "Send STR to process in the current buffer.
  7874. A CR-LFD pair is appended automatically as per the 'official' IRC protocol,
  7875. but it seems unnecessary.  Returns its argument STR."
  7876.   (setq str (irc-lowlevel-enquote str))
  7877.   (let* ((proc (get-buffer-process (current-buffer)))
  7878.      (sent (if (processp proc)
  7879.            (condition-case x
  7880.                (send-string proc (concat str "\r\n"))
  7881.              (error x))))
  7882.      (ok (and (processp proc)
  7883.           (eq sent nil))))
  7884.     (if (not ok)
  7885.     (let ((stars (make-string (1- (window-width (get-buffer-window
  7886.                              (current-buffer))))
  7887.                   ?*)))
  7888.       (irc-insert "")
  7889.       (irc-insert "")
  7890.       (irc-insert "%s" stars)
  7891.       (irc-insert "?Failed sending to server!")
  7892.       (cond ((not (processp proc))
  7893.          (irc-insert "?No \"process\" to send to."))
  7894.         ((consp sent)
  7895.          (irc-insert (concat "?Signaled condition is \"%s\" and"
  7896.                      " associated data is \"%s\".")
  7897.                  (car sent)
  7898.                  (cdr sent)))
  7899.         (t (irc-insert "?Unknown reason, proc=%s, sent=%s."
  7900.                    proc
  7901.                    sent)))
  7902.       (irc-insert "?Your IRC session aborted at %s." (irc-get-time))
  7903.       (irc-insert "%s" stars)
  7904.       (if (processp proc) (delete-process proc))
  7905.       (error "IRC aborted"))
  7906.     (irc-log-in-debug-buffer (concat "+ " str)))))
  7907.  
  7908.  
  7909.  
  7910. ;; sending messages to people
  7911. (defun irc-execute-privmsg (str)
  7912.   "Usage: /MSG recipient(s) message
  7913.  
  7914. This command is provided simply for compatability with the C client.
  7915. It is preferable instead to just type the name of the user followed by
  7916. a semi-colon and then the message. That is, \"tale;hi!\" will send the
  7917. message \"hi!\" to the user with the nickname which starts with
  7918. \"tale\".  A semi-colon at the beginning of the line means to send to
  7919. the last recipient explicity specified; typing a semi-colon at the
  7920. beginning of a line expands it to the last recipient(s) specified. The
  7921. recipients for a message can be a comma separated list of users and/or
  7922. channels. Don't use any spaces left of the semi-colon.
  7923.  
  7924. You can send messages to users and channels, and if you are an enabled
  7925. IRC operator, you can also send broadcasts to server machines and
  7926. client machines.
  7927.  
  7928. Examples:
  7929. /msg wiz hi there           send \"hi there\" to user with nickname wiz
  7930. wiz;hi there                send to user wiz
  7931. msa,wiz;hi there            send to the users wiz and msa
  7932. 42;hi there                 send into channel 42
  7933. 42,wiz;hi there             channel 42 and user wiz
  7934.  
  7935. If you are an enabled IRC operator:
  7936. $minsk.docs.uu.se;...       send a message to all users using server minsk
  7937. $*.se;...                   send to all users using swedish servers
  7938. #cia.docs.uu.se;...         send to all users running their clients on cia
  7939. #*.se;...                   all user running their clients on swedish machines"
  7940.   (irc-add-to-hist
  7941.    (irc-execute-msg
  7942.     (concat
  7943.      (setq irc-last-explicit (concat (substring str 0 (string-match " +\\|$"
  7944.                                     str))
  7945.                      ";"))
  7946.      (substring str (match-end 0))))))
  7947.  
  7948.  
  7949. (defun irc-execute-msg (str)
  7950.   "Send a message to a channel or another user.  Returns its argument STR,
  7951. munged slightly to indicate where it was attempted to be sent."
  7952.   ;; this really is an indirect function of the UI (ie, not through a /COMMAND)
  7953.   ;; so it isn't interactive
  7954.   (let ((tolist nil)
  7955.     (orig str)
  7956.     (icw nil)
  7957.     (confirm nil)
  7958.     (on-hash (irc-is-multijoinable-channel irc-channel))
  7959.     (newsrvr (irc-server-has-multijoinable-channels)))
  7960.     (if (string-match "^[:;]" str)
  7961.         ;; a little bit of fill-in-the-blank
  7962.         (setq str (concat irc-last-explicit (substring str 1)))
  7963.     (if (not (irc-find-to str 'explicit))
  7964.         ;; prepend an implicit sendlist if need be
  7965.         (if irc-default-to
  7966.         (setq str (concat irc-default-to str))
  7967.         (irc-insert "%%You have no default sendlist."))))
  7968.     (if (irc-find-to str 'explicit)
  7969.         (setq icw (irc-find-to str)
  7970.               tolist (irc-burst-comma (substring icw 0 (1- (length icw))))
  7971.           tolist (mapcar 'irc-clean-up-message tolist)
  7972.               str (irc-find-message str)
  7973.               ;; kill on leading space if it exists.  ie, "tale: hi" will
  7974.               ;; send "hi" as a message not " hi".
  7975.               str (if (string-match "^ *" str)
  7976.               (substring str (match-end 0)))))
  7977.     (setq confirm (delq            ; whee.  lisp indentation is fun.
  7978.            nil
  7979.            (mapcar
  7980.             (function
  7981.              (lambda (to)
  7982.               (if (not (zerop (string-to-int to)))
  7983.               (if (string= to irc-channel)
  7984.                   (progn
  7985.                 (irc-send
  7986.                  (if (and newsrvr on-hash)
  7987.                      (concat "PRIVMSG " irc-channel " :" str)
  7988.                      (concat "MSG :" str)))
  7989.                 to)
  7990.                   ;; new in 1.2 -- you _can_ send to a channel you
  7991.                   ;; are not on
  7992.                   (irc-send (concat "PRIVMSG " to " :" str))
  7993.                   to)
  7994.               (if (not (or (string= to "*")
  7995.                        (string= to "0")))
  7996.                   (setq icw (irc-check-list (irc-recall-all
  7997.                              'irc-nicknames)
  7998.                             to)))
  7999.               (cond ((string= to "*")
  8000.                  (if (string= "0" irc-channel)
  8001.                      (progn
  8002.                        (irc-insert (concat "%%You are not"
  8003.                                " talking to any"
  8004.                                " channel."))
  8005.                        nil)
  8006.                      (irc-send
  8007.                       (if (and newsrvr on-hash)
  8008.                       (concat "PRIVMSG " irc-channel
  8009.                           " :" str)
  8010.                       (concat "MSG :" str)))
  8011.                      irc-channel))
  8012.                 ((string= to "0")
  8013.                  (irc-insert "%%You can't send to channel 0.")
  8014.                  nil)
  8015.                 ((= (length icw) 1)
  8016.                  (irc-send (concat "PRIVMSG "
  8017.                            (car icw)
  8018.                            " :"
  8019.                            str))
  8020.                  (car icw))
  8021.                 ((not icw)
  8022.                  ;; Wox! No one found, but we'll do a
  8023.                  ;; nonomatching. Try sending it anyway and
  8024.                  ;; let the server bitch if necessary.
  8025.                  ;; So don't remember this "nonmatch".
  8026.                  (irc-send (concat "PRIVMSG " to " :" str))
  8027.                  to)
  8028.                 (t (irc-insert (concat "%%Ambiguous recipient"
  8029.                                " \"%s\"; could be %s.")
  8030.                            to
  8031.                            (irc-subst-comma
  8032.                         (mapconcat
  8033.                          (function
  8034.                           (lambda (arg)
  8035.                            (concat "\"" arg "\"")))
  8036.                          icw
  8037.                          ", ")
  8038.                         "or"))
  8039.                    nil)))))
  8040.             tolist)))
  8041.     (setq confirm (let ((foo ())
  8042.             (bar confirm))
  8043.             (while (> (length bar) 0)
  8044.               (setq foo (cons
  8045.                  (concat
  8046.                   (cond
  8047.                     ((irc-is-nickname (car bar)) "user")
  8048.                     ((irc-is-channelname (car bar)) "channel")
  8049.                     ((irc-is-broadcastname (car bar)) "server")
  8050.                     (t "receiver"))
  8051.                   " "
  8052.                   (car bar))
  8053.                  foo)
  8054.                 bar (cdr bar)))
  8055.             foo))
  8056.     (let* ((rcvr (irc-subst-comma (mapconcat 'eval confirm ", ")
  8057.                   "and"))
  8058.        (data (irc-clean-up-message (format irc-msg-sent rcvr))))
  8059.       (if (and confirm irc-confirm)
  8060.       (let ((c confirm))
  8061.         (while c
  8062.           (let ((r (irc-clean-up-message (format irc-msg-sent (car c)))))
  8063.         (irc-insert "%s%s" (make-string
  8064.                     (max 0 (- (window-width
  8065.                            (get-buffer-window
  8066.                         (current-buffer)))
  8067.                           (length r)
  8068.                           1))
  8069.                     ? )
  8070.                 r)
  8071.         (setq c (cdr c)))))
  8072.       (if (not confirm)
  8073.           (irc-insert "%% Message not sent. Use /HELP for help."))))
  8074.     orig))
  8075.  
  8076.  
  8077. (defun irc-execute-oops (newto)
  8078.   "Usage: /OOPS intended-recipient
  8079. Send irc-oops to recipient(s) of last message and resend message to
  8080. 'intended-recipient'.  This command is handy when you've just sent a message
  8081. to the wrong place and you want the person/people who saw it to know that they
  8082. should just disregard it.  The message which was originally sent then gets
  8083. forwarded to its proper destination."
  8084.   (interactive '(""))
  8085.   (if (not irc-called-from-buffer)
  8086.       (progn (irc-insert "")
  8087.          (irc-insert "/OOPS")))  
  8088.   (let* ((prev (irc-find-to (car irc-history)))
  8089.      (data (concat prev irc-oops)))
  8090.     ;; first do the oops message
  8091.     (irc-execute-msg data)
  8092.     ;; then resend the original
  8093.     (if (and (string= "" newto) irc-called-from-buffer)
  8094.     (irc-insert (concat "%%No new receiver given. Oops said to %s. Not"
  8095.                 " redirected.")
  8096.             prev)
  8097.     (irc-execute-redirect newto)))
  8098.   (setq irc-idle-last-sent (irc-current-time)))
  8099.  
  8100.  
  8101. (defun irc-execute-redirect (newto)
  8102.   "Usage: /REDIRECT additional-recipient
  8103.  
  8104. Send to 'additional-recipient' the last message which you sent.  This 
  8105. command can be fairly easily duplicated using the history mechanism by hand
  8106. but it is provided to make it even easier."
  8107.   (interactive '(""))
  8108.   (if (not irc-history)
  8109.       (irc-insert "%%No message sent yet, nothing to redirect.")
  8110.       (let* ((default (if irc-default-to 
  8111.               (substring irc-default-to 0 (string-match
  8112.                                "[:;]" irc-default-to))
  8113.               ""))
  8114.          (prompt (if (string< "" default)
  8115.              (concat "(RET for "
  8116.                  (irc-nuke-whitespace
  8117.                   (concat
  8118.                    default
  8119.                    (if (string-match "\\*" default)
  8120.                        (concat "; where *=\""
  8121.                            irc-channel
  8122.                            "\""))))
  8123.                  ") ")
  8124.              ""))
  8125.          (n (irc-nuke-whitespace
  8126.          (if (and (string= "" newto) (not irc-called-from-buffer))
  8127.              (irc-read-object
  8128.               (format "Send copy of last message (%s) to whom? %s"
  8129.                   (let ((m (irc-find-message (car irc-history))))
  8130.                 (if (> (length m) 5)
  8131.                     (concat (substring m 0 5) "...")
  8132.                     m))
  8133.                   prompt)
  8134.               ""
  8135.               (irc-recall-all 'irc-nicknames))
  8136.              newto)))
  8137.          (new (if (string= "" n) default n)))
  8138.     (if (not (irc-is-receiver new))
  8139.         (irc-insert (concat "%%\"%s\" is not a valid receiver. Message not"
  8140.                 " redirected.")
  8141.             new)
  8142.         (let ((to (if (string= "" new)
  8143.               default
  8144.               (concat new ";"))))
  8145.           (setq irc-last-explicit to)
  8146.           (irc-add-to-hist
  8147.            (irc-execute-msg
  8148.         (concat to (irc-find-message (car irc-history)))))))))
  8149.   (setq irc-idle-last-sent (irc-current-time)))
  8150.  
  8151.  
  8152.  
  8153. ;; /commands for the server
  8154. (defun irc-execute-quote (msg)
  8155.   "Usage: /QUOTE string
  8156.  
  8157. This command is used to send 'string' directly to the IRC server without
  8158. any local processing.  Warning: this has the potential to screw up some
  8159. things in irc-mode, particularly if it is used to change your nickname or
  8160. to switch channels."
  8161.   (interactive '(""))
  8162.   (let ((m (if (and (string= "" msg) (not irc-called-from-buffer))
  8163.            (read-string "String to send to server: ")
  8164.            msg)))
  8165.     (cond ((string-match "^ *\\([^ ]+\\)" m)
  8166.        (let ((cmd (subfield m 1)))
  8167.          (irc-send m)
  8168.          (irc-send (concat "CLIENT-SYNCH :QUOTE " cmd))))
  8169.       (t (irc-insert "%%Nothing was sent to the IRC server."))))
  8170.   (setq irc-idle-last-sent (irc-current-time)))
  8171.  
  8172.  
  8173. (defun irc-execute-who (channel)
  8174.   "Usage: /WHO { channel | user }
  8175.  
  8176. Get a list of the users on IRC. The argument \"channel\" means to show
  8177. just the users on that channel, with * representing the current channel.
  8178. User can be any mask, ie *.se for current swedish IRCjunkies.
  8179.  
  8180. Each user is indicated on a separate line with their nickname, status,
  8181. channel, login name, host and real name. The second column, \"Stat\"
  8182. gives the status for the user, and is shown as a four letter word (:-)
  8183. according to the combination of their attributes. The possible
  8184. attributes are being an IRC operator, being a channel operator and
  8185. being marked as being away.
  8186.  
  8187.                                           Status field
  8188. A normal user having no attributes set:     (blank)
  8189. A normal user marked as being away:          Away
  8190. An IRC operator with no other attribues:     Iopr
  8191. An IRC operator marked as being away:        IoAw
  8192. A channel operator with no other attributes: Copr
  8193. A channel operator marked as being away:     CoAw
  8194. User being both IRC- and channel operator:   ICop
  8195. As above but also marked as being away:      ICAw
  8196.  
  8197. Being ignored takes precedence over all
  8198. other attributes, always shown as:           IGNR     (cf \"/HELP IGNORE\"). 
  8199.  
  8200. Users being on either no channel at all, or on channels with the mode
  8201. PRIVATE are appear with a blank \"Channel\" field. If you are
  8202. connected to a server of version 2.6, and are requesting a \"general\"
  8203. who listing (ie for users potentially on different channels), all
  8204. users \"Channel\" field will be blank.
  8205.  
  8206. An %-sign is appended to the name or number of your current
  8207. channel.
  8208.  
  8209. BE WARNED: on some servers, the operators CAN see who's on a negative channel.
  8210. On some of these servers, the channel number is disclosed, on others only
  8211. the fact that a user is on a negative channel, but not which one.
  8212. The same goes for \"private\" and \"secret\" channels.
  8213.  
  8214. If a single \"user\" is given as the argument, (ie a word starting with neither
  8215. a + nor a digit) it is taken to be the nickname of a user on IRC and more
  8216. information, if available, is given about the person.
  8217.  
  8218. If this function is called interactively then the prefix argument is used
  8219. as the channel to query.  No argument means all of them and an argument
  8220. of \"-\" or \"*\" means the current channel." 
  8221.   (interactive '(""))
  8222.   (let* ((c (if (and (string= "" channel) (not irc-called-from-buffer))
  8223.         (irc-read-object (concat "Who? "
  8224.                      (if (not (string= "0" irc-channel))
  8225.                          (concat "(Press return for "
  8226.                              irc-channel
  8227.                              ") ")
  8228.                          ""))
  8229.                  ""
  8230.                  (irc-get-channels-and-nicks-and-servers))
  8231.         channel))
  8232.      (c2 (irc-nuke-whitespace c))
  8233.      (chan (cond ((or (string= "" c2)
  8234.               (string= "*" c2))
  8235.               irc-channel)
  8236.              (t c2))))
  8237.     (if (string= "0" chan)
  8238.     (irc-insert (concat "%%No argument (or argument 0) given to /WHO,"
  8239.                 " this would certainly disconnect your"
  8240.                 " IRC-session. You can use /QUOTE WHO 0 if you"
  8241.                 " *really* want to do this."))
  8242.       (let ((s (irc-recall-all 'irc-services)))
  8243.     (irc-forget-all 'irc-nicknames)
  8244.     (irc-remember irc-nick-used 'irc-nicknames)
  8245.     (while (and (listp s) s)
  8246.       (irc-remember (car s) 'irc-nicknames)
  8247.       (setq s (cdr s)))
  8248.     (if (not irc-called-from-buffer)
  8249.         (progn (irc-insert "")
  8250.            (irc-insert "/WHO %s" chan)))
  8251.     (if (and irc-called-from-buffer (irc-is-nickname chan))
  8252.         (irc-execute-whois chan)
  8253.       (irc-send (concat "WHO " chan))))
  8254.       (setq irc-idle-last-sent (irc-current-time)))))
  8255.  
  8256.  
  8257. (defun irc-execute-whois (user)
  8258.   "Usage: /WHOIS user
  8259.  
  8260. Get a two line description of who and where \"user\" is.  If user is not
  8261. provided it is read from the minibuffer with a completing-read.
  8262. If * is given instead of a user name, you will be informed about ALL users.
  8263.  
  8264. BUG: The list of users used when * is given may be somewhat obsolete,
  8265. therefore first give a NAMES command."
  8266.   (interactive '(""))
  8267.   (let ((wholist (irc-recall-all 'irc-nicknames)))
  8268.     (if (and (string-match "^ *$" user) (not irc-called-from-buffer))
  8269.     (setq user (irc-read-object "Who is who? "
  8270.                     user
  8271.                     wholist)))
  8272.     (if (string< "" user)
  8273.     (progn (if (not irc-called-from-buffer)
  8274.            (progn (irc-insert "")
  8275.               (irc-insert "/WHOIS %s" user)))
  8276.            (irc-send (concat "WHOIS " user)))
  8277.     (irc-insert "%%Who is who? No nick given.")))
  8278.   (setq irc-idle-last-sent (irc-current-time)))
  8279.  
  8280.  
  8281. (defun irc-execute-motd (server)
  8282.   "Usage: /MOTD [ server ]
  8283.  
  8284. Tells the message of the day at the server."
  8285.   (interactive '(""))
  8286.   (let ((host (if (string= "" server)
  8287.           (if (not irc-called-from-buffer)
  8288.               (irc-read-object
  8289.                "Get message of the day for which host? "
  8290.                ""
  8291.                (irc-recall-all 'irc-servernames))
  8292.               "")
  8293.           server)))
  8294.     (if (string-match "^ *\\([^: ]*\\)" host)
  8295.     (let ((host (substring host (match-beginning 1) (match-end 1))))
  8296.       (if (not irc-called-from-buffer)
  8297.           (progn (irc-insert "")
  8298.              (irc-insert "/MOTD %s" host)))
  8299.       (irc-send (concat "MOTD " host)))
  8300.     (irc-insert (concat "%%Internal error in function irc-execute-motd,"
  8301.                 " please try another syntax and notify %s"
  8302.                 " by email.")
  8303.             irc-hacker)))
  8304.   (setq irc-idle-last-sent (irc-current-time)))
  8305.  
  8306.  
  8307. (defun irc-execute-version (server)
  8308.   "Usage: /VERSION [ server | user ]
  8309.  
  8310. Shows the version of the server, or of a user. If the argument looks
  8311. like a nickname, that user's client is queried using CTCP (client to
  8312. client protocol) about which client it is and which version of it it
  8313. is. If the queried client doesn't understand CTCP, no answer will
  8314. follow."
  8315.   (interactive '(""))
  8316.   (let* ((host (irc-nuke-whitespace
  8317.         (if (string= "" server)
  8318.             (if (not irc-called-from-buffer)
  8319.             (irc-read-object
  8320.              "Get version of which server/nick? "
  8321.              ""
  8322.              (irc-get-channels-and-nicks-and-servers))
  8323.             "")
  8324.             server)))
  8325.      (host (if (string= "" host) irc-server host))
  8326.      (hst (if (string= "*" host) irc-channel host)))
  8327.     (if (string-match "^ *\\([^: ]*\\)" hst)
  8328.     (let ((h (substring hst (match-beginning 1) (match-end 1))))
  8329.       (cond ((or (irc-is-nickname h)
  8330.              (irc-is-channelname h))
  8331.          (if (not irc-called-from-buffer)
  8332.              (progn (irc-insert "")
  8333.                 (irc-insert (concat "/VERSION " h))))
  8334.          (irc-insert (concat "%sQuerying client of user%s %s for"
  8335.                      " version of client%s")
  8336.                  irc-msg-info-pre
  8337.                  (if (irc-is-channelname h) "s on channel" "")
  8338.                  h
  8339.                  irc-msg-info-post)
  8340.          (irc-send (concat "PRIVMSG " h " :\001"
  8341.                    (irc-ctcp-enquote "VERSION")
  8342.                    "\001")))
  8343.         (t (if (not irc-called-from-buffer)
  8344.                (progn (irc-insert "")
  8345.                   (irc-insert "/VERSION %s" h)))
  8346.            (irc-send (concat "VERSION " h)))))
  8347.     (irc-insert "%%Give only one word please. \"%s\" is not valid."
  8348.             hst)))
  8349.   (setq irc-idle-last-sent (irc-current-time)))
  8350.  
  8351.  
  8352. (defun irc-execute-list (channel)
  8353.   "Usage: /LIST [channel]
  8354.  
  8355. Get a list of the discussions that are on IRC. If a channel is given,
  8356. only the topic for that channel is shown. A * denotes your current
  8357. channel, if any. An %-sign is appended to your current channel's name
  8358. or number."
  8359.   (interactive '(""))
  8360.   (if (not irc-called-from-buffer)
  8361.       (progn (irc-insert "")
  8362.          (irc-insert "/LIST %s" channel)))
  8363.   (irc-send (concat "LIST " channel))
  8364.   (setq irc-idle-last-sent (irc-current-time)))
  8365.  
  8366.  
  8367. (defun irc-execute-links (mask)
  8368.   "Usage: /LINKS [ mask ]
  8369.  
  8370. Show the names of all the servers which can communicate with your server.
  8371. The links can go down isolating different parts of the IRC-net, so this
  8372. is a good way to find out how extensive it is at the moment.
  8373.  
  8374. Given a mask like *.se, only server names matching the mask are displayed."
  8375.   (interactive '(""))
  8376.   (let ((m (if (and (string= "" mask) (not irc-called-from-buffer))
  8377.            (irc-read-object (concat "Check for which servers? (RET for"
  8378.                     " all, *.SE for swedish servers etc) ")
  8379.                 ""
  8380.                 (irc-recall-all 'irc-servernames))
  8381.            mask)))
  8382.     (cond ((string-match "^ *\\*? *$" m)
  8383.        (irc-forget-all 'irc-servernames)
  8384.        (irc-forget-all 'irc-linksinfo)))
  8385.     (if (not irc-called-from-buffer)
  8386.     (progn (irc-insert "")
  8387.            (irc-insert "/LINKS %s" m)))
  8388.     (irc-send (concat "LINKS " m)))
  8389.   (setq irc-idle-last-sent (irc-current-time)))
  8390.  
  8391.  
  8392. (defun irc-execute-lusers (mask)
  8393.   "Usage: /LUSERS [servermask]
  8394.  
  8395. Get the number of users and servers on your IRC network. 
  8396.  
  8397. There is a optional argument you can use if you only want
  8398. to see the count of some part of the IRCnet. For instance,
  8399. to see how many swedish users are on, try /lusers *.se"
  8400.   (interactive '(""))
  8401.   (let* ((mask (irc-nuke-whitespace mask)))
  8402.     (if (not irc-called-from-buffer)
  8403.     (progn (irc-insert "")
  8404.            (irc-insert (format "/LUSERS %s" mask))))
  8405.     (irc-send (concat "LUSERS " mask))
  8406.     (setq irc-idle-last-sent (irc-current-time))))
  8407.  
  8408.  
  8409. (defun irc-execute-admin (server)
  8410.   "Usage: /ADMIN [ server ]
  8411.  
  8412. Get information about the IRC administrator for 'server'; if server is not
  8413. supplied just query for the server to which you are connected."
  8414.   (interactive '(""))
  8415.   (let ((s (if (and (string= "" server) (not irc-called-from-buffer))
  8416.            (irc-read-object "Administrative info about which server? "
  8417.                 ""
  8418.                 (irc-recall-all 'irc-servernames))
  8419.            server)))
  8420.     (if (not irc-called-from-buffer)
  8421.     (progn (irc-insert "")
  8422.            (irc-insert "/ADMIN %s" s)))
  8423.     (irc-send (concat "ADMIN " s)))
  8424.   (setq irc-idle-last-sent (irc-current-time)))
  8425.  
  8426.  
  8427. (defun irc-execute-time (&optional server)
  8428.   "Usage: /TIME [ server ]
  8429.  
  8430. Get the current time on 'server'; is no server is provided use the one to which
  8431. you are connected.  When called with a interactively with a prefix-argument
  8432. the server name is read using the minibuffer.
  8433.  
  8434. Querying other servers can be handy given that people on IRC are spread out
  8435.  from the west coast of the United States to Finland.  The question \"What
  8436. time is it in Finland?\" comes up so frequently that an alias -- /TF -- has
  8437. been provided by default to get the answer.  This alias should work as long
  8438. as tut.fi is connected to your IRC-net."
  8439.   (interactive '(""))
  8440.   (let ((s (if (and (stringp server)
  8441.             (string= "" server)
  8442.             (not irc-called-from-buffer))
  8443.            (irc-read-object "Get the time at which server? "
  8444.                 ""
  8445.                 (irc-recall-all 'irc-servernames))
  8446.            server)))
  8447.     (if (and (stringp server) (not irc-called-from-buffer))
  8448.     (progn (irc-insert "")
  8449.            (irc-insert "/TIME %s" s)))
  8450.     (irc-send (concat "TIME " s)))
  8451.   (setq irc-idle-last-sent (irc-current-time)))
  8452.  
  8453.  
  8454. (defun irc-execute-join (channel)
  8455.   "Usage: /JOIN channel [mode]
  8456.  
  8457. Join \"channel\" on IRC.  If channel is not provided it is requested
  8458. in the minibuffer; when called interactively, the channel is prompted
  8459. for in the minibuffer.  Use /LEAVE to exit the channel.
  8460.  
  8461. You can supply an initial mode for the channel. If the channel didn't
  8462. exist before you joined it, the channel will be sat to the supplied mode.
  8463. If the channel already existed, the mode will be ignored by the server.
  8464.  
  8465. One can be listening on several channels at once. Up to 10 channels
  8466. can be listened to at any single time, either 10 #channels, or 1 old
  8467. style (either a +channel or a nummeric channel) and 9 #channels. Use
  8468. /JOIN to join (ie start listening and talkinging to) a channel and
  8469. /LEAVE to stop listening to a channel. If you /LEAVE the channel you
  8470. were talking to, you will end up not talking to any channel; just use
  8471. /JOIN again to remedy that situation.  There is no way yet to start
  8472. listening to a channel without choosing that channel as the one you
  8473. will talk to. Of course, another /JOIN will help..."
  8474.  
  8475.   (interactive '(""))
  8476.   (let* ((pair (cond
  8477.          ((string-match "^ *\\([^ ]+\\) +\\([^ ]\\)" channel)
  8478.           (cons (subfield channel 1)
  8479.             (concat (subfield channel 2)
  8480.                 (substring channel (match-end 0)))))
  8481.          ((string-match "^ *\\([^ ]+\\) *$" channel)
  8482.           (cons (subfield channel 1) ""))
  8483.          (t (cons "" ""))))
  8484.      (c (car pair))
  8485.      (m (cdr pair))
  8486.      (subchnls (irc-recall-all 'irc-subscribed-channels))
  8487.      (chn (irc-nuke-whitespace
  8488.            (if (and (string= c "")
  8489.             (not irc-called-from-buffer))
  8490.            (irc-read-object "Channel to join? "
  8491.                     ""
  8492.                     subchnls)
  8493.            c)))
  8494.      (mode (irc-nuke-whitespace
  8495.         (if (and (string= m "")
  8496.              (not irc-called-from-buffer)
  8497.              (not (irc-recall chn 'irc-subscribed-channels)))
  8498.             (irc-read-object (format
  8499.                       "Initial mode for channel \"%s\"? "
  8500.                       chn)
  8501.                      ""
  8502.                      '("A combination of +-bilmnopst"))
  8503.             m)))
  8504.      (digit-start (string-match "^-?[0-9]" chn)))
  8505.     (if (string= "" chn) ; well, so much for that 
  8506.     (irc-insert "%%No channel given. continuing talking to %s."
  8507.             irc-channel)
  8508.     (let* ((newsrvr (irc-server-has-multijoinable-channels)) 
  8509.            (mtch (irc-recall chn 'irc-subscribed-channels)))
  8510.       (cond ((string= "0" chn) 
  8511.          (setq irc-channel "0")
  8512.          (irc-show-subscribed-channels)) 
  8513.         ((and (not mtch)
  8514.               (not (irc-is-channelname chn)))
  8515.          (irc-insert (concat "%%Warning, that channel name (%s) looks" 
  8516.                      " strange, but will try to /join it"
  8517.                      " anyway. You might be in for a surprise,"
  8518.                      " thought.")
  8519.                  chn)
  8520.          (if (not irc-called-from-buffer) 
  8521.              (progn (irc-insert "")
  8522.                 (irc-insert "/JOIN %s %s" chn mode))) 
  8523.          (irc-send (format "%s %s %s"
  8524.                    (if newsrvr "JOIN " "CHANNEL ")
  8525.                    chn
  8526.                    mode)))
  8527.         (mtch (setq irc-channel mtch)
  8528.               (if (not irc-called-from-buffer) 
  8529.               (progn (irc-insert "")
  8530.                  (irc-insert "/JOIN %s" mtch)))
  8531.               (irc-show-subscribed-channels))
  8532.         (t (if (not irc-called-from-buffer)
  8533.                (progn (irc-insert "")
  8534.                   (irc-insert "/JOIN %s %s" chn mode)))
  8535.            (irc-send (format "%s %s %s"
  8536.                      (if newsrvr "JOIN " "CHANNEL ")
  8537.                      chn
  8538.                      mode))))))
  8539.     (setq irc-msg-cont-used
  8540.       (if (string= "0" chn) ;On private?
  8541.           irc-msg-cont 
  8542.           (make-string (1- (length (concat irc-msg-cont chn)))
  8543.                (string-to-char " ")))) )
  8544.   (setq irc-idle-last-sent (irc-current-time)))
  8545.  
  8546.  
  8547. (defun irc-execute-leave (channel)
  8548.   "Usage: /LEAVE [channel]
  8549.  
  8550. Leave your current channel (or a selected one from the set of joined channels,
  8551. if you're using a v2.6 or later server). Don't join another channel.
  8552.  
  8553. Also see /HELP JOIN."
  8554.   (interactive '(""))
  8555.   (let* ((c (if (and (string-match "^ *$" channel)
  8556.              (not irc-called-from-buffer))
  8557.         (irc-read-object (concat "Leave which channel? (0 for ALL"
  8558.                      (if (string= "0" irc-channel)
  8559.                          ") "
  8560.                          (concat ", RET for "
  8561.                              irc-channel
  8562.                              ") ")))
  8563.                  ""
  8564.                  (irc-recall-all 'irc-subscribed-channels))
  8565.         channel))
  8566.      (chan (irc-nuke-whitespace
  8567.         (if (and (not (string= "0" irc-channel))
  8568.              (or (string= "*" c) (string= "" c)))
  8569.             irc-channel
  8570.           (if (and (string= "" c)
  8571.                (not irc-called-from-buffer))
  8572.               (message "%%No channel chosen"))
  8573.           c))))
  8574.     (if (string= "0" chan)
  8575.     (progn
  8576.       (let ((lst (irc-recall-all 'irc-subscribed-channels))
  8577.         (irc-multiple-leave-in-progress t)
  8578.         (irc-called-from-buffer t))
  8579.         (while (not (null lst))
  8580.           (irc-send (concat "PART " (car lst)))
  8581.           (setq lst (cdr lst))))
  8582.       (irc-show-subscribed-channels))
  8583.     (if (not irc-called-from-buffer)
  8584.         (progn (irc-insert "")
  8585.            (irc-insert "/LEAVE %s" chan)))
  8586.     (if (string< "" chan)
  8587.         (progn (irc-insert "%sLeaving channel %s%s"
  8588.                    irc-msg-info-pre chan irc-msg-info-post)
  8589.            (if (irc-server-has-multijoinable-channels)
  8590.                (irc-send (concat "PART " chan))
  8591.                (irc-send "CHANNEL 0")))
  8592.         (irc-insert (concat "%%Leave which channel? No channel given. Try"
  8593.                 " /MEMBERSHIPS")))))
  8594.   (setq irc-idle-last-sent (irc-current-time)))
  8595.  
  8596.  
  8597. (defun irc-execute-nick (name)
  8598.   "Usage: /NICKNAME name
  8599.  
  8600. Change your nickname in IRC.  A nickname can contain alphanumeric characters,
  8601. underscores (_), hyphens (-) or the special characters left brace ({), right
  8602. brace (}), vertical bar (|), left bracket ([), right bracket (]) and back
  8603. slash (\\). These special character are alphabetic characters in some
  8604. languages like the scandinavian ones.  The name cannot start with a hyphen or
  8605. number and only the first nine characters are used.
  8606.  
  8607. Unfortunately, due to the way confirmation from the servers work, it might be
  8608. falsely reported that your nickname was successfully changed when it was not.
  8609. The server will come back and say so and finally irc-mode will wise-up and
  8610. note that your nickname was not changed.
  8611.  
  8612. All the above things change from server version to server version, so they may
  8613. or may not work. Try it."
  8614.   (interactive '(""))
  8615.   (let ((newnick (if (and (string= "" name) (not irc-called-from-buffer))
  8616.              (irc-nuke-whitespace (read-string "New nickname? "))
  8617.              name)))
  8618.     (if (string= "" newnick)
  8619.     (irc-insert "%sNickname not changed%s"
  8620.             irc-msg-info-pre
  8621.             irc-msg-info-post)
  8622.     (progn
  8623.       (if (not irc-called-from-buffer)
  8624.           (progn (irc-insert "")
  8625.              (irc-insert "/NICK %s" newnick)))
  8626.       (irc-insert "%sTrying to change your nickname to \"%s\"%s"
  8627.               irc-msg-info-pre
  8628.               newnick
  8629.               irc-msg-info-post)
  8630.       (set-buffer-modified-p (buffer-modified-p))
  8631.       (irc-send (concat "NICK " newnick)))))
  8632.   (setq irc-idle-last-sent (irc-current-time)))
  8633.  
  8634.  
  8635. (defun irc-execute-quit (text)
  8636.   "Usage: /QUIT [reason]
  8637.  
  8638. Exit IRC.  The connection is closed but the buffer is left behind.
  8639. If you want, you can give a reason for quitting IRC."
  8640.   (interactive '(""))
  8641.   (if (not irc-called-from-buffer)
  8642.       (progn (if (string-match "^ *$" text)
  8643.          (setq text (yow)))
  8644.          (let ((parias '("\n" "  " "\t"))
  8645.            (ok nil)
  8646.            (n 0))
  8647.            (while (not ok)
  8648.          (let ((p parias))
  8649.            (while p
  8650.              (while (string-match (car p) text)
  8651.                (setq text (concat (substring text
  8652.                              0
  8653.                              (match-beginning 0))
  8654.                       " "
  8655.                       (substring text (match-end 0)))))
  8656.              (setq p (cdr p))))
  8657.          (setq n (1+ n))
  8658.          (if (> n 10)
  8659.              (setq text ""))
  8660.          (if (< (length text) 80)
  8661.              (setq ok t)
  8662.              (setq text (yow)))))
  8663.          (irc-insert "")
  8664.          (irc-insert "/QUIT %s" text)))
  8665.   (irc-send (concat "QUIT :" text))
  8666.   (sit-for 2)                ;Give server a chance to react.
  8667.   (let ((proc (get-buffer-process (current-buffer))))
  8668.     (cond ((processp proc)
  8669.        (irc-sentinel proc "finished\n")
  8670.        (delete-process proc))))
  8671.   (setq irc-idle-last-sent (irc-current-time)))
  8672.  
  8673.  
  8674. (defun irc-execute-away (text)
  8675.   "Usage: /AWAY [message]
  8676.  
  8677. Mark yourself as away, giving TEXT to people who send you private messages.
  8678. Without any arguments it will just insert a message about your current status."
  8679.   (interactive '(""))
  8680.   (let ((reason (if (and (string= "" text) (not irc-called-from-buffer))
  8681.             (read-string "Reason to be away? ")
  8682.             text)))
  8683.     (if (string= "" reason)
  8684.     (if irc-away
  8685.         (let ((pre (concat irc-msg-info-pre "You are ")))
  8686.           (irc-insert (concat "%smarked as being away: \"%s\", "
  8687.                   "use /HERE to remove the mark%s")
  8688.               pre
  8689.               (substring irc-away 2 -1)
  8690.               irc-msg-info-post))
  8691.         (irc-insert "%sYou are not currently marked as being away%s"
  8692.             irc-msg-info-pre
  8693.             irc-msg-info-post))
  8694.     (if (not irc-called-from-buffer)
  8695.         (progn (irc-insert "")
  8696.            (irc-insert "/AWAY %s" reason)))
  8697.     (irc-send (concat "AWAY :" reason))
  8698.     (setq irc-away (concat " [" reason "]")))
  8699.     (set-buffer-modified-p (buffer-modified-p)))
  8700.   (setq irc-idle-last-sent (irc-current-time)))
  8701.  
  8702.  
  8703. (defun irc-execute-here (cruft)
  8704.   "Usage: /HERE
  8705.  
  8706. Mark yourself as present (ie, not \"away\") on IRC.  Any arguments to this
  8707. command are ignored."
  8708.   (interactive '(""))
  8709.   (if (not irc-called-from-buffer)
  8710.       (progn (irc-insert "")
  8711.          (irc-insert "/HERE")))
  8712.   (irc-send "AWAY")
  8713.   (setq irc-away nil)
  8714.   (set-buffer-modified-p (buffer-modified-p))
  8715.   (setq irc-idle-last-sent (irc-current-time)))
  8716.  
  8717.  
  8718. (defun irc-execute-topic (topic)
  8719.   "Usage: /TOPIC channel [topic ...]
  8720.       or: /TOPIC [topic ...]
  8721.  
  8722. Make 'topic' the description of the named channel; * for channelname means
  8723. the current channel you're talking to.
  8724.  
  8725. With no topic, doesn't change the topic but only inspects it.
  8726.  
  8727. If no channel is given (and the first word of the topic doesn't looks like
  8728. a channel name), the command operates on the current channel you're talking to.
  8729. "
  8730.   (interactive '(""))
  8731.   (let* ((top1 (cond ((and (string= "" topic) (not irc-called-from-buffer))
  8732.               (read-string (concat "Topic for channel "
  8733.                        irc-channel
  8734.                        "? (RET to check) ")))
  8735.              (t topic)))
  8736.      (top (if (string-match "^\\([#&][^ :]+\\) *" top1)
  8737.           (substring top1 (match-end 0))
  8738.           top1))
  8739.      (chn (if (string-match "^\\([#&][^ :]+\\) *" top1)
  8740.           (subfield top1 1)
  8741.           irc-channel)))
  8742.     (if (not irc-called-from-buffer)
  8743.     (progn (irc-insert "")
  8744.            (irc-insert "/TOPIC %s %s" chn top)))
  8745.     (cond ((string= "0" chn)
  8746.        (irc-insert "%%You aren't on any channel."))
  8747.       ((and (irc-is-multijoinable-channel chn)
  8748.         (irc-server-has-settable-topic-on-multijoinable-channel))
  8749.        (if (string-match "^ *$" top)
  8750.            (irc-send (concat "TOPIC " chn))
  8751.            (irc-send (concat "TOPIC " chn " :" top))))
  8752.       ((irc-is-multijoinable-channel irc-channel)
  8753.        (irc-insert "%%Can't set the topic of a #channel."))
  8754.       (t (irc-send (concat "TOPIC :" top)))))
  8755.   (setq irc-idle-last-sent (irc-current-time)))
  8756.  
  8757.  
  8758. (defun irc-execute-oper (oper)
  8759.   "Usage: /OPER [ name [ password ]]
  8760.  
  8761. Attempt to become an IRC Operator.  Can take the name of the operator
  8762. and the password as arguments.  If name is missing then it will be read
  8763. from the minibuffer; if password is missing it will be read and hidden
  8764. in the minibuffer.
  8765.  
  8766. If you become an operator then the word \"operator\" will appear in the
  8767. minibuffer along with the mode name."
  8768.   (interactive '(""))
  8769.   (let* ((pair (cond
  8770.          ((string-match "^ *\\([^: ]+\\) +" oper)
  8771.           (cons (subfield oper 1) (substring oper (match-end 0))))
  8772.          ((string-match "^ *\\([^: ]+\\) *$" oper)
  8773.           (cons (subfield oper 1) ""))
  8774.          (t (cons "" ""))))
  8775.      (n (car pair))
  8776.      (n1 (if (string= "" n)
  8777.          (read-string (concat "Operator name at server "
  8778.                       (upcase irc-server)
  8779.                       "? "))
  8780.          n))
  8781.      (name (irc-nuke-whitespace n1))
  8782.      (p (irc-nuke-whitespace (cdr pair)))
  8783.      (p1 (if (and (string= "" p) (string< "" name))
  8784.          (irc-read-passwd (concat "Password for operator "
  8785.                       name
  8786.                       " at server "
  8787.                       (upcase irc-server)
  8788.                       "? "))
  8789.          p))
  8790.      (password (irc-nuke-whitespace p1)))
  8791.     (cond ((string= "" name)
  8792.        (irc-insert "%%No operator name given."))
  8793.       ((string= "" password)
  8794.        (irc-insert "%%No password given."))
  8795.       (t (if (not irc-called-from-buffer)
  8796.          (progn (irc-insert "")
  8797.             (irc-insert "/OPER ...")))
  8798.          (irc-send (concat "OPER " name " " password)))))
  8799.   (setq irc-idle-last-sent (irc-current-time)))
  8800.  
  8801.  
  8802. (defun irc-execute-summon (user)
  8803.   "Usage: /SUMMON login-name@server
  8804.  
  8805. Summon a user not on IRC to join IRC.  The argument provided may either be
  8806. a user name on the local machine or user@server, where server is another
  8807. machine on the IRC-net.  The user must be signed on to the specified server."
  8808.   (interactive '(""))
  8809.   (let* ((pair (cond ((string-match (concat "^ *\\([^ @]*\\) *@ *"
  8810.                         "\\([^ @]*\\) *$")
  8811.                     user)
  8812.               (cons
  8813.                (substring user (match-beginning 1) (match-end 1))
  8814.                (substring user (match-beginning 2) (match-end 2))))
  8815.              ((string-match "^ *\\([^ @]*\\) *$" user)
  8816.               (cons
  8817.                (substring user (match-beginning 1) (match-end 1))
  8818.                ""))
  8819.              (t (cons "" ""))))
  8820.      (login (irc-nuke-whitespace
  8821.          (if (and (string= "" (car pair)) (not irc-called-from-buffer))
  8822.              (read-string "Login-name of person to summon? ")
  8823.              (car pair))))
  8824.      (s (irc-nuke-whitespace
  8825.          (if (and (not (string= "" login))
  8826.               (string= "" (cdr pair))
  8827.               (not irc-called-from-buffer))
  8828.          (irc-read-object (format "Server \"%s\" is on? " login)
  8829.                   ""
  8830.                   (irc-recall-all 'irc-servernames))
  8831.          (cdr pair))))
  8832.      (server (if (string= "" s) irc-server s)))
  8833.     (if (string= "" login)
  8834.     (irc-insert "%%No login name given.")
  8835.     (progn (if (not irc-called-from-buffer)
  8836.            (progn (irc-insert "")
  8837.               (irc-insert "/SUMMON %s@%s" login server)))
  8838.            (irc-send (concat "SUMMON " login "@" server)))))
  8839.   (setq irc-idle-last-sent (irc-current-time)))
  8840.  
  8841.  
  8842. (defun irc-execute-users (host)
  8843.   "Usage: /USERS [ server ]
  8844.  
  8845. Get a list of the users signed on to \"server\".  If no server name is provided
  8846. then the server to which you are connected is used.  When called interactively
  8847. a prefix argument means to prompt for the server to query."
  8848.   (interactive '(""))
  8849.   (let* ((h (irc-nuke-whitespace
  8850.          (if (and (string= "" host) (not irc-called-from-buffer))
  8851.          (irc-read-object (format (concat "List users on which host?"
  8852.                           " (RET for %s) ")
  8853.                       irc-server)
  8854.                   ""
  8855.                   (irc-recall-all 'irc-servernames))
  8856.          host)))
  8857.      (hst (if (string= "" h) irc-server h)))
  8858.     (if (not irc-called-from-buffer)
  8859.     (progn (irc-insert "")
  8860.            (irc-insert "/USERS %s" hst)))
  8861.     (irc-send (concat "USERS " hst)))
  8862.   (setq irc-idle-last-sent (irc-current-time)))
  8863.  
  8864.  
  8865. (defun irc-execute-ignore (user)
  8866.   "Usage: /IGNORE username@host [event]
  8867.  
  8868. Used to ignore a user. The first argument is a specification of whose messages
  8869. to ignore. The second specifies which kind of messages should be ignored from
  8870. that particular user.
  8871.  
  8872. When specifying a user, you can give either just the user's login name at the
  8873. remote site (you can see what it is by doing a /whois), or you can give the
  8874. user's login name followed by a @ and the name of the user's and the host of
  8875. the user (i.e. the name of host the user's client is running on). You can give
  8876. a * instead of a username to ignore everyone at the given client machine.
  8877.  
  8878. One can either ignore all signs of the user, or just certain events. The events
  8879. include
  8880.     CTCP-ANSWER = Don't display any client to client protocol answers (they
  8881.                   *might* be spurios). Also, don't react on erronous answers.
  8882.     CTCP-QUERY  = Neither display nor answer any client to client protocoll
  8883.                   questions from the user.
  8884.     INVITE      = Don't display 
  8885.     JOIN
  8886.     NICK
  8887.     NOTICE
  8888.     PART
  8889.     PRIVMSG
  8890.     QUIT
  8891.     channel
  8892.     
  8893. THIS IS ALL NOT YET IMPLEMENTED.
  8894.  
  8895. "
  8896.   (interactive '(""))
  8897.   (let ((usr (irc-nuke-whitespace
  8898.           (if (and (string= "" user) (not irc-called-from-buffer))
  8899.           (irc-read-object "Ignore which user? (RET to view) "
  8900.                    user
  8901.                    (irc-recall-all 'irc-nicknames))
  8902.           user))))
  8903.     (if (string= "" usr)
  8904.     (if (not (irc-nothing-remembered-p 'irc-ignored-ppl))
  8905.         (irc-insert "%sYou are currently ignoring %s%s"
  8906.             irc-msg-info-pre
  8907.             (irc-subst-comma (mapconcat
  8908.                       'eval
  8909.                       (irc-recall-all 'irc-ignored-ppl)
  8910.                       ", ")
  8911.                      "and")
  8912.             irc-msg-info-post)
  8913.         (irc-insert "%sYou are not ignoring anyone%s"
  8914.             irc-msg-info-pre
  8915.             irc-msg-info-post))
  8916.     (progn (irc-remember usr 'irc-ignored-ppl)
  8917.            (irc-insert "%sYou are now ignoring %s%s"
  8918.                irc-msg-info-pre
  8919.                usr
  8920.                irc-msg-info-post))))
  8921.   (setq irc-idle-last-sent (irc-current-time)))
  8922.  
  8923.  
  8924. (defun irc-execute-info (nick)
  8925.   "Usage: /INFO nick
  8926.  
  8927. With * as the argument, show some information about who built IRC.
  8928. Else query a users client and show the information she/he has given
  8929. about her/himself. With no argument, show the information you have
  8930. given about yourself. You can set the information with the command
  8931. /USERINFO."
  8932.   (interactive '(""))
  8933.   (let* ((name (irc-nuke-whitespace
  8934.         (if (and (string= "" nick) (not irc-called-from-buffer))
  8935.             (irc-read-object
  8936.              (concat "Info for which user or server? (RET"
  8937.                  " for yourself, * for server program)"
  8938.                  " ")
  8939.              ""
  8940.              (irc-get-names-and-servers))
  8941.             nick))))
  8942.     (cond ((and (string= "" name)
  8943.         (stringp irc-userinfo))
  8944.        (let* ((pre (concat irc-msg-info-pre "You have "))
  8945.           (irc-msg-cont-used (make-string (length pre) ? )))
  8946.          (irc-insert (concat "%sgiven the information \"%s\" about"
  8947.                  " yourself. Use /USERINFO to change it."
  8948.                  " (Warning: /USERINFO with no argument will"
  8949.                  " clear the information)%s")
  8950.              pre
  8951.              irc-userinfo
  8952.              irc-msg-info-post)))
  8953.       ((string= "" name)
  8954.        (let* ((pre (concat irc-msg-info-pre "You haven't "))
  8955.           (irc-msg-cont-used (make-string (length pre) ? )))
  8956.          (irc-insert (concat "%sgiven any information about"
  8957.                  " yourself yet. Use /USERINFO to do so%s")
  8958.              pre
  8959.              irc-msg-info-post)))
  8960.       ((string= "*" name)
  8961.        (if (not irc-called-from-buffer)
  8962.            (progn (irc-insert "")
  8963.               (irc-insert "/INFO *")))
  8964.        (irc-send "INFO"))
  8965.       ((irc-is-receiver name)
  8966.        (if (not irc-called-from-buffer)
  8967.            (progn (irc-insert "")
  8968.               (irc-insert (concat "/INFO " name))))
  8969.        (irc-insert (concat "%sQuerying client of user %s for user supplied"
  8970.                    " information%s")
  8971.                irc-msg-info-pre name irc-msg-info-post)
  8972.        (irc-send (format "WHOIS %s %s" name name)) ;Get names servers idea
  8973.                     ;of names idle time.
  8974.        (irc-send
  8975.         (concat "PRIVMSG "
  8976.             name
  8977.             " :\001FINGER\001"
  8978.             "\001VERSION\001"
  8979.             "\001USERINFO\001"
  8980.             "\001SOURCE\001")))
  8981.       ((irc-is-hostname name)
  8982.        (if (not irc-called-from-buffer)
  8983.            (progn (irc-insert "")
  8984.               (irc-insert (concat "/ADMIN " name))))
  8985.        (irc-send (concat "ADMIN " name)))
  8986.       (t (irc-insert "%%Can't be a users nickname: \"%s\"." name))))
  8987.   (setq irc-idle-last-sent (irc-current-time)))
  8988.  
  8989.  
  8990. (defun irc-execute-userinfo (information)
  8991.   "Usage: /USERINFO [information]
  8992.  
  8993. Set some information (any text you want) to be given out to anybody
  8994. querying this client for it. With no argument, remove all information
  8995. you have given about yourself, making further queries \"draw a
  8996. blank\". You can use /INFO to query other clients. Be warned though,
  8997. other clients may or may not know of this query so you may sometimes
  8998. get back no answer or strange responses."
  8999.   (interactive '(""))
  9000.   (let ((info (if (and (string= "" information) (not irc-called-from-buffer))
  9001.           (read-string (concat "What information do you wish to"
  9002.                        " disclose? (RET to remove) "))
  9003.           information)))
  9004.     (let ((inf (irc-nuke-whitespace info)))
  9005.       (cond ((string= "" inf)
  9006.          (setq irc-userinfo nil)
  9007.          (irc-insert "%sCleared your information string%s"
  9008.              irc-msg-info-pre irc-msg-info-post))
  9009.         (t (setq irc-userinfo inf)
  9010.            (irc-insert "%sThe information string is: \"%s\"%s"
  9011.                irc-msg-info-pre
  9012.                irc-userinfo
  9013.                irc-msg-info-post)))))
  9014.   (setq irc-idle-last-sent (irc-current-time)))
  9015.  
  9016.  
  9017. (defun irc-execute-kill (user-etc)
  9018.   "Usage: /KILL user comment
  9019.  
  9020. Forcibly remove a user from IRC. The mandotory comment will be displayed to
  9021. the victim and to all the IRC operators online. The topic should be in English,
  9022. which after all is the lingua franca of IRC.
  9023.  
  9024. This command is reserved for IRC operators."
  9025.   (interactive '(""))
  9026.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\(.\\|\n\\)+ *$"
  9027.                     user-etc)
  9028.               (cons (subfield user-etc 1) (subfield user-etc 2)))
  9029.              ((string-match "^ *\\([^ ]+\\) *$" user-etc)
  9030.               (cons (subfield user-etc 1) ""))
  9031.              (t (cons "" ""))))
  9032.      (u (irc-nuke-whitespace (car pair)))
  9033.      (user (irc-nuke-whitespace
  9034.         (if (and (string= "" u) (not irc-called-from-buffer))
  9035.             (irc-read-object "Nuke which user? "
  9036.                      ""
  9037.                      (irc-recall-all 'irc-nicknames))
  9038.             u)))
  9039.      (c (irc-nuke-whitespace (cdr pair)))
  9040.      (comm (irc-nuke-whitespace
  9041.         (if (and (string= "" c)
  9042.              (string< "" user)
  9043.              (not irc-called-from-buffer))
  9044.             (read-string "Comment? (In English please) ")
  9045.             c))))
  9046.     (if (string< "" user)
  9047.     (if (string< "" comm)
  9048.         (progn (if (not irc-called-from-buffer)
  9049.                (progn (irc-insert "")
  9050.                   (irc-insert "/KILL %s %s" user comm)))
  9051.            (irc-send (concat "KILL " user " " comm)))
  9052.         (irc-insert "%%No comment given to /KILL command."))
  9053.     (irc-insert "%%No user given, no killing take place.")))
  9054.   (setq irc-idle-last-sent (irc-current-time)))
  9055.  
  9056.  
  9057. (defun irc-execute-invite (user)
  9058.   "Usage: /INVITE user [ channel ]
  9059.  
  9060. Ask \"user\" on IRC to join \"channel\".  If channel is 0, * or not provided
  9061. then the invitation de faults to your current channel, ie the on you're talking
  9062. to. If you are not talking to any channel and channel is 0 or not provided then
  9063. no invitation is sent -- you can't invite someone to \"go private\". When
  9064. called interactively, channel is set to the prefix argument; with no argument
  9065. or - the current channel is assumed."
  9066.   (interactive '(""))
  9067.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$"
  9068.                     user)
  9069.               (cons
  9070.                (substring user (match-beginning 1) (match-end 1))
  9071.                (substring user (match-beginning 2) (match-end 2))))
  9072.              ((string-match " *\\([^ ]+\\) *$" user)
  9073.               (cons (substring user (match-beginning 1) (match-end 1))
  9074.                 ""))
  9075.              (t (cons "" ""))))
  9076.      (usr (irc-nuke-whitespace
  9077.            (if (and (string= "" (car pair)) (not irc-called-from-buffer))
  9078.            (irc-read-object "Invite which user? "
  9079.                     ""
  9080.                     (irc-recall-all 'irc-nicknames))
  9081.            (car pair))))
  9082.      (c1 (irc-nuke-whitespace
  9083.           (if (and (string= "" (cdr pair))
  9084.                (string< "" usr)
  9085.                (not irc-called-from-buffer))
  9086.           (irc-read-object
  9087.            (if (string= "0" irc-channel)
  9088.                (format "Invite \"%s\" to which channel? " usr)
  9089.                (format "Invite \"%s\" %s \"%s\") "
  9090.                    usr
  9091.                    "to which channel? (RET for"
  9092.                    irc-channel))
  9093.            ""
  9094.            (irc-recall-all 'irc-subscribed-channels))
  9095.           (cdr pair))))
  9096.      (chn (if (string= "" c1) irc-channel c1)))
  9097.     (cond ((string= "" usr) (irc-insert "%%No users nick given."))
  9098.       ((string= "0" chn) (irc-insert "%%Can't invite to \"channel\" 0."))
  9099.       (t (if (not irc-called-from-buffer)
  9100.          (progn (irc-insert "")
  9101.             (irc-insert "/INVITE %s %s"
  9102.                     usr
  9103.                     (irc-clean-up-message chn))))
  9104.          (irc-send (format "INVITE %s %s" usr chn)))))
  9105.   (setq irc-idle-last-sent (irc-current-time)))
  9106.  
  9107.  
  9108. (defun irc-execute-names (channel)
  9109.   "Usage: /NAMES [ channel ]
  9110.  
  9111. Show which channels everyone is on.  Optional argument \"channel\" means
  9112. to show just the users on that channel.  * means to show people on the
  9113. current channel.
  9114.  
  9115. Each line starts with a column for the channel number and is followed
  9116. by the nicknames of the people on that channel.  Users who are on
  9117. private channels or who are not on any channel are listed as
  9118. \"Private\".  Users who are on secret channels (channels less than 0)
  9119. are not shown at all.  A %-sign is appended to the current channel's
  9120. name or number."
  9121.   (interactive '(""))
  9122.   (let* ((c (if (and (string= "" channel) (not irc-called-from-buffer))
  9123.          (irc-read-object (format
  9124.                   "Names of persons on which channel? (%s) "
  9125.                   (if (string= "0" irc-channel)
  9126.                       "RET for all"
  9127.                       (concat "RET for all, * for "
  9128.                           irc-channel)))
  9129.                  ""
  9130.                  (irc-recall-all 'irc-subscribed-channels))
  9131.         channel))
  9132.      (chn (if (string= "*" c) irc-channel c)))
  9133.     (if (string= "" chn)
  9134.      (let ((lst (irc-recall-all 'irc-services)))
  9135.       (irc-forget-all 'irc-nicknames)
  9136.       (while lst
  9137.         (irc-remember (car lst) 'irc-nicknames)
  9138.         (setq lst (cdr lst)))))
  9139.     (if (not irc-called-from-buffer)
  9140.      (progn (irc-insert "")
  9141.            (irc-insert "/NAMES %s" chn)))
  9142.     (irc-send (concat "NAMES " chn))
  9143.     (if (not (and (irc-terminal-is-slow)
  9144.           (irc-server-has-end-of-names)))
  9145.     (progn (irc-insert "")
  9146.            (irc-insert "Name of channel Users Nicknames")
  9147.            (irc-insert "--------------- ----- ---------")
  9148.            (set-buffer-modified-p (buffer-modified-p)))))
  9149.   (setq irc-idle-last-sent (irc-current-time)))
  9150.  
  9151.  
  9152. (defun irc-execute-wall (message)
  9153.   "Usage: /WALL message
  9154.  
  9155. Send 'message' to everyone on IRC.  This can only be done by IRC Operators."
  9156.   (interactive '(""))
  9157.   (let ((msg (if (and (string= "" message) (not irc-called-from-buffer))
  9158.          (read-string "Message to send to everyone? ")
  9159.          message)))
  9160.     (if (string= "" msg)
  9161.     (irc-insert "%%No message.")
  9162.     (if (not irc-called-from-buffer)
  9163.         (progn (irc-insert "")
  9164.            (irc-insert "/WALL %s" msg)))
  9165.     (irc-send (concat "WALL " msg))))
  9166.   (setq irc-idle-last-sent (irc-current-time)))
  9167.  
  9168.  
  9169. (defun irc-execute-wallops (message)
  9170.   "Usage: /WALLOPS message
  9171.  
  9172. Send 'message' to every enabled IRC-operator on IRC.
  9173. If you got any problems you think an enabled IRC operator might be the right
  9174. person to help you with, *use* /WALLOPS. (But please don't *ABuse* it)."
  9175.   (interactive '(""))
  9176.   (let ((msg (if (and (string= "" message) (not irc-called-from-buffer))
  9177.          (read-string "Message to send to all enabled IRC operators? ")
  9178.          message)))
  9179.     (if (string< "" msg)
  9180.     (let ((data (format irc-msg-sent "all ENABLED operators of IRC")))
  9181.       (if (not irc-called-from-buffer)
  9182.           (progn (irc-insert "")
  9183.              (irc-insert "/WALLOPS %s" msg)))
  9184.       (irc-send (concat "WALLOPS " msg))
  9185.       (if irc-confirm
  9186.           (irc-insert "%s%s" (make-string
  9187.                   (max 0 (- (window-width
  9188.                          (get-buffer-window
  9189.                           (current-buffer)))
  9190.                         (length data)
  9191.                         1))
  9192.                   ? )
  9193.               data)))
  9194.     (irc-insert "%%No message given, no message sent.")))
  9195.   (setq irc-idle-last-sent (irc-current-time)))
  9196.  
  9197.  
  9198. (defun irc-execute-rehash (cruft)
  9199.   "Usage: /REHASH
  9200.  
  9201. Force the server to which you are connected to reread it's irc.conf file.
  9202. Arguments are ignored.  This command is only available to IRC Operators."
  9203.   (interactive '(""))
  9204.   (if (not irc-called-from-buffer)
  9205.       (progn (irc-insert "")
  9206.          (irc-insert "/REHASH")))
  9207.   (irc-send "REHASH")
  9208.   (setq irc-idle-last-sent (irc-current-time)))
  9209.  
  9210.  
  9211. (defun irc-execute-trace (server)
  9212.   "Usage: /TRACE [ server ]
  9213.  
  9214. Find the route from the server to which you are attached to 'server'; if the
  9215. server argument is not provided then the servers to which the current server
  9216. is directly connected are listed.  This command is only available to IRC
  9217. Operators."
  9218.   (interactive '(""))
  9219.   (let ((srvr (if (and (string= "" server) (not irc-called-from-buffer))
  9220.           (irc-read-object (concat "Trace route to server/user?"
  9221.                        " (RET for " irc-server ") ")
  9222.                    ""
  9223.                    (irc-get-names-and-servers))
  9224.           server)))
  9225.     (if (not irc-called-from-buffer)
  9226.     (progn (irc-insert "")
  9227.            (irc-insert "/TRACE %s" srvr)))
  9228.     (irc-send (concat "TRACE " srvr)))
  9229.   (setq irc-idle-last-sent (irc-current-time)))
  9230.  
  9231.  
  9232. (defun irc-execute-squit (server)
  9233.   "Usage: /SQUIT [ server ]
  9234.  
  9235. Shut down a server-to-server link.
  9236. The link shut down is the the one next farest away from you, ie if you do a
  9237. /SQUIT BYE.EDU and the path to it is your.server.edu!a!b!bye.edu, then the
  9238. link between b and bye.edu will be disconnected.
  9239.  
  9240. You have to be an enabled IRC operator to issue this conmmand."
  9241.   (interactive '(""))
  9242.   (let ((srvr (if (and (string= "" server) (not irc-called-from-buffer))
  9243.           (irc-read-object "Shut down link to which server? "
  9244.                    ""
  9245.                    (irc-recall-all 'irc-servernames))
  9246.           server)))
  9247.     (if (not irc-called-from-buffer)
  9248.     (progn (irc-insert "")
  9249.            (irc-insert "/SQUIT %s" srvr)))
  9250.     (irc-send (concat "SQUIT " srvr))
  9251.     (irc-insert "%sClosing the link to server %s%s"
  9252.         irc-msg-info-pre srvr irc-msg-info-post))
  9253.   (setq irc-idle-last-sent (irc-current-time)))
  9254.  
  9255.  
  9256. (defun irc-execute-connect (new)
  9257.   "Usage: /CONNECT [ newhost [ port [remoteserver ] ] ]
  9258.  
  9259. Connect the local server to SERVER on tcp-port PORT.
  9260.  
  9261. You have to be an enabled IRC operator to issue this conmmand."
  9262.   (interactive '(""))
  9263.   (let* ((tri (cond ((string-match
  9264.               (concat "^ *\\([^ ]+\\) +\\([^ ]+\\) +"
  9265.                   "\\([^ ]+\\) *$")
  9266.               new)
  9267.              (cons (subfield new 1)
  9268.                (cons (subfield new 2)
  9269.                  (subfield new 3))))
  9270.             ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$"
  9271.                    new)
  9272.              (cons (subfield new 1)
  9273.                (cons (subfield new 2)
  9274.                  "")))
  9275.             ((string-match "^ *\\([^ ]+\\) *$" new)
  9276.              (cons (subfield new 1) (cons "" "")))
  9277.             (t (cons "" (cons "" "")))))
  9278.      (h1 (car tri))
  9279.      (h2 (if (and (string= "" h1) (not irc-called-from-buffer))
  9280.          (irc-read-object (concat "Connect server-link to which"
  9281.                       " internet host? ")
  9282.                   ""
  9283.                   (irc-recall-all 'irc-servernames))
  9284.          h1))
  9285.      (new-host (irc-nuke-whitespace h2))
  9286.      (p1 (car (cdr tri)))
  9287.      (p2 (if (and (string= "" p1)
  9288.               (string< "" new-host)
  9289.               (not irc-called-from-buffer))
  9290.          (irc-read-object (concat "Use which TCP-port for"
  9291.                       " server-link? (RET for 6667) ")
  9292.                   ""
  9293.                   (list "194" "6667"))
  9294.          p1))
  9295.      (p3 (irc-nuke-whitespace p2))
  9296.      (new-port (if (string= "" p3)
  9297.                6667 
  9298.                (string-to-int p3)))
  9299.      (s1 (cdr (cdr tri)))
  9300.      (s2 (if (and (string= "" s1)
  9301.               (string< "" new-host)
  9302.               (not irc-called-from-buffer))
  9303.          (irc-read-object (concat "Execute connect command at which"
  9304.                       " (reachable) server? (RET for"
  9305.                       " local) ")
  9306.                   ""
  9307.                   (irc-recall-all 'irc-servernames))
  9308.          s1))
  9309.      (s3 (irc-nuke-whitespace s2))
  9310.      (remote-server (if (string= "" s3) irc-server s3)))
  9311.     (cond ((string-match " " new-host)
  9312.        (irc-insert "%%Spaces aren't allowed in hostnames (%s)." new-host))
  9313.       ((string-match " " remote-server)
  9314.        (irc-insert "%%Spaces aren't allowed in servername (%s)."
  9315.                remote-server))
  9316.       (t (if (not irc-called-from-buffer)
  9317.          (progn (irc-insert "")
  9318.             (if (string= "" new-host)
  9319.                 (irc-insert "/CONNECT")
  9320.                 (irc-insert "/CONNECT %s %d %s"
  9321.                     new-host new-port remote-server))))
  9322.          (if (string= "" new-host)
  9323.          (irc-insert "%%No host to connect too given.")
  9324.          (irc-send (format "CONNECT %s %d %s"
  9325.                    new-host new-port remote-server))
  9326.          (irc-insert (concat "%sConnecting a server-link to host %s on"
  9327.                      " port %d from server %s%s")
  9328.                  irc-msg-info-pre
  9329.                  (upcase new-host)
  9330.                  new-port
  9331.                  (upcase remote-server)
  9332.                  irc-msg-info-post)))
  9333.       (setq irc-idle-last-sent (irc-current-time)))))
  9334.  
  9335. ;; /command just for the client  (need /stamp /alias /unalias)
  9336. (defun irc-execute-send (slist)
  9337.   "Usage: /SEND [ sendlist | - ]
  9338.  
  9339. Set the default sendlist for IRC messages.  This is a comma separated list
  9340. of the intended recipient(s) of messages which do not have an explicit
  9341. sendlist.  '-' as an argument means to disable the default sendlist; every
  9342. message sent then must have an explicit recipient provided with the message.
  9343. Without any arguments this command just displays the current default sendlist.
  9344.  
  9345. Each item specified is checked to see whether you can send there; ambiguous
  9346. references to users are not allowed.
  9347.  
  9348. \"*\" is always allowed and means to send to the current channel, ie the
  9349. channel you are talking to.
  9350. If no item in the new list can be set then the sendlist is not changed."
  9351.   (interactive "sDefault recipient(s) for messages? ")
  9352.   ;; blast some whitespace
  9353.   (setq slist (irc-nuke-whitespace slist))
  9354.   (let (matches)
  9355.     ;; first the easiest case
  9356.     (if (string= "-" slist) (setq irc-default-to nil)
  9357.     (setq matches
  9358.           (delq nil                   ; more indentation fun.  can someone
  9359.             (mapcar               ; recommend a good style manual?
  9360.              (function (lambda (arg)
  9361.                (setq matches (irc-check-list
  9362.                       (irc-recall-all 'irc-nicknames)
  9363.                       arg))
  9364.                (cond
  9365.              ((string= arg "*") arg)
  9366.              ((string= arg "0")
  9367.               (irc-insert "%%You can't send to channel 0.")
  9368.               nil)
  9369.              ((= (length matches) 1) (car matches))
  9370.              ((eq matches nil)
  9371.               (irc-insert "%%No names found to match \"%s\"." arg)
  9372.               nil)
  9373.              (t (irc-insert (concat "%%Ambiguous recipient %s;"
  9374.                         " could be %s.")
  9375.                     arg
  9376.                     (irc-subst-comma
  9377.                      (mapconcat (function (lambda (arg)
  9378.                               (concat "\"" arg "\"")))
  9379.                             matches
  9380.                             ", ")
  9381.                      "or"))
  9382.                 nil))))
  9383.              (irc-burst-comma slist))))
  9384.     (if matches
  9385.         (setq irc-default-to (concat (mapconcat 'eval matches ",") ";"))
  9386.         (or (string= "" slist)  ; only print the error if tried to set it.
  9387.         (irc-insert "%%No matches -- sendlist not changed."))))
  9388.     (cond ((not irc-default-to)
  9389.        (irc-insert (concat "%%Your default sendlist is disabled. (Ie you"
  9390.                    " are not sending to anyone when failing to"
  9391.                    " give an explicit receiver)")))
  9392.       ((string= irc-default-to "*;")
  9393.        (irc-insert (concat "%sYou are now using the default send list (ie"
  9394.                    " sending to the current channel (%s) when"
  9395.                    " failing to give an explicit receiver)%s")
  9396.                irc-msg-info-pre
  9397.                (if (string= "0" irc-channel) "none" irc-channel)
  9398.                irc-msg-info-post))
  9399.       (t (irc-insert (concat "%sYou are sending to %s, use /SEND * to"
  9400.                  " get back default sendlist%s")
  9401.              irc-msg-info-pre
  9402.              (irc-subst-comma
  9403.               (mapconcat 'eval
  9404.                      (irc-burst-comma
  9405.                       (substring irc-default-to 0
  9406.                          (1- (length irc-default-to))))
  9407.                      ", ")
  9408.               "and")
  9409.              irc-msg-info-post))))
  9410.   (setq irc-idle-last-sent (irc-current-time)))
  9411.  
  9412.  
  9413. (defun irc-execute-service (service)
  9414.   "Usage: /SERVICE [ [+]nick | -nick ]
  9415.  
  9416. Show or update list of services. A service is an automaton which looks
  9417. like a normal user, ie it has a nickname. It doesn't act as a normal
  9418. user though; normaly you can ask it for some service. For instance, at
  9419. NICKSERV you can register your nick name (do \"nickserv; help\" for
  9420. more information). Services often talk to you with so called NOTICE's.
  9421. When a service isn't marked as being one, these messages will be
  9422. displayed in a somewhat annoying format. Use this command to get a
  9423. nicer display.
  9424.  
  9425. With no argument, show which nicknames are assumed to be services."
  9426.   (interactive '(""))
  9427.   (let* ((pair (cond ((string-match (concat "^ *\\(+\\|-\\) *"
  9428.                         "\\([^ ]+\\) *$")
  9429.                     service)
  9430.               (cons (subfield service 1) (subfield service 2)))
  9431.              ((string-match "^ *\\([^ ]+\\) *$" service)
  9432.               (cons "+" (subfield service 1)))
  9433.              (t (cons "" ""))))
  9434.      (a (car pair))
  9435.      (a2 (irc-nuke-whitespace
  9436.           (if (and (string= "" a) (not irc-called-from-buffer))
  9437.           (irc-read-object (concat "Mark or unmark nick as"
  9438.                        " service? (RET to mark) ")
  9439.                    ""
  9440.                    '("mark" "unmark"))
  9441.           a)))
  9442.      (action (if (string-match "\\(unmark\\|-\\)" (downcase a2)) nil t))
  9443.      (n (cdr pair))
  9444.      (nick (irc-nuke-whitespace
  9445.         (if (and (string= "" n) (not irc-called-from-buffer))
  9446.             (irc-read-object (format "%sark which %s as service? (%s) "
  9447.                          (if action "M" "Unm")
  9448.                          (if action "nick" "service")
  9449.                          "RET to view existing")
  9450.                      ""
  9451.                      (if action
  9452.                      (irc-recall-all 'irc-nicknames)
  9453.                      (irc-recall-all 'irc-services)))
  9454.             n)))
  9455.      (s-list (irc-recall-all 'irc-services))
  9456.      (s-len (length s-list))
  9457.      (plural (if (= 1 s-len) "" "s"))
  9458.      (lst (irc-listify s-list ", " "and")))
  9459.     (if (not irc-called-from-buffer)
  9460.     (progn (irc-insert "")
  9461.            (irc-insert "/SERVICE %s%s" (if action "+" "-") nick)))
  9462.     (if (string= "" nick)
  9463.     (if (irc-nothing-remembered-p 'irc-services)
  9464.         (irc-insert "%sNo users marked as automatons%s"
  9465.             irc-msg-info-pre irc-msg-info-post)
  9466.         (irc-insert (concat "%s%d \"user%s\" marked as being"
  9467.                 " automaton%s (which provide some service):"
  9468.                 " %s%s")
  9469.             irc-msg-info-pre s-len plural plural lst
  9470.             irc-msg-info-post))
  9471.     (let ((irc-called-from-buffer t))
  9472.       (irc-insert "%s%sing \"%s\" %s being treated as a service%s"
  9473.               irc-msg-info-pre
  9474.               (if action "Add" "Remov")
  9475.               nick
  9476.               (if action "as" "from")
  9477.               irc-msg-info-post)
  9478.       (if action
  9479.           (irc-remember nick 'irc-services)
  9480.           (irc-forget nick 'irc-services))
  9481.       (irc-execute-service ""))))
  9482.   (setq irc-idle-last-sent (irc-current-time)))
  9483.  
  9484.  
  9485. (defun irc-execute-event (events)
  9486.   "Usage: /EVENT [ [+]event | -event ] [...]
  9487.  
  9488. Set the list of events to notify you about with a message.  Notification
  9489. is a one-line message inserted when someone causes that event to occur.
  9490. Events are added with +event or simply event; they are removed with -event.
  9491. + adds all supported events and - removes all supported events.  More than
  9492. one event can be specified in the arguments.  In case of conflict, the argument
  9493. which appears later overrides the argument with which it conflicts.
  9494.  
  9495. Currently supported by /EVENT are the \"ctcp\", \"join\", \"nick\", \"quit\"
  9496. and \"topic\" events.
  9497.  
  9498. CTCP happens whenever someone send you a CTCP query.
  9499. Join happens whenever someone enters or leaves a channel which you are on.
  9500. Nick occurs when someone changes nicknames; recognition of this event is
  9501. currently limited to when the person making the change is on the same channel
  9502. as you.
  9503. Quit happens when someone quits from IRC and you see it.
  9504. Topic happens when the topic of a channel you listen to is changed.
  9505.  
  9506.  
  9507. "
  9508.   (interactive "sNotify for events: ")
  9509.   ;; die scurvy whitespace
  9510.   (setq events (irc-nuke-whitespace events))
  9511.   (let ((recog '(ctcp join nick quit topic))
  9512.     (str events)
  9513.     sym
  9514.     off
  9515.     event
  9516.     (count 0))
  9517.     (while (string< "" events)
  9518.       ;; multiple args are okay.  we'll do one at a time.
  9519.       (setq str (substring events 0 (or (string-match " +" events)
  9520.                     (string-match "$" events)))
  9521.         events (substring events (match-end 0)))
  9522.       (string-match "^\\([---+]?\\)" str)
  9523.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  9524.         event (substring str (match-end 0))
  9525.         sym (if (string= "" event) nil
  9526.             (car (delq nil    ; do some minor pattern matching
  9527.                    (mapcar    ; to find the intended event
  9528.                 (function
  9529.                  (lambda (arg)
  9530.                   (if (string-match
  9531.                        (concat "^" (regexp-quote event))
  9532.                        (prin1-to-string arg))
  9533.                       arg))) recog)))))
  9534.       (cond
  9535.     ((and (string= "" event) off) (setq irc-events nil))
  9536.     ;; the only way for this to happen and not the above is str == "+"
  9537.     ((string= "" event) (setq irc-events recog))
  9538.     ((null sym)
  9539.      (irc-insert "%sEvent: Unknown argument \"%s\"%s"
  9540.              irc-msg-info-pre
  9541.              event
  9542.              irc-msg-info-post))
  9543.     (t (setq irc-events (if off (delq sym irc-events)
  9544.                   (if (not (memq sym irc-events)) ; avoid
  9545.                       (cons sym irc-events) ; redundancy
  9546.                       irc-events))))))
  9547.     (if irc-events
  9548.     (irc-insert "%sEvent notification is currently enabled for %s%s"
  9549.             irc-msg-info-pre
  9550.             (irc-subst-comma (mapconcat 'prin1-to-string irc-events
  9551.                         ", ") "and")
  9552.             irc-msg-info-post)
  9553.     (irc-insert "%sNotification is currently disabled%s"
  9554.             irc-msg-info-pre
  9555.             irc-msg-info-post)))
  9556.   (setq irc-idle-last-sent (irc-current-time)))
  9557.  
  9558.  
  9559. (defun irc-execute-confirm (str)
  9560.   "Usage: /CONFIRM [ + | - ]
  9561.  
  9562. Turn on message confirmation with + or off with -.  Any other arguments or no
  9563. arguments just gives a message about the current setting.
  9564.  
  9565. Message confirmation is a line indicating to whom a message was sent.
  9566. Occasionally this will say that a message has been sent to someone who
  9567. was not present but another message soon after will set the record straight."
  9568.   (interactive '(""))
  9569.   (let* ((c1 (irc-nuke-whitespace
  9570.           (if (and (string= "" str) (not irc-called-from-buffer))
  9571.           (irc-read-object "Turn confirm on or off? (RET to view) "
  9572.                    ""
  9573.                    '("+" "on" "-" "off"))
  9574.           str)))
  9575.      (conf (cond ((string-match "^\\(on\\|+\\)$" c1) "+")
  9576.              ((string-match "^\\(off\\|-\\)$" c1) "-")
  9577.              ((string= "" c1) "")
  9578.              (t nil))))
  9579.     (if (not conf)
  9580.     (irc-insert "%Huh? Try /HELP CONFIRM.")
  9581.     (progn (if (string= "+" conf) (setq irc-confirm t))
  9582.            (if (string= "-" conf) (setq irc-confirm nil))
  9583.            (irc-insert "%sMessage confirmation is %s%s"
  9584.                irc-msg-info-pre
  9585.                (if irc-confirm "on" "off")
  9586.                irc-msg-info-post))))
  9587.   (setq irc-idle-last-sent (irc-current-time)))
  9588.  
  9589.  
  9590. (defun irc-execute-notify (users)
  9591.   "Usage: /NOTIFY [ + | [-]nick ... ]
  9592.  
  9593. Add and delete nicknames from your notifylist. When people on the list get
  9594. detected, you will be notified. When they quit IRC, you will be notified of
  9595. this fact too.
  9596.  
  9597. With no argument, show the people on list, no matter if they've been
  9598. detected or not.
  9599.  
  9600. With a list of nicknames as the argument (each optionally prepended by
  9601. a \"-\"), add those nicknames to the list, unless a \"-\" was
  9602. prepended, in which case the nickname is removed."
  9603.   (interactive '(""))
  9604.   (let* ((str (irc-nuke-whitespace
  9605.            (if (and (string= "" users) (not irc-called-from-buffer))
  9606.            (irc-read-object
  9607.             "Notify when detecting whom? (RET to show list) "
  9608.             ""
  9609.             (irc-recall-all 'irc-nicknames))
  9610.            users)))
  9611.      (list (mapcar 'irc-nuke-whitespace (reverse (irc-burst-comma str))))
  9612.      (added ())
  9613.      (removed ())
  9614.      (show-current (null list)))
  9615.     (while (not (null list))
  9616.       (let* ((subtract (= ?- (aref (car list) 0)))
  9617.          (name (if subtract (substring (car list) 1) (car list)))
  9618.          (is-in-list (irc-recall name 'irc-notify-looked-for)))
  9619.     (cond ((not (irc-is-nickname name))
  9620.            (irc-insert "%%This doesn't look like a nickname: \"%s\"."
  9621.                name))
  9622.           (subtract
  9623.            (if is-in-list
  9624.            (setq removed (cons name removed)))
  9625.            (irc-forget (substring (car list) 1) 'irc-notify-looked-for))
  9626.           (t (if (not is-in-list)
  9627.              (setq added (cons name added)))
  9628.          (irc-remember (car list) 'irc-notify-looked-for))))
  9629.       (setq list (cdr list)))
  9630.     (irc-who-is-on (irc-recall-all 'irc-notify-looked-for))
  9631.     (if show-current
  9632.     (let* ((detected (irc-recall-all 'irc-notify-detected))
  9633.            (looked-for (irc-recall-all 'irc-notify-looked-for))
  9634.            (pre (format "%sOf the persons "
  9635.                 irc-msg-info-pre))
  9636.            (irc-msg-cont-used (make-string (length pre) ? )))
  9637.       (if (null looked-for)
  9638.           (irc-insert "%sYou're not looking for anybody%s"
  9639.               irc-msg-info-pre irc-msg-info-post)
  9640.           (progn
  9641.         (irc-insert "%syou want notifications for (%s),"
  9642.                 pre
  9643.                 (irc-listify looked-for ", " "and"))
  9644.         (setq irc-msg-cont-used (substring
  9645.                      irc-msg-cont-used
  9646.                      0
  9647.                      (- (length "the persons "))))
  9648.         (irc-insert "%s%s on IRC at the moment%s"
  9649.                 irc-msg-cont-used
  9650.                 (if (null detected)
  9651.                 "no one is"
  9652.                 (concat
  9653.                  "the person"
  9654.                  (if (= 1 (length detected)) " " "s ")
  9655.                  (irc-listify detected ", " "and")
  9656.                  (if (= 1 (length detected)) " is" " are")))
  9657.                 irc-msg-info-post))))
  9658.     (let* ((a (if added
  9659.               (format "Added %s to"
  9660.                   (irc-listify (reverse added) ", " "and"))))
  9661.            (r (if removed
  9662.               (format "%semoved %s from"
  9663.                   (if added ", and r" "R")
  9664.                   (irc-listify (reverse removed) ", " "and"))))
  9665.            (str (cond ((and added removed) (format "%s%s" a r))
  9666.               (added a)
  9667.               (removed r)
  9668.               (t "No change to")))
  9669.            (indent (or (and (string-match " " str) (1+ (match-end 0)))
  9670.                irc-msg-cont-used))
  9671.            (irc-msg-cont-used (make-string indent ? )))
  9672.       (irc-insert "%s%s the notification list%s"
  9673.               irc-msg-info-pre str irc-msg-info-post)))))
  9674.  
  9675.  
  9676. (defun irc-execute-unignore (user)
  9677.   "Usage: /UNIGNORE user | + | -
  9678.  
  9679. Stop ignoring a user who has been /IGNOREd.  The special arguments + or -
  9680. mean to stop ignoring everyone who is being ignored."
  9681.   (interactive '(""))
  9682.   (let ((usr (irc-nuke-whitespace
  9683.           (if (and (string= "" user) (not irc-called-from-buffer))
  9684.           (irc-read-object "Stop ignoring whom? (RET to view) "
  9685.                    ""
  9686.                    (irc-recall-all 'irc-ignored-ppl))
  9687.           user))))
  9688.     (if (string= "" usr)
  9689.     (if (irc-nothing-remembered-p 'irc-ignored-ppl)
  9690.         (irc-insert "%sYou are not ignoring anyone%s"
  9691.             irc-msg-info-pre
  9692.             irc-msg-info-post)
  9693.         (irc-insert "%sYou are currently ignoring %s%s"
  9694.             irc-msg-info-pre
  9695.             (irc-subst-comma
  9696.              (mapconcat 'eval
  9697.                     (irc-recall-all 'irc-ignored-ppl)
  9698.                     ", ")
  9699.              "and")
  9700.             irc-msg-info-post))
  9701.     (if (string-match "^[---+]$" usr)
  9702.         (progn (irc-forget-all 'irc-ignored-ppl)
  9703.            (irc-insert "%sYou are no longer ignoring anyone%s"
  9704.                    irc-msg-info-pre
  9705.                    irc-msg-info-post))
  9706.         (if (string< "" user)
  9707.         (progn (irc-forget user 'irc-ignored-ppl)
  9708.                (irc-insert "%sYou are no longer ignoring %s%s"
  9709.                    irc-msg-info-pre
  9710.                    user
  9711.                    irc-msg-info-post))))))
  9712.   (setq irc-idle-last-sent (irc-current-time)))
  9713.  
  9714.  
  9715. (defun irc-execute-kick (kick)
  9716.   "Usage: /KICK user [channel]
  9717.    or: /KICK channel user
  9718.  
  9719. Kick user out from a channel. If no channel is given, defaults to the channel
  9720. you are currently talking to."
  9721.   (interactive)
  9722.   (let* ((c (if (string-match "^ *[^: ]+ +\\([^: ]+\\) *$" kick)
  9723.         (substring kick (match-beginning 1) (match-end 1))
  9724.         irc-channel))
  9725.      (chn (if (string= c "*") irc-channel c))
  9726.      (usr (if (string-match "^ *\\([^: ]+\\) +[^: ]+ *$" kick)
  9727.            (substring kick (match-beginning 1) (match-end 1))
  9728.            kick))
  9729.      (reversed (and (or (irc-is-channelname usr)
  9730.                 (string= usr "*"))
  9731.             (irc-is-nickname chn)))
  9732.      (chan (if reversed (if (string= "*" usr) irc-channel usr) chn))
  9733.      (user (if reversed chn usr)))
  9734.     (if (string-match "^ *$" user)
  9735.     (irc-insert "%%No user given, use /HELP KICK for help.")
  9736.     (if (not irc-called-from-buffer)
  9737.         (progn (irc-insert "")
  9738.            (irc-insert "/KICK %s %s" user chan)))
  9739.     (irc-send (concat "KICK " chan " :" user))))
  9740.   (setq irc-idle-last-sent (irc-current-time)))
  9741.  
  9742.  
  9743. (defun irc-execute-mail (m)
  9744.   "Usage: /MAIL [command [arguments]]
  9745.  
  9746. Give commands to the MAIL subsystem of IRC. This has nothing to do with
  9747. \"regular email\".
  9748. Do \"/MAIL HELP\" for seeing what commands are supported and how to use them.
  9749. Be warned though, the syntax in the help is somewhat ... nonstandard."
  9750.   (interactive)
  9751.   (if (not irc-called-from-buffer)
  9752.       (progn (irc-insert "")
  9753.          (irc-insert "/MAIL %s" m)))
  9754.   (irc-send (concat "MAIL " m))
  9755.   (setq irc-idle-last-sent (irc-current-time)))
  9756.  
  9757.  
  9758. (defun irc-execute-stats (args)
  9759.   "Usage: /STATS [ type [ server ] ]
  9760.  
  9761. Get statistics from a server. There are different kind of statistics
  9762. one can obtain:
  9763.     C    tells which other servers etc a server will accept
  9764.         connections from and will connect to
  9765.     H    tells which servers are treated as HUBS and LEAVES
  9766.     I    tells which masks are used to allow client connections
  9767.         at a server
  9768.     K    tells which user isn't allowed to use a specific server
  9769.     L    tells how much data has passed over the currently
  9770.         active links
  9771.         M       tells how many times the different (server level) commands
  9772.                 has been seen by the server
  9773.         N       same as C
  9774.     Q    tells which servers are in quarantine, ie for which servers
  9775.         a server disconnects its local link in that direction
  9776.         R       tells some internal resource statistics regarding traffic on
  9777.                 the server
  9778.         S       tells which services are connected to a server
  9779.         U       tells the uptime of a server
  9780.     Y    tells the connection classes in effect at a server
  9781.         Z       tells some internal resource statistics regarding the servers
  9782.                 memory usage
  9783.  
  9784. If no server is given, the current server (ie the one your client is
  9785. connected to at the time of the command) is used."
  9786.   (interactive '(""))
  9787.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$" args)
  9788.               (cons (subfield args 1) (subfield args 2)))
  9789.              ((string-match "^ *\\([^ ]+\\) *$" args)
  9790.               (cons (subfield args 1) ""))
  9791.              (t (cons "" ""))))
  9792.      (c (car pair))
  9793.      (s (cdr pair))
  9794.      (cmd (irc-nuke-whitespace
  9795.            (if (and (string= "" c) (not irc-called-from-buffer))
  9796.            (irc-read-object (concat "Which STATS command? (C, I, K, L,"
  9797.                         " M, Q, R, S, U, Y or Z) ")
  9798.                     ""
  9799.                     '("C" "I" "K" "L" "M" "Q" "R" "S" "U" "Y"
  9800.                       "Z"))
  9801.            c)))
  9802.      (server (irc-nuke-whitespace
  9803.           (if (and (string= "" s) (not irc-called-from-buffer))
  9804.               (irc-read-object (concat "STATS at which server? "
  9805.                            "(RET for "
  9806.                            irc-server
  9807.                            ") ")
  9808.                        ""
  9809.                        (irc-recall-all 'irc-servernames))
  9810.               s))))
  9811.     (if (not irc-called-from-buffer)
  9812.     (progn (irc-insert "")
  9813.            (irc-insert "/STATS %s"
  9814.                (concat (upcase cmd)
  9815.                    (if (not (string= "" cmd))
  9816.                        " "
  9817.                        "")
  9818.                    server))))
  9819.     (irc-send (concat "STATS " (concat cmd " " server)))
  9820.     (setq irc-idle-last-sent (irc-current-time))))
  9821.  
  9822.  
  9823. (defun irc-execute-mode (mode)
  9824.   "Usage: /MODE [channel [commands [arguments]]]
  9825.    or: /MODE nick [commands [arguments]]
  9826.  
  9827. Change or inspect the mode of a channel or a user.
  9828. The following modes exist for channels:
  9829.    a      Make channel anonymous (not supported by any servers yet)
  9830.    b      Manipulate a channels list of banned people
  9831.    i      Make channel joinable only with an invitation
  9832.    k      Add or remove channel key (password)
  9833.    l      Limit the number of users on the channel (argument: count)
  9834.    m      Make channel moderated
  9835.    n      Forbid /MSG's into channel
  9836.    o      Make someone a channel operator of this channel (argument: user)
  9837.    p      Make the channel private (ie channel invisible, users shown as being
  9838.           on some private channel)
  9839.    s      Make the channel secret (ie both channel and users invisible)
  9840.    t      Lock the topic of the channel (only settable by channel operators)
  9841.    v      Gives a user a voice on a moderated channel
  9842.  
  9843. The following modes exist for a user:
  9844.    i      Invisible
  9845.    o      Operator on IRC - can only be set with /OPER command
  9846.    s      Statusmessages, receive from server
  9847.    w      WALLOPS, receive from server
  9848. At the moment, only one self can be manipulated, and only i, s and w
  9849. can be set.
  9850.  
  9851. Prepend the mode command character with a + to turn the correspending
  9852. mode on, or with a - to turn it off.
  9853.  
  9854. Examples:
  9855.     /mode                    Show the mode of the current channel.
  9856.     /mode #foo               Show the mode of the channel named \"#foo\".
  9857.     /mode #foo +t            Locks the topic of channel \"#foo\".
  9858.     /mode * +i+o WiZ         Makes the current channel invite only and
  9859.                              gives user WiZ channel operator status.
  9860.     /mode * -o+l+o WiZ 3 `   Removes channel operator status for the
  9861.                              current channel from user WiZ, sets the
  9862.                              maximum number of users to 3 and makes
  9863.                              user ` a channel operator.
  9864.  
  9865.     /mode WiZ                Show the mode of user WiZ.
  9866.     /mode WiZ +s             Start receiving local status messages, such as
  9867.                              other servers connecting to this server etc.
  9868.     /mode WiZ +i-w           Become invisible and stop receiving WALLOPS.
  9869.  
  9870. "
  9871.   (interactive '(""))
  9872.   (let* ((tri (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]\\)"
  9873.                    mode)
  9874.              (cons (subfield mode 1)
  9875.                (cons (subfield mode 2)
  9876.                  (concat (subfield mode 3)
  9877.                      (substring mode (match-end 0))))))
  9878.             ((string-match "^ *\\([^ ]+\\) +\\([^ ]\\)" mode)
  9879.              (cons (subfield mode 1)
  9880.                (cons (concat (subfield mode 2)
  9881.                      (substring mode (match-end 0)))
  9882.                  "")))
  9883.             ((string-match "^ *[^ ]" mode)
  9884.              (cons (irc-nuke-whitespace mode) (cons "" "")))
  9885.             (t (cons "" (cons "" "")))))
  9886.      (ch1 (irc-nuke-whitespace (car tri)))
  9887.      (ch2 (irc-nuke-whitespace
  9888.            (if (and (string= "" ch1) (not irc-called-from-buffer))
  9889.            (irc-read-object (concat "Get/set mode of what channel/user"
  9890.                         "? "
  9891.                         (if (not (string= "0" irc-channel))
  9892.                         (format "(RET for %s) "
  9893.                             irc-channel)))
  9894.                     ""
  9895.                     (append
  9896.                      (irc-recall-all 'irc-subscribed-channels)
  9897.                      (list irc-nick)))
  9898.            ch1)))
  9899.      (channel (if (or (string= "" ch2) (string= "*" ch2)) irc-channel ch2))
  9900.      (is-nick (irc-is-nickname channel))
  9901.      (cmd1 (irc-nuke-whitespace (car (cdr tri))))
  9902.      (command (irc-nuke-whitespace
  9903.            (if (and (string= "" cmd1)
  9904.                 (string< "" channel)
  9905.                 (not irc-called-from-buffer))
  9906.                (irc-read-object (format (concat "Mode commands for"
  9907.                             " channel %s? (RET to"
  9908.                             " view) ")
  9909.                         channel)
  9910.                     ""
  9911.                     (if is-nick
  9912.                         '("+" "-" "i" "o" "s" "w")
  9913.                         '("+" "-" "b" "i" "k" "l" "m" "n"
  9914.                           "o" "p" "s" "t" "v")))
  9915.                cmd1)))
  9916.      (a1 (irc-nuke-whitespace (cdr (cdr tri))))
  9917.      (arg (irc-nuke-whitespace
  9918.            (if (and (string= "" a1)
  9919.             (string< "" channel)
  9920.             (string-match "[LOlo]" command)    ;Needs arguments?
  9921.             (not irc-called-from-buffer))
  9922.            (irc-read-object (format "Arguments to \"/MODE %s %s\"? "
  9923.                         channel command)
  9924.                     ""
  9925.                     (irc-recall-all 'irc-nicknames))
  9926.            a1))))
  9927.     (if (not irc-called-from-buffer)
  9928.     (progn (irc-insert "")
  9929.            (irc-insert "/MODE %s %s %s" channel command arg))) 
  9930.     (irc-send (format "MODE %s %s %s" channel command arg)))
  9931.   (setq irc-idle-last-sent (irc-current-time)))
  9932.  
  9933.  
  9934. (defun irc-execute-die (&optional dummy)
  9935.   "Usage: /DIE
  9936.  
  9937. Tells your local server to go belly-up."
  9938.   (interactive)
  9939.   (if (not irc-called-from-buffer)
  9940.       (progn (irc-insert "")
  9941.          (irc-insert "/DIE")))
  9942.   (irc-send (concat "DIE"))
  9943.   (setq irc-idle-last-sent (irc-current-time)))
  9944.  
  9945.  
  9946. (defun irc-execute-finger (nick)
  9947.   "Usage: /FINGER user
  9948.  
  9949. Query a users client to get users finger information. As some clients don't
  9950. understand this query, you might or might not get back a valid answer.
  9951. Sometime you'll get back a confused \"What?\" from user instead."
  9952.   (interactive '(""))
  9953.   (let* ((u (irc-nuke-whitespace nick))
  9954.      (user (irc-nuke-whitespace
  9955.         (if (and (string= "" u) (not irc-called-from-buffer))
  9956.             (irc-read-object "Get FINGER info from whom? "
  9957.                      ""
  9958.                      (irc-recall-all 'irc-nicknames))
  9959.             u))))
  9960.     (if (string= "" user)
  9961.     (irc-insert "%%No nick name given.")
  9962.     (if (not irc-called-from-buffer)
  9963.         (progn (irc-insert "")
  9964.            (irc-insert "/FINGER %s" user)))
  9965.     (irc-send (concat "PRIVMSG " user " :\001FINGER\001"))))
  9966.   (setq irc-idle-last-sent (irc-current-time)))
  9967.  
  9968.  
  9969. (defun irc-execute-describe (str)
  9970.    "Usage: /DESCRIBE user action
  9971.  
  9972. Send a CTCP ACTION message to a user. As some clients don't understand
  9973. this message, you might get back a confused \"What?\" from user instead.
  9974.  
  9975. See also: /ME"
  9976.    (interactive '(""))
  9977.    (let* ((nick (substring str 0 (string-match " +\\|$" str)))
  9978.       (action (substring str (match-end 0)))
  9979.       (u (irc-nuke-whitespace nick))
  9980.       (user (irc-nuke-whitespace
  9981.          (if (and (string= "" u) (not irc-called-from-buffer))
  9982.              (irc-read-object "Send a ACTION message to whom? "
  9983.                       ""
  9984.                       (irc-recall-all 'irc-nicknames))
  9985.              u)))
  9986.       (m (irc-nuke-whitespace action))
  9987.       (msg (irc-nuke-whitespace
  9988.             (if (and (string= "" m) (not irc-called-from-buffer))
  9989.             (irc-read-object "What is your action? "
  9990.                      ""
  9991.                     nil)
  9992.            m))))
  9993.      (if (string= "" user)
  9994.      (irc-insert "%%No nick name given.")
  9995.     (if (string= "" msg)
  9996.        (irc-insert "%%No action given.")
  9997.       (if (not irc-called-from-buffer)
  9998.          (progn (irc-insert "")
  9999.             (irc-insert "/DESCRIBE %s %s" user msg)))
  10000.      (irc-send (concat "PRIVMSG " user " :\001ACTION " msg "\001")))))
  10001.    (setq irc-idle-last-sent (irc-current-time)))
  10002.  
  10003.  
  10004. (defun irc-execute-me (action)
  10005.    "Usage: /ME action
  10006.  
  10007. Send a CTCP ACTION message to current channel. As some clients don't
  10008. understand this message, you might get back a confused \"What?\" from
  10009. some users.
  10010.  
  10011. See also: /DESCRIBE"
  10012.    (interactive '(""))
  10013.    (let* ((m (irc-nuke-whitespace action))
  10014.       (msg (irc-nuke-whitespace
  10015.             (if (and (string= "" m) (not irc-called-from-buffer))
  10016.             (irc-read-object "What is your action? "
  10017.                     ""
  10018.                     nil)
  10019.            m)))
  10020.       (on-hash (irc-is-multijoinable-channel irc-channel))
  10021.       (newsrvr (irc-server-has-multijoinable-channels)))
  10022.      (if (string= "" msg)
  10023.      (irc-insert "%%No action given.")
  10024.     (if (not irc-called-from-buffer)
  10025.        (progn (irc-insert "")
  10026.           (irc-insert "/ME %s" msg)))
  10027.        (irc-send (concat (if (and newsrvr on-hash)
  10028.                  (concat "PRIVMSG " irc-channel)
  10029.                 "MSG")
  10030.              " :\001ACTION " msg "\001"))
  10031.        (let* ((confirm (format "(Description sent to channel %s)" irc-channel))
  10032.           (padding (make-string (max 0 (- (window-width
  10033.                            (get-buffer-window
  10034.                         (current-buffer)))
  10035.                           (length confirm)
  10036.                           1))
  10037.                     ? )))
  10038.      (irc-insert "%s%s" padding confirm))
  10039.        ))
  10040.    (setq irc-idle-last-sent (irc-current-time)))
  10041.  
  10042.  
  10043. (defun irc-execute-ping (nicks)
  10044.   "Usage: /PING nick ...
  10045.  
  10046. Query a user's client (using CTCP) and calculate the distance between
  10047. the two of you in tenth of seconds. As some clients don't understans this
  10048. query, you might or might not get back a valid answer. Sometimes you
  10049. might even get back a confused \"What?\" from the user of the client.
  10050.  
  10051. Due to some technical limits and sojges laziness, the measurment isn't
  10052. foolproof. If the result seems to be totally wrong, resubmit the query.
  10053.  
  10054. The granularity is 500 ms."
  10055.   (interactive '(""))
  10056.   (while (string-match "^ *\\([^ :]+\\) *" nicks)
  10057.     (sit-for 0)
  10058.     (let* ((nick (subfield nicks 1))
  10059.        (dummy (setq nicks (substring nicks (match-end 1))))
  10060.        (n (irc-nuke-whitespace nick))
  10061.        (v (irc-nuke-whitespace
  10062.            (if (and (string= "" n) (not irc-called-from-buffer))
  10063.            (irc-read-object "Get PING distance to whom? "
  10064.                     ""
  10065.                     (irc-recall-all 'irc-nicknames))
  10066.            n)))
  10067.        (victim (if (string= "*" v) irc-channel v)))
  10068.       (if (string= "" victim)
  10069.       (irc-insert "%%No name given.")
  10070.       (if (not irc-called-from-buffer)
  10071.           (progn (irc-insert "")
  10072.              (irc-insert "/PING %s" victim)))
  10073.       (irc-send (format (concat "PRIVMSG %s :"
  10074.                     "\001ERRMSG PING RELAY %d\001"
  10075.                     "\001PING %d\001")
  10076.                 victim
  10077.                 (car (cdr (irc-current-time)))
  10078.                 (car (cdr (irc-current-time))))))))
  10079.   (setq irc-idle-last-sent (irc-current-time)))
  10080.  
  10081.  
  10082. (defun irc-execute-memberships (&optional dummy)
  10083.   "Usage: /MEMBERSHIPS
  10084.  
  10085. Show which channels you're listening to, and which one you're talking to.
  10086.  
  10087. Use /JOIN to join more or other channels, /LEAVE to leave some."
  10088.   (interactive '(""))
  10089.   (if (not irc-called-from-buffer)
  10090.       (progn (irc-insert "")
  10091.          (irc-insert "/MEMBERSHIPS")))
  10092.   (irc-show-subscribed-channels)
  10093.   (setq irc-idle-last-sent (irc-current-time)))
  10094.  
  10095.  
  10096. (defun irc-execute-signal (sigs)
  10097.   "Usage: /SIGNAL [ + | - | [+]event | -event ] [...]
  10098.  
  10099. Set the events which will get signals (aks bells or dings) when they
  10100. occur.  Events supported are:
  10101.  
  10102. backtalk -- your nick is mentioned            private  -- private messages
  10103. detect   -- nick in notify list seen/gone     public   -- public messages
  10104. invite   -- invitations                       topic    -- channel topic changes
  10105. join     -- channel changes                   wall     -- broadcast messages
  10106. nick     -- nickname changes                  
  10107.  
  10108. Without any arguments /SIGNAL simply prints a message about what signals
  10109. are currently enabled.  With event or +event turn on all signalling for that
  10110. event.  Remove all signals for an event with -event.  /SIGNAL + or /SIGNAL -
  10111. adds or removes all signals respectively.  Multiple arguments are accepted;
  10112. later ones take precedence over the ones which came before them.  For example,
  10113. \"/SIGNAL - +w +i\" would turn off all signals and then turn on signalling only
  10114. for wall messages and invitations."
  10115.   (interactive "sSet signal: ")
  10116.   ;; blow some whitespace away.  curiously this doesn't work correctly in debug
  10117.   (setq sigs (irc-nuke-whitespace sigs))
  10118.   (let ((recog '(backtalk
  10119.          detect
  10120.          invite
  10121.          join
  10122.          nick
  10123.          private
  10124.          public
  10125.          wall
  10126.          topic))
  10127.     str
  10128.     sym
  10129.     on
  10130.     off
  10131.     event)
  10132.     (while (string< "" sigs)
  10133.       ;; take one argument at a time
  10134.       (setq str  (substring sigs 0 (string-match " +\\|$" sigs))
  10135.         sigs (substring sigs (match-end 0)))
  10136.       (string-match "^\\([---+]?\\)" str)
  10137.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  10138.         event (substring str (match-end 0))
  10139.         sym (if (string= "" event) nil
  10140.             (car (delq nil
  10141.                    (mapcar
  10142.                 (function
  10143.                  (lambda (arg)
  10144.                   (if (string-match
  10145.                        (concat "^" (regexp-quote event))
  10146.                        (prin1-to-string arg))
  10147.                       arg))) recog)))))
  10148.       (cond
  10149.     ((and (string= "" event) off)
  10150.      (setq irc-signals (mapcar 'list recog)))
  10151.     ((string= "" event)
  10152.      (setq irc-signals (mapcar
  10153.                 (function (lambda (arg) (list arg t))) recog)))
  10154.     ((null sym)
  10155.      (irc-insert "%%Signal: Unknown argument %s."
  10156.              irc-msg-info-pre
  10157.              event
  10158.              irc-msg-info-post))
  10159.     (t (if off (setcdr (assoc sym irc-signals) nil)
  10160.            (setcdr (assoc sym irc-signals) '(t))))))
  10161.     (setq on (delq nil
  10162.            (mapcar        ; test against t because I have plans
  10163.             (function     ; to couple users and events
  10164.              (lambda (arg)
  10165.               (if (eq (nth 1 (assoc arg irc-signals)) t)
  10166.               arg))) recog)))
  10167.     (if on
  10168.     (irc-insert "%sSignalling is enabled for %s%s"
  10169.             irc-msg-info-pre
  10170.             (irc-subst-comma
  10171.              (mapconcat 'prin1-to-string on ", ") "and")
  10172.             irc-msg-info-post)
  10173.     (irc-insert "%sAll signalling is currently disabled%s"
  10174.             irc-msg-info-pre
  10175.             irc-msg-info-post)))
  10176.   (setq irc-idle-last-sent (irc-current-time)))
  10177.  
  10178.  
  10179. (defun irc-execute-stamp (stamp)
  10180.   "Usage: /STAMP [ + | - | [+]event | -event | interval ] [...]
  10181.  
  10182. Set time-stamping for IRC.  + means to turn it on for all messages from users
  10183. and - means to turn it off for them.  +event or just event will turn it on for
  10184. that class of message and -event means to disable it for those messages.  An
  10185. integer interval means to insert a message indicating the time every N minutes,
  10186. where N is the interval.  With no arguments simply insert a message indicating
  10187. the current time-stamps.
  10188.  
  10189. The current time in HH:MM format can appear two different ways in IRC.  One is
  10190. to have it associate with 'event'; two events, 'private' and 'public' messages,
  10191. are supported this way.  The other is to have it as a stand-alone message
  10192. indicating the current time.  Both can be very useful in noting when someone
  10193. actually sent you a message or when another event happened if you happen to be
  10194. away for a while.  The accuracy of the interval timer is currently limited to
  10195. 0-2 minutes beyond the interval if display-time is not running; accuracy is
  10196. greatly improved if it is.  It can be turned off by setting the interval
  10197. to 0."
  10198.   (interactive "sSet time-stamp: ")
  10199.   ;; whee.  napalm would feel particularly good here.
  10200.   (setq stamp (irc-nuke-whitespace stamp))
  10201.   (let (str sym event off)
  10202.     (while (string< "" stamp)
  10203.       ;; as the args go marching one by one the last one stopped ... <ahem>
  10204.       (setq str   (substring stamp 0 (string-match " +\\|$" stamp))
  10205.         stamp (substring stamp (match-end 0)))
  10206.       (string-match "^\\([---+]?\\)" str)
  10207.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  10208.         event (substring str (match-end 1))
  10209.         sym (cond ((string= "" event) nil)
  10210.               ((string-match (concat "^" (regexp-quote event))
  10211.                      "private") 'private)
  10212.               ((string-match (concat "^" (regexp-quote event))
  10213.                      "public")  'public)
  10214.               ((natnump (car (read-from-string event)))
  10215.                (car (read-from-string event)))))
  10216.       ;; the following cond is really what sets eveything
  10217.       (cond ((and (string= "" event) off) (setq irc-message-stamp nil))
  10218.         ((string= "" event) (setq irc-message-stamp t))
  10219.         ((null sym) (irc-insert "%%Stamp: Unknown argument %s."
  10220.                     irc-msg-info-pre
  10221.                     event
  10222.                     irc-msg-info-post))
  10223.         ((natnump sym) (setq irc-time-stamp sym))
  10224.         (off (setq irc-message-stamp
  10225.                (car (delq sym (if (eq irc-message-stamp t)
  10226.                       '(private public)
  10227.                       (list irc-message-stamp))))))
  10228.         (t (setq irc-message-stamp
  10229.              (cond ((null irc-message-stamp) sym)
  10230.                ((or (eq irc-message-stamp t)
  10231.                 (eq irc-message-stamp sym)) irc-message-stamp)
  10232.                (t t)))))))
  10233.   (irc-insert "%s%s messages get time-stamps.%s%s"
  10234.           irc-msg-info-pre
  10235.           (cond ((eq irc-message-stamp t) "Private and public")
  10236.             ((null irc-message-stamp) "No")
  10237.             (t (capitalize (prin1-to-string irc-message-stamp))))
  10238.           (if (zerop irc-time-stamp) ""
  10239.           (format "  The time interval is %d minutes."
  10240.               irc-time-stamp))
  10241.           irc-msg-info-post)
  10242.   (setq irc-idle-last-sent (irc-current-time)))
  10243.  
  10244.  
  10245. (defun irc-execute-alias (alias)
  10246.   "Usage: /ALIAS alias [command] [args for command]]]
  10247.  
  10248. Allow 'alias' to be equivalent to 'command'.
  10249. For example, \"/ALIAS tf time tut.fi\" will make typing \"/tf\" be equivalent
  10250. to having issued the command \"/time tut.fi\".  Aliases can only be made
  10251. to existing commands, not other aliases.  They are also only recognized when
  10252. in the command name position of a line.  If given with no arguments then
  10253. all aliases are displayed; if given with just an alias name then the alias
  10254. with that name will be shown.  Aliases can be removed with /UNALIAS."
  10255.   (interactive "sWhat name should the new alias have? (RET to view all) ")
  10256.   (if (and (interactive-p) (string-match "[^: ]+" alias))
  10257.       (setq alias (concat
  10258.            alias
  10259.            " "
  10260.            (irc-read-object
  10261.             (format (concat "Alias \"%s\" to which command? "
  10262.                     "(Including optional arguments) ")
  10263.                 alias)
  10264.             ""
  10265.             (mapcar (function (lambda (pair)
  10266.                   (upcase (cdr pair))))
  10267.                 (append irc-alias-alist
  10268.                     (append irc-command-alist
  10269.                         irc-operator-alist)))))))
  10270.   (setq alias (irc-nuke-whitespace alias))
  10271.   (string-match "^/?\\([^: ]*\\) */?\\([^: ]*\\) *" alias)
  10272.   (let ((new (upcase (subfield alias 1)))
  10273.     (cmd (upcase (subfield alias 2)))
  10274.     (arg (irc-nuke-whitespace (substring alias (match-end 2))))
  10275.     match)
  10276.     (cond
  10277.       ((string= "" new)
  10278.        (let ((aliases irc-alias-alist))
  10279.      (cond ((> (length aliases) 0)
  10280.         (while aliases
  10281.           (irc-insert "%s/%s is aliased to mean \"/%s\"%s"
  10282.                   irc-msg-info-pre
  10283.                   (car (car aliases))
  10284.                   (cdr (car aliases))
  10285.                   irc-msg-info-post)
  10286.           (setq aliases (cdr aliases)))
  10287.         (irc-insert "%sListed all aliases%s"
  10288.                 irc-msg-info-pre
  10289.                 irc-msg-info-post))
  10290.            (t (irc-insert "%sYou don't have any aliases%s"
  10291.                   irc-msg-info-pre
  10292.                   irc-msg-info-post)))))
  10293.       ((string= "" cmd)
  10294.        (let ((alias (assoc new irc-alias-alist)))
  10295.      (if alias
  10296.          (irc-insert "%s/%s is aliased to mean \"/%s\"%s"
  10297.              irc-msg-info-pre
  10298.              (car alias)
  10299.              (cdr alias)
  10300.              irc-msg-info-post)
  10301.          ;; this could possibly have done some matching to see whether
  10302.          ;; just an abbrev was being given, but we'll just take it as given
  10303.          (irc-insert "%s\"/%s\" is not aliased%s"
  10304.              irc-msg-info-pre
  10305.              new
  10306.              irc-msg-info-post))))
  10307.       (t
  10308.        ;; Okay, we've got at least a command.  let's try and make this as
  10309.        ;; painless as possible. 
  10310.        (setq match (irc-check-list
  10311.             (mapcar 'car (append irc-command-alist
  10312.                      irc-operator-alist))
  10313.             cmd
  10314.             'start-only))
  10315.        (if (/= (length match) 1)
  10316.        (if match
  10317.            (irc-insert "%%Ambiguous command /%s; could be %s."
  10318.                cmd
  10319.                (irc-subst-comma
  10320.                 (mapconcat (function (lambda (arg)
  10321.                      (concat "\"" arg "\"")))
  10322.                        match
  10323.                        ", ")
  10324.                 "or"))
  10325.            (irc-insert "%%Command not found: /%s." cmd))
  10326.        (irc-change-alias new
  10327.                  (concat (downcase (car match))
  10328.                      ;; no trailing space if no arg
  10329.                      (if (string= "" arg)
  10330.                      ""
  10331.                      " ")
  10332.                      arg)
  10333.                  'add)
  10334.        (irc-insert "%s\"/%s\" has been aliased to mean \"/%s\"%s"
  10335.                irc-msg-info-pre
  10336.                new 
  10337.                (cdr (assoc new irc-alias-alist))
  10338.                irc-msg-info-post)))))
  10339.   (setq irc-idle-last-sent (irc-current-time)))
  10340.  
  10341.  
  10342. (defun irc-execute-unalias (alias)
  10343.   "Usage: /UNALIAS alias
  10344.  
  10345. Remove the 'alias' for a command."
  10346.   (interactive '(""))
  10347.   (let* ((tmpalias (if (and (string= "" alias) (not irc-called-from-buffer))
  10348.                (irc-read-object "Remove which alias? "
  10349.                     ""
  10350.                     (mapcar (function (lambda (p)
  10351.                           (upcase (car p))))
  10352.                         (irc-recall-all
  10353.                          'irc-alias-alist)))
  10354.                alias))
  10355.      (a (irc-nuke-whitespace tmpalias)) 
  10356.      (match (irc-check-list (mapcar 'car irc-alias-alist) a t)))
  10357.     (if (/= (length match) 1)
  10358.     (if match (irc-insert "%%%s is an ambiguous alias. Could be %s."
  10359.                   (upcase alias)
  10360.                   (irc-subst-comma
  10361.                    (mapconcat (function (lambda (arg)
  10362.                         (concat "\"" arg "\"")))
  10363.                       match
  10364.                       ", ")
  10365.                    "or"))
  10366.         (irc-insert "%%No alias found to match %s." (upcase alias)))
  10367.     (irc-change-alias (car match) nil 'remove)
  10368.     (irc-insert "%s\"%s\" is no longer aliased%s"
  10369.             irc-msg-info-pre (car match) irc-msg-info-post)))
  10370.   (setq irc-idle-last-sent (irc-current-time)))
  10371.  
  10372.  
  10373. ;;START of code by Per StarbΣck (starback@Student.DoCS.UU.SE)
  10374. (defun irc-execute-help (topic)
  10375.   "Usage: /HELP topic
  10376.  
  10377. Get the documentation for \"command\".  If no command is given then a list
  10378. of the possible topics is shown.  Note that commands for IRC Operators will
  10379. not appear in the help topics when not an IRC Operator."
  10380.   (interactive '(""))
  10381.   (let* ((normal-commands (mapcar (function car) irc-command-alist))
  10382.      (oper-commands (mapcar (function car) irc-operator-alist))
  10383.      (alias-commands (mapcar (function car) irc-alias-alist))
  10384.      (help-topics (mapcar (function car) irc-help-topic-alist))
  10385.      (top (irc-nuke-whitespace
  10386.            (if (and (string= "" topic) (not irc-called-from-buffer))
  10387.            (irc-read-object
  10388.             "Help for which command or topic? "
  10389.             ""
  10390.             (append normal-commands
  10391.                 (if irc-operator oper-commands '())
  10392.                 alias-commands
  10393.                 help-topics))
  10394.          topic))))
  10395.     (if (not irc-called-from-buffer)
  10396.     (progn (irc-insert "")
  10397.            (irc-insert "/HELP %s" top)))
  10398.     (if (string= top "")
  10399.     (let* ((str (concat "Help is available for the following IRC-mode"
  10400.                 " commands:\n"))
  10401.            (topics (sort (append normal-commands
  10402.                      (if irc-operator oper-commands nil)
  10403.                      alias-commands
  10404.                      help-topics)
  10405.                  (function string<))))
  10406.       (while topics
  10407.         (setq str (concat str
  10408.                   (format "\n%14s%14s%14s%14s%14s"
  10409.                       (nth 0 topics)
  10410.                       (or (nth 1 topics) "")
  10411.                       (or (nth 2 topics) "")
  10412.                       (or (nth 3 topics) "")
  10413.                       (or (nth 4 topics) "")))
  10414.           topics (nthcdr 5 topics)))
  10415.       (with-output-to-temp-buffer "*Help*" (princ str)))
  10416.       (let* ((matches (irc-check-list
  10417.                (append normal-commands
  10418.                    (if irc-operator oper-commands '())
  10419.                    alias-commands
  10420.                    help-topics)
  10421.                top t))
  10422.          ;;(matches-normal (irc-common-element matches normal-commands))
  10423.          (matches-oper (irc-common-element matches oper-commands))
  10424.          (matches-alias (irc-common-element matches alias-commands))
  10425.          (matches-topic (irc-common-element matches help-topics))
  10426.          (shadowingalias nil))
  10427.     ;; If there is an alias with the same name as a command,
  10428.     ;; the alias is preferred.  Other collisions shouldn't be possible.
  10429.     (if (and (cdr matches)        ;== (> (length matches) 1)
  10430.          (irc-all-true (mapcar (function (lambda (x)
  10431.                            (string= x (car matches))))
  10432.                        (cdr matches))))
  10433.         (if matches-alias
  10434.         (setq matches (list (car matches))
  10435.               shadowingalias (concat
  10436.                       "\n\nThis shadows the "
  10437.                       (cond (matches-topic
  10438.                          "general help on the topic")
  10439.                         (matches-oper "operator command")
  10440.                         (t "command"))
  10441.                       " with the same name."))
  10442.           (with-output-to-temp-buffer "*Help*"
  10443.         (princ (format (concat "There are several things called %s, "
  10444.                        "and no way to know \nwhich one you "
  10445.                        "want help on.  This is a bug--please "
  10446.                        "contact \n%s.")
  10447.                    (car matches) irc-hacker)))))
  10448.     ;; If nothing else matches even a non-oper gets to see
  10449.     ;; help on oper commands.
  10450.     (if (and (null matches) (not irc-operator))
  10451.         (setq matches (irc-check-list oper-commands top t)
  10452.           matches-oper matches))
  10453.     (cond ((null matches)
  10454.            (irc-insert "%%No help is available for \"%s\"."
  10455.                (upcase top)))
  10456.           ((cdr matches)        ;== (> (length matches) 1)
  10457.            (irc-insert "%%Ambiguous help topic %s; could be %s."
  10458.                (upcase top)
  10459.                (irc-subst-comma
  10460.                 (mapconcat (function (lambda (arg)
  10461.                            (concat "\"" arg "\"")))
  10462.                        matches
  10463.                        ", ")
  10464.                 "or")))
  10465.           (t ;;Exactly one match:
  10466.            (let ((match (car matches)))
  10467.          (with-output-to-temp-buffer "*Help*"
  10468.            (cond (matches-alias
  10469.               (let ((aliasfor (cdr (assoc match irc-alias-alist))))
  10470.                 (princ (format "%s is an alias for \"/%s\"."
  10471.                        match aliasfor))
  10472.                 (if shadowingalias (princ shadowingalias))
  10473.                 (princ (format "\n\n%s"
  10474.                        (irc-help-for-command
  10475.                         (upcase
  10476.                          (substring 
  10477.                           aliasfor 0
  10478.                           (string-match " "
  10479.                                 aliasfor))))))))
  10480.              (matches-topic
  10481.               (princ (cdr (assoc match irc-help-topic-alist))))
  10482.              (t (princ (irc-help-for-command match))))))))))))
  10483.  
  10484.  
  10485. (defun irc-help-for-command (command)
  10486.   "Returns the documentation string for the irc command COMMAND."
  10487.   (documentation
  10488.    (or (intern-soft (concat "irc-execute-"
  10489.                 (or (cdr (assoc command irc-command-alist))
  10490.                 (cdr (assoc command irc-operator-alist)))))
  10491.        'irc-internal-error-dummy)))
  10492.  
  10493.  
  10494. (defun irc-common-element (list1 list2)
  10495.   "True if two lists have at least one common element.
  10496. The predicate eq is used for the comparisions."
  10497.   (cond ((null list1) nil)
  10498.     ((memq (car list1) list2) t)
  10499.     (t (irc-common-element (cdr list1) list2))))
  10500.  
  10501.  
  10502. (defun irc-all-true (list)
  10503.   "Is true if all args in LIST are true."
  10504.   ;; This is needed as special forms (like AND) can't be given to FUNCALL.
  10505.   (if (null list) t (and (car list) (irc-all-true (cdr list)))))
  10506. ;;;END of code by Per StarbΣck.
  10507.  
  10508.  
  10509. (defun irc-later-execute-lusers ()
  10510.   "Dummy function. Used when it's desired to do a irc-execute-lusers in a
  10511. little while. Not implemented yet."
  10512.   nil)
  10513.  
  10514.  
  10515. (defun irc-internal-error-dummy ()
  10516.   "Internal error.
  10517.  
  10518. No internal function associated with this command. This should never happen.
  10519. Please report this to the person mentioned in variable irc-hacker."
  10520.   nil)
  10521.  
  10522.  
  10523.  
  10524. ;; miscellaneous irc-* commands
  10525. (defun irc-truncate-buffer (max min)
  10526.   "Remove as many lines from the beginning of the buffer as is
  10527. necessary to get it under MAX number of characters, downto MIN number
  10528. of characters. This function is used by irc-mode to prevent an
  10529. irc-session from consuming gross amounts of space.
  10530.  
  10531. See irc-filter about not truncating the Kiwi buffer at all."
  10532.   (if (>= (buffer-size) max)
  10533.       (save-excursion
  10534.     ;; first go to the lowest point posssible that would do it
  10535.     (goto-char min)
  10536.     ;; get to the end of this line
  10537.     (end-of-line)
  10538.     (if (< (point) irc-mark)
  10539.         ;; just to make sure we don't toast pending input
  10540.         (delete-region 1 (1+ (point)))
  10541.         (message "Warning: %s exceeding %s characters.  Couldn't truncate."
  10542.              (buffer-name (current-buffer)) max)))))
  10543.  
  10544.  
  10545. (defun irc-read-passwd (&optional prompt)
  10546.   "Allow user to type a string without it showing.  Returns string.
  10547. If optional PROMPT non-nil, use it as the prompt string in the minibuffer."
  10548.   ;; this is based on a similar function in telnet.el
  10549.   ;; the major drawback is that while being prompted for a password
  10550.   ;; it stays in this routine until C-g, RET or LFD is typed.
  10551.   (let ((passwd "") (echo-keystrokes 0) char)
  10552.     (if prompt (message prompt))
  10553.     (while (not (or (= (setq char (read-char)) 13) (= char 10)))
  10554.       ;; naughty bit.  take C-h to mean DEL.
  10555.       (if (or (= char 8) (= char 127))
  10556.       (if (> (length passwd) 0)
  10557.           (setq passwd (substring passwd 0 (1- (length passwd)))))
  10558.       (setq passwd (concat passwd (char-to-string char))))
  10559.       (if prompt (message (concat prompt (make-string (length passwd) ?*)))))
  10560.     (if prompt (message ""))
  10561.     passwd))
  10562.  
  10563.  
  10564. (defun irc-read-object (prompt object list)
  10565.   "Prompting with PROMPT, read an IRC objects name from the minibuffer.
  10566. Second argument OBJECT is a string which is checked for a non-ambiguous match
  10567. before the minibuffer read is done.  Optional third argument LIST is a
  10568. list to use for checking rather than the irc-nicknames.
  10569.  
  10570. It returns either the name of a object or an empty string (\"\")."
  10571.   (if (not (string-match "^ *\\([^: ]*\\)" object)) ; just want one name
  10572.       "" 
  10573.       (let ((completion-ignore-case t)
  10574.         (object (substring object (match-beginning 1) (match-end 1)))
  10575.         (match nil))
  10576.     (if (or (string= "" object)
  10577.         (/= (length (setq match (irc-check-list list object))) 1))
  10578.         (completing-read (format "%s%s"
  10579.                      (if (string= "" object)
  10580.                      ""
  10581.                      (format (if (zerop (length match))
  10582.                              "No names match %s.  "
  10583.                              "\"%s\" is ambiguous.  ")
  10584.                          object))
  10585.                      prompt)
  10586.                  ;; build the list for completing-read.  a
  10587.                  ;; null string is there so that it can exit
  10588.                  ;; without anything, since we require matches
  10589.                  (mapcar 'list (cons "" list))
  10590.                  nil
  10591.                  nil        ;Also non exact matches are OK.
  10592.                  object)
  10593.         (car match)))))
  10594.  
  10595. (defun irc-nuke-whitespace (str)
  10596.   "One string argument.  Returns it with surrounding whitespace removed."
  10597.   (let* ((tmp (and (string-match "^ *" str)
  10598.            (substring str (match-end 0)))))
  10599.     (if (not tmp)
  10600.     str
  10601.     (and (string-match " *$" tmp)
  10602.          (substring tmp 0 (match-beginning 0))))))
  10603.  
  10604.  
  10605. (defun irc-stringlist-to-string (list &optional sep)
  10606.   "Take a LIST of strings and concate all string into one single string.
  10607. Optionally takes as a second argument a string to use as a seperator."
  10608.   (mapconcat (function (lambda (arg) arg)) list sep))
  10609.  
  10610.  
  10611. (defun irc-subst-comma (str newsep)
  10612.   "Return the string formed by substituting for the last \", \" in STR
  10613. the string NEWSEP followed by a space.  For example:
  10614.   (irc-subst-comma \"1, 2, 3\" \"or\") => \"1, 2 or 3\"
  10615.  
  10616. This function is especially designed for making message from irc-mode
  10617. more grammatically correct and the strings which it operates on should
  10618. be carefully chosen so as to avoid possibly blowing away a comma that
  10619. really wasn't separating elements in a list."
  10620.   ;; did you know that example up there can't appear starting in column 0
  10621.   ;; without screwing up lisp-indent-line?
  10622.   (if (string-match ", [^,]*$" str)
  10623.       (concat (substring str 0 (match-beginning 0)) " " newsep
  10624.           (substring str (1+ (match-beginning 0))))
  10625.       str))
  10626.  
  10627.  
  10628. (defun irc-listify (list sep conn)
  10629.   "Take a LIST of strings, and put them together into one single string, using
  10630. the SEPerator string between every pair of string, except the last pair where
  10631. the CONNector is used.
  10632. Example: (irc-listify '(\"a\" \"b\" \"c\") \", \" \"and\") returns
  10633. \"a, b and c\"."
  10634.   (irc-subst-comma (irc-stringlist-to-string list sep) conn))
  10635.  
  10636.  
  10637. (defun irc-get-time ()
  10638.   "Return the hour and minutes of the current time in the form \"HH:MM\"."
  10639.   (let ((time (current-time-string)))
  10640.     (substring time
  10641.            (string-match "[0-2][0-9]:[0-5][0-9]" time)
  10642.            (match-end 0))))
  10643.  
  10644.  
  10645. ;;;(defun irc-current-time ()
  10646. ;;;  "Return current time as number of seconds since 1-jan-1970 0:00:00.
  10647. ;;;As this is a 32 bit number but GNU Emacs only handles 16 bit numbers, split
  10648. ;;;it up in a cons with the car being the high order 16 bit numer and th cdr
  10649. ;;;the low order 16 bit number."
  10650. ;;;  (if (= 0 (buffer-size))
  10651. ;;;      (irc-insert ""))
  10652. ;;;  (write-region (point-max) (1- (point-max)) irc-idle-scratch-file nil 'silent)
  10653. ;;;  (nth 6 (file-attributes irc-idle-scratch-file)))
  10654.  
  10655.  
  10656. (defun irc-current-time ()
  10657.   "Return current time as number of seconds since 1-jan-1970 0:00:00.
  10658. As this is a 32 bit number but GNU Emacs only handles 16 bit numbers, split
  10659. it up in a cons with the car being the high order 16 bit numer and the cdr
  10660. the low order 16 bit number.
  10661.  
  10662. Written by Stephen Ma <ma_s@maths.su.oz.au>"
  10663.   (irc-time-to-int (current-time-string)))
  10664.  
  10665.  
  10666. (defun irc-time-to-int (timestr)
  10667.   "Convert from time in string format as returned by current-time-string
  10668. to a double integer format, as returned by file-attributes.
  10669.  
  10670. Written by Stephen Ma <ma_s@maths.su.oz.au>"
  10671.   (let* ((norm+ '(lambda (num1 num2)
  10672.           (let ((sumh (+ (car num1) (car num2)))
  10673.             (suml (+ (car (cdr num1)) (car (cdr num2)))))
  10674.             (list (+ sumh (/ suml 65536)) (% suml 65536)))))
  10675.      (norm* '(lambda (num1 num2)
  10676.           (let ((prodh (* num1 (car num2)))
  10677.             (prodl (* num1 (car (cdr num2)))))
  10678.             (list (+ prodh (/ prodl 65536)) (% prodl 65536)))))
  10679.      (seconds (string-to-int (substring timestr 17 19)))
  10680.      (minutes (string-to-int (substring timestr 14 16)))
  10681.      (hours (string-to-int (substring timestr 11 13)))
  10682.      (partdays (1- (string-to-int (substring timestr 8 10))))
  10683.      (years (string-to-int (substring timestr 20 24)))
  10684.      (days (+ partdays
  10685.           (cond ((and (= (% years 4) 0)
  10686.                   (/= (% years 100) 0))
  10687.              (cdr (assoc (substring timestr 4 7)
  10688.                      '(("Jan" . 0)
  10689.                        ("Feb" . 31)
  10690.                        ("Mar" . 60)
  10691.                        ("Apr" . 91)
  10692.                        ("May" . 121)
  10693.                        ("Jun" . 152)
  10694.                        ("Jul" . 182)
  10695.                        ("Aug" . 213)
  10696.                        ("Sep" . 244)
  10697.                        ("Oct" . 274)
  10698.                        ("Nov" . 305)
  10699.                        ("Dec" . 335)))))
  10700.             (t (cdr (assoc (substring timestr 4 7)
  10701.                        '(("Jan" . 0)
  10702.                      ("Feb" . 31)
  10703.                      ("Mar" . 59)
  10704.                      ("Apr" . 90)
  10705.                      ("May" . 120)
  10706.                      ("Jun" . 151)
  10707.                      ("Jul" . 181)
  10708.                      ("Aug" . 212)
  10709.                      ("Sep" . 243)
  10710.                      ("Oct" . 273)
  10711.                      ("Nov" . 304)
  10712.                      ("Dec" . 334))))))
  10713.           (* (- years 1970) 365)
  10714.           (/ (- years 1969) 4)
  10715.           (- (/ (- years 1901) 100)))))
  10716.     (funcall norm+
  10717.          (funcall norm*
  10718.               60
  10719.               (funcall norm+
  10720.                    (funcall norm*
  10721.                     60
  10722.                     (funcall norm+
  10723.                          (funcall norm*
  10724.                               24
  10725.                               (list 0 days))
  10726.                          (list 0 hours)))
  10727.                    (list 0 minutes)))
  10728.          (list 0 seconds))))
  10729.  
  10730.  
  10731. (defun irc-time= (a b)
  10732.   "Compare two time, return true if they're equal."
  10733.   (and (= (nth 0 a) (nth 0 b))
  10734.        (= (nth 1 a) (nth 1 b))))
  10735.  
  10736.  
  10737. (defun irc-time< (a b)
  10738.   "Compare two times, return t if the first is earlier than the second."
  10739.   (or (< (nth 0 a) (nth 0 b))
  10740.       (and (= (nth 0 a) (nth 0 b))
  10741.        (< (nth 1 a) (nth 1 b)))))
  10742.  
  10743.  
  10744. (defun irc-time-diff (a b)
  10745.   "Return the difference between two times. This functions requires
  10746. the first argument to be later in time than the second argument."
  10747.   (cond ((= (nth 0 a) (nth 0 b)) (list 0 (- (nth 1 a) (nth 1  b))))
  10748.     ((> (nth 1 b) (nth 1 a)) (list (- (nth 0 a) (nth 0 b) 1)
  10749.                        (- (+ 65536 (nth 1 a)) (nth 1 b))))
  10750.     (t (list (- (nth 0 a) (nth 0 b))
  10751.          (- (nth 1 a) (nth 1 b))))))
  10752.  
  10753.  
  10754. (defun irc-idle-time ()
  10755.   "Return a approximation of the idle time. The time is the number of seconds
  10756. which have passed since the last write to the server. If a valid idle-time
  10757. can't be returned, -1 is returned instead."
  10758.   (let ((now (irc-current-time))
  10759.     (then irc-idle-last-sent))
  10760.     (if (or (numberp irc-idle-last-sent)
  10761.         (not (= (car now) (car then))))
  10762.     -1
  10763.     (- (car (cdr now))
  10764.        (car (cdr then))))))
  10765.  
  10766.  
  10767. (defun irc-internal-time ()
  10768.   "Return a new value every time irc-internal-time is called. The new value is
  10769. larger than the latest returned, starting at 0."
  10770.   (if (not (boundp 'irc-internal-time))
  10771.       (set (make-local-variable 'irc-internal-time) nil))
  10772.   (if (not (integerp irc-internal-time))
  10773.       (setq irc-internal-time 0)
  10774.       (setq irc-internal-time (1+ irc-internal-time))))
  10775.  
  10776.  
  10777. (defun irc-check-time ()
  10778.   "Check to see whether it is time to insert a current-time message into
  10779. the *IRC* buffer."
  10780.   (if (null irc-last-time)
  10781.       (setq irc-last-time 0))
  10782.   (let* ((time (irc-get-time))
  10783.      (last (if (and (boundp 'irc-last-time) (stringp irc-last-time))
  10784.            irc-last-time
  10785.            time))
  10786.       (old-minute (string-to-int (substring last 3)))
  10787.       (new-minute (string-to-int (substring time 3)))
  10788.       (total-time (if (numberp irc-total-time) irc-total-time 0)))
  10789.     (if (and (zerop irc-time-stamp) (zerop irc-notify-interval))
  10790.      ()
  10791.     ;; check the time sentinel
  10792.     (if (string= irc-last-time time)
  10793.         ()
  10794.         ;; time has gone stomping on by ...
  10795.         (setq new-minute (+ new-minute (if (< new-minute old-minute) 60 0))
  10796.           irc-last-time time
  10797.           irc-total-time (+ total-time (- new-minute old-minute)))
  10798.         (if (not (zerop irc-time-stamp))
  10799.         (if (not (< (- irc-total-time irc-last-stamp) irc-time-stamp))
  10800.             (progn (irc-wrap-display-time)
  10801.                (irc-send "TIME")
  10802.                (setq irc-last-stamp irc-total-time))))
  10803.         (if (not (zerop irc-notify-interval))
  10804.         (if (not (< (- irc-total-time irc-last-notify)
  10805.                 irc-notify-interval))
  10806.             (progn (irc-wrap-display-time)
  10807.                (irc-who-is-on
  10808.                 (irc-recall-all 'irc-notify-looked-for))
  10809.                (setq irc-last-notify irc-total-time))))))))
  10810.  
  10811.  
  10812. (defun irc-wrap-display-time ()
  10813.   "Set up a wrapper around the display-time-filter to hopefully provide a
  10814. little better accuracy for the time stamps."
  10815.   (if (and (fboundp 'display-time-filter)
  10816.            (not (fboundp 'original-display-time-filter)))
  10817.       (progn
  10818.         (fset 'original-display-time-filter
  10819.               (symbol-function 'display-time-filter))
  10820.         ;; a nested defun seems to do funny things to the byte-compiler, so
  10821.         ;; instead we find a way around it.
  10822.         (fset 'display-time-filter
  10823.               (function
  10824.                (lambda (proc str)
  10825.         "
  10826. The filter for the display-time-process.  This function has been modified
  10827. for IRC-mode to call irc-check-time before calling the original
  10828. display-time-filter."
  10829.         (save-excursion
  10830.           (let ((procs (irc-active-servers)))
  10831.             (while procs
  10832.               (let ((buf (buffer-name (process-buffer (car procs)))))
  10833.             (if buf (progn (set-buffer buf) (irc-check-time)))
  10834.             (setq procs (cdr procs))))))
  10835.         (original-display-time-filter proc str)))))))
  10836.  
  10837.  
  10838. (defun irc-who-is-on (&optional list)
  10839.   (if (or (not (boundp 'irc-last-who-is-on))
  10840.       (not (and (listp irc-last-who-is-on)
  10841.             (numberp (nth 0 irc-last-who-is-on))
  10842.             (numberp (nth 1 irc-last-who-is-on)))))
  10843.       (set (make-local-variable 'irc-last-who-is-on) '(0 0)))
  10844.   (let* ((now (irc-current-time))
  10845.      (diff (irc-time-diff now irc-last-who-is-on)))
  10846.     (cond ((or (not (= 0 (nth 0 diff)))
  10847.            (> (nth 1 diff) 60))
  10848.        (setq irc-last-who-is-on (irc-current-time))
  10849.        (let ((str "")
  10850.          (namelist (if (null list)
  10851.                    (irc-recall-all 'irc-notify-looked-for)
  10852.                    list)))
  10853.          (while (not (null namelist))
  10854.            (setq str (concat str " " (car namelist))
  10855.              namelist (cdr namelist)))
  10856.          (irc-send (format "ISON :%s" str)))))))
  10857.  
  10858.  
  10859. (defun irc-change-alias (alias cmd add)
  10860.   "Modify ALIAS for CMD in the irc-alias-alist.  ADD non-nil means to put the
  10861. alias in the list, nil (or the symbol \"remove\") means to clear it.  This
  10862. function does no hand-holding like /ALIAS; its intended use is in
  10863. irc-mode-hook."
  10864.   (let ((entry (assoc (upcase alias) irc-alias-alist)))
  10865.     (if (or (null add) (eq add 'remove))
  10866.         (setq irc-alias-alist (delq entry irc-alias-alist))
  10867.     (if entry (setcdr entry cmd)
  10868.         (setq irc-alias-alist
  10869.           (cons (cons (upcase alias) cmd) irc-alias-alist))))))
  10870.  
  10871.  
  10872. (defun irc-signal (user event)
  10873.   "Return t if a ding should be issued for a USER/EVENT pair.
  10874. Currently only the event part of things is supported by /SIGNAL."
  10875.   (let ((signal (cdr (assoc event irc-signals))))
  10876.     (or (memq t signal)
  10877.     (irc-member-general user signal 'string=)
  10878.         (irc-member-general user
  10879.                 (cdr (assoc 'user irc-signals))
  10880.                 'string=))))
  10881.  
  10882.  
  10883. (defun irc-check-list (list item &optional start-only)
  10884.   "See if LIST has string ITEM.  Returns a list of possible matches.  The list
  10885. returned is based on the following precedence rules:  if there is an exact
  10886. match, it is returned.  If there are any strings in the list whose beginning
  10887. match the item, they are returned.  If that fails and optional argument
  10888. START-ONLY is missing or nil, strings which have the item match anywhere are
  10889. returned.  As a last resort, nil is returned.
  10890. This function is not case-sensitive."
  10891.   (let ((return nil)
  10892.     (case-fold-search t)
  10893.     (item (regexp-quote item)))
  10894.     (if (setq return
  10895.               (delq nil                         ; whole words
  10896.                     (mapcar (function   
  10897.                              (lambda (arg)
  10898.                   (if (string-match (concat "^" item "$") arg)
  10899.                   arg))) list)))
  10900.         return
  10901.     (if (setq return
  10902.           (delq nil                       ; beginnings
  10903.             (mapcar (function
  10904.                  (lambda (arg)
  10905.                   (if (string-match (concat "^" item) arg)
  10906.                       arg))) list)))
  10907.         return
  10908.         (if start-only
  10909.         nil
  10910.         (delq nil
  10911.               (mapcar (function               ; anywhere
  10912.                    (lambda (arg)        
  10913.                 (if (string-match (concat "." item) arg) arg)))
  10914.                   list)))))))
  10915.  
  10916.  
  10917. (defun irc-list-remember (item list)
  10918.   "Add string ITEM to ordered LIST destructivly, returning the new list in
  10919. reversed order. The intended way to call this is like:
  10920.   (setq lst (irc-list-remember \"foo\" lst)).
  10921.  
  10922. This function is case insensitive."
  10923.   (let ((ui (upcase item)))
  10924.     (cond ((null list) (cons item nil))
  10925.       ((string< (upcase (car list)) ui) (cons item list))
  10926.       ((string= (upcase (car list)) ui)
  10927.        (rplaca list item)
  10928.        list)
  10929.       (t (let ((ptr list))
  10930.            (while (and (not (null (cdr ptr)))
  10931.                (string< ui (upcase (car (cdr ptr)))))
  10932.          (setq ptr (cdr ptr)))
  10933.            (cond ((null (cdr ptr)) (rplacd ptr (cons item nil)))
  10934.              ((string= (upcase (car (cdr ptr))) ui)
  10935.               (rplaca (cdr ptr) item))
  10936.              ((string< (upcase (car (cdr ptr))) ui)
  10937.               (rplacd ptr (cons item (cdr ptr))))
  10938.              (t (error
  10939.              (format "NOT possible! item=%s, list=%s, ptr=%s."
  10940.                  item list ptr)))))
  10941.          list))))
  10942.          
  10943.          
  10944. (defun irc-hash-value (str tbl-size)
  10945.   "Return a hash value (index into a hash table) for string ITEM according to
  10946. a table of size SIZE."
  10947.   (let ((h 0)
  10948.     (i 0)
  10949.     (l (min 4 (length str))))
  10950.     (while (< i l)
  10951.       (setq h (% (+ (* h 256) (upcase (aref str i))) tbl-size)
  10952.         i (1+ i)))
  10953.     h))
  10954.  
  10955.  
  10956. (defconst irc-hash-index-size 0
  10957.   "Index of size field in a Kiwi hash table.")
  10958. (defconst irc-hash-index-timestamp 1
  10959.   "Index of timestamp field in a Kiwi hash table.")
  10960. (defconst irc-hash-index-cleanflag 2
  10961.   "Index of cleanstamp in a Kiwi hash table. Either a symbol or a list.")
  10962. (defconst irc-hash-index-bucketarray 3
  10963.   "Index of bucketarray in a Kiwi hash table.")
  10964.  
  10965.  
  10966. (defun irc-create-new-hash-table (size)
  10967.   "Create a empty hash table of size SIZE." 
  10968.   ;; [size write-date cleanflag bucketarray]
  10969.   ;; cleanflag is a list = non-dirty, valid sorted list representation of
  10970.   ;; the hashed data. Else only data to be found is in the hashtable. The hash
  10971.   ;; table is always clean.
  10972.   (let ((htbl (make-vector 4 nil)))
  10973.     (aset htbl irc-hash-index-size size)
  10974.     (aset htbl irc-hash-index-timestamp (irc-internal-time))
  10975.     (aset htbl irc-hash-index-cleanflag 'empty)
  10976.     (aset htbl irc-hash-index-bucketarray (make-vector size nil))
  10977.     htbl))
  10978.  
  10979.  
  10980. (defun irc-nothing-remembered-p (bag)
  10981.   "True if the BAG is empty."
  10982.   (let* ((htbl (symbol-value bag))
  10983.      (flg (aref htbl irc-hash-index-cleanflag)))
  10984.     (cond ((and (symbolp flg) (eq 'empty flg)) flg)
  10985.       (t (let* ((a (aref htbl irc-hash-index-bucketarray))
  10986.             (size (aref htbl irc-hash-index-size))
  10987.             (i size)
  10988.             (empty t))
  10989.            (while (and empty (> i 0))
  10990.          (setq i (1- i)
  10991.                empty (null (aref a i))))
  10992.            (if empty
  10993.            (irc-forget-all bag))
  10994.            empty)))))
  10995.  
  10996.  
  10997. (defun irc-remember (item bag)
  10998.   "Store a string ITEM in the named BAG."
  10999.   (let* ((htbl (symbol-value bag))
  11000.      (a (aref htbl irc-hash-index-bucketarray))
  11001.      (fixed (cond ((eq bag 'irc-servernames)
  11002.                (let ((i (irc-extract-hostname (upcase item))))
  11003.              (cond ((not i) nil)
  11004.                    ((string-match "^ *$" i)
  11005.                 (irc-insert (concat "%%Function irc-remember"
  11006.                             " found a space in"
  11007.                             " a hostname %s).")
  11008.                         item)
  11009.                 (if debug-on-error
  11010.                     (error "SPC in hostname"))
  11011.                 nil)
  11012.                    (t i))))
  11013.               ((or (eq bag 'irc-linksinfo)
  11014.                (eq bag 'irc-namtree)
  11015.                (eq bag 'irc-whotree)
  11016.                (eq bag 'irc-listtree))
  11017.                item)
  11018.               ((or (eq bag 'irc-nicknames)
  11019.                (eq bag 'irc-notify-detected)
  11020.                (eq bag 'irc-notify-looked-for))
  11021.                (cond ((string= "" item)
  11022.                   (irc-insert "%%Skipped \"\" in irc-nicknames.")
  11023.                   nil)
  11024.                  ((= ?@ (aref item 0))
  11025.                   (substring item 1))
  11026.                  ((string-match " " item)
  11027.                   (irc-insert (concat "%%Function irc-remember"
  11028.                           " found a space in a"
  11029.                           " nickname (%s).")
  11030.                       item)
  11031.                   (if debug-on-error
  11032.                   (error "SPC in nickname"))
  11033.                   nil)
  11034.                  ((string-match "\\." item)
  11035.                   (irc-insert (concat "%%Function irc-remember"
  11036.                           " found a dot in a"
  11037.                           " nickname (%s).")
  11038.                       item)
  11039.                   (if debug-on-error
  11040.                   (error "Dot in nickname"))
  11041.                   nil)
  11042.                  (t item)))
  11043.               ((string-match " " item)
  11044.                (irc-insert (concat "%%Function irc-remember"
  11045.                        " found a space in an item"
  11046.                        " (%s).")
  11047.                    item)
  11048.                (if debug-on-error
  11049.                (error "SPC in item"))
  11050.                nil)
  11051.               (t item))))
  11052.     (cond (fixed
  11053.        (let* ((idx (irc-hash-value fixed (aref htbl irc-hash-index-size)))
  11054.           (oldlen (length (aref a idx))))
  11055.          (aset a idx (irc-list-remember fixed (aref a idx)))
  11056.          (cond ((not (= oldlen (length (aref a idx))))
  11057.             (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11058.             (aset htbl irc-hash-index-cleanflag 'dirty)))
  11059.          (if (and (eq bag 'irc-nicknames)
  11060.               (not (irc-recall fixed 'irc-notify-detected))
  11061.               (irc-recall fixed 'irc-notify-looked-for))
  11062.          (irc-who-is-on (irc-recall-all 'irc-notify-looked-for))))))))
  11063.  
  11064.  
  11065. (defun irc-debug-check-all-hashtables ()
  11066.   ""
  11067.   (let ((n (irc-internal-time)))
  11068.     (setq irc-userinfo (format "DEBUGGING CLIENT -- %s." n))
  11069.     (mapcar (function (lambda (p)
  11070.           (irc-debug-check-hashtable (car p) (cdr p) n)))
  11071.         '((irc-nicknames . irc-is-nickname)
  11072.           (irc-ignored-ppl . irc-is-nickname)
  11073.           (irc-linksinfo . nil)
  11074.           (irc-listtree . nil)
  11075.           (irc-notify-looked-for . irc-is-nickname)
  11076.           (irc-notify-detected . irc-is-nickname)
  11077.           (irc-namtree . nil)
  11078.           (irc-servernames . irc-is-hostname)
  11079.           (irc-subscribed-channels . irc-is-channelname)
  11080.           (irc-services . irc-is-nickname)
  11081.           (irc-whotree . nil)))))
  11082.  
  11083.  
  11084. (defun irc-debug-check-hashtable (bag chkfcn &optional mark)
  11085.   ""
  11086.   (let* ((data (irc-recall-all bag))
  11087.      (lst data)
  11088.      (id (if (null mark) "" mark))
  11089.      (consistent t)
  11090.      (doublettes nil))
  11091.     (sit-for 0)
  11092.     (irc-insert "DEBUG: %s checking if hashtable %s is consistent using %s."
  11093.         id bag chkfcn)
  11094.     (irc-insert "DEBUG: %s = %s." bag data)
  11095.     (while (not (null lst))
  11096.       (let* ((matches (irc-check-list data (car lst)))
  11097.          (l (length matches)))
  11098.     (cond ((= 1 l) (irc-insert "DEBUG: %s  OK, \"%s\" found once."
  11099.                    id (car lst)))
  11100.           ((= 0 l)
  11101.            (irc-insert "DEBUG: %s Huh? \"%s\" not found."
  11102.                id (car lst))
  11103.            (setq doublettes t))
  11104.           (t (irc-insert "DEBUG: %s ERROR \"%s\" FOUND %d TIMES."
  11105.                  id (car lst) l)
  11106.          (setq doublettes t)))
  11107.     (setq lst (cdr lst))))
  11108.     (irc-insert "DEBUG: %s checked for doublettes, done." id)
  11109.     (sit-for 0)
  11110.     (if (not (null chkfcn))
  11111.     (let ((lst data))
  11112.       (while (not (null lst))
  11113.         (cond ((funcall chkfcn (car lst))
  11114.            (irc-insert "DEBUG: %s item \"%s\" of %s -- OK."
  11115.                    id (car lst) bag))
  11116.           (t (irc-insert "DEBUG: %s item \"%s\" of %s FAILED CHECK."
  11117.                  id (car lst) bag)
  11118.              (setq consistent nil)))
  11119.         (setq lst (cdr lst)))))
  11120.     (irc-insert "DEBUG: %s done checking: doublettes %s, consistent %s"
  11121.         id (if doublettes "FAILED" "OK") (if consistent "OK" "FAILED"))
  11122.     (irc-insert "DEBUG: %s --------------" id)
  11123.     (sit-for 0)))
  11124.  
  11125.  
  11126. (defun irc-list-recall (item list)
  11127.   "Check if a string ITEM is in the LIST. The comparsion is not case
  11128. sensitive. If the item is found, return the stored spelling, else nil."
  11129.   (let ((ui (upcase item)))
  11130.     (while (and (not (null list))
  11131.         (string< ui (upcase (car list))))
  11132.       (setq list (cdr list)))
  11133.     (if (and (not (null list)) (string= (upcase (car list)) ui))
  11134.     (car list)
  11135.     nil)))
  11136.  
  11137.  
  11138. (defun irc-recall (item bag)
  11139.   "Check if a string ITEM is in the BAG. If so, return the stored spelling,
  11140. else ni. All checking is done without being case sensitive."
  11141.   (let* ((htbl (symbol-value bag))
  11142.      (idx (irc-hash-value item (aref htbl irc-hash-index-size))))
  11143.     (irc-list-recall item (aref (aref htbl irc-hash-index-bucketarray)
  11144.         (irc-hash-value item (aref htbl irc-hash-index-size))))))
  11145.  
  11146.  
  11147. (defun irc-recall-all (bag)
  11148.   "Return a sorted list representation of all strings in the BAG."
  11149.   ;; [size write-date cleanflag bucketarray]
  11150.   (let* ((htbl (symbol-value bag))
  11151.      (cached-data (aref htbl irc-hash-index-cleanflag))
  11152.      (is-clean (listp cached-data))
  11153.      (buckets (aref htbl irc-hash-index-bucketarray))
  11154.      (size (aref htbl irc-hash-index-size)))
  11155.     (cond ((not (= size (length buckets)))
  11156.        (irc-insert "%%Bad hash list %s, size != length bucketarray." bag)))
  11157.     (cond (is-clean cached-data)
  11158.       (t (let ((r nil)
  11159.            (i size)
  11160.            (a nil))
  11161.            (while (> i 0)
  11162.          (setq i (1- i)
  11163.                a (aref buckets i))
  11164.          (while (not (null a))
  11165.            (setq r (cons (car a) r)
  11166.              a (cdr a))))
  11167.            (let ((s (sort r '(lambda (a b)
  11168.                   (string< (upcase a) (upcase b))))))
  11169.          (aset htbl irc-hash-index-cleanflag s)
  11170.          s))))))
  11171.  
  11172.  
  11173. (defun irc-recall-all-and-display (bag ind &optional plur sing)
  11174.   "Enter the nodes in the BAG as seperate lines in the irc buffer. Entries
  11175. longer than 1 line are continued with an indentation of IND, a number.
  11176.  
  11177. If you supply the optional arguments PLUR and SING, then after the lines
  11178. a short message of the form \"[%d %s]\" is printed. If only PLUR is supplied,
  11179. it is always used. If both PLUS and SING is supplied, then SING is used if
  11180. exactly one line was printed, else PLUR is used."
  11181.   (let ((lst (irc-recall-all bag))
  11182.     (n 0)
  11183.     (irc-msg-cont-used (make-string ind ? )))
  11184.     (while lst
  11185.       (irc-insert "%s" (car lst))
  11186.       (setq n (1+ n)
  11187.         lst (cdr lst)))
  11188.     (if (stringp plur)
  11189.     (if (zerop n)            ;List empty?
  11190.         (if (irc-terminal-is-slow) ;When on a slow terminal, no list
  11191.         (irc-insert "%%No %s." plur) ; is kept.
  11192.         (irc-insert "%sEnd of (unsorted) %s list%s"
  11193.                 irc-msg-info-pre
  11194.                 plur
  11195.                 irc-msg-info-post))
  11196.         (irc-insert "%s%d %s%s"
  11197.             irc-msg-info-pre
  11198.             n
  11199.             (if (= n 1)
  11200.                 (if (stringp sing) sing plur)
  11201.                 plur)
  11202.             irc-msg-info-post))
  11203.     (irc-insert "%sEnd of (unsorted) list%s"
  11204.             irc-msg-info-pre
  11205.             irc-msg-info-post)))
  11206.   (irc-insert ""))
  11207.  
  11208.  
  11209. (defun irc-list-forget (item list)
  11210.   "Remove a string ITEM from a LIST of string, if it's found. The comparsions
  11211. are not case sensitive."
  11212.   (let ((ui (upcase item)))
  11213.     (cond ((null list) list)
  11214.       ((string< (upcase (car list)) ui) list)
  11215.       ((string= (upcase (car list)) ui) (cdr list))
  11216.       (t (let ((ptr list))
  11217.            (while (and (not (null (cdr ptr)))
  11218.                (string< ui (upcase (car (cdr ptr)))))
  11219.          (setq ptr (cdr ptr)))
  11220.            (cond ((null (cdr ptr)) nil)
  11221.              ((string< (upcase (car (cdr ptr))) ui) nil)
  11222.              ((string= (upcase (car (cdr ptr))) ui)
  11223.               (rplacd ptr (cdr (cdr ptr))))
  11224.              (t (error (concat  "irc-list-forget: NOT possible!"
  11225.                     " item=%s, list=%s, ptr=%s.")
  11226.                    item list ptr))))
  11227.          list))))
  11228.  
  11229.  
  11230. (defun irc-forget (item bag)
  11231.   "Remove a string ITEM from the BAG, if the item was there. Not case
  11232. sensitive."
  11233.   (let* ((htbl (symbol-value bag))
  11234.      (idx (irc-hash-value item (aref htbl irc-hash-index-size)))
  11235.      (a (aref htbl irc-hash-index-bucketarray))
  11236.      (oldlen (length (aref a idx))))
  11237.     (aset a idx (irc-list-forget item (aref a idx)))
  11238.     (if (and (eq bag 'irc-nicknames)
  11239.          (irc-recall item 'irc-notify-detected)
  11240.          (irc-recall item 'irc-notify-looked-for))
  11241.     (irc-who-is-on (irc-recall-all 'irc-notify-looked-for)))
  11242.     (cond ((not (= oldlen (length (aref a idx))))
  11243.        (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11244.        (aset htbl irc-hash-index-cleanflag 'dirty)))))
  11245.  
  11246.  
  11247. (defun irc-forget-all (bag)
  11248.   "Empty BAG."
  11249.   (let* ((htbl (symbol-value bag))
  11250.      (size (aref htbl irc-hash-index-size))
  11251.      (a (aref htbl irc-hash-index-bucketarray))
  11252.      (i 0))
  11253.     (while (< i size)
  11254.       (aset a i nil)
  11255.       (setq i (1+ i)))
  11256.     (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11257.     (aset htbl irc-hash-index-cleanflag 'empty)))
  11258.  
  11259.  
  11260. (defun irc-get-names-and-servers ()
  11261.   "Return a alphabetically sorted list of all the nick- and servernames which
  11262. are known by the client."
  11263.   (if (not (boundp 'irc-cache-n+s))
  11264.       (set (make-local-variable 'irc-cache-n+s) nil))
  11265.   (if (or (null irc-cache-n+s)        ;No data yet?
  11266.       (< (car irc-cache-n+s)    ;Nicknames updated?
  11267.          (aref irc-nicknames irc-hash-index-timestamp))
  11268.       (< (car irc-cache-n+s)    ;Servernames updated?
  11269.          (aref irc-servernames irc-hash-index-timestamp)))
  11270.       (let* ((servers (irc-recall-all 'irc-servernames))
  11271.          (names (irc-recall-all 'irc-nicknames))
  11272.          (data nil))
  11273.     (while (not (null servers))
  11274.       (setq data (cons (car servers) data)
  11275.         servers (cdr servers)))
  11276.     (while (not (null names))
  11277.       (setq data (cons (car names) data)
  11278.         names (cdr names)))
  11279.     (let ((s (sort data '(lambda (a b) (string< (upcase a) (upcase b))))))
  11280.       (setq irc-cache-n+s (cons (irc-internal-time) s)))))
  11281.   (cdr irc-cache-n+s))
  11282.  
  11283.  
  11284. (defun irc-get-channels-and-nicks-and-servers ()
  11285.   "Return a alphabetically sorted list of all the channel-, nick- and server-
  11286. names which are known by the client."
  11287.   (if (not (boundp 'irc-cache-c+n+s))
  11288.       (set (make-local-variable 'irc-cache-c+n+s) nil))
  11289.   (if (or (null irc-cache-c+n+s)
  11290.       (< (car irc-cache-c+n+s)
  11291.          (aref irc-subscribed-channels irc-hash-index-timestamp))
  11292.       (< (car irc-cache-c+n+s)
  11293.          (aref irc-nicknames irc-hash-index-timestamp))
  11294.       (< (car irc-cache-c+n+s)
  11295.          (aref irc-servernames irc-hash-index-timestamp)))
  11296.       (let* ((channels (irc-recall-all 'irc-subscribed-channels))
  11297.          (nicks (irc-recall-all 'irc-nicknames))
  11298.          (servers (irc-recall-all 'irc-servernames))
  11299.          (data nil))
  11300.     (while (not (null channels))
  11301.       (setq data (cons (car channels) data)
  11302.         channels (cdr channels)))
  11303.     (while (not (null nicks))
  11304.       (setq data (cons (car nicks) data)
  11305.         nicks (cdr nicks)))
  11306.     (while (not (null servers))
  11307.       (setq data (cons (car servers) data)
  11308.         servers (cdr servers)))
  11309.     (let ((s (sort data '(lambda (a b) (string< (upcase a) (upcase b))))))
  11310.       (setq irc-cache-c+n+s (cons (irc-internal-time) s)))))
  11311.   (cdr irc-cache-c+n+s))
  11312.  
  11313.  
  11314. (defun irc-sec-to-time (n)
  11315.   "Convert number of SECONDS into a time string of one of the following
  11316. formats \"SS seconds\" or \"MM minutes and SS seconds\"
  11317. or \"HH hours, MM minutes and SS seconds\"
  11318. or \"DD days, HH hourse, MM minutes and SS seconds\"."
  11319.   (let* ((one-minute 60)
  11320.      (one-hour (* 60 one-minute))
  11321.      (one-day (* 24 one-hour))
  11322.      (days (/ n one-day))
  11323.      (day-string (cond ((= 0 days) "")
  11324.                ((= 1 days) "1 day")
  11325.                (t (format "%d days" days))))
  11326.      (m (% n one-day))
  11327.      (hours (/ m one-hour))
  11328.      (hour-string (cond ((= 0 hours) "")
  11329.                 ((= 1 hours) "1 hour")
  11330.                 (t (format "%d hours" hours))))
  11331.      (l (% m one-hour))
  11332.      (minutes (/ l one-minute))
  11333.      (min-string (cond ((= 0 minutes) "")
  11334.                ((= 1 minutes) "1 minute")
  11335.                (t (format "%d minutes" minutes))))
  11336.      (seconds (% l one-minute))
  11337.      (sec-string (cond ((= 0 seconds) "")
  11338.                ((= 1 seconds) "1 second")
  11339.                (t (format "%d seconds" seconds)))))
  11340.     ;; Possible combinations:
  11341.     ;; D H M S
  11342.     ;; 0 0 0 0 = none
  11343.     ;; 0 0 0 1 = S
  11344.     ;; 0 0 1 0 = M
  11345.     ;; 0 0 1 1 = MS
  11346.     ;; 0 1 0 0 = H
  11347.     ;; 0 1 0 1 = HS
  11348.     ;; 0 1 1 0 = HM
  11349.     ;; 0 1 1 1 = HMS
  11350.     ;; 1 0 0 0 = D
  11351.     ;; 1 0 0 1 = DS
  11352.     ;; 1 0 1 0 = DM
  11353.     (let ((acc nil))
  11354.       (if (not (string= "" sec-string)) (setq acc (cons sec-string acc)))
  11355.       (if (not (string= "" min-string)) (setq acc (cons min-string acc)))
  11356.       (if (not (string= "" hour-string)) (setq acc (cons hour-string acc)))
  11357.       (if (not (string= "" day-string)) (setq acc (cons day-string acc)))
  11358.       (cond ((= 0 (length acc)) "0 seconds")
  11359.         ((= 1 (length acc)) (car acc))
  11360.         ((= 2 (length acc)) (format "%s and %s" (nth 0 acc) (nth 1 acc)))
  11361.         ((= 3 (length acc))
  11362.          (format "%s, %s and %s" (nth 0 acc) (nth 1 acc) (nth 2 acc)))
  11363.         (t (format "%s, %s, %s and %s"
  11364.                (nth 0 acc) (nth 1 acc) (nth 2 acc) (nth 3 acc)))))))
  11365.  
  11366.  
  11367. (defun irc-burst-comma (str)
  11368.   "Take a comma or space separated STR and turn it into a list of its elements.
  11369. Example: \"1, 2,3,4,  6  7\" becomes the list
  11370. (\"7\" \"6\" \"4\" \"3\" \"2\" \"1\")."
  11371.   (let (list sub (beg 0))
  11372.     (string-match "" str)
  11373.     (while (string-match ",+\\| +\\|,+ +" str beg)
  11374.       (if (not (string= (setq sub (substring str beg (match-beginning 0))) ""))
  11375.           (setq list (cons sub list)))
  11376.       (setq beg (match-end 0)))
  11377.     (if (/= (length str) beg) (cons (substring str beg) list) list)))
  11378.  
  11379.  
  11380.  
  11381. ;; miscellaneous other commands (usually from other sources)
  11382.  
  11383. ;; this makes up for not being able to provide a :test to memq.
  11384. ;; irc-member-general by Bard Bloom <bard@theory.lcs.mit.com>
  11385. (defun irc-member-general (x l comparison)
  11386.   "Is X a member of L under COMPARISON?"
  11387.   (let ((not-found t))
  11388.     (while (and l not-found)
  11389.       (setq not-found (not (funcall comparison x (car l)))
  11390.             l         (cdr-safe l)))
  11391.     (not not-found)))
  11392.  
  11393.  
  11394. ;; wish i could remember who I got this from; I had to patch it to work
  11395. ;; with the minibuffer correctly but it is mostly untouched.
  11396. (defun irc-walk-windows (proc &optional no-mini)
  11397.   "Applies PROC to each visible window (after selecting it, for convenience).
  11398. Optional arg NO-MINI non-nil means don't apply PROC to the minibuffer
  11399. even if it is active."
  11400.   (let* ((real-start (selected-window))
  11401.      (start (next-window real-start no-mini))
  11402.      (current start) done)
  11403.     (while (not done)
  11404.       (select-window current)
  11405.       (funcall proc)
  11406.       (setq current (next-window current no-mini))
  11407.       (setq done (eq current start)))
  11408.     (select-window real-start)))
  11409.  
  11410.  
  11411. (defun irc-count-windows (&optional no-mini)
  11412.   "Returns the number of visible windows.
  11413. Optional arg NO-MINI non-nil means don't count the minibuffer
  11414. even if it is active."
  11415.   (let ((count 0))
  11416.     (irc-walk-windows (function (lambda () (setq count (1+ count)))) no-mini)
  11417.     count))
  11418.  
  11419.  
  11420. ;; swiped from minibuf.el, but made exclusive to * Minibuf-n*.
  11421. (defun irc-minibuffer-message (format &rest args)
  11422.   "Print a temporary message at the end of the Minibuffer.
  11423. After 2 seconds or when a key is typed, erase it."
  11424.   (if (zerop (minibuffer-depth)) (apply 'message format args)
  11425.       (let (p)
  11426.     (save-excursion
  11427.       (set-buffer (concat " *Minibuf-" (1- (minibuffer-depth)) "*"))
  11428.       (unwind-protect
  11429.            (progn
  11430.          (setq p (goto-char (point-max)))
  11431.          (insert (apply 'format format args))
  11432.          (sit-for 2))
  11433.         (delete-region p (point-max)))))))
  11434.  
  11435.  
  11436. (defun irc-find-to (str &optional explicit)
  11437.   "Find the part of STRING that IRC-mode will interpret as the sendlist.
  11438. If no explicit list is found, irc-default-to is returned.  The string returned
  11439. is either : or ; terminated.
  11440.  
  11441. If optional EXPLICIT is non-nil, then return t if a sendlist was explicitly
  11442. specified, nil if the sendlist was implicit."
  11443.   (let* ((part (if (string-match "^ *\\([^;:]*\\) *\\([:;]\\)" str)
  11444.            (subfield str 1)
  11445.            nil))
  11446.      (retval (if (not part)
  11447.              ""
  11448.              (concat part (subfield str 2))))
  11449.      (matched (and part
  11450.                (or (string= "" part)
  11451.                (let ((s part))
  11452.                  (while (string-match (concat "^ *\\([^ ,]+\\)"
  11453.                               " *, *")
  11454.                           s)
  11455.                    (let ((b1 (match-beginning 1))
  11456.                      (e0 (match-end 0))
  11457.                      (e1 (match-end 1)))
  11458.                  (if (irc-is-receiver (substring s b1 e1))
  11459.                      (setq s (substring s e0))
  11460.                      (setq s ":"))))
  11461.                  (irc-is-receiver s))))))
  11462.     (if explicit matched (if matched retval irc-default-to))))
  11463.  
  11464.  
  11465. (defun irc-find-message (string)
  11466.   "Find the message that IRC will see if STR were sent.  For messages
  11467. sent with explicit lists, this is everything following the colon or
  11468. semi-colon.  For everything else, it is just the string."
  11469.   (substring string (length (irc-find-to string))))
  11470.  
  11471.  
  11472.  
  11473. ;; functions for the irc-history list
  11474. (defun irc-add-to-hist (str)
  11475.   "Put STRING at the head of the irc-history list."
  11476.   (if (string-match "^[;:]" str)
  11477.       (setq str
  11478.             (concat irc-last-explicit (substring str 1 (length str)))))
  11479.   (setq irc-history (append (list str) irc-history))
  11480.   (and (> (length irc-history) irc-max-history)
  11481.        (setq irc-history (reverse (cdr (reverse irc-history))))))
  11482.  
  11483.  
  11484. (defun irc-yank-prev-command ()
  11485.   "Put the last IRC /command in the input-region."
  11486.   (interactive)
  11487.   (delete-region irc-mark (goto-char (point-max)))
  11488.   (insert "/" irc-last-command)
  11489.   (goto-char (1+ irc-mark)))
  11490.  
  11491.  
  11492. (defun irc-history-prev (arg)
  11493.   "Select the previous message in the IRC history list.  ARG means
  11494. select that message out of the list (0 is the first)."
  11495.   (interactive "P")
  11496.   (let ((str (nth (or arg (1+ (or irc-history-index 0))) irc-history)))
  11497.     (if (not str)
  11498.         (message "No message %d in history." (or arg (1+ irc-history-index)))
  11499.     (delete-region irc-mark (goto-char (point-max)))
  11500.     (insert str)
  11501.     (goto-char irc-mark)
  11502.     (setq irc-history-index (or arg (1+ irc-history-index))))))
  11503.  
  11504.  
  11505. (defun irc-history-next (arg)
  11506.   "Select the next message in the IRC history list.  With prefix ARG
  11507. select that message out of the list (same as irc-history-prev if
  11508. called with a prefix arg)."
  11509.   (interactive "P")
  11510.   (if arg (irc-history-prev arg)
  11511.       (if (= irc-history-index -1)
  11512.       (message "No next message in history.")
  11513.       (delete-region irc-mark (goto-char (point-max)))
  11514.       (insert (if (zerop irc-history-index) ""
  11515.               (nth (1- irc-history-index) irc-history)))
  11516.       (setq irc-history-index (1- irc-history-index)))))
  11517.  
  11518.  
  11519. (defun irc-kill-input ()
  11520.   "Delete the input region and start out fresh.  This function is recommended
  11521. over any other way of killing the input-region interactively because it
  11522. also resets the index for the history list."
  11523.   (interactive)
  11524.   (delete-region irc-mark (goto-char (point-max)))
  11525.   (setq irc-history-index -1))
  11526.  
  11527.  
  11528. (defun irc-complete-name ()
  11529.   "Not completed yet."
  11530.   (interactive)
  11531.   (let* ((end (point))
  11532.      (beg (save-excursion
  11533.         (while
  11534.             (and (not (= (point) (point-min)))
  11535.              (irc-is-receiver (buffer-substring (1- (point)) end)))
  11536.           (backward-char 1))
  11537.         (point)))
  11538.      (pattern (downcase (buffer-substring beg end)))
  11539.      (alist (mapcar (function (lambda (s)
  11540.               (list (downcase s))))
  11541.             (irc-get-names-and-servers)))
  11542.      (completion (try-completion pattern alist)))
  11543.     (cond ((eq completion t))        ;Exact match.
  11544.       ((null completion)        ;No match at all.
  11545.        (ding)
  11546.        (message "Can't find completion for \"%s\"" pattern))
  11547.       ((not (string= pattern completion)) ;Complete (but maybe not unique).
  11548.        (delete-region beg end)
  11549.        (insert completion)) 
  11550.       (t (let* ((name (irc-nuke-whitespace
  11551.                (completing-read "Who? "
  11552.                         alist
  11553.                         nil
  11554.                         nil
  11555.                         pattern))))
  11556.            (delete-region beg end)
  11557.            (insert name))))))
  11558.  
  11559.  
  11560. (defun irc-line-count (buf)
  11561.   "Returns the size of the buffer BUF."
  11562.   (save-excursion (set-buffer buf)
  11563.           (goto-line 1)
  11564.           (count-lines (point-min) (1+ (buffer-size)))))
  11565.  
  11566.  
  11567. (defun irc-log-in-debug-buffer (line)
  11568.   "Append a LINE to the debug buffer associated with a session, appending a
  11569. newline to the line. If the debug buffer doesn't exist, do nothing."
  11570.   (let ((debug-buffer (concat (buffer-name (current-buffer))
  11571.                   "-*debug*")))
  11572.     (if (get-buffer debug-buffer)
  11573.     (irc-append-string-to-buffer line (get-buffer debug-buffer)))))
  11574.  
  11575.  
  11576. (defun irc-append-string-to-buffer (str buf)
  11577.   "Append the string STR to the buffer BUF as a line."
  11578.   (save-excursion (set-buffer buf)
  11579.           (goto-char (1+ (buffer-size)))
  11580.           (insert str "\n")))
  11581.  
  11582.  
  11583. (defun irc-get-buffers-nth-line (n buf)
  11584.   "Returns the line number N in the buffer BUF as a string.
  11585. The first line inb the buffer is line number 1.
  11586. If the buffer is empty, returns \"\"."
  11587.   (if (>= (irc-line-count buf) n)
  11588.       (save-excursion (set-buffer buf)
  11589.               (goto-line n)
  11590.               (let ((p (point)))
  11591.             (search-forward "\n" (1+ (buffer-size)) 'non-nil-non-t)
  11592.             (buffer-substring p (1- (point)))))
  11593.     ""))
  11594.  
  11595.  
  11596. (defun irc-sort-lines-in-buffer (buf &optional reverse)
  11597.   "Sort the lines in buffer BUF.
  11598. An optional argument REVERSE can be supplied as non-nil to sort the buffer
  11599. in reversed order."
  11600.   (save-excursion (set-buffer buf)
  11601.           (sort-lines reverse (point-min) (1+ (buffer-size)))))
  11602.  
  11603.  
  11604. (defun irc-history-menu ()
  11605.   "List the history of messages kept by irc-mode in another buffer."
  11606.   (interactive)
  11607.   (let ((pop-up-windows t) (hist irc-history) (line 0))
  11608.     (save-excursion
  11609.       (set-buffer (get-buffer-create "*IRC History*"))
  11610.       (fundamental-mode)
  11611.       (erase-buffer)
  11612.       (while hist
  11613.         (insert (format "%2d: %s\n" line (car hist)))
  11614.         (setq hist (cdr hist))
  11615.         (setq line (1+ line)))
  11616.       (if (zerop line)
  11617.           (insert "No messages have been sent to IRC yet."))
  11618.       (set-buffer-modified-p nil)
  11619.       (goto-char (point-min)))
  11620.     (display-buffer "*IRC History*")))
  11621.  
  11622.  
  11623.  
  11624. ;; stuff about irc-mode
  11625. (defun irc-version (&optional arg)
  11626.   "Print the current version of irc.el in the minibuffer.  With optional
  11627. ARG, insert it in the current buffer."
  11628.   (interactive "P")
  11629.   (if arg
  11630.       (insert irc-version)
  11631.       (princ irc-version)))
  11632.  
  11633.  
  11634. (defun irc-fatal (msg item)
  11635.   (irc-insert "FATAL ERROR: \"%s\" \"%s\"." msg item))
  11636.  
  11637.  
  11638. ;;; Force GC to prevent GC bug in older (pre 18.57) GNU Emacs'es.
  11639. (garbage-collect)
  11640.  
  11641. (defun irc-execute-news (dummy)
  11642.   "Shows news about latest changes to this GNU Emacs client.
  11643. Even shows news about old changes -- what a wonderous function indeed.
  11644.  
  11645. Latest changes to IRC mode, oldest at bottom, newest at top:
  11646.  
  11647. *** NEEDS TO BE UPDATED ***"
  11648.   (interactive '(""))
  11649.   (save-excursion
  11650.     (set-buffer (get-buffer-create "*IRC-mode News*"))
  11651.     (erase-buffer)
  11652.     (insert (documentation 'irc-execute-news))
  11653.     (goto-char (point-min)))
  11654.   (display-buffer "*IRC-mode News*"))
  11655.  
  11656.  
  11657. (defun irc-report-bug (client-message server-message type)
  11658.   ""
  11659.   (irc-insert "%%%s" client-message)
  11660.   (irc-insert "%% \"%s\" (%s)." server-message type)
  11661.   (irc-insert "%% Please tell %s, it might be a bug." irc-hacker)
  11662.   (irc-insert "%% (Client \"%s\", server %s version %d.%d)."
  11663.           irc-version irc-major-version irc-minor-version))
  11664.  
  11665.  
  11666. ;; We're done defining an irc mode, so let's provide it.
  11667. (provide 'irc)
  11668.