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.36.el next >
Text File  |  1996-09-05  |  427KB  |  11,634 lines

  1. ;(set (make-local-variable 'debug-on-error) t)
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;; -*- Mode: Emacs-Lisp -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;; Kiwi.el --- A user interface for the Internet Relay Chat
  4. (defconst irc-version "Kiwi v4.36 for GNU Emacs" "Current Kiwi version.")
  5. (defconst irc-ftp-version "4.36" "Current FTP'able version.")
  6. (defconst irc-ftp-file-names (list (format "Kiwi.%s.el*" irc-ftp-version)
  7.                  "Kiwi.README"))
  8. (defconst irc-ftp-source (list (list "FTP.Lysator.LiU.SE" "pub/emacs/Kiwi"
  9.                      irc-ftp-file-names)
  10.                    (list "FTP.FUNet.FI" "pub/unix/irc/Emacs"
  11.                      irc-ftp-file-names)))
  12. (defconst irc-hacker "Klaus.Zeuge@Student.DoCS.UU.SE"
  13.   "Email address of the person to send complaints and ideas too.")
  14. ;;;;;;;;;
  15. ;; v4.36 Fri Sep  6 19:21:56 1996    sojge@Student.DoCS.UU.SE
  16. ;;    - Message 325 (channel creation time), 338 (login time for a
  17. ;;      user) and 339 (time when the topic of a channel was set)
  18. ;; v4.35 Mon Aug 26 00:07:03 1996    sojge@Student.DoCS.UU.SE
  19. ;;    - Better Undernet handling in various places.
  20. ;;    - BUGFIX: make it harder to issue /WHO command w/o arument.
  21. ;;    - New value for irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1.
  22. ;; v4.34 Fri Feb  9 19:38:02 1996    sojge@Student.DoCS.UU.SE
  23. ;;    - Use last-command-char instead of last-input-char.
  24. ;;    - Obsoleted irc-explain-who-mode, moved to code to 352 handler.
  25. ;;    - Added undernet message 329, 333.
  26. ;;    - If emacs-version > 18, assume irc-emacs-knows-ISO8859-1 to t.
  27. ;;    - Added RPL262.
  28. ;;    - Made irc-startup-hook non-depended on LUSERS commands, moved it to
  29. ;;      CLIENT-SYNCH like mechanism (CLIENT-START)
  30. ;;      - Added 250 highest connect count.
  31. ;;    - Added a "whois x x" in irc-execute-info.
  32. ;;    - Added ignore stuff in notify detector, RPL303.
  33. ;;    - Added 409 no origin spec'ed (from /quo ping).
  34. ;;    - Reply 442 keeps changing, more kludging added.
  35. ;;    - BUGFIX, now understands 002 message "ircd2.8/dog3-super.pl7"
  36. ;; v4.33 Tue Dec 13 18:59:10 1994    sojge@Student.DoCS.UU.SE
  37. ;;    - Added new variable irc-scroll-step.
  38. ;;    - Added better knoweldge of &channels.
  39. ;;    - Show own nickname in ping replies on screen from others.
  40. ;;    - Cleaned up server informatio in /LINKS reply.
  41. ;;    - Better regexp when parsing 203:205 messages.
  42. ;;    - Put \< and \> around nick regexp for backtalk.
  43. ;;    - IRC-servers now understands command "TOPIC #C"
  44. ;;    - BUGFIX: 2.8.20 has a new 204 format with funky timer.
  45. ;; v4.32 Mon Aug  8 02:53:16 1994    sojge@Student.DoCS.UU.SE
  46. ;;    - BUGFIX: server 2.8.20 has new 317 message.
  47. ;;    - Added status line counter irc-reply-count for /who, /names, /links.
  48. ;;    - Added new /signal detect for /notify detect/lost sight messages.
  49. ;;    - Added new variable irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1
  50. ;;      to be used if one wants irc-self-insert to map certain keystrokes.
  51. ;;    - Changed irc-self-insert to be able to map from ISO 646-SE2 to
  52. ;;      ISO 8859-1.
  53. ;;    - Fixed typo in docstring of irc-time-diff.
  54. ;;    - Use irc-userhost in irc-parse-channel.
  55. ;; v4.31 Tue Oct 19 20:59:11 1993    sojge@Student.DoCS.UU.SE
  56. ;;    - BUGFIX: don't crash if CTCP quote is last in string.
  57. ;;    - BUGFIX: name buffer accoring to connected TCP-port, not default
  58. ;;      TCP-port.
  59. ;;    - Better handling of channel topic display.
  60. ;;    - Added handling of ERR 422 and 443, and RPL 249.
  61. ;;    - Clean up CTCP VERSION reply before displaying it.
  62. ;; v4.30 Tue Aug 24 20:52:21 1993    sojge@Student.DoCS.UU.SE
  63. ;;    - BUG FIX: erroneous format string fixed when handling CTCP ECHO reply.
  64. ;;    - Bug fix in irc-execute-notify, don't try to irc-forget a non nick.
  65. ;;    - Added backtalk to documentation of /signal.
  66. ;;    - Made variable irc-port (ie the TCP port used to connect to an IRC
  67. ;;      server) buffer local so different sessions can use diffferent ports.
  68. ;;    - Added handling of RPL 392.
  69. ;;    - Better handling of RPL 322.
  70. ;;    - Now cleans up QUIT messages.
  71. ;;    - Added handling ERR 422, no MOTD file.
  72. ;;    - Minor betterification in character mapping.
  73. ;; v4.29 Thu Aug 12 03:24:57 1993    sojge@Student.DoCS.UU.SE
  74. ;;    - If DEL pressed while point is at first postion in input region,
  75. ;;      scroll down page instead of beep.
  76. ;;    - More channel modes explained in irc-explain-mode (k and v).
  77. ;;    - Force emacs to offer to save the Kiwi buffer before exiting emacs.
  78. ;;    - Splitted up irc-parse-RPL so it's byte-compile'able with v18 emacs.
  79. ;;    - Remove the CTCP MOOD command as no one else used it.
  80. ;;    - As there are a lot of old clients out there, send several CTCP pings.
  81. ;;    - Unless debug-on-error is non-nil, don't crash when finding dots in
  82. ;;      host names, nicks etc.
  83. ;;    - New function irc-time-diff used to not send ISON commands more often
  84. ;;      than every 60 second.
  85. ;;    - New handling of topic, see /HELP TOPIC.
  86. ;;    - Don't care what user tries to /VERSION, let server decide if it
  87. ;;      makes sense.
  88. ;;    - Added handling of RPL 305, 306, 371, 374, 392, 394.
  89. ;;    - Added handling of RPL 242, 243, 244, 253, 261.
  90. ;;    - New format in TRACE output in RPL 200, 211.
  91. ;;    - Better parsing of "hello this is ircd version xxx" string at startup.
  92. ;;    - Added handling of ERR 436, 444, 445, 446, 467, 475.
  93. ;;    - Some minor changes in the CTCP handling. Nothing important.
  94. ;;    - make-local-variable doesn't set the variable in emacs v19, so needed
  95. ;;      to add a set in several places. NOW RUNS WITH GNU EMACS VERSION 19.
  96. ;;    - Fumbled around some more with character set convertings. Should go
  97. ;;      the v19 way, in the future.
  98. ;; v4.28 Mon Apr 19 15:48:45 1993    sojge@Student.DoCS.UU.SE
  99. ;;    - Made client somewhat compliant to ircd 2.8.
  100. ;;    - Added some (as of yet incomplete) support for different character
  101. ;;      sets like ISO 8859-1 and SIS E47.
  102. ;;    - Changed output of /WHO
  103. ;;    - Bugfixed irc-lowlevel-dequote to not crash when getting erroneous
  104. ;;      messages breaking the CNTRL/P quoting.
  105. ;;    - Bugfixed irc-execute-event.
  106. ;;    - Added CTCP MOOD. No /MOOD command yet, though.
  107. ;;    - Clean up a users full name in WHO replies.
  108. ;; v4.27 Mon Sep 14 19:17:23 1992    sojge@Student.DoCS.UU.SE
  109. ;;    - Better handling of versions through irc-ftp-* variables.
  110. ;;    - Added variable irc-show-japanese-characters to get better control
  111. ;;      about in what way japanese characters are inserted into buffer.
  112. ;;    - Spiffed up CTCP VERSION handling to comply to CTCP.mem v13.
  113. ;;    - Added flag irc-drop-ircII-text-kludge-control-characters for those
  114. ;;      users who WANT to see ^B, ^V and ^_ in text.
  115. ;;    - Ignore CNTRL/B, CNTRL/V and CNTRL/_ in incoming messages, as those
  116. ;;      are used by the ircII client to toggle reverse, underline and bold
  117. ;;      attributes of text.
  118. ;;    - Added variable irc-emacs-knows-ISO8859-1.
  119. ;;    - Fixed timing problem when receiving a PRIVMSG just after changing
  120. ;;      the nickname of oneself.
  121. ;; v4.26 Thu Aug 20 05:17:00 1992    sojge@Student.DoCS.UU.SE
  122. ;;    - Assorted small fixes.
  123. ;;    - Some new table headers (like for WHO).
  124. ;;    - Added RPL369, end of WHOWAS.
  125. ;;    - Added L line reply handling (RPL241).
  126. ;;    - Be nicer when sending automatic warnings.
  127. ;;    - Better handling of CTCP PING replies.
  128. ;;    - Reordered most global variable initialisations.
  129. ;; v4.25 Fri May 29 21:00:32 1992    sojge@Student.DoCS.UU.SE
  130. ;;    - Added user modes (eg /mode sojge -o)
  131. ;;    - Handles display of a channel's ban list (ie reply to /mode #x -b).
  132. ;;    - Better handling of some STATS replies.
  133. ;;    - Fixed irc-parse-quit.
  134. ;;    - Fixed irc-parse-kick.
  135. ;;    - Take care of v2.7.2 message ERROR: Closing Link.
  136. ;;    - Added CTCP commands ECHO, PING, SOURCE.
  137. ;;    - Started on a crude but better /IGNORE command.
  138. ;;    - Made Kiwi display unknown NOTICE's in block style.
  139. ;;    - Added /PING command, based on CTCP. Coded by Kimmo.Suominen@lut.fi.
  140. ;;    - Started on inout and output convertion tables to displat different
  141. ;;      character sets on different equipment.
  142. ;; 4.24 Mon Feb 24 17:01:09 1992    Klaus-Zeuge@DoCS.UU.SE
  143. ;;    - Still more RPL312 hacking. Hopefully looks OK on a 2.6.2 server now.
  144. ;; 4.23 Sat Feb 22 20:57:27 1992    Klaus.Zeuge@DoCS.UU.SE
  145. ;;    - Added real version number and edit history.
  146. ;; 4.22 Sat Feb 22 17:23:41 1992    Klaus.Zeuge@DoCS.UU.SE
  147. ;;    - Bugfixed CTCP VERSION reply from ircII.
  148. ;; 4.21 Sat Feb 22 16:38:05 1992    Klaus.Zeuge@DoCS.UU.SE
  149. ;;    - Removed annoying bug which mixed up different hash tables.
  150. ;;    - /mode can set modes for a user.
  151. ;;    - Added Q and Y to /stats.
  152. ;;    - /notify, a new command helping to see when your friends enter IRC.
  153. ;;    - /topic understands #channels, both when querying and setting.
  154. ;;    - /whois takes an optional first argument with name of server which
  155. ;;      should answer the whois question.
  156. ;;    - /quit now takes an optional reason.
  157. ;;    - Made /quote send an illegal command to server to help synchronizing.
  158. ;;    - Created variables irc-notify-looked-for and irc-notify-detected.
  159. ;;    - Added user mode in irc-explain-mode, added frontend functions
  160. ;;      irc-explain-user-mode and irc-explain-channel-mode.
  161. ;;    - Cope with different RPL312 styles.
  162. ;;    - Doing a somewhat better job at parsing ircII's ugly CTCP VERSION
  163. ;;      replies.
  164. ;;    - Cope with new RPL201-209, 211, 212, 213-219, 221.
  165. ;;    - Cope with some new NOTICE's.
  166. ;;    - Cope with new format of "Received SQUIT" NOTICE.
  167. ;;    - Cosmetic change in presenting other persons QUIT reasons.
  168. ;;    - Renamed irc-notifies into irc-events (lessens confusion with /notify)
  169. ;;    - Recognize the 500 series of ERR's from server.
  170. ;;    - Do a a sleep-for after EVERY received line from server.
  171. ;;    - Moved logging in *debug* buffer into irc-log-in-debug-buffer.
  172. ;; v4.20 Wed Dec 18 06:33:57 1991    Klaus.Zeuge@DoCS.UU.SE
  173. ;;    - Change a!b@c on incoming messages into a in irc-parse-server-msg.
  174. ;;      (Can you say kludge? I *knew* you could!)
  175. ;;    - Added RPL353 and RPL352 as front ends for NAMREPLY and WHOREPLY.
  176. ;;    - Parse 2.7(.0) version string correctly.
  177. ;;    - Better value for irc-msg-cont-used when reporting a channels mode.
  178. ;;    - Added Kimmo's code for detecting people on IRC using the ISON
  179. ;;      mechanism, irc-execute-notify. Also his irc-notify-list etc.
  180. ;;    - Added Kimmo's code for /ME and /DESCRIBE commands for CTCP ACTION.
  181. ;;    - Added Kimmo's code for recognizing CTCP ACTION commands.
  182. ;;    - Added fixes to keep Kiwi.el from choking on 2.7 messages.
  183. ;;      Fixed RPL messages are: 206, 209, 301, 304, 352, 353, 354,
  184. ;;      367, 368, 371, 373, 383, 384. Thank you Kimmo Suominen <kim@lut.fi>
  185. ;;      for supplying fixes.
  186. ;;    - Made comand "/join #channel +p" and friends kosher.
  187. ;;    - Added : as /MSG like command again after getting requests for it.
  188. ;;    - Threw out my irc-current-time based on writing irc-idle-scratch-file
  189. ;;      and replaced it by one donated by Stephen Ma <ma_s@maths.su.oz.au>.
  190. ;;    - Removed bug in irc-execute-signal.
  191. ;;    - Fixed parse error in irc-parse-pong.
  192. ;;    - More defensive handling of RPL319.
  193. ;; v4.19 Wed Nov 13 15:18:00 1991    Klaus.Zeuge@DoCS.UU.SE
  194. ;;    - Removed forgotten disabling of /KILL command. Ehum...
  195. ;;    - Use function make-temp-name when naming irc-idle-scratch-file.
  196. ;;    - Better formatting in /membership display.
  197. ;;    - Made irc-nuke-whitespace remove trailing spaces too.
  198. ;;    - Understand USERHOST replies (RPL302).
  199. ;;    - More 442 messages understood. Sigh.
  200. ;;    - Incoming TOPIC messages might contain channel name field.
  201. ;;    - USERS reply might contain word "display". Still valid.
  202. ;;    - Cope with 2.6.2e type of TRACE link lines.
  203. ;;    - "Understand" reason field in incoming QUIT messages.
  204. ;;    - Added Kims (kim@lut.fi) fix for 2.6.2e type of LUSER reply.
  205. ;;    - Fixed bug wtih dropped first character when user says "/mode * o u".
  206. ;; v4.18 Tue Oct 22 06:46:49 1991    Klaus.Zeuge@DoCS.UU.SE
  207. ;;    - Moved creation of irc-count-incoming-messages to irc-mode from
  208. ;;      irc-parse-server-msg.
  209. ;;    - Changed irc-truncate-buffer to chop down to irc-minimum-size whenever
  210. ;;      buffer has grown to irc-maximum-size.
  211. ;;    - Made irc-maximum-size = 64KB.
  212. ;;    - Added irc-minimum-size = 32KB.
  213. ;;    - Made most hash table twice as big.
  214. ;; v4.17 Sun Oct 20 17:05:01 1991    Klaus.Zeuge@DoCS.UU.SE
  215. ;;    - Rewrote most calls to string-match so they don't depend on . in
  216. ;;      regexps, as . doesn't match \n.
  217. ;;    - Made CTCP handling more iterative (recursive handling turned out
  218. ;;      to exhaust stacks in worst cases).
  219. ;;    - Made a few more variables buffer local.
  220. ;;    - Added low level quoting of \000, \n, \r, \020 and changed CTCP level
  221. ;;      quoting to use only \001 and \\.
  222. ;;    - Better irc-execute-stats.
  223. ;;    - Replaced all "\\s " by " " and all "\\S " by "[^: ]". Hopefully
  224. ;;      works better.
  225. ;;    - Crude RPL303 handling (reply to ISON).
  226. ;;    - Ripped out irc-maintain-tree! Hooray! Replaced by hash table code
  227. ;;      BUT named the new functions irc-remember, irc-recall, irc-forget.
  228. ;;      This speeded up /NAMES from some 5 minutes to some 10 seconds.
  229. ;; v4.16 Tue Sep 17 21:07:01 1991    Klaus.Zeuge@DoCS.UU.SE
  230. ;;    - When seeing idle time from IrcII clients, translate the large number
  231. ;;      of seconds into days, hours, minutes and seconds.
  232. ;;    - Writing to /dev/null to keep track of idle isn't portable. Use a
  233. ;;      temporary file in the users home directory instead.
  234. ;; v4.15 Thu Aug 22 13:46:03 1991    sojge@mizar.docs.uu.se
  235. ;;    - If user connects to server at host foo.bar.se and foo.se is an
  236. ;;      alias for rela.name.se, Kiwi gets confused. Now irc-server is
  237. ;;      set to real (ie generic) name from the servers Welcome message.
  238. ;;    - Fixed the macro subfield so it won't evaluate at compile time.
  239. ;;      Sigh. Stupid sojge. Thank you Lennart Staflin, Link|ping.
  240. ;;    - Fixed irc-parse-RPL: 317 does NOT give victims nick.
  241. ;;    - Fixed irc-maintain-tree to not crash when removing a service.
  242. ;;    - Added "Notice unauthorized connect" in irc-parse-notice.
  243. ;;    - Added CTCP query and reply for "FINGER". Hopefully this is added in
  244. ;;      a portable way, but I don't really KNOW ... :-(
  245. ;;    - Made irc-is-receiver recognize foo@bar.dom as valid receiver.
  246. ;; v4.14 Mon Aug 12 10:15:05 1991    sojge@mizar.docs.uu.se
  247. ;;    - Fixed /MODE command to work even when saying "/mode ..." in the
  248. ;;      buffer, not only when using C-c m.
  249. ;;    - Fixed some ERR-reply parsing code to grok new format.
  250. ;;    - Added /LEAVE 0 to leave all channels, and made /JOIN 0 just stop
  251. ;;      talking to the current channel.
  252. ;;    - Better nickname control, new scheme with irc-nick-used to keep track
  253. ;;      of what nick we have.
  254. ;;    - Renamed irc-linkstree into irc-linksinfo.
  255. ;;    - Kludged the mess with 2.6 servers first being names 2.6pre19,
  256. ;;      later 2.6.1a so the latter gets a HIGHER irc-edit-version number.
  257. ;;    - Parse RPL 364 messages, ie answers to /LINKS in 2.6.1 servers.
  258. ;;    - For now, ignore message 318.
  259. ;; v4.13 Thu Jun 13 10:28:31 1991    sojge@mizar.docs.uu.se
  260. ;;    - Handle ERR_NICKNAMEINUSE (433) at "login" time.
  261. ;;    - More homogenous command parsing (both /-style and keybound).
  262. ;;    - Cache subscribed channel names.
  263. ;;    - Name  Kiwi buffer "*Kiwi-<server>*".
  264. ;;    - Always run in "slow speed terminal" mode.
  265. ;;    - Shorter messages displayed when seeing a KILL, skipped path.
  266. ;;    - Renamed irc-hosttree into irc-servernames.
  267. ;;    - Added code to put communication in -*debug* buffer IFF it exists.
  268. ;;    - Changed regexp for host names yet again.
  269. ;;    - When getting the windows width, make sure it's the Kiwi window.
  270. ;;    - Prepared function irc to handle several sessions.
  271. ;;    - Handle some 2.6pre19 messages (324, MODE, 403).
  272. ;;    - Bound C-c i to /info.
  273. ;;    - Changed C-c m from /motd to /mode.
  274. ;;    - Fixed misfeature for v18.57 GNU Emacs. Several return values from
  275. ;;      function process-status are valid. Don't start a new session when
  276. ;;      an old one is running.
  277. ;;    - Fixed bug in showing LIST or NAMES reply of Kanjii channel.
  278. ;;    - Clean up channel names as they can contain cntrl-chars too.
  279. ;;    - Fixed display of time to be nicer.
  280. ;;    - Make the (interactive)-part of the irc-execute-* commands more alike
  281. ;;      each other.
  282. ;;    - Bugfix: understand ESC in channel names in a few more places.
  283. ;;    - Bugfix: understand "i" etc, not only "+i" when parsing MODE.
  284. ;;    - Made /COMMAND be shown in buffer when doing command by keys.
  285. ;;    - Amazingly how yours truly can mess up code! Fixed /LEAVE again :-)
  286. ;; v4.12 Sun Mar  3 02:45:21 1991    sojge@mizar.docs.uu.se
  287. ;;    - Changed wording on ctcp (client-to-client protocol) answer for
  288. ;;      a VERSION query.
  289. ;;    - Added C-c C-k to do irc-execute-kill.
  290. ;;    - Bugfixed irc-execute-leave so it works when typing /LEAVE not just
  291. ;;      when typing C-c q.
  292. ;;    - Better handling of /STATS C replies from remote servers.
  293. ;;    - Handle error after /kick user when user's not on channel.
  294. ;; v4.11 Fri Mar  1 16:31:04 1991    sojge@mizar.docs.uu.se
  295. ;;    - Bugfix, corrected misspelled variable for when replying to unkown
  296. ;;      client-to-client PRIVMSG.
  297. ;; v4.10 Thu Feb 28 20:06:05 1991    sojge@mizar.docs.uu.se
  298. ;;    - New behaivour of /WHO, see /HELP WHO.
  299. ;;    - Various bugfixes. (Mostly due to bound keys).
  300. ;;    - Replaced irc-read-user/host by irc-read-object.
  301. ;; v4.9 Wed Feb 27 20:29:58 1991    sojge@mizar.docs.uu.se
  302. ;;    - Added quoting of messages between CNTRL/A:s.
  303. ;;    - Better grok of WALLOPS.
  304. ;;    - Remember correct spelling of a services nickname when seeing
  305. ;;      NOTICES's from one.
  306. ;;    - Bugfixed /CONNECT which w/o "remoteserver" goofed.
  307. ;; v4.8 Wed Feb 27 03:57:50 1991    sojge@mizar.docs.uu.se
  308. ;;    - More initialisation help.
  309. ;;    - Changed client-to-client protocol in non-backward compatible way.
  310. ;;    - OK'ed "/version mizar*".
  311. ;;    - Better handling of /join 0 when on #channel. Updates irc-channel.
  312. ;;    - Changed handling of unknown NOTICE's to be treated as PRIVMSG's.
  313. ;;    - Fixed bug when replying to CLIENT ERRMSG.
  314. ;;    - Show irc-channel in status line.
  315. ;;    - Always send two ^A's, even if to queries/answers are in a row.
  316. ;;    - Made /msg grok broadcast addresses ($server, #host) when enabled.
  317. ;;    - Fixed bugs in /kick.
  318. ;;    - Better help for how to install your personal IRC initiation.
  319. ;; v4.7 Sun Feb  3 03:51:59 1991    sojge@mizar.docs.uu.se
  320. ;;    - Take care of some new styled NOTICE's from the server.
  321. ;;    - Cleaned up the code of irc-parse-priv.
  322. ;;    - Bugfixed irc-parse-kick to keep better track of where we are.
  323. ;;    - Added command /SERVICE.
  324. ;; v4.6 Fri Feb  1 04:03:31 1991    sojge@mizar.docs.uu.se
  325. ;;    - Better handling of /WHOWAS.
  326. ;;    - Changed string from "Kiwi Operator" into "Kiwi, Operator" while
  327. ;;      enabled.
  328. ;; v4.5 Fri Feb  1 02:24:00 1991    sojge@mizar.docs.uu.se
  329. ;;    - Added command /USERINFO to set a string which can be queried by other
  330. ;;      users. Augmented commands /INFO and /VERSION to query the user
  331. ;;      settable string and to query some client version from a users client.
  332. ;;    - Added knowledge of some more NOTICE's from the server.
  333. ;;    - Better handling of STATS, both in giving command (/STATS) and
  334. ;;      parsing L type replies (ie how much data). Added /HELP STATS.
  335. ;;    - Display another field in WHOIS/WHOWAS replies, showing servers text
  336. ;;      field from message 312.
  337. ;;    - Added in irc-parse-notice case for "*** ..." messages.
  338. ;;    - Bugfixed irc-execute-help, so it deals with aliases and topics which
  339. ;;      aren't commands.
  340. ;;    - Changed clients name from sojge-irc.el to Kiwi.el
  341. ;;      (Kiwi initially was irc.el).
  342. ;;    - Added varibales irc-msg-info-pre and -post for letting user select
  343. ;;      how information (default eg: [Foo has joined channel +Bar], the [
  344. ;;      and ] characters) messages start and end.
  345. ;;    - Statistics display nicyfied.
  346. ;; v4.4 Mon Dec 17 17:51:24 1990    sojge@mizar.docs.uu.se
  347. ;;    - Added column alignment (irc-msg-cont-used) for RPL322 and RPL323
  348. ;;      messages (RPL_LIST and RPL_LISTEND).
  349. ;;    - Bugfix: prevents client from crashing (when connected to a 2.6-server
  350. ;;      and doing a TRACE for a nonexistent server) by adding some
  351. ;;      code the for 402 ERR reply (ERR_NOSUCHSERVER).
  352. ;; v4.3 Sun Dec 16 19:19:00 1990    sojge@mizar.docs.uu.se
  353. ;;    - Added case for trace reply "UNKNOWN" in irc-parse-notice.
  354. ;;    - Added key C-c = to do a /MEMBER command.
  355. ;;    - Bugfix: changed general regexp in irc-parse-server-msg to not allow
  356. ;;      spaces in the server part.
  357. ;;    - Made irc-execute-whois handle the /WHOWAS command.
  358. ;;    - Tell the clients version too, after a /VERSION.
  359. ;;    - Bugfix: rewrote irc-execute-topic to put the (interactive) "command"
  360. ;;      in "topmode".
  361. ;;    - Save username in 2.6 kind of USER-traces.
  362. ;;    - Bugfix: Don't remove bogus irc-nick from irc-nicknames on startup
  363. ;;      when setting first nick after default nick failed.
  364. ;; v4.2 Sat Dec 15 04:14:22 1990    sojge@mizar.docs.uu.se
  365. ;;    - Bugfix in irc-parse-server-msg: NOTICE's don't have a : before them
  366. ;;      (except the optional :server part).
  367. ;;    - Can't set topic of a #channel, changed irc-execute-topic.
  368. ;;    - Bugfix: irc-parse-notice now recognizes IRC OPERs as users in traces.
  369. ;;    - Made "NOTICE -- Received kill" equivalente to older
  370. ;;      "NOTICE: Received kill".
  371. ;; v4.1 Thu Dec 13 13:35:43 1990    sojge@mizar.docs.uu.se
  372. ;;    - Zapped irc-news to contain little, but current, information.
  373. ;;    - Corrected bug in alignment of output of who-replies for
  374. ;;      servers w/o end-of-who markes (hello 2.6.pre14!) in
  375. ;;      irc-parse-whoreply.
  376. ;;    - Added knowledge of some trace messages in irc-parse-notice.
  377. ;;    - Fixed bug in irc-parse-notice, so the number of invisble users
  378. ;;      will be displayed if you're an enabled irc operator.
  379. ;;      Thank's heu@byron.u.washington.edu.
  380. ;;    - Fixed irc-execute-links to only reset list of known hosts on
  381. ;;      a LINKS of all the world. (Ie don't reset on LINKS *.SE).
  382. ;;    - Spiffed up sojge-irc's grok of which privmsg go where, changed
  383. ;;      way irc-parse-priv talks to irc-parse-public.
  384. ;;    - Added /MEMBER to show which channels the user's listening and
  385. ;;      talking to.
  386. ;;    - Indicate ircII's CNTRL/B's by *'s.
  387. ;;    - Scrapped [You have joined/left]-messages, instead tell user which
  388. ;;      she's listening and writing to, if any.
  389. ;;    - Added NOTICE-pattern matching of OPER to be analogous to USER
  390. ;;      and CHANOP.
  391. ;;      Thank's kim@lut.fi.
  392. ;;    - Swapped key definitions of C-c C-q and C-c q.
  393. ;;      Thank's kim@lut.fi.
  394. ;;    - Made irc-parse-public look for single old channel in
  395. ;;      irc-subscribed-channels.
  396. ;;    - Added better support for irc-subscribed-channels.
  397. ;;    - irc-parse-RPL, 472: s/inventation/invitation/.
  398. ;;    - Made /WHOWASRPL's be written correctly.
  399. ;;    - Rewrote irc-parse-channel to be better in coping with #channels.
  400. ;;    - Added #channels to be recognized in irc-is-named-channel and in
  401. ;;      irc-is-channelname.
  402. ;;    - Fixed typo in irc-parse-notice.
  403. ;; v4.0 Fri Nov 16 07:06:02 1990    sojge@mizar.docs.uu.se
  404. ;;      Seems to work with both v2.5.1 and v2.6pre14 servers.
  405. ;;    - Made irc-execute-msg send with PRIVMSG is irc-channel is a #channel.
  406. ;;    - Added PART when on 2.6 server in irc-execute-leave.
  407. ;;    - Added JOIN when on 2.6 server in irc-execute-join.
  408. ;;    - Added 2.6 level reply message 317 in irc-parse-RPL.
  409. ;;    - Added 2.6 level commands JOIN and PART in irc-parse-server-msg and
  410. ;;      irc-parse-channel.
  411. ;;    - On nonmatcher NOTICE, just give the notice to the user with out
  412. ;;      frightening her with big WARNING signs.
  413. ;;    - Removed buggy string-match in irc-parse-notice for svarte being
  414. ;;      matched against a terminal (rt).
  415. ;;    - irc-parse-RPL: set irc-msg-cont-used when receiving message 314
  416. ;;      (RPL_WHOWASUSER).
  417. ;;    - Made confirmation when sending to several users/channels at once
  418. ;;      being written one confirmation per line.
  419. ;; v3.14 Thu Nov  1 19:47:09 1990    sojge@mizar.docs.uu.se
  420. ;;    - Made /OOPS work without an argument, if non given, ask for one.
  421. ;;    - Added possible bugfix in irc-parse-RPL for message 322.
  422. ;;    - irc-execute-command: don't put "'s around help w/ possible commands.
  423. ;;    - irc-insert-most: use right-most argument of irc-choose-break-point.
  424. ;;    - irc-insert: use right-most argument of irc-choose-break-point.
  425. ;;    - irc-choose-break-point: use parameter right-most, not (window-width).
  426. ;;    - irc-parse-notice: slightly new "no users logged in" message.
  427. ;;    - irc-parse-notice: write "serverlink", not "connection" in /TRACES.
  428. ;;    - irc-parse-wallops: set irc-msg-cont-used to max window-width / 2.
  429. ;;    - irc-parse-priv: set irc-msg-cont-used to max window-width / 2.
  430. ;;    - irc-parse-public: set irc-msg-cont-used to max window-width / 2.
  431. ;;    - irc-parse-channel: prevent negative string length in pd.
  432. ;; v3.13 Tue Oct  9 04:35:51 1990    sojge@mizar.docs.uu.se
  433. ;;    - Sigh, when do I learn not to release code when being ++tired?
  434. ;;      Fixed a newborn bug in irc-execute-msg.
  435. ;; v3.12 Tue Oct  9 03:49:14 1990    sojge@mizar.docs.uu.se
  436. ;;    - Made a quick and dirty bugfix to prevent crashing in irc-insert-more.
  437. ;;      Sort of works. Sigh.
  438. ;;    - Fixed bug in irc-parse-server-msg, do accept NOTICEs from "strange"
  439. ;;      origins...
  440. ;;    - Set global irc-msg-cont-used in irc-parse-RPL while parsing WHOIS
  441. ;;      replies.
  442. ;;    - Removed two bugs in irc-insert-more.
  443. ;;    - Made /WHOIS STRING trying to get information even if STRING isn't
  444. ;;      remembered in irc-nicknames as being present.
  445. ;;    - Made /WHO USER do a WHOIS USER, while /WHO CHANNEL does a
  446. ;;      WHO CHANNEL.
  447. ;;    - Made irc-execute-wallops confirm if irc-confirm is non-nil.
  448. ;; v3.11 Thu Aug 30 17:41:18 1990    sojge@mizar.docs.uu.se
  449. ;;    - Sigh, fixed bug in irc-execute-whowas. I'd better do a RPLACA...
  450. ;; v3.10 Thu Aug 30 15:47:36 1990    sojge@mizar.docs.uu.se
  451. ;;    - Added irc-execute-whowas (long due).
  452. ;;    - Fixed som other minor bugs. I hope.
  453. ;;    - BUGFIX in irc-remove-from-tree, do comparsion in upcase.
  454. ;;    - Made irc-execute-msg tell if receivers are users or channels.
  455. ;;    - Fixed bug in irc-is-channel. ("-77?" is NOT a channel ID).
  456. ;;    - Recognize Kanji message and replace with generic string.
  457. ;; v3.9 Wed Aug 22 08:07:21 1990    sojge@mizar.docs.uu.se
  458. ;;    - Added a rudimentary function irc-execute-kick.
  459. ;;    - Wrote predicate irc-is-channelname.
  460. ;;    - Updated predicate irc-is-nickname to better reflect reality.
  461. ;;    - Made irc-execute-msg grok channel's as receipants.
  462. ;;    - Added simplistic irc-execute-mode function.
  463. ;;    - FIXED BUG in irc-find-to by rewriting it.
  464. ;;    - Made message 421 grok 2.5 messages too.
  465. ;;    - Added function irc-parse-kick.
  466. ;;    - Added some more (let ((irc-msg-cont-used ...) around irc-insert's.
  467. ;;    - Made irc-explain-mode work.
  468. ;;    - Changed count in irc-execute-send so irc-msg-sent is right justified.
  469. ;; v3.8 Sun Aug 19 04:55:31 1990    sojge@mizar.docs.uu.se
  470. ;;    - BUGFIX: v3.6 introduced bug making it hard to join negative channels,
  471. ;;      now it's easy again.
  472. ;; v3.7 Sat Aug 18 23:48:56 1990    sojge@mizar.docs.uu.se
  473. ;;    - Set irc-msg-cont-used before calling irc-insert for some lists.
  474. ;;    - Understand ERR_NOTONCHANNEL message.
  475. ;;    - Don't explecitly request MOTD (message of the day) when connected
  476. ;;      to v2.5 servers or later. They give it anyway.
  477. ;;    - Don't show the "no topic set" messages from remote old server
  478. ;;      at topic changes.
  479. ;;    - Collect server names in irc-parse-RPL.
  480. ;;    - Added irc-split-lines to make better line splits in irc-insert.
  481. ;; v3.6 Fri Aug 17 04:41:19 1990    sojge@mizar.docs.uu.se
  482. ;;    - Changed format of how the status in a WHO listing appears.
  483. ;;    - Ignore error messages from other old server complaining MODE being
  484. ;;      an unknown command.
  485. ;;    - Understands the WHO-reply statuses "channel operator"
  486. ;;      and "channe operator and IRC operator".
  487. ;;    - Sort of understands reply message 316 .
  488. ;;    - Join channel 007, not +007 at "/join 007" (ie no prepending of + when
  489. ;;      first letter in channelname is a digit).
  490. ;;    - Understand reply message 324.
  491. ;;    - Say "using default" after a "/query *".
  492. ;; v3.5 Thu Jun 14 07:23:51 1990    sojge@emil.csd.uu.se
  493. ;;    - Teached /KILL to understand comments.
  494. ;;    - Added a simplistic header to linreply display.
  495. ;;    - Make it possible for away messages to start with :.
  496. ;;    - Save nickname in irc-parse-wallops.
  497. ;; v3.4 Mon Jun 11 03:55:08 1990    sojge@emil.csd.uu.se
  498. ;;    - Added operator level command /CONNECT.
  499. ;;    - Remapped C-C C-S to be irc-execute-squit.
  500. ;;    - Added operator level command /SQUIT.
  501. ;;    - Added operator level command /WALLOPS.
  502. ;;    - Added some support for mnemonic channel ID's, ie not only numbers
  503. ;;      but also strings can identify a channel. Probaly a bit buggy.
  504. ;;      Problem: How long can an ID be?
  505. ;;    - Made irc-channel into a string, from being a number.
  506. ;;    - Made /WHO SOJGE show a one line WHO reply (plus header) about SOJGE,
  507. ;;      ie not doing a WHOIS for SOJGE. Will probaly change.
  508. ;; v3.3 Wed Jun  6 07:26:57 1990    sojge@emil.csd.uu.se
  509. ;;    - Keep statistics on LIST replies in a new way.
  510. ;;    - Made irc-add-to-tree do it's string comparsions in upper case, this
  511. ;;      prevents the same name in two different cases to be stored.
  512. ;;    - Corrected minor bug in irc-parse-notice about reconizing USERS
  513. ;;      replies.
  514. ;;    - Changed (irc-insert "foo\nbar") into 
  515. ;;      (irc-insert "foo") (irc-insert "bar")
  516. ;;    - Made the "IRC halted" message a bit more flashy.
  517. ;; v3.2 Mon Jun  4 19:59:00 1990    sojge@emil.csd.uu.se
  518. ;;    - When on a fast terminal (see irc-terminal-is-slow), don't bother
  519. ;;      to collect various replies in temporary storage lists. Display the
  520. ;;      unsorted entrys as fast as they come in.
  521. ;;    - Improved handling of /USERS replies.
  522. ;; v3.1 Sat May 26 03:05:46 1990    sojge@emil.csd.uu.se
  523. ;;    - Corrected bug which prevented LINK to actually display any data...
  524. ;; v3.0 Sat May 26 02:21:52 1990    sojge@emil.csd.uu.se
  525. ;;    - Changed version from 1.9 to 3.0 in one step.
  526. ;;    - Set irc-nick according to incoming NOTICE messages.
  527. ;;    - Made the WHOREPLY header be displayed when the first reply comes in.
  528. ;;    - Understand message 314, RPL_WHOWASUSER.
  529. ;;    - Renamed irc-nameslist (former irc-whotree) into irc-nicknames.
  530. ;;    - Added case for "no motd at server", both for 2.4 and pre 2.4 servers.
  531. ;;    - Beautified "IRC server xx runs version yy" message.
  532. ;;    - Added irc-execute-version.
  533. ;;    - Added irc-execute-motd.
  534. ;; v1.9 Sat May 19 14:44:58 1990    sojge@emil.csd.uu.se
  535. ;;    - Wrote irc-parse-pong to collect host name from ping messages.
  536. ;;    - Made irc-extract-hosts skip parts between between nodename and "!".
  537. ;;    - Made WHO lists more mnemonic.
  538. ;;    - Made LINREPLYs be gathered in a variable before sorting and
  539. ;;      displaying it even for 2.2 type servers.
  540. ;;    - Make client ask for the message of the day (MOTD) when seeing
  541. ;;      the (final line of the) servers welcome message, not at "start up".
  542. ;;    - Look as far as 1/3 of the line from the right when choosing a
  543. ;;      break point in irc-insert. Makes a few listing look better on
  544. ;;      a 80 column screen.
  545. ;;    - Take care of "unknown connection" message in irc-parse-notice.
  546. ;; v1.8 Thu May 17 00:53:20 1990    sojge@emil.csd.uu.se
  547. ;;    - Say "use /HELP" if user seems totaly confused on channel 0.
  548. ;;    - Fixed bug in irc-parse-whoreply, don't add header to irc-whotree.
  549. ;;    - Say "no users" on a 2.4 (or later) server if user issued /who 
  550. ;;      for an empty channel.
  551. ;; v1.7 Wed May 16 23:34:01 1990    sojge@emil.csd.uu.se
  552. ;;    - Show time when being pinged, not every x minutes.
  553. ;;    - Don't crash if server closed connection, reopen it,
  554. ;;    - Skip some messages like START OF MOTD ...
  555. ;;    - Show what remote server, if any, a message came from.
  556. ;;    - Take care of a bunch of new NOTICE messages.
  557. ;;    - Understand new (server v2.4) type of welcome message.
  558. ;;    - Ignore empty lines from server.
  559. ;;    - Moved logic about format of different information keeping trees
  560. ;;      into irc-maintain-tree.
  561. ;;    - Made (most) error messages start with a % sign.
  562. ;;    - Renamed IRC-WHOTREE into IRC-NAMESTREE.
  563. ;;    - Keeps track of what version the used server is, and depending on it
  564. ;;      uses (or not) the fact that it's possible to gather WHOREPLYs and
  565. ;;      LINREPLYs before displaying it. Exploits the "end of who/links"
  566. ;;      message from the server.
  567. ;;    - Understands new MOTD notices, collects data until end-of-motd-list.
  568. ;;    - Better handling of extracting hostnames from different places.
  569. ;;      Uses irc-extract-hostname.
  570. ;;    - Made irc-maintain-tree use upcase and irc-extract-hostname on items
  571. ;;      for irc-hosttree.
  572. ;;    - Now extracts info from MOTD replies.
  573. ;; v1.6 Mon Apr  9 22:25:22 1990    sojge@emil.csd.uu.se
  574. ;;    - Improved handling of %-signs in messages (data part so to say) by
  575. ;;      doing a s/%/%%/ in functions irc-parse-public and irc-parse-privmsg.
  576. ;; v1.5 Mon Apr  9 17:32:51 1990    sojge@emil.csd.uu.se
  577. ;;    - Extract server names from KILL messages paths.
  578. ;; v1.4 Fri Apr  6 01:30:46 1990    sojge@emil.csd.uu.se
  579. ;;    - Removed s/%/%%/ from irc-parse-server-msg.
  580. ;;    - Let function irc check that the *IRC* buffer has an open stream
  581. ;;      "process" associated with it before trying to switch to the buffer.
  582. ;;      This is handy when the stream has been closed.
  583. ;; v1.3 Tue Apr  3 23:51:38 1990    sojge@emil.csd.uu.se
  584. ;;    - Made irc.el cope with new format on some NOTICE messages.
  585. ;;      (:server NOTICE ...)
  586. ;; v1.2 Fri Mar 30 03:42:31 1990    sojge@emil.csd.uu.se
  587. ;;    - Changed protocol, initiate with USER <username> * * <realname> now.
  588. ;;    - Changed misc. error messages to start with %.
  589. ;;    - Made a few "server message unkown" messages tell where they are
  590. ;;      in the code.
  591. ;;    - Added code to make WHOIS * invokde WHOIS for all users.
  592. ;;    - Made irc-parse-channel set irc-msg-cont-used.
  593. ;;    - Added and removed code for automatic greeting of new joiners to
  594. ;;      channels, in irc-parse-channel. But this doesn't seem to be enough.
  595. ;;      More debugging needed ...
  596. ;;    - Made irc.el understand MOTD messages from server, not reliying on
  597. ;;      all lines in MOTD file starting with a blank.
  598. ;; v1.1 Mon Mar 26 03:37:03 1990    sojge@emil.csd.uu.se
  599. ;;    - Cleaned up some more, in how things are displayed. Servers
  600. ;;      domain names are displayed in upper case, in
  601. ;;      irc-parse-linrpl and their information text "as is". Some
  602. ;;      headers  are underlined.
  603. ;;    - Corrected (?) bug in irc-parse-RPL which handled RPL_MOTD
  604. ;;      messages incorrectly.
  605. ;; v1.0 Wed Feb 28 21:53:49 1990    sojge@emil.csd.uu.se
  606. ;;    - Changed look and feel by introducing a couple of variables
  607. ;;      and removing the conserve-space kludge. Apperence is now user
  608. ;;      settable.
  609. ;;    - Rewritten buggy irc-insert so it works. No more infinite looping.
  610. ;;    - Added a few key bindings.
  611. ;;    - Made irc-parse-RPL (at RPL_WHOISSERVER) and irc-parse-notice add
  612. ;;      information to the irc-hostlist, just like irc-parse-linreply does.
  613. ;; v0.9 Sometime 1989    flax@mizar.docs.uu.se
  614. ;;    - Made irc-linreply add to a list of known hosts so completion of
  615. ;;      host names in irc-execute-admin and others will work. Neat.
  616. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  617. ;; Author          : David C Lawrence           <tale@pawl.rpi.edu>
  618. ;; Created On      : Wed Jun 14 22:22:57 1989
  619. ;; Last major modification: Jonas Flygare
  620. ;; Last minor modification: Klaus Zeuge
  621. ;; Last Modified On: Wed Jan 24 00:54:29 1990
  622. ;; Update Count    : 100
  623. ;; Status          : Stable
  624. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  625. ;;  Copyright (C) 1989  David C Lawrence
  626.  
  627. ;;  This program is free software; you can redistribute it and/or modify
  628. ;;  it under the terms of the GNU General Public License as published by
  629. ;;  the Free Software Foundation; either version 1, or (at your option)
  630. ;;  any later version.
  631.  
  632. ;;  This program is distributed in the hope that it will be useful,
  633. ;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
  634. ;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  635. ;;  GNU General Public License for more details.
  636.  
  637. ;;  You should have received a copy of the GNU General Public License
  638. ;;  along with this program; if not, write to the Free Software
  639. ;;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  640.  
  641. ;; Comments and/or bug reports about this interface should be directed to:
  642. ;;     Dave Lawrence          <tale@{pawl,itsgw}.rpi.edu>
  643. ;;     76 1/2 13th Street     +1 518 273 5385
  644. ;;     Troy NY 12180          Generally available on IRC as "tale"
  645.  
  646. ;; History         
  647. ;; 27-Sep-1989        Gnu Maint Acct    (gnu at life.pawl.rpi.edu)
  648. ;;    Last Modified: Wed Sep 27 18:56:19 1989 #6
  649. ;;    * Fixed a misrefenced variable in irc-parse-server-msg so that lines
  650. ;;      which can't be parsed insert only that unparsable line.
  651. ;;    * Added irc-parse-topic and changed irc-signals and irc-notifies
  652. ;;      appropriately.
  653. ;;    * Moved setting of irc-channel to irc-parse-channel from irc-execute-join
  654. ;;      because a channel change isn't guaranteed (ie, trying to change to
  655. ;;      a channel not in 0-10 which has ten users on it).
  656. ;;    * Made irc-message-stamp 'private by default. (Geoff)
  657. ;;    * Made irc-time-stamp 0 by default.      (Also Geoff)
  658. ;;      This tickled an unseen bug in the start-up function which incremented
  659. ;;      irc-last-stamp.  It's fixed now.
  660. ;;    * Fixed a bug with interactive irc-execute-names -- prefix arg was being
  661. ;;      (list ...)ed.
  662. ;;    * Fixed a bug in irc-parse-namreply that dropped a name in the output
  663. ;;      when a line got wrapped.
  664. ;;    * Added /lusers.  I really dislike the name.
  665. ;;    * Added irc-parse-kill.
  666. ;;    * Made irc-execute-msg strip one space after the colon in messages;
  667. ;;      ie, "tale: hi" will send "hi" as a message not " hi".
  668. ;;    * Took out hardcoded width numbers for word-wrapping.  Uses
  669. ;;      (window-width) instead.
  670. ;;    * Added to the regexp for failed nickname changes in irc-parse-error;
  671. ;;      the sentences got changed in the newer servers.
  672. ;;    * Wrapped irc-check-time around display-time-filter for better accuracy
  673. ;;      if a display-time process is running.
  674. ;;    * Made the "IRC Session finished" message include the time.
  675. ;;    * Added irc-conserve-space to imitate the C client message style.  I
  676. ;;      really dislike it aesthetically, but it is handy for people running
  677. ;;      on 24 line screens and at slow baud rates. (Kimmel & others)
  678. ;;    * Support IRCNICK and IRCSERVER environment variables at load time. (Kim)
  679. ;;    * Made /WHO call /WHOIS if given a non-numeric argument.  (Nate)
  680. ;;    * Fixed a bug where an alias would be executed before an exactly matching
  681. ;;      command; ie, alias /WHOALIAS whould execute when /WHO was entered.
  682. ;;    * Runs things in auto-fill-mode with a fill-column of 75 by default.
  683. ;;    * Processes the whole input region as one line instead of line-at-a-time.
  684. ;;    * Made irc-change-alias for non-interactive setting/removing of aliases;
  685. ;;      ie, via irc-mode-hook.  No frills.  (Chris & Nate)
  686. ;;    * _Finally_ got around to adding parsing of numeric notices for new
  687. ;;      servers.
  688.  
  689. ;; Need backquote.el for our macros.
  690. (require 'backquote)
  691.  
  692.  
  693. ;; Defined variables
  694.  
  695. (defvar irc-abusive-ignore nil
  696.   "If non nil, send back a message to persons being ignored, instead of
  697. being silent, while throwing away messages from them.")
  698.  
  699.  
  700. (defvar irc-alias-alist
  701.   '(
  702.     ("?" . "help")            ; Abbrevation
  703.     ("BYE" . "quit")
  704.     ("CHANNEL" . "join")
  705.     ("END" . "quit")            ; Plenty of ways out
  706.     ("EXIT" . "quit")
  707.     ("IDLE" . "who")            ; for people too used to Connect
  708.     ("L" . "list")            ; Abbrevation
  709.     ("M" . "msg")            ; Abbrevation
  710.     ("MS" . "msg")            ; Abbrevation
  711.     ("N" . "names")            ; Abbrevation
  712.     ("QUERY" . "send")            ; For people used to the C client
  713.     ("STOP" . "quit")            ; Plenty of ways out
  714.     ("U". "users")            ; Abbrevation
  715.     ("US". "users")            ; Abbrevation
  716.     ("USE". "users")            ; Abbrevation
  717.     ("USER". "users")            ; Abbrevation
  718.     ("W" . "who")            ; Abbrevation
  719.     ("WHAT" . "list")            ; /WHAT from Connect
  720.     )
  721.   "An association list of command aliases used in irc-mode.
  722. This is the first list checked when irc-mode is looking for a command and it
  723. is maintained with the /ALIAS and /UNALIAS commands.")
  724.  
  725.  
  726. (make-variable-buffer-local
  727.  (defvar irc-cache-n+s nil
  728.    "Cache of known nicks and servers"))
  729.  
  730.  
  731. (make-variable-buffer-local
  732.  (defvar irc-cache-c+n+s nil
  733.    "Cache of known channels, nicks and servers"))
  734.  
  735.  
  736. (make-variable-buffer-local
  737.  (defvar irc-called-from-buffer nil
  738.    "Flag saying whether a command is called from the irc buffer with /names
  739. or invoked through pressing a key like C-c C-c."))
  740.  
  741.  
  742. (make-variable-buffer-local
  743.  (defvar irc-called-from-buffer nil
  744.    "Flag saying whether a command is called from the irc buffer with /names
  745. or invoked through pressing a key like C-c C-c."))
  746.  
  747.  
  748. (defconst irc-command-alist
  749.     '(("ADMIN" . "admin")        ; Get information about IRC admins
  750.       ("ALIAS" . "alias")        ; Add command aliases
  751.       ("AWAY" . "away")            ; Give som indication of your presenc
  752.       ("CONFIRM" . "confirm")        ; Set message confirmation on or off
  753.       ("DESCRIBE" . "describe")        ; CTCP action.
  754.       ("DIE" . "die")            ; Tell server to die.
  755.       ("EVENT" . "event")        ; Change which events give notification
  756.       ("FINGER" . "finger")        ; CTCP finger.
  757.       ("HELP" . "help")            ; Get help on the /COMMANDs
  758.       ("HERE" . "here")            ; Remove the away mark
  759.       ("IGNORE" . "ignore")        ; Ignore messages from a specified user
  760.       ("INFO" . "info")            ; Information about users and authors
  761.       ("INVITE" . "invite")        ; Ask another user to join your channel
  762.       ("JOIN" . "join")            ; Join a channel
  763.       ("KICK" . "kick")            ; Boot a user from a channel
  764.       ("LEAVE" . "leave")        ; Leave a channel
  765.       ("LINKS" . "links")        ; Show which servers are in the IRC-net
  766.       ("LIST" . "list")            ; Show a list of channels and topics
  767.       ("LUSERS" . "lusers")        ; Get the number of users and servers
  768.       ("MAIL" . "mail")            ; Give commands to the mail subsystem.
  769.       ("ME" . "me")            ; Send a CTCP ACTION message to channel
  770.       ("MEMBERSHIPS" . "memberships")    ; Show subscribed channels.
  771.       ("MODE" . "mode")            ; Change or inspect the mode of a chan
  772.       ("MOTD" . "motd")            ; Message of the day
  773.       ("MSG" . "privmsg")        ; Send a private message to someone
  774.       ("NAMES" . "names")        ; Display nick names on each channel
  775.       ("NEWS" . "news")            ; Show news about client.
  776.       ("NICKNAME" . "nick")        ; Change your IRC nickname
  777.       ("NOTIFY" . "notify")        ; Notify when selected nicks are seen
  778.       ("OOPS" . "oops")            ; Resend a misdirected message
  779.       ("OPER" . "oper")            ; Login as an IRC operator
  780.       ("QUIT" . "quit")            ; Exit IRC
  781.       ("QUOTE" . "quote")        ; Send raw text to the server
  782.       ("PING" . "ping")            ; Send CTCP PING to another user
  783.       ("REDIRECT" . "redirect")        ; Send the last message to someone else
  784.       ("SEND" . "send")            ; Set the implicit send list for msgs's
  785.       ("SERVICE" . "service")        ; Add and subtract to list of automates
  786.       ("SIGNAL" . "signal")        ; Change which events give a signal
  787.       ("STAMP" . "stamp")        ; Set time notification interval
  788.       ("STATS" . "stats")        ; Get statistics from server.
  789.       ("SUMMON" . "summon")        ; Ask a user not on IRC to join it
  790.       ("TIME" . "time")            ; Get the current time from a server
  791.       ("TOPIC" . "topic")        ; Change the topic of the channel
  792.       ("TRACE" . "trace")        ; Show the links between servers
  793.       ("UNALIAS" . "unalias")        ; Remove command aliases
  794.       ("UNIGNORE" . "unignore")        ; Stop ignoring user
  795.       ("USERINFO" . "userinfo")        ; Set information about oneself
  796.       ("USERS" . "users")        ; Show users logged in at a server
  797.       ("VERSION" . "version")        ; Version of a server or a users client
  798.       ("WALLOPS" . "wallops")        ; Send a message to all operators
  799.       ("WHO" . "who")            ; Get list of users and their channels
  800.       ("WHOIS" . "whois")        ; Get longer information about a user
  801.       ("WHOWAS" . "whois"))        ; Check who user who has left IRC was.
  802.   "An association list of the regular commands to which all users have access.
  803. Form is (\"COMMAND\" . \"function\") where \"function\" is that last element in
  804. an irc-execute-* symbol.  See also irc-alias-alist and irc-operator-alist.")
  805.  
  806.  
  807. (defvar irc-confirm t
  808.   "*If non-nil, provide confirmation for messages sent on IRC.
  809. It should be noted that confirmation only indicates where irc-mode
  810. tried to send the message, not whether it was actually received.
  811. Use the /CONFIRM command to change.")
  812.  
  813.  
  814. (make-variable-buffer-local
  815.  (defvar irc-default-to "*;"
  816.    "The default recipient of a message if no : or ; is provided.
  817. \"*\" means the current channel, no matter what it is."))
  818.  
  819.  
  820. (make-variable-buffer-local
  821.  (defvar irc-drop-ircII-text-kludge-control-characters t
  822.    "*If nil, show CNTRL/B, CNTRL/V and CNTRL/_ as ^B. ^V and ^_ in text. These
  823. characters are used as a kludge by the client ircII to toggle the attributes
  824. reverse, underline and bold respectivly in text. If non-nil, drop those three
  825. characters."))
  826.  
  827.  
  828. (defvar irc-emacs-knows-ISO8859-1 (>= (string-to-int emacs-version) 19)
  829.   "*Non-nil if Kiwi shouldn't translate octets in incoming messages with
  830. the high bit set to \xyz strings; nil if translation for such characters
  831. (0240 - 0377) should occur.")
  832.  
  833.  
  834. (make-variable-buffer-local
  835.  (defvar irc-events '(ctcp join nick quit topic)
  836.    "Events in IRC that should get notification messages.
  837. A notification message is just one line to indicate that the event has
  838. occurred.  The \"ctcp\", \"join\", \"nick\", \"quit\" and \"topic\"
  839. events are currently supported by the /EVENT command."))
  840.  
  841.  
  842. (defconst irc-help-topic-alist
  843.     '((";" . "Usage: RECEIVER[,RECEIVER]...; MESSAGE
  844.  
  845. Send a message to one or several receivers.
  846. About the same as /MSG and :, see /HELP : and /HELP MSG.
  847.  
  848. When no receiver is given yet, on a line, and you press ; first on that line,
  849. the last receiver is inserted (this may be a users nickname, a channelname,
  850. a list of receivers, etc)
  851.  
  852. Don't use any spaces left of the ;.")
  853.       (":" . "Usage: RECEIVER [, RECEIVER] ... ; MESSAGE
  854.  
  855. Send a message to one or several receivers.
  856. About the same as /MSG and ;, see /HELP ; and /HELP MSG
  857.  
  858. When no receiver was given yet, and : is inserted first on the line, the
  859. last person you sent to will be the default receiver.
  860.  
  861. Don't use any spaces left of the :.")
  862.       ("STARTUP" . "Initiation and startup
  863.  
  864. To make your GNU Emacs know of this IRC user interface, you can add
  865. the following command to your GNU Emacs initialisation file (normaly
  866. .emacs) in your home directory:
  867.         (autoload 'irc \"Kiwi\"
  868.             \"Internet Relay Chat user interface.\" t nil)
  869.  
  870. This will make your Emacs to load the library file Kiwi.elc or Kiwi.el
  871. when you typing M-x irc RET. The file must be in one of the
  872. directories mentioned in the variable load-path. (You can check this
  873. variables value by typing C-h v load-path RET). You can compile the
  874. file Kiwi.el by typing M-x byte-compile-file RET Kiwi.el RET to get
  875. Kiwi.elc.
  876.  
  877. At startup time of IRC, you may want to initiate some settings and
  878. give some commands. This can be done by setting some variables in your
  879. GNU Emacs initialisation file (normaly called .emacs). Some typical
  880. initialisations may be
  881.  
  882.        (setq irc-server \"minsk.docs.uu.se\"      ;Which server to use.
  883.              irc-msg-public \"%s%9s/%s:  \"       ;How to display public msgs
  884.              irc-pop-on-signal 3                ;Use about 1/3 of screen when
  885.                                                 ; popping up a Kiwi buffer.
  886.              ;; Give some information about yourself, whatever you want.
  887.              irc-userinfo (concat
  888.                            \"Studying computer science at the university of\"
  889.                            \" Uppsala. Call me on +46 18 463253.\")
  890.              ;; Commands to be executed when seeing the Welcome message
  891.              ;; from a server we just connected to.
  892.              irc-startup-hook '(lambda ()
  893.                                 (irc-execute-command \"links *.se\")
  894.                                 (irc-execute-command \"who *.se\")))
  895.  
  896. This will make IRC use about 1/3 of the screen when popping up a
  897. window (this happens for instance when you have deselcted all IRC
  898. windows and someone sends you a message). Also, the information string
  899. for you (which can contain any information you choose) is initiated.
  900. When a server says \"welcome\", you will be shown all active servers
  901. in Sweden (SE) and all active users using IRC in Sweden.
  902.  
  903. Don't give the leading / in the arguments to irc-execute-command.
  904.  
  905. If you want more control over how to display public and/or private messages
  906. (at the time exluding WALLs and WALLOPSs) you can use this clumsy way (be
  907. patient, a more user friendly method is on it's way) of setting the variables
  908. irc-public-insert and irc-private-insert to functions taking 3 strings as
  909. arguments, namely the name of the sender, name of the receiver (user or channel
  910. name normaly) and the message itself (in raw format, after extracting the
  911. client-to-client protocol stuff). All this sums up to, that if you don't know
  912. elisp, you probaly don't want to use this method, or else just change the
  913. control string constants in the examples below.
  914. Examples:
  915.   (setq
  916.    irc-public-insert '(lambda (from to msg)
  917.                (let* ((same-chan (string= (upcase irc-channel)
  918.                           (upcase to)))
  919.                   (hdr
  920.                    (format (if same-chan
  921.                        \"%s %9s:  \"
  922.                        \"%s %9s/%s:  \")
  923.                        (if (and irc-message-stamp
  924.                         (not (eq irc-message-stamp
  925.                              'private)))
  926.                        (irc-get-time)
  927.                        \"\")
  928.                        from
  929.                        to))
  930.                   (irc-msg-cont-used
  931.                    (make-string 
  932.                 (min (length hdr)
  933.                      (/ (window-width (get-buffer-window
  934.                                (current-buffer)))
  935.                     2))
  936.                 ? )))
  937.              (irc-insert
  938.               (concat hdr (irc-clean-up-message msg)))))
  939.    irc-private-insert '(lambda (from to msg)
  940.             (let* ((to-whom
  941.                 (cond ((string= (upcase irc-nick-used)
  942.                         (upcase to))
  943.                        \"*%s %s*  \")
  944.                       ((irc-is-broadcastname to)
  945.                        (concat \"=%s %s BROADCAST to all\"
  946.                            \"users on IRC server(s)\"
  947.                            \" \\\"%s\\\"=  \"))
  948.                       (t \"*%s %s/%s*  \")))
  949.                    (hdr
  950.                 (format to-whom
  951.                     (if (and
  952.                          irc-message-stamp
  953.                          (eq irc-message-stamp
  954.                          'private))
  955.                         (irc-get-time)
  956.                         \"\")
  957.                     from
  958.                     to))
  959.                    (irc-msg-cont-used (make-string 
  960.                            (min (length hdr)
  961.                             (/ (window-width (get-buffer-window (current-buffer)))
  962.                                2))
  963.                            ? )))
  964.               (irc-insert
  965.                (concat hdr (irc-clean-up-message msg))))))
  966.  
  967. Hint: the internal control strings uses 2 or 3 of the %s to write the time,
  968. the senders name and the receivers name. If only 2 %s are given, the receivers
  969. name won't be written.
  970.  
  971. [Note: this is a preliminary version of the help text, please send mail
  972. to Klaus.Zeuge@Student.DoCS.UU.SE if you think it needs to be changed.]"))
  973.   "A-list with car = keyword-string for a topic and cdr = descriptions string
  974. of the keyword.")
  975.  
  976.  
  977. (make-variable-buffer-local
  978.  (defvar irc-history nil
  979.    "A list of messages which irc-mode has processed.
  980. This includes both successfully and unsuccessfully sent messages, starting
  981. with the most recent first.  irc-max-history limits the number of items
  982. that can appear in the list when using irc-add-to-history."))
  983.  
  984.  
  985. (make-variable-buffer-local
  986.  (defvar irc-ignore-automatic-warnings nil
  987.    "*Variable to say whether to to display or not display automatic warnings
  988. from users. Such warnings start with the marker \"<Automatic warning> \" in
  989. a message either directly to to, or on a channel. The default and RECOMMENDED
  990. value is nil, ie to display. Set to non-nil to supress such messages."))
  991.  
  992.  
  993. (make-variable-buffer-local
  994.  (defvar irc-ignores nil
  995.    "A list of NICKNAMES whose events will be ignored.
  996. Messages or other actions (like joining a channel) generated by anyone in
  997. the list will not be displayed or signalled.  This list is maintained with
  998. the /IGNORE and /UNIGNORE commands."))
  999.  
  1000.  
  1001. (make-variable-buffer-local
  1002.  (defvar irc-ignore-trunk nil
  1003.    "A trunk (for now an array of hash tables) of events and nicks to ignore."))
  1004.  
  1005.  
  1006. (defvar irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1 nil
  1007.   "*Set to true if you want the sevenbit ISO 646-SE2 characters @[\]^`{|}~ to
  1008. be mapped into the corrosponding eightbith ISO 8859-1 characters when
  1009. being typed.
  1010.  
  1011. Set to nil to get no such mapping.
  1012.  
  1013. Set to neither t or nil if you want to get the mapping with the case
  1014. for ], [, \\ reversed, i.e. want to have the [ key treated as \344 and
  1015. the { key treated as \304.")
  1016.  
  1017.  
  1018. (defvar irc-max-history 40
  1019.   "*The maximum number of messages retained by irc-mode.
  1020. This limits messages sent, not messages received.  They are stored to be
  1021. easily recalled by irc-history-prev and irc-history-next (C-c C-p and C-c C-n
  1022. by default).")
  1023.  
  1024.  
  1025. (defvar irc-max-server-message-length 512
  1026.   "The maximum length of a message one can send to a server. This include the
  1027. trailing CRLF, so the \"real\" message length is 2 less.")
  1028.  
  1029.  
  1030. (defvar irc-maximum-size (* 64 1024)
  1031.   "*Maximum size that the *Kiwi-server* buffer can attain, in bytes.
  1032. The default value of 64KB represents an average of about 1500 lines, or roughly
  1033. 65 screens on a standard 24 line monitor. See also irc-minimum-size.")
  1034.  
  1035.  
  1036. (defvar irc-message-stamp 'private
  1037.   "*Mark messages received in IRC with the time of their arrival if non-nil.
  1038. If this is the symbol \"private\" or \"public\" then only messages of the
  1039. specified type are marked with the time.  WALL messages are always
  1040. time-stamped.")
  1041.  
  1042.  
  1043. (defvar irc-minimum-size (* 32 1024)
  1044.   "*Minimum size that the *Kiwi-server* buffer will get truncated to after
  1045. hitting the size in irc-maximum-size.")
  1046.  
  1047. (defvar irc-mode-hook nil
  1048.   "*Hook to run after starting irc-mode but before connecting to the server.")
  1049.  
  1050.  
  1051. (defvar irc-mode-map nil
  1052.   "The keymap which irc-mode uses.
  1053.  
  1054. Currently set to: \\{irc-mode-map}")
  1055.  
  1056.  
  1057. (make-variable-buffer-local
  1058.  (defvar irc-msg-info-post (if (boundp 'irc-msg-info-post)
  1059.                    irc-msg-info-post
  1060.                  "]")
  1061.    "*String to end an information message with."))
  1062.  
  1063.  
  1064. (make-variable-buffer-local
  1065.  (defvar irc-msg-info-pre (if (boundp 'irc-msg-info-pre)
  1066.                   irc-msg-info-pre
  1067.                 "[")
  1068.    "*String to start an information message with."))
  1069.  
  1070.  
  1071. (make-variable-buffer-local
  1072.  (defvar irc-msg-cont (if (boundp 'irc-msg-cont)
  1073.               irc-msg-cont
  1074.             (make-string 23 (string-to-char " ")))
  1075.    "*The string put first on a continued line."))
  1076.  
  1077.  
  1078. (make-variable-buffer-local
  1079.  (defvar irc-msg-priv (if (boundp 'irc-msg-priv)
  1080.               irc-msg-priv
  1081.             "==%%s%%%ds == ")
  1082.    "*The string put first on a line where a private message begins,
  1083. using TIME and SENDER strings, and EXTRA string."))
  1084.  
  1085.  
  1086. (make-variable-buffer-local
  1087.  (defvar irc-msg-public (if (boundp 'irc-msg-public)
  1088.                 irc-msg-public
  1089.               "-- %s%9s (on %s) -- ")
  1090.    "*The string put first on a line where a public message begins,
  1091. using TIME string, SENDER string and CHANNEL number"))
  1092.  
  1093.  
  1094. (make-variable-buffer-local
  1095.  (defvar irc-msg-sent (if (boundp 'irc-msg-sent)
  1096.               irc-msg-sent
  1097.             "(Message sent to %s)")
  1098.    "*Message displayed after sending a string to the server.
  1099. Contains TYPE (ie \"channel\" or \"person\") and RECEIVER (ie channel name or
  1100. users nick)."))
  1101.  
  1102.  
  1103. (make-variable-buffer-local
  1104.  (defvar irc-msg-wall (if (boundp 'irc-msg-wall)
  1105.               irc-msg-wall
  1106.             "##%s%s ## ")
  1107.    "*The string put first on a line where awrite all (wall) message begins,
  1108. using TIME and SENDER strings."))
  1109.  
  1110.  
  1111. (make-variable-buffer-local
  1112.  (defvar irc-multiple-leave-in-progress nil
  1113.    "Flag saying whether a multiple /LEAVE command is in progress, so that
  1114. irc-parse-channel shouldn't call irc-show-subscribed-channels."))
  1115.  
  1116.  
  1117. (make-variable-buffer-local
  1118.  (defvar irc-nick (or (getenv "IRCNICK") (user-login-name))
  1119.    "*The nickname with which to enter IRC.
  1120. The default value is set from your login name.  Using /NICKNAME changes it."))
  1121.  
  1122.  
  1123. (defconst irc-legal-session-name "^\\*Kiwi-\\([^/]+\\)/\\([0-9]+\\)\\*$"
  1124.   "A regexp describing a legal session-name. (See irc-get-*-from-session-name).
  1125. Two fields are extracted, the first being a host name, and the second a
  1126. TCP port number.")
  1127.  
  1128.  
  1129. (defvar irc-notify-interval 2
  1130.   "*How often to check for people. The time is in minutes.")
  1131.  
  1132.  
  1133. (defvar irc-oops "Oops ... please ignore that."
  1134.   "*The text to send to the original IRC message recipient when using /OOPS.")
  1135.  
  1136.  
  1137. (defconst irc-operator-alist
  1138.   '(("CONNECT" . "connect")        ; Establish links between servers
  1139.     ("KILL" . "kill")            ; Forcibly remove a user
  1140.     ("REHASH" . "rehash")        ; Reread irc.conf
  1141.     ("SQUIT" . "squit")        ; Quit links between servers
  1142.     ("WALL" . "wall"))        ; Send a message to everyone on IRC
  1143.   "As association list of commands which only an IRC Operator can use.
  1144. It is kept as a separate list so that regular users won't wonder how
  1145. come the commands don't work for them.")
  1146.  
  1147.  
  1148. (make-variable-buffer-local
  1149.  (defvar irc-output-character-set (if (boundp 'irc-output-character-set)
  1150.                       irc-output-character-set
  1151.                     (if irc-emacs-knows-ISO8859-1
  1152.                     'ISO-8859-1
  1153.                       'ASCII))
  1154.    "*Specifies whether the Emacs understands just ASCII (seven bit characters),
  1155. ISO-8859/1 (8 bits) or Kanjii (16 bits). The value is one of the following
  1156. atoms: ASCII ISO-8859-1 KANJII"))
  1157.  
  1158.  
  1159. (defvar irc-pop-on-signal 4
  1160.   "*An integer value means to display the *IRC* buffer when a signal is issued.
  1161. The number represents roughly how much of the Emacs screen to use when
  1162. popping up the IRC window if only one window is visible.  The reciprocal
  1163. is used, so a value of 1 causes the window to appear full-screen, 2 makes
  1164. the window half of the screen, 3 makes it one third, et cetera.  If the value
  1165. is not an integer then no attempt is made to show the *IRC* buffer if it
  1166. is not already visible.")
  1167.  
  1168.  
  1169. (make-variable-buffer-local
  1170.  (defvar irc-port (if (boundp 'irc-port)
  1171.               irc-port
  1172.             (let* ((p (getenv "IRCPORT"))
  1173.                (np (and p (string-to-int p))))
  1174.               (if (and (numberp np) (> np 0) (< np 16384)) np 6667)))
  1175.    "*The port on which the IRC server responds.
  1176. Many sites don't have irc as a named service (ie, it has no entry in
  1177. /etc/inetd.conf) so you might have to set this to a number; the most
  1178. common configuration is to have IRC respond on port 6667. If there is
  1179. an enviroment variable called IRCPORT and it's value is nummeric
  1180. between 1 and 16387, that value is used instead."))
  1181.  
  1182.  
  1183. (defvar irc-private-insert nil
  1184.   "*Hook to be used to insert private messages (PRIVMSG) sent to you.")
  1185.  
  1186.  
  1187. (defvar irc-processes nil
  1188.   "All currently open streams to irc-servers are kept in this list.
  1189. It is used so that the \"irc\" function knows whether to start a new process
  1190. by default.")
  1191.  
  1192.  
  1193. (defvar irc-public-insert nil
  1194.   "*Hook to be used to insert public messages (MSG) sent to channel.")
  1195.  
  1196.  
  1197. (make-variable-buffer-local
  1198.  (defvar irc-reply-count 0
  1199.    "Internal Kiwi variable to keep track of number of replies to /LINKS,
  1200. /NAMES, or /WHO."))
  1201.  
  1202.  
  1203. (make-variable-buffer-local
  1204.  (defvar irc-reply-count-interval 1
  1205.    "Internal Kiwi variable to keep track of how many seconds should
  1206. pass at least between each display of irc-reply-count when waiting
  1207. for the reply of a /LINKS, /NAMES, or /WHO to finnish."))
  1208.  
  1209.  
  1210. (make-variable-buffer-local
  1211.  (defvar irc-reply-count-time '(0 0)
  1212.    "Internal Kiwi variable to keep track of en irc-reply-count was displayed
  1213. last."))
  1214.  
  1215.  
  1216. (make-variable-buffer-local
  1217.  (defvar irc-scroll-step (if (boundp 'irc-scroll-step)
  1218.                  irc-scroll-step
  1219.                  nil)
  1220.    "*The scroll step used by irc-insert. Set to non-number to get
  1221. the nice automatic behaivour you get by default."))
  1222.  
  1223.  
  1224. (make-variable-buffer-local
  1225.  (defvar irc-server (if (boundp 'irc-server)
  1226.             irc-server
  1227.               (or (getenv "IRCSERVER") "irc.ludd.luth.se"))
  1228.    "*The name of the internet host running the IRC daemon.
  1229. IRC servers generally restrict which machines can maintain connetions with
  1230. them, so you'll probably have to find a server in your local domain.
  1231. Initiated from enviroment variable IRCSERVER."))
  1232.  
  1233.  
  1234. (make-variable-buffer-local
  1235.  (defvar irc-show-japanese-characters nil
  1236.    "*If nil, replace Kanjii characters in text by a marker like \"Old Kanjii\"
  1237. followed by a list of integers denoting the 16 bit values of the characters.
  1238. If t, enter the text \"as is\" e.i., keep even the ESCape characters.
  1239. If neither nil nor t, enter the text in \"raw\" mode e.i., replace the ESCapes
  1240. by ^[ and insert the resulting text in the buffer.
  1241. The default is nil."))
  1242.  
  1243.  
  1244. (make-variable-buffer-local
  1245.  (defvar irc-signals '((backtalk t)
  1246.                (detect nil)
  1247.                (invite t)
  1248.                (join nil)
  1249.                (nick nil)
  1250.                (private t)
  1251.                (topic nil)
  1252.                (wall t)
  1253.                        (public nil)
  1254.                (user nil))
  1255.    "Events in IRC that should get signalled when they occur.
  1256. Generally the signal is an audible beep.  The value of irc-signals is an
  1257. association list of events recognized by irc-mode and is maintained with
  1258. the /SIGNAL command."))
  1259.  
  1260.  
  1261. (defvar irc-spacebar-pages t
  1262.   "*When this variable is non-nil, the following keys are in effect when
  1263. point is in the output region.
  1264.  
  1265. SPC      scroll-forward    DEL           scroll-backward
  1266. TAB      previous-line     LFD or RET    next-line")
  1267.  
  1268.  
  1269. (defvar irc-time-stamp 5
  1270.   "*How often to insert a time-stamp into *IRC* buffers.
  1271. The first time one is based from the hour the IRC process was started so that
  1272. values which divide evenly into 60 minutes (like the default of 10) will split
  1273. the hour evenly (as in 13:10, 13:20, 13:30, et cetera).  To disable the
  1274. time-stamping set this variable to 0.  This can be set with the /STAMP command.
  1275.  
  1276. The accuracy of the time-stamping can be improved greatly by running
  1277. M-x display-time; with default settings this guarantees that Emacs will have
  1278. some sort of predictable activity every minute.  If display-time is not running
  1279. and the IRC session is idle, the time-stamp can be up to two minutes late.")
  1280.  
  1281. (defvar irc-translation-table-incoming
  1282.   (cond
  1283.    ((and (boundp 'irc-translation-table-incoming)
  1284.      (arrayp irc-translation-table-incoming)
  1285.      (= 256 (length irc-translation-table-incoming)))
  1286.     irc-translation-table-incoming)
  1287.    ((and (boundp 'irc-translation-table-incoming)
  1288.      (symbolp irc-translation-table-incoming)
  1289.      (eq 'scandinavian irc-translation-table-incoming))
  1290.     irc-translation-table-incoming-scandinavian7)
  1291.    (t nil)
  1292.    (t 'scandinavian7))            ;Obsolete default
  1293.   "*Translation table for incoming characters.
  1294. If non-nil, single characters are translated one by one according to
  1295. this table. The table consists of a 256 elements long array, where each
  1296. element is either a string or nil. If the element is nil, the character
  1297. with the corresponding code is dropped, if the element is a string, the
  1298. string is inserted instead of the character.")
  1299.  
  1300. (defvar irc-translation-table-incoming-scandinavian7
  1301.   '["^@"                ;000
  1302.     "^A"                ;001
  1303.     ""                    ;002    ircII kludge
  1304.     "^C"                ;003
  1305.     "^D"                ;004
  1306.     "^E"                ;005
  1307.     "^F"                ;006
  1308.     "^G"                ;007
  1309.     "^H"                ;010
  1310.     "^I"                ;011
  1311.     "^J\n"                ;012
  1312.     "^K"                ;013
  1313.     "^L"                ;014
  1314.     "^M"                ;015
  1315.     "^N"                ;016
  1316.     ""                    ;017    ircII kludge
  1317.     "^P"                ;020
  1318.     "^Q"                ;021
  1319.     "^R"                ;022
  1320.     "^S"                ;023
  1321.     "^T"                ;024
  1322.     "^U"                ;025
  1323.     ""                    ;026    ircII kludge
  1324.     "^W"                ;027
  1325.     "^X"                ;030
  1326.     "^Y"                ;031
  1327.     "^Z"                ;032
  1328.     "^["                ;033
  1329.     "^\\"                ;034
  1330.     "^]"                ;035
  1331.     "^^"                ;036
  1332.     ""                    ;037    ircII kludge
  1333.     " "                    ;040
  1334.     "!"                    ;041
  1335.     "\""                ;042
  1336.     "#"                    ;043
  1337.     "$"                    ;044
  1338.     "%%"                ;045    Need %% to not disturb format.
  1339.     "&"                    ;046
  1340.     "'"                    ;047
  1341.     "("                    ;050
  1342.     ")"                    ;051
  1343.     "*"                    ;052
  1344.     "+"                    ;053
  1345.     ","                    ;054
  1346.     "-"                    ;055
  1347.     "."                    ;056
  1348.     "/"                    ;057
  1349.     "0"                    ;060
  1350.     "1"                    ;061
  1351.     "2"                    ;062
  1352.     "3"                    ;063
  1353.     "4"                    ;064
  1354.     "5"                    ;065
  1355.     "6"                    ;066
  1356.     "7"                    ;067
  1357.     "8"                    ;070
  1358.     "9"                    ;071
  1359.     ":"                    ;072
  1360.     ";"                    ;073
  1361.     "<"                    ;074
  1362.     "="                    ;075
  1363.     ">"                    ;076
  1364.     "?"                    ;077
  1365.     "@"                    ;100
  1366.     "A"                    ;101
  1367.     "B"                    ;102
  1368.     "C"                    ;103
  1369.     "D"                    ;104
  1370.     "E"                    ;105
  1371.     "F"                    ;106
  1372.     "G"                    ;107
  1373.     "H"                    ;110
  1374.     "I"                    ;111
  1375.     "J"                    ;112
  1376.     "K"                    ;113
  1377.     "L"                    ;114
  1378.     "M"                    ;115
  1379.     "N"                    ;116
  1380.     "O"                    ;117
  1381.     "P"                    ;120
  1382.     "Q"                    ;121
  1383.     "R"                    ;122
  1384.     "S"                    ;123
  1385.     "T"                    ;124
  1386.     "U"                    ;125
  1387.     "V"                    ;126
  1388.     "W"                    ;127
  1389.     "X"                    ;130
  1390.     "Y"                    ;131
  1391.     "Z"                    ;132
  1392.     "["                    ;133
  1393.     "\\"                ;134
  1394.     "]"                    ;135
  1395.     "^"                    ;136
  1396.     "_"                    ;137
  1397.     "`"                    ;140
  1398.     "a"                    ;141
  1399.     "b"                    ;142
  1400.     "c"                    ;143
  1401.     "d"                    ;144
  1402.     "e"                    ;145
  1403.     "f"                    ;146
  1404.     "g"                    ;147
  1405.     "h"                    ;150
  1406.     "i"                    ;151
  1407.     "j"                    ;152
  1408.     "k"                    ;153
  1409.     "l"                    ;154
  1410.     "m"                    ;155
  1411.     "n"                    ;156
  1412.     "o"                    ;157
  1413.     "p"                    ;160
  1414.     "q"                    ;161
  1415.     "r"                    ;162
  1416.     "s"                    ;163
  1417.     "t"                    ;164
  1418.     "u"                    ;165
  1419.     "v"                    ;166
  1420.     "w"                    ;167
  1421.     "x"                    ;170
  1422.     "y"                    ;171
  1423.     "z"                    ;172
  1424.     "{"                    ;173
  1425.     "|"                    ;174
  1426.     "}"                    ;175
  1427.     "~"                    ;176
  1428.     "^?"                ;177
  1429.     "\200"                ;200
  1430.     "~"                    ;201 MSDOS
  1431.     "\202"                ;202
  1432.     "\203"                ;203
  1433.     "{"                    ;204 MSDOS
  1434.     "\205"                ;205
  1435.     "}"                    ;206 MSDOS
  1436.     "\207"                ;207
  1437.     "\210"                ;210
  1438.     "\211"                ;211
  1439.     "\212"                ;212
  1440.     "\213"                ;213
  1441.     "\214"                ;214
  1442.     "\215"                ;215
  1443.     "["                    ;216 MSDOS
  1444.     "]"                    ;217 MSDOS
  1445.     "\220"                ;220
  1446.     "\221"                ;221
  1447.     "\222"                ;222
  1448.     "\223"                ;223
  1449.     "|"                    ;224 MSDOS
  1450.     "\225"                ;225
  1451.     "\226"                ;226
  1452.     "\227"                ;227
  1453.     "\230"                ;230
  1454.     "\\"                ;231 MSDOS
  1455.     "^"                    ;232 MSDOS
  1456.     "\233"                ;233
  1457.     "\234"                ;234
  1458.     "\235"                ;235
  1459.     "\236"                ;236
  1460.     "\237"                ;237
  1461.     " "                    ;240
  1462.     "!"                    ;241
  1463.     "c"                    ;242
  1464.     "#"                    ;243
  1465.     "$"                    ;244
  1466.     "Y"                    ;245
  1467.     "|"                    ;246
  1468.     "$"                    ;247
  1469.     "\""                ;250
  1470.     "c"                    ;251
  1471.     "+"                    ;252
  1472.     "<<"                ;253
  1473.     "!"                    ;254
  1474.     "-"                    ;255
  1475.     "R"                    ;256
  1476.     "~"                    ;257
  1477.     "C"                    ;260
  1478.     "+"                    ;261
  1479.     "2"                    ;262
  1480.     "3"                    ;263
  1481.     "'"                    ;264
  1482.     "u"                    ;265
  1483.     "$"                    ;266
  1484.     "-"                    ;267
  1485.     ","                    ;270
  1486.     "1"                    ;271
  1487.     "0"                    ;272
  1488.     ">>"                ;273
  1489.     "?"                    ;274
  1490.     "?"                    ;275
  1491.     "?"                    ;276
  1492.     "?"                    ;277
  1493.     "A"                    ;300
  1494.     "A"                    ;301
  1495.     "A"                    ;302
  1496.     "A"                    ;303
  1497.     "["                    ;304
  1498.     "]"                    ;305
  1499.     "["                    ;306
  1500.     "C"                    ;307
  1501.     "E"                    ;310
  1502.     "@"                    ;311
  1503.     "E"                    ;312
  1504.     "E"                    ;313
  1505.     "I"                    ;314
  1506.     "I"                    ;315
  1507.     "I"                    ;316
  1508.     "I"                    ;317
  1509.     "D"                    ;320
  1510.     "N"                    ;321
  1511.     "O"                    ;322
  1512.     "O"                    ;323
  1513.     "O"                    ;324
  1514.     "O"                    ;325
  1515.     "\\"                ;326
  1516.     "*"                    ;327
  1517.     "\\"                ;330
  1518.     "U"                    ;331
  1519.     "U"                    ;332
  1520.     "U"                    ;333
  1521.     "^"                    ;334
  1522.     "Y"                    ;335
  1523.     "T"                    ;336
  1524.     "ss"                ;337
  1525.     "a"                    ;340
  1526.     "a"                    ;341
  1527.     "a"                    ;342
  1528.     "a"                    ;343
  1529.     "{"                    ;344
  1530.     "}"                    ;345
  1531.     "{"                    ;346
  1532.     "c"                    ;347
  1533.     "e"                    ;350
  1534.     "`"                    ;351
  1535.     "e"                    ;352
  1536.     "e"                    ;353
  1537.     "i"                    ;354
  1538.     "i"                    ;355
  1539.     "i"                    ;356
  1540.     "i"                    ;357
  1541.     "d"                    ;360
  1542.     "n"                    ;361
  1543.     "o"                    ;362
  1544.     "o"                    ;363
  1545.     "o"                    ;364
  1546.     "o"                    ;365
  1547.     "|"                    ;366
  1548.     "/"                    ;367
  1549.     "|"                    ;370
  1550.     "u"                    ;371
  1551.     "u"                    ;372
  1552.     "u"                    ;373
  1553.     "~"                    ;374
  1554.     "y"                    ;375
  1555.     "t"                    ;376
  1556.     "y"]                ;377
  1557.   "*Translation table for incoming characters to translate from ISO 8859-1
  1558. to SIS E47. Also handles some MSDOS characters.")
  1559.  
  1560.  
  1561. (defvar irc-translation-table-incoming-scandinavian8
  1562.   '["^@"                ;000
  1563.     "^A"                ;001
  1564.     ""                    ;002    ircII kludge
  1565.     "^C"                ;003
  1566.     "^D"                ;004
  1567.     "^E"                ;005
  1568.     "^F"                ;006
  1569.     "^G"                ;007
  1570.     "^H"                ;010
  1571.     "^I"                ;011
  1572.     "^J\n"                ;012
  1573.     "^K"                ;013
  1574.     "^L"                ;014
  1575.     "^M"                ;015
  1576.     "^N"                ;016
  1577.     ""                    ;017    ircII kludge
  1578.     "^P"                ;020
  1579.     "^Q"                ;021
  1580.     "^R"                ;022
  1581.     "^S"                ;023
  1582.     "^T"                ;024
  1583.     "^U"                ;025
  1584.     ""                    ;026    ircII kludge
  1585.     "^W"                ;027
  1586.     "^X"                ;030
  1587.     "^Y"                ;031
  1588.     "^Z"                ;032
  1589.     "^["                ;033
  1590.     "^\\"                ;034
  1591.     "^]"                ;035
  1592.     "^^"                ;036
  1593.     ""                    ;037    ircII kludge
  1594.     " "                    ;040
  1595.     "!"                    ;041
  1596.     "\""                ;042
  1597.     "#"                    ;043
  1598.     "$"                    ;044
  1599.     "%%"                ;045    Need %% to not disturb format.
  1600.     "&"                    ;046
  1601.     "'"                    ;047
  1602.     "("                    ;050
  1603.     ")"                    ;051
  1604.     "*"                    ;052
  1605.     "+"                    ;053
  1606.     ","                    ;054
  1607.     "-"                    ;055
  1608.     "."                    ;056
  1609.     "/"                    ;057
  1610.     "0"                    ;060
  1611.     "1"                    ;061
  1612.     "2"                    ;062
  1613.     "3"                    ;063
  1614.     "4"                    ;064
  1615.     "5"                    ;065
  1616.     "6"                    ;066
  1617.     "7"                    ;067
  1618.     "8"                    ;070
  1619.     "9"                    ;071
  1620.     ":"                    ;072
  1621.     ";"                    ;073
  1622.     "<"                    ;074
  1623.     "="                    ;075
  1624.     ">"                    ;076
  1625.     "?"                    ;077
  1626.     "\311"                ;100
  1627.     "A"                    ;101
  1628.     "B"                    ;102
  1629.     "C"                    ;103
  1630.     "D"                    ;104
  1631.     "E"                    ;105
  1632.     "F"                    ;106
  1633.     "G"                    ;107
  1634.     "H"                    ;110
  1635.     "I"                    ;111
  1636.     "J"                    ;112
  1637.     "K"                    ;113
  1638.     "L"                    ;114
  1639.     "M"                    ;115
  1640.     "N"                    ;116
  1641.     "O"                    ;117
  1642.     "P"                    ;120
  1643.     "Q"                    ;121
  1644.     "R"                    ;122
  1645.     "S"                    ;123
  1646.     "T"                    ;124
  1647.     "U"                    ;125
  1648.     "V"                    ;126
  1649.     "W"                    ;127
  1650.     "X"                    ;130
  1651.     "Y"                    ;131
  1652.     "Z"                    ;132
  1653.     "\304"                ;133
  1654.     "\326"                ;134
  1655.     "\305"                ;135
  1656.     "\334"                ;136
  1657.     "_"                    ;137
  1658.     "\351"                ;140
  1659.     "a"                    ;141
  1660.     "b"                    ;142
  1661.     "c"                    ;143
  1662.     "d"                    ;144
  1663.     "e"                    ;145
  1664.     "f"                    ;146
  1665.     "g"                    ;147
  1666.     "h"                    ;150
  1667.     "i"                    ;151
  1668.     "j"                    ;152
  1669.     "k"                    ;153
  1670.     "l"                    ;154
  1671.     "m"                    ;155
  1672.     "n"                    ;156
  1673.     "o"                    ;157
  1674.     "p"                    ;160
  1675.     "q"                    ;161
  1676.     "r"                    ;162
  1677.     "s"                    ;163
  1678.     "t"                    ;164
  1679.     "u"                    ;165
  1680.     "v"                    ;166
  1681.     "w"                    ;167
  1682.     "x"                    ;170
  1683.     "y"                    ;171
  1684.     "z"                    ;172
  1685.     "\344"                ;173
  1686.     "\366"                ;174
  1687.     "\345"                ;175
  1688.     "\374"                ;176
  1689.     "^?"                ;177
  1690.     "\200"                ;200
  1691.     "\374"                ;201 MSDOS
  1692.     "\202"                ;202
  1693.     "\203"                ;203
  1694.     "\344"                ;204 MSDOS
  1695.     "\205"                ;205
  1696.     "\345"                ;206 MSDOS
  1697.     "\207"                ;207
  1698.     "\210"                ;210
  1699.     "\211"                ;211
  1700.     "\212"                ;212
  1701.     "\213"                ;213
  1702.     "\214"                ;214
  1703.     "\215"                ;215
  1704.     "\305"                ;216 MSDOS
  1705.     "\304"                ;217 MSDOS
  1706.     "\220"                ;220
  1707.     "\221"                ;221
  1708.     "\222"                ;222
  1709.     "\223"                ;223
  1710.     "\366"                ;224 MSDOS
  1711.     "\225"                ;225
  1712.     "\226"                ;226
  1713.     "\227"                ;227
  1714.     "\230"                ;230
  1715.     "\326"                ;231 MSDOS
  1716.     "\334"                ;232 MSDOS
  1717.     "\233"                ;233
  1718.     "\234"                ;234
  1719.     "\235"                ;235
  1720.     "\236"                ;236
  1721.     "\237"                ;237
  1722.     "\240"                ;240
  1723.     "\241"                ;241
  1724.     "\242"                ;242
  1725.     "\243"                ;243
  1726.     "\244"                ;244
  1727.     "\245"                ;245
  1728.     "\246"                ;246
  1729.     "\247"                ;247
  1730.     "\250"                ;250
  1731.     "\251"                ;251
  1732.     "\252"                ;252
  1733.     "\253"                ;253
  1734.     "\254"                ;254
  1735.     "\255"                ;255
  1736.     "\256"                ;256
  1737.     "\257"                ;257
  1738.     "\260"                ;260
  1739.     "\261"                ;261
  1740.     "\262"                ;262
  1741.     "\263"                ;263
  1742.     "\264"                ;264
  1743.     "\265"                ;265
  1744.     "\266"                ;266
  1745.     "\267"                ;267
  1746.     "\270"                ;270
  1747.     "\271"                ;271
  1748.     "\272"                ;272
  1749.     "\273"                ;273
  1750.     "\274"                ;274
  1751.     "\275"                ;275
  1752.     "\276"                ;276
  1753.     "\277"                ;277
  1754.     "\300"                ;300
  1755.     "\301"                ;301
  1756.     "\302"                ;302
  1757.     "\303"                ;303
  1758.     "\304"                ;304
  1759.     "\305"                ;305
  1760.     "\306"                ;306
  1761.     "\307"                ;307
  1762.     "\310"                ;310
  1763.     "\311"                ;311
  1764.     "\312"                ;312
  1765.     "\313"                ;313
  1766.     "\314"                ;314
  1767.     "\315"                ;315
  1768.     "\316"                ;316
  1769.     "\317"                ;317
  1770.     "\320"                ;320
  1771.     "\321"                ;321
  1772.     "\322"                ;322
  1773.     "\323"                ;323
  1774.     "\324"                ;324
  1775.     "\325"                ;325
  1776.     "\326"                ;326
  1777.     "\327"                ;327
  1778.     "\330"                ;330
  1779.     "\331"                ;331
  1780.     "\332"                ;332
  1781.     "\333"                ;333
  1782.     "\334"                ;334
  1783.     "\335"                ;335
  1784.     "\336"                ;336
  1785.     "\337"                ;337
  1786.     "\340"                ;340
  1787.     "\341"                ;341
  1788.     "\342"                ;342
  1789.     "\343"                ;343
  1790.     "\344"                ;344
  1791.     "\345"                ;345
  1792.     "\346"                ;346
  1793.     "\347"                ;347
  1794.     "\350"                ;350
  1795.     "\351"                ;351
  1796.     "\352"                ;352
  1797.     "\353"                ;353
  1798.     "\354"                ;354
  1799.     "\355"                ;355
  1800.     "\356"                ;356
  1801.     "\357"                ;357
  1802.     "\360"                ;360
  1803.     "\361"                ;361
  1804.     "\362"                ;362
  1805.     "\363"                ;363
  1806.     "\364"                ;364
  1807.     "\365"                ;365
  1808.     "\366"                ;366
  1809.     "\367"                ;367
  1810.     "\370"                ;370
  1811.     "\371"                ;371
  1812.     "\372"                ;372
  1813.     "\373"                ;373
  1814.     "\374"                ;374
  1815.     "\375"                ;375
  1816.     "\376"                ;376
  1817.     "\377"]                ;377
  1818.   "*Translation table for incoming characters to translate from SIS E47
  1819. to ISO 8859-1. Also handles some MSDOS characters.")
  1820.  
  1821.  
  1822. (make-variable-buffer-local
  1823.  (defvar irc-userinfo (if (boundp 'irc-userinfo)
  1824.               irc-userinfo
  1825.               nil)
  1826.    "*If non-nil, a user settable string to be replied with when the client is
  1827. queried by some other user."))
  1828.  
  1829.  
  1830.  
  1831.  
  1832. ;;; Macros
  1833. ;;;
  1834. (defmacro subfield (str n)
  1835.   "Return a substring of STR. The substring is field N, as used in the latest
  1836. string-match."
  1837.   (` (if (and (numberp (match-beginning (, n)))
  1838.           (numberp (match-end (, n))))
  1839.      (substring (, str) (match-beginning (, n)) (match-end (, n)))
  1840.      "")))
  1841.  
  1842.  
  1843. ;;; Handle host names.
  1844. ;;;
  1845. ;;; First a constant regular expression string matching only host names.
  1846. ;;;
  1847. (defconst irc-hostname "^[A-Za-z][A-Za-z0-9.-.---]*$"
  1848.   "A regexp matching a string if and only if the string is a hostname.")
  1849.  
  1850.  
  1851. (defconst irc-hostname-complement "\\(^\\.\\|\\.$\\)")
  1852.  
  1853.  
  1854. ;;; See RFC 952
  1855. (defconst irc-hostname-chars '(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m
  1856.                    ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
  1857.                    ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M
  1858.                    ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
  1859.                    ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?- ?.))
  1860.  
  1861.  
  1862. (defun irc-is-hostname (name)
  1863.   "Returns t if the NAME is a hostname, nil else.
  1864. This functions is more paranoid (Hello RFC 952!) than the IRC servers."
  1865.   (and (stringp name)
  1866.        (not (not (and (string-match irc-hostname name)
  1867.               (string-match "\\." name)
  1868.               (not (string-match (regexp-quote irc-hostname-complement)
  1869.                      name)))))))
  1870.  
  1871.  
  1872. (defun irc-is-nickname (name)
  1873.   "Returns t if the NAME is a valid nick name in IRC."
  1874.   (and (numberp (string-match (concat "^[]A-Z[\\^_a-z{|}~`]"
  1875.                       "[]A-Z0-9[\\_^a-z{|}~`-`---]*$")
  1876.                   name))
  1877.        (not (numberp (string-match "\n" name)))))
  1878.  
  1879.  
  1880. (defun irc-is-channelname (name)
  1881.   "Returns t if NAME is a valid channel identification."
  1882.   (or (and (irc-server-has-multijoinable-channels)
  1883.        (or (= ?# (aref name 0))
  1884.            (= ?& (aref name 0)))
  1885.        (irc-is-named-channel name))
  1886.       (and (irc-server-has-non-numeric-channel-names)
  1887.        (= ?+ (aref name 0))
  1888.        (irc-is-named-channel name))
  1889.       (and (numberp (string-match "^ *-?[0-9]+ *$" name))
  1890.        (irc-is-named-channel (concat "+" name)))))
  1891.  
  1892.  
  1893. (defun irc-is-broadcastname (name)
  1894.   "Return t if NAME is a valid broadcast address, ie is a server- or hostname
  1895. containing wildcards prepended by $ (server) or # (host). Broadcasts came at
  1896. the same time as #channels."
  1897.   (and (irc-server-has-multijoinable-channels)
  1898.        (or (= ?$ (aref name 0)) (= ?# (aref name 0)))))
  1899.  
  1900.  
  1901. (defun irc-is-named-channel (name)
  1902.   "Return t if NAME is a valid nummeric channel identification."
  1903.   (or (and (irc-server-has-multijoinable-channels)
  1904.        (numberp (string-match "^[&#+][]/a-zA-Z#+{}[^~()*!@.,0-9_-_---]*$"
  1905.                   name)))
  1906.       (and (irc-server-has-non-numeric-channel-names)
  1907.        (numberp (string-match "^+[]/a-zA-Z+{}[^~()*!@.,0-9_-_---]*$"
  1908.                   name)))))
  1909.  
  1910.  
  1911. (defun irc-is-multijoinable-channel (channel)
  1912.   "True if CHANNEL is a multijoinable channel, ie a channel one can listen
  1913. to along several other multijoinable channels. This feature was introduced in
  1914. server version 2.6."
  1915.   (and (stringp channel)
  1916.        (or (= (aref channel 0) ?#)
  1917.        (= (aref channel 0) ?&))))
  1918.  
  1919.  
  1920. (defun irc-is-receiver (obj)
  1921.   "True if STR could be either a nick or channel name.
  1922. If user is an enabled irc operator, broadcast addresses are OK too."
  1923.   (or (string= "*" obj)
  1924.       (irc-is-nickname obj)
  1925.       (and (string-match "^\\([^@]+\\)@\\([^@]+\\)$" obj)
  1926.        (let ((pre (subfield obj 1))
  1927.          (post (subfield obj 2)))
  1928.          (and (irc-is-nickname pre)
  1929.           (irc-is-hostname post))))
  1930.       (irc-is-channelname obj)
  1931.       (and irc-operator (irc-is-broadcastname obj))))
  1932.  
  1933.  
  1934. (defun irc-format-channel (channel &optional width)
  1935.   "Format a CHANNEL identification (name, number or * (ie private)) to be left
  1936. justified in a 15 character wide field. Ie make what the format string %-15s
  1937. SHOULD do. If the channel equals irc-channel, ie the current channel, it is
  1938. postpended with a %.
  1939.  
  1940. Arguments are a string with the channel ID, and optional a number saying how
  1941. wide the resulting string should be at least. If none is given, 15 is used as
  1942. the default."
  1943.   (let* ((w (max 0 (or (and (numberp width) width) 15)))
  1944.      (isnamed (irc-is-named-channel channel))
  1945.      (c (cond ((string= "*" channel) "Private")
  1946.           ((string= channel irc-channel) (concat channel "%"))
  1947.           (t channel)))
  1948.      (rpad (make-string (max 0 (- w (length c))) ? )))
  1949.     (concat c rpad)))
  1950.  
  1951.  
  1952. (defun irc-extract-hostname (s)
  1953.   "Extract the hostname part from the STRING, ignoring a trailing comment.
  1954. The string doesn't start with a host name, return nil."
  1955.   (let ((i 0)
  1956.     (len (length s)))
  1957.     (while (and (< i len)
  1958.         (memq (string-to-char (substring s i))
  1959.               irc-hostname-chars))
  1960.       (setq i (1+ i)))
  1961.     (if (irc-is-hostname (substring s 0 i))
  1962.     (substring s 0 i)
  1963.     nil)))
  1964.  
  1965.  
  1966. (defun irc-extract-hosts (path)
  1967.   "Extract and remember the different hosts mentioned in the path string,
  1968. \"h1!h2!h3!x\" where x is either a host or a nick name."
  1969.   (let* ((first-host (irc-extract-hostname path))
  1970.      (first-! (string-match "!" path))
  1971.      (len (length first-host)))
  1972.     (cond ((string= path "") nil)
  1973.       ((and (not first-host) first-!)
  1974.        (irc-extract-hosts (substring path (1+ first-!))))
  1975.       ((not first-host) nil)
  1976.       (t (irc-extract-hosts (substring path len))))))
  1977.  
  1978. ;; keymap
  1979. ;; what i tend to like for keys might be very different from what most people
  1980. ;; find useful; in fact i tend to type the /COMMANDs more than use any bindings
  1981.  
  1982. ;; there are more things bound here just so people can see the different
  1983. ;; things available to them
  1984. (or irc-mode-map
  1985.     (progn
  1986.       (setq irc-mode-map (make-keymap))
  1987.       (define-key irc-mode-map "\C-j"        'irc-process-input)
  1988.       (define-key irc-mode-map "\C-m"        'irc-process-input)
  1989.       (define-key irc-mode-map "\C-i"        'irc-tab)
  1990.       (define-key irc-mode-map "\C-c\C-a"    'irc-execute-alias)
  1991.       (define-key irc-mode-map "\C-c\C-c"    'irc-execute-names)
  1992.       (define-key irc-mode-map "\C-c\C-h"    'irc-execute-help)
  1993.       (define-key irc-mode-map "\C-c\C-i"    'irc-execute-invite)
  1994.       (define-key irc-mode-map "\C-c\C-j"    'irc-execute-join)
  1995.       (define-key irc-mode-map "\C-c\C-k"    'irc-execute-kill)
  1996.       (define-key irc-mode-map "\C-c\C-l"    'irc-execute-list)
  1997.       (define-key irc-mode-map "\C-c\C-m"    'irc-history-menu)
  1998.       (define-key irc-mode-map "\C-c\C-n"    'irc-history-next)
  1999.       (define-key irc-mode-map "\C-c\C-o"    'irc-execute-oops)
  2000.       (define-key irc-mode-map "\C-c\C-p"    'irc-history-prev)
  2001.       (define-key irc-mode-map "\C-c\C-q"    'irc-execute-quote)
  2002.       (define-key irc-mode-map "\C-c\C-r"    'irc-execute-redirect)
  2003.       (define-key irc-mode-map "\C-c\C-s"    'irc-execute-squit)
  2004.       (define-key irc-mode-map "\C-c\C-t"    'irc-execute-topic)
  2005.       (define-key irc-mode-map "\C-c\C-u"    'irc-kill-input)
  2006.       (define-key irc-mode-map "\C-c\C-v"    'irc-execute-version)
  2007.       (define-key irc-mode-map "\C-c\C-w"    'irc-execute-who)
  2008.       (define-key irc-mode-map "\C-c\C-?"    'irc-kill-input)
  2009.       ;; it's nice to bind to a key while in development, but regular users
  2010.       ;; wonder about it in production.
  2011.       ;; (define-key irc-mode-map "\C-c " 'irc-pong)
  2012.       (define-key irc-mode-map "\C-c#" 'irc-execute-lusers)
  2013.       (define-key irc-mode-map "\C-c=" 'irc-execute-memberships)
  2014.       (define-key irc-mode-map "\C-c?" 'describe-mode)
  2015.       (define-key irc-mode-map "\C-ca" 'irc-execute-admin)
  2016.       (define-key irc-mode-map "\C-cc" 'irc-execute-connect)
  2017.       (define-key irc-mode-map "\C-cf" 'irc-execute-finger)
  2018.       (define-key irc-mode-map "\C-ci" 'irc-execute-info)
  2019.       (define-key irc-mode-map "\C-ck" 'irc-execute-quit)
  2020.       (define-key irc-mode-map "\C-cl" 'irc-execute-links)
  2021.       (define-key irc-mode-map "\C-cm" 'irc-execute-mode)
  2022.       (define-key irc-mode-map "\C-cn" 'irc-execute-news)
  2023.       (define-key irc-mode-map "\C-co" 'irc-execute-oper)
  2024.       (define-key irc-mode-map "\C-cp" 'irc-yank-prev-command)
  2025.       (define-key irc-mode-map "\C-cq"    'irc-execute-leave)
  2026.       (define-key irc-mode-map "\C-cs" 'irc-execute-summon)
  2027.       (define-key irc-mode-map "\C-ct" 'irc-execute-trace)
  2028.       (define-key irc-mode-map "\C-cu" 'irc-execute-users)
  2029.       (define-key irc-mode-map "\C-cv" 'irc-version)
  2030.       (define-key irc-mode-map "\C-cw" 'irc-execute-whois)
  2031.       (define-key irc-mode-map "\C-?"  'irc-del-backward-char)
  2032.       ;; make any self-inserting keys call irc-self-insert
  2033.       (mapcar (function
  2034.                (lambda (key)
  2035.         (define-key irc-mode-map key 'irc-self-insert)))
  2036.           (append
  2037.            (where-is-internal 'self-insert-command nil nil)
  2038.            '(" " "!" "\"" "#" "$" "%" "&" "'"
  2039.          "(" ")" "*" "+" "," "-" "." "/"
  2040.          "0" "1" "2" "3" "4" "5" "6" "7"
  2041.          "8" "9" ":" ";" "<" "=" ">" "?"
  2042.          "@" "A" "B" "C" "D" "E" "F" "G"
  2043.          "H" "I" "J" "K" "L" "M" "N" "O"
  2044.          "P" "Q" "R" "S" "T" "U" "V" "W"
  2045.          "X" "Y" "Z" "[" "\\" "]" "^" "_"
  2046.          "`" "a" "b" "c" "d" "e" "f" "g"
  2047.          "h" "i" "j" "k" "l" "m" "n" "o"
  2048.          "p" "q" "r" "s" "t" "u" "v" "w"
  2049.          "x" "y" "z" "{" "|" "}" "~")))))
  2050.  
  2051. ;; filters (mostly irc-parse-*)
  2052. ;; Filtering of server messages from reception to insertion in the buffer
  2053. ;; are all done on this page.  In particular, if a new server message has
  2054. ;; to be dealt with, it should be added in the irc-parse-server-msg function.
  2055. (defun irc-filter (proc str)
  2056.   "Filtering procedure for IRC server messages.
  2057. It waits until everything up to a newline is accumulated before handing the
  2058. string over to irc-parse-server-msg to be processed.  If irc-pop-on-signal
  2059. is an integer and a signal is issued then the *IRC* buffer will be displayed.
  2060.  
  2061. Unless irc-maximum-size is zero or negative, truncate the Kiwi buffer to
  2062. be no larger than irc-maximum-size. If it is larger, truncate it to
  2063. the size irc-minimum-size."
  2064.   (let* ((ibuf (process-buffer proc))
  2065.          bell irc-mark-to-point new-point old-irc-mark win)
  2066.     (save-excursion
  2067.       (set-buffer ibuf)
  2068.       ;; still can't tell why i need this; sure, i probably change point
  2069.       ;; in ibuf.  but so what?  set-window-point should clean up after that.
  2070.       ;; it works with it though and not without it, so it stays.
  2071.       (save-excursion 
  2072.     ;; trim buffer if needed
  2073.     (if (> irc-maximum-size 0)
  2074.         (irc-truncate-buffer irc-maximum-size irc-minimum-size))
  2075.         (setq irc-mark-to-point   ; so we can restore relative position later
  2076.               (- (point) (setq old-irc-mark (goto-char irc-mark)))
  2077.               ;; just glue str to the end of any partial line that's there
  2078.               irc-scratch (concat irc-scratch str))
  2079.         ;; see if it is time for a message
  2080.         (irc-check-time)
  2081.         (while (string-match "\n" irc-scratch) ; do as many lines as possible
  2082.           ;; first use irc-scratch for the dp returned by irc-parse-server-msg
  2083.           (setq irc-scratch (irc-parse-server-msg irc-scratch)
  2084.         bell (cdr irc-scratch) ; issue a signal?
  2085.                 ;; now irc-scratch is what it was, minus the line parsed
  2086.                 irc-scratch (car irc-scratch))
  2087.           (if bell
  2088.           (progn
  2089.         ;; issue a signal; no need to trash someone's kbd-macro over it
  2090.         (ding 'no-terminate)
  2091.         (irc-minibuffer-message "%sBell in %s%s"
  2092.                     irc-msg-info-pre
  2093.                     (buffer-name ibuf)
  2094.                     irc-msg-info-post))))
  2095.         ;; if point was in front of the irc-mark, new-point is figured relative
  2096.         ;; to the old mark, otherwise it is relative to the new one
  2097.         (setq new-point (+ (if (< irc-mark-to-point 0) old-irc-mark irc-mark)
  2098.                            irc-mark-to-point))))
  2099.     ;; update point based on whether the buffer is visible
  2100.     ;; we have a real problem here if there is more than one window displaying
  2101.     ;; the process-buffer and the user is not in the first canonical one.
  2102.     ;; i haven't yet determined a nice way to solve this
  2103.     (if (setq win (if (eq (window-buffer) ibuf)    ;930224/PS: Use selected
  2104.               (selected-window)    ; window if it shows that buffer.
  2105.               (get-buffer-window ibuf)))
  2106.     (set-window-point win new-point)
  2107.     (save-excursion (set-buffer ibuf) (goto-char new-point)))
  2108.     ;; if *IRC* isn't visible, a bell was issued and irc-pop-on-signal is an
  2109.     ;; integer then show the buffer.
  2110.     (if (and (integerp irc-pop-on-signal) bell (not win))
  2111.     (progn
  2112.       (setq win (selected-window))
  2113.       (if (/= (irc-count-windows 'no-mini) 1)
  2114.           (display-buffer ibuf) ;don't futz with sizes if more than 1 win's
  2115.           ;; we might be in the mininbuffer at the moment, so insure that
  2116.           ;; this happens starting in the current regular window
  2117.           (select-window (next-window win 'no-mini))
  2118.           ;; full screen doesn't get handled well by the algorithm
  2119.           ;; for the rest
  2120.           (if (= irc-pop-on-signal 1)
  2121.           (set-window-buffer (selected-window) ibuf)
  2122.           (split-window nil
  2123.                 (if (fboundp 'frame-height)
  2124.                     (- (frame-height)
  2125.                        (/ (frame-height) irc-pop-on-signal))
  2126.                   (- (screen-height)
  2127.                      (/ (screen-height) irc-pop-on-signal))))
  2128.           (display-buffer ibuf)
  2129.           ;; perhaps we need to go back to the minibuffer
  2130.           (select-window win)))))))
  2131.  
  2132.  
  2133. (defun irc-string-display-length (str)
  2134.   "Return the number of display positions a string would take when
  2135. being displayed by GNU-emacs. A character can be displayed in 1, 2 or
  2136. 4 positions. Also a TAB can be 1 to 8 positions wide.
  2137.  
  2138. This function is pessimistic, and will rather return a too large count than a
  2139. too small."
  2140.   (let ((len 0)
  2141.     (i (length str))
  2142.     (x 0))
  2143.     (while (> i 0)
  2144.       (setq i (1- i)
  2145.         x (+ x (let ((c (aref i str)))
  2146.              (cond
  2147.                ((= c \t) 8)    ;TAB.
  2148.                ((or (< c ?\040) (= c ?\177)) ;Normal CNTRL character.
  2149.             (if ctl-arrow 2 4)) ;^X or \030 notation.
  2150.                ((< c ?\177) 1) ;Regular character.
  2151.                ((< c ?\240) 4) ;Eight bit "CNTRL" chararacter.
  2152.                ((< c ?\400)
  2153.             (cond ((eq irc-output-character-set 'ASCII) 4)
  2154.                   ((eq irc-output-character-set 'ISO-8859-1) 1)
  2155.                   (t 4)))
  2156.                (t 4))))))
  2157.     x))
  2158.  
  2159.  
  2160. (defun irc-clean-up-message (str)
  2161.   "Exchange all \"%\" with \"%%\" in STR. Also exchange CNTRL/X in STR
  2162. with ^X. Substitute a ^B for CNTRL/B (which is used by ircII to togle the
  2163. boldness of text) if irc-drop-ircII-text-kludge-control-characters is true,
  2164. or else drop the character. As a further kudo, replace japanese characters
  2165. coded with JIS etc unless irc-show-japanese-characters is nil."
  2166.   (let* ((clean "")
  2167.      (dirty-chars (concat "%"
  2168.                   "\000\001\002\003\004\005\006\007"
  2169.                   "\010\011\012\013\014\015\016\017"
  2170.                   "\020\021\022\023\024\025\026\027"
  2171.                   "\030\031\032\033\034\035\036\037"
  2172.  
  2173.                   "\177"
  2174.                   
  2175.                   "\200\201\202\203\204\205\206\207"
  2176.                   "\210\211\212\213\214\215\216\217"
  2177.                   "\220\221\222\223\224\225\226\227"
  2178.                   "\230\231\232\233\234\235\236\237"
  2179.  
  2180.                   (if irc-emacs-knows-ISO8859-1
  2181.                   ""
  2182.                   (concat "\240\241\242\243\244\245\246\247"
  2183.                       "\250\251\252\253\254\255\256\257"
  2184.                       "\260\261\262\263\264\265\266\267"
  2185.                       "\270\271\272\273\274\275\276\277"
  2186.                       "\300\301\302\303\304\305\306\307"
  2187.                       "\310\311\312\313\314\315\316\317"
  2188.                       "\320\321\322\323\324\325\326\327"
  2189.                       "\330\331\332\333\334\335\336\337"
  2190.                       "\340\341\342\343\344\345\346\347"
  2191.                       "\350\351\352\353\354\355\356\357"
  2192.                       "\360\361\362\363\364\365\366\367"
  2193.                       "\370\371\372\373\374\375\376\377"))
  2194.                   ""))
  2195.      (dirty (concat "[" dirty-chars "]"))
  2196.      (non-dirty (concat "[^" dirty-chars "]")))
  2197.     (if (symbolp irc-translation-table-incoming)
  2198.     (cond ((eq 'scandinavian7 irc-translation-table-incoming)
  2199.            (setq irc-translation-table-incoming
  2200.              irc-translation-table-incoming-scandinavian7))
  2201.           ((eq 'scandinavian8 irc-translation-table-incoming)
  2202.            (setq irc-translation-table-incoming
  2203.              irc-translation-table-incoming-scandinavian8))))
  2204.     (while (or (string-match dirty str)
  2205.            (and irc-translation-table-incoming
  2206.             (string< "" str)))
  2207.       (let ((split (cond ((and (or (eq irc-show-japanese-characters t)
  2208.                    (eq irc-show-japanese-characters nil))
  2209.                    (string-match (concat
  2210.                           "^ ?\033$\\([@AB]\\)\\([^\033]*"
  2211.                           "\\)\033\\([()]. ?\\)")
  2212.                          str))
  2213.               (cond
  2214.                 ((eq irc-show-japanese-characters t)
  2215.                  (let* ((pre (subfield str 1))
  2216.                     (msg (subfield str 2))
  2217.                     (trail (subfield str 3)))
  2218.                  (cons (concat "\033$"
  2219.                        pre
  2220.                        (irc-clean-up-message msg)
  2221.                        trail))
  2222.                    (substring str (match-end 0))))
  2223.                 ((eq irc-show-japanese-characters nil)
  2224.                  (let ((msgend (match-end 0))
  2225.                    (type (substring str
  2226.                             (match-beginning 1)
  2227.                             (match-end 1))))
  2228.                    (cons (concat irc-msg-info-pre
  2229.                          (cond ((string= type "@")
  2230.                             "Old Kanjii: ")
  2231.                            ((string= type "A")
  2232.                             "Probaly chinese: ")
  2233.                            ((string= type "B")
  2234.                             "Modern Kanjii: ")
  2235.                            (t "Unkown 16-bit: "))
  2236.                          (irc-clean-up-message
  2237.                           (irc-translate-kanji
  2238.                            (substring str
  2239.                               (match-beginning 2)
  2240.                               (match-end 2))))
  2241.                          irc-msg-info-post
  2242.                          " ")
  2243.                      (substring str msgend))))
  2244.                 (t (irc-insert (concat "%%Bug in japanese part of"
  2245.                            " irc-clean-up-message."))
  2246.                    (cons (substring str 0 (match-end 0))
  2247.                      (substring str (match-end 0))))))
  2248.              ((not (null irc-translation-table-incoming))
  2249.               (cons (aref irc-translation-table-incoming
  2250.                       (aref str 0))
  2251.                 (substring str 1)))
  2252.              ((and (>= (aref str 0) ?\200) ;8 bit?
  2253.                    (or (< (aref str 0) ?\240)
  2254.                    (not (eq irc-output-character-set
  2255.                         'ISO-8859-1))))
  2256.               (cons (concat (format "\\%o" (aref str 0)))
  2257.                 (substring str 1)))
  2258.              ((string-match (concat "^" non-dirty "*%") str)
  2259.               (cons (concat (substring str 0 (1- (match-end 0)))
  2260.                     "%%")
  2261.                 (substring str (match-end 0))))
  2262.              ((= (aref str 0) ?\t)
  2263.               (cons "^I" (substring str 1)))
  2264.              ((= (aref str 0) ?\177)
  2265.               (cons "^?" (substring str 1)))
  2266.              ((and irc-drop-ircII-text-kludge-control-characters
  2267.                    (irc-member-general (aref str 0)
  2268.                            '(?\002 ?\017 ?\026 ?\037)
  2269.                            '=))
  2270.               (cons "" (substring str 1)))
  2271.              ((and (>= (aref str 0) ?\000)
  2272.                    (<= (aref str 0) ?\037))
  2273.               (cons
  2274.                (concat "^" (char-to-string (+ ?@ (aref str 0))))
  2275.                (substring str 1)))
  2276.              ((string-match (concat "^" non-dirty "+") str)
  2277.               (cons (substring str
  2278.                        (match-beginning 0)
  2279.                        (match-end 0))
  2280.                 (substring str (match-end 0))))
  2281.              (t (cons (substring str 0 1) (substring str 1))))))
  2282.     (setq clean (concat clean (car split))
  2283.           str (cdr split))))
  2284.     (concat clean str)))
  2285.  
  2286.  
  2287. (defun irc-translate-kanji (str)
  2288.   "Translate a japanese Kanjicoded message in STR into nummeric codes.
  2289. Just exchange every two octet sequence into their nummeric codes."
  2290.   (let ((retval ""))
  2291.     (while (>= (length str) 2)
  2292.       (let ((double (+ (* (aref str 0) 256) (aref str 1))))
  2293.     (setq retval (format "%s%s%d"
  2294.                  retval
  2295.                  (if (string= "" retval) "" " ")
  2296.                  double)
  2297.           str (substring str 2))))
  2298.     (if (> (length str) 0)
  2299.     (format "ODD %d" (aref str 0))
  2300.     retval)))
  2301.  
  2302.  
  2303. (defun irc-parse-server-msg (str)
  2304.   "Take the first line from STR and pass it on to the appropriate irc-parse-*
  2305. function.  If the message is one which irc-mode doesn't recognize, just display
  2306. it as the raw server message.
  2307.  
  2308. It returns a dotted-pair whose car is the remainder of STR after the first
  2309. newline and whose cdr is either t or nil, indicating whether a signal should
  2310. be issued."
  2311.   (let ((n (string-match "\r" str)))
  2312.     (while n
  2313.       (setq str (concat (substring str 0 n)
  2314.             (substring str (1+ n)))
  2315.         n (string-match "\r" str))))
  2316.   (let* ((nl (string-match "\n" str)) 
  2317.      (eol (or nl (length str)))
  2318.      (line (substring str 0 eol))
  2319.      (dummy (irc-log-in-debug-buffer (concat "  " line)))
  2320.      (new (or (string-match "^:\\([^! :]+\\)!\\([^@ :]+\\)@\\([^ :]+\\)"
  2321.                 line)))
  2322.      (triple (if new (cons (subfield line 1)
  2323.                    (cons (subfield line 2)
  2324.                      (subfield line 3)))))
  2325.      (rest (if new (substring line (match-end 0))))
  2326.      (irc-userhost (if new
  2327.                (format " <%s@%s>"
  2328.                    (car (cdr triple)) (cdr (cdr triple)))
  2329.                ""))
  2330.      (line (if new (format ":%s%s" (car triple) rest) line))
  2331.      (last-NOTICE-rcv irc-last-NOTICE-rcv)
  2332.      (last-NOTICE-src irc-last-NOTICE-src))
  2333.     (if (not nl)
  2334.     (irc-insert "%%WARNING: got incomplete line from server! No newline."))
  2335.     (setq irc-last-NOTICE-rcv ""
  2336.       irc-last-NOTICE-src "")
  2337.     (if (not (boundp 'irc-count-incoming-messages))
  2338.     (progn
  2339.       (message "?Kiwi: Variable irc-count-incoming-messages unbound")
  2340.       (set (make-local-variable 'irc-count-incoming-messages) nil)))
  2341.     (if (not (numberp irc-count-incoming-messages))
  2342.     (progn
  2343.       (message "?Kiwi: irc-count-incoming-messages=%d, not a number"
  2344.            irc-count-incoming-messages)
  2345.       (setq irc-count-incoming-messages 0)))
  2346.     (setq line (irc-lowlevel-dequote line)
  2347.       irc-count-incoming-messages (1+ irc-count-incoming-messages))
  2348.     (if (= 0 (% irc-count-incoming-messages 50))
  2349.     (irc-send (concat "PONG " irc-server)))
  2350.     (cons
  2351.      ;; the part of str not being parsed.
  2352.      (substring str (1+ (string-match "\n" str)))
  2353.      (cond
  2354.        ;; each function here should return t or nil indicating whether
  2355.        ;; to issue a signal.  Some of these regexps are fugly because
  2356.        ;; of inconsistent protocol use by the servers.  Fortunately Jarkko
  2357.        ;; is fixing that.
  2358.        ((string-match "^ *$" line) nil)    ;Ignore empty lines.
  2359.        ((string-match "^:[^: ]+ +MSG " line) (irc-parse-public line))
  2360.        ((string-match "^:[^: ]+ +CHANNEL " line) (irc-parse-channel line))
  2361.        ((string-match "^:[^ ]+ +JOIN " line) (irc-parse-channel line))
  2362.        ((string-match "^:[^: ]+ +PART " line) (irc-parse-channel line))
  2363.        ((string-match "^:[^: ]+ +INVITE " line) (irc-parse-invite line))
  2364.        ((string-match "^:[^: ]+ +NICK " line) (irc-parse-nick line))
  2365.        ((string-match "^:[^: ]+ +WALL " line) (irc-parse-wall line))
  2366.        ((string-match "^:[^: ]+ +WALLOPS " line) (irc-parse-wallops line))
  2367.        ((string-match "^:[^: ]+ +QUIT " line) (irc-parse-quit line))
  2368.        ((string-match "^:[^: ]+ +KICK " line) (irc-parse-kick line))
  2369.        ((string-match "^:[^: ]+ +KILL " line) (irc-parse-kill line))
  2370.        ((string-match "^:[^: ]+ +TOPIC " line) (irc-parse-topic line))
  2371.        ((string-match "^:[^: ]+ +MODE " line) (irc-parse-mode-reply line))
  2372.        ((string-match "^:[^: ]+ +[023][0-9][0-9][^0-9]" line)
  2373.     (irc-parse-RPL line))
  2374.        ((string-match "^:[^: ]+ +[4-5][0-9][0-9][^0-9]" line)
  2375.     (irc-parse-ERR line))
  2376.        ((string-match (concat "^\\(:?\\)\\([^: ]*\\) *NOTICE"
  2377.                   " +\\([^: ]+\\) *:"
  2378.                   "\\([^\001]*\001[^\001]*\001\\)")
  2379.               line)
  2380.     (setq irc-last-NOTICE-rcv last-NOTICE-rcv
  2381.           irc-last-NOTICE-src last-NOTICE-src)
  2382.     (let* ((colon (subfield line 1))
  2383.            (from (subfield line 2))
  2384.            (to (subfield line 3))
  2385.            (msg (concat (subfield line 4)
  2386.                 (substring line (match-end 0))))
  2387.            (frm (if (string= "" from) irc-server from)))
  2388.       (if (irc-is-nickname frm)
  2389.           (irc-remember frm 'irc-nicknames))
  2390.       (while (string-match "^\\([^\001]*\\)\\(\001[^\001]*\001\\)" msg)
  2391.         (let ((start (subfield msg 1))
  2392.           (ctcp (subfield msg 2))
  2393.           (end (substring msg (match-end 0))))
  2394.           (setq msg (concat start end))
  2395.           (if (string= "\001\001" ctcp)
  2396.           (setq msg (concat msg "\001"))
  2397.           (irc-parse-CLIENT-answer frm to ctcp))))
  2398.       (if (not (string-match "^ *$" msg))
  2399.           (irc-parse-server-msg
  2400.            (concat colon from " NOTICE " to " :" msg "\n")))))
  2401.        ((string-match "^\\(:[^: ]* +\\)?NOTICE " line)
  2402.     (setq irc-last-NOTICE-rcv last-NOTICE-rcv
  2403.           irc-last-NOTICE-src last-NOTICE-src)
  2404.     (irc-parse-notice line))
  2405.        ((string-match (concat "^\\(:?\\)\\([^: ]*\\) *PRIVMSG"
  2406.                   " +\\([^ ]+\\) +:"
  2407.                   "\\([^\001]*\001[^\001]*\001\\)") 
  2408.               line)
  2409.     (let* ((colon (subfield line 1))
  2410.            (from (subfield line 2))
  2411.            (to (subfield line 3))
  2412.            (msg (concat (subfield line 4)
  2413.                 (substring line (match-end 0))))
  2414.            (frm (if (string= "" from) irc-server from)))
  2415.       (if (irc-is-nickname frm)
  2416.           (irc-remember frm 'irc-nicknames))
  2417.       (while (string-match "^\\([^\001]*\\)\\(\001[^\001]*\001\\)" msg)
  2418.         (let ((start (subfield msg 1))
  2419.           (ctcp (subfield msg 2))
  2420.           (end (substring msg (match-end 0))))
  2421.           (setq msg (concat start end))
  2422.           (if (string= "\001\001" ctcp)
  2423.           (setq msg (concat msg "\001"))
  2424.           (irc-parse-CLIENT-query frm to ctcp))))
  2425.       (if (not (string-match "^ *$" msg))
  2426.           (irc-parse-server-msg
  2427.            (concat colon from " PRIVMSG " to " :" msg "\n")))))
  2428.        ((string-match "^\\(:[^: ]* +\\)?PRIVMSG " line)
  2429.     (irc-parse-priv line))
  2430.        ((string-match "^PING " line) (irc-pong))
  2431.        ((string-match "^\\(:[^: ^]* +\\)?PONG " line)
  2432.     (irc-parse-pong line))
  2433.        ((string-match "^ERROR " line) (irc-parse-error line))
  2434.        ((string-match "^WHOREPLY " line) (irc-parse-whoreply line))
  2435.        ((string-match "^NAMREPLY " line) (irc-parse-namreply line))
  2436.        ((string-match "^LINREPLY " line) (irc-parse-linreply line))
  2437.        (t (irc-insert (concat "%%Received unkown message from server,"
  2438.                   " in function irc-parse-server-msg:"))
  2439.       (irc-insert "%% \"%s\" (cleaned up line)."
  2440.               (irc-clean-up-message line))
  2441.       (irc-insert (concat "%% Please let %s know about this;"
  2442.                   " it might be a bug.")
  2443.               irc-hacker)
  2444.       nil)))))
  2445.  
  2446.  
  2447. (defun irc-parse-channel (str)
  2448.   "Examine CHANNEL, JOIN and PART messages from the IRC server.
  2449. CHANNEL indicates a user entering or leaving the channel which you are
  2450. on, JOIN indicates a user entering a channel and PART indicates a user
  2451. leaving the channel. If the user is not being ignored and \"join\" is
  2452. in irc-events, a message is inserted indicating the change.  A
  2453. message is always provided as confirmation if the user is the irc-mode
  2454. user.
  2455.  
  2456. This function returns t if a bell should be issued for the \"join\" event,
  2457. nil otherwise."
  2458.   (if (not (or (string-match (concat "^: *\\([^ ]+\\) +\\(JOIN\\)"
  2459.                      " +:?\\([^ ]+\\) +\\([^ ]*\\) *$")
  2460.                  str)
  2461.            (string-match (concat "^: *\\([^ ]+\\) +\\(JOIN\\)"
  2462.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2463.                  str)
  2464.            (string-match (concat "^: *\\([^ ]+\\) +\\(PART\\)"
  2465.                      " +:?\\([^ ]+\\) +\\([^ ]*\\) *$")
  2466.                  str)
  2467.            (string-match (concat "^: *\\([^ ]+\\) +\\(PART\\)"
  2468.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2469.                  str)
  2470.            (string-match (concat "^: *\\([^ ]+\\) +\\(CHANNEL\\)"
  2471.                      " +:?\\([^ ]+\\) *\\(\\)$")
  2472.                  str)))
  2473.       (progn (irc-insert (concat "%%Unknown format on command from server,"
  2474.                  " please notify %s, it migh be a bug.")
  2475.              irc-hacker)
  2476.          (irc-insert "%% str=\"%s\"." str)
  2477.          (irc-insert "%% Function irc-parse-channel."))
  2478.       (let* ((user (subfield str 1))
  2479.          (type (subfield str 2))
  2480.          (channel (subfield str 3))
  2481.          (mode (subfield str 4))
  2482.          (left (or (string= type "PART")
  2483.                (and (string= type "CHANNEL") (string= channel "0"))))
  2484.          (pd (make-string (max 0 (1- (length channel))) ? ))
  2485.          (cont (concat irc-msg-cont pd)))
  2486.     (if (string= user irc-nick-used)
  2487.         (progn
  2488.           (if left
  2489.           (irc-forget channel 'irc-subscribed-channels)
  2490.           (irc-remember channel 'irc-subscribed-channels)))
  2491.         )
  2492.     (if (string= user irc-nick-used)
  2493.         (progn
  2494.           (if left
  2495.           (if (irc-server-has-multijoinable-channels)
  2496.               (if (or (string= (upcase channel) (upcase irc-channel))
  2497.                   (string= irc-channel "0"))
  2498.               (progn
  2499.                 (setq irc-channel "0")
  2500.                 (irc-show-subscribed-channels))
  2501.               (progn
  2502.                 (if nil
  2503.                 (irc-remember channel
  2504.                           'irc-subscribed-channels))
  2505.                 (irc-show-subscribed-channels)))
  2506.               (progn
  2507.             (if nil
  2508.                 (irc-remember irc-channel
  2509.                       'irc-subscribed-channels))
  2510.             (setq irc-channel "0")
  2511.             (irc-show-subscribed-channels)))
  2512.           (progn (setq irc-channel channel)
  2513.              (if nil
  2514.                  (irc-remember channel 'irc-subscribed-channels))
  2515.              (irc-send (concat "MODE " irc-channel))
  2516.              (irc-show-subscribed-channels))))
  2517.         (if (and (not (irc-recall user 'irc-ignored-ppl))
  2518.              (memq 'join irc-events))
  2519.         (progn
  2520.           (if left
  2521.               (irc-insert "%s%s%s has LEFT channel %s%s"
  2522.                   irc-msg-info-pre
  2523.                   user
  2524.                   irc-userhost
  2525.                   (if (irc-server-has-multijoinable-channels)
  2526.                       channel
  2527.                       irc-channel)
  2528.                   irc-msg-info-post)
  2529.               (progn
  2530.             (irc-remember user 'irc-nicknames)
  2531.             (irc-insert "%s%s%s has JOINED channel %s%s"
  2532.                     irc-msg-info-pre
  2533.                     user
  2534.                     irc-userhost
  2535.                     channel
  2536.                     irc-msg-info-post)))
  2537.           )
  2538.         (irc-signal user 'join)))))) ; check for signal for join
  2539.  
  2540.  
  2541. (defun irc-parse-CLIENT-answer (sndr rcvr str)
  2542.   "Examine a client answer message from another client.
  2543.  
  2544. Generally, incoming message will look like \"^ACLIENT keyword arg1 .. argN^A\"
  2545. one or several pasted together."
  2546.   (if (irc-recall sndr 'irc-ignored-ppl)
  2547.       ;; Ignored person.
  2548.       (setq str ""))
  2549.   (if (not (string-match "^\001\\([^\001]*\\)\001$" str))
  2550.       (progn (irc-insert "%%Got non-clientmessage in irc-parse-CLIENT-answer:")
  2551.          (irc-insert "%% \"%s\" (str)." str)
  2552.          (irc-insert "%% Please tell %s, probaly en internal error."
  2553.              irc-hacker))
  2554.     (setq str (irc-ctcp-dequote
  2555.            (substring str (match-beginning 1) (match-end 1)))))
  2556.   (if (not (string-match (concat " *\\([^\001 \t]+\\)"    ;1 keyword
  2557.                  " *:?"            ;optional colon
  2558.                  " *\\([^\001]*\\)"        ;2 data
  2559.                  " *$")
  2560.              str))
  2561.       (if (string< "" str)
  2562.       (progn (irc-insert "%%Received unknown CTCP answer message:")
  2563.          (irc-insert "%% \"%s\" (str)." (irc-clean-up-message str))
  2564.          (irc-insert "%% This is probaly NOT a bug.")))
  2565.       (let* ((keyw (subfield str 1))
  2566.          (args (subfield str 2))
  2567.          (pre (concat irc-msg-info-pre "User \"" sndr "\" "))
  2568.          (irc-msg-cont-used (make-string (length pre) ? )))
  2569.     (cond
  2570.       ((string= keyw "ACTION")    ;Ignore ACTION replies.
  2571.        )
  2572.       ((string= keyw "CLIENTINFO")
  2573.        (irc-insert (concat "%sis using a client which is using the"
  2574.                    " client-to-client-protocol keyword %s in the"
  2575.                    " following way: %s%s")
  2576.                pre keyw args irc-msg-info-post))
  2577.       ((string= keyw "ECHO")
  2578.        (irc-insert "%sechoed back \"%s\" to us with (CTCP) ECHO%s"
  2579.                pre args irc-msg-info-post))
  2580.       ((string= keyw "PING")
  2581.        (cond ((not (string-match "^[0-9]+$" args))
  2582.           (irc-insert (concat "%%Received bogus (CTCP) PING reply from"
  2583.                       " user %s: \"%s\".")
  2584.                   sndr args))
  2585.          (t (let* ((cur (car (cdr (irc-current-time))))
  2586.                (rep (string-to-int args))
  2587.                (ans (- cur rep))
  2588.                (tos (/ (* 10 (if (< ans 0)
  2589.                          (+ cur (- 65536 rep))
  2590.                          ans))
  2591.                    2))
  2592.                (int-part (/ tos 10))
  2593.                (dec-part  (- tos (* 10 int-part))))
  2594.               (irc-insert (concat "%sis about %d.%d seconds"
  2595.                       " away from you, %s%s")
  2596.                   pre int-part dec-part irc-nick-used
  2597.                   irc-msg-info-post)))))
  2598.       ((string= keyw "ERRMSG")
  2599.        (cond ((string-match "^PING +RELAY +\\([0-9]+\\)\\( +:.*\\)? *$"
  2600.                 args)
  2601.           (irc-parse-CLIENT-answer sndr
  2602.                        rcvr
  2603.                        (format "\001PING %s\001"
  2604.                            (subfield args 1))))
  2605.          ((string-match "^ACTION " args)
  2606.           ;; Ignore complaints about CTCP ACTION.
  2607.           )
  2608.          (t (irc-insert (concat "%%Errormessage from client of"
  2609.                     " user %s: \"%s\".")
  2610.                 sndr args))))
  2611.       ((string= keyw "FINGER")
  2612.        (let* ((data (if (string-match (concat "^ *Please +check +"
  2613.                           "my +USERINFO +instead"
  2614.                           " *:")
  2615.                       args)
  2616.                 (substring args (match-end 0))
  2617.                 args)))
  2618.          (if (string-match (concat "^\\(.* +Idle *\\)\\(for +\\)?"
  2619.                        "\\([0-9]+\\) *seconds? *$")
  2620.                    data)
  2621.          (let* ((m (subfield data 1))
  2622.             (idle (subfield data 3))
  2623.             (xpre (concat "\"" (irc-clean-up-message m)))
  2624.             (idle-time (string-to-int idle))
  2625.             (xpost (if (= 1 idle-time) "second" "seconds"))
  2626.             (idle-string (if (>= idle-time 60)
  2627.                      (format "%s %s\" (%s)"
  2628.                          idle
  2629.                          xpost
  2630.                          (irc-sec-to-time idle-time))
  2631.                      (concat idle " " xpost "\""))))
  2632.            (irc-insert "%shas FINGER-info %s%s"
  2633.                    pre
  2634.                    (concat xpre idle-string)
  2635.                    irc-msg-info-post))
  2636.          (irc-insert "%shas fingerinfo \"%s\"%s"
  2637.                  pre data irc-msg-info-post))))
  2638.       ((string= keyw "SOURCE")
  2639.        (cond
  2640.          ((string-match "^ *$" args)
  2641.           (irc-insert "%sEnd of source site listing%s"
  2642.               irc-msg-info-pre irc-msg-info-post))
  2643.          ((string-match "^ *\\([^: ]+\\) *: *\\([^: ]+\\) *: *\\(.*\\) *"
  2644.                 args)
  2645.           (let ((site (subfield args 1))
  2646.             (dir (subfield args 2))
  2647.             (files (subfield args 3)))
  2648.         (irc-insert "%sSource site: %s (directory %s, files %s)%s"
  2649.                 irc-msg-info-pre
  2650.                 site dir files
  2651.                 irc-msg-info-post)))
  2652.          (t (irc-insert "%%Received unknown CTCP %s reply from %s: %s"
  2653.                 keyw sndr args))))
  2654.       ((string= keyw "USERINFO")
  2655.        (if (or (string-match "^ *$" args)
  2656.            (string-match
  2657.             "^ *\\(HUH *\\?\\) *WHO +WANTS +TO +KNOW *\\? *$"
  2658.             (upcase args))
  2659.            (string= "<None Supplied>" args)
  2660.            (string= "And what you want to know?" args)
  2661.            (string= "No user info given." args)
  2662.            )
  2663.            (irc-insert (concat "%shasn't given any information"
  2664.                    " about him/herself%s")
  2665.                pre irc-msg-info-post)
  2666.            (progn
  2667.          (string-match "\\(\\.?\\)$" args)
  2668.          (let ((info (substring args 0 (match-beginning 0)))
  2669.                (dot (subfield args 2)))
  2670.            (irc-insert (concat "%shas given the information"
  2671.                        " \"%s\"%s about him/herself%s")
  2672.                    pre
  2673.                    (irc-clean-up-message info)
  2674.                    dot
  2675.                    irc-msg-info-post)))))
  2676.       ((or (string= keyw "VERSION")    ;CLIENT_VERSION
  2677.            (string= keyw "VRSN"))
  2678.        (if (string-match "^ *\\([^:]+\\) *: *\\([^:]+\\) *: *\\(.*\\) *$"
  2679.                  args)
  2680.            (let ((name (subfield args 1))
  2681.              (vrsn (subfield args 2))
  2682.              (env (subfield args 3)))
  2683.          (irc-insert (concat "%sUser \"%s\" claims to be using"
  2684.                      " client %s version %s (%s)%s")
  2685.                  irc-msg-info-pre
  2686.                  sndr name (irc-clean-up-message vrsn) env
  2687.                  irc-msg-info-post))
  2688.            (irc-insert "%sclaims to be using client %s%s"
  2689.                pre
  2690.                (irc-clean-up-message
  2691.                 (let ((c (cond
  2692.                        ((or (string-match
  2693.                          (concat
  2694.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2695.                           "\\([0-9]+\\.[0-9]+[^:]+\\) *:"
  2696.                           "[^0-9]*\\([0-9]\\.[0-9][^ \\.]+"
  2697.                           "*\\).*$")
  2698.                          args)
  2699.                         (string-match
  2700.                          (concat
  2701.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2702.                           "[^:]*: *\\(.*[0-9]\\."
  2703.                           "[0-9].*\\) *\\(\\)$")
  2704.                          args)
  2705.                         (string-match
  2706.                          (concat
  2707.                           "^ *[Ii][Rr][Cc][Ii][Ii] +"
  2708.                           "\\([^:]+\\) *:.*\\(\\)$")
  2709.                          args))
  2710.                     (concat "ircII "
  2711.                         (subfield args 1)
  2712.                         (subfield args 2)))
  2713.                        ((string-match
  2714.                      (concat "^[^:]*: *\\(.*[0-9]+\\."
  2715.                          "[0-9]+.*.*\\) *$")
  2716.                      args)
  2717.                     (subfield args 1))
  2718.                        ((string-match
  2719.                      "^[^:]*[0-9]+\\.[0-9]+[^:]*"
  2720.                      args)
  2721.                     (substring args 0 (match-end 0)))
  2722.                        (t args))))
  2723.                   (irc-nuke-whitespace
  2724.                    (progn
  2725.                  (while
  2726.                      (or (string-match
  2727.                       " The one true client\\." c)
  2728.                      (string-match (concat
  2729.                             " Who could ask for"
  2730.                             " anything more\\.")
  2731.                                c)
  2732.                      (string-match "SIAWPIO!" c))
  2733.                    (setq c (concat
  2734.                         (substring c 0 (match-beginning 0))
  2735.                         (substring c (match-end 0)))))
  2736.                  c))))
  2737.                irc-msg-info-post)))
  2738.       ((string= keyw "VRSN")
  2739.        (if (string-match "^ *\\([^:]+\\) *: *\\([^:]+\\) *: *\\(.*\\) *$"
  2740.                  args)
  2741.            (let ((name (subfield args 1))
  2742.              (vrsn (subfield args 2))
  2743.              (env (subfield args 3)))
  2744.          (irc-insert (concat "%sUser \"%s\" claims to be using"
  2745.                      " client %s version %s (%s)%s")
  2746.                  irc-msg-info-pre
  2747.                  sndr name vrsn env
  2748.                  irc-msg-info-post))
  2749.            (irc-insert "%%Received unknown (CTCP) %s reply from %s: %s"
  2750.                keyw sndr args)))
  2751.       (t (irc-insert (concat "%%Received unknown answer with keyword"
  2752.                  " \"%s\" from client of user \"%s\":"
  2753.                  " \"%s\".")
  2754.              keyw sndr args))))))
  2755.  
  2756.  
  2757. (defun irc-parse-CLIENT-query (sndr rcvr str)
  2758.   "Examine a client query message from another client.
  2759.  
  2760. Generally, incoming message will look like \"^A CLIENT keyword data
  2761. ... ^A\" where sndr is nick of client query is comming from, rcvr is
  2762. nick of receiver (either one self or a channel or a broadcast), and
  2763. keyword being a token in the set VERSION, USERINFO, ERRMSG etc. Arg1
  2764. to argN are optional." 
  2765.   (cond
  2766.     ((irc-recall sndr 'irc-ignored-ppl)
  2767.      ;; Ignored person.
  2768.      nil)
  2769.     ((not (string-match "^\001\\([^\001]*\\)\001$" str))
  2770.      (progn (irc-insert "%%Got non-CTCP query in irc-parse-CLIENT-query:")
  2771.         (irc-insert "%% \"%s\" (str)." str)
  2772.         (irc-insert "%% Please tell %s, probaly an internal error."
  2773.             irc-hacker)))
  2774.     (t (setq str (irc-ctcp-dequote
  2775.           (substring str (match-beginning 1) (match-end 1))))
  2776.        (if (not (string-match (concat " *\\([^\001 \t]+\\)" ;1 keyword
  2777.                       " *\\([^\001]*\\)" ;2 data
  2778.                       " *$")
  2779.                   str))
  2780.        (if (and debug-on-error
  2781.             (string< "" str))
  2782.            (progn
  2783.          (irc-insert "%%Received unknown CTCP request:")
  2784.          (irc-insert "%% \"%s\" (str)." (irc-clean-up-message str))
  2785.          (irc-insert "%% This is probaly not a bug.")))
  2786.        (let ((keyw (substring str (match-beginning 1) (match-end 1)))
  2787.          (args (substring str (match-beginning 2) (match-end 2)))
  2788.          (tell (memq 'ctcp irc-events)))
  2789.          (cond
  2790.            ((string= keyw "ACTION") ;CLIENT_ACTION
  2791.         (if (string= "" args)
  2792.             (irc-send (format "NOTICE %s :\001ERRMSG ACTION :%s\001"
  2793.                       sndr
  2794.                       "No argument supplied."))
  2795.             (irc-insert ">>> (To %s) User %s %s"
  2796.                 rcvr
  2797.                 sndr
  2798.                 (irc-clean-up-message args))))
  2799.            ((string= keyw "CLIENTINFO")
  2800.         (cond ((string-match "^ *$" args) ;No arguments
  2801.                (irc-send
  2802.             (concat "NOTICE " sndr " :\001"
  2803.                 (irc-ctcp-enquote
  2804.                  (concat
  2805.                   "CLIENTINFO :You can request help of the"
  2806.                   " commands ACTION CLIENTINFO ECHO ERRMSG"
  2807.                   " FINGER PING SOURCE USERINFO VERSION"
  2808.                   " by giving an argument to CLIENTINFO."))
  2809.                 "\001"))
  2810.                (if tell
  2811.                (irc-insert
  2812.                 "%sAnswered (CTCP) CLIENTINFO query to %s by %s%s"
  2813.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)) )
  2814.               ((string-match "^ *\\([^: ]+\\) *$" args) ;1 arg
  2815.                (let* ((w (substring args
  2816.                         (match-beginning 1)
  2817.                         (match-end 1)))
  2818.                   (uw (upcase w))
  2819.                   (info (cond
  2820.                       ((string= uw "ACTION")
  2821.                        (concat
  2822.                     "ACTION takes one or more arguments,"
  2823.                     " and displayes them as a \"MUD like"
  2824.                     " feeling\" to this user. If nick"
  2825.                     " sojge sends \"falls down\", this"
  2826.                     " user gets a message looking more or"
  2827.                     " less like \"User sojge falls"
  2828.                     " down\"."))
  2829.                       ((string= uw "CLIENTINFO")
  2830.                        (concat
  2831.                     "CLIENTINFO with 0 arguments gives"
  2832.                     " a list of known client query"
  2833.                     " keywords. With 1 argument,"
  2834.                     " a description of the client query"
  2835.                     " keyword is returned."))
  2836.                       ((string= uw "ECHO")
  2837.                        (concat
  2838.                     "ECHO returns whatever argument is"
  2839.                     " given."))
  2840.                       ((string= uw "ERRMSG")
  2841.                        (concat
  2842.                     "ERRMSG is returned either when the"
  2843.                     " query keyword is ERRMSG (in which"
  2844.                     " case all arguments are echoed) or"
  2845.                     " when an error in a query is"
  2846.                     " detected or some other error"
  2847.                     " happens in connection to CTCP (in"
  2848.                     " which case the query is returned as"
  2849.                     " the replies arguments, with a short"
  2850.                     " error message added)."))
  2851.                       ((string= uw "FINGER")
  2852.                        (concat
  2853.                     "FINGER shows user's real name, login"
  2854.                     " name, client machine and idle"
  2855.                     " time."))
  2856.                       ((string= uw "PING")
  2857.                        (concat
  2858.                     "PING takes a integer number as its"
  2859.                     " argument and echoes it back to the"
  2860.                     " sender."))
  2861.                       ((string= uw "SOURCE")
  2862.                        (concat
  2863.                     "SOURCE takes 0 arguments and returns"
  2864.                     " a description of where to find the"
  2865.                     " source code of the client. The"
  2866.                     " description is made up out of zero"
  2867.                     " or more lines followed by an end"
  2868.                     " marker. Every line is a CTCP"
  2869.                     " reply with the SOURCE keyword,"
  2870.                     " a space, the name of a FTP-server, a"
  2871.                     " colon, a directory name, a colon,"
  2872.                     " and 0 or more file names."
  2873.                     " If no file names are given, all the"
  2874.                     " files in the named directory are"
  2875.                     " needed. The end marker contains just"
  2876.                     " the keyword."))
  2877.                       ((string= uw "VERSION")
  2878.                        (concat
  2879.                     "VERSION takes 0 arguments and"
  2880.                     " returns a list of words consisting"
  2881.                     " of clients name, any number of"
  2882.                     " versions (starting with the major"
  2883.                     " version), and ending with the"
  2884.                     " enviroment the client runs in. A"
  2885.                     " colon and a plain text descrpition"
  2886.                     " of the clients version is appended"
  2887.                     " after the list."))
  2888.                       ((string= uw "USERINFO")
  2889.                        (concat
  2890.                     "USERINFO takes no arguments and"
  2891.                     " returns a user settable"
  2892.                     " string."))
  2893.                       (t nil))))
  2894.              (cond ((stringp info)
  2895.                 (irc-send
  2896.                  (concat "NOTICE " sndr " :\001"
  2897.                      (irc-ctcp-enquote
  2898.                       (concat "CLIENTINFO :" info))
  2899.                      "\001"))
  2900.                 (if tell
  2901.                     (irc-insert
  2902.                      (concat "%sAnswered (CTCP)"
  2903.                          " CLIENTINFO %s to %s by %s%s")
  2904.                      irc-msg-info-pre
  2905.                      uw
  2906.                      rcvr
  2907.                      sndr
  2908.                      irc-msg-info-post)))
  2909.                    (t (irc-send
  2910.                    (concat
  2911.                     "NOTICE " sndr " :\001"
  2912.                     (irc-ctcp-enquote
  2913.                      (concat
  2914.                       "ERRMSG " keyw
  2915.                       (if args
  2916.                       (concat " " args)
  2917.                       "")
  2918.                       " :Unknown keyword in CLIENTINFO"
  2919.                       " client query. Send CLIENTINFO"
  2920.                       " CLIENTINFO for help."))
  2921.                     "\001"))))))
  2922.               (t (irc-send
  2923.               (concat "NOTICE " sndr " :\001"
  2924.                   (irc-ctcp-enquote
  2925.                    (concat "ERRMSG " keyw " " args " :"
  2926.                        "CLIENTINFO takes 0 or 1"
  2927.                        " argument. Send"
  2928.                        " CLIENTINFO CLIENTINFO"
  2929.                        " for help."))
  2930.                   "\001"))
  2931.              (if tell
  2932.                  (irc-insert (concat
  2933.                       "%sComplained about user %s's"
  2934.                       " corrupted CTCP CLIENTINFO query to"
  2935.                       " %s%s")
  2936.                      irc-msg-info-pre
  2937.                      sndr
  2938.                      rcvr
  2939.                      irc-msg-info-post)))))
  2940.            ((string= keyw "ECHO") 
  2941.         (irc-send (format "NOTICE %s :\001ECHO %s\001"
  2942.                   sndr
  2943.                   (irc-ctcp-enquote args)))
  2944.         (if tell
  2945.             (irc-insert (concat "%sAnswered to (CTCP) ECHO request"
  2946.                     " from %s to %s, echoed back \"%s\"%s")
  2947.                 irc-msg-info-pre rcvr sndr args
  2948.                 irc-msg-info-post)))
  2949.            ((string= keyw "ERRMSG")
  2950.         (irc-send (format "NOTICE %s :\001ERRMSG %s :No errors.\001"
  2951.                   sndr args))
  2952.         (cond ((not tell)
  2953.                )
  2954.               ((string-match "^ *PING +RELAY +[0-9]+ *$" args)
  2955.                (irc-insert (concat "%sAnswered to (CTCP) ERRMSG PING"
  2956.                        " RELAY request to %s from %s%s")
  2957.                    irc-msg-info-pre rcvr sndr
  2958.                    irc-msg-info-post))
  2959.               (t (irc-insert (concat "%sAnswered to (CTCP) ERRMSG"
  2960.                          " request to %s from %s, echoed"
  2961.                          " back \"%s\"%s")
  2962.                      irc-msg-info-pre
  2963.                      rcvr sndr (concat args " :No errors")
  2964.                      irc-msg-info-post))))
  2965.            ((string= keyw "FINGER")
  2966.         (let* ((idle (irc-idle-time))
  2967.                (verbose-idle (concat "(" (irc-sec-to-time idle) ") "))
  2968.                (plur (not (= 1 idle))))
  2969.           (irc-send (format (concat "NOTICE %s :\001FINGER :Please"
  2970.                         " check my USERINFO instead :%s"
  2971.                         " (%s@%s) %d second%s %sha%s"
  2972.                         " passed since %s gave a command"
  2973.                         " last.\001")
  2974.                     sndr
  2975.                     (user-full-name)
  2976.                     (user-real-login-name)
  2977.                     (system-name)
  2978.                     idle
  2979.                     (if plur "s" "")
  2980.                     (if (>= idle 60) verbose-idle "")
  2981.                     (if plur "ve" "s")
  2982.                     irc-nick-used)))
  2983.         (if tell
  2984.             (irc-insert "%sAnswered (CTCP) FINGER query to %s by %s%s"
  2985.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  2986.            ((string= keyw "PING")
  2987.         (cond ((string-match "^[0-9]+$" args)
  2988.                (irc-send (format "NOTICE %s :\001PING %s\001"
  2989.                      sndr
  2990.                      (irc-ctcp-enquote args)))
  2991.                (if tell
  2992.                (irc-insert
  2993.                 "%sAnswered to (CTCP) PING query to %s from %s%s"
  2994.                 irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  2995.               (t (irc-send (format "NOTICE %s :\001%s %s :%s\001"
  2996.                        sndr
  2997.                        "ERRMSG PING"
  2998.                        (irc-ctcp-enquote args)
  2999.                        "Argument was not a number"))
  3000.              (cond
  3001.                (tell
  3002.                 (irc-insert (concat "%%Received unknown CTCP PING"
  3003.                         " query to %s from user"
  3004.                         " \"%s\":")
  3005.                     rcvr sndr)
  3006.                 (irc-insert "%% \"%s\" (args)." args)
  3007.                 (irc-insert "%% This is probaly NOT a bug."))))))
  3008.            ((string= keyw "SOURCE")
  3009.         (let ((s irc-ftp-source))
  3010.           (while (not (null s))
  3011.             (let* ((r (car s))
  3012.                (site (nth 0 r))
  3013.                (dir (nth 1 r))
  3014.                (files (nth 2 r)))
  3015.               (irc-send
  3016.                (concat "NOTICE " sndr " :\001"
  3017.                    (irc-ctcp-enquote
  3018.                 (format "SOURCE %s:%s:%s"
  3019.                     site
  3020.                     dir
  3021.                     (irc-listify files " " "")))
  3022.                    "\001"))
  3023.               (setq s (cdr s))))
  3024.           (irc-send (concat "NOTICE " sndr " :\001SOURCE\001"))
  3025.           (if tell
  3026.               (irc-insert
  3027.                "%sAnswered (CTCP) SOURCE query to %s by %s%s"
  3028.                irc-msg-info-pre
  3029.                rcvr sndr
  3030.                irc-msg-info-post))))
  3031.            ((string= keyw "USERINFO") ;CLIENT_USERINFO
  3032.         (irc-send (concat "NOTICE " sndr " :\001"
  3033.                   (irc-ctcp-enquote
  3034.                    (concat "USERINFO :"
  3035.                        (if (stringp irc-userinfo)
  3036.                            irc-userinfo
  3037.                            "")))
  3038.                   "\001"))
  3039.         (if tell
  3040.             (irc-insert
  3041.              "%sAnswered (CTCP) USERINFO query to %s by %s%s"
  3042.              irc-msg-info-pre rcvr sndr irc-msg-info-post)))
  3043.            ((string= keyw "VERSION")
  3044.         (cond ((string-match (concat
  3045.                       "^ *\\([^: ]+\\) +v?\\([0-9]+[^ ]+\\)"
  3046.                       " +\\(.*\\) *$")
  3047.                      irc-version)
  3048.                (irc-send
  3049.             (concat "NOTICE " sndr " :\001"
  3050.                 (irc-ctcp-enquote
  3051.                  (format "%s %s:%s:%s, %s, emacs %s"
  3052.                      keyw
  3053.                      (subfield irc-version 1)
  3054.                      (subfield irc-version 2)
  3055.                      (subfield irc-version 3)
  3056.                      (cond
  3057.                        (irc-emacs-knows-ISO8859-1
  3058.                         "8bit ISO 8859-1 characters")
  3059.                        (irc-translation-table-incoming
  3060.                         "8bit characters")
  3061.                        (t (concat "7bit ISO 646 characters"
  3062.                               " (ie ASCII with"
  3063.                               " friends)")))
  3064.                      emacs-version))
  3065.                 "\001"))
  3066.                (if tell
  3067.                (irc-insert
  3068.                 "%sAnswered (CTCP) %s query to %s by %s%s"
  3069.                 irc-msg-info-pre keyw rcvr sndr
  3070.                 irc-msg-info-post)))
  3071.               (t (irc-send (concat "NOTICE " sndr " :\001"
  3072.                        (irc-ctcp-enquote
  3073.                         (format "%s Kiwi::%s"
  3074.                             keyw
  3075.                             irc-version))
  3076.                        "\001"))
  3077.              (cond
  3078.                (tell
  3079.                 (irc-insert
  3080.                  "%sAnswered (CTCP) %s query to %s by %s%s"
  3081.                  irc-msg-info-pre keyw rcvr sndr irc-msg-info-post)
  3082.                 (irc-insert "%% Client doesn't know who it is!")
  3083.                 (irc-insert "%% Please tell %s." irc-hacker))))))
  3084.            (t (and nil
  3085.                (irc-send
  3086.            (concat "NOTICE " sndr " :\001"
  3087.                (irc-ctcp-enquote
  3088.                 (concat "ERRMSG "
  3089.                     keyw
  3090.                     (if args
  3091.                     (concat " " args)
  3092.                     "")
  3093.                     " :Query is unknown"))
  3094.                "\001"))
  3095.                )
  3096.           (cond
  3097.             (tell
  3098.              (irc-insert (concat "%%Received unknown CTCP \"%s\" to %s"
  3099.                      " from user \"%s\".")
  3100.                  str rcvr sndr))))))))))
  3101.  
  3102.  
  3103. (defun irc-parse-ERR (str)
  3104.   "Examine a numeric ERR_ message from the IRC server. Numeric
  3105. control messages are used by newer servers to aid in generalized
  3106. client design; while people are converting to the new servers the
  3107. older irc-parse-error, irc-parse-notice, et al, functions are
  3108. redundant with irc-parse-ERR and irc-parse-RPL.  Values used by this
  3109. function are found in the IRC source file numeric.h.
  3110.  
  3111. Note well that some things are still going to come out wrong because the
  3112. servers are currently still doing things inconsistently."
  3113.   (if (not (string-match (concat "^:\\(.*\\) +\\([4-5][0-9][0-9]\\) +"
  3114.                  "\\([^: ]*\\)? *:? *\\(.*\\) *$")
  3115.              str))
  3116.       (progn
  3117.     (irc-insert (concat "%%Received an ERR message with unknown format in"
  3118.                 " function irc-parse-ERR:"))
  3119.     (irc-insert "%% \"%s\"." str)
  3120.     (irc-insert "%%Please report this to %s." irc-hacker))
  3121.       (let*
  3122.       ;; we assume that the server and message are consistent for us; just
  3123.       ;; worry about the numeric value and the rest of the line
  3124.       ((srvr (subfield str 1))
  3125.        (code (subfield str 2))
  3126.        (txt (subfield str 4))
  3127.        (num (string-to-int code))
  3128.        (parorg (if (string= (upcase srvr) (upcase irc-server))
  3129.                ""
  3130.                (concat "(" srvr ") ")))
  3131.        (tmp1 nil))
  3132.     (if (not (string= "" srvr))
  3133.         (irc-remember srvr 'irc-servernames))
  3134.     (cond
  3135.       ((= num 401)        ; ERR_NOSUCHNICK
  3136.        (cond ((string-match (concat "^[^: ]+ +401 +[^: ]+ +"
  3137.                     ":Hunting +for +ghosts +?.*$")
  3138.                 str)
  3139.           nil)        ;Ignore "Hunting for ghosts ?" message.
  3140.          ((string-match (concat "^[^: ]+ +401 +[^: ]+ +"
  3141.                     ":Cannot +kick +user +off +"
  3142.                     "channel *$")
  3143.                 str)
  3144.           (irc-insert "%%%sCan't boot that user from that channel."
  3145.                   parorg))
  3146.          ((string-match "^@?[^:@ ]+" txt)
  3147.           (let* ((user (substring txt
  3148.                       (match-beginning 0)
  3149.                       (match-end 0)))
  3150.              (is-service (irc-recall user 'irc-services)))
  3151.             (if is-service
  3152.             (irc-insert (concat "%%Service %s isn't reachable at"
  3153.                         " the moment, please try again"
  3154.                         " later.")
  3155.                     is-service)
  3156.             (progn
  3157.               (if (irc-is-nickname user)
  3158.                   (irc-forget user 'irc-nicknames))
  3159.               (irc-insert (concat
  3160.                        "%%%sThere is no user called"
  3161.                        " \"%s\" on IRC at the moment.")
  3162.                       parorg
  3163.                       user)))
  3164.             (if (and (>= irc-major-version 2)
  3165.                  (>= irc-minor-version 6))
  3166.             (irc-send (concat "WHOWAS :" user))
  3167.             )))
  3168.          (t (irc-insert (concat "%%%sUnrecognized NO SUCH NICK"
  3169.                     " message follows; please tell %s:")
  3170.                 parorg
  3171.                 irc-hacker)
  3172.             (irc-insert "%% \"%s\"." str)
  3173.             (irc-insert "%%Function irc-parse-err, at 401."))))
  3174.       ((= num 402)        ; ERR_NOSUCHSERVER
  3175.        (cond ((or (string-match (concat "^ *\\(.+\\) *: *"
  3176.                         "\\(\\*\\*\\* * \\)?No +such +"
  3177.                         "server *.? *$")
  3178.                     txt)
  3179.               (string-match (concat "^:? *\\** *No +such"
  3180.                         " +server *( *"
  3181.                         "\\([^: ]+\\) *) *.?"
  3182.                         " *$")
  3183.                     txt))
  3184.           (irc-insert (concat "%%%sThere is no server \"%s\" on the"
  3185.                       " IRCnet at the moment.")
  3186.                   parorg
  3187.                   (irc-nuke-whitespace (subfield txt 1))))
  3188.          (t (irc-insert (concat "%%Unknown ERR 402 message received"
  3189.                     " in function irc-parse-ERR:"))
  3190.             (irc-insert "%% txt=\"%s\"." txt)
  3191.             (irc-insert "%% Please tell %s, it might be a bug."
  3192.                 irc-hacker))))
  3193.       ((= num 403)        ; ERR_NOSUCHCHANNEL
  3194.        (if (string= (upcase srvr) (upcase irc-server))
  3195.            (let ((chn (if (string-match "^\\([^: ]+\\) *:.*$" txt)
  3196.                   (subfield txt 1))))
  3197.          (if chn
  3198.              (irc-insert (concat "%%%sThere is no channel called"
  3199.                      " \"%s\" in use right now.")
  3200.                  parorg chn)
  3201.              (irc-insert "%%%sNo such channel in use." parorg)))))
  3202.       ((= num 404)        ; ERR_CANNOTSENDTOCHAN
  3203.        (if (string-match "^ *\\([^ :]+\\) *:" txt)
  3204.            (irc-insert "%%%sChannel %s rejected the message."
  3205.                parorg (subfield txt 1))
  3206.            (irc-insert "%%%sChannel rejected the message." parorg)))
  3207.       ((= num 405)
  3208.        (cond ((string-match (concat "^ *\\([^ ]+\\) *: *You +have +joined"
  3209.                     " +too +many +channels.? *$")
  3210.                 txt)
  3211.           (irc-insert (concat "%%Failed joining channel %s, as you're"
  3212.                       " already listening to too many"
  3213.                       " channels.")
  3214.                   (subfield txt 1)))
  3215.          (t (irc-insert "*** %s %s." parorg txt))))
  3216.       ((= num 406)
  3217.        (if (string-match "^ *\\([^: ]+\\) *: *\\(.*\\) *$"
  3218.                  txt)
  3219.            (let ((m (substring txt (match-beginning 2) (match-end 2)))
  3220.              (n (substring txt (match-beginning 1) (match-end 1))))
  3221.          (irc-insert
  3222.           "%%No trace left about \"%s\" in history of server %s."
  3223.           n srvr))
  3224.            (progn
  3225.          (irc-insert "%%Unknown type 406 error message from server:")
  3226.          (irc-insert "%% \"%s\" (str)." str)
  3227.          (irc-insert "%% Please tell %s, it migth be a bug."
  3228.                  irc-hacker))))
  3229.       ((= num 409)
  3230.        ;txt="No origin specified"
  3231.        (irc-insert "%%%s%s" parorg txt))
  3232.       ((= num 411)        ; ERR_NORECIPIENT
  3233.        (irc-insert "%%%sThe last message had no recipient." parorg))
  3234.       ((= num 412)        ; ERR_NOTEXTTOSEND
  3235.        (irc-insert "%%%sThe last message had no text to send." parorg))
  3236.       ((= num 413)
  3237.        (irc-insert "%%%sNo top level domain specified (no such receiver)."
  3238.                parorg))
  3239.       ((= num 421)        ; ERR_UNKNOWNCOMMAND
  3240.        (cond ((string-match "^CLIENT-SYNCH :?\\(.*\\) *:Unknown command$"
  3241.                 txt)
  3242.           (let* ((cmd (irc-nuke-whitespace (subfield txt 1)))
  3243.              (ucmd (upcase cmd)))
  3244.             (cond 
  3245.              ((or t (string-match "^QUOTE " ucmd))
  3246.               (irc-insert "%sEnd of quoted command%s"
  3247.                   irc-msg-info-pre irc-msg-info-post))
  3248.              (t (irc-insert (concat "%%Unknown internal"
  3249.                         " synchronisation in"
  3250.                         " irc-parse-ERR at 421:"))
  3251.             (irc-insert "%% \"%s\" (txt)." txt)
  3252.             (irc-insert "%% Please tell %s, this *is* a bug."
  3253.                     irc-hacker)))))
  3254.          ((string-match (concat "^\\(MODE\\|KICK\\|JOIN\\|PART\\)"
  3255.                     ".*Unknown :?command *$")
  3256.                 txt)
  3257.           nil)
  3258.          ((string-match "^CLIENT-START *: *Unknown *command *$" txt)
  3259.           (run-hooks 'irc-startup-hook))
  3260.          ((or (string-match "^\\(.*\\) :?Unknown :?command$" txt)
  3261.               (string-match "^:?Unknown command \\(.*[^ ].*\\) *$"
  3262.                     txt))
  3263.           (if (string= (upcase irc-server) (upcase srvr))
  3264.               (irc-insert "%%%sUnknown server command: %s."
  3265.                   parorg
  3266.                   (subfield txt 1))))
  3267.          (t (irc-insert (concat "%%%sUnkown server command,"
  3268.                     " reported in unknown format:")
  3269.                 parorg)
  3270.             (irc-insert "%% \"%s\" (txt)." txt)
  3271.             (irc-insert "%% Function irc-parse-err, at 421."))))
  3272.       ((or (= num 422)        ;ERR_NOMOTD
  3273.            (= num 423))        ;ERR_NOADMIN
  3274.        (irc-insert "%%%s%s" parorg txt))
  3275.       ((= num 431)        ; ERR_NONICKNAMEGIVEN
  3276.        (irc-insert "%%%sNo nickname give to change to." parorg))
  3277.       ((= num 432)        ; ERR_ERRONEUSNICKNAME
  3278.        (irc-insert (concat "%%%sBad format for nickname change. Your"
  3279.                    " nickname is \"%s\".")
  3280.                parorg irc-nick-used))
  3281.       ((= num 433)        ; ERR_NICKNAMEINUSE
  3282.        (if (or (string-match (concat "^:[^: \t]+ +433 +"
  3283.                      "\\([^: \t]+\\) +"
  3284.                      "\\([^: \t]+\\) +:")
  3285.                  str)
  3286.            (string-match (concat "^:[^: \t]+ +433 +\\(\\)"
  3287.                      "\\([^: \t]+\\) +:")
  3288.                  str))
  3289.            (let ((current (subfield str 1))
  3290.              (failed (subfield str 2)))
  3291.          (irc-insert (concat "%%%sNickname \"%s\" is already being"
  3292.                      " used, please choose another one.")
  3293.                  parorg
  3294.                  failed)
  3295.          (irc-insert "%sHmmm ... looks like you're still %s%s"
  3296.                  irc-msg-info-pre
  3297.                  (if (string= current "")
  3298.                  (concat "without a nickname, use \"/HELP"
  3299.                      " NICK\" to get help about how to"
  3300.                      " set one")
  3301.                  (concat "\"" current "\""))
  3302.                  irc-msg-info-post))
  3303.            (irc-insert "%%Unknown ERR 433 type message received:")
  3304.            (irc-insert "%% \"%s\" (str)." str)
  3305.            (irc-insert "%% Please tell %s." irc-hacker)))
  3306.       ((= num 436)
  3307.        (cond ((string-match "^\\([^ :]+\\) :Nickname collision KILL$" txt)
  3308.           (let ((nick (subfield txt 1)))
  3309.             (irc-insert "%sUser %s killed due to NAMECLASH at %s%s"
  3310.                 irc-msg-info-pre
  3311.                 nick
  3312.                 srvr
  3313.                 irc-msg-info-post)
  3314.             (irc-forget nick 'irc-nicknames)))
  3315.          (t (irc-insert "%%Unknown ERR 436 type message received:")
  3316.             (irc-insert "%% \"%s\" (txt)." txt)
  3317.             (irc-insert "%% Please tell %s." irc-hacker))))
  3318.       ((= num 441)        ; ERR_USERNOTINCHANNEL
  3319.        (if (string= (upcase irc-server) (upcase srvr))
  3320.            (irc-insert "%%%sYou're not on any channel." parorg)))
  3321.       ((= num 442)        ; ERR_NOTONCHANNEL
  3322.        (cond ((or (string-match (concat "^ *\\([^ :]+\\) +"
  3323.                         "\\([^ :]+\\) *: *"
  3324.                         "\\([^ :]+\\) +is +not"
  3325.                         " +here *.? *$")
  3326.                     txt)
  3327.               (string-match (concat "^ *\\([^: ]+\\) *\\(\\):\\"
  3328.                         "([^: ]+\\) +is +not +here *$")
  3329.                     str))
  3330.           (let* ((o1 (subfield txt 1))
  3331.              (c (subfield txt 2))
  3332.              (o2 (subfield txt 3))
  3333.              (chn (if (string= c "") irc-channel c))
  3334.              (name (if (string= o1 o2)
  3335.                    o1
  3336.                    (concat o2 " (" o1 ")"))))
  3337.             (irc-insert (concat "%%You can't change the channel"
  3338.                     " operator status of %s while s/he"
  3339.                     " isn't here on %s.")
  3340.                 name chn)))
  3341.          ((string-match (concat "^ *\\([^ :]+\\) +\\([^ :]+\\)"
  3342.                     " *: *\\(isn't +on +your"
  3343.                     " +channel\\|Cannot +kick"
  3344.                     " +user +off\\ +channel\\)")
  3345.                 txt)
  3346.           (let ((who (subfield txt 1))
  3347.             (chn (subfield txt 2))
  3348.             (msg (subfield txt 3)))
  3349.             (cond ((string-match "^isn't" msg)
  3350.                (irc-insert (concat "%%Can't /KICK %s while"
  3351.                            " s/he's not on your"
  3352.                            " channel %s.")
  3353.                        who chn))
  3354.               (t (irc-insert (concat "%%Failed to /KICK %s from"
  3355.                          " channel %s.")
  3356.                      who chn)))))
  3357.          ((string-match (concat "^: *[^: ]+ +442 +[^: ]+"
  3358.                     " +\\([^: ]+\\) *: *"
  3359.                     "isn't *on *your *"
  3360.                     "channel *!* *$")
  3361.                 str)
  3362.           (let ((u (subfield str 1)))
  3363.             (irc-insert (concat "%%Can't /kick user %s while s/he's"
  3364.                     " not on this channel.")
  3365.                 u)))
  3366.          ((or (string-match (concat ":[^: ]+ +442 +[^: ]+"
  3367.                         " +\\([^: ]+\\) +: *You're +not"
  3368.                         " +on *\\(that\\)? +channel *$")
  3369.                     str)
  3370.               (string-match
  3371.                (concat "^:[^: ]+ +442 +[^: ]+ +\\([^ ]+\\) *: *Not"
  3372.                    " *On *Channel$")
  3373.                str)
  3374.               (string-match (concat "^[^: ]+ +442 +[^: ]+"
  3375.                         " +\\([^ ]+\\): *You're +not +on"
  3376.                         " +channel +\\([^ ]+\\) *$")
  3377.                     str)
  3378.               (string-match (concat "^:[^: ]+ +442 +[^: ]+"
  3379.                         " *: *You're +not on"
  3380.                         " +channel +\\([^ ]+\\) *$")
  3381.                     str))
  3382.           (let ((c (subfield str 1)))
  3383.             (irc-insert "%%You're not on channel %s." c)))
  3384.          ((string-match "^\\([^ :]+\\) *:\\(.*\\)$" txt)
  3385.           (irc-insert "%%%s: %s" (subfield txt 2) (subfield txt 1)))
  3386.          ((string= (upcase irc-server) (upcase srvr))
  3387.           (irc-insert (concat "%%Unknown format on"
  3388.                       " ERR_NOTONCHANNEL message;"
  3389.                       " please tell %s, it might be"
  3390.                       " a bug:")
  3391.                   irc-hacker)
  3392.           (irc-insert "%% \"%s\" (str)." str)
  3393.           (irc-insert "%% Function irc-parse-ERR, at 442."))))
  3394.       ((= num 443)
  3395.        (if (string-match (concat "^\\([^: ]+\\) +\\([^: ]+\\) +"
  3396.                      ":is already on channel.?$")
  3397.                  txt)
  3398.            (let ((nick (subfield txt 1))
  3399.              (chan (subfield txt 2)))
  3400.          (irc-insert "%%User %s is already on channel %s." nick chan))
  3401.            (irc-insert "%%Unknown ERR433 message seen in irc-parse-ERR:")
  3402.            (irc-insert "%% \"%s\" (txt)." txt)
  3403.            (irc-insert "%% Please tell %s." irc-hacker)))
  3404.       ((= num 444)
  3405.        (if (string-match "^\\([^: ]+\\) +:\\(.*\\)$" txt)
  3406.            (let ((user (subfield txt 1))
  3407.              (mesg (subfield txt 2)))
  3408.          (irc-insert "%%%sNo such user as \"%s\" logged in."
  3409.                  parorg user))
  3410.            (irc-insert "%%%sNo such user logged in." parorg)))
  3411.       ((= num 445)
  3412.        (irc-insert "%%%s%s" parorg txt))
  3413.       ((= num 446)
  3414.        (irc-insert "%%%sCommand /%s" parorg txt))
  3415.       ((= num 451)        ; ERR_NOTREGISTERED
  3416.        (irc-insert "%%%sYou haven't checked in yet.  Choose a nickname."
  3417.                parorg))
  3418.       ((= num 461)        ; ERR_NEEDMOREPARAMS
  3419.        (if (or (string= "" srvr)
  3420.            (string= (upcase irc-server) (upcase srvr)))
  3421.            (irc-insert (concat "%%%sThere weren't enough arguments for"
  3422.                    " the last command.")
  3423.                parorg)))
  3424.       ((= num 462)        ; ERR_ALREADYREGISTRED
  3425.        (irc-insert "%%%sYou've already registered." parorg))
  3426.       ((= num 463)        ; ERR_NOPERMFORHOST
  3427.        (irc-insert "%%%sYour host isn't permitted." parorg))
  3428.       ((= num 464)        ; ERR_PASSWDMISMATCH
  3429.        (irc-insert "%%%sThat password is incorrect." parorg))
  3430.       ((= num 465)        ; ERR_YOUREBANNEDCREEP
  3431.        (irc-insert "%%%sYou've been banned from IRC." parorg))
  3432.       ((= num 466)        ; ERR_YOUWILLBEBANNED
  3433.        (irc-insert "%%%sYou will be banned from IRC (%s)." parorg str))
  3434.       ((= num 467)
  3435.        (if (string-match "^\\([^ :]+\\) :" txt)
  3436.            (irc-insert (concat "%%%sChannel %s already has a key, use"
  3437.                    " /MODE %s to see it.")
  3438.                parorg
  3439.                (subfield txt 1)
  3440.                (subfield txt 1))
  3441.            (irc-insert (concat "%%%sChannel already has a key, use /MODE"
  3442.                    " to see it.")
  3443.                parorg)))
  3444.       ((= num 471)        ; ERR_CHANNELISFULL
  3445.        (string-match "^[^: ]+" txt)
  3446.        (let ((s (substring txt (match-beginning 0) (match-end 0))))
  3447.          (irc-insert (concat "%%%sChannel %s is full. (Check limit with"
  3448.                  " /MODE %s)")
  3449.              parorg s s)))
  3450.       ((= num 472)        ; ERR_UNKNOWNMODE
  3451.        (if (not (string-match (concat "^: *\\([^: ]+\\) +472 +"
  3452.                       "\\([^: ]+\\) +\\(.*\\) +:?is +"
  3453.                       "unknown +mode +char +to +me *$")
  3454.                   str))
  3455.            (progn (irc-insert (concat "%%Unrecognized type 472 message;"
  3456.                       " please tell %s:")
  3457.                   irc-hacker)
  3458.               (irc-insert "%% \"%s\"." str)
  3459.               (irc-insert "%% Function irc-parse-ERR, at 472."))
  3460.            (let ((srv (substring str (match-beginning 1) (match-end 1)))
  3461.              (nick (substring str (match-beginning 2) (match-end 2)))
  3462.              (chr (substring str (match-beginning 3) (match-end 3))))
  3463.          (if (not (string= (upcase srvr) (upcase srv)))
  3464.              (irc-remember srv 'irc-servernames))
  3465.          (irc-remember nick 'irc-nicknames)
  3466.          (irc-insert "%%Character \"%s\" is not a MODE character."
  3467.                  chr))))
  3468.       ((= num 473)        ; ERR_INVITEONLYCHAN
  3469.        (if (not (string-match (concat "^:[^: ]+ +473 +[^: ]+ +"
  3470.                       "\\([^ ]+\\) +.*")
  3471.                   str))
  3472.            (progn (irc-insert (concat "%%%sUnknown format on"
  3473.                       " ERR_INVITEONLYCHAN; please tell"
  3474.                       " %s, it might be a bug:")
  3475.                   parorg
  3476.                   irc-hacker)
  3477.               (irc-insert "%% \"%s\" (str)." str)
  3478.               (irc-insert "%% Function irc-parse-ERR, at 473."))
  3479.            (let ((chn (substring str (match-beginning 1) (match-end 1))))
  3480.          (irc-insert (concat "%%%sYou need an invitation to join"
  3481.                      " invitation-only channel \"%s\".")
  3482.                  parorg
  3483.                  chn))))
  3484.       ((= num 474)
  3485.        (cond
  3486.          ((string-match "^\\([^ ]+\\) +:" txt)
  3487.           (let ((channel (subfield txt 1)))
  3488.         (irc-insert (concat "%%Can't join channel %s -- you're"
  3489.                     " banned from it.")
  3490.                 channel)))
  3491.          (t (irc-insert "%%Unknown ERR474 seen in irc-parse-ERR:")
  3492.         (irc-insert "%% \"%s\" (txt)" txt)
  3493.         (irc-insert "%% Please tell %s, it might be a bug."
  3494.                 irc-hacker))))
  3495.       ((= num 475)            ;ERR_CANT_JOIN
  3496.        (cond ((string-match "^\\([^ ]+\\) +:" txt)
  3497.           (let ((channel (subfield txt 1)))
  3498.             (irc-insert (concat "%%Can't join channel %s -- you"
  3499.                     " haven't supplied the right channel"
  3500.                     " key/password."))))
  3501.          (t (irc-insert "%%Unknown ERR475 seen in irc-parse-ERR:")
  3502.             (irc-insert "%% \"%s\" (txt)" txt)
  3503.             (irc-insert "%% Please tell %s, it might be a bug."
  3504.                 irc-hacker))))
  3505.       ((= num 481)        ; ERR_NOPRIVILEGES
  3506.        (if (string= (upcase irc-server) (upcase srvr))
  3507.            (if (string-match "CHANNEL" str)
  3508.            (irc-insert
  3509.             (concat "%%%sYou must be a channel operator"
  3510.                 " to "
  3511.                 (cond
  3512.                   ((string-match (concat ":Cannot set topic, not"
  3513.                              " channel OPER$")
  3514.                          str)
  3515.                    "set the channels topic.")
  3516.                   (t "do that.")))
  3517.             parorg)
  3518.            (irc-insert (concat "%%%sYou must be an enabled IRC"
  3519.                        " Operator to do THAT!")
  3520.                    parorg))))
  3521.       ((= num 482)        ; ERR_NOOPERHOST
  3522.        (if (and (irc-server-has-channelname-in-msgs)
  3523.             (string-match "^\\([^ ]+\\) *:.*$" txt))
  3524.            (irc-insert "%%%sYou're not a channel operator for %s!"
  3525.                parorg
  3526.                (subfield txt 1))
  3527.            (irc-insert (concat "%%%sYou're not a channel operator on"
  3528.                    " that channel!")
  3529.                parorg)))
  3530.       ((= num 491)        ; ERR_NOOPERHOST
  3531.        (irc-insert (concat "%%Password check failed at server %s,"
  3532.                    " you're still a disabled luser.")
  3533.                (upcase srvr)))
  3534.       ((= num 501)        ; ERR_UMODEUNKNOWNFLAG
  3535.        (irc-insert "%%%s." txt))
  3536.       ((= num 502)        ; ERR_USERSDONTMATCH
  3537.        (irc-insert (concat "%%You can't change, not even look at, other"
  3538.                    " user's modes.")))
  3539.       ((= num 513)
  3540.        (if (string-match "^To connect, type /QUOTE PONG \\([1-9][0-9]*\\)$"
  3541.                  txt)
  3542.            (irc-send (format "PONG :%s" (subfield txt 1)))
  3543.          (irc-insert "%%Unknown MSG 513 \"%s\"" txt)))
  3544.       (t                                 ; default
  3545.        (irc-insert (concat "%%%sUnrecognized numeric ERR message"
  3546.                    " follows; please tell %s:")
  3547.                parorg
  3548.                irc-hacker)
  3549.        (irc-insert "%% \"%s\" (str)." str)
  3550.        (irc-insert "%%Function irc-parse-err, at catch all.")))))
  3551.   nil)
  3552.  
  3553.  
  3554. (defun irc-parse-error (str)
  3555.   "Examine an ERROR message from the IRC server.
  3556. ERROR is used when something bogus happens like an unparsable command
  3557. is issued to the server.  Usually this will not happen unless something
  3558. like /QUOTE is used.  This message is also used when a user attempts to
  3559. change to a name that already exists.
  3560.  
  3561. Returns nil; currently no signals are issued for an error."
  3562.   (string-match " +:" str)        ;Skip "^ERROR :"
  3563.   (setq str (substring str (match-end 0)))
  3564.   (cond
  3565.     ((string-match (concat "^ *Nickname +[^: ]* +\\(is \\)?"
  3566.                "\\(already\\|not +chan\\|in use\\) *$")
  3567.            str)
  3568.      (irc-insert "%%%s" str)
  3569.      ;; either we couldn't change the current nickname
  3570.      (setq irc-nick (or (and irc-nick (get 'irc-nick 'o-nick))
  3571.             ;; or we never even had one
  3572.             "NO NAME YET (/NICK to set one)"))
  3573.      (set-buffer-modified-p (buffer-modified-p))
  3574.      (irc-insert (if (get 'irc-nick 'o-nick)
  3575.              "%sHmmm ... looks like you're still \"%s\"%s" 
  3576.              "%s%s%s")
  3577.          irc-msg-info-pre
  3578.          irc-nick
  3579.          irc-msg-info-post))
  3580.     ((string-match " *No +option +specified. *Try +MAIL +HELP *$" str)
  3581.      (irc-insert "%%No option specified; try /HELP MAIL and /MAIL HELP."))
  3582.     ((or (string-match (concat "Closing +Link *: *\\([^[ :]+\\[[^]]+\\]\\)"
  3583.                    " *\\(\\)(\\(.*\\)) *$")
  3584.                str)
  3585.      (string-match (concat "Closing +Link *: *\\([^ :]+\\) +\\([^ :]+\\)"
  3586.                    " *\\(.\\|\n\\)+$")
  3587.                str))
  3588.      (let* ((id (subfield str 1))
  3589.         (srce (subfield str 2))
  3590.         (preason (subfield str 3))
  3591.         (reason (if (and (> (length preason) 0)
  3592.                  (= ?\050 (aref preason 0))
  3593.                  (= ?\051 (aref preason (1- (length preason)))))
  3594.             (substring preason 1 (1- (length preason)))
  3595.             preason))
  3596.         (matches (string-match "^\\([^[]+\\)\\[\\([^]]+\\)\\]$" id))
  3597.         (nick (if matches (subfield id 1) ""))
  3598.         (host (if matches (subfield id 2) "")))
  3599.        (irc-parse-quit (format ":%s QUIT %s :%s"
  3600.                    nick
  3601.                    nick
  3602.                    reason))))
  3603.     (t (irc-insert "%%%s" str)))
  3604.   nil)
  3605.  
  3606.  
  3607. (defun irc-parse-invite (str)
  3608.   "Examine an INVITE message from the IRC server.
  3609. INVITE is sent when one user invites another to a channel.
  3610. If the inviter is not being ignored a message is inserted in the buffer.
  3611.  
  3612. This function returns t if a bell should be issued for the \"invite\" event,
  3613. nil otherwise."
  3614.   (let ((user (substring str 1 (string-match " +INVITE " str)))
  3615.         (to (substring str (match-end 0)
  3616.                        (string-match " +:?" str (match-end 0))))
  3617.         (channel (substring str (match-end 0))))
  3618.     ;; glom a new name, if necessary
  3619.     (irc-remember user 'irc-nicknames)
  3620.     (if (irc-recall user 'irc-ignored-ppl)
  3621.         (irc-send (concat "NOTICE " user " :You are being ignored by \""
  3622.               irc-nick-used
  3623.               "\"."))
  3624.     (progn
  3625.       (irc-insert "%sUser %s invites %s to join channel %s%s"
  3626.               irc-msg-info-pre
  3627.               user
  3628.               (if (string= (downcase to) (downcase irc-nick-used))
  3629.               "you"
  3630.               to)
  3631.               (irc-clean-up-message channel)
  3632.               irc-msg-info-post)
  3633.       (irc-signal user 'invite)))))
  3634.  
  3635.  
  3636. (defun irc-parse-kick (str)
  3637.   "Examine and display a KICK message."
  3638.   (if (not
  3639.        (string-match "^: *\\([^: ]+\\) +KICK +\\([^: ]+\\) +\\([^: ]+\\) *"
  3640.              str))
  3641.       (progn (irc-insert (concat "%%Unknown format on KICK message; please"
  3642.                  " tell %s, it might be a bug:")
  3643.              irc-hacker)
  3644.          (irc-insert "%% \"%s\" (str)." str)
  3645.          (irc-insert "%% Function irc-parse-kick."))
  3646.       (let ((actor (substring str (match-beginning 1) (match-end 1)))
  3647.         (chan (substring str (match-beginning 2) (match-end 2)))
  3648.         (victim (substring str (match-beginning 3) (match-end 3))))
  3649.     (irc-remember actor 'irc-nicknames)
  3650.     (irc-remember victim 'irc-nicknames)
  3651.     (cond ((and (string= (upcase actor) (upcase victim))
  3652.             (string= (upcase actor) (upcase irc-nick-used)))
  3653.            (irc-insert "%sYou kicked yourself from channel %s%s"
  3654.                irc-msg-info-pre chan irc-msg-info-post))
  3655.           ((string= (upcase actor) (upcase victim))
  3656.            (irc-insert "%sUser %s kicked him/herself from channel %s%s"
  3657.                irc-msg-info-pre actor chan irc-msg-info-post))
  3658.           ((string= (upcase victim) (upcase irc-nick-used))
  3659.            (irc-insert (concat "%%You have been kicked out from"
  3660.                    " channel %s by user %s.")
  3661.                chan
  3662.                actor))
  3663.           ((string= (upcase actor) (upcase irc-nick-used))
  3664.            (irc-insert (concat "%sYou have kicked out user %s from"
  3665.                    " channel %s%s")
  3666.                irc-msg-info-pre
  3667.                victim
  3668.                chan
  3669.                irc-msg-info-post))
  3670.           (t (irc-insert (concat "%sUser %s kicked out user %s"
  3671.                      " from channel %s%s")
  3672.                  irc-msg-info-pre
  3673.                  actor
  3674.                  victim
  3675.                  chan
  3676.                  irc-msg-info-post)))
  3677.     (if (string= (upcase victim) (upcase irc-nick-used))
  3678.         ;; No need to irc-maintain the victim, -parse-chan does that.
  3679.         (progn (if (irc-server-has-multijoinable-channels)
  3680.                (irc-parse-channel (concat ":" victim " PART " chan))
  3681.                (irc-parse-channel (concat ":" victim " CHANNEL 0")))
  3682.            t)
  3683.         nil))))
  3684.  
  3685.  
  3686. (defun irc-parse-kill (str)
  3687.   "Examine a KILL message from the IRC server.
  3688. For a client this means its connexion will be closing momentarily.  This rather
  3689. drastic turn of events will always get a signal so this function returns t."
  3690.   (if (not (string-match "\\(:[^: ]+ +\\)?KILL +\\([^: ]+\\) +:" str))
  3691.       (progn
  3692.     (irc-insert "%%Spurios KILL message: \"%s\" (str) in irc-parse-kill."
  3693.             str)
  3694.     (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  3695.       (let* ((s (subfield str 1))
  3696.          (v (subfield str 2))
  3697.          (i (substring str (match-end 0)))
  3698.          (server (irc-nuke-whitespace s))
  3699.          (victim (irc-nuke-whitespace v))
  3700.          (info (irc-nuke-whitespace i)))
  3701.     (cond ((string-match "\\([^!]+\\)!\\([^! ]+\\) +"
  3702.                  info)
  3703.            (let* ((s (subfield info 1))
  3704.               (o (subfield info 2))
  3705.               (m (substring info (match-end 0)))
  3706.               (c (if (and (= ?\050 (aref m 0))
  3707.                   (= ?\051 (aref m (1- (length m)))))
  3708.                  (substring m 1 (1- (length m)))
  3709.                  m)))
  3710.          (if (string= (upcase irc-nick-used) (upcase victim))
  3711.              (irc-insert (concat "%sYou have been /KILL'ed by operator"
  3712.                      " %s@%s (%s)%s")
  3713.                  irc-msg-info-pre
  3714.                  (irc-nuke-whitespace o)
  3715.                  (irc-nuke-whitespace s)
  3716.                  (irc-nuke-whitespace c)
  3717.                  irc-msg-info-post)
  3718.              (irc-insert "%sOperator %s@%s /KILL'ed user %s (%s)%s"
  3719.                  irc-msg-info-pre
  3720.                  (irc-nuke-whitespace o)
  3721.                  (irc-nuke-whitespace s)
  3722.                  victim
  3723.                  (irc-nuke-whitespace m)
  3724.                  irc-msg-info-post))))
  3725.           (t (irc-insert "%sUser %s KILL'ed by %s%s"
  3726.                  irc-msg-info-pre
  3727.                  victim
  3728.                  info
  3729.                  irc-msg-info-post)))))
  3730.   t)
  3731.  
  3732.  
  3733. (defun irc-parse-linreply (str)
  3734.   "Examine a LINREPLY message from the IRC server.
  3735. LINREPLY is used to answer a LINKS request to show all the servers on line.
  3736. \"Links\" is a bit of a misnomer since little information regarding the
  3737. actual structure of the IRCnet can be gained from these messages.
  3738.  
  3739. No signals are issued for lines from the LINREPLY."
  3740.   (if (not (string-match "^LINREPLY +\\([^: ]+\\) +" str))
  3741.       (progn (irc-insert (concat "%%Unkown LINREPLY format in "
  3742.                  "function irc-parse-linreply:"))
  3743.          (irc-insert "%% \"%s\"." str)
  3744.          (irc-insert "%% Please tell %s, it may be a bug." irc-hacker))
  3745.       (let ((old-mark irc-mark)
  3746.         (server-name (substring str (match-beginning 1) (match-end 1)))
  3747.         (server-info (irc-clean-up-message (substring str (match-end 0)))))
  3748.     (irc-remember server-name 'irc-servernames)
  3749.     (if (and (irc-terminal-is-slow)
  3750.          (or (irc-server-has-end-of-links) ;New server version ?
  3751.              (and (= irc-major-version 2) (= irc-minor-version 2))))
  3752.         (progn (irc-remember (format "Server %s: %s"
  3753.                      (upcase server-name)
  3754.                      server-info)
  3755.                  'irc-linksinfo)
  3756.            (if (and (not (irc-terminal-is-slow))
  3757.                 (string= (upcase server-name) (upcase irc-server)))
  3758.                (progn
  3759.              (irc-insert irc-links-header)
  3760.              (irc-insert irc-links-stroke)
  3761.              (set-buffer-modified-p (buffer-modified-p))
  3762.              (irc-recall-all-and-display 'irc-linksinfo
  3763.                              (progn
  3764.                                (string-match
  3765.                             "^[^: ]* ."
  3766.                             irc-links-header)
  3767.                                (match-end 0))
  3768.                              "servers"
  3769.                              "server")
  3770.              (irc-forget-all 'irc-linksinfo))))
  3771.     (progn (irc-insert "Server %s: %s"
  3772.                    (upcase server-name)
  3773.                    server-info)))))
  3774.   nil)
  3775.  
  3776.  
  3777. (defun irc-parse-mode-reply (str)
  3778.   "Examine a MODE reply message from the IRC server.
  3779. MODE replies are used in respnse to the MODE command to indicate the current,
  3780. ie new, status of a specified channel or user.
  3781.  
  3782. No signals are issued for MODE replies."
  3783.   (cond ((string-match (concat "^ *: *\\([^: ]+\\) +MODE +"
  3784.                    "\\([^: ]+\\) +:? *")
  3785.                str)
  3786.      (let ((orig (subfield str 1))
  3787.            (chan (subfield str 2))
  3788.            (mode (irc-nuke-whitespace (substring str (match-end 0)))) )
  3789.        (cond ((irc-is-hostname orig)
  3790.           (irc-remember orig 'irc-servernames))
  3791.          ((irc-is-nickname orig)
  3792.           (irc-remember orig 'irc-nicknames)))
  3793.        (cond ((irc-is-nickname chan)
  3794.           (let ((i (1- (length mode)))
  3795.             (um (upcase mode)))
  3796.             (while (and (>= i 0) (not (= ?O (aref um i))))
  3797.               (setq i (1- i)))
  3798.             (while (and (>= i 0)
  3799.                 (not (= ?- (aref um i)))
  3800.                 (not (= ?+ (aref um i))))
  3801.               (setq i (1- i)))
  3802.             (if (and (>= i 0) (= ?- (aref um i)))
  3803.             (setq irc-operator nil)
  3804.             (set-buffer-modified-p (buffer-modified-p))))
  3805.           (irc-insert "%sMode for user %s changed by %s: %s%s"
  3806.                   irc-msg-info-pre
  3807.                   chan
  3808.                   orig
  3809.                   (irc-explain-user-mode mode)
  3810.                   irc-msg-info-post))
  3811.          ((irc-is-nickname orig)
  3812.           (irc-insert "%sUser %s changed mode for channel %s: %s%s"
  3813.                   irc-msg-info-pre
  3814.                   orig
  3815.                   chan
  3816.                   (irc-explain-channel-mode mode)
  3817.                   irc-msg-info-post))
  3818.          ((irc-is-hostname orig)
  3819.           (irc-remember orig 'irc-servernames))
  3820.          (t (irc-insert "%%Unknown sender in irc-parse-mode-reply:")
  3821.             (irc-insert "%% \"%s\" (str), \"%s\" (orig)." str orig)
  3822.             (irc-insert "%% Please tell %s, this might be a bug."
  3823.                 irc-hacker)))))
  3824.     (t (irc-insert "%%Unkown format on MODE reply; please tell %s:"
  3825.                irc-hacker)
  3826.        (irc-insert "%% \"%s\"." str)
  3827.        (irc-insert "%% Function irc-parse-mode-reply.")))
  3828.   nil)
  3829.  
  3830.  
  3831. (defun irc-parse-namreply (str)
  3832.   "Examine a NAMREPLY message from the IRC server.
  3833. NAMREPLY is used in repsonse to NAMES to indicate what users are on what
  3834. channels.  All users on secret or private channels which the client is not
  3835. on are grouped together on one private channel.
  3836.  
  3837. No signals are issued for NAMREPLYs."
  3838.   (if (not (string-match "^NAMREPLY +[^ ]+ +\\([^ ]+\\) +" str))
  3839.       (progn (irc-insert (concat "%%Unknown format on NAMREPLY message,"
  3840.                  " in function IRC-PARSE-NAMREPLY:"))
  3841.          (irc-insert "%% \"%s\"." str))
  3842.       (let* ((channel (substring str (match-beginning 1) (match-end 1)))
  3843.          (users (substring str (match-end 0)))
  3844.          (count 0)
  3845.          (to-insert "")
  3846.          (nick nil)
  3847.          (format-string "%s  %3d   %s")
  3848.          (irc-msg-cont-used irc-names-cont-msg))
  3849.     ;; yet another source of information for irc-nicknames.
  3850.     (while (string-match "^\\([^ ]+\\)\\( \\|$\\)" users)
  3851.       (setq nick (substring users 0 (match-end 1))
  3852.         users (substring users (match-end 0))
  3853.         count (1+ count)
  3854.         to-insert (concat to-insert " " nick))
  3855.       (irc-remember nick 'irc-nicknames)) 
  3856.     (if (and (irc-terminal-is-slow) (irc-server-has-end-of-names))
  3857.         (let ((lin (format format-string
  3858.                 (irc-format-channel channel)
  3859.                    count
  3860.                    (irc-clean-up-message to-insert))))
  3861.           (setq irc-reply-count (1+ irc-reply-count))
  3862.           (let ((diff (irc-time-diff (irc-current-time)
  3863.                      irc-reply-count-time)))
  3864.         (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since last
  3865.                (> (nth 0 diff) 0)) ; display?
  3866.                (setq irc-reply-count-time (irc-current-time))
  3867.                (message (format " %d channel%s ..."
  3868.                     irc-reply-count
  3869.                     (if (= 1 irc-reply-count) "" "s"))))))
  3870.           (irc-remember lin 'irc-namtree))
  3871.         (irc-insert format-string
  3872.             (irc-format-channel channel)
  3873.             count
  3874.             (irc-clean-up-message to-insert)))))
  3875.   nil)
  3876.  
  3877.  
  3878. (defun irc-parse-nick (str)
  3879.   "Examine a NICK message from the IRC server.
  3880. NICK is sent when a user's nickname is changed, but it is only sent to the
  3881. people on the same channel as the user.  If the person changing names is
  3882. being ignored, this fact is tracked across the change.  If notification
  3883. is not enabled for \"nick\" then no message is inserted.
  3884.  
  3885. This function returns t if a signal should be issued for the \"nick\" event,
  3886. nil otherwise."
  3887.   (cond ((string-match "^: *\\([^ :]+\\) +NICK +:?\\([^ :]+\\) *$" str)
  3888.      (let* ((old (subfield str 1))
  3889.         (new (subfield str 2))
  3890.         (current irc-nick-used))
  3891.        (if (not (irc-recall old 'irc-services)) ;Always keep /services.
  3892.            (irc-forget old 'irc-nicknames))
  3893.        (irc-remember new 'irc-nicknames)
  3894.        (cond ((string= (upcase irc-nick-used) (upcase old))
  3895.           ;; Our own nick has changed.
  3896.           (setq irc-nick-used new)
  3897.           (set-buffer-modified-p (buffer-modified-p))))
  3898.        (cond ((irc-recall old 'irc-ignored-ppl)
  3899.           (irc-forget old 'irc-ignored-ppl)
  3900.           (irc-remember new 'irc-ignored-ppl)
  3901.           nil)            ;Don't signal this.
  3902.          ((and (memq 'nick irc-events)
  3903.                (not (string= (upcase new) (upcase current))))
  3904.           (irc-insert "%s%s is now known as %s%s"
  3905.                   irc-msg-info-pre old new irc-msg-info-post)
  3906.           (irc-signal old 'user))
  3907.          (t nil))))
  3908.     (t (irc-insert "%%Unknown NICK seen in irc-parse-nick:")
  3909.        (irc-insert "%% \"%s\" (str)." str)
  3910.        (irc-insert "%% Please tell %s, this might be a bug." irc-hacker))))
  3911.  
  3912.  
  3913. ;irc-remember
  3914. (defun irc-parse-notice (str)
  3915.   "Examine a NOTICE message from the IRC server.
  3916. NOTICE is the catch-all for IRC messages; if it can't be classified as
  3917. one of the other currently existing messages then the information is
  3918. sent as NOTICE.  This message is overused, even when it another could be
  3919. used instead.  For example, if an attempt is made to send to a nickname
  3920. which is not on IRC the error reply is sent via NOTICE.
  3921.  
  3922. No signal is issued for NOTICE because it is way too random with what it
  3923. means."
  3924.   (let* ((lst (if (string-match (concat "^ *:? *\\([^: ]*\\)? *NOTICE *"
  3925.                     "\\([^: ]*\\)? *:")
  3926.                 str)
  3927.           (list (substring str (match-beginning 1) (match-end 1)) ;srvr
  3928.             (substring str (match-beginning 2) (match-end 2)) ;rcvr
  3929.             (substring str (match-end 0))) ;msg
  3930.           (list "" "" str)))
  3931.      (srvnam (if (string= (car lst) "") irc-server (car lst)))
  3932.      (srvr (if (string= (upcase srvnam) (upcase irc-server)) "" srvnam))
  3933.      (parorg (if (string= "" srvr) "" (concat "(" srvr ") ")))
  3934.      (rcvr (car (cdr lst)))
  3935.      (msg (car (cdr (cdr lst))))
  3936.      (cmsg (irc-clean-up-message msg))
  3937.      (retval nil))            ;Kludge!
  3938.     (if (not (stringp irc-server))
  3939.     (setq irc-server (if (stringp (default-value 'irc-server))
  3940.                  (default-value 'irc-server)
  3941.                  "")))
  3942.     (if (and rcvr (irc-is-nickname rcvr))
  3943.     (setq irc-nick-used rcvr))
  3944.     (irc-remember srvr 'irc-servernames)
  3945.     (cond
  3946.       ((and (string= "POXAV" (upcase srvr))
  3947.         (string-match "weenie" msg))
  3948.        )
  3949.       ((irc-recall srvr 'irc-services)
  3950.        (irc-remember srvr 'irc-services) ;Update spelling.
  3951.        (irc-remember srvr 'irc-nicknames)
  3952.        (irc-insert "%s%s%s %s"
  3953.            irc-msg-info-pre srvr irc-msg-info-post cmsg))
  3954.       ((string-match (concat "^\\*\\*\\* *Notice *-- *Access *denied *"
  3955.                  "(\\(.*\\)) *\\(.*\\) *$")
  3956.              msg)
  3957.        (let ((reason (subfield msg 1))
  3958.          (refused-server (subfield msg 2)))
  3959.      (irc-insert "%%Refused server-link connection from server %s: %s."
  3960.              (upcase refused-server)
  3961.              reason)))
  3962.       ((string-match (concat "^\\*\\*\\* *Notice *-- *Rehashing *Server"
  3963.                  " *config *file *(\\(.*\\)) *$")
  3964.              msg)
  3965.        (let ((file (subfield msg 1)))
  3966.      (irc-insert "%sServer %s has reloaded it's configuration file %s%s"
  3967.              irc-msg-info-pre
  3968.              (upcase srvnam)
  3969.              file
  3970.              irc-msg-info-post)))
  3971.       ((string-match (concat "^\\*\\*\\* *Notice *-- *\\(Hack\\|Fake\\) *:"
  3972.                  " *\\([^ ]+\\) +MODE +\\([^ ]+\\)"
  3973.                  " *\\([^ ]*\\).*$")
  3974.              msg)
  3975.        ;;Ignore this information. It's just a way for enabled operators on 2.7
  3976.        ;; server to see people on 2.6 server as they join channels with initial
  3977.        ;; modes, such as secret or private. Hopefulle this will go away when
  3978.        ;; 2.6 servers go way.
  3979.        (let ((user (subfield msg 2))
  3980.          (channel (subfield msg 3))
  3981.          (mode (irc-nuke-whitespace (subfield msg 4))))
  3982.      (cond ((string-match "\\+[^-]*[sp]" mode)
  3983.         (irc-insert (concat "%sWarning a user about seeing her/his"
  3984.                     " secret channel join%s")
  3985.                 irc-msg-info-pre irc-msg-info-post)
  3986.         (irc-send (concat "NOTICE " user " :<Automatic warning> My"
  3987.                   " client (but not I myself -- I don't even"
  3988.                   " know who you are unless you'll tell me or"
  3989.                   " you happen to be marked as being AWAY)"
  3990.                   " saw you join channel "
  3991.                   channel
  3992.                   " ("
  3993.                   mode
  3994.                   "). The fact was broadcasted to everyone"
  3995.                   " seeing WALLOPS messages on 2.7 (and later)"
  3996.                   " servers. Your channel is probably"
  3997.                   " without any special mode on other servers."
  3998.                   " (But still look \"valid\" at yous site)."
  3999.                   " If you have any questions, then don't send"
  4000.                   " them to "
  4001.                   irc-nick
  4002.                   " but to the channel #Twilight_Zone."
  4003.                   ))
  4004.         (irc-send (concat "NOTICE " user " :<Automatic warning> If"
  4005.                   " you don't care about getting warned, but"
  4006.                   " want to think you're invisible while being"
  4007.                   " visible, and you happen to use a Kiwi"
  4008.                   " client, you can do M-x set-variable RET"
  4009.                   " irc-ignore-automatic-warnings RET t"
  4010.                   " RET. If you're using ircII, instead do"
  4011.                   " /on ^notice \"" irc-nick " <Automatic"
  4012.                   " warning>*\: /^comment"))
  4013.         ))))
  4014.       ((string-match (concat "^\\*\\*\\* Message-of-today is missing"
  4015.                  " on host \\([^: ]+\\)? *$")
  4016.              msg)
  4017.        (let ((host (irc-clean-up-message (subfield msg 1))))
  4018.      (if (not (string= (upcase srvr) (upcase host)))
  4019.          (irc-remember host 'irc-servernames))
  4020.      (irc-insert "%%%sNo message of the day at server %s."
  4021.              (if (or (string= srvr irc-server)
  4022.                  (string= srvr ""))
  4023.              ""
  4024.              (concat "(" srvr ") "))
  4025.              (upcase host))))
  4026.       ((string-match "^MOTD *- ?*\\([^: ]+\\)? *message +of +the +day *-? *$"
  4027.              msg)
  4028.        (let ((server (irc-clean-up-message (substring msg
  4029.                               (match-beginning 1)
  4030.                               (match-end 1)))))
  4031.      (if (not (string= (upcase srvr) (upcase server)))
  4032.          (irc-remember server 'irc-servernames))
  4033.      (irc-insert "")
  4034.      (irc-insert ">>> Message of the day at server %s:" server)
  4035.      (set-buffer-modified-p (buffer-modified-p))))
  4036.       ((string-match "^MOTD *- ?" msg)
  4037.        (setq irc-motd-lines (append irc-motd-lines
  4038.                     (list (irc-clean-up-message
  4039.                        (substring msg (match-end 0)))))))
  4040.       ((string-match "^\\* *end +of +/?motd +command. *$" msg)
  4041.        (while irc-motd-lines
  4042.      (irc-insert ">>> %s" (car irc-motd-lines))
  4043.      (setq irc-motd-lines (cdr irc-motd-lines))))
  4044.       ((string-match (concat "^\\*\\*\\* *Error *: *No +mere +mortals +"
  4045.                  "may +trace +the +nets +of +the +universe *$")
  4046.              msg)
  4047.        (irc-insert (concat "%%%sYou must be an enabled IRC operator to trace"
  4048.                " the IRCnet, use /OPER to enable yourself. An"
  4049.                " alternative is to use /STATS L, do /HELP STATS.")
  4050.            parorg))
  4051.       ((string-match "^Good afternoon, gentleman\\. I am a HAL 9000" msg)
  4052.        (if (string= srvr "")
  4053.        (irc-insert "%sOperator status for %s ENABLED%s"
  4054.                irc-msg-info-pre
  4055.                irc-nick-used
  4056.                irc-msg-info-post)
  4057.        (irc-insert "%sOperator status at %s for %s ENABLED%s"
  4058.                irc-msg-info-pre
  4059.                srvr
  4060.                irc-nick-used
  4061.                irc-msg-info-post))
  4062.        ;; we've been granted operator privileges.  the string is for mode-line
  4063.        (setq irc-operator " IOPR")
  4064.        (set-buffer-modified-p (buffer-modified-p)))
  4065.       ((string-match (concat "^\\*\\*\\* *notice *-- *Received"
  4066.                  " +unauthorized +connection +from +")
  4067.              msg)
  4068.        (irc-insert (concat "%%Something at internet host %s tried to"
  4069.                " establish a connection with us. Refused"
  4070.                " as it isn't enabled in the confiugation file.")
  4071.            (irc-nuke-whitespace (substring msg (match-end 0)))))
  4072.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\) *Link"
  4073.                  " +with +\\([^ ]+\\) +established"
  4074.                  " *.? *$")
  4075.              msg)
  4076.        ;; In a few seconds, we ought to issue a LINKS command to the server,
  4077.        ;; but without displaying the answer, only storing it. Sigh.
  4078.        (let* ((h (irc-extract-hostname
  4079.           (irc-clean-up-message
  4080.            (subfield msg 2))))
  4081.           (host (if (stringp h) h "")))
  4082.      (if (not (string= (upcase srvr) (upcase host)))
  4083.          (irc-remember host 'irc-servernames))
  4084.      (irc-insert "%s%sLink with %s established%s"
  4085.              irc-msg-info-pre
  4086.              (if (string= srvr "") "" (concat "(" srvr ")"))
  4087.              (upcase host)
  4088.              irc-msg-info-post))
  4089.        (irc-later-execute-lusers))
  4090.       ((or (string-match (concat "^\\*\\*\\* *\\([^ ]+\\) +\\([^:]+\\) *"
  4091.                  "==> *\\(.+\\) *$")
  4092.              cmsg)
  4093.        ;; 2.6 following
  4094.        (string-match (concat "^\\*\\*\\* +\\(Connection\\) +\\([^ ]+\\) +"
  4095.                  "==> +\\([^ ]+\\) +\\[\\([^ ]+\\)\\] *$")
  4096.              cmsg)
  4097.        (string-match (concat "^\\*\\*\\* +\\(Connection\\) +\\([^ ]+\\) +"
  4098.                  "==> +\\([^ ]+\\) *$")
  4099.              cmsg)
  4100.        (string-match (concat "^\\*\\*\\* +\\(Link\\) +\\([^ ]+\\) +"
  4101.                  "==> +\\([^ ]+\\) *$")
  4102.              cmsg)
  4103.        (string-match (concat "^\\*\\*\\* +\\(<newtype>\\) +\\([^ ]+\\) +"
  4104.                  "==> +\\([^ ]+\\) *$")
  4105.              cmsg))
  4106.        (let* ((type (substring cmsg (match-beginning 1) (match-end 1)))
  4107.           (lcl (substring cmsg (match-beginning 2) (match-end 2)))
  4108.           (remote (substring cmsg (match-beginning 3) (match-end 3)))
  4109.           (address (if (match-beginning 4)
  4110.                (substring cmsg (match-beginning 4) (match-end 4))
  4111.                remote))
  4112.           (extra (cond
  4113.                ((not (string= (upcase remote) (upcase address)))
  4114.             (concat "(" address ")"))
  4115.                ((string-match
  4116.              "^\\([^ ]+\\) +\\([0-9]+\\)S +\\([0-9]+\\)C$"
  4117.              remote)
  4118.             (let ((x (subfield remote 1))
  4119.                   (s (string-to-int (subfield remote 2)))
  4120.                   (c (string-to-int (subfield remote 3))))
  4121.               (setq remote x)
  4122.               (format " (%d server%s, %d client%s)"
  4123.                   s
  4124.                   (if (= 1 s) "" "s")
  4125.                   c
  4126.                   (if (= 1 c) "" "s"))))
  4127.                (t "")))
  4128.           (p (cond
  4129.            ((string-match "^ *CLASS\\[\\([0-9]+\\)\\] +\\([^: ]+\\) *$"
  4130.                   lcl)
  4131.             (cons (subfield lcl 2) (subfield lcl 1)))
  4132.            ((string-match "^ *CLASS\\[\\([0-9]+\\)\\] *$" lcl)
  4133.             (cons srvr (subfield lcl 1)))
  4134.            (t (cons lcl nil))))
  4135.           (local (irc-nuke-whitespace (car p)))
  4136.           (class (cdr p))
  4137.           (lserv (irc-extract-hostname local))
  4138.           (rserv (irc-extract-hostname remote)))
  4139.      (if (and lserv (not (string= (upcase srvr) (upcase lserv))))
  4140.          (irc-remember lserv 'irc-servernames))
  4141.      (if (and rserv (not (string= (upcase srvr) (upcase rserv))))
  4142.          (irc-remember remote 'irc-servernames))
  4143.      (cond
  4144.        ((string= (upcase type) "LINK")
  4145.         (irc-insert "%s%s to %s%s goes through %s%s"
  4146.             irc-msg-info-pre
  4147.             type
  4148.             (upcase remote)
  4149.             extra
  4150.             (upcase local)
  4151.             irc-msg-info-post))
  4152.        ((and (string-match "\\(CHANOP\\|OPER\\|USER\\)" (upcase type))
  4153.          (numberp (string-match "^\\([^[]*\\)\\[\\([^: ]+\\)\\]$"
  4154.                     remote)))
  4155.         (let ((user (subfield remote 1))
  4156.           (cm (subfield remote 2)))
  4157.           (irc-remember user 'irc-nicknames)
  4158.           (if (stringp class)
  4159.           (irc-insert
  4160.            "%s%s of class %3s at server %s: \"%s\" (client on %s)%s"
  4161.            irc-msg-info-pre
  4162.            type
  4163.            class
  4164.            (upcase local)
  4165.            user
  4166.            (upcase cm)
  4167.            irc-msg-info-post)
  4168.           (irc-insert "%s%s at server %s: \"%s\" (client on %s)%s"
  4169.                   irc-msg-info-pre
  4170.                   type
  4171.                   (upcase local)
  4172.                   user
  4173.                   (upcase cm)
  4174.                   irc-msg-info-post))))
  4175.        ((and (string-match "\\(UNKNOWN\\)" (upcase type))
  4176.          (numberp (string-match "^\\([^[]*\\)\\[\\([^: ]+\\)\\]$"
  4177.                     remote)))
  4178.         (let ((cm (substring remote
  4179.                  (match-beginning 2)
  4180.                  (match-end 2))))
  4181.           (irc-insert (concat "%s%s at server %s from internet"
  4182.                   " host %s%s")
  4183.               irc-msg-info-pre
  4184.               (cond ((string= "UNKNOWN" (upcase type))
  4185.                  "Half open connection")
  4186.                 (t (concat "<Unknown type (%s) in function"
  4187.                        " irc-parse-notice, please"
  4188.                        " tell "
  4189.                        irc-hacker
  4190.                        ">")))
  4191.               (upcase local)
  4192.               (upcase cm)
  4193.               irc-msg-info-post)))
  4194.        (t (irc-insert "%s%s at server %s to%s server %s%s%s"
  4195.               irc-msg-info-pre
  4196.               (cond ((string= (upcase type) "CONNECTION")
  4197.                  "Serverlink")
  4198.                 ((string= (upcase type) "CONNECTING")
  4199.                  "Server-search")
  4200.                 (t type))
  4201.               (upcase local)
  4202.               (if (stringp class)
  4203.                   (format " class %3s" class)
  4204.                   "")
  4205.               (upcase remote)
  4206.               (downcase extra)
  4207.               irc-msg-info-post)))))
  4208.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\)"
  4209.                  " *No +response +from +"
  4210.                  "\\([^ ]+\\) *, *closing +link *$")
  4211.              cmsg)
  4212.        (irc-insert "%%Closed serverlink to %s due to lack of respone."
  4213.            (substring cmsg (match-beginning 2) (match-end 2)))
  4214.        (irc-later-execute-lusers))
  4215.       ((string-match (concat "^\\*\\*\\* *Class +\\([0-9]+\\) *"
  4216.                  "Entries *linked *: *\\([0-9]+\\) *$")
  4217.              cmsg)
  4218.        (let ((class (string-to-int (subfield cmsg 1)))
  4219.          (count (string-to-int (subfield cmsg 2))))
  4220.      (irc-insert "%s%s%d service%s linked for class %3d%s"
  4221.              irc-msg-info-pre
  4222.              parorg
  4223.              count
  4224.              (if (= 1 count) "" "s")
  4225.              class
  4226.              irc-msg-info-post)))
  4227.       ((string-match (concat "^\\([A-Za-z]+\\) +has +been +used +"
  4228.                  "\\([0-9]+\\) +times? +after +"
  4229.                  "startup *$")
  4230.              cmsg)
  4231.        (let ((cmd (substring cmsg (match-beginning 1) (match-end 1)))
  4232.          (cnt (substring cmsg (match-beginning 2) (match-end 2))))
  4233.      (irc-insert "%sServer %s has seen %s%s command%s of type %s%s"
  4234.              irc-msg-info-pre
  4235.              (upcase (if (string= srvr "") irc-server srvr))
  4236.              (make-string (max 0 (- 5 (length cnt))) ? )
  4237.              cnt
  4238.              (if (string= cnt "1") " " "s")
  4239.              cmd
  4240.              irc-msg-info-post)))
  4241.       ((string-match "^\\*\\*\\* *No +such +server *" cmsg)
  4242.        (let ((unknown (substring cmsg (match-end 0))))
  4243.      (irc-forget unknown 'irc-servernames)
  4244.      (irc-insert "%%%sNo such server: \"%s\"."
  4245.              (if (string= "" srvr)
  4246.              ""
  4247.              (concat "(" srvr ")"))
  4248.              unknown)))
  4249.       ((string-match (concat "^\\*\\*\\* *unknown \\([^: ]+\\) *==> *"
  4250.                  "\\([^: ]+\\) *$")
  4251.              cmsg)
  4252.        (irc-insert "%sUnknown connection at server %s to host %s%s"
  4253.            irc-msg-info-pre
  4254.            (upcase (substring cmsg (match-beginning 1) (match-end 1)))
  4255.            (upcase (substring cmsg (match-beginning 2) (match-end 2)))
  4256.            irc-msg-info-post))
  4257.       ((string-match (concat "^\\*\\*\\* *\\(User\\)?\\(ChanOp\\)?"
  4258.                  "\\(Oper\\)? +\\([^: ]+\\) *==> *"
  4259.                  "\\([^: ]*\\) *\\[\\(.\\|\n\\)*\\] *$")
  4260.              cmsg)
  4261.        (let* ((first (substring cmsg
  4262.                 (or (match-beginning 1) 0)
  4263.                 (or (match-end 1) 0)))
  4264.           (second (substring cmsg
  4265.                  (or (match-beginning 2) 0)
  4266.                  (or (match-end 2) 0)))
  4267.           (third (substring cmsg
  4268.                 (or (match-beginning 3) 0)
  4269.                 (or (match-end 3) 0)))
  4270.           (srvr (substring cmsg (match-beginning 4) (match-end 4)))
  4271.           (nick (substring cmsg (match-beginning 5) (match-end 5)))
  4272.           (client (substring cmsg (match-beginning 6) (match-end 6)))
  4273.           (type (cond ((not (string= "" first)) "User")
  4274.               ((not (string= "" second)) "Channel operator")
  4275.               ((not (string= "" third)) "IRC operator")
  4276.               (t "?UNKNOWN?"))))
  4277.      (irc-remember nick 'irc-nicknames)
  4278.      (irc-insert "%s%s at server %s: \"%s\" (client on %s)%s"
  4279.              irc-msg-info-pre
  4280.              type
  4281.              (upcase srvr)
  4282.              nick
  4283.              (upcase client)
  4284.              irc-msg-info-post)))
  4285.       ((string-match (concat "^\\(\\*\\*\\*\\)? *\\([0-9]+\\) +users* +"
  4286.                  "\\(have\\|has\\) +connection +to +the +"
  4287.                  "twilight +zone *$")
  4288.              cmsg)
  4289.        (let ((n (string-to-int (subfield cmsg 2))))
  4290.      (irc-insert "*** There %s %d enabled operator%s online."
  4291.              (if (= 1 n) "is" "are")
  4292.              n
  4293.              (if (= 1 n) "" "s"))))
  4294.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There \\(is\\|are\\) +"
  4295.                   "+\\([0-9]+\\) +channels*. *$")
  4296.               cmsg)
  4297.         (let ((n (string-to-int (subfield cmsg 3))))
  4298.       (irc-insert "*** There %s %d channel%s."
  4299.               (if (= 1 n) "is" "are")
  4300.               n
  4301.               (if (= 1 n) "" "s"))))
  4302.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There \\(is\\|are\\) +"
  4303.                   "+\\([0-9]+\\) +clients* +connected +"
  4304.                   "to +\\([^ ,]+\\).*$")
  4305.               cmsg)
  4306.         (let ((n (string-to-int (subfield cmsg 3)))
  4307.           (s (subfield cmsg 4)))
  4308.       (irc-insert "*** There %s %d client%s on %s."
  4309.               (if (= 1 n) "is" "are")
  4310.               n
  4311.               (if (= 1 n) "" "s")
  4312.               s)))
  4313.       ((string-match "^###" cmsg)
  4314.        (let ((m (substring cmsg (match-end 0))))
  4315.      (irc-insert "###%s%s"
  4316.              (if (or (string= "" srvr)
  4317.                  (string= (upcase srvr) (upcase irc-server)))
  4318.              ""
  4319.              (concat "(" srvr ")"))
  4320.              m)))
  4321.       ((string-match (concat "^\\*\\*\\* *welcome +to +the +internet +"
  4322.                  "relay +network *, *\\([^: ]+\\) *$")
  4323.              cmsg)        ;v2.4 welcome message
  4324.        (let ((user (subfield cmsg 1)))
  4325.      (irc-remember user 'irc-nicknames)))
  4326.       ((string-match (concat "^\\*\\*\\* *Your +host +is +"
  4327.                  "\\([^ ,]+\\) *, *running +version +"
  4328.                  "\\([^: ]+\\) *$")
  4329.              cmsg)
  4330.        (let* ((s (subfield cmsg 1))
  4331.           (vrsn (subfield cmsg 2))
  4332.           (s (downcase (irc-extract-hostname s))) ;REAL GENERIC servername
  4333.           (cur-bufname (buffer-name (current-buffer)))
  4334.           (new-bufname (irc-host+port-to-buffer-name s irc-port))
  4335.           (pre-kludge nil))
  4336.      (setq-default irc-server s)
  4337.      (setq irc-server s)
  4338.      (if (string< cur-bufname new-bufname)
  4339.          (rename-buffer new-bufname))
  4340.      (if (not (string= (upcase srvr) (upcase s)))
  4341.          (irc-remember s 'irc-servernames))
  4342.      (if (or (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4343.                        "[^0-9]+\\([0-9]+\\)\\([^0-9]+\\)"
  4344.                        "\\([0-9]+\\)")
  4345.                    vrsn)
  4346.          (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4347.                        "[^0-9]+\\([0-9]+\\)\\(\\)")
  4348.                    vrsn)
  4349.          (string-match (concat "^\\([Ii][Rr][Cc][Dd]?\\)?\\([u0-9]+\\)"
  4350.                        "\\(\\)\\(\\)")
  4351.                    vrsn))
  4352.          (let* ((type nil)
  4353.             (major (subfield vrsn 2))
  4354.             (minor (subfield vrsn 3))
  4355.             (kludge (subfield vrsn 4))
  4356.             (edit (subfield vrsn 5))
  4357.             (minor (if (string= "" minor) 0 (string-to-int minor)))
  4358.             (edit (if (string= "" edit) 0 (string-to-int edit))))
  4359.            (if (string-match "^u" major)
  4360.            (setq type (format "%c" (aref major 0))
  4361.              major (substring major 1)))
  4362.            (setq irc-type-version type
  4363.              irc-major-version (string-to-int major)
  4364.              irc-minor-version minor
  4365.              pre-kludge kludge
  4366.              irc-edit-version edit)
  4367.            )
  4368.          (irc-insert "%%Failed parsing vrsn \"%s\" in irc-parse-notice."
  4369.              vrsn))
  4370.      (if (and (= irc-major-version 2)
  4371.           (= irc-minor-version 6)
  4372.           (not (string= (upcase pre-kludge) "PRE")))
  4373.          (setq irc-edit-version (+ 10000 irc-edit-version)))
  4374.      (irc-insert "")
  4375.      (irc-insert "*** Welcome to the IRC server at %s!" s)
  4376.      (irc-insert "*** The server's version is %s," vrsn)))
  4377.       ((string-match "^\\*\\*\\* *This +server +was +created +"
  4378.              cmsg)
  4379.        (irc-insert "*** and it was created %s."
  4380.            (substring cmsg (match-end 0))))
  4381.       ;; Hello message from a 2.2 server.
  4382.       ((string-match (concat "^\\*\\*\\* *Welcome +to +Internet +Relay +"
  4383.                  "Server *")
  4384.              cmsg)
  4385.        (let ((vrsn (irc-nuke-whitespace (substring cmsg (match-end 0)))))
  4386.      (if (string-match (concat "^[^0-9]*\\([0-9]+\\)\\.\\([0-9]+\\)"
  4387.                    "[^0-9]+\\([0-9]+\\)?.*$")
  4388.                vrsn)
  4389.          (let ((maj (substring vrsn (match-beginning 1) (match-end 1)))
  4390.            (min (substring vrsn (match-beginning 2) (match-end 2)))
  4391.            (edt (substring vrsn (match-beginning 3) (match-end 3))))
  4392.            (setq irc-major-version (string-to-int maj)
  4393.              irc-minor-version (string-to-int min)
  4394.              irc-edit-version (string-to-int edt))))
  4395.      (irc-send "MOTD")
  4396.      (irc-insert (concat "*** Welcome to the Internet Relay Chat server "
  4397.                  "version %s at %s!")
  4398.              vrsn
  4399.              irc-server)
  4400.      (set-buffer-modified-p (buffer-modified-p))))
  4401.        ((string-match (concat "^\\(\\*\\*\\*\\)? *There +are +\\([0-9]+\\) +"
  4402.                  "users +\\(and +\\|(\\)?"
  4403.                  "\\([^0-9]*[0-9]+ invisible\\)?\\()\\)? *"
  4404.                  "on +\\([0-9]+\\) +servers *$")
  4405.              cmsg)
  4406.        (let* ((ucount (subfield cmsg 2))
  4407.           (sdelim (subfield cmsg 3))
  4408.           (invstr (subfield cmsg 4))
  4409.           (edelim (subfield cmsg 5))
  4410.           (scount (subfield cmsg 6))
  4411.           (inv (if (string= "" invstr)
  4412.                ""
  4413.                (concat " "  sdelim invstr edelim)))
  4414.           (n (string-to-int ucount)))
  4415.      (irc-insert "*** There %s %s user%s%s on %s server%s."
  4416.              (if (= n 1) "is" "are")
  4417.              ucount
  4418.              (if (= n 1) "" "s")
  4419.              inv
  4420.              scount
  4421.              (if (= (string-to-int scount) 1) "" "s"))))
  4422.       ((string-match (concat "^\\(\\*\\*\\*\\)? *There +are \\([0-9]+\\) +"
  4423.                  "yet +unknown +connections *$")
  4424.              cmsg)
  4425.        (let ((count (substring cmsg (match-beginning 2) (match-end 2))))
  4426.      (irc-insert "*** There %s yet %s unknown connection%s."
  4427.              (if (string= count "1") "is" "are")
  4428.              count
  4429.              (if (string= count "1") "" "s"))))
  4430.       ((string-match (concat "^\\(\\*\\*\\*\\)? *I +have +\\([0-9]+\\)"
  4431.                  " +clients +and \\([0-9]+\\) +servers *$")
  4432.              cmsg)
  4433.        (let* ((c (subfield cmsg 2))
  4434.           (s (subfield cmsg 3))
  4435.           (cn (string-to-int c))
  4436.           (sn (string-to-int s))
  4437.           (isare (if (= 1 cn) "is" "are"))
  4438.           (cstr (if (= 1 cn) "client" "clients"))
  4439.           (sstr (if (= 1 sn) "server" "servers")))
  4440.      (irc-insert "*** There %s %d %s and %d %s on this server."
  4441.              isare cn cstr sn sstr)))
  4442.       ((string-match (concat "^\\*\\*\\* +Notice *:?-?-? +Received +KILL"
  4443.                  " +message +for +\\([^ ]+\\).\\( +From [^ ]+\\)?"
  4444.                  " +Path: *")
  4445.              cmsg)
  4446.        (let* ((sender (substring cmsg (match-beginning 1) (match-end 1)))
  4447.           (f (subfield cmsg 2))
  4448.           (path (substring cmsg (match-end 0)))
  4449.           (from (cond ((string-match "^From " f)
  4450.                (substring cmsg (match-end 0)))
  4451.               ((irc-is-hostname f) f)
  4452.               (t ""))))
  4453.      (cond ((string-match "\\([^!]+\\)!?(\\([^ ]*\\) *<- *\\([^ ]*\\)) *$"
  4454.                   path)
  4455.         (let* ((at (subfield path 1))
  4456.                (old (subfield path 2))
  4457.                (new (subfield path 3))
  4458.                (local (irc-is-nickname old))
  4459.                (irc-msg-cont-used (make-string
  4460.                        (length (concat irc-msg-info-pre
  4461.                                "User "))
  4462.                        ? )))
  4463.           (irc-insert
  4464.            (concat "%s%s COLLIDED at %s, "
  4465.                (if local
  4466.                    "local user %s seen on link from %s%s"
  4467.                    "was on %s, now from %s%s"))
  4468.            irc-msg-info-pre
  4469.            sender
  4470.            (upcase (irc-nuke-whitespace at))
  4471.            (upcase (irc-nuke-whitespace old))
  4472.            (upcase (irc-nuke-whitespace new))
  4473.            irc-msg-info-post)))
  4474.            ((or (string-match "\\([^!]+\\)!\\([^=][^! ]*\\) +(\\(.*\\))$"
  4475.                   path)
  4476.             (string-match "\\([^!]+\\)!\\([^=][^! ]*\\) *\\(\\)$"
  4477.                   path))
  4478.         (let* ((s (subfield path 1))
  4479.                (o (subfield path 2))
  4480.                (m (subfield path 3))
  4481.                (site (irc-nuke-whitespace s))
  4482.                (oper (irc-nuke-whitespace o))
  4483.                (type (if (string-match "\\." oper)
  4484.                  "Server"
  4485.                  "Operator"))
  4486.                (m2 (irc-nuke-whitespace m))
  4487.                (mesg (if (string= "" m2) "" (concat " (" m2 ")"))))
  4488.           (if (string-match "\\." oper)
  4489.               (irc-remember oper 'irc-servernames)
  4490.               (irc-remember oper 'irc-nicknames))
  4491.           (irc-insert "%sOperator %s (@%s) /KILL'ed user %s%s%s"
  4492.                   irc-msg-info-pre
  4493.                   oper
  4494.                   site
  4495.                   sender
  4496.                   mesg
  4497.                   irc-msg-info-post))
  4498.         (irc-send (concat "WHOWAS :" sender)))
  4499.            (t (irc-insert "%sUser %s KILL'ed, path: %s%s"
  4500.                   irc-msg-info-pre
  4501.                   sender
  4502.                   path
  4503.                   irc-msg-info-post)))))
  4504.       ((or (string-match "^ *You +have +been +marked +as +being +away *$" cmsg)
  4505.        (string-match "^ *You +have +marked +as +being +away *$" cmsg))
  4506.        (if (string= srvr "")
  4507.        (irc-insert (concat "%sYou have been marked as being away,"
  4508.                    " use /HERE to revert the effect%s")
  4509.                irc-msg-info-pre
  4510.                irc-msg-info-post)))
  4511.       ((string-match "^ *You +are +no +longer +marked +as +being +away *$"
  4512.              cmsg)
  4513.        (if (string= srvr "")        ;Only display if from local server.
  4514.        (irc-insert "%sYou are no longer marked as being away%s"
  4515.                irc-msg-info-pre
  4516.                irc-msg-info-post)))
  4517.       ((string-match (concat "^ *\\([^: *]*\\) *"
  4518.                  "\\(tty[^: ]+"
  4519.                  "\\|pty/tty[^: ]+"
  4520.                  "\\|vt[0-9]+"
  4521.                  "\\|pt[^: ]+"
  4522.                  "\\|display"
  4523.                  "\\|console\\) *"
  4524.                  "\\([ -~]+\\)?.*$")
  4525.              cmsg)
  4526.        (let ((user (substring cmsg (match-beginning 1) (match-end 1)))
  4527.          (tty (substring cmsg (match-beginning 2) (match-end 2)))
  4528.          (remote (substring cmsg (match-beginning 3) (match-end 3))))
  4529.      (irc-insert "%s%s %s%s %s"
  4530.              user
  4531.              (make-string (max 0 (- 39 (length user))) ? )
  4532.              tty
  4533.              (make-string (max 0 (- 14 (length tty))) ? )
  4534.              remote)))
  4535.       ((string-match " *Nobody +logged +in +on +\\([^: ]+\\) *$" cmsg)
  4536.        (let* ((s (subfield cmsg 1))
  4537.           (server (irc-extract-hostname s)))
  4538.      (if (and (stringp server)
  4539.           (not (string= (upcase srvr) (upcase server))))
  4540.          (irc-remember server 'irc-servernames))
  4541.      (irc-insert (concat "%%No users logged in on the Internet node"
  4542.                  " which runs the IRC server %s at the moment.")
  4543.              server)))
  4544.       ((string-match "^ *\\(UserId +Terminal +Host\\) *$" cmsg)
  4545.        (let ((m (substring cmsg (match-beginning 1) (match-end 1))))
  4546.      (irc-insert (concat "Login name                              "
  4547.                  "TTY            Logged in from"))
  4548.      (irc-insert (concat "--------------------------------------- "
  4549.                  "-------------- --------------"))))
  4550.       ((string-match (concat "^\\*\\*\\* *\\(Notice\\)? *\\(:\\|--\\)?"
  4551.                  " *Connecti\\(ng\\|on\\) *to"
  4552.                  " +\\(.+\\) +activated.? *$")
  4553.              cmsg)
  4554.        (irc-insert "%s%sTrying to establish a serverlink to %s%s"
  4555.            irc-msg-info-pre
  4556.            parorg
  4557.            (upcase (substring cmsg (match-beginning 4) (match-end 4)))
  4558.            irc-msg-info-post))
  4559.       ((string-match (concat "^\\*\\*\\* *Notice *\\(:\\|--\\)"
  4560.                  " *Failed *in *connecting *to"
  4561.                  " *\\([^: ]+\\) *: *Socket *is"
  4562.                  " *not *connected *.? *$")
  4563.              cmsg)
  4564.        (irc-insert (concat "%%%sFailed to establish a serverlink to %s;"
  4565.                " no active server at other end.")
  4566.            parorg
  4567.            (upcase
  4568.             (substring cmsg (match-beginning 2) (match-end 2)))))
  4569.       ((string-match (concat "^\\*\\*\\* *Notice *: *Connect +"
  4570.                  "to +host +\\(.\\|\n\\)* +failed *:")
  4571.              cmsg)
  4572.        (let* ((host (substring cmsg (match-beginning 1) (match-end 1)))
  4573.           (reason (substring cmsg (match-end 0)))
  4574.           (server (upcase (irc-extract-hostname host))))
  4575.      (irc-forget server 'irc-servernames) ;Just in case.
  4576.      (irc-insert "%%Failed to establish a serverlink to %s; %s."
  4577.              (upcase server)
  4578.              reason)))
  4579.       ((string-match (concat "^\\*\\*\\* Notice: Access denied (no such server"
  4580.                  " enabled) \\([^ ]+\\) *\\(\\[[^ ]+\\]\\)? *$")
  4581.              cmsg)
  4582.        (let ((claimed (substring cmsg (match-beginning 1) (match-end 1)))
  4583.          (truename (substring cmsg
  4584.                   (1+ (or (match-beginning 2) -1))
  4585.                   (1- (or (match-end 2) 1)))))
  4586.      (irc-insert (concat "%%Rejected attemp by internethost \"%s\"%s to"
  4587.                  " establish a serverlink; that host isn't enabled"
  4588.                  " in the configuration file.")
  4589.              (if (string= "" truename) claimed truename)
  4590.              (if (or (string= "" truename)
  4591.                  (string= (upcase claimed) (upcase truename)))
  4592.              ""
  4593.              (concat " (claiming to be \"" claimed "\")")))))
  4594.       ((string-match (concat "^ *\\*\\*\\* +Notice *: +No +"
  4595.                  "response +from +\\([^: ]+\\) +, +"
  4596.                  "closing +link *$")
  4597.              cmsg)
  4598.        (let ((removed-server (substring cmsg
  4599.                     (match-beginning 1)
  4600.                     (match-end 1))))
  4601.      (irc-forget removed-server 'irc-servernames)
  4602.      (irc-insert (concat "%%Failed to get any response whatsoever from"
  4603.                  " server %s, removing the serverlink to it.")
  4604.              removed-server))
  4605.        (irc-later-execute-lusers))
  4606.       ((or (string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4607.                  " *Max +buffering +limit +exceed"
  4608.                  " +for +\\([^ ]+\\)")
  4609.              cmsg)
  4610.        (string-match (concat "^ *\\*\\*\\* *Notice\\ *\\(:\\|--\\)"
  4611.                  " *SendQueued +called +for +a"
  4612.                  " +DEADSOCKET +\\([^: ]*\\) *"
  4613.                  "\\(:-(\\)? *$")
  4614.              cmsg))
  4615.        (let ((host (irc-extract-hostname (substring cmsg
  4616.                             (match-beginning 2)
  4617.                             (match-end 2)))))
  4618.      (irc-forget host 'irc-servernames)
  4619.      (irc-insert (concat "%%Closed serverlink to %s, max buffering limit"
  4620.                  " got exceeded.")
  4621.              (upcase host)))
  4622.        (irc-later-execute-lusers))
  4623.       ((string-match (concat "^ *\\*\\*\\* *Host +\\(.*\\) +is"
  4624.                  " +unknown *\\.* *$")
  4625.              cmsg)
  4626.        (irc-insert "%%Host \"%s\" is unknown."
  4627.            (upcase
  4628.             (substring cmsg (match-beginning 1) (match-end 1)))))
  4629.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *Connect +to +host"
  4630.                  " +\\(.+\\) +failed *: *\\(.+\\) *$")
  4631.              cmsg)
  4632.        (let ((h (subfield cmsg 1))
  4633.          (reason (subfield cmsg 2)))
  4634.      (irc-insert "%%Connect to host %s failed: %s" (upcase h) reason)))
  4635.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR +"
  4636.                  "from +\\(.*\\) *: *SUMMON +No +"
  4637.                  "such +host *( *\\(.\\|\n\\)* *) *found"
  4638.                  " *$")
  4639.              cmsg)
  4640.        (let* ((fld1 (subfield cmsg 1))
  4641.           (fld2 (subfield cmsg 2))
  4642.           (at-server (irc-extract-hostname fld1))
  4643.           (unknown-host (irc-extract-hostname fld2)))
  4644.      (if (and (string< "" at-server)
  4645.           (not (string= (upcase srvr) (upcase at-server))))
  4646.          (irc-remember at-server 'irc-servernames))
  4647.      (irc-insert (concat "%%Summon command failed as server %s doesn't"
  4648.                  " know of any Internet host called \"%s\".")
  4649.              (upcase fld1)
  4650.              fld2)))
  4651.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR"
  4652.                  " +from\\ +\\(.*\\) *: *Access +"
  4653.                  "denied *( *no +such +server +"
  4654.                  "enabled *) *")
  4655.              cmsg)
  4656.        (let ((complainer (subfield cmsg 1))
  4657.          (disabled (substring cmsg (match-end 0))))
  4658.      (if (and (irc-is-hostname complainer)
  4659.           (not (string= (upcase srvr) (upcase complainer))))
  4660.          (irc-remember complainer 'irc-servernames))
  4661.      (irc-insert (concat "%%Server %s refuses to accept serverlink from"
  4662.                  " host %s as that host isn't enabled in the"
  4663.                  " configuration. Use \"/STATS C %s\" to check"
  4664.                  " which hosts ARE enabled.")
  4665.              complainer
  4666.              disabled)))
  4667.       ((string-match (concat "^ *\\([^: ]+\\) +seems +to +have +"
  4668.                  "disabled +summoning")
  4669.              cmsg)
  4670.        (irc-insert "%%User %s@%s has disabled summoning."
  4671.            (substring cmsg (match-beginning 1) (match-end 1))
  4672.            srvnam))
  4673.       ((string-match (concat "^ *Summoning +user *\\([^: ]*\\) +"
  4674.                  "to +irc *$")
  4675.              cmsg)
  4676.        (irc-insert "%sSummoning user %s@%s to IRC%s"
  4677.            irc-msg-info-pre
  4678.            (substring cmsg (match-beginning 1) (match-end 1))
  4679.            srvnam
  4680.            irc-msg-info-post))
  4681.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4682.                  " *Link +\\(.*\\) +cancelled *,"
  4683.                  " *server +\\(.*\\) +already"
  4684.                  " +exists *$")
  4685.              cmsg)
  4686.        (let ((rhost (substring cmsg (match-beginning 2) (match-end 2)))
  4687.          (rsrvr (substring cmsg (match-beginning 3) (match-end 3))))
  4688.      (irc-insert (concat "%%Server %s %s tried to establish a serverlink"
  4689.                  " to us (%s). Refused as we already are linked.")
  4690.              rsrvr rhost irc-server)))
  4691.       ((string-match (concat "^ *Connect *: *Server +\\([^ ]+\\) +already"
  4692.                  " +exists +from +\\([^ ]+\\) *$")
  4693.              cmsg)
  4694.        (let ((other-side (subfield cmsg 1))
  4695.          (trying-side (subfield cmsg 2)))
  4696.      (irc-remember other-side 'irc-servernames)
  4697.      (irc-remember trying-side 'irc-servernames)
  4698.      (irc-insert "%%Server %s is already connected to %s"
  4699.              (upcase other-side)
  4700.              (upcase trying-side))))
  4701.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4702.                  " *ERROR +from +\\(.*\\) *:"
  4703.                  " *Server +\\(.*\\) +already +exists"
  4704.                  " *\\.?\\.?\\.? *$")
  4705.              cmsg)
  4706.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2)))
  4707.          (local (substring cmsg (match-beginning 3) (match-end 3))))
  4708.      (if (not (string= (upcase srvr) (upcase remote)))
  4709.          (irc-remember remote 'irc-servernames))
  4710.      (irc-insert (concat "%%Server %s refused to accept a serverlink from"
  4711.                  " %s, the servers are already connected.")
  4712.              (upcase remote)
  4713.              (if (string= (upcase local) (upcase irc-server))
  4714.              (concat "this server (" local ")")
  4715.              (concat "other server " local))))) 
  4716.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4717.                  " *Server +\\([^: ]+\\) +closed +the"
  4718.                  " +connection *.? *$")
  4719.              cmsg)
  4720.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2))))
  4721.      (irc-forget remote 'irc-servernames)
  4722.      (irc-insert "%%%sServerlink from %s closed by remote side."
  4723.              parorg
  4724.              (upcase remote))))
  4725.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4726.                  " *Access +denied *( *no +such"
  4727.                  " +server +enabled *) *")
  4728.              cmsg)
  4729.        (let* ((remote (substring cmsg (match-end 0)))
  4730.           (s (irc-extract-hostname remote))
  4731.           (server (if (stringp s) s ""))
  4732.           (rest (substring remote (length server)))
  4733.           (h (irc-nuke-whitespace rest))
  4734.           (host (upcase (if (string= "" h) server h))))
  4735.      (irc-insert (concat "%%Server %s (on host %s) tried to set up a"
  4736.                  " server-link to us (%s) but we refused as there"
  4737.                  " is no N line accepting that host/server"
  4738.                  " combination.")
  4739.              server host irc-server)))
  4740.       ((string-match (concat "^ *\\*\\*\\* *Notice *\\(:\\|--\\)"
  4741.                  " *Lost +server +connection +to"
  4742.                  " +\\(.*\\) *:")
  4743.              cmsg)
  4744.        (let ((remote (substring cmsg (match-beginning 2) (match-end 2)))
  4745.          (reason (substring cmsg (match-end 0))))
  4746.      (irc-forget remote 'irc-servernames)
  4747.      (irc-insert "%%Lost serverlink to %s (%s)." (upcase remote) reason)
  4748.      (irc-later-execute-lusers)))
  4749.       ((string-match (concat "^ *Connect *: *Host +\\(.\\|\n\\)*"
  4750.                  " +not +listed +in +ircd?.conf *$")
  4751.              cmsg)
  4752.        (let ((host (substring cmsg (match-beginning 1) (match-end 1))))
  4753.      (irc-insert (concat "%%There is no host matching the description"
  4754.                  " \"%s\" in the servers (%s) configuration"
  4755.                  " file.")
  4756.              host irc-server)))
  4757.       ((string-match "^ *\\(.\\|\n\\)* *: *Privileged +command *$"
  4758.              cmsg)
  4759.        (irc-insert (concat "%%You must be an ENABLED IRC operator to use"
  4760.                " command \"%s\". Use /OPER to enable yourself.")
  4761.            (upcase (subfield cmsg 1))))
  4762.       ((string-match (concat "^ *\\*\\*\\* *Notice *-- *ERROR +"
  4763.                  "from +\\(.*\\) *: *SUMMON +No +"
  4764.                  "such +host *( *\\(.*\\) *) *found"
  4765.                  " *$")
  4766.              cmsg)
  4767.        (let ((complainer (subfield cmsg 1))
  4768.          (nonfound (subfield cmsg 2)))
  4769.      (if (not (string= (upcase srvr) (upcase complainer)))
  4770.          (irc-remember complainer 'irc-servernames))
  4771.      (irc-insert (concat "%%Command /SUMMON found as server \"%s\" doesn't"
  4772.                  " know about any server \"%s\".")
  4773.              complainer nonfound)))
  4774.       ((and (irc-is-hostname srvr)
  4775.         (string-match (concat "^ *User +\\(.\\|\n\\)* +not +logged"
  4776.                   " +in *$")
  4777.               cmsg))
  4778.        (irc-insert (concat "%%Command /SUMMON failed as no user called \"%s\""
  4779.                " is logged in at %s at the moment.")
  4780.            (subfield cmsg 1) (upcase srvr)))
  4781.       ((or (string-match "^\\*\\*\\* *Notice *:?-* *\\([^ ]*\\) *$" cmsg)
  4782.        (string-match "^\\*\\*\\* *\\([^ ]*\\) *$" cmsg)
  4783.        (string-match "^ *Notice *:?-* *\\([^ ]+\\) *$" cmsg)
  4784.        (string-match "^ *\\([CNIYQK] *:.*\\) *$" cmsg) ;/STATS C
  4785.        (string-match "^ *\\*\\*\\* *\\(.*\\) *$" cmsg))
  4786.        (let* ((b (or (match-beginning 1) 0))
  4787.           (e (or (match-end 1) b))
  4788.           (m (substring cmsg b e)))
  4789.      (irc-insert "%s%s%s%s%s%s"
  4790.              irc-msg-info-pre
  4791.              (if (or (string= rcvr "")
  4792.                  (string= (upcase rcvr) (upcase irc-nick-used)))
  4793.              ""
  4794.              (concat
  4795.               "To "
  4796.               (cond ((irc-is-nickname rcvr) "user ")
  4797.                 ((irc-is-channelname rcvr) "channel ")
  4798.                 ((irc-is-broadcastname rcvr) "server "))
  4799.               rcvr
  4800.               " "))
  4801.              (cond ((string= srvr "") "")
  4802.                ((or (string-match "^C:" m) (string-match "^N:" m))
  4803.                 parorg)
  4804.                (t (concat "from "
  4805.                       (if (irc-is-hostname srvr)
  4806.                       "server (user?)"
  4807.                       "user (server?)")
  4808.                       " "
  4809.                       srvr)))
  4810.              (if (and (string= srvr "")
  4811.                   (or (string= rcvr "")
  4812.                   (string= (upcase rcvr)
  4813.                        (upcase irc-nick-used))))
  4814.              ""
  4815.              ": ")
  4816.              m
  4817.              irc-msg-info-post)))
  4818.       ((or (string-match (concat "^[^: ]+ +[0-9]+ *[0-9]+ *[0-9]+ *"
  4819.                  "[0-9]+ *[0-9]+ +\\("
  4820.                  "Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun"
  4821.                  "\\) +")
  4822.              cmsg)
  4823.        (string-match (concat "^ *Link +SendQ +SendM +SendBytes"
  4824.                  " +RcveM +RcveBytes +Open +since"
  4825.                  " *$")
  4826.              cmsg))
  4827.        (irc-insert cmsg))
  4828. ;;;      ((string-match "^ *: *\\([^: ]+\\) +NOTICE +\\([^: ]+\\) *:" str)
  4829. ;;;       (let ((from (substring str (match-beginning 1) (match-end 1)))
  4830. ;;;         (to (substring str (match-beginning 2) (match-end 2)))
  4831. ;;;         (msg (substring str (match-end 0))))
  4832. ;;;     (setq retval (irc-parse-priv (concat ":" from " PRIVMSG " to
  4833. ;;;                          " :" msg)))))
  4834.       ((string-match "^\\(.*\\) +ToolZ V[0-9]+\\.[0-9]+[a-zA-Z]* *$" cmsg)
  4835.        (let ((m (subfield cmsg 1)))
  4836.      (if (string-match "^[ :;\\.?]*" m)
  4837.          (setq m (substring m (match-end 0))))
  4838.      (if (string-match "[ :;\\.?]*$" m)
  4839.          (setq m (substring m 0 (match-beginning 0))))
  4840.      (irc-insert "%sToolZ-notice from %s: %s%s"
  4841.              irc-msg-info-pre
  4842.              srvnam
  4843.              m
  4844.              irc-msg-info-post)))
  4845.       ((and (string= (upcase rcvr) (upcase irc-last-NOTICE-rcv))
  4846.         (string= (upcase srvr) (upcase irc-last-NOTICE-src)))
  4847.        (setq irc-last-NOTICE-rcv rcvr
  4848.          irc-last-NOTICE-src srvr)
  4849.        (let ((irc-msg-cont-used "    "))
  4850.      (irc-insert "*** %s" cmsg)))
  4851.       (t (setq irc-last-NOTICE-rcv rcvr
  4852.            irc-last-NOTICE-src srvr)
  4853.      (cond ((irc-is-nickname srvr)
  4854.         (irc-remember srvr 'irc-nicknames))
  4855.            ((irc-is-hostname srvr)
  4856.         (irc-remember srvr 'irc-servernames)))
  4857.      (irc-insert "")
  4858.      (let ((irc-msg-cont-used "       "))
  4859.        (irc-insert "****** %s %s says to %s:"
  4860.                (cond ((string= "" srvr) "Your")
  4861.                  ((irc-is-nickname srvr)
  4862.                   "User (or possible server)")
  4863.                  (t "Server (or possible user)"))
  4864.                (cond ((string= "" srvr) "server")
  4865.                  (t (concat "\"" srvr "\"")))
  4866.                (if (string= (upcase rcvr) (upcase irc-nick))
  4867.                "you"
  4868.                rcvr))
  4869.        (let ((irc-msg-cont-used "   "))
  4870.          (irc-insert "*** %s" cmsg)))))
  4871.     retval))
  4872.  
  4873.  
  4874. (defun irc-parse-pong (str)
  4875.   "Examine a PONG message from the IRC server.
  4876. Normaly the server should never send such a message, but when it does,
  4877. chances are there's a server name  given."
  4878.   (if (string-match "^PONG *\\([^: ]*\\)? *" str)
  4879.       (let* ((s (subfield str 1))
  4880.          (data (irc-nuke-whitespace (substring str (match-end 0))))
  4881.          (server (irc-extract-hostname s)))
  4882.     (if (irc-is-hostname server)
  4883.         (irc-remember server 'irc-servernames))
  4884.     (if data
  4885.         (irc-insert "%sServer %s says PONG, with message \"%s\"%s"
  4886.             irc-msg-info-pre
  4887.             server
  4888.             data
  4889.             irc-msg-info-post)
  4890.         (irc-insert "%sServer %s says PONG%s"
  4891.             irc-msg-info-pre
  4892.             server
  4893.             irc-msg-info-post)))))
  4894.  
  4895.  
  4896. (defun irc-parse-priv (str)
  4897.   "Examine a PRIVMSG message from the IRC server.
  4898. PRIVMSG is intended to be used for private message sent between users.
  4899. This is not always the case at the moment; servers will use it like either
  4900. NOTICE or MSG on occasion.
  4901.  
  4902. If it really is a private message, this function returns t if a signal should
  4903. be issued for the \"private\" event, nil otherwise."
  4904.   ;; This is really gross because it kludges in the fact that PRIVMSG can
  4905.   ;; be used to send notification of a change of channel topic.
  4906.  
  4907.   (if (not (string-match (concat "^ *: *\\([^: ]*\\) *PRIVMSG"
  4908.                  " *\\([^ ]*\\) +:")
  4909.              str))
  4910.       (progn
  4911.     (irc-insert "%%Unknown PRIVMSG seen in irc-parse-priv:")
  4912.     (irc-insert "%% \"%s\" (str)." str)
  4913.     (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  4914.       (let* ((from (substring str (match-beginning 1) (match-end 1))) 
  4915.          (to (substring str (match-beginning 2) (match-end 2)))
  4916.          (msg (substring str (match-end 0)))
  4917.          (time (if (and irc-message-stamp
  4918.                 (not (eq 'public irc-message-stamp)))
  4919.                (concat " (" (irc-get-time) ") ")
  4920.                ""))
  4921.          (hdr (format (format irc-msg-priv (+ 7 (length irc-channel)))
  4922.               time
  4923.               from
  4924.               "")))
  4925.     (cond ((and (irc-is-nickname from)
  4926.             (not (irc-recall to 'irc-subscribed-channels)))
  4927.            (irc-remember from 'irc-nicknames))
  4928.           ((irc-is-hostname from)
  4929.            (irc-remember from 'irc-servernames)))
  4930.     (cond
  4931.       ((and irc-ignore-automatic-warnings
  4932.         (string-match "^<Automatic +warning> +" msg))
  4933.        nil)
  4934.       ((irc-recall to 'irc-subscribed-channels)
  4935.        (irc-parse-public (concat ":" from " MSG :" msg) to))
  4936.       ((irc-recall from 'irc-ignored-ppl)
  4937.        (if (and (boundp 'irc-abusive-ignore)
  4938.             irc-abusive-ignore)
  4939.            (irc-send (concat "NOTICE "
  4940.                  from
  4941.                  " :You are being ignored by "
  4942.                  irc-nick-used))))
  4943.       ((string= (upcase to) (upcase irc-nick-used))
  4944.        (setq irc-last-private (concat from ":"))
  4945.        (let ((irc-msg-cont-used (make-string
  4946.                      (min (length hdr)
  4947.                       (/ (window-width
  4948.                           (get-buffer-window
  4949.                            (current-buffer)))
  4950.                          2))
  4951.                      ? )))
  4952.          (if (and (boundp 'irc-private-insert)
  4953.               irc-private-insert)
  4954.          (funcall irc-private-insert from to msg)
  4955.          (irc-insert (concat hdr (irc-clean-up-message msg))))
  4956.          (irc-signal from 'private)))
  4957.       ((irc-is-broadcastname to)
  4958.        (let ((irc-msg-cont-used (make-string
  4959.                      (min (length hdr)
  4960.                       (/ (window-width
  4961.                           (get-buffer-window
  4962.                            (current-buffer)))
  4963.                          2))
  4964.                      ? )))
  4965.          (irc-insert (concat hdr
  4966.                  "[BROADCAST to all users on IRC "
  4967.                  (if (= ?$ (aref to 0))
  4968.                      "server(s) "
  4969.                      "clients(s) on Internet host(s) ")
  4970.                  (upcase (substring to 1))
  4971.                  "] "
  4972.                  (irc-clean-up-message msg)))
  4973.          (irc-signal from 'wall)))
  4974.       (t (setq irc-last-private (concat from ":"))
  4975.          (let ((irc-msg-cont-used (make-string
  4976.                        (min (length hdr)
  4977.                         (/ (window-width
  4978.                         (get-buffer-window
  4979.                          (current-buffer)))
  4980.                            2))
  4981.                        ? )))
  4982.            (irc-insert "*** Private message to \"%s\" follows:" to)
  4983.            (if (and (boundp 'irc-private-insert)
  4984.             irc-private-insert)
  4985.            (funcall irc-private-insert from to msg)
  4986.            (irc-insert (concat hdr (irc-clean-up-message msg))))
  4987.            (irc-signal from 'private)))))))
  4988.  
  4989.  
  4990. (defun irc-parse-public (str &optional priv-chan)
  4991.   "Examine a MSG message from the IRC server.
  4992. MSG is sent when someone has sent a message to a channel.  In reality,
  4993. sometimes PRIVMSG is used but irc-parse-private should hand those off to
  4994. here.
  4995.  
  4996. This function returns t if a bell should be issued for the \"public\" or
  4997. \"backtalk\" events, nil otherwise."
  4998.   (let* ((user (substring str 1 (string-match " MSG :" str)))
  4999.      (rcvr (if priv-chan
  5000.            priv-chan
  5001.            (let ((clst (irc-recall-all 'irc-subscribed-channels)))
  5002.              ;; Find out which of the channel's is "MSG:able".
  5003.              (while (and clst (listp clst))
  5004.                (if (irc-is-multijoinable-channel (car clst))
  5005.                (setq clst (cdr clst))
  5006.                (setq clst (car clst))))
  5007.              ;; As THIS function was activated, we are listening to one
  5008.              ;; of the old type channels (42, +glbf) if priv-chan=nil.
  5009.              (if (not clst)
  5010.              "???"
  5011.              clst))))
  5012.      (msg (substring str (match-end 0)))
  5013.      (about-self (numberp (string-match
  5014.                    (concat "\\<"
  5015.                        (regexp-quote irc-nick-used)
  5016.                        "\\>")
  5017.                    msg)))
  5018.      (ismem (irc-recall user 'irc-ignored-ppl))
  5019.      (hdr (if ismem ""
  5020.           (format irc-msg-public
  5021.               (if (and irc-message-stamp
  5022.                    (not (eq 'private irc-message-stamp)))
  5023.                   (concat " (" (irc-get-time) ")")
  5024.                   "")
  5025.               user
  5026.               rcvr)))
  5027.      (irc-msg-cont-used (make-string
  5028.                  (min (length hdr)
  5029.                   (/ (window-width
  5030.                       (get-buffer-window (current-buffer)))
  5031.                      2))
  5032.                  ? )))
  5033.     ;; even here we can't guarantee that the sender has already been noted
  5034.     ;; someplace else like join or nick -- the sender might be someplace
  5035.     ;; else and sending to this channel with PRIVMSG.
  5036.     (irc-remember user 'irc-nicknames)
  5037.     (cond ((not ismem)            ;Not ignored?
  5038.        (progn (if (and (boundp 'irc-public-insert)
  5039.                irc-public-insert)
  5040.               (funcall irc-public-insert user rcvr msg)
  5041.               (irc-insert (concat hdr (irc-clean-up-message msg))))
  5042.           (or (irc-signal user 'public)
  5043.               (and about-self (irc-signal user 'backtalk))))))))
  5044.  
  5045.  
  5046. (defun irc-parse-quit (str)
  5047.   "Examine a QUIT message from the IRC server.
  5048. QUIT is used to tell of a user's departure from IRC.  It is currently sent
  5049. by the servers to those clients which are on the same channel as the
  5050. departing user.
  5051.  
  5052. This function returns t if a signal should be issued for the \"join\" event,
  5053. since it also signals someone leaving the channel.  It returns nil if no
  5054. bell should be issued."
  5055.   (if (not (or (string-match "^:? *\\([^ :]+\\)? +QUIT +\\([^ :]+\\) *: *" str)
  5056.            (string-match "^:? *\\([^ :]+\\)? +QUIT *\\(\\): *" str)))
  5057.       (progn (irc-insert "%%Unknown QUIT message in irc-parse-quit:")
  5058.          (irc-insert "%% \"%s\" (str)." str)
  5059.          (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  5060.       (let* ((u (subfield str 1))
  5061.          (user2 (subfield str 2))
  5062.          (c (irc-clean-up-message (irc-nuke-whitespace
  5063.                        (substring str (match-end 0)))))
  5064.          (user (if (string= "" u) irc-nick-used u))
  5065.          (myself (string= (upcase user) (upcase irc-nick-used)))
  5066.          (uc (upcase c))
  5067.          (comment (cond ((or (string= "" c)
  5068.                  (string= (upcase user) uc))
  5069.                  ": user quit")
  5070.                 ((string= "LEAVING" uc)
  5071.                  ": user quit, one ircII user less on IRC")
  5072.                 ((string= "BAD LINK?" uc)
  5073.                  ": link closed from client's side")
  5074.                 ((string-match "^\\([^.!]+\\)![A-Za-z][^ !]+$" c)
  5075.                  (format ": user quit past %s" (subfield c 1)))
  5076.                 ((string= "KILLED" uc)
  5077.                  ": killed")
  5078.                 ((string= "PING TIMEOUT" uc)
  5079.                  ": killed off due to inactivity")
  5080.                 ((string= "DEAD SOCKET" uc)
  5081.                  ": dead socket")
  5082.                 ((string= "WRITE ERROR" uc)
  5083.                  ": write error")
  5084.                 ((string-match
  5085.                   (concat "^\\([^ ]+\\.[^ .][^ ]*\\)"
  5086.                       " +\\([^ ]+\\.[^ .][^ ]*\\)$")
  5087.                   c)
  5088.                  (format ": netsplit past %s (lost %s)"
  5089.                      (subfield c 1)
  5090.                      (subfield c 2)))
  5091.                 ((string-match "^[^ ]+\\.[^ .][^ ]$" c)
  5092.                  (irc-remember c 'irc-servernames)
  5093.                  (concat ": netsplit just past " c))
  5094.                 (t (concat " (" c ")")))))
  5095.     (if (and (string< "" user2)
  5096.          (not (string= (upcase user) (upcase user2)))
  5097.          (boundp 'debug-on-error)
  5098.          debug-on-error)
  5099.         (irc-insert (concat "%sirc-parse-quit: secondary user to QUIT"
  5100.                 " differed, user=\"%s\", user2=\"%s\"%s")
  5101.             irc-msg-info-pre user user2 irc-msg-info-post))
  5102.     (irc-forget user 'irc-nicknames)
  5103.     (if (and (not (irc-recall user 'irc-ignored-ppl))
  5104.          (memq 'quit irc-events))
  5105.         (progn (irc-insert "%s%s left IRC%s%s"
  5106.                irc-msg-info-pre
  5107.                (if myself "You" user)
  5108.                comment
  5109.                irc-msg-info-post)
  5110.            ;; currently just the join event; some modification will
  5111.            ;; need to be made here when/if Jarkko has QUIT sent to
  5112.            ;; everyone,not just the channel 
  5113.            (irc-signal user 'join))))))
  5114.  
  5115.  
  5116. (defun irc-parse-RPL (str)
  5117.   "Examine a numeric RPL_ message from the IRC server.
  5118. Numeric control messages are used by newer servers to aid in generalized
  5119. client design; while people are converting to the new servers the older
  5120. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5121. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5122. in the IRC source file numeric.h.
  5123.  
  5124. Note well that some things are still going to come out wrong because the
  5125. servers are currently still doing things inconsistently."
  5126.   (if (string-match "^:?[^: ]+ +\\([023]\\)[0-9][0-9] +" str)
  5127.       (let ((n (string-to-int (subfield str 1))))
  5128.     (cond ((= n 3) (irc-parse-RPL-3xx str))
  5129.           ((= n 2) (irc-parse-RPL-2xx str))
  5130.           (t (irc-parse-RPL-0xx str))))
  5131.       (progn 
  5132.     (irc-insert "%%Function irc-parse-RPL called with non-RPL:")
  5133.     (irc-insert "%% \"%s\" (str)" str)
  5134.     (irc-insert "%% Please tell %s." irc-hacker))))
  5135.  
  5136.  
  5137. (defun irc-parse-RPL-0xx (str)
  5138.   "Examine a numeric RPL_ message from the IRC server.
  5139. Numeric control messages are used by newer servers to aid in generalized
  5140. client design; while people are converting to the new servers the older
  5141. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5142. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5143. in the IRC source file numeric.h.
  5144.  
  5145. Note well that some things are still going to come out wrong because the
  5146. servers are currently still doing things inconsistently."
  5147.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5148.                 "\\([^: ]+\\)? +:?")
  5149.             str)
  5150.       ;; we assume that the server and message are consistent for us; just
  5151.       ;; worry about the numeric value and the rest of the line
  5152.       (let* ((origin (subfield str 1))
  5153.          (num (string-to-int (subfield str 2)))
  5154.          (user (subfield str 3))
  5155.          (txt (substring str (match-end 0)))
  5156.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5157.              ""
  5158.              (concat "(" origin ") ")))
  5159.          tmp1 tmp2 tmp3 tmp4)
  5160.     (irc-remember origin 'irc-servernames)
  5161.     (cond
  5162.       ((= num 001)
  5163.        )
  5164.       ((= num 002)
  5165.        (irc-parse-notice (format "NOTICE %s :*** %s" user txt)))
  5166.       ((= num 003)
  5167.        (irc-parse-notice (format "NOTICE %s :*** %s" user txt)))
  5168.       ((= num 004)
  5169.        (irc-insert "*** FEATURES: %s" txt))
  5170.       (t                                 ; default
  5171.        (irc-insert (concat "%%Unrecognized numeric RPL 0xx message; "
  5172.                    "please tell %s:")
  5173.                irc-hacker)
  5174.        (irc-insert "%% str=\"%s\"." str)
  5175.        (irc-insert "%% Function irc-parse-RPL-0xx."))))
  5176.       ;; else
  5177.       (irc-insert (concat "%%Unrecognized nonnumeric RPL 0xx message follows; "
  5178.               "please tell %s:")
  5179.           irc-hacker)
  5180.       (irc-insert "%% \"%s\"." str)
  5181.       (irc-insert "%% Function irc-parse-RPL-0xx."))
  5182.   nil)
  5183.  
  5184.  
  5185. (defun irc-parse-RPL-2xx (str)
  5186.   "Examine a numeric RPL_ message from the IRC server.
  5187. Numeric control messages are used by newer servers to aid in generalized
  5188. client design; while people are converting to the new servers the older
  5189. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5190. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5191. in the IRC source file numeric.h.
  5192.  
  5193. Note well that some things are still going to come out wrong because the
  5194. servers are currently still doing things inconsistently."
  5195.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5196.                 "\\([^: ]+\\)? +:?")
  5197.             str)
  5198.       ;; we assume that the server and message are consistent for us; just
  5199.       ;; worry about the numeric value and the rest of the line
  5200.       (let* ((origin (subfield str 1))
  5201.          (num (string-to-int (subfield str 2)))
  5202.          (user (subfield str 3))
  5203.          (txt (substring str (match-end 0)))
  5204.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5205.              ""
  5206.              (concat "(" origin ") ")))
  5207.          tmp1 tmp2 tmp3 tmp4)
  5208.     (irc-remember origin 'irc-servernames)
  5209.     (cond
  5210.       ((= num 200)
  5211.        (cond ((string-match
  5212.            "^ *Link +\\([^ ]+\\) *:?\\([^ ]+\\) *:?\\([^ ]+\\)? *$"
  5213.            txt)
  5214.           (let ((vrsn (subfield txt 1))
  5215.             (goal (subfield txt 2))
  5216.             (next (subfield txt 3)))
  5217.             (irc-insert "%sLink to %s passes %s<%s>%s%s"
  5218.                 irc-msg-info-pre
  5219.                 (upcase goal)
  5220.                 (upcase origin)
  5221.                 (upcase vrsn)
  5222.                 (if (string= "" next)
  5223.                     ""
  5224.                     (concat "; next:" next))
  5225.                 irc-msg-info-post)))
  5226.          (t (irc-insert "%%Unknown RPL200 received in irc-parse-RPL-2xx:")
  5227.             (irc-insert "%% \"%s\" (txt)." txt)
  5228.             (irc-insert "%% Please tell %s, this might be a bug."
  5229.                 irc-hacker))))
  5230.       ((or (= num 201)        ; RPL_TRACECONNECTING "Try."
  5231.            (= num 202))        ; RPL_TRACEHANDSHAKE
  5232.        (cond ((string-match "^\\([^ ]+\\) +\\([0-9]+\\) +:?\\([^ ]+\\)"
  5233.                 txt)
  5234.           (let* ((type (subfield txt 1))
  5235.              (class (subfield txt 2))
  5236.              (host (subfield txt 3))
  5237.              (utype (upcase type))
  5238.              (state (cond ((string= "TRY." utype)
  5239.                        "trying to connect to it")
  5240.                       ((string= "H.S." utype)
  5241.                        "registering us as server at it")
  5242.                       (t type))))
  5243.             (irc-insert "%s%sClass %3s half: %s (%s)%s"
  5244.                 irc-msg-info-pre
  5245.                 parorg class (upcase host) state
  5246.                 irc-msg-info-post)))
  5247.          (t (irc-insert "%%Received unknown RPL%d in irc-parse-RPL-2xx:"
  5248.                 num)
  5249.             (irc-insert "%% \"%s\" (txt)." txt)
  5250.             (irc-insert "%% Please tell %s, it might be a bug."
  5251.                 irc-hacker))))
  5252.       ((or (= num 203)        ; RPL_TRACEUNKNOWN
  5253.            (= num 204)        ; RPL_TRACEOPERATOR "Oper"
  5254.            (= num 205))        ; RPL_TRACEUSER "User"
  5255.        (cond ((string-match (concat "^\\([^ ]+\\) +\\(-?[0-9]+\\) *:?"
  5256.                     "*\\([^ ]*\\)\\[\\(.+\\)\\] *"
  5257.                     ":?[0-9]*")
  5258.                 txt)
  5259.           (let* ((type (subfield txt 1))
  5260.              (class (subfield txt 2))
  5261.              (u (subfield txt 3))
  5262.              (cm (subfield txt 4))
  5263.              (user (irc-nuke-whitespace u)))
  5264.             (if (string< "" user)
  5265.             (irc-remember user 'irc-nicknames))
  5266.             (irc-insert "%s%sClass %3s %s: \"%s\" (client on %s)%s"
  5267.                 irc-msg-info-pre
  5268.                 parorg
  5269.                 class
  5270.                 (downcase type)
  5271.                 user
  5272.                 (upcase cm)
  5273.                 irc-msg-info-post)))
  5274.          (t (irc-insert
  5275.              "%%Unknown RPL203:205 seen, in irc-parse-RPL-2xx:")
  5276.             (irc-insert "%% \"%s\" (str); \"%s\" (txt)." str txt)
  5277.             (irc-insert "%% Please tell %s, it might be a bug."
  5278.                 irc-hacker))))
  5279.       ((= num 206)            ; RPL_TRACESERVER "Serv"
  5280.        (if (or (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) +\\(\\)"
  5281.                      "\\([0-9]+\\)S +\\([0-9]+\\)C +:? *"
  5282.                      "\\([^ ]+\\) *$")
  5283.                  txt)
  5284.            (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) +"
  5285.                      "\\([^ ]+\\) +\\([0-9]+\\)S *:?"
  5286.                      " *\\([0-9]+\\)C *$")
  5287.                  txt)
  5288.            (string-match (concat "^\\([^ ]+\\) +\\([0-9]+\\) *"
  5289.                      ":? *\\(.+\\) *\\(\\)\\(\\)$")
  5290.                  txt))
  5291.            (let* ((type (subfield txt 1))
  5292.               (class (subfield txt 2))
  5293.               (r (subfield txt 3))
  5294.               (ns (string-to-int (subfield txt 4)))
  5295.               (nc (string-to-int (subfield txt 5)))
  5296.               (remote (if (string= "" r) (subfield txt 6) r)))
  5297.          (irc-remember remote 'irc-servernames)
  5298.          (irc-insert "%s%sClass %3s %s: %s%s%s"
  5299.                  irc-msg-info-pre
  5300.                  parorg
  5301.                  class
  5302.                  (downcase type)
  5303.                  (upcase remote)
  5304.                  (if (and (= ns 0) (= nc 0))
  5305.                  ""
  5306.                  (format " (%d server%s, %d client%s)%s"
  5307.                      ns
  5308.                      (if (= 1 ns) "" "s")
  5309.                      nc
  5310.                      (if (= 1 nc) "" "s")))
  5311.                  irc-msg-info-post))
  5312.            (progn
  5313.          (irc-insert "%%Unknown RPL206 received in irc-parse-RPL-2xx:")
  5314.          (irc-insert "%% \"%s\" (txt)." txt)
  5315.          (irc-insert "%% Please tell %s, it might be a bug."
  5316.                  irc-hacker))))
  5317.       ;; Missing 207 RPL_TRACESERVICE
  5318.       ;; Missing 208 RPL_TRACENEWTYPE
  5319.       ((= num 209)            ; RPL_TRACECLASS
  5320.        (cond ((string-match (concat "^Class +\\([0-9]+\\) *"
  5321.                     ":? *\\([0-9]+\\) *$")
  5322.                 txt)
  5323.           (let ((class (string-to-int (subfield txt 1)))
  5324.             (count (string-to-int (subfield txt 2))))
  5325.             (irc-insert
  5326.              "%s%s%d service%s linked for class %3d%s"
  5327.              irc-msg-info-pre
  5328.              parorg
  5329.              count
  5330.              (if (= 1 count) "" "s")
  5331.              class
  5332.              irc-msg-info-post)))
  5333.          (t (irc-insert "%%Unknown RPL209 message in irc-parse-RPL-2xx:")
  5334.             (irc-insert "%% \"%s\" (txt)" txt)
  5335.             (irc-insert "%% Please tell %s, it might be a bug."
  5336.                 irc-hacker))))
  5337.       ((= num 211)            ;L-lines
  5338.        (cond ((string-match (concat "^\\([^: ]+\\) +\\([0-9]+\\) +"
  5339.                     "\\([0-9]+\\) +\\([0-9]+\\) +"
  5340.                     "\\([0-9]+\\) +\\([0-9]+\\) +"
  5341.                     ": *\\(.*\\) *$")
  5342.                 txt)
  5343.           (let* ((link (subfield txt 1))
  5344.              (sendq (subfield txt 2))
  5345.              (sendm (subfield txt 3))
  5346.              (sendbytes (subfield txt 4))
  5347.              (rcvem (subfield txt 5))
  5348.              (rcvebytes (subfield txt 6))
  5349.              (rest (subfield txt 7))
  5350.              (irc-msg-cont-used
  5351.               "                                                 "))
  5352.             (irc-insert "%8s %8s %10s %8s %10s %s"
  5353.                 sendq sendm sendbytes rcvem rcvebytes rest)
  5354.             (irc-insert "%s(to %s)" irc-msg-cont-used (upcase link))))
  5355.          ((string-match (concat "^ *\\(Link +\\)?SendQ +SendM"
  5356.                     " +SendBytes +RcveM +RcveBytes"
  5357.                     " +:Open since *$")
  5358.                 txt)
  5359.           (irc-insert (concat
  5360.                    " SendQue   S-Msgs    S-Bytes   R-Msgs"
  5361.                    "    R-Bytes Date (to link)"))
  5362.           (irc-insert (concat
  5363.                    "-------- -------- ---------- --------"
  5364.                    " ---------- --------------")))
  5365.          (t (irc-insert "%%Unknown RPL211, in irc-parse-RPL-2xx:")
  5366.             (irc-insert "%% \"%s\" (txt)." txt)
  5367.             (irc-insert "%% Please tell %s, it might be a bug."
  5368.                 irc-hacker))))
  5369.       ((= num 212)            ;RPL_STATSCOMMANDS (ie non CIKLQY)
  5370.        (cond ((string-match "^\\([^ ]+\\) +:?\\([0-9]+\\) *\\([0-9]+\\)?$"
  5371.                 txt)
  5372.           (let* ((type (subfield txt 1))
  5373.              (count (subfield txt 2))
  5374.              (rcount (subfield txt 3))
  5375.              (n (string-to-int count))
  5376.              (rn (string-to-int rcount))
  5377.              (c (concat (make-string (max 0 (- 5 (length count)))
  5378.                          ? )
  5379.                     count))
  5380.              (cmds (if (= n 1) "command " "commands")))
  5381.             (irc-insert "%sServer %s has seen %s %s of type %s%s%s"
  5382.                 irc-msg-info-pre
  5383.                 (upcase origin)
  5384.                 c
  5385.                 cmds
  5386.                 (upcase type)
  5387.                 (if (string= "" rcount)
  5388.                     ""
  5389.                     (format " %s(%d remote?)"
  5390.                         (make-string (- 7 (length type))
  5391.                              ? )
  5392.                         rn))
  5393.                 irc-msg-info-post)))
  5394.          (t (irc-insert
  5395.              "%%Unknown RPL212 message received in irc-parse-RPL-2xx:")
  5396.             (irc-insert "%% \"%s\" (txt)." txt)
  5397.             (irc-insert "%% Please tell %s, it might be a bug."
  5398.                 irc-hacker))))
  5399.       ((or (= num 213)        ;C-lines
  5400.            (= num 214)        ;N-lines
  5401.            (= num 215)        ;I-lines
  5402.            (= num 216)        ;K-lines
  5403.            (= num 217)        ;Q-lines
  5404.            (= num 241)        ;L-lines
  5405.            (= num 242)        ;Uptime
  5406.            (= num 243)        ;O-lines
  5407.            (= num 244)        ;H-lines
  5408.            (= num 249)        ;other such lines
  5409.            )
  5410.        (cond ((string= (upcase origin) (upcase irc-server))
  5411.           (irc-insert "*** %s" txt))
  5412.          (t (irc-insert "*** (%s): %s" origin txt))))
  5413.       ((= num 218)            ;Y-lines
  5414.        (cond ((string-match
  5415.            (concat "^ *Y +\\([0-9]+\\) +\\([0-9]+\\) +\\([0-9]+\\) +:?"
  5416.                " *\\([0-9]+\\) +:?\\([0-9]+\\)")
  5417.            txt)
  5418.           (let* ((class (subfield txt 1))
  5419.              (ping-freq (subfield txt 2))
  5420.              (conn-freq (subfield txt 3))
  5421.              (max-links (subfield txt 4))
  5422.              (plur (if (= 1 (string-to-int max-links)) "" "s"))
  5423.              (sendq (subfield txt 5))
  5424.              (pre (format (concat "*** %sClass: %s, conn. freq."
  5425.                           " %ss, ping freq. %ss, ")
  5426.                       parorg class conn-freq ping-freq))
  5427.              (irc-msg-cont-used (make-string (length pre) ? )))
  5428.             (irc-insert "%smax# %s link%s, SendQ %s."
  5429.                 pre
  5430.                 max-links
  5431.                 plur
  5432.                 sendq)))
  5433.          (t (irc-insert "%%Unknown RPL218 in irc-parse-RPL-2xx:")
  5434.             (irc-insert "%% \"%s\" (txt)." txt)
  5435.             (irc-insert "%% Please tell %s, it might be a bug."
  5436.                 irc-hacker))))
  5437.       ((= num 219)
  5438.        (irc-insert "%sSTATS listing for server %s done%s"
  5439.                irc-msg-info-pre
  5440.                (upcase origin)
  5441.                irc-msg-info-post)
  5442.        (irc-insert ""))
  5443.       ((= num 221)
  5444.        (let ((i (1- (length txt)))
  5445.          (ut (upcase txt)))
  5446.          (while (and (>= i 0) (not (= ?O (aref ut i))))
  5447.            (setq i (1- i)))
  5448.          (while (and (>= i 0)
  5449.              (not (= ?- (aref ut i)))
  5450.              (not (= ?+ (aref ut i))))
  5451.            (setq i (1- i)))
  5452.          (setq irc-operator (if (and (>= i 0) (= ?+ (aref ut i)))
  5453.                      " IOPR"
  5454.                      nil)))
  5455.        (irc-insert "%sUser %s'%s mode%s: %s%s"
  5456.                irc-msg-info-pre
  5457.                user
  5458.                (if (= ?S (aref (upcase user) (1- (length user))))
  5459.                ""
  5460.                "s")
  5461.                (if (= 2 (length txt)) " is" "s are")
  5462.                (irc-explain-user-mode txt 'no-direction)
  5463.                irc-msg-info-post))
  5464. ;;;      ((= num 232)
  5465. ;;;       (irc-insert "DEBUG: RPL232 txt=\"%s\"." txt))
  5466. ;;;      ((= num 241) SEE RPL213-217
  5467. ;;;       )
  5468. ;;;      ((= num 242) SEE RPL213-217
  5469. ;;;       )
  5470. ;;;      ((= num 243) SEE RPL213-217
  5471. ;;;       )
  5472. ;;;      ((= num 244) SEE RPL213-217
  5473. ;;;       )
  5474. ;;;      ((= num 249) SEE RPL213-217
  5475. ;;;       )
  5476.       ((= num 250)
  5477.        (irc-insert "*** %s" txt))
  5478.       ((= num 251)
  5479.        (irc-insert "*** %s" txt))
  5480.       ((= num 252)
  5481.        (cond ((string-match "^\\([0-9]+\\) +:operator.*online$" txt)
  5482.           (irc-parse-notice (format (concat
  5483.                          "NOTICE %s :*** %s users have"
  5484.                          " connection to the twilight"
  5485.                          " zone")
  5486.                         user (subfield txt 1))))
  5487.          ((string-match "^\\([^ :]+\\) *: *\\(.*\\)$" txt)
  5488.           (irc-insert "*** %s %s" (subfield txt 1) (subfield txt 2)))
  5489.          (t (irc-insert "*** %s" txt))))
  5490.       ((= num 253)
  5491.        (if (string-match "^\\([0-9]+\\) *:unknown connection(?s?)?" txt)
  5492.            (let ((n (string-to-int (subfield txt 1))))
  5493.          (irc-insert "*** There %s %d %s of (yet) unknown %s."
  5494.                  (if (= 1 n) "is" "are")
  5495.                  n
  5496.                  (if (= 1 n) "connection" "connections")
  5497.                  (if (= 1 n) "type" "types")))
  5498.            (progn (irc-insert "%%Unrecognized RPL 253 message seen:")
  5499.               (irc-insert "%% \"%s\" (txt)" txt)
  5500.               (irc-insert "%% Please tell %s" irc-hacker))))
  5501.       ((= num 254)
  5502.        (if (string-match "^\\([0-9]+\\) :channel" txt)
  5503.            (irc-parse-notice (format (concat "NOTICE %s :*** There are %s"
  5504.                          " channels.")
  5505.                      user (subfield txt 1)))
  5506.            (irc-insert "*** %s" txt)))
  5507.       ((= num 255)            ;"I have 77 clients, 0 services and 1 servers"
  5508.        (let ((text (if (string-match "^I have \\(.*\\)" txt)
  5509.                (format "%s has %s"
  5510.                    (upcase origin)
  5511.                    (subfield txt 1))
  5512.              txt)))
  5513.          (irc-insert "*** %s" text)))
  5514.       ((= num 256)            ;RPL admin, first line
  5515.        (irc-insert "### %s" txt))
  5516.       ((= num 257)            ;RPL admin, second line
  5517.        (irc-insert "### %s" txt))
  5518.       ((= num 258)            ;RPL admin, third line
  5519.        (irc-insert "### %s" txt))
  5520.       ((= num 259)            ;RPL admin, fourth and last line
  5521.        (irc-insert "### %s" txt)
  5522.        (irc-insert "%sEnd of ADMIN for %s%s"
  5523.                irc-msg-info-pre origin irc-msg-info-post)
  5524.        (irc-insert ""))
  5525.       ((= num 261)            ;RPL log file
  5526.        (if (string-match "^File +\\(.+\\) +:\\([0-9]+\\)$"
  5527.                  txt)
  5528.            (let ((file (subfield txt 1))
  5529.              (dbglvl (subfield txt 2)))
  5530.          (irc-insert
  5531.           "%s%sThe servers log file for debug level %s is %s%s"
  5532.           irc-msg-info-pre
  5533.           parorg
  5534.           dbglvl
  5535.           file
  5536.           irc-msg-info-post))
  5537.            (progn (irc-insert "%%Unknown RPL 261 seen:")
  5538.               (irc-insert "%% \"%s\" (txt)" txt)
  5539.               (irc-insert "%% Please tell %s" irc-hacker))))
  5540.       ((= num 262)
  5541.        (if (string-match "\\([^ ]+\\) +\\([^ ]+\\)\\.? *: *\\(.*\\)" txt)
  5542.            (irc-insert "%%%s for %s who's using a server of version %s"
  5543.                (subfield txt 3)
  5544.                (subfield txt 1)
  5545.                (subfield txt 2))
  5546.          (irc-insert "%%%s" txt)))
  5547.       ((= num 265)
  5548.        (irc-insert "*** %s" txt))
  5549.       ((= num 266)
  5550.        (irc-insert "*** %s" txt))
  5551.       (t                                 ; default
  5552.        (irc-insert (concat "%%Unrecognized numeric RPL 2xx message; "
  5553.                    "please tell %s:")
  5554.                irc-hacker)
  5555.        (irc-insert "%% str=\"%s\"." str)
  5556.        (irc-insert "%% Function irc-parse-RPL-2xx."))))
  5557.       ;; else
  5558.       (irc-insert (concat "%%Unrecognized nonnumeric RPL 2xx message follows; "
  5559.               "please tell %s:")
  5560.           irc-hacker)
  5561.       (irc-insert "%% \"%s\"." str)
  5562.       (irc-insert "%% Function irc-parse-RPL-2xx."))
  5563.   nil)
  5564.  
  5565.  
  5566. (defun irc-parse-RPL-3xx (str)
  5567.   "Examine a numeric RPL_ message from the IRC server.
  5568. Numeric control messages are used by newer servers to aid in generalized
  5569. client design; while people are converting to the new servers the older
  5570. irc-parse-error, irc-parse-notice, et al, functions are redundant with
  5571. irc-parse-ERR and irc-parse-RPL.  Values used by this function are found
  5572. in the IRC source file numeric.h.
  5573.  
  5574. Note well that some things are still going to come out wrong because the
  5575. servers are currently still doing things inconsistently."
  5576.   (if (string-match (concat "^:?\\([^: ]+\\) *\\([023][0-9][0-9]\\) +"
  5577.                 "\\([^: ]+\\)? +:?")
  5578.             str)
  5579.       ;; we assume that the server and message are consistent for us; just
  5580.       ;; worry about the numeric value and the rest of the line
  5581.       (let* ((origin (subfield str 1))
  5582.          (num (string-to-int (subfield str 2)))
  5583.          (user (subfield str 3))
  5584.          (txt (substring str (match-end 0)))
  5585.          (parorg (if (string= (upcase origin) (upcase irc-server))
  5586.              ""
  5587.              (concat "(" origin ") ")))
  5588.          tmp1 tmp2 tmp3 tmp4)
  5589.     (irc-remember origin 'irc-servernames)
  5590.     (cond
  5591.      ((= num 301)                       ; RPL_AWAY
  5592.       (cond ((string-match "^\\([^: ]+\\) :" txt)
  5593.          (let ((nick (subfield txt 1))
  5594.                (msg (substring txt (match-end 0))))
  5595.            (irc-remember nick 'irc-nicknames)
  5596.            (irc-insert "%%User %s is away (%s)."
  5597.                    nick
  5598.                    (irc-clean-up-message msg))))
  5599.         (t (irc-insert (concat "%%One of the last persons you sent to"
  5600.                        " is away, delivered your"
  5601.                        " message anyway.")))))
  5602.      ((= num 302)                 ; RPL_USERHOST
  5603.       (let ((s txt))
  5604.         (while (string-match
  5605.             (concat "^\\([^ =*]+\\)\\(\\*?\\)=\\([+-]\\)"
  5606.                 "\\([^@]+\\)@\\([^ ]+\\) *")
  5607.             s)
  5608.           (let* ((nick (subfield s 1))
  5609.              (oper (subfield s 2))
  5610.              (away (subfield s 3))
  5611.              (user (subfield s 4))
  5612.              (host (subfield s 5))
  5613.              (rest (substring s (match-end 0))))
  5614.         (irc-remember nick 'irc-nicknames)
  5615.         (irc-remember host 'irc-servernames)
  5616.         (irc-insert "%s%s \"%s\" is %s@%s%s%s"
  5617.                 irc-msg-info-pre
  5618.                 (if (string= "*" oper) "Operator" "User")
  5619.                 nick
  5620.                 user
  5621.                 host
  5622.                 (if (string= "-" away) " (AWAY)" "")
  5623.                 irc-msg-info-post)
  5624.         (setq s rest)))))
  5625.      ((= num 303)                 ; RPL_ISON
  5626.       (let ((data (if (and (> (length txt) 0) (= ?: (aref txt 0)))
  5627.               (substring txt 1) txt))
  5628.         (ignored 0)
  5629.         (list ())
  5630.         (found ()))
  5631.         (while (string-match "^ *\\([^ ]+\\)" data)
  5632.           (setq found (cons (subfield data 1) found)
  5633.             data (substring data (match-end 0))))
  5634.         (while (not (null found))
  5635.           (if (irc-recall (car found) 'irc-ignored-ppl)
  5636.           (setq ignored (1+ ignored))
  5637.         (setq list (cons (car found) list)))
  5638.           (setq found (cdr found)))
  5639.         (setq list (reverse list))    ;Keep list sorted.
  5640.         (let ((l list)
  5641.           (arrivers ()))
  5642.           (while (not (null l))
  5643.         (if (not (irc-recall (car l) 'irc-notify-detected))
  5644.             (progn (setq arrivers (cons (car l) arrivers))
  5645.                (irc-send (format "WHOIS %s %s" (car l) (car l)))
  5646.                (irc-remember (car l) 'irc-notify-detected)
  5647.                (irc-remember (car l) 'irc-nicknames)
  5648.                ))
  5649.         (setq l (cdr l)))
  5650.           (let ((l (irc-recall-all 'irc-notify-detected))
  5651.             (gonners ()))
  5652.         (while (not (null l))
  5653.           (if (not (irc-list-recall (car l) list))
  5654.               (progn (setq gonners (cons (car l) gonners))
  5655.                  (irc-forget (car l) 'irc-notify-detected)))
  5656.           (setq l (cdr l)))
  5657.         (if (not (null arrivers))
  5658.             (let ((a arrivers)
  5659.               (as (irc-listify arrivers ", " "and")))
  5660.               (irc-insert "%sDETECTED %s%s on IRC%s"
  5661.                   irc-msg-info-pre
  5662.                   as
  5663.                   (if (> ignored 0)
  5664.                       (format " (also %d ignored person%s)"
  5665.                           ignored
  5666.                           (if (= 1 ignored) "" "s"))
  5667.                     "")
  5668.                   irc-msg-info-post)
  5669.               (if (irc-signal (car a) 'detect)
  5670.               (progn
  5671.                 (message (format "Kiwi: Detected %s on IRC" as))
  5672.                 (ding t)))))
  5673.         (if (not (null gonners))
  5674.             (let ((g gonners)
  5675.               (gs (irc-listify gonners ", " "and")))
  5676.               (irc-insert "%sLOST SIGHT of %s from IRC%s"
  5677.                   irc-msg-info-pre
  5678.                   gs
  5679.                   irc-msg-info-post)
  5680.               (while g
  5681.             (if (irc-signal (car g) 'detect)
  5682.                 (progn
  5683.                   (message (format
  5684.                     "Kiwi: lost sight of %s from IRC"
  5685.                     gs))
  5686.                   (ding t)))
  5687.             (setq g (cdr g)))))))))
  5688.      ((= num 304)                 ; RPL_TEXT
  5689.       (irc-insert "Text: %s" txt))
  5690.      ((= num 305)
  5691.       (irc-insert "%sYou are no longer marked as being away%s"
  5692.               irc-msg-info-pre irc-msg-info-post))
  5693.      ((= num 306)
  5694.       (irc-insert (concat "%sYou have been marked as being away, use"
  5695.                   " /HERE to revert the effect%s")
  5696.               irc-msg-info-pre irc-msg-info-post))
  5697.      ((= num 311)                       ; RPL_WHOISUSER
  5698.       (string-match (concat "^\\([^: ]+\\) +\\([^: ]+\\) +\\([^: ]+\\)"
  5699.                 " \\([^: ]+\\) :")
  5700.             txt)
  5701.       (let* ((nick (subfield txt 1))
  5702.          (rn (substring txt (match-end 0)))
  5703.          (user-name (subfield txt 2))
  5704.          (client (subfield txt 3))
  5705.          (c (subfield txt 4))
  5706.          (channel (if (string= c "*")
  5707.                   ""
  5708.                 (concat " on channel " c)))
  5709.          (cntrl1 (format "%s \"%s\" "
  5710.                  (if (irc-recall nick 'irc-ignored-ppl)
  5711.                      "IGNORED user"
  5712.                    "User")
  5713.                  nick))
  5714.          (real-name (irc-nuke-whitespace rn)))
  5715.         (setq irc-msg-cont-used (make-string (length cntrl1) ? ))
  5716.         (irc-remember nick 'irc-nicknames)
  5717.         (irc-insert (concat cntrl1 "is %s <%s@%s>%s,")
  5718.             (irc-clean-up-message real-name)
  5719.             (irc-clean-up-message user-name)
  5720.             client
  5721.             channel)))
  5722.      ((= num 312)            ; RPL_WHOISSERVER
  5723.       (let ((info-hop-count nil)
  5724.         (info-nick nil)
  5725.         (info-real-server-or-relay-name nil)
  5726.         (info-server-name nil)
  5727.         (info-server-descr nil)
  5728.         (found-info nil))
  5729.         (cond
  5730.          ((string-match "^ *\\([^ :]+\\) +\\([^ :]+\\) *: *" txt)
  5731.           (setq info-nick (subfield txt 1)
  5732.             info-server-name (subfield txt 2))
  5733.           (let ((rst (substring txt (match-end 0))))
  5734.         (cond ((string-match (concat "^... ... +[0-9]+ [0-9]+:"
  5735.                          "[0-9]+:[0-9]+ [0-9]+$")
  5736.                      rst)
  5737.                (setq info-server-descr (format "gone since %s" rst)
  5738.                  found-info t))
  5739.               ((string-match (concat "^\\([0-9]+\\) *: *\\["
  5740.                          "\\([^]]+\\)\\] *\\(.*\\) *$")
  5741.                      rst)
  5742.                (setq info-hop-count (subfield rst 1)
  5743.                  info-real-server-or-relay-name (subfield rst 2)
  5744.                  info-server-descr (subfield rst 3)
  5745.                  found-info t))
  5746.               ((string-match "^\\([0-9]+\\) +:? *\\(.*\\) *$" rst)
  5747.                (setq info-hop-count (subfield rst 1)
  5748.                  info-server-descr (subfield rst 2)
  5749.                  found-info t))
  5750.               ((string-match "^\\[\\([^]]+\\)\\] *\\(.*\\) *$"
  5751.                      rst)
  5752.                (setq info-real-server-or-relay-name (subfield rst 1)
  5753.                  info-server-descr (subfield rst 2)
  5754.                  found-info t))
  5755.               (t (setq info-server-descr rst
  5756.                    found-info t)))))
  5757.          ((string-match (concat "^\\([^ :]+\\) *: *\\([0-9]+\\) *: *"
  5758.                     "\\([^ ].*[^ ]\\) *$")
  5759.                 txt)
  5760.           (setq info-server-name (subfield txt 1)
  5761.             info-hop-count (subfield txt 2)
  5762.             info-server-descr (subfield txt 3)
  5763.             found-info t))
  5764.          ((string-match "^\\([^ :]+\\) *: *\\([^ ].*[^ ]\\) *$" txt)
  5765.           (setq info-server-name (subfield txt 1)
  5766.             info-server-descr (subfield txt 2)
  5767.             found-info t)))
  5768.         (if (not found-info)
  5769.         (progn
  5770.           (irc-insert "%%Found unknown RPL312 in irc-parse-RPL-3xx:")
  5771.           (irc-insert "%% \"%s\" (txt)." txt)
  5772.           (irc-insert "%% Please tell %s, it might be a bug."
  5773.                   irc-hacker))
  5774.           (irc-remember info-server-name 'irc-servernames)
  5775.           (let ((s (format "%s%son %s (%s)%s."
  5776.                    irc-msg-cont-used
  5777.                    (if info-real-server-or-relay-name
  5778.                    (concat "(according to "
  5779.                        info-real-server-or-relay-name
  5780.                        ") ")
  5781.                  "")
  5782.                    info-server-name
  5783.                    (irc-clean-up-message
  5784.                 (irc-nuke-whitespace info-server-descr))
  5785.                    (if info-hop-count
  5786.                    (concat " at least "
  5787.                        info-hop-count
  5788.                        " hops away")
  5789.                  ""))))
  5790.         (irc-insert "%s" s)))))
  5791.      ((= num 313)            ; RPL_WHOISOPERATOR
  5792.       (string-match "^[^: ]+" txt)
  5793.       (irc-insert "%s\"%s\" is an ENABLED operator on IRC."
  5794.               irc-msg-cont-used
  5795.               (substring txt (match-beginning 0) (match-end 0))))
  5796.      ((= num 314)                 ; RPL_WHOWASUSER
  5797.       (if (string-match (concat "^\\([^: ]+\\) \\([^: ]+\\) \\([^: ]+\\)"
  5798.                     " \\([^: ]+\\) *:")
  5799.                 txt)
  5800.           (let* ((nick (subfield txt 1))
  5801.              (rn (substring txt (match-end 0)))
  5802.              (user-name (subfield txt 2))
  5803.              (client (subfield txt 3))
  5804.              (c (subfield txt 4))
  5805.              (channel (if (string= c "*")
  5806.                   ""
  5807.                 (concat " on channel " c)))
  5808.              (real-name (irc-nuke-whitespace rn))
  5809.              (cntrl1 (format "%%User \"%s\" " nick)))
  5810.         (setq irc-msg-cont-used (make-string (length cntrl1) ? ))
  5811.         (if (not (irc-recall nick 'irc-services))
  5812.             (irc-forget nick 'irc-nicknames))
  5813.         (irc-insert (concat "%" cntrl1 "isn't on IRC anymore,"
  5814.                     " was %s <%s@%s>%s,")
  5815.                 (irc-clean-up-message real-name)
  5816.                 (irc-clean-up-message user-name)
  5817.                 client
  5818.                 channel))))
  5819.      ((= num 315)                 ; RPL_WHOEND
  5820.       (if (= 0 irc-reply-count)
  5821.           (irc-insert "%%No users listed")
  5822.         (irc-insert "%s%d user%s listed%s"
  5823.             irc-msg-info-pre
  5824.             irc-reply-count
  5825.             (if (= 1 irc-reply-count) "" "s")
  5826.             irc-msg-info-post))
  5827.       (setq irc-reply-count 0)
  5828.       (if t ()
  5829.         (message "")
  5830.         (if (irc-nothing-remembered-p 'irc-whotree)
  5831.         (let ((c (if (string-match (concat "^ *: *[^ ]+ +315"
  5832.                            " +[^ ]+ +\\([^:]+\\)"
  5833.                            " +:")
  5834.                        str)
  5835.                  (subfield str 1))))
  5836.           (irc-insert (if c "%%No users on \"%s\"." "%%No users.")
  5837.                   c))
  5838.           (irc-recall-all-and-display 'irc-whotree
  5839.                     ;(string-match "-* *$"
  5840.                     ;irc-who-stroke)
  5841.                       31
  5842.                       "users"
  5843.                       "user")
  5844.           (irc-forget-all 'irc-whotree)))
  5845.       )
  5846.      ((= num 316)                 ; RPL_WHOISCHANOP
  5847.       (if (not
  5848.            (string-match (concat "^:\\([^: ]+\\)? +316 +\\([^: ]+\\) +"
  5849.                      "\\([^: ]+\\) +: *has +been +"
  5850.                      "touched +by +magic +forces *$")
  5851.                  str))
  5852.           (progn (irc-insert (concat "%%Unrecognized type 316 reply; "
  5853.                      "please tell %s:")
  5854.                  irc-hacker)
  5855.              (irc-insert "%% \"%s\"." str)
  5856.              (irc-insert " Function irc-parse-RPL-3xx, at 316."))
  5857.         (let ((server (substring str (match-beginning 1) (match-end 1)))
  5858.           (own (substring str (match-beginning 2) (match-end 2)))
  5859.           (other (substring str (match-beginning 3) (match-end 3))))
  5860.           (irc-remember own 'irc-nicknames)
  5861.           (irc-remember other 'irc-nicknames)
  5862.           (irc-insert "%s\"%s\" is a channel operator."
  5863.               irc-msg-cont-used
  5864.               other))))
  5865.      ((= num 317)            ;RPL_IDLETIME
  5866.       (cond ((or (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+"
  5867.                        " +\\([^ ]+\\)"
  5868.                        " +\\([0-9]+\\)"
  5869.                        " +\\([0-9]+\\)"
  5870.                        " *:")
  5871.                    str)
  5872.              (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+"
  5873.                        " +\\([^ ]+\\)"
  5874.                        " +\\([0-9]+\\)"
  5875.                        "\\(\\) *:")
  5876.                    str)
  5877.              (string-match (concat "^ *: *[^ ]+ +317 +[^ ]+\\(\\)\\(\)"
  5878.                        " +\\([0-9]+\\)"
  5879.                        " *:")
  5880.                    str))
  5881.          (let* ((user (subfield str 1))
  5882.             (time (string-to-int (subfield str 2)))
  5883.             (logintime (string-to-int (subfield str 3))))
  5884.            (if (zerop time)
  5885.                (irc-insert "%s\"%s\" is actively typing."
  5886.                    irc-msg-cont-used
  5887.                    user)
  5888.              (irc-insert "%sIdle time for user %s is %d second%s%s."
  5889.                  irc-msg-cont-used
  5890.                  user
  5891.                  time
  5892.                  (if (= 1 time) "" "s")
  5893.                  (if (> 60 time)
  5894.                      ""
  5895.                    (concat " ("
  5896.                        (irc-sec-to-time time)
  5897.                        ")"))))))
  5898.         (t (irc-insert (concat "%%Unknown 317 type reply message in"
  5899.                        " function irc-parse-RPL-3xx."))
  5900.            (irc-insert "%% \"%s\" (str)." str)
  5901.            (irc-insert "%% Please tell %s, it might be a bug."
  5902.                    irc-hacker))))
  5903.      ((= num 318)                 ; RPL_ENDOFWHOIS
  5904.       )
  5905.      ((= num 319)
  5906.       (cond ((string-match "^\\([^:]*:\\)?" txt)
  5907.          (let ((list (irc-listify
  5908.                   (irc-burst-comma
  5909.                    (irc-nuke-whitespace
  5910.                 (substring txt (match-end 0))))
  5911.                   ", " "and")))
  5912.            (irc-insert "%sis listening to channel%s %s,"
  5913.                    irc-msg-cont-used
  5914.                    (if (string-match " [^ ]" list) "s" "")
  5915.                    list)))
  5916.         (t (irc-insert (concat "%%Unknown 319 type reply message in"
  5917.                        " function irc-parse-RPL-3xx."))
  5918.            (irc-insert "%% \"%s\" (txt)." txt)
  5919.            (irc-insert "%% Please tell %s, it might be a bug."
  5920.                    irc-hacker))))
  5921.      ((= num 321)                       ; RPL_LISTSTART
  5922.       (irc-insert irc-list-header)
  5923.       (irc-insert irc-list-stroke)
  5924.       (setq irc-list-stats '(0 0))
  5925.       (set-buffer-modified-p (buffer-modified-p)))
  5926.      ((= num 322)                       ; RPL_LIST
  5927.       (if (not (string-match "^\\([^ ]+\\) \\([^ ]+\\) :" txt))
  5928.           (progn (irc-insert (concat "%%Unknown format on RPL_LIST"
  5929.                      " message; please tell %s.")
  5930.                  irc-hacker)
  5931.              (irc-insert "%% \"%s\" (txt)." txt)
  5932.              (irc-insert "%% Function irc-parse-RPL-3xx, at 322."))
  5933.         (let* ((chan (substring txt (match-beginning 1) (match-end 1)))
  5934.            (count (substring txt (match-beginning 2) (match-end 2)))
  5935.            (topic (irc-nuke-whitespace
  5936.                (substring txt (match-end 0))))
  5937.            (tmpline (format "%s   %2s   "
  5938.                     (irc-format-channel chan)
  5939.                     count))
  5940.            (top (irc-clean-up-message topic))
  5941.            (line (concat tmpline top))
  5942.            (irc-msg-cont-used (make-string (length tmpline) ? )))
  5943.           (if (or t (> (string-to-int count) 10))
  5944.           (let ((irc-msg-cont-used (make-string
  5945.                         (string-match "-* *$"
  5946.                               irc-list-stroke)
  5947.                         ? )))
  5948.             (setq irc-list-stats (list (1+ (car irc-list-stats))
  5949.                            (+ (nth 1 irc-list-stats)
  5950.                           (string-to-int count))))
  5951.             (irc-insert (irc-clean-up-message line)))))))
  5952.      ((= num 323)                       ; RPL_LISTEND
  5953.       (let ((ch (car irc-list-stats))
  5954.         (us (nth 1 irc-list-stats)))
  5955.         (if (and (zerop us) (zerop ch))
  5956.         (irc-insert "%%No visible channels.")
  5957.           (irc-insert (concat "%s%s user%s on the %s channel%s"
  5958.                   " which happen to be visible%s")
  5959.               irc-msg-info-pre
  5960.               (if (zerop us) "No" (int-to-string us))
  5961.               (if (= 1 us) "" "s")
  5962.               (if (zerop ch) "No" (int-to-string ch))
  5963.               (if (= 1 ch) "" "s")
  5964.               irc-msg-info-post)))
  5965.       (setq irc-list-stats '(0 0)))
  5966.      ((= num 324)                 ; RPL_CHANNELMODEIS
  5967.       (let* ((lst (if (irc-server-has-channelname-in-msgs)
  5968.               (if (string-match
  5969.                    (concat "^ *: *\\([^ ]+\\) +324" ;origin
  5970.                        " +\\([^ ]+\\)"    ;nick
  5971.                        " +\\([^ ]+\\)"    ;channel
  5972.                        " +\\(\\+[^ ]*\\)" ;mode
  5973.                        "\\( [-+]?[^ ]+\\)? *$") ;extra
  5974.                    str)
  5975.                   (list (subfield str 1) ;origin
  5976.                     (subfield str 2) ;nick
  5977.                     (subfield str 3) ;channel
  5978.                     (subfield str 4) ;mode (at least a "+")
  5979.                     (subfield str 5)))    ;limit (optional)
  5980.             (if (string-match
  5981.                  (concat "^ *: *\\([^ ]+\\) +324 +"
  5982.                      "\\([^ ]+\\) +\\(+[^ ]*\\)"
  5983.                      "\\( +[0-9]+\\)? *$")
  5984.                  str)
  5985.                 (list (subfield str 1) ;origin
  5986.                   (subfield str 2) ;nick
  5987.                   nil ;channel not given
  5988.                   (subfield str 3) ;mode (at least "+")
  5989.                   (subfield str 4))))) ;limit (optional)
  5990.          (orig (nth 0 lst))
  5991.          (nick (nth 1 lst))
  5992.          (channel (nth 2 lst))
  5993.          (mode (if lst (irc-nuke-whitespace (concat (nth 3 lst)
  5994.                                 (nth 4 lst)))))
  5995.          (expl (if lst (irc-explain-channel-mode mode 'skip-dir)))
  5996.          (chntxt (concat (if channel "The channel " "The channels")
  5997.                  (if channel
  5998.                      (concat
  5999.                       channel
  6000.                       "'"
  6001.                       (if (not (= ?s (aref channel
  6002.                                (1- (length
  6003.                                 channel)))))
  6004.                       "s"))
  6005.                    "")
  6006.                  " "))
  6007.          (irc-msg-cont-used (make-string (+ (length chntxt)
  6008.                             (length irc-msg-info-pre))
  6009.                          ? )))
  6010.         (if (not lst)
  6011.         (progn
  6012.           (irc-insert (concat "%%Received RPL_CHANNELMODEIS reply"
  6013.                       " in unknown format:"))
  6014.           (irc-insert "%% \"%s\" (str)." str)
  6015.           (irc-insert "%% In irc-parse-RPL-3xx at 324. Please tell %s."
  6016.                   irc-hacker))
  6017.           (progn
  6018.         (if (irc-is-nickname orig)
  6019.             (irc-remember orig 'irc-nicknames))
  6020.         (if (and (irc-is-hostname orig)
  6021.              (not (string= (upcase origin) (upcase orig))))
  6022.             (irc-remember orig 'irc-servernames))
  6023.         (irc-remember nick 'irc-nicknames)
  6024.         (if (or t (string= (upcase orig) (upcase irc-server)))
  6025.             (irc-insert "%s%smode%s %s %s%s"
  6026.                 irc-msg-info-pre
  6027.                 chntxt 
  6028.                 (if (string-match " and " expl) "s" "")
  6029.                 (if (string-match " and " expl) "are" "is")
  6030.                 expl
  6031.                 irc-msg-info-post)
  6032.           ;; Ignore MODE replies from remote servers.
  6033.           )))))
  6034.      ((= num 325)
  6035.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6036.      ((= num 329)            ;undernet: time of channe; creation
  6037.       (cond ((string-match "\\([^ ]+\\) +\\([^ ]+\\)$" txt) ;Undernet
  6038.          ;;(let ((chan (subfield txt 1))
  6039.          ;;    (time (subfield txt 2)))
  6040.          ;;(irc-insert "%sNYI: channel %s was created at <%s>%s"
  6041.          ;;        irc-msg-info-pre
  6042.          ;;        chan
  6043.          ;;        time
  6044.          ;;        irc-msg-info-post))
  6045.          )
  6046.         (t (irc-insert "%% Bad 329 message, txt=\"%s\"." txt))))
  6047.      ((= num 331)                       ; RPL_NOTOPIC
  6048.       (if (string= parorg "")    ;Not when message from remote (old)
  6049.           (if (string-match (concat "^\\([^ ]+\\) +: *No +topic"
  6050.                     " +is +set *.? *$")
  6051.                 txt)
  6052.           (irc-insert "%sNo topic is set for channel %s%s"
  6053.                   irc-msg-info-pre
  6054.                   (subfield txt 1)
  6055.                   irc-msg-info-post)
  6056.         (irc-insert "%sNo topic is set%s"
  6057.                 irc-msg-info-pre
  6058.                 irc-msg-info-post))))
  6059.      ((= num 332)                       ; RPL_TOPIC
  6060.       (cond ((and (irc-server-has-end-of-whois)
  6061.               (string-match "^\\([^ ]+\\) *:" txt))
  6062.          (irc-insert "%sThe topic for channel %s is \"%s\"%s"
  6063.                  irc-msg-info-pre
  6064.                  (irc-clean-up-message (subfield txt 1))
  6065.                  (irc-clean-up-message
  6066.                   (irc-nuke-whitespace
  6067.                    (substring txt (match-end 0))))
  6068.                  irc-msg-info-post))
  6069.         ((string-match ":?" txt)
  6070.          (irc-insert "%sThe topic is \"%s\"%s"
  6071.                  irc-msg-info-pre
  6072.                  (irc-clean-up-message (substring txt
  6073.                                   (match-end 0)))
  6074.                  irc-msg-info-post))
  6075.         (t (irc-insert "%sThe topic is \"%s\"%s"
  6076.                    irc-msg-info-pre
  6077.                    (irc-clean-up-message txt)
  6078.                    irc-msg-info-post))))
  6079.      ((= num 333)
  6080.       (cond ((string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([0-9]+\\)$" txt)
  6081.          (irc-insert "%sChannel %s created by %s%s"
  6082.                  irc-msg-info-pre
  6083.                  (subfield txt 1)
  6084.                  (subfield txt 2)
  6085.                  irc-msg-info-post))
  6086.         (t (irc-insert "%% Bad 333 message, txt=\"%s\"." txt))))
  6087.      ((= num 338)
  6088.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6089.      ((= num 339)
  6090.       (irc-insert "%s%s%s" irc-msg-info-pre txt irc-msg-info-post))
  6091.      ((= num 341)                       ; RPL_INVITING
  6092.       (string-match (concat "^:\\([^: ]+\\) +341 +[^: ]+ +\\([^: ]+\\) +"
  6093.                 "\\([^ ]+\\)")
  6094.             str)
  6095.       (let ((nick (subfield str 2))
  6096.         (channel (subfield str 3)))
  6097.         (irc-remember nick 'irc-nicknames)
  6098.         (irc-insert "%sYou are inviting user \"%s\" to channel %s%s"
  6099.             irc-msg-info-pre
  6100.             nick
  6101.             (irc-clean-up-message channel)
  6102.             irc-msg-info-post)))
  6103.      ((= num 351)                       ; RPL_VERSION | RPL_WHOREPLY
  6104.       (if (string-match "^\\([^: ]+\\) :?\\([^: ]+\\)" txt)
  6105.           (let ((s (substring txt (match-beginning 2) (match-end 2)))
  6106.             (v (substring txt (match-beginning 1) (match-end 1))))
  6107.         (if (not (string= (upcase origin) (upcase s)))
  6108.             (irc-remember s 'irc-servernames))
  6109.         (irc-insert (concat "%sIRC server %s is running version %s,"
  6110.                     " and the client you are using is %s%s")
  6111.                 irc-msg-info-pre
  6112.                 (upcase s)
  6113.                 v
  6114.                 irc-version
  6115.                 irc-msg-info-post))))
  6116.      ((= num 352)
  6117.       ;;(irc-parse-whoreply (format "WHOREPLY %s" txt))
  6118.       (cond ((= 0 irc-reply-count)
  6119.          (irc-insert irc-who-header)
  6120.          (irc-insert irc-who-stroke) 
  6121.          (setq irc-msg-cont-used (make-string
  6122.                       (string-match "-* *$"
  6123.                             irc-who-stroke)
  6124.                       ? ))))
  6125.       (setq irc-reply-count (1+ irc-reply-count))
  6126.       (if (string-match (concat "^\\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\\)"
  6127.                     " \\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\\)"
  6128.                     " :\\([0-9]+\\) \\(.+\\)$")
  6129.                 txt)
  6130.           (let* ((chan (subfield txt 1))
  6131.              (login (subfield txt 2))
  6132.              (client (subfield txt 3))
  6133.              (server (subfield txt 4))
  6134.              (nick (subfield txt 5))
  6135.              (mode (subfield txt 6))
  6136.              (unkn (subfield txt 7))
  6137.              (realname (subfield txt 8))
  6138.              (vsts (cond ((irc-recall nick 'irc-ignored-ppl) "IGNR")
  6139.                  ((string= "H"   mode) "    ") ;Norm
  6140.                  ((string= "G"   mode) "Away") ;Away
  6141.                  ((string= "H*"  mode) "Iopr") ;Iopr
  6142.                  ((string= "G*"  mode) "IoAw") ;IoAw
  6143.                  ((string= "H@"  mode) "Copr") ;Copr
  6144.                  ((string= "G@"  mode) "CoAw") ;CoAw
  6145.                  ((string= "H*@" mode) "ICop") ;ICop
  6146.                  ((string= "G*@" mode) "ICAw") ;ICAw
  6147.                  ((string= "S"   mode) "    ") ;Norm
  6148.                  (t mode))))
  6149.         (irc-insert "%-9s %-4s %-15s %s@%s \"%s\""
  6150.                 nick
  6151.                 vsts
  6152.                 chan
  6153.                 login
  6154.                 client
  6155.                 realname))))
  6156.      ((= num 353)                       ; RPL_NAMREPLY
  6157.       (if (or (string-match "^@ +\\([#&][^ ]+\\) +:?" txt)
  6158.           (string-match "^ *[=*] +\\([^ ]+\\) *:" txt))
  6159.           (let ((c (subfield txt 1))
  6160.             (n (substring txt (match-end 0))))
  6161.         (irc-parse-namreply
  6162.          (format "NAMREPLY placeholder %s %s" c n)))
  6163.         (irc-parse-namreply (format "NAMREPLY %s" txt))))
  6164.      ((= num 354)                       ; RPL_ENDOFNAMES
  6165.       (irc-insert "Names 354: %s" txt))
  6166.      ((= num 361)                       ; RPL_KILLDONE
  6167.       (string-match "^[^: ]+" txt)
  6168.       (irc-insert "%sYou have removed \"%s\" from IRC (/killed)%s"
  6169.               irc-msg-info-pre
  6170.               (substring txt (match-beginning 0) (match-end 0))
  6171.               irc-msg-info-post))
  6172.      ((= num 364)                 ; RPL_LINKS
  6173.       (if (not (or (string-match "^\\([^ ]*\\) \\([^ ]*\\) *:" txt)
  6174.                (string-match "^\\([^ ]*\\) *:" txt)))
  6175.           (progn
  6176.         (irc-insert "%%Error in parsing RPL 364, please tell %s:"
  6177.                 irc-hacker)
  6178.         (irc-insert "%% \"%s\" (txt)." txt)
  6179.         (irc-insert "%% In function irc-parse-RPL-3xx, at 364."))
  6180.         (let ((s (upcase (subfield txt 1)))
  6181.           (f2 (subfield txt 2))
  6182.           (info (irc-nuke-whitespace
  6183.              (irc-clean-up-message
  6184.               (substring txt (match-end 0))))))
  6185.           (setq irc-reply-count (1+ irc-reply-count))
  6186.           (let ((diff (irc-time-diff (irc-current-time)
  6187.                      irc-reply-count-time)))
  6188.         (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since last
  6189.                (> (nth 0 diff) 0)) ; display?
  6190.                (setq irc-reply-count-time (irc-current-time))
  6191.                (message (format " %d server%s ..."
  6192.                     irc-reply-count
  6193.                     (if (= 1 irc-reply-count)
  6194.                         ""
  6195.                       "s"))))))
  6196.           (irc-remember (format "Server %s%s: %s"
  6197.                     s
  6198.                     (if (string= "" f2)
  6199.                     ""
  6200.                       (format " (to %s)" (upcase f2)))
  6201.                     info) 
  6202.                 'irc-linksinfo)
  6203.           (if (not (string= (upcase origin) (upcase s)))
  6204.           (irc-remember s 'irc-servernames)))))
  6205.      ((= num 365)                 ; RPL_ENDOFLINKS
  6206.       (setq irc-reply-count 0)
  6207.       (message "")
  6208.       (irc-insert irc-links-header)
  6209.       (irc-insert irc-links-stroke)
  6210.       (set-buffer-modified-p (buffer-modified-p))
  6211.       (irc-recall-all-and-display 'irc-linksinfo
  6212.                       (progn (string-match "^[^: ]* ."
  6213.                                irc-links-header)
  6214.                          (match-end 0))
  6215.                       "servers"
  6216.                       "server") 
  6217.       (irc-forget-all 'irc-linksinfo))
  6218.      ((= num 366)                 ; RPL_NAMES_END
  6219.       (setq irc-reply-count 0)
  6220.       (message "")
  6221.       (if (irc-terminal-is-slow)
  6222.           (let ((lincnt 0)
  6223.             (usrcnt 0)
  6224.             (adjust 0)
  6225.             (w (irc-recall-all 'irc-namtree))
  6226.             (irc-msg-cont-used irc-names-cont-msg))
  6227.         (irc-insert "Name of channel  Users  Nicknames")
  6228.         (irc-insert "---------------  -----  ---------")
  6229.         (set-buffer-modified-p (buffer-modified-p))
  6230.         (while w
  6231.           (irc-insert "%s" (car w))
  6232.           (let* ((pair (if (string-match (concat "^ *\\([^ ]+\\) +"
  6233.                              "\\([0-9]+\\)")
  6234.                          (car w))
  6235.                    (cons (subfield (car w) 1)
  6236.                      (subfield (car w) 2))
  6237.                  (cons "" "0")))
  6238.              (ldiff (if (string= "PRIVATE" (upcase (car pair)))
  6239.                     1
  6240.                   0))
  6241.              (udiff (string-to-int (cdr pair))))
  6242.             (setq usrcnt (+ usrcnt udiff)
  6243.               lincnt (1+ lincnt)
  6244.               adjust (+ adjust ldiff)
  6245.               w (cdr w))))
  6246.         (let ((adjusted (- lincnt adjust)))
  6247.           (irc-insert (concat "%s%d visible user%s on %d visible"
  6248.                       " channel%s or on some private"
  6249.                       " channel%s")
  6250.                   irc-msg-info-pre
  6251.                   usrcnt
  6252.                   (if (= usrcnt 1) "" "s")
  6253.                   adjusted
  6254.                   (if (= adjusted 1) "" "s")
  6255.                   irc-msg-info-post)
  6256.           (irc-insert ""))
  6257.         (irc-forget-all 'irc-namtree))
  6258.         ;; Else fast terminal.
  6259.         (irc-insert "%sEnd of NAMES list%s"
  6260.             irc-msg-info-pre
  6261.             irc-msg-info-post)))
  6262.      ((= num 367)                       ; RPL_BANLIST
  6263.       (cond
  6264.        ((string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\) +\\(.+\\)$"
  6265.               txt)
  6266.         (let ((chan (subfield txt 1))
  6267.           (banned (subfield txt 2))
  6268.           (banner (subfield txt 3))
  6269.           (time (subfield txt 4)))
  6270.           (irc-insert "%sUser(s) \"%s\" are banned from %s by %s at %s%s"
  6271.               irc-msg-info-pre
  6272.               banned
  6273.               chan
  6274.               banner
  6275.               time
  6276.               irc-msg-info-post)))
  6277.        ((string-match "^\\([^ ]+\\) +\\(.+\\)$" txt)
  6278.         (let ((channel (subfield txt 1))
  6279.           (user (subfield txt 2)))
  6280.           (irc-insert (concat "%sUser(s) matching \"%s\""
  6281.                   " are banned from %s%s")
  6282.               irc-msg-info-pre user channel irc-msg-info-post)))
  6283.        (t (irc-insert "%%Unknown type 367 reply seen in irc-parse-RPL-3xx:")
  6284.           (irc-insert "%% \"%s\" (txt)" txt)
  6285.           (irc-insert "%% Please tell %s, it might be a bug."
  6286.               irc-hacker))))
  6287.      ((= num 368)                       ; RPL_BANLISTEND 
  6288.       (irc-insert (concat "%sEnd of list of banned users (who are"
  6289.                   " prohibited to join)%s")
  6290.               irc-msg-info-pre irc-msg-info-post))
  6291.      ((= num 369)                 ; RPL_ENDOFWHOWAS
  6292.       )
  6293.      ((= num 371)                       ; RPL_INFO
  6294.       (irc-insert "* %s" txt))
  6295.      ((= num 372)                       ; RPL_MOTD
  6296.       (cond
  6297.        ((string-match (concat "^ *: *\\([^: ]+\\)? +372 *\\([^: ]+\\)?"
  6298.                   " *: *Message-of-today +not +found +"
  6299.                   "in +server +\\([^: ]+\\) *$")
  6300.               str)
  6301.         (let* ((f (substring str (match-beginning 1) (match-end 1)))
  6302.            (frm (if (string= (upcase f) (upcase irc-server)) "" f))
  6303.            (at (substring str (match-beginning 3)
  6304.                   (match-end 3))))
  6305.           (if (not (string= (upcase origin) (upcase frm)))
  6306.           (irc-remember frm 'irc-servernames))
  6307.           (if (not (string= (upcase origin) (upcase at)))
  6308.           (irc-remember at 'irc-servernames))
  6309.           (irc-insert "%%%sNo message of the day at server %s."
  6310.               (if (string= frm "")
  6311.                   ""
  6312.                 (concat "(" frm ") "))
  6313.               (upcase at))))
  6314.        ((string-match (concat "^ *: *\\([^: ]+\\)? +372 *"
  6315.                   "\\([^: ]+\\)? *:? *"
  6316.                   "\\(start\\|end\\)?"
  6317.                   "\\( +at +server +\\)?"
  6318.                   "\\([A-Za-z.-.---]*\\|.*\\)"
  6319.                   "\\( *:\\)? *$")
  6320.               str)
  6321.         (let* ((from-1 (irc-non-num-to-0 (match-beginning 1)))
  6322.            (to-1 (irc-non-num-to-0 (match-end 1)))
  6323.            (from-2 (irc-non-num-to-0 (match-beginning 2)))
  6324.            (to-2 (irc-non-num-to-0 (match-end 2)))
  6325.            (from-3 (irc-non-num-to-0 (match-beginning 3)))
  6326.            (to-3 (irc-non-num-to-0 (match-end 3)))
  6327.            (from-4 (irc-non-num-to-0 (match-beginning 4)))
  6328.            (to-4 (irc-non-num-to-0 (match-end 4)))
  6329.            (from-5 (irc-non-num-to-0 (match-beginning 5)))
  6330.            (to-5 (irc-non-num-to-0 (match-end 5)))
  6331.            (from-6 (irc-non-num-to-0 (match-beginning 6)))
  6332.            (to-6 (irc-non-num-to-0 (match-end 6)))
  6333.            (server (substring str from-1 to-1))
  6334.            (user (substring str from-2 to-2))
  6335.            (direction (substring str from-3 to-3))
  6336.            (token (substring str from-4 to-4))
  6337.            (message (substring str from-5 to-5))
  6338.            (colon (substring str from-6 to-6)))
  6339.           (if (and (not (string= "" server))
  6340.                (not (string= (upcase origin) (upcase server))))
  6341.           (irc-remember server 'irc-servernames))
  6342.           (if (not (string= "" user))
  6343.           (irc-remember user 'irc-nicknames))
  6344.           (cond ((and (or (string= (downcase direction) "start")
  6345.                   (string= (downcase direction) "end"))
  6346.               (string-match "^ *at +server *$" token)
  6347.               (not (string= "" message))
  6348.               (string-match "^ *:$" colon)
  6349.               (not (string= (upcase origin)
  6350.                     (upcase message))))
  6351.              (irc-remember message 'irc-servernames))
  6352.             ((string-match "[^: ]" message)
  6353.              (irc-insert ">>> %s" (concat direction
  6354.                           token
  6355.                           message
  6356.                           colon))))))
  6357.        (t (irc-insert (concat "%%Unkown format on MOTD reply,"
  6358.                   " in function irc-parse-RPL-3xx,"
  6359.                   " num 372"))
  6360.           (irc-insert "%% \"%s\"." str))))
  6361. ;;;       ((= num 373)                       ; RPL_VERSION
  6362. ;;;        (irc-insert "DEBUG: RPL373 txt=\"%s\"." txt))
  6363.      ((= num 374)            ;RPL_INFO_END
  6364.       (irc-insert "%sEnd of information about this IRC server%s"
  6365.               irc-msg-info-pre irc-msg-info-post))
  6366.      ((= num 375)            ;RPL, start of MOTD
  6367.       (irc-insert ">>> %s" txt))
  6368.      ((= num 376)            ;RPL, end of MOTD
  6369.       (irc-insert "%sEnd of MOTD at %s%s"
  6370.               irc-msg-info-pre origin irc-msg-info-post))
  6371.      ((= num 377)
  6372.       (irc-insert ">>> %s" txt))
  6373.      ((= num 381)                       ; RPL_YOUREOPER
  6374.       (setq irc-operator " IOPR")
  6375.       (set-buffer-modified-p (buffer-modified-p))
  6376.       (irc-insert "%sOperator status for %s ENABLED%s"
  6377.               irc-msg-info-pre
  6378.               irc-nick-used
  6379.               irc-msg-info-post))
  6380.      ((= num 382)                       ; RPL_REHASHING
  6381.       (irc-insert "%sReread local ircd configuration information%s"
  6382.               irc-msg-info-pre
  6383.               irc-msg-info-post))
  6384. ;;;       ((= num 383)                       ; RPL_YOURESERVICE / Kim
  6385. ;;;        (irc-insert "DEBUG: RPL383, txt=\"%s\"." txt))
  6386. ;;;       ((= num 384)                       ; RPL_MYPORTIS / Kim
  6387. ;;;        (irc-insert "DEBUG: RPL384 txt=\"%s\"." txt))
  6388. ;;;       ((= num 385)            ; deop reply?
  6389. ;;;        (irc-insert "DEBUG: RPL385 txt=\"%s\"." txt))
  6390.      ((= num 391)                       ; RPL_TIME
  6391.       (setq irc-last-time (irc-get-time))
  6392.       (let* ((pair
  6393.           (if (string-match (concat
  6394.                      "^ *\\([^ :]+\\) *: *" ;srvr
  6395.                      "\\([A-Za-z][A-Za-z][A-Za-z]\\)"
  6396.                      "[A-Za-z]*day" ;weekday
  6397.                      " +\\(...\\)[^: ]* +" ;month
  6398.                      "\\([0-9]+\\) +"     ;monthday
  6399.                      "\\([0-9]+\\) +-* *") ;year
  6400.                     txt)
  6401.               (cons (subfield txt 1) 
  6402.                 (format "%s %s %s %s %s"
  6403.                     (substring txt (match-end 0)) ;clock
  6404.                     (subfield txt 2) ;weekday
  6405.                     (subfield txt 4) ;monthday
  6406.                     (subfield txt 3) ;month
  6407.                     (subfield txt 5))) ;year
  6408.             (progn (string-match "^\\([^: ]+\\) :" txt)
  6409.                (cons (subfield txt 1)
  6410.                  (irc-nuke-whitespace
  6411.                   (substring txt (match-end 0)))))))
  6412.          (server (car pair))
  6413.          (server (if (string= "" server) origin server))
  6414.          (date (irc-nuke-whitespace (cdr pair))))
  6415.         (irc-insert "%sLocal time at %s is %s%s%s"
  6416. ;;;             "%s%s%s local time is %s%s%s"
  6417.             irc-msg-info-pre
  6418.             (upcase server)
  6419. ;;;             (if (= ?S (aref (upcase server) (1- (length server))))
  6420. ;;;                 "'"
  6421. ;;;                 "'s")
  6422.             date
  6423.             (if (string= "0" irc-channel)
  6424.                 ""
  6425.               (concat " /" irc-channel))
  6426.             irc-msg-info-post)))
  6427.      ((or (= num 392)
  6428.           (= num 393))
  6429.       (irc-parse-notice (format ":%s NOTICE %s :%s"
  6430.                     origin user txt)))
  6431.      ((= num 394)
  6432.       (irc-insert "%sEnd of USERS at %s%s"
  6433.               irc-msg-info-pre origin irc-msg-info-post))
  6434.      ((= num 395)
  6435.       (irc-insert "%%No one logged in on Internet host %s" origin))
  6436.      (t                                 ; default
  6437.       (irc-insert (concat "%%Unrecognized numeric RPL 3xx message; "
  6438.                   "please tell %s:")
  6439.               irc-hacker)
  6440.       (irc-insert "%% str=\"%s\"." str)
  6441.       (irc-insert "%% Function irc-parse-RPL-3xx."))))
  6442.     ;; else
  6443.     (irc-insert (concat "%%Unrecognized nonnumeric RPL 3xx message follows; "
  6444.             "please tell %s:")
  6445.         irc-hacker)
  6446.     (irc-insert "%% \"%s\"." str)
  6447.     (irc-insert "%% Function irc-parse-RPL-3xx."))
  6448.   nil)
  6449.  
  6450.  
  6451. (defun irc-parse-topic (str)
  6452.   "Examine a TOPIC message from the IRC server.
  6453. TOPIC is sent to all of the users on a channel when someone changes the
  6454. topic of the channel.  Secret channels can not have the topic set.  TOPIC
  6455. messages are displayed as long as 'topic' is in irc-events, even if the user
  6456. changing the topic is being ignored.
  6457.  
  6458. This function returns t if a signal should be issued for the 'topic' event,
  6459. nil otherwise."
  6460.   (if (not (string-match "^:\\([^: ]+\\) +TOPIC +\\([^ ]*\\) *:" str))
  6461.       (progn (irc-insert "%%Unknown TOPIC command in irc-parse-topic:")
  6462.          (irc-insert "%% \"%s\"." str)
  6463.          (irc-insert "%% Please tell %s, it might be a bug." irc-hacker))
  6464.     (let* ((user (subfield str 1))
  6465.        (chnl (subfield str 2))
  6466.        (topic (substring str (match-end 0)))
  6467.        (old-chnl (let ((l (irc-recall-all 'irc-subscribed-channels)))
  6468.                (while (not (atom l))
  6469.              (setq l (if (irc-is-multijoinable-channel (car l))
  6470.                      (cdr l)
  6471.                    (car l))))
  6472.                (if (listp l) "" l)))
  6473.        (channel (if (string< "" chnl) chnl old-chnl)))
  6474.       (irc-remember user 'irc-nicknames)
  6475.       (irc-remember channel 'irc-subscribed-channels)
  6476.       (irc-insert (concat "%s%s has changed the topic of channel %s to \""
  6477.               (irc-clean-up-message topic)
  6478.               "\"%s")
  6479.           irc-msg-info-pre
  6480.           user
  6481.           channel
  6482.           irc-msg-info-post)
  6483.       (if (memq 'topic irc-events)
  6484.       (irc-signal user 'topic)))))
  6485.  
  6486.  
  6487. (defun irc-parse-wall (str)
  6488.   "Examine a WALL message from the IRC server.
  6489. WALL is sent by IRC operators to everyone on IRC.  A WALL message will
  6490. always be displayed even if the sender is being ignored.
  6491.  
  6492. This function returns t if a signal should be issued for the \"wall\" event,
  6493. nil otherwise."
  6494.   (if (not (string-match "^:? *\\([^: ]*\\) +WALL +:" str))
  6495.       (progn (irc-insert (concat "%%Internal error, function irc-parse-wall"
  6496.                  " called with a non-WALL message:"))
  6497.          (irc-insert "%% \"%s\"." str)
  6498.          (irc-insert "%%Please tell %s about it." irc-hacker)
  6499.          (irc-signal "<internal-error in irc-parse-wall>" 'wall))
  6500.       (let ((user (substring str (match-beginning 1) (match-end 1)))
  6501.         (msg (substring str (match-end 0))))
  6502.     (irc-remember user 'irc-nicknames)
  6503.     (irc-insert (concat (format irc-msg-wall
  6504.                     (concat " (" (irc-get-time) ") ")
  6505.                     user)
  6506.                 msg))
  6507.     (irc-signal user 'wall))))
  6508.  
  6509.  
  6510. (defun irc-parse-wallops (str)
  6511.   "Examine a WALLOPS message from the IRC server.
  6512. WALLOPS are sent by any user to all enabled operators on IRC. A WALLOPS will
  6513. allways be displayed, even if the sender is being ignores.
  6514.  
  6515. This function returns t if a signal should be issued for the \"wall\" event,
  6516. nil otherwise."
  6517.   (if (not (string-match "^: *\\([^: ]*\\) +WALLOPS +:" str))
  6518.       (progn (irc-insert (concat "%%Internal error, function irc-parse-wallops"
  6519.                  " called with a non-WALLOPS message:"))
  6520.          (irc-insert "%% \"%s\"." str)
  6521.          (irc-insert "%%Please tell %s about it." irc-hacker)
  6522.          (irc-signal "<internal-error in irc-parse-wallops>" 'wall))
  6523.       (let* ((sender (substring str (match-beginning 1) (match-end 1)))
  6524.          (msg (substring str (match-end 0))))
  6525.     (cond ((string-match (concat "^Remote 'CONNECT \\([^ ]+\\) +"
  6526.                      "\\([0-9]*\\)' from \\([^ ]+\\) *$")
  6527.                  msg)
  6528.            (let ((nsrv (substring msg (match-beginning 1) (match-end 1)))
  6529.              (port (substring msg (match-beginning 2) (match-end 2)))
  6530.              (user (substring msg (match-beginning 3) (match-end 3))))
  6531.          (cond ((irc-is-nickname user)
  6532.             (irc-remember user 'irc-nicknames))
  6533.                ((irc-is-hostname user)
  6534.             (irc-remember user 'irc-servernames)))
  6535.          (irc-insert (concat "%sTrying to establish a serverlink from"
  6536.                      " %s to %s on port %s on remote command"
  6537.                      " by user \"%s\"%s")
  6538.                  irc-msg-info-pre
  6539.                  (upcase sender)
  6540.                  (upcase nsrv)
  6541.                  port
  6542.                  user
  6543.                  irc-msg-info-post)))
  6544.           ((string-match (concat "Received SQUIT \\([^ ]+\\) +from"
  6545.                      " +\\(.+\\) *$")
  6546.                  msg)
  6547.            (let ((oded (substring msg (match-beginning 1) (match-end 1)))
  6548.              (orig (substring msg (match-beginning 2) (match-end 2))))
  6549.          (cond ((irc-is-nickname orig)
  6550.             (irc-remember orig 'irc-nicknames))
  6551.                ((irc-is-hostname orig)
  6552.             (irc-remember orig 'irc-servernames)))
  6553.          (irc-insert (concat "%sClosing the serverlink from %s to"
  6554.                      " server %s, by order of %s%s")
  6555.                  irc-msg-info-pre
  6556.                  (upcase sender)
  6557.                  (upcase oded) ;OD'ed server
  6558.                  (upcase orig)
  6559.                  irc-msg-info-post)))
  6560.           (t (let* ((head (format "%s%s" (concat
  6561.                           (format (format irc-msg-priv 0) 
  6562.                               (concat " ("
  6563.                                   (irc-get-time)
  6564.                                   ") ")
  6565.                               (concat sender
  6566.                                   " (WALLOPS)")))))
  6567.             (irc-msg-cont-used (make-string
  6568.                         (min
  6569.                          (length head)
  6570.                          (/ (window-width
  6571.                          (get-buffer-window
  6572.                           (current-buffer)))
  6573.                         2))
  6574.                         ? )))
  6575.            (cond ((and (irc-is-hostname sender)
  6576.                    (not (irc-is-nickname sender)))
  6577.               (irc-remember sender 'irc-servernames))
  6578.              ((irc-is-nickname sender)
  6579.               (irc-remember sender 'irc-nicknames)))
  6580.            (irc-insert (concat head (irc-clean-up-message msg))))))
  6581.     (if (irc-is-nickname sender)
  6582.         (irc-signal sender 'wall)
  6583.         (irc-later-execute-lusers)))))
  6584.  
  6585.  
  6586. (defun irc-parse-whoreply (str)
  6587.   "OBSELETE FUNCTION
  6588.  
  6589. Examine a WHOREPLY message from the IRC server.
  6590. The message is formatted into a line that is more easily understood than
  6591. the raw data.  
  6592. The status of the users is shown as a four letter word (:-) according to
  6593. the combination of their attributes. The possible attributes being
  6594. an IRC operator, being a channel operator and being marked away.
  6595.  
  6596.                                           Status field
  6597. A normal user having no attributes set:     (blank)
  6598. A normal user marked as being away:          Away
  6599. An IRC operator with no other attribues:     Iopr
  6600. An IRC operator marked as being away:        IoAw
  6601. A channel operator with no other attributes: Copr
  6602. A channel operator marked as being away:     CoAw
  6603. User being both IRC- and channel operator:   ICop
  6604. As above but also marked as being away:      ICAw
  6605.  
  6606. Being ignored takes precedence over all
  6607. other attributes, always shown as:           IGNR
  6608.  
  6609.  
  6610. No signals are issued for lines from the WHOREPLY."
  6611.   (string-match "^WHOREPLY +" str)
  6612.   (setq str (substring str (match-end 0)))
  6613.   (let ((is-header (or (string-match (concat "^\\* +User +Host +Server"
  6614.                          " +Nickname +S +: *Name *$")
  6615.                      str)
  6616.                (string-match (concat "^Channel +User +Host +Server"
  6617.                          " +Nickname +S +: *Name *$")
  6618.                      str)))
  6619.     (split))          ; make this a list of strings of each data item.
  6620.     ;; the elements of 'split' are:
  6621.     ;; 0 - full name (with possible hop count)
  6622.     ;; 1 - status
  6623.     ;; 2 - nickname
  6624.     ;; 3 - hostname of server
  6625.     ;; 4 - hostname of client
  6626.     ;; 5 - login name
  6627.     ;; 6 - channel
  6628.     (if (or (string-match (concat "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)"
  6629.                   " +\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)"
  6630.                   " +:\\([0-9]+\\)? *\\(.+\\)$")
  6631.               str))
  6632.     (let* ((channel (subfield str 1))
  6633.            (x-login-name (subfield str 2))
  6634.            (x-client-host (subfield str 3))
  6635.            (x-server-host (subfield str 4))
  6636.            (x-nickname (subfield str 5))
  6637.            (x-status (subfield str 6))
  6638.            (hop-count (subfield str 7))
  6639.            (x-full-name (subfield str 8))
  6640.            (name-col (string-match "-* *$" irc-who-stroke)) ;Last stroke
  6641.            (chan-col (string-match "-* +-+ *$" irc-who-stroke)) ;2nd last
  6642.            )
  6643.       (if (not (string= x-status "S")) ;Header?
  6644.           (progn
  6645.         ;; if it isn't the bogus header
  6646.         (irc-remember x-nickname 'irc-nicknames) ; add nick
  6647.         (if (and (not is-header)
  6648.              (irc-terminal-is-slow)
  6649.              (irc-server-has-end-of-who)
  6650.              (irc-nothing-remembered-p 'irc-whotree))
  6651.             (let ((irc-msg-cont-used
  6652.                (make-string name-col ? )))
  6653.               (irc-insert irc-who-header)
  6654.               (irc-insert irc-who-stroke)
  6655.               ;;(sit-for 0)
  6656.               (set-buffer-modified-p (buffer-modified-p))))
  6657.         (irc-remember x-server-host 'irc-servernames) ; hostnames.
  6658.         (irc-remember x-client-host 'irc-servernames)))
  6659.       (let* ((full-name (irc-clean-up-message
  6660.                  x-full-name))
  6661.          (nick-pad (make-string (max 0 (- (1- 10) (length x-nickname)))
  6662.                     ? ))
  6663.          (vsts (cond ((irc-recall x-nickname 'irc-ignored-ppl) "IGNR")
  6664.                  ((string= "H"   x-status) "    ") ;Norm
  6665.                  ((string= "G"   x-status) "Away") ;Away
  6666.                  ((string= "H*"  x-status) "Iopr") ;Iopr
  6667.                  ((string= "G*"  x-status) "IoAw") ;IoAw
  6668.                  ((string= "H@"  x-status) "Copr") ;Copr
  6669.                  ((string= "G@"  x-status) "CoAw") ;CoAw
  6670.                  ((string= "H*@" x-status) "ICop") ;ICop
  6671.                  ((string= "G*@" x-status) "ICAw") ;ICAw
  6672.                  ((string= "S"   x-status) "    ") ;Norm
  6673.                  (t (concat "\"" x-status "\""))))
  6674.          (vchnl (irc-format-channel
  6675.              (cond ((string= "-1" channel) "-")
  6676.                    ((string= "0" channel) "")
  6677.                    ((string= "*" channel) "")
  6678.                    (t channel))))
  6679.          (vusr (irc-clean-up-message x-login-name))
  6680.          (vclt (irc-clean-up-message x-client-host))
  6681.          (vsrv (irc-clean-up-message x-server-host))
  6682.           (line (format "%s%s %s %s <%s> %s@%s \"%s\" SERVER=%s"
  6683.                    x-nickname nick-pad vsts vchnl hop-count vusr
  6684.                    vclt full-name vsrv))
  6685.           (line (format "%s%s %s %s %s@%s \"%s\""
  6686.                    x-nickname nick-pad vsts vchnl vusr
  6687.                    vclt full-name))
  6688. ;         (line (format "%s%s %s %s@%s \"%s\""
  6689. ;                   x-nickname nick-pad vsts vusr vclt full-name))
  6690.          (irc-msg-cont-used (make-string 31 ? )))
  6691.         (if (and (irc-terminal-is-slow) (irc-server-has-end-of-who))
  6692.         (if (not is-header)
  6693.             (progn
  6694.               (setq irc-reply-count (1+ irc-reply-count))
  6695.               (let ((diff (irc-time-diff (irc-current-time)
  6696.                          irc-reply-count-time)))
  6697.             (cond ((or (> (nth 1 diff) 5) ;At least 5 seconds since
  6698.                    (> (nth 0 diff) 0)) ; last display?
  6699.                    (setq irc-reply-count-time (irc-current-time))
  6700.                    (message (format " %d nick%s ..."
  6701.                         irc-reply-count
  6702.                         (if (= 1 irc-reply-count)
  6703.                             ""
  6704.                             "s"))))))
  6705.               (irc-remember line 'irc-whotree)))
  6706.         (if is-header        ;No RPL_ENDOFWHO
  6707.             (let ((irc-msg-cont-used
  6708.                (make-string (string-match "-* *$" irc-who-stroke)
  6709.                     ? )))
  6710.               (irc-insert irc-who-header)
  6711.               (irc-insert irc-who-stroke))
  6712.             (irc-insert "%s" (irc-clean-up-message line))))))
  6713.     (irc-insert "%%Unkown WHOREPLY line: \"%s\"." str)))
  6714.     nil)
  6715.  
  6716.  
  6717. (defun irc-explain-channel-mode (mode &optional skip-direction)
  6718.   "Front end to irc-explain-mode."
  6719.   (irc-explain-mode mode 'channel skip-direction))
  6720.  
  6721.  
  6722. (defun irc-explain-user-mode (mode &optional skip-direction)
  6723.   "Front end to irc-explain-mode."
  6724.   (irc-explain-mode mode 'user skip-direction))
  6725.   
  6726.  
  6727. (defun irc-explain-mode (mode type &optional skip-direction)
  6728.   "Translate a channels MODE code into plain text. Use optional FLAG when
  6729. addition / removal information shouldn't be added."
  6730.   (let* ((known-modes '(((?a 0 "anonymous <A>")
  6731.              (?b 1 "ban (from channel) <B>" " of " " of ")
  6732.              (?i 0 "invite only <I>")
  6733.              (?k 1 "channel key <K> ")
  6734.              (?l 1 "limit number of users on channel <L>" " to ")
  6735.              (?m 0 "moderated <M>")
  6736.              (?n 0 "disallow nonlisteners to talk to channel <N>")
  6737.              (?o 1 "channel operator privilege <O>"
  6738.                    " for " " for ")
  6739.              (?p 0 "private <P>")
  6740.              (?s 0 "secret <S>")
  6741.              (?t 0 "topic lock <T>")
  6742.              (?v 1 "voice capability <V>" " to " " to "))
  6743.             .
  6744.             ((?i 0 "invisibility <I>")
  6745.              (?o 0 "IRC-operator <O>")
  6746.              (?s 0
  6747.               "subscription to local server status messages <S>")
  6748.              (?w 0 "subscription to WALLOPS <W>"))))
  6749.      (modes (cond ((eq type 'channel) (car known-modes))
  6750.               ((eq type 'user) (cdr known-modes))
  6751.               (t nil)))
  6752.      (cmds (if (string-match " +" mode) 
  6753.            (substring mode 0 (match-beginning 0))
  6754.            mode))
  6755.      (args (substring mode (length cmds)))
  6756.      (dir "added ")
  6757.      (argl ())
  6758.      (expl ""))
  6759.     (while (string-match "^ *\\([^: ]+\\)" args)
  6760.       (setq argl (append argl (list (subfield args 1)))
  6761.         args (substring args (match-end 1))))
  6762.     (while (not (string= cmds ""))
  6763.       (let ((c (string-to-char (substring cmds 0 1))))
  6764.     (cond ((= ?+ c) (setq dir "added "))
  6765.           ((= ?- c) (setq dir "removed "))
  6766.           (t (let ((p (assoc c modes)))
  6767.            (setq expl (concat expl
  6768.                       ", "
  6769.                       (if (not skip-direction) dir)
  6770.                       (if p
  6771.                       (nth 2 p)
  6772.                       (concat irc-msg-info-pre
  6773.                           "UNKNOWN '"
  6774.                           (char-to-string c)
  6775.                           "'"
  6776.                           irc-msg-info-post))
  6777.                       (cond ((and (string= dir "added ")
  6778.                           (nth 3 p))
  6779.                          (nth 3 p))
  6780.                         ((and (string= dir "removed ")
  6781.                           (nth 4 p))
  6782.                          (nth 4 p))
  6783.                         (t ""))
  6784.                       (let ((n (or (nth 1 p) 0))
  6785.                         (s ""))
  6786.                     (while (and (> n 0) (car argl))
  6787.                       (setq s (concat s (car argl))
  6788.                         argl (cdr argl)
  6789.                         n (1- n)))
  6790.                     s)))))))
  6791.       (setq cmds (substring cmds 1)))
  6792.     (concat (cond ((string-match "^\\(, *\\)[\000-\377]*\\(,\\) [^,]+" expl)
  6793.            (concat (substring expl (match-end 1) (match-beginning 2))
  6794.                " and"
  6795.                (substring expl (match-end 2))))
  6796.           ((string-match "^\\(, *\\)" expl)
  6797.            (substring expl (match-end 1)))
  6798.           ((string= expl "") (if skip-direction "normal" "none"))
  6799.           (t expl))
  6800.         (if (and (= (length argl) 1)
  6801.              (string-match "^[0-9]+$" (car argl)))
  6802.         (concat "; user limit is " (car argl))
  6803.         (progn (if (not (equal argl ()))
  6804.                (progn (irc-insert (concat "%%Warning: parts left"
  6805.                               " unparsed in function"
  6806.                               " irc-explain-mode."))
  6807.                   (irc-insert "%% \"%s\" (mode)." mode)
  6808.                   (irc-insert (concat "%% Please tell %s, it"
  6809.                               " might be a bug.")
  6810.                           irc-hacker))
  6811.                ""))))))
  6812.  
  6813. ;;;(defun irc-explain-who-mode (mode)
  6814. ;;;  ""
  6815. ;;;   (cond ((irc-recall x-nickname 'irc-ignored-ppl) "IGNR")
  6816. ;;;                 ((string= "H"   mode) "    ") ;Norm
  6817. ;;;                 ((string= "G"   mode) "Away") ;Away
  6818. ;;;                 ((string= "H*"  mode) "Iopr") ;Iopr
  6819. ;;;                 ((string= "G*"  mode) "IoAw") ;IoAw
  6820. ;;;                 ((string= "H@"  mode) "Copr") ;Copr
  6821. ;;;                 ((string= "G@"  mode) "CoAw") ;CoAw
  6822. ;;;                 ((string= "H*@" mode) "ICop") ;ICop
  6823. ;;;                 ((string= "G*@" mode) "ICAw") ;ICAw
  6824. ;;;                 ((string= "S"   mode) "    ") ;Norm
  6825. ;;;                 (t (concat "\"" mode "\""))))
  6826.  
  6827. (defun irc-ctcp-dequote (str)
  6828.   "Return STRING with quoted characters changed into the unquoted equivalents."
  6829.   (let ((new ""))
  6830.     (while (string-match "\\\\" str)    ;Get to next backslash, if any
  6831.       (let ((pos (match-beginning 0)))
  6832.     (if (>= (- (length str) pos) 2)
  6833.         (setq new (concat new
  6834.                   (substring str 0 pos)
  6835.                   (irc-ctcp-dequote-char (aref str (1+ pos))))
  6836.           str (substring str (+ 2 pos)))
  6837.         (irc-insert (concat "%%Received badly quoted CTCP string, ignored"
  6838.                 " superfluous backslash."))
  6839.         (setq new (concat new (substring str 0 pos))
  6840.           str (substring str (1+ pos))))))
  6841.     (concat new str)))
  6842.  
  6843.  
  6844. (defun irc-ctcp-dequote-char (char)
  6845.   "Map a two character STRING to it's corresponding character."
  6846.   (char-to-string (cond ((= char ?a) ?\001)
  6847.             ((= char ?\\) ?\\)
  6848.             (t char))))
  6849.  
  6850.  
  6851. (defun irc-ctcp-enquote (str)
  6852.   "Enquote a STRING, exchanging some characters to two character combinations."
  6853.   (let ((d "")
  6854.     (dirty "[\001\\]"))
  6855.     (while (string-match dirty str)
  6856.       (setq d (concat d
  6857.               (substring str 0 (match-beginning 0))
  6858.               (irc-ctcp-enquote-char (aref str (match-beginning 0))))
  6859.         str (substring str (match-end 0))))
  6860.     (concat d str)))
  6861.  
  6862.  
  6863. (defun irc-ctcp-enquote-char (char)
  6864.   "Map a character to it's corresponding one or two character STRING."
  6865.   (cond ((= char ?\001) "\\a")
  6866.     ((= char ?\\) "\\\\")
  6867.     (t (char-to-string char))))
  6868.  
  6869.  
  6870. (defun irc-lowlevel-dequote (str)
  6871.   "Return STRING with quoted characters changed into the unquoted equivalents."
  6872.   (let ((new ""))
  6873.     (while (string-match "\020" str)
  6874.       (let ((pos (match-beginning 0)))
  6875.     (if (< pos (1- (length str)))
  6876.         (setq new (concat new
  6877.                   (substring str 0 pos)
  6878.                   (irc-lowlevel-dequote-char (aref str (1+ pos))))
  6879.           str (substring str (+ 2 pos)))
  6880.         (setq new (concat new
  6881.                   (substring str 0 pos)
  6882.                   "<<ERROR in senders client: unquoted CNTRL/P>>")
  6883.           str "")
  6884.         )))
  6885.     (concat new str)))
  6886.  
  6887.  
  6888. (defun irc-lowlevel-dequote-char (char)
  6889.   "Map the CHARACTER after a \020 to it's corresponding character."
  6890.   (char-to-string (cond ((= char ?0) ?\000)
  6891.             ((= char ?n) ?\n)
  6892.             ((= char ?r) ?\r)
  6893.             ((= char ?\020) ?\020)
  6894.             (t char))))
  6895.  
  6896.  
  6897. (defun irc-lowlevel-enquote (str)
  6898.   "Enquote a STRING, exchanging some characters to two character combinations."
  6899.   (let ((d "")
  6900.     (dirty "[\000\n\r\020]"))
  6901.     (while (string-match dirty str)
  6902.       (setq d (concat
  6903.            d
  6904.            (substring str 0 (match-beginning 0))
  6905.            (irc-lowlevel-enquote-char (aref str (match-beginning 0))))
  6906.         str (substring str (match-end 0))))
  6907.     (concat d str)))
  6908.  
  6909.  
  6910. (defun irc-lowlevel-enquote-char (char)
  6911.   "Map a character to it's corresponding one or two character STRING."
  6912.   (cond ((= char ?\000) "\0200")
  6913.     ((= char ?\n) "\020n")
  6914.     ((= char ?\r) "\020r")
  6915.     ((= char ?\020) "\020\020")
  6916.     (t (char-to-string char))))
  6917.  
  6918.  
  6919. (defun irc-show-subscribed-channels ()
  6920.   "Show which channel's user is listening to, and which one is talked to."
  6921.   (if (not irc-multiple-leave-in-progress)
  6922.       (let ((listen (irc-clean-up-message
  6923.              (irc-listify
  6924.               (irc-recall-all 'irc-subscribed-channels)
  6925.               ", "
  6926.               "and"))))
  6927.     (cond ((irc-nothing-remembered-p 'irc-subscribed-channels)
  6928.            (cond ((string= "0" irc-channel)
  6929.               (irc-insert (concat "%sYou're neither listening nor"
  6930.                       " talking to any channel%s")
  6931.                   irc-msg-info-pre
  6932.                   irc-msg-info-post))
  6933.              (t (irc-insert (concat "%sYou're now talking and"
  6934.                         " listening to channel %s%s")
  6935.                     irc-msg-info-pre
  6936.                     irc-channel
  6937.                     irc-msg-info-post))))
  6938.           ((string= "0" irc-channel)
  6939.            (irc-insert (concat "%sYou're not talking to any channel, but"
  6940.                    " listening to %s%s")
  6941.                irc-msg-info-pre
  6942.                listen
  6943.                irc-msg-info-post))
  6944.           (t (let* ((part-1 (format "%sYou are now talking to channel "
  6945.                     irc-msg-info-pre))
  6946.             (irc-msg-cont-used (make-string (length part-1) ? )))
  6947.            (irc-insert "%s%s, while listening to %s%s"
  6948.                    part-1
  6949.                    irc-channel
  6950.                    listen
  6951.                    irc-msg-info-post)))))
  6952.       (set-buffer-modified-p (buffer-modified-p)))
  6953.   nil)
  6954.  
  6955.  
  6956. (defun irc-server-has-end-of-who ()
  6957.   "True if the current server end WHOREPLY with a \"end of list\" message."
  6958.   (or (> irc-major-version 2)
  6959.       (and (= irc-major-version 2)
  6960.        (>= irc-minor-version 4))))
  6961.  
  6962.  
  6963. (defun irc-server-has-end-of-names ()
  6964.   "True if the current server end NAMREPLY with a \"end of list\" message."
  6965.   (or (> irc-major-version 2)
  6966.       (and (= irc-major-version 2)
  6967.        (>= irc-minor-version 4))))
  6968.  
  6969.  
  6970. (defun irc-server-has-end-of-links ()
  6971.   "True if the current server end LINREPLY with a \"end of list\" message."
  6972.   (or (> irc-major-version 2)
  6973.       (and (= irc-major-version 2)
  6974.        (>= irc-minor-version 4))))
  6975.  
  6976.  
  6977. (defun irc-server-has-non-numeric-channel-names ()
  6978.   "True if the current server supports non nummeric IDs for channels."
  6979.   (or (> irc-major-version 2)
  6980.       (and (= irc-major-version 2)
  6981.        (or (> irc-minor-version 4)
  6982.            (and (= irc-minor-version 4)
  6983.             (>= irc-edit-version 2))))))
  6984.  
  6985.  
  6986. (defun irc-server-has-multijoinable-channels ()
  6987.   "True if the current server supports #-type channels and the commands JOIN
  6988. and PART. Probaly v2.6 or later."
  6989.   (or (> irc-major-version 2)
  6990.       (and (= irc-major-version 2)
  6991.        (>= irc-minor-version 6))))
  6992.  
  6993.  
  6994. (defun irc-server-has-channelname-in-msgs ()
  6995.   "True if the server gives the channels name in a RPL_CHANNELMODEIS message."
  6996.   (or (> irc-major-version 2)
  6997.       (and (>= irc-major-version 2)
  6998.        (or (> irc-minor-version 6)
  6999.            (and (>= irc-minor-version 6)
  7000.             (>= irc-edit-version 19))))))
  7001.  
  7002.  
  7003. (defun irc-server-has-end-of-whois ()
  7004.   "True if the server ends WHOIS replies with an enad marker."
  7005.   (or (> irc-major-version 2)
  7006.       (and (>= irc-major-version 2)
  7007.        (or (> irc-minor-version 6)
  7008.            (and (>= irc-minor-version 6)
  7009.             (>= irc-edit-version 20))))))
  7010.  
  7011.  
  7012. (defun irc-server-has-settable-topic-on-multijoinable-channel ()
  7013.   "True if the server supports setting topic for a multijoinable channel."
  7014.   (or (> irc-major-version 2)
  7015.       (and (>= irc-major-version 2)
  7016.        (>= irc-minor-version 7))))
  7017.  
  7018.  
  7019. (defun irc-active-servers ()
  7020.   "Return list of active IRC processes."
  7021.   (let ((lst (if (boundp 'irc-processes) irc-processes))
  7022.     (act nil))
  7023.     (while (consp lst)
  7024.       (if (and (memq (process-status (car lst)) '(open run))
  7025.            (stringp (buffer-name (process-buffer (car lst)))))
  7026.       (setq act (cons (car lst) act)))
  7027.       (setq lst (cdr lst)))
  7028.     (reverse act)))
  7029.  
  7030.  
  7031. (defun irc-host+port-to-buffer-name (host-name port-number)
  7032.   "Return a legal buffer name for a Kiwi session."
  7033.   (cond ((or (not (numberp port-number))
  7034.          (> 0 port-number)
  7035.          (> port-number 65535))
  7036.      (error (format "Kiwi: \"%s\" illegal TCP-port number" port-number)))
  7037.     (t (format "*Kiwi-%s/%d*" host-name port-number))))
  7038.  
  7039.  
  7040. (defun irc-host+port-to-buffer (host-name port-number)
  7041.   "Return the buffer a HOST-NAME in a Kiwi session is associated with.
  7042. If no such buffer exist, create it.
  7043.  
  7044. See also: irc-host-to-buffer-name <f>"
  7045.   (get-buffer-create (irc-host+port-to-buffer-name host-name port-number)))
  7046.  
  7047.  
  7048. (defun irc-session-to-buffer (session)
  7049.   "Convert a Kiwi SESSION (ie host name) to its associated buffer.
  7050. The buffer must exist."
  7051.   (get-buffer session))
  7052.  
  7053.  
  7054. (defun irc-session-names (proc-list)
  7055.   "Convert a LIST of Kiwi processes to a list of the processes host names."
  7056.   (mapcar (function (lambda (p)
  7057.          (buffer-name (process-buffer p))))
  7058.       proc-list))
  7059.  
  7060.  
  7061. (defun irc-get-host-from-session-name (session-name)
  7062.   "Extract the host name associated with a SESSION-NAME."
  7063.   (if (string-match irc-legal-session-name session-name)
  7064.       (subfield session-name 1)
  7065.       (error (format "Illegal session-name: \"%s\"." session-name))))
  7066.  
  7067.  
  7068. (defun irc-get-port-from-session-name (session-name)
  7069.   "Extract the TCP/IP port number associated with a SESSION-NAME."
  7070.   (if (string-match irc-legal-session-name session-name)
  7071.       (string-to-int (subfield session-name 2))
  7072.       (error (format "Illegal session-name: \"%s\"." session-name))))
  7073.  
  7074.  
  7075. (defun irc-terminal-is-slow ()
  7076.   "True if the terminal's speed (baud-rate) is lower than the variable
  7077. \"search-slow-speed\" (the variable is defined in either file loaddefs.el or
  7078. isearch.el in the lisp subdirectory)."
  7079.   (if (not (boundp 'search-slow-speed))    ;This should never happen.
  7080.       (progn (load "loaddefs"))
  7081.       (if (not (boundp 'search-slow-speed))
  7082.       (load "isearch"))
  7083.       (if (not (boundp 'search-slow-speed))
  7084.       (setq search-slow-speed 1200)))
  7085. ;;;  (if (boundp 'baud-rate)
  7086. ;;;      (<= baud-rate search-slow-speed)
  7087. ;;;    (<= (baud-rate) search-slow-speed))
  7088.   t)                    ;Patched.
  7089.  
  7090.  
  7091. (defun irc-non-num-to-0 (x)
  7092.   (if (numberp x)
  7093.       x
  7094.       0))
  7095.  
  7096.  
  7097. (defun irc-pong ()
  7098.   "Send a PONG message with the hostname as an argument.
  7099. This is usually used to answer a PING message."
  7100.   ;; it's interactive so it can be bound during testing.
  7101.   (interactive)
  7102.   (irc-send (concat "PONG :" (system-name)))
  7103.   (irc-who-is-on)
  7104.   nil)
  7105.  
  7106.  
  7107. (defun irc-new-scroll-step (scroll-step)
  7108.   "Calculate a new scroll-step value based on the current windows height
  7109. if terminal is slow (see function irc-terminal-is-slow)."
  7110.   (cond ((and (boundp 'irc-scroll-step)
  7111.           (numberp irc-scroll-step))
  7112.      irc-scroll-step)
  7113.     ((irc-terminal-is-slow)
  7114.      (let* ((h (- (window-height) 3))
  7115.         (x (- h (/ h 6))))
  7116.        (if (> window-min-height x)
  7117.            1
  7118.            (if (> (* 2 window-min-height) x)
  7119.            (/ x 2)
  7120.            x))))
  7121.     (t scroll-step)))        ;Else use old value.
  7122.  
  7123.  
  7124. (defun irc-last-found (str left-most char)
  7125.   "Search in STRING, position LEFT-MOST to end of string, for a CHARacter.
  7126. Return its position, or nil if not found."
  7127.   (let* ((n (length str))
  7128.      (m (while (and (>= n left-most)
  7129.             (not (= char (string-to-char (substring str n nil)))))
  7130.           (setq n (1- n)))))
  7131.     (if (>= n left-most) (1+ n) nil)))
  7132.  
  7133.  
  7134. (defun irc-choose-break-point (str left-most right-most delimiters)
  7135.   "Choose a nice point to break a string in. Break at a delimiting
  7136. character like space, bang or comma. Return a list of two strings,
  7137. the part before and the part after the breakpoint."
  7138.   (cond
  7139.     ((string-match "\n" str)
  7140.      (irc-split-string str (string-match "\n" str)))
  7141.     ((< (length str) right-most)
  7142.      (irc-split-string str (length str)))
  7143.     (t (let ((s (substring str 0 (1- right-most))))
  7144.      (if (or (null delimiters)
  7145.          (<= (min left-most (length str))
  7146.              0))
  7147.          (irc-split-string str (1- right-most))
  7148.          (let ((possible (irc-last-found s left-most (car delimiters))))
  7149.            (if possible
  7150.            (irc-split-string str possible)
  7151.            (irc-choose-break-point str
  7152.                        left-most
  7153.                        right-most
  7154.                        (cdr delimiters)))))))))
  7155.  
  7156.  
  7157. (defun irc-split-string (str n)
  7158.   "Split string STR into two at position N, trimming all white space
  7159. around the split point."
  7160.   (let* ((x (min n (length str)))
  7161.      (first-half (substring str 0 x))
  7162.      (second-half (substring str x))
  7163.      (a (progn (string-match "[\n\t ]*$" first-half)
  7164.            (match-beginning 0)))
  7165.      (b (progn (string-match "^[\n\t ]*" second-half)
  7166.            (match-end 0))))
  7167.     (cons (substring first-half 0 a)
  7168.       (substring second-half (match-end 0)))))
  7169.  
  7170.  
  7171. (defun irc-insert (format &rest args)
  7172.   "Insert before irc-mark the string created by FORMAT with substituted ARGS.
  7173. Resets the global variable \"scroll-step\" each time. If the string is to long
  7174. to be inserted on one line, insert just first part and give the rest to
  7175. \"irc-insert-more\"."
  7176.   (setq scroll-step (irc-new-scroll-step scroll-step))
  7177.   (let* ((str (apply 'format format args))
  7178.      (strlen (length str))
  7179.      (left-most (* (/ (window-width (get-buffer-window (current-buffer)))
  7180.               3)
  7181.                2))
  7182.      (splitted (irc-choose-break-point
  7183.             str
  7184.             left-most
  7185.             (window-width (get-buffer-window (current-buffer)))
  7186.             '(?, ?  ?\050 ?! ?? ?. ?\051)))
  7187.      (first-half (car splitted))
  7188.      (second-half (cdr splitted)))
  7189.     (save-excursion
  7190.       (goto-char (if (and (boundp 'irc-mark) (markerp irc-mark))
  7191.              irc-mark
  7192.              (point-max)))
  7193.       (insert-before-markers first-half "\n")
  7194.       (if (not (string= "" second-half))
  7195.       (irc-insert-more irc-msg-cont-used left-most second-half)))))
  7196.  
  7197.  
  7198. (defun irc-insert-more (continue left-most str)
  7199.   "Insert before irc-mark the line created by concatenating the CONTINUE string
  7200. and the MESSAGE string. If the line is to long, insert the first part and 
  7201. recurse with the rest."
  7202.   (let* ((cont (substring continue 0 (min (/ (* 3 (window-width
  7203.                            (get-buffer-window
  7204.                             (current-buffer))))
  7205.                          4)
  7206.                       (length continue))))
  7207.      (splitted (irc-choose-break-point str ;;QUICK ugly bug fix.... bleah!
  7208.                        (max 0 (- left-most (length cont)))
  7209.                        (- (window-width (get-buffer-window
  7210.                                  (current-buffer)))
  7211.                           (length cont))
  7212.                        '(?, ?  ?\( ?! ?? ?. ?;)))
  7213.      (first-half (concat cont (car splitted)))
  7214.      (second-half (cdr splitted)))
  7215.     (insert-before-markers first-half "\n")
  7216.     (if (not (string= "" second-half))
  7217.     (irc-insert-more cont left-most second-half))))
  7218.  
  7219.  
  7220. (defun irc-fix-wordwrap (line1 line2)
  7221.   "With arguments LINE1 and LINE2 apply some simple heuristics to see if the
  7222. line which they originally formed was broken in an acceptable place.  Returns
  7223. a dotted pair with LINE1 as the car and LINE2 as the cdr."
  7224.   (cond ((string-match "^ +" line2)
  7225.          ;; broke at whitespace; strip leading space from next line
  7226.          (setq line2 (substring line2 1)))
  7227.         ((string-match " +$" line1)
  7228.          ;; trailing whitespace on line.  might as well just nuke it all.
  7229.          (setq line1 (substring line1 0 (match-beginning 0))))
  7230.         ((string-match "\\( +\\)[^: ]+$" line1)
  7231.          ;; broke in a word, but it's wrappable.  just eat one space.
  7232.          (setq line2 (concat (substring line1 (1+ (match-beginning 1))) line2)
  7233.                line1 (substring line1 0 (match-beginning 0)))))
  7234.   (cons line1 line2))
  7235.  
  7236.  
  7237.  
  7238. ;; simple key functions -- self-insert, tab, destructive backspace
  7239. (defun irc-self-insert (arg)
  7240.   "Normaly just inserts the typed character in the input region.
  7241. If point is in the output region, irc-spacebar-pages is non-nil and a space
  7242. is typed, scroll-up otherwise point moves to end of input region and inserts
  7243. the character.
  7244.  
  7245. If the character to be inserted is a colon or semi-colon and it is the first
  7246. non-white space character on the line then the input region is updated to
  7247. begin with the last explicit sendlist, irc-last-explicit.
  7248.  
  7249. Inserts the character ARG times if self-inserting.  An argument is not
  7250. passed to scroll-up if paging with the spacebar."
  7251.   (interactive "p")
  7252.   (let* ((in-region (>= (point) irc-mark))
  7253.      (mapped (assoc last-command-char
  7254.             '((?\100 . ?\311)
  7255.               (?\133 . ?\304)
  7256.               (?\134 . ?\326)
  7257.               (?\135 . ?\305)
  7258.               (?\136 . ?\334)
  7259.               (?\140 . ?\351)
  7260.               (?\173 . ?\344)
  7261.               (?\174 . ?\366)
  7262.               (?\175 . ?\345)
  7263.               (?\176 . ?\374))))
  7264.      (invmapped (assoc last-command-char
  7265.                '((?\100 . ?\311)
  7266.                  (?\133 . ?\344)
  7267.                  (?\134 . ?\366)
  7268.                  (?\135 . ?\345)
  7269.                  (?\136 . ?\334)
  7270.                  (?\140 . ?\351)
  7271.                  (?\173 . ?\304)
  7272.                  (?\174 . ?\326)
  7273.                  (?\175 . ?\305)
  7274.                  (?\176 . ?\374))))
  7275.      (chr (if (and irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1
  7276.                mapped)
  7277.           (cdr (if (eq t irc-map-keyboard-ISO-646-SE2-to-ISO-8859-1)
  7278.                mapped
  7279.              invmapped))
  7280.           last-command-char))
  7281.          ;; it's times like this that i wish someone would tell me what
  7282.          ;; a good indentation style is for this expression
  7283.          (expand-colon
  7284.           (and
  7285.        (or (= last-command-char ?\;) (= last-command-char ?:))
  7286.            (string-match "^ *$"
  7287.              (buffer-substring
  7288.               irc-mark
  7289.               (if in-region (point) (point-max)))))))
  7290.     (if (not expand-colon)
  7291.         (if in-region
  7292.         (while (> arg 0)
  7293.           (insert chr)
  7294.           (setq arg (1- arg)))
  7295.         ;; else
  7296.         (if (and irc-spacebar-pages
  7297.              (= last-command-char 32))
  7298.         ;; it's nice to be able to return to the input region just by
  7299.         ;; pounding on the spacebar repeatedly.
  7300.         (condition-case EOB (scroll-up nil)
  7301.           (end-of-buffer (goto-char (point-max))))
  7302.         (goto-char (point-max))
  7303.         (while (> arg 0)
  7304.           (insert chr)
  7305.           (setq arg (1- arg)))))
  7306.     (or in-region (goto-char (point-max)))
  7307.     ;; Kill white space. This also takes out previous lines in
  7308.     ;; input region.
  7309.     (delete-region irc-mark (point))
  7310.     (insert (if (= last-command-char ?:) irc-last-private irc-last-explicit))
  7311.     ;; put in the extra characters if need be.
  7312.     (setq arg (1- arg))
  7313.     (while (> arg 0)
  7314.       (insert chr)
  7315.       (setq arg (1- arg))))))
  7316.  
  7317.  
  7318. (defun irc-del-backward-char (arg)
  7319.   "If in the input region, delete ARG characters before point, restricting
  7320. deletion to the input region.  If in the output region and irc-spacebar-pages
  7321. then scroll-down (aka window-back) otherwise do nothing."
  7322.   (interactive "p")
  7323.   (if (> (point) irc-mark)
  7324.       ;; only delete as far back as irc-mark at most
  7325.       (if (> arg (- (point) irc-mark)) (delete-region (point) irc-mark)
  7326.       (delete-backward-char arg))
  7327.       (if (and (<= (point) irc-mark) irc-spacebar-pages) (scroll-down nil)
  7328.       (ding))))
  7329.  
  7330.  
  7331. (defun irc-tab ()
  7332.   "If point is in the input region then tab-to-tab-stop.  If it is in the
  7333. output region, go to the previous line if irc-spacebar-pages; do nothing
  7334. otherwise."
  7335.   (interactive)
  7336.   (if (>= (point) irc-mark) (tab-to-tab-stop)
  7337.       (if irc-spacebar-pages (previous-line 1)
  7338.       (ding))))
  7339.  
  7340.  
  7341.  
  7342. ;; top-level -- entry, sentinel and mode
  7343. (defun irc (&optional universal-argument)
  7344.   "Enter the Internet Relay Chat conferencing system.
  7345. If no connexion to an irc-server is open, then one is started.  If no buffer
  7346. *IRC* exists then it is created otherwise the existing buffer is used.  If
  7347. a connexion is already active then the most recently started IRC session
  7348. is switched to in the current window.  This makes binding 'irc' to a key
  7349. much more convenient.
  7350.  
  7351. With prefix argument NEW-BUFFER, another *IRC* buffer is created and a
  7352. new IRC session is started.  This is provided so that multiple IRC
  7353. sessions can co-exist in one Emacs, which is sometimes a useful thing."
  7354.   (interactive "P")
  7355.   (let* ((act (irc-active-servers))
  7356.      (session-names (irc-session-names act))
  7357.      (number-of-sessions (length session-names))
  7358.      (ask-for-session (> number-of-sessions 1))
  7359.      (session (let ((s (if ask-for-session
  7360.                    (irc-nuke-whitespace
  7361.                 (irc-read-object
  7362.                  "Select which Kiwi session? (RET for new) "
  7363.                  ""
  7364.                  session-names))
  7365.                    "")))
  7366.             (if (or (irc-member-general s
  7367.                         session-names
  7368.                         'string=)
  7369.                 (string= "" s))
  7370.             s
  7371.             (error (format "No such active session: %s" s)))))
  7372.      (ask-for-host (or universal-argument
  7373.                (= 0 number-of-sessions)
  7374.                (and ask-for-session
  7375.                 (string= "" session))))
  7376.      (host (downcase
  7377.         (cond
  7378.           (ask-for-host
  7379.            (let ((h (irc-nuke-whitespace
  7380.                  (read-string
  7381.                   (concat "Connect new Kiwi session to which"
  7382.                       " internet host? (RET for "
  7383.                       irc-server
  7384.                       ") ")))))
  7385.              (if (string= "" h) irc-server h)))
  7386.           (ask-for-session
  7387.            (irc-get-host-from-session-name session))
  7388.           ((= 1 number-of-sessions)
  7389.            (irc-get-host-from-session-name (car session-names)))
  7390.           (t ""))))
  7391.      (port (cond
  7392.          (ask-for-host
  7393.           (let* ((p (irc-nuke-whitespace
  7394.                  (read-string
  7395.                   (concat "Use which TCP port for new connection?"
  7396.                       " (RET for "
  7397.                       (int-to-string irc-port)
  7398.                       ", * for 194) "))))
  7399.              (n (string-to-int p)))
  7400.             (cond ((string= "*" p) 194)
  7401.               ((string= "" p) irc-port)
  7402.               ((and (> n 0) (> 65535 n)) n)
  7403.               (t (error "Illegal TCP port")))))
  7404.          (ask-for-session
  7405.           (irc-get-port-from-session-name session))
  7406.          ((= 1 number-of-sessions)
  7407.           (irc-get-port-from-session-name (car session-names)))
  7408.          (t nil)))
  7409.      (buffer (irc-host+port-to-buffer host port)))
  7410.     (make-variable-buffer-local 'irc-port)
  7411.     (setq irc-port port)
  7412.     (switch-to-buffer buffer)
  7413.     (if (not (get-buffer-process (current-buffer)))
  7414.     (progn
  7415.       (goto-char (point-max))
  7416.       (irc-mode)
  7417.       (irc-insert "")
  7418.       (irc-insert "")
  7419.       (irc-insert "%s for GNU Emacs v18.57 and around...." irc-version)
  7420.       (irc-insert "Comments to %s." irc-hacker)
  7421.       (irc-insert "")
  7422.       (condition-case NOT-IRCED
  7423.           (let ((proc (open-network-stream
  7424.                "irc" buffer host port)))
  7425.         (set-process-filter proc 'irc-filter)
  7426.         (set-process-sentinel proc 'irc-sentinel)
  7427.         (setq irc-server host)
  7428.         (setq-default irc-server host)
  7429.         (irc-send (concat "NICK " irc-nick))
  7430.         (irc-send (format "USER %s %s %s :%s"
  7431.                   (user-login-name)
  7432.                   (system-name)
  7433.                   irc-server
  7434.                   (or (getenv "IRCNAME")
  7435.                       (getenv "NAME")
  7436.                       (user-full-name)
  7437.                       "<<USERNAME UNKNOWN>>")))
  7438.         ;; a new process, so initialize the variables.  they aren't set
  7439.         ;; in irc-mode so that irc-mode can be called at any time.
  7440.         ;; (irc-remember irc-nick 'irc-nicknames)
  7441.         (let ((s (irc-recall-all 'irc-services)))
  7442.           (while (and (listp s) s)
  7443.             (irc-remember (car s) 'irc-nicknames)
  7444.             (setq s (cdr s))))
  7445.         (irc-remember irc-server 'irc-servernames)
  7446.         (setq irc-nick-used ".Not.connected.yet."
  7447.               irc-major-version 0
  7448.               irc-minor-version 0
  7449.               irc-edit-version 0
  7450.               irc-motd-lines nil
  7451.               irc-list-stats '(0 0)
  7452.               irc-away nil
  7453.               irc-channel "0"
  7454.               irc-history-index -1
  7455.               irc-operator nil
  7456.               irc-scratch ""
  7457.               irc-last-command  ""
  7458.               irc-last-explicit "*;"
  7459.               irc-last-private "*;"
  7460.               irc-last-time (irc-get-time)
  7461.               ;; this next bit of messiness just ups irc-last-stamp
  7462.               ;; in an effort to make nice numbers out of the time
  7463.               ;; stamps -- ie, if the time is now 13:53 with an
  7464.               ;; interval of 15 minutes, this makes it 13:45
  7465.               irc-last-stamp 0
  7466.               irc-total-time (string-to-int
  7467.                       (substring irc-last-time 3))
  7468.               irc-last-stamp (if (zerop irc-time-stamp)
  7469.                      0
  7470.                      (while (< (+ irc-last-stamp
  7471.                               irc-time-stamp)
  7472.                            irc-total-time)
  7473.                        (setq irc-last-stamp
  7474.                          (+ irc-last-stamp
  7475.                             irc-time-stamp)))
  7476.                      irc-last-stamp)
  7477.               irc-last-notify irc-last-stamp
  7478.               irc-processes (cons proc irc-processes))
  7479.         (irc-send "CLIENT-START"))
  7480.         (error
  7481.          (irc-insert (concat "%%Couldn't connect to the TCP/IP"
  7482.                  " port %s at the internet host %s --"
  7483.                  " sorry: %s")
  7484.              port
  7485.              host
  7486.              NOT-IRCED)
  7487.          ))))))
  7488.  
  7489.  
  7490. (defun irc-mode ()
  7491.   "To understand some documentation given with irc-mode variables and
  7492. functions, \"output region\" is defined as everything before the irc-mark.
  7493. irc-mark is a marker kept by irc-mode to know where to insert new text
  7494. from IRC.  Text in the output region cannot be modified by the most common
  7495. methods of typing a self-inserting character or pressing delete.
  7496.  
  7497. The input region is everything which follows irc-mark.  It is what
  7498. gets processed by irc-mode when you type LFD or RET.  If irc-spacebar-pages
  7499. is non-nil, the following keys are in effect when the cursor is in the
  7500. output region:
  7501.  
  7502. SPC             scroll-forward       DEL     scroll-backward
  7503. LFD or RET      next-line            TAB     previous-line
  7504.  
  7505. Local keys:
  7506. \\{irc-mode-map}"
  7507.   (interactive)
  7508.   (setq buffer-offer-save t)
  7509.   (kill-all-local-variables)
  7510.   (setq major-mode 'irc-mode
  7511.     mode-name "Kiwi"
  7512.     fill-column (- (window-width (get-buffer-window (current-buffer))) 5))
  7513.   (set (make-local-variable 'irc-away) nil) ; for the mode-line
  7514.   (set (make-local-variable 'irc-channel) nil) ; for sendlists and broken PRIVMSGs
  7515.   (set (make-local-variable 'irc-edit-version) nil) ; edit version number of server
  7516.   (set (make-local-variable 'irc-history-index) nil) ; for the message history
  7517.   (set (make-local-variable 'irc-last-command) nil) ; for the command history
  7518.   (set (make-local-variable 'irc-last-explicit) nil) ; for sendlist ; auto-expansion
  7519.   (set (make-local-variable 'irc-last-private) nil) ; for sendlist : auto-expansion
  7520.   (set (make-local-variable 'irc-last-stamp) nil) ; for time-sentinel
  7521.   (set (make-local-variable 'irc-last-time) nil) ;
  7522.   (set (make-local-variable 'irc-list-stats) nil) ; for RPL_LIST statistics (temp)
  7523.   (set (make-local-variable 'irc-major-version) nil) ; major version number of server
  7524.   (set (make-local-variable 'irc-minor-version) nil) ; major version number of server
  7525.   (set (make-local-variable 'irc-nick-used) nil) ; the nick used at the server
  7526.   (set (make-local-variable 'irc-operator) nil)    ; for special privileges
  7527.   (set (make-local-variable 'irc-scratch) nil) ; for accumulating server messages
  7528.   (set (make-local-variable 'irc-total-time) nil) ;
  7529.   (set (make-local-variable 'irc-count-incoming-messages) 0)
  7530.   (set (make-local-variable 'irc-idle-last-sent) -1)
  7531. ;;;  (set (make-local-variable 'irc-idle-scratch-file)
  7532. ;;;       (expand-file-name
  7533. ;;;    (concat (make-temp-name "/tmp/.Kiwi.")
  7534. ;;;        "."
  7535. ;;;        (user-login-name)
  7536. ;;;        ".may-safely-be-deleted-anytime")))
  7537. ;;;  (if (file-exists-p irc-idle-scratch-file)
  7538. ;;;      (delete-file irc-idle-scratch-file))
  7539.   (set (make-local-variable 'irc-ignored-ppl) ;Nicks actually ignored
  7540.        (irc-create-new-hash-table 7))
  7541.   (set (make-local-variable 'irc-last-NOTICE-rcv) "")
  7542.   (set (make-local-variable 'irc-last-NOTICE-src) "")
  7543.   (set (make-local-variable 'irc-links-header) "Known server links.")
  7544.   (set (make-local-variable 'irc-links-stroke) "-------------------")
  7545.   (set (make-local-variable 'irc-linksinfo) ; for LINREPLY & RPL364 data (temp)
  7546.        (irc-create-new-hash-table 149))    ;2*(65-70 seen links, oct -91)
  7547.   (set (make-local-variable 'irc-list-header) "Name of channel  Users Topic")
  7548.   (set (make-local-variable 'irc-list-stroke) "---------------  ----- -----")
  7549.   (set (make-local-variable 'irc-listtree) ; for RPL_LIST 322 data (temp)
  7550.        (irc-create-new-hash-table 163))    ;2*(50-80 channels, oct -91)
  7551.   (set (make-local-variable 'irc-msg-cont-used) irc-msg-cont)
  7552.   ;; Indentation for continued long lines when displaying NAMREPLY's.
  7553.   (set (make-local-variable 'irc-names-cont-msg) (make-string 24 ? ))
  7554.   (set (make-local-variable 'irc-notify-looked-for)
  7555.        (irc-create-new-hash-table 149))
  7556.   (set (make-local-variable 'irc-notify-detected)
  7557.        (irc-create-new-hash-table 149))
  7558.   (set (make-local-variable 'irc-namtree) ; for NAMREPLY data (temp)
  7559.        (irc-create-new-hash-table 853))    ;2*(200-400 users, oct -91)
  7560.   (set 'irc-nicknames            ; for sendlists
  7561.        (irc-create-new-hash-table 853)) 
  7562.   (set 'irc-servernames            ; for server completion
  7563.        (irc-create-new-hash-table 997))    ;2*((60-70 seen links)+(200-400usrs))
  7564.   (set (make-local-variable 'irc-subscribed-channels) ; channels we listen to
  7565.        (irc-create-new-hash-table 7))    ;max 11
  7566.   (set (make-local-variable 'irc-services) ; for services like NICKSERV
  7567.        (irc-create-new-hash-table 17))
  7568.   (set (make-local-variable 'irc-who-header)
  7569.        (concat "Nickname  Stat Channel name   "
  7570.            " <Hop count> Login@Client \"Real name\" SERVER=srvr"))
  7571.   (set (make-local-variable 'irc-who-header)
  7572.        (concat "Nickname  Stat Random channel  Whatever@clientmachine \"Real name\""))
  7573.   (set (make-local-variable 'irc-who-stroke)
  7574.        (concat "--------  ---- --------------  "
  7575.            "------------------------------------------------"))
  7576.   (set (make-local-variable 'irc-whotree) ; for WHOREPLY data (temp)
  7577.        (irc-create-new-hash-table 853))    ;(200-400 users, oct -91)
  7578.   (set (make-local-variable 'mode-line-format)
  7579.        (list (purecopy "--- %14b ")
  7580.          'global-mode-string
  7581.          (purecopy " %[(")
  7582.          'mode-name 'minor-mode-alist 'irc-operator
  7583.          (purecopy ")%] ")
  7584.          'irc-nick-used ":" 'irc-channel
  7585.          " " 'irc-away (purecopy "-%-")))
  7586.   ;; too many ways to get unbalanced parens (most notably ":-)")
  7587.   (set (make-local-variable 'blink-matching-paren) nil)
  7588.   ;; as closest we can come to "natural" terminal scrolling
  7589.   (set (make-local-variable 'scroll-step) 1) ; Reset in irc.
  7590.   (set-marker (set (make-local-variable 'irc-mark) (make-marker)) (point-max))
  7591.   (let ((nicks irc-ignores))
  7592.     (while (not (null nicks))
  7593.       (irc-remember (car nicks) 'irc-ignored-ppl)
  7594.       (setq nicks (cdr nicks))))
  7595.   (let ((services '(;;"AMIGASERV"
  7596.             ;;"ARSKA"        ;TZoper of #42.
  7597.             ;;"CDSERV"
  7598.             ;;"CONVSERV"    ;Convert from Celsius to Fahrenheit etc
  7599.             ;;"EU-OPER"        ;TZoper of #Eu-opers.
  7600.             "IRCIIHELP"        ;Help automaton for ircII commands
  7601.             ;;"JIRCC"        ;Japanese Kanjii/ASCII translator
  7602.             ;;"MSGSERV"        ;Stores and forwards user-user messages
  7603.             "NICKSERV"        ;Register for nick names
  7604.             ;;"NOTE-NO"
  7605.             ;;"NOTESERV"    ;"Wait for user" and "store messages".
  7606.             ;;"SWEDESERV"
  7607.             ;;"TZOPER"        ;Copr ioprs on #Twilight_Zone
  7608.             ;;"WEBSERV"
  7609.             )))
  7610.     (while services
  7611.       (irc-remember (car services) 'irc-services)
  7612.       (irc-remember (car services) 'irc-nicknames)
  7613.       (setq services (cdr services))))
  7614.   (buffer-enable-undo)
  7615.   (irc-wrap-display-time)
  7616.   (turn-on-auto-fill)
  7617.   ;; "invisible subwindows" or whatever you would like to call them would be
  7618.   ;; nice.  That way I could make the output-region read-only.  The two things
  7619.   ;; most likely to screw up the buffer are backward-kill-word and kill-region
  7620.   (use-local-map irc-mode-map)
  7621.   (run-hooks 'irc-mode-hook))
  7622.  
  7623.  
  7624. (defun irc-sentinel (proc stat)
  7625.   "The sentinel for the IRC connexion.
  7626. Takes the normal sentinel arguments PROCESS and STATUS."
  7627.   ;; ignore anything but finished; i don't know what to do with the others
  7628.   (cond ((or (string= stat "finished\n")
  7629.          (string-match "^exit" stat))
  7630.          (save-excursion
  7631.            (set-buffer (cond ((processp proc) (process-buffer proc))
  7632.                  ((bufferp proc) proc)
  7633.                  (t (get-buffer
  7634.                  (irc-host+port-to-buffer irc-server
  7635.                               irc-port)))))
  7636.            (goto-char (point-max))
  7637.        (ding nil)
  7638.        (ding nil)
  7639.        (ding nil)
  7640.        (irc-insert "")
  7641.        (irc-insert "")
  7642.        (irc-insert (make-string (1- (window-width
  7643.                      (get-buffer-window (current-buffer))))
  7644.                     ?*))
  7645.        (let ((msg (format "Your IRC session ended at %s." (irc-get-time))))
  7646.          (irc-insert "%s%s"
  7647.              (make-string (max (/ (- (window-width
  7648.                           (get-buffer-window
  7649.                            (current-buffer)))
  7650.                          (length msg))
  7651.                           2)
  7652.                        0)
  7653.                       ? )
  7654.              msg))
  7655.        (irc-insert (make-string (1- (window-width
  7656.                      (get-buffer-window (current-buffer))))
  7657.                     ?*))
  7658.        (irc-insert ""))
  7659.          ;; all that needs to be done is a little maintenance ...
  7660.          (setq irc-processes (delq proc irc-processes)))))
  7661.  
  7662.  
  7663.  
  7664. ;; processing input
  7665. (defun irc-process-input ()
  7666.   "If in the input region, parse it for messages and commands.
  7667. In the output region, next-line if irc-spacebar-pages, otherwise do nothing.
  7668.  
  7669. All of the lines in the input region are rejoined during processing to be
  7670. handled as one.  A command is any line starting with a / after leading
  7671. whitespace is stripped away; commands can not exceed 510 characters.  Messages
  7672. can be longer but they will be split into 510 character segments for IRC.  The
  7673. buffer will reflect how the message was sent if it needed to be broken; the
  7674. split(s) will be indicated by \" >>\" to mean that the message is continued."
  7675.   (interactive)
  7676.   ;; do the simple stuff for the output region
  7677.   (if (< (point) irc-mark)
  7678.       (if irc-spacebar-pages
  7679.       (next-line 1)
  7680.       (ding))
  7681.       (if (not (processp (get-buffer-process (current-buffer))))
  7682.       (irc-insert (concat "%%Buffer not connected to any IRC-server, type"
  7683.                   " M-x irc RET to connect to a server."))
  7684.       (irc-check-time)
  7685.       ;; the input region is more work ...
  7686.       ;; first, toast extraneous spaces, tabs and newlines
  7687.       ;; at end of input region
  7688.       (delete-region (goto-char (point-max))
  7689.              (if (re-search-backward "[^ \n]" irc-mark t)
  7690.                  (1+ (point))
  7691.                  (point)))
  7692.       ;; nuke the white space at the beginning of input region, too
  7693.       (delete-region (goto-char irc-mark)
  7694.              (progn (re-search-forward " *")
  7695.                 (point)))
  7696.       (setq irc-history-index -1)    ; reset the history scroll location
  7697.       (let ((txt (buffer-substring irc-mark (point-max)))
  7698.         (maxlen (- irc-max-server-message-length 2))
  7699.         send
  7700.         ass)
  7701.         ;; check to see if the input region is empty
  7702.         (if (string= "" txt)
  7703.         (message "%%Nothing sent to the irc-server.")
  7704.         (while (string-match "\n" txt)
  7705.           (aset txt (match-beginning 0) ? ))
  7706.         (if (string-match "^/" txt)  ; it's a command
  7707.             (if (< (length txt) maxlen)
  7708.             (progn
  7709.               (goto-char (point-max))
  7710.               (insert "\n")
  7711.               (set-marker irc-mark (point))
  7712.               (irc-execute-command
  7713.                (setq irc-last-command (substring txt 1))))
  7714.             ;; can't use error because that kills the function
  7715.             (ding)
  7716.             (message "IRC commands can't exceed %d characters."
  7717.                  maxlen))
  7718.             ;; "a specified sendlist" -- was there one?
  7719.             (setq ass (irc-find-to txt 'explicit))
  7720.             (if (and ass
  7721.                  (string-match "^[^;:]" txt))
  7722.             ;; a real sendlist was specified, so
  7723.             ;; update irc-last-explicit
  7724.             (setq irc-last-explicit (irc-find-to txt)))
  7725.             (irc-add-to-hist (concat (if (not ass)
  7726.                          irc-default-to)
  7727.                          (buffer-substring irc-mark
  7728.                                    (point-max))))
  7729.             (while (> (length txt) maxlen)
  7730.               (setq send (substring txt 0 maxlen)
  7731.                 txt  (substring txt maxlen)
  7732.                 send (irc-fix-wordwrap send txt)
  7733.                 txt  (concat (if ass
  7734.                          irc-last-explicit
  7735.                          irc-default-to)
  7736.                      (cdr send))
  7737.                 send (concat (car send) " >>"))
  7738.               (goto-char (+ irc-mark (- (length send) 3)))
  7739.               (insert " >>\n" (if ass
  7740.                       irc-last-explicit
  7741.                       irc-default-to))
  7742.               (if (looking-at " ")
  7743.               (delete-char 1))
  7744.               (beginning-of-line)
  7745.               (set-marker irc-mark (point))
  7746.               (irc-execute-msg send))
  7747.             (goto-char (point-max))
  7748.             (insert "\n")
  7749.             (set-marker irc-mark (point))
  7750.             (irc-execute-msg txt))))))
  7751.   (setq irc-idle-last-sent (irc-current-time)))
  7752.  
  7753.  
  7754. (defun irc-execute-command (str)
  7755.   "Execute the \"/\" command of STR.  STR should not begin with a slash.
  7756. Commands are first looked up in the irc-alias-alist; if it is found there
  7757. then the alias gets passed recursively with any arguments the original
  7758. had.  The irc-command-alist is checked next and finally the irc-operator-alist.
  7759. A command is considered \"found\" when it matches either exactly or
  7760. unambiguously starting at the first character.  That is, J would match JOIN,
  7761. but OIN would not."
  7762.   (let* ((case-fold-search t)
  7763.          (cmd (substring str 0 (string-match "\\( +\\|$\\)" str)))
  7764.          (text (substring str (match-end 0)))
  7765.          (ambig (irc-check-list
  7766.                  (mapcar 'car (append irc-alias-alist irc-command-alist
  7767.                                       (if irc-operator irc-operator-alist)))
  7768.                  cmd 'start-only))
  7769.          (matches nil)
  7770.      (irc-called-from-buffer t))
  7771.     ;; if no matches are found the command might still be a valid command
  7772.     ;; name hiding behind non-operator status.  i don't like messages that
  7773.     ;; lie and say "Unknown command '/REHASH'" so this should make it not lie.
  7774.     (if (and (not irc-operator) (null ambig))
  7775.         (setq ambig (irc-check-list (mapcar 'car irc-operator-alist) cmd t)))
  7776.     ;; first determine any ambiguities among the lists
  7777.     (if (null ambig)
  7778.         ;; no matches at all were found
  7779.         (irc-insert "%%Unknown command \"/%s\".  Type /HELP for help."
  7780.                     (upcase cmd))
  7781.     ;; this is here for when a regular command gets aliased.  it shows up
  7782.     ;; as being ambiguous but it really isn't later on.
  7783.     (if (irc-member-general (car ambig) (cdr ambig) 'string=)
  7784.         (setq ambig (cdr ambig)))
  7785.     (if (> (length ambig) 1)
  7786.         (irc-insert "%%Ambiguous command \"/%s\".  Could be %s."
  7787.             (upcase cmd)
  7788.             (irc-subst-comma
  7789.              (mapconcat (function (lambda (arg)
  7790.                       (concat "/" arg)))
  7791.                     ambig
  7792.                     ", ")
  7793.              "or"))
  7794.         ;; alias list has highest priority
  7795.         (setq matches (irc-check-list (mapcar 'car irc-alias-alist) cmd t))
  7796.         ;; make sure matches is what we set out to looking for ...
  7797.         (if (and matches (string= (car matches) (car ambig)))
  7798.         ;; call this function again with the text as argument
  7799.         (irc-execute-command
  7800.          (concat (cdr (assoc (car matches) irc-alias-alist))
  7801.              ;; the servers won't grok trailing whitespace for some
  7802.              ;; messages so only use it to separate an argument
  7803.              (if (string< "" text) " ") text))
  7804.         ;; next try the command alist
  7805.         (setq matches (irc-check-list (mapcar 'car irc-command-alist)
  7806.                           cmd
  7807.                           t))
  7808.         (if (and matches
  7809.              (not (irc-check-list (mapcar 'car irc-operator-alist)
  7810.                           cmd
  7811.                           t)))
  7812.             ;; call the appropriate irc-execute-* function
  7813.             (funcall (intern-soft
  7814.                   (concat "irc-execute-"
  7815.                       (cdr (assoc (car matches)
  7816.                           irc-command-alist))))
  7817.                  text)
  7818.             ;; no matches yet.  last resort is the operator alist
  7819.             (setq matches (irc-check-list (mapcar 'car
  7820.                               irc-operator-alist)
  7821.                           cmd
  7822.                           t))
  7823.             (if matches
  7824.             (if irc-operator
  7825.                 (funcall
  7826.                  (intern-soft (concat
  7827.                        "irc-execute-"
  7828.                        (cdr
  7829.                         (assoc (car matches)
  7830.                            irc-operator-alist))))
  7831.                  text)
  7832.                 (irc-insert (concat "%%Only enabled IRC Operators"
  7833.                         " can use the /%s command. Use"
  7834.                         " /OPER to enable yourself.")
  7835.                     (upcase (car matches)))))))))))
  7836.  
  7837.  
  7838. (defun irc-send (str)
  7839.   "Send STR to process in the current buffer.
  7840. A CR-LFD pair is appended automatically as per the 'official' IRC protocol,
  7841. but it seems unnecessary.  Returns its argument STR."
  7842.   (setq str (irc-lowlevel-enquote str))
  7843.   (let* ((proc (get-buffer-process (current-buffer)))
  7844.      (sent (if (processp proc)
  7845.            (condition-case x
  7846.                (send-string proc (concat str "\r\n"))
  7847.              (error x))))
  7848.      (ok (and (processp proc)
  7849.           (eq sent nil))))
  7850.     (if (not ok)
  7851.     (let ((stars (make-string (1- (window-width (get-buffer-window
  7852.                              (current-buffer))))
  7853.                   ?*)))
  7854.       (irc-insert "")
  7855.       (irc-insert "")
  7856.       (irc-insert "%s" stars)
  7857.       (irc-insert "?Failed sending to server!")
  7858.       (cond ((not (processp proc))
  7859.          (irc-insert "?No \"process\" to send to."))
  7860.         ((consp sent)
  7861.          (irc-insert (concat "?Signaled condition is \"%s\" and"
  7862.                      " associated data is \"%s\".")
  7863.                  (car sent)
  7864.                  (cdr sent)))
  7865.         (t (irc-insert "?Unknown reason, proc=%s, sent=%s."
  7866.                    proc
  7867.                    sent)))
  7868.       (irc-insert "?Your IRC session aborted at %s." (irc-get-time))
  7869.       (irc-insert "%s" stars)
  7870.       (if (processp proc) (delete-process proc))
  7871.       (error "IRC aborted"))
  7872.     (irc-log-in-debug-buffer (concat "+ " str)))))
  7873.  
  7874.  
  7875.  
  7876. ;; sending messages to people
  7877. (defun irc-execute-privmsg (str)
  7878.   "Usage: /MSG recipient(s) message
  7879.  
  7880. This command is provided simply for compatability with the C client.
  7881. It is preferable instead to just type the name of the user followed by
  7882. a semi-colon and then the message. That is, \"tale;hi!\" will send the
  7883. message \"hi!\" to the user with the nickname which starts with
  7884. \"tale\".  A semi-colon at the beginning of the line means to send to
  7885. the last recipient explicity specified; typing a semi-colon at the
  7886. beginning of a line expands it to the last recipient(s) specified. The
  7887. recipients for a message can be a comma separated list of users and/or
  7888. channels. Don't use any spaces left of the semi-colon.
  7889.  
  7890. You can send messages to users and channels, and if you are an enabled
  7891. IRC operator, you can also send broadcasts to server machines and
  7892. client machines.
  7893.  
  7894. Examples:
  7895. /msg wiz hi there           send \"hi there\" to user with nickname wiz
  7896. wiz;hi there                send to user wiz
  7897. msa,wiz;hi there            send to the users wiz and msa
  7898. 42;hi there                 send into channel 42
  7899. 42,wiz;hi there             channel 42 and user wiz
  7900.  
  7901. If you are an enabled IRC operator:
  7902. $minsk.docs.uu.se;...       send a message to all users using server minsk
  7903. $*.se;...                   send to all users using swedish servers
  7904. #cia.docs.uu.se;...         send to all users running their clients on cia
  7905. #*.se;...                   all user running their clients on swedish machines"
  7906.   (irc-add-to-hist
  7907.    (irc-execute-msg
  7908.     (concat
  7909.      (setq irc-last-explicit (concat (substring str 0 (string-match " +\\|$"
  7910.                                     str))
  7911.                      ";"))
  7912.      (substring str (match-end 0))))))
  7913.  
  7914.  
  7915. (defun irc-execute-msg (str)
  7916.   "Send a message to a channel or another user.  Returns its argument STR,
  7917. munged slightly to indicate where it was attempted to be sent."
  7918.   ;; this really is an indirect function of the UI (ie, not through a /COMMAND)
  7919.   ;; so it isn't interactive
  7920.   (let ((tolist nil)
  7921.     (orig str)
  7922.     (icw nil)
  7923.     (confirm nil)
  7924.     (on-hash (irc-is-multijoinable-channel irc-channel))
  7925.     (newsrvr (irc-server-has-multijoinable-channels)))
  7926.     (if (string-match "^[:;]" str)
  7927.         ;; a little bit of fill-in-the-blank
  7928.         (setq str (concat irc-last-explicit (substring str 1)))
  7929.     (if (not (irc-find-to str 'explicit))
  7930.         ;; prepend an implicit sendlist if need be
  7931.         (if irc-default-to
  7932.         (setq str (concat irc-default-to str))
  7933.         (irc-insert "%%You have no default sendlist."))))
  7934.     (if (irc-find-to str 'explicit)
  7935.         (setq icw (irc-find-to str)
  7936.               tolist (irc-burst-comma (substring icw 0 (1- (length icw))))
  7937.           tolist (mapcar 'irc-clean-up-message tolist)
  7938.               str (irc-find-message str)
  7939.               ;; kill on leading space if it exists.  ie, "tale: hi" will
  7940.               ;; send "hi" as a message not " hi".
  7941.               str (if (string-match "^ *" str)
  7942.               (substring str (match-end 0)))))
  7943.     (setq confirm (delq            ; whee.  lisp indentation is fun.
  7944.            nil
  7945.            (mapcar
  7946.             (function
  7947.              (lambda (to)
  7948.               (if (not (zerop (string-to-int to)))
  7949.               (if (string= to irc-channel)
  7950.                   (progn
  7951.                 (irc-send
  7952.                  (if (and newsrvr on-hash)
  7953.                      (concat "PRIVMSG " irc-channel " :" str)
  7954.                      (concat "MSG :" str)))
  7955.                 to)
  7956.                   ;; new in 1.2 -- you _can_ send to a channel you
  7957.                   ;; are not on
  7958.                   (irc-send (concat "PRIVMSG " to " :" str))
  7959.                   to)
  7960.               (if (not (or (string= to "*")
  7961.                        (string= to "0")))
  7962.                   (setq icw (irc-check-list (irc-recall-all
  7963.                              'irc-nicknames)
  7964.                             to)))
  7965.               (cond ((string= to "*")
  7966.                  (if (string= "0" irc-channel)
  7967.                      (progn
  7968.                        (irc-insert (concat "%%You are not"
  7969.                                " talking to any"
  7970.                                " channel."))
  7971.                        nil)
  7972.                      (irc-send
  7973.                       (if (and newsrvr on-hash)
  7974.                       (concat "PRIVMSG " irc-channel
  7975.                           " :" str)
  7976.                       (concat "MSG :" str)))
  7977.                      irc-channel))
  7978.                 ((string= to "0")
  7979.                  (irc-insert "%%You can't send to channel 0.")
  7980.                  nil)
  7981.                 ((= (length icw) 1)
  7982.                  (irc-send (concat "PRIVMSG "
  7983.                            (car icw)
  7984.                            " :"
  7985.                            str))
  7986.                  (car icw))
  7987.                 ((not icw)
  7988.                  ;; Wox! No one found, but we'll do a
  7989.                  ;; nonomatching. Try sending it anyway and
  7990.                  ;; let the server bitch if necessary.
  7991.                  ;; So don't remember this "nonmatch".
  7992.                  (irc-send (concat "PRIVMSG " to " :" str))
  7993.                  to)
  7994.                 (t (irc-insert (concat "%%Ambiguous recipient"
  7995.                                " \"%s\"; could be %s.")
  7996.                            to
  7997.                            (irc-subst-comma
  7998.                         (mapconcat
  7999.                          (function
  8000.                           (lambda (arg)
  8001.                            (concat "\"" arg "\"")))
  8002.                          icw
  8003.                          ", ")
  8004.                         "or"))
  8005.                    nil)))))
  8006.             tolist)))
  8007.     (setq confirm (let ((foo ())
  8008.             (bar confirm))
  8009.             (while (> (length bar) 0)
  8010.               (setq foo (cons
  8011.                  (concat
  8012.                   (cond
  8013.                     ((irc-is-nickname (car bar)) "user")
  8014.                     ((irc-is-channelname (car bar)) "channel")
  8015.                     ((irc-is-broadcastname (car bar)) "server")
  8016.                     (t "receiver"))
  8017.                   " "
  8018.                   (car bar))
  8019.                  foo)
  8020.                 bar (cdr bar)))
  8021.             foo))
  8022.     (let* ((rcvr (irc-subst-comma (mapconcat 'eval confirm ", ")
  8023.                   "and"))
  8024.        (data (irc-clean-up-message (format irc-msg-sent rcvr))))
  8025.       (if (and confirm irc-confirm)
  8026.       (let ((c confirm))
  8027.         (while c
  8028.           (let ((r (irc-clean-up-message (format irc-msg-sent (car c)))))
  8029.         (irc-insert "%s%s" (make-string
  8030.                     (max 0 (- (window-width
  8031.                            (get-buffer-window
  8032.                         (current-buffer)))
  8033.                           (length r)
  8034.                           1))
  8035.                     ? )
  8036.                 r)
  8037.         (setq c (cdr c)))))
  8038.       (if (not confirm)
  8039.           (irc-insert "%% Message not sent. Use /HELP for help."))))
  8040.     orig))
  8041.  
  8042.  
  8043. (defun irc-execute-oops (newto)
  8044.   "Usage: /OOPS intended-recipient
  8045. Send irc-oops to recipient(s) of last message and resend message to
  8046. 'intended-recipient'.  This command is handy when you've just sent a message
  8047. to the wrong place and you want the person/people who saw it to know that they
  8048. should just disregard it.  The message which was originally sent then gets
  8049. forwarded to its proper destination."
  8050.   (interactive '(""))
  8051.   (if (not irc-called-from-buffer)
  8052.       (progn (irc-insert "")
  8053.          (irc-insert "/OOPS")))  
  8054.   (let* ((prev (irc-find-to (car irc-history)))
  8055.      (data (concat prev irc-oops)))
  8056.     ;; first do the oops message
  8057.     (irc-execute-msg data)
  8058.     ;; then resend the original
  8059.     (if (and (string= "" newto) irc-called-from-buffer)
  8060.     (irc-insert (concat "%%No new receiver given. Oops said to %s. Not"
  8061.                 " redirected.")
  8062.             prev)
  8063.     (irc-execute-redirect newto)))
  8064.   (setq irc-idle-last-sent (irc-current-time)))
  8065.  
  8066.  
  8067. (defun irc-execute-redirect (newto)
  8068.   "Usage: /REDIRECT additional-recipient
  8069.  
  8070. Send to 'additional-recipient' the last message which you sent.  This 
  8071. command can be fairly easily duplicated using the history mechanism by hand
  8072. but it is provided to make it even easier."
  8073.   (interactive '(""))
  8074.   (if (not irc-history)
  8075.       (irc-insert "%%No message sent yet, nothing to redirect.")
  8076.       (let* ((default (if irc-default-to 
  8077.               (substring irc-default-to 0 (string-match
  8078.                                "[:;]" irc-default-to))
  8079.               ""))
  8080.          (prompt (if (string< "" default)
  8081.              (concat "(RET for "
  8082.                  (irc-nuke-whitespace
  8083.                   (concat
  8084.                    default
  8085.                    (if (string-match "\\*" default)
  8086.                        (concat "; where *=\""
  8087.                            irc-channel
  8088.                            "\""))))
  8089.                  ") ")
  8090.              ""))
  8091.          (n (irc-nuke-whitespace
  8092.          (if (and (string= "" newto) (not irc-called-from-buffer))
  8093.              (irc-read-object
  8094.               (format "Send copy of last message (%s) to whom? %s"
  8095.                   (let ((m (irc-find-message (car irc-history))))
  8096.                 (if (> (length m) 5)
  8097.                     (concat (substring m 0 5) "...")
  8098.                     m))
  8099.                   prompt)
  8100.               ""
  8101.               (irc-recall-all 'irc-nicknames))
  8102.              newto)))
  8103.          (new (if (string= "" n) default n)))
  8104.     (if (not (irc-is-receiver new))
  8105.         (irc-insert (concat "%%\"%s\" is not a valid receiver. Message not"
  8106.                 " redirected.")
  8107.             new)
  8108.         (let ((to (if (string= "" new)
  8109.               default
  8110.               (concat new ";"))))
  8111.           (setq irc-last-explicit to)
  8112.           (irc-add-to-hist
  8113.            (irc-execute-msg
  8114.         (concat to (irc-find-message (car irc-history)))))))))
  8115.   (setq irc-idle-last-sent (irc-current-time)))
  8116.  
  8117.  
  8118.  
  8119. ;; /commands for the server
  8120. (defun irc-execute-quote (msg)
  8121.   "Usage: /QUOTE string
  8122.  
  8123. This command is used to send 'string' directly to the IRC server without
  8124. any local processing.  Warning: this has the potential to screw up some
  8125. things in irc-mode, particularly if it is used to change your nickname or
  8126. to switch channels."
  8127.   (interactive '(""))
  8128.   (let ((m (if (and (string= "" msg) (not irc-called-from-buffer))
  8129.            (read-string "String to send to server: ")
  8130.            msg)))
  8131.     (cond ((string-match "^ *\\([^ ]+\\)" m)
  8132.        (let ((cmd (subfield m 1)))
  8133.          (irc-send m)
  8134.          (irc-send (concat "CLIENT-SYNCH :QUOTE " cmd))))
  8135.       (t (irc-insert "%%Nothing was sent to the IRC server."))))
  8136.   (setq irc-idle-last-sent (irc-current-time)))
  8137.  
  8138.  
  8139. (defun irc-execute-who (channel)
  8140.   "Usage: /WHO { channel | user }
  8141.  
  8142. Get a list of the users on IRC. The argument \"channel\" means to show
  8143. just the users on that channel, with * representing the current channel.
  8144. User can be any mask, ie *.se for current swedish IRCjunkies.
  8145.  
  8146. Each user is indicated on a separate line with their nickname, status,
  8147. channel, login name, host and real name. The second column, \"Stat\"
  8148. gives the status for the user, and is shown as a four letter word (:-)
  8149. according to the combination of their attributes. The possible
  8150. attributes are being an IRC operator, being a channel operator and
  8151. being marked as being away.
  8152.  
  8153.                                           Status field
  8154. A normal user having no attributes set:     (blank)
  8155. A normal user marked as being away:          Away
  8156. An IRC operator with no other attribues:     Iopr
  8157. An IRC operator marked as being away:        IoAw
  8158. A channel operator with no other attributes: Copr
  8159. A channel operator marked as being away:     CoAw
  8160. User being both IRC- and channel operator:   ICop
  8161. As above but also marked as being away:      ICAw
  8162.  
  8163. Being ignored takes precedence over all
  8164. other attributes, always shown as:           IGNR     (cf \"/HELP IGNORE\"). 
  8165.  
  8166. Users being on either no channel at all, or on channels with the mode
  8167. PRIVATE are appear with a blank \"Channel\" field. If you are
  8168. connected to a server of version 2.6, and are requesting a \"general\"
  8169. who listing (ie for users potentially on different channels), all
  8170. users \"Channel\" field will be blank.
  8171.  
  8172. An %-sign is appended to the name or number of your current
  8173. channel.
  8174.  
  8175. BE WARNED: on some servers, the operators CAN see who's on a negative channel.
  8176. On some of these servers, the channel number is disclosed, on others only
  8177. the fact that a user is on a negative channel, but not which one.
  8178. The same goes for \"private\" and \"secret\" channels.
  8179.  
  8180. If a single \"user\" is given as the argument, (ie a word starting with neither
  8181. a + nor a digit) it is taken to be the nickname of a user on IRC and more
  8182. information, if available, is given about the person.
  8183.  
  8184. If this function is called interactively then the prefix argument is used
  8185. as the channel to query.  No argument means all of them and an argument
  8186. of \"-\" or \"*\" means the current channel." 
  8187.   (interactive '(""))
  8188.   (let* ((c (if (and (string= "" channel) (not irc-called-from-buffer))
  8189.         (irc-read-object (concat "Who? "
  8190.                      (if (not (string= "0" irc-channel))
  8191.                          (concat "(Press return for "
  8192.                              irc-channel
  8193.                              ") ")
  8194.                          ""))
  8195.                  ""
  8196.                  (irc-get-channels-and-nicks-and-servers))
  8197.         channel))
  8198.      (c2 (irc-nuke-whitespace c))
  8199.      (chan (cond ((or (string= "" c2)
  8200.               (string= "*" c2))
  8201.               irc-channel)
  8202.              (t c2))))
  8203.     (if (string= "0" chan)
  8204.     (irc-insert (concat "%%No argument (or argument 0) given to /WHO,"
  8205.                 " this would certainly disconnect your"
  8206.                 " IRC-session. You can use /QUOTE WHO 0 if you"
  8207.                 " *really* want to do this."))
  8208.       (let ((s (irc-recall-all 'irc-services)))
  8209.     (irc-forget-all 'irc-nicknames)
  8210.     (irc-remember irc-nick-used 'irc-nicknames)
  8211.     (while (and (listp s) s)
  8212.       (irc-remember (car s) 'irc-nicknames)
  8213.       (setq s (cdr s)))
  8214.     (if (not irc-called-from-buffer)
  8215.         (progn (irc-insert "")
  8216.            (irc-insert "/WHO %s" chan)))
  8217.     (if (and irc-called-from-buffer (irc-is-nickname chan))
  8218.         (irc-execute-whois chan)
  8219.       (irc-send (concat "WHO " chan))))
  8220.       (setq irc-idle-last-sent (irc-current-time)))))
  8221.  
  8222.  
  8223. (defun irc-execute-whois (user)
  8224.   "Usage: /WHOIS user
  8225.  
  8226. Get a two line description of who and where \"user\" is.  If user is not
  8227. provided it is read from the minibuffer with a completing-read.
  8228. If * is given instead of a user name, you will be informed about ALL users.
  8229.  
  8230. BUG: The list of users used when * is given may be somewhat obsolete,
  8231. therefore first give a NAMES command."
  8232.   (interactive '(""))
  8233.   (let ((wholist (irc-recall-all 'irc-nicknames)))
  8234.     (if (and (string-match "^ *$" user) (not irc-called-from-buffer))
  8235.     (setq user (irc-read-object "Who is who? "
  8236.                     user
  8237.                     wholist)))
  8238.     (if (string< "" user)
  8239.     (progn (if (not irc-called-from-buffer)
  8240.            (progn (irc-insert "")
  8241.               (irc-insert "/WHOIS %s" user)))
  8242.            (irc-send (concat "WHOIS " user)))
  8243.     (irc-insert "%%Who is who? No nick given.")))
  8244.   (setq irc-idle-last-sent (irc-current-time)))
  8245.  
  8246.  
  8247. (defun irc-execute-motd (server)
  8248.   "Usage: /MOTD [ server ]
  8249.  
  8250. Tells the message of the day at the server."
  8251.   (interactive '(""))
  8252.   (let ((host (if (string= "" server)
  8253.           (if (not irc-called-from-buffer)
  8254.               (irc-read-object
  8255.                "Get message of the day for which host? "
  8256.                ""
  8257.                (irc-recall-all 'irc-servernames))
  8258.               "")
  8259.           server)))
  8260.     (if (string-match "^ *\\([^: ]*\\)" host)
  8261.     (let ((host (substring host (match-beginning 1) (match-end 1))))
  8262.       (if (not irc-called-from-buffer)
  8263.           (progn (irc-insert "")
  8264.              (irc-insert "/MOTD %s" host)))
  8265.       (irc-send (concat "MOTD " host)))
  8266.     (irc-insert (concat "%%Internal error in function irc-execute-motd,"
  8267.                 " please try another syntax and notify %s"
  8268.                 " by email.")
  8269.             irc-hacker)))
  8270.   (setq irc-idle-last-sent (irc-current-time)))
  8271.  
  8272.  
  8273. (defun irc-execute-version (server)
  8274.   "Usage: /VERSION [ server | user ]
  8275.  
  8276. Shows the version of the server, or of a user. If the argument looks
  8277. like a nickname, that user's client is queried using CTCP (client to
  8278. client protocol) about which client it is and which version of it it
  8279. is. If the queried client doesn't understand CTCP, no answer will
  8280. follow."
  8281.   (interactive '(""))
  8282.   (let* ((host (irc-nuke-whitespace
  8283.         (if (string= "" server)
  8284.             (if (not irc-called-from-buffer)
  8285.             (irc-read-object
  8286.              "Get version of which server/nick? "
  8287.              ""
  8288.              (irc-get-channels-and-nicks-and-servers))
  8289.             "")
  8290.             server)))
  8291.      (host (if (string= "" host) irc-server host))
  8292.      (hst (if (string= "*" host) irc-channel host)))
  8293.     (if (string-match "^ *\\([^: ]*\\)" hst)
  8294.     (let ((h (substring hst (match-beginning 1) (match-end 1))))
  8295.       (cond ((or (irc-is-nickname h)
  8296.              (irc-is-channelname h))
  8297.          (if (not irc-called-from-buffer)
  8298.              (progn (irc-insert "")
  8299.                 (irc-insert (concat "/VERSION " h))))
  8300.          (irc-insert (concat "%sQuerying client of user%s %s for"
  8301.                      " version of client%s")
  8302.                  irc-msg-info-pre
  8303.                  (if (irc-is-channelname h) "s on channel" "")
  8304.                  h
  8305.                  irc-msg-info-post)
  8306.          (irc-send (concat "PRIVMSG " h " :\001"
  8307.                    (irc-ctcp-enquote "VERSION")
  8308.                    "\001")))
  8309.         (t (if (not irc-called-from-buffer)
  8310.                (progn (irc-insert "")
  8311.                   (irc-insert "/VERSION %s" h)))
  8312.            (irc-send (concat "VERSION " h)))))
  8313.     (irc-insert "%%Give only one word please. \"%s\" is not valid."
  8314.             hst)))
  8315.   (setq irc-idle-last-sent (irc-current-time)))
  8316.  
  8317.  
  8318. (defun irc-execute-list (channel)
  8319.   "Usage: /LIST [channel]
  8320.  
  8321. Get a list of the discussions that are on IRC. If a channel is given,
  8322. only the topic for that channel is shown. A * denotes your current
  8323. channel, if any. An %-sign is appended to your current channel's name
  8324. or number."
  8325.   (interactive '(""))
  8326.   (if (not irc-called-from-buffer)
  8327.       (progn (irc-insert "")
  8328.          (irc-insert "/LIST %s" channel)))
  8329.   (irc-send (concat "LIST " channel))
  8330.   (setq irc-idle-last-sent (irc-current-time)))
  8331.  
  8332.  
  8333. (defun irc-execute-links (mask)
  8334.   "Usage: /LINKS [ mask ]
  8335.  
  8336. Show the names of all the servers which can communicate with your server.
  8337. The links can go down isolating different parts of the IRC-net, so this
  8338. is a good way to find out how extensive it is at the moment.
  8339.  
  8340. Given a mask like *.se, only server names matching the mask are displayed."
  8341.   (interactive '(""))
  8342.   (let ((m (if (and (string= "" mask) (not irc-called-from-buffer))
  8343.            (irc-read-object (concat "Check for which servers? (RET for"
  8344.                     " all, *.SE for swedish servers etc) ")
  8345.                 ""
  8346.                 (irc-recall-all 'irc-servernames))
  8347.            mask)))
  8348.     (cond ((string-match "^ *\\*? *$" m)
  8349.        (irc-forget-all 'irc-servernames)
  8350.        (irc-forget-all 'irc-linksinfo)))
  8351.     (if (not irc-called-from-buffer)
  8352.     (progn (irc-insert "")
  8353.            (irc-insert "/LINKS %s" m)))
  8354.     (irc-send (concat "LINKS " m)))
  8355.   (setq irc-idle-last-sent (irc-current-time)))
  8356.  
  8357.  
  8358. (defun irc-execute-lusers (mask)
  8359.   "Usage: /LUSERS [servermask]
  8360.  
  8361. Get the number of users and servers on your IRC network. 
  8362.  
  8363. There is a optional argument you can use if you only want
  8364. to see the count of some part of the IRCnet. For instance,
  8365. to see how many swedish users are on, try /lusers *.se"
  8366.   (interactive '(""))
  8367.   (let* ((mask (irc-nuke-whitespace mask)))
  8368.     (if (not irc-called-from-buffer)
  8369.     (progn (irc-insert "")
  8370.            (irc-insert (format "/LUSERS %s" mask))))
  8371.     (irc-send (concat "LUSERS " mask))
  8372.     (setq irc-idle-last-sent (irc-current-time))))
  8373.  
  8374.  
  8375. (defun irc-execute-admin (server)
  8376.   "Usage: /ADMIN [ server ]
  8377.  
  8378. Get information about the IRC administrator for 'server'; if server is not
  8379. supplied just query for the server to which you are connected."
  8380.   (interactive '(""))
  8381.   (let ((s (if (and (string= "" server) (not irc-called-from-buffer))
  8382.            (irc-read-object "Administrative info about which server? "
  8383.                 ""
  8384.                 (irc-recall-all 'irc-servernames))
  8385.            server)))
  8386.     (if (not irc-called-from-buffer)
  8387.     (progn (irc-insert "")
  8388.            (irc-insert "/ADMIN %s" s)))
  8389.     (irc-send (concat "ADMIN " s)))
  8390.   (setq irc-idle-last-sent (irc-current-time)))
  8391.  
  8392.  
  8393. (defun irc-execute-time (&optional server)
  8394.   "Usage: /TIME [ server ]
  8395.  
  8396. Get the current time on 'server'; is no server is provided use the one to which
  8397. you are connected.  When called with a interactively with a prefix-argument
  8398. the server name is read using the minibuffer.
  8399.  
  8400. Querying other servers can be handy given that people on IRC are spread out
  8401.  from the west coast of the United States to Finland.  The question \"What
  8402. time is it in Finland?\" comes up so frequently that an alias -- /TF -- has
  8403. been provided by default to get the answer.  This alias should work as long
  8404. as tut.fi is connected to your IRC-net."
  8405.   (interactive '(""))
  8406.   (let ((s (if (and (stringp server)
  8407.             (string= "" server)
  8408.             (not irc-called-from-buffer))
  8409.            (irc-read-object "Get the time at which server? "
  8410.                 ""
  8411.                 (irc-recall-all 'irc-servernames))
  8412.            server)))
  8413.     (if (and (stringp server) (not irc-called-from-buffer))
  8414.     (progn (irc-insert "")
  8415.            (irc-insert "/TIME %s" s)))
  8416.     (irc-send (concat "TIME " s)))
  8417.   (setq irc-idle-last-sent (irc-current-time)))
  8418.  
  8419.  
  8420. (defun irc-execute-join (channel)
  8421.   "Usage: /JOIN channel [mode]
  8422.  
  8423. Join \"channel\" on IRC.  If channel is not provided it is requested
  8424. in the minibuffer; when called interactively, the channel is prompted
  8425. for in the minibuffer.  Use /LEAVE to exit the channel.
  8426.  
  8427. You can supply an initial mode for the channel. If the channel didn't
  8428. exist before you joined it, the channel will be sat to the supplied mode.
  8429. If the channel already existed, the mode will be ignored by the server.
  8430.  
  8431. One can be listening on several channels at once. Up to 10 channels
  8432. can be listened to at any single time, either 10 #channels, or 1 old
  8433. style (either a +channel or a nummeric channel) and 9 #channels. Use
  8434. /JOIN to join (ie start listening and talkinging to) a channel and
  8435. /LEAVE to stop listening to a channel. If you /LEAVE the channel you
  8436. were talking to, you will end up not talking to any channel; just use
  8437. /JOIN again to remedy that situation.  There is no way yet to start
  8438. listening to a channel without choosing that channel as the one you
  8439. will talk to. Of course, another /JOIN will help..."
  8440.  
  8441.   (interactive '(""))
  8442.   (let* ((pair (cond
  8443.          ((string-match "^ *\\([^ ]+\\) +\\([^ ]\\)" channel)
  8444.           (cons (subfield channel 1)
  8445.             (concat (subfield channel 2)
  8446.                 (substring channel (match-end 0)))))
  8447.          ((string-match "^ *\\([^ ]+\\) *$" channel)
  8448.           (cons (subfield channel 1) ""))
  8449.          (t (cons "" ""))))
  8450.      (c (car pair))
  8451.      (m (cdr pair))
  8452.      (subchnls (irc-recall-all 'irc-subscribed-channels))
  8453.      (chn (irc-nuke-whitespace
  8454.            (if (and (string= c "")
  8455.             (not irc-called-from-buffer))
  8456.            (irc-read-object "Channel to join? "
  8457.                     ""
  8458.                     subchnls)
  8459.            c)))
  8460.      (mode (irc-nuke-whitespace
  8461.         (if (and (string= m "")
  8462.              (not irc-called-from-buffer)
  8463.              (not (irc-recall chn 'irc-subscribed-channels)))
  8464.             (irc-read-object (format
  8465.                       "Initial mode for channel \"%s\"? "
  8466.                       chn)
  8467.                      ""
  8468.                      '("A combination of +-bilmnopst"))
  8469.             m)))
  8470.      (digit-start (string-match "^-?[0-9]" chn)))
  8471.     (if (string= "" chn) ; well, so much for that 
  8472.     (irc-insert "%%No channel given. continuing talking to %s."
  8473.             irc-channel)
  8474.     (let* ((newsrvr (irc-server-has-multijoinable-channels)) 
  8475.            (mtch (irc-recall chn 'irc-subscribed-channels)))
  8476.       (cond ((string= "0" chn) 
  8477.          (setq irc-channel "0")
  8478.          (irc-show-subscribed-channels)) 
  8479.         ((and (not mtch)
  8480.               (not (irc-is-channelname chn)))
  8481.          (irc-insert (concat "%%Warning, that channel name (%s) looks" 
  8482.                      " strange, but will try to /join it"
  8483.                      " anyway. You might be in for a surprise,"
  8484.                      " thought.")
  8485.                  chn)
  8486.          (if (not irc-called-from-buffer) 
  8487.              (progn (irc-insert "")
  8488.                 (irc-insert "/JOIN %s %s" chn mode))) 
  8489.          (irc-send (format "%s %s %s"
  8490.                    (if newsrvr "JOIN " "CHANNEL ")
  8491.                    chn
  8492.                    mode)))
  8493.         (mtch (setq irc-channel mtch)
  8494.               (if (not irc-called-from-buffer) 
  8495.               (progn (irc-insert "")
  8496.                  (irc-insert "/JOIN %s" mtch)))
  8497.               (irc-show-subscribed-channels))
  8498.         (t (if (not irc-called-from-buffer)
  8499.                (progn (irc-insert "")
  8500.                   (irc-insert "/JOIN %s %s" chn mode)))
  8501.            (irc-send (format "%s %s %s"
  8502.                      (if newsrvr "JOIN " "CHANNEL ")
  8503.                      chn
  8504.                      mode))))))
  8505.     (setq irc-msg-cont-used
  8506.       (if (string= "0" chn) ;On private?
  8507.           irc-msg-cont 
  8508.           (make-string (1- (length (concat irc-msg-cont chn)))
  8509.                (string-to-char " ")))) )
  8510.   (setq irc-idle-last-sent (irc-current-time)))
  8511.  
  8512.  
  8513. (defun irc-execute-leave (channel)
  8514.   "Usage: /LEAVE [channel]
  8515.  
  8516. Leave your current channel (or a selected one from the set of joined channels,
  8517. if you're using a v2.6 or later server). Don't join another channel.
  8518.  
  8519. Also see /HELP JOIN."
  8520.   (interactive '(""))
  8521.   (let* ((c (if (and (string-match "^ *$" channel)
  8522.              (not irc-called-from-buffer))
  8523.         (irc-read-object (concat "Leave which channel? (0 for ALL"
  8524.                      (if (string= "0" irc-channel)
  8525.                          ") "
  8526.                          (concat ", RET for "
  8527.                              irc-channel
  8528.                              ") ")))
  8529.                  ""
  8530.                  (irc-recall-all 'irc-subscribed-channels))
  8531.         channel))
  8532.      (chan (irc-nuke-whitespace
  8533.         (if (and (not (string= "0" irc-channel))
  8534.              (or (string= "*" c) (string= "" c)))
  8535.             irc-channel
  8536.           (if (and (string= "" c)
  8537.                (not irc-called-from-buffer))
  8538.               (message "%%No channel chosen"))
  8539.           c))))
  8540.     (if (string= "0" chan)
  8541.     (progn
  8542.       (let ((lst (irc-recall-all 'irc-subscribed-channels))
  8543.         (irc-multiple-leave-in-progress t)
  8544.         (irc-called-from-buffer t))
  8545.         (while (not (null lst))
  8546.           (irc-send (concat "PART " (car lst)))
  8547.           (setq lst (cdr lst))))
  8548.       (irc-show-subscribed-channels))
  8549.     (if (not irc-called-from-buffer)
  8550.         (progn (irc-insert "")
  8551.            (irc-insert "/LEAVE %s" chan)))
  8552.     (if (string< "" chan)
  8553.         (progn (irc-insert "%sLeaving channel %s%s"
  8554.                    irc-msg-info-pre chan irc-msg-info-post)
  8555.            (if (irc-server-has-multijoinable-channels)
  8556.                (irc-send (concat "PART " chan))
  8557.                (irc-send "CHANNEL 0")))
  8558.         (irc-insert (concat "%%Leave which channel? No channel given. Try"
  8559.                 " /MEMBERSHIPS")))))
  8560.   (setq irc-idle-last-sent (irc-current-time)))
  8561.  
  8562.  
  8563. (defun irc-execute-nick (name)
  8564.   "Usage: /NICKNAME name
  8565.  
  8566. Change your nickname in IRC.  A nickname can contain alphanumeric characters,
  8567. underscores (_), hyphens (-) or the special characters left brace ({), right
  8568. brace (}), vertical bar (|), left bracket ([), right bracket (]) and back
  8569. slash (\\). These special character are alphabetic characters in some
  8570. languages like the scandinavian ones.  The name cannot start with a hyphen or
  8571. number and only the first nine characters are used.
  8572.  
  8573. Unfortunately, due to the way confirmation from the servers work, it might be
  8574. falsely reported that your nickname was successfully changed when it was not.
  8575. The server will come back and say so and finally irc-mode will wise-up and
  8576. note that your nickname was not changed.
  8577.  
  8578. All the above things change from server version to server version, so they may
  8579. or may not work. Try it."
  8580.   (interactive '(""))
  8581.   (let ((newnick (if (and (string= "" name) (not irc-called-from-buffer))
  8582.              (irc-nuke-whitespace (read-string "New nickname? "))
  8583.              name)))
  8584.     (if (string= "" newnick)
  8585.     (irc-insert "%sNickname not changed%s"
  8586.             irc-msg-info-pre
  8587.             irc-msg-info-post)
  8588.     (progn
  8589.       (if (not irc-called-from-buffer)
  8590.           (progn (irc-insert "")
  8591.              (irc-insert "/NICK %s" newnick)))
  8592.       (irc-insert "%sTrying to change your nickname to \"%s\"%s"
  8593.               irc-msg-info-pre
  8594.               newnick
  8595.               irc-msg-info-post)
  8596.       (set-buffer-modified-p (buffer-modified-p))
  8597.       (irc-send (concat "NICK " newnick)))))
  8598.   (setq irc-idle-last-sent (irc-current-time)))
  8599.  
  8600.  
  8601. (defun irc-execute-quit (text)
  8602.   "Usage: /QUIT [reason]
  8603.  
  8604. Exit IRC.  The connection is closed but the buffer is left behind.
  8605. If you want, you can give a reason for quitting IRC."
  8606.   (interactive '(""))
  8607.   (if (not irc-called-from-buffer)
  8608.       (progn (if (string-match "^ *$" text)
  8609.          (setq text (yow)))
  8610.          (let ((parias '("\n" "  " "\t"))
  8611.            (ok nil)
  8612.            (n 0))
  8613.            (while (not ok)
  8614.          (let ((p parias))
  8615.            (while p
  8616.              (while (string-match (car p) text)
  8617.                (setq text (concat (substring text
  8618.                              0
  8619.                              (match-beginning 0))
  8620.                       " "
  8621.                       (substring text (match-end 0)))))
  8622.              (setq p (cdr p))))
  8623.          (setq n (1+ n))
  8624.          (if (> n 10)
  8625.              (setq text ""))
  8626.          (if (< (length text) 80)
  8627.              (setq ok t)
  8628.              (setq text (yow)))))
  8629.          (irc-insert "")
  8630.          (irc-insert "/QUIT %s" text)))
  8631.   (irc-send (concat "QUIT :" text))
  8632.   (sit-for 2)                ;Give server a chance to react.
  8633.   (let ((proc (get-buffer-process (current-buffer))))
  8634.     (cond ((processp proc)
  8635.        (irc-sentinel proc "finished\n")
  8636.        (delete-process proc))))
  8637.   (setq irc-idle-last-sent (irc-current-time)))
  8638.  
  8639.  
  8640. (defun irc-execute-away (text)
  8641.   "Usage: /AWAY [message]
  8642.  
  8643. Mark yourself as away, giving TEXT to people who send you private messages.
  8644. Without any arguments it will just insert a message about your current status."
  8645.   (interactive '(""))
  8646.   (let ((reason (if (and (string= "" text) (not irc-called-from-buffer))
  8647.             (read-string "Reason to be away? ")
  8648.             text)))
  8649.     (if (string= "" reason)
  8650.     (if irc-away
  8651.         (let ((pre (concat irc-msg-info-pre "You are ")))
  8652.           (irc-insert (concat "%smarked as being away: \"%s\", "
  8653.                   "use /HERE to remove the mark%s")
  8654.               pre
  8655.               (substring irc-away 2 -1)
  8656.               irc-msg-info-post))
  8657.         (irc-insert "%sYou are not currently marked as being away%s"
  8658.             irc-msg-info-pre
  8659.             irc-msg-info-post))
  8660.     (if (not irc-called-from-buffer)
  8661.         (progn (irc-insert "")
  8662.            (irc-insert "/AWAY %s" reason)))
  8663.     (irc-send (concat "AWAY :" reason))
  8664.     (setq irc-away (concat " [" reason "]")))
  8665.     (set-buffer-modified-p (buffer-modified-p)))
  8666.   (setq irc-idle-last-sent (irc-current-time)))
  8667.  
  8668.  
  8669. (defun irc-execute-here (cruft)
  8670.   "Usage: /HERE
  8671.  
  8672. Mark yourself as present (ie, not \"away\") on IRC.  Any arguments to this
  8673. command are ignored."
  8674.   (interactive '(""))
  8675.   (if (not irc-called-from-buffer)
  8676.       (progn (irc-insert "")
  8677.          (irc-insert "/HERE")))
  8678.   (irc-send "AWAY")
  8679.   (setq irc-away nil)
  8680.   (set-buffer-modified-p (buffer-modified-p))
  8681.   (setq irc-idle-last-sent (irc-current-time)))
  8682.  
  8683.  
  8684. (defun irc-execute-topic (topic)
  8685.   "Usage: /TOPIC channel [topic ...]
  8686.       or: /TOPIC [topic ...]
  8687.  
  8688. Make 'topic' the description of the named channel; * for channelname means
  8689. the current channel you're talking to.
  8690.  
  8691. With no topic, doesn't change the topic but only inspects it.
  8692.  
  8693. If no channel is given (and the first word of the topic doesn't looks like
  8694. a channel name), the command operates on the current channel you're talking to.
  8695. "
  8696.   (interactive '(""))
  8697.   (let* ((top1 (cond ((and (string= "" topic) (not irc-called-from-buffer))
  8698.               (read-string (concat "Topic for channel "
  8699.                        irc-channel
  8700.                        "? (RET to check) ")))
  8701.              (t topic)))
  8702.      (top (if (string-match "^\\([#&][^ :]+\\) *" top1)
  8703.           (substring top1 (match-end 0))
  8704.           top1))
  8705.      (chn (if (string-match "^\\([#&][^ :]+\\) *" top1)
  8706.           (subfield top1 1)
  8707.           irc-channel)))
  8708.     (if (not irc-called-from-buffer)
  8709.     (progn (irc-insert "")
  8710.            (irc-insert "/TOPIC %s %s" chn top)))
  8711.     (cond ((string= "0" chn)
  8712.        (irc-insert "%%You aren't on any channel."))
  8713.       ((and (irc-is-multijoinable-channel chn)
  8714.         (irc-server-has-settable-topic-on-multijoinable-channel))
  8715.        (if (string-match "^ *$" top)
  8716.            (irc-send (concat "TOPIC " chn))
  8717.            (irc-send (concat "TOPIC " chn " :" top))))
  8718.       ((irc-is-multijoinable-channel irc-channel)
  8719.        (irc-insert "%%Can't set the topic of a #channel."))
  8720.       (t (irc-send (concat "TOPIC :" top)))))
  8721.   (setq irc-idle-last-sent (irc-current-time)))
  8722.  
  8723.  
  8724. (defun irc-execute-oper (oper)
  8725.   "Usage: /OPER [ name [ password ]]
  8726.  
  8727. Attempt to become an IRC Operator.  Can take the name of the operator
  8728. and the password as arguments.  If name is missing then it will be read
  8729. from the minibuffer; if password is missing it will be read and hidden
  8730. in the minibuffer.
  8731.  
  8732. If you become an operator then the word \"operator\" will appear in the
  8733. minibuffer along with the mode name."
  8734.   (interactive '(""))
  8735.   (let* ((pair (cond
  8736.          ((string-match "^ *\\([^: ]+\\) +" oper)
  8737.           (cons (subfield oper 1) (substring oper (match-end 0))))
  8738.          ((string-match "^ *\\([^: ]+\\) *$" oper)
  8739.           (cons (subfield oper 1) ""))
  8740.          (t (cons "" ""))))
  8741.      (n (car pair))
  8742.      (n1 (if (string= "" n)
  8743.          (read-string (concat "Operator name at server "
  8744.                       (upcase irc-server)
  8745.                       "? "))
  8746.          n))
  8747.      (name (irc-nuke-whitespace n1))
  8748.      (p (irc-nuke-whitespace (cdr pair)))
  8749.      (p1 (if (and (string= "" p) (string< "" name))
  8750.          (irc-read-passwd (concat "Password for operator "
  8751.                       name
  8752.                       " at server "
  8753.                       (upcase irc-server)
  8754.                       "? "))
  8755.          p))
  8756.      (password (irc-nuke-whitespace p1)))
  8757.     (cond ((string= "" name)
  8758.        (irc-insert "%%No operator name given."))
  8759.       ((string= "" password)
  8760.        (irc-insert "%%No password given."))
  8761.       (t (if (not irc-called-from-buffer)
  8762.          (progn (irc-insert "")
  8763.             (irc-insert "/OPER ...")))
  8764.          (irc-send (concat "OPER " name " " password)))))
  8765.   (setq irc-idle-last-sent (irc-current-time)))
  8766.  
  8767.  
  8768. (defun irc-execute-summon (user)
  8769.   "Usage: /SUMMON login-name@server
  8770.  
  8771. Summon a user not on IRC to join IRC.  The argument provided may either be
  8772. a user name on the local machine or user@server, where server is another
  8773. machine on the IRC-net.  The user must be signed on to the specified server."
  8774.   (interactive '(""))
  8775.   (let* ((pair (cond ((string-match (concat "^ *\\([^ @]*\\) *@ *"
  8776.                         "\\([^ @]*\\) *$")
  8777.                     user)
  8778.               (cons
  8779.                (substring user (match-beginning 1) (match-end 1))
  8780.                (substring user (match-beginning 2) (match-end 2))))
  8781.              ((string-match "^ *\\([^ @]*\\) *$" user)
  8782.               (cons
  8783.                (substring user (match-beginning 1) (match-end 1))
  8784.                ""))
  8785.              (t (cons "" ""))))
  8786.      (login (irc-nuke-whitespace
  8787.          (if (and (string= "" (car pair)) (not irc-called-from-buffer))
  8788.              (read-string "Login-name of person to summon? ")
  8789.              (car pair))))
  8790.      (s (irc-nuke-whitespace
  8791.          (if (and (not (string= "" login))
  8792.               (string= "" (cdr pair))
  8793.               (not irc-called-from-buffer))
  8794.          (irc-read-object (format "Server \"%s\" is on? " login)
  8795.                   ""
  8796.                   (irc-recall-all 'irc-servernames))
  8797.          (cdr pair))))
  8798.      (server (if (string= "" s) irc-server s)))
  8799.     (if (string= "" login)
  8800.     (irc-insert "%%No login name given.")
  8801.     (progn (if (not irc-called-from-buffer)
  8802.            (progn (irc-insert "")
  8803.               (irc-insert "/SUMMON %s@%s" login server)))
  8804.            (irc-send (concat "SUMMON " login "@" server)))))
  8805.   (setq irc-idle-last-sent (irc-current-time)))
  8806.  
  8807.  
  8808. (defun irc-execute-users (host)
  8809.   "Usage: /USERS [ server ]
  8810.  
  8811. Get a list of the users signed on to \"server\".  If no server name is provided
  8812. then the server to which you are connected is used.  When called interactively
  8813. a prefix argument means to prompt for the server to query."
  8814.   (interactive '(""))
  8815.   (let* ((h (irc-nuke-whitespace
  8816.          (if (and (string= "" host) (not irc-called-from-buffer))
  8817.          (irc-read-object (format (concat "List users on which host?"
  8818.                           " (RET for %s) ")
  8819.                       irc-server)
  8820.                   ""
  8821.                   (irc-recall-all 'irc-servernames))
  8822.          host)))
  8823.      (hst (if (string= "" h) irc-server h)))
  8824.     (if (not irc-called-from-buffer)
  8825.     (progn (irc-insert "")
  8826.            (irc-insert "/USERS %s" hst)))
  8827.     (irc-send (concat "USERS " hst)))
  8828.   (setq irc-idle-last-sent (irc-current-time)))
  8829.  
  8830.  
  8831. (defun irc-execute-ignore (user)
  8832.   "Usage: /IGNORE username@host [event]
  8833.  
  8834. Used to ignore a user. The first argument is a specification of whose messages
  8835. to ignore. The second specifies which kind of messages should be ignored from
  8836. that particular user.
  8837.  
  8838. When specifying a user, you can give either just the user's login name at the
  8839. remote site (you can see what it is by doing a /whois), or you can give the
  8840. user's login name followed by a @ and the name of the user's and the host of
  8841. the user (i.e. the name of host the user's client is running on). You can give
  8842. a * instead of a username to ignore everyone at the given client machine.
  8843.  
  8844. One can either ignore all signs of the user, or just certain events. The events
  8845. include
  8846.     CTCP-ANSWER = Don't display any client to client protocol answers (they
  8847.                   *might* be spurios). Also, don't react on erronous answers.
  8848.     CTCP-QUERY  = Neither display nor answer any client to client protocoll
  8849.                   questions from the user.
  8850.     INVITE      = Don't display 
  8851.     JOIN
  8852.     NICK
  8853.     NOTICE
  8854.     PART
  8855.     PRIVMSG
  8856.     QUIT
  8857.     channel
  8858.     
  8859. THIS IS ALL NOT YET IMPLEMENTED.
  8860.  
  8861. "
  8862.   (interactive '(""))
  8863.   (let ((usr (irc-nuke-whitespace
  8864.           (if (and (string= "" user) (not irc-called-from-buffer))
  8865.           (irc-read-object "Ignore which user? (RET to view) "
  8866.                    user
  8867.                    (irc-recall-all 'irc-nicknames))
  8868.           user))))
  8869.     (if (string= "" usr)
  8870.     (if (not (irc-nothing-remembered-p 'irc-ignored-ppl))
  8871.         (irc-insert "%sYou are currently ignoring %s%s"
  8872.             irc-msg-info-pre
  8873.             (irc-subst-comma (mapconcat
  8874.                       'eval
  8875.                       (irc-recall-all 'irc-ignored-ppl)
  8876.                       ", ")
  8877.                      "and")
  8878.             irc-msg-info-post)
  8879.         (irc-insert "%sYou are not ignoring anyone%s"
  8880.             irc-msg-info-pre
  8881.             irc-msg-info-post))
  8882.     (progn (irc-remember usr 'irc-ignored-ppl)
  8883.            (irc-insert "%sYou are now ignoring %s%s"
  8884.                irc-msg-info-pre
  8885.                usr
  8886.                irc-msg-info-post))))
  8887.   (setq irc-idle-last-sent (irc-current-time)))
  8888.  
  8889.  
  8890. (defun irc-execute-info (nick)
  8891.   "Usage: /INFO nick
  8892.  
  8893. With * as the argument, show some information about who built IRC.
  8894. Else query a users client and show the information she/he has given
  8895. about her/himself. With no argument, show the information you have
  8896. given about yourself. You can set the information with the command
  8897. /USERINFO."
  8898.   (interactive '(""))
  8899.   (let* ((name (irc-nuke-whitespace
  8900.         (if (and (string= "" nick) (not irc-called-from-buffer))
  8901.             (irc-read-object
  8902.              (concat "Info for which user or server? (RET"
  8903.                  " for yourself, * for server program)"
  8904.                  " ")
  8905.              ""
  8906.              (irc-get-names-and-servers))
  8907.             nick))))
  8908.     (cond ((and (string= "" name)
  8909.         (stringp irc-userinfo))
  8910.        (let* ((pre (concat irc-msg-info-pre "You have "))
  8911.           (irc-msg-cont-used (make-string (length pre) ? )))
  8912.          (irc-insert (concat "%sgiven the information \"%s\" about"
  8913.                  " yourself. Use /USERINFO to change it."
  8914.                  " (Warning: /USERINFO with no argument will"
  8915.                  " clear the information)%s")
  8916.              pre
  8917.              irc-userinfo
  8918.              irc-msg-info-post)))
  8919.       ((string= "" name)
  8920.        (let* ((pre (concat irc-msg-info-pre "You haven't "))
  8921.           (irc-msg-cont-used (make-string (length pre) ? )))
  8922.          (irc-insert (concat "%sgiven any information about"
  8923.                  " yourself yet. Use /USERINFO to do so%s")
  8924.              pre
  8925.              irc-msg-info-post)))
  8926.       ((string= "*" name)
  8927.        (if (not irc-called-from-buffer)
  8928.            (progn (irc-insert "")
  8929.               (irc-insert "/INFO *")))
  8930.        (irc-send "INFO"))
  8931.       ((irc-is-receiver name)
  8932.        (if (not irc-called-from-buffer)
  8933.            (progn (irc-insert "")
  8934.               (irc-insert (concat "/INFO " name))))
  8935.        (irc-insert (concat "%sQuerying client of user %s for user supplied"
  8936.                    " information%s")
  8937.                irc-msg-info-pre name irc-msg-info-post)
  8938.        (irc-send (format "WHOIS %s %s" name name)) ;Get names servers idea
  8939.                     ;of names idle time.
  8940.        (irc-send
  8941.         (concat "PRIVMSG "
  8942.             name
  8943.             " :\001FINGER\001"
  8944.             "\001VERSION\001"
  8945.             "\001USERINFO\001"
  8946.             "\001SOURCE\001")))
  8947.       ((irc-is-hostname name)
  8948.        (if (not irc-called-from-buffer)
  8949.            (progn (irc-insert "")
  8950.               (irc-insert (concat "/ADMIN " name))))
  8951.        (irc-send (concat "ADMIN " name)))
  8952.       (t (irc-insert "%%Can't be a users nickname: \"%s\"." name))))
  8953.   (setq irc-idle-last-sent (irc-current-time)))
  8954.  
  8955.  
  8956. (defun irc-execute-userinfo (information)
  8957.   "Usage: /USERINFO [information]
  8958.  
  8959. Set some information (any text you want) to be given out to anybody
  8960. querying this client for it. With no argument, remove all information
  8961. you have given about yourself, making further queries \"draw a
  8962. blank\". You can use /INFO to query other clients. Be warned though,
  8963. other clients may or may not know of this query so you may sometimes
  8964. get back no answer or strange responses."
  8965.   (interactive '(""))
  8966.   (let ((info (if (and (string= "" information) (not irc-called-from-buffer))
  8967.           (read-string (concat "What information do you wish to"
  8968.                        " disclose? (RET to remove) "))
  8969.           information)))
  8970.     (let ((inf (irc-nuke-whitespace info)))
  8971.       (cond ((string= "" inf)
  8972.          (setq irc-userinfo nil)
  8973.          (irc-insert "%sCleared your information string%s"
  8974.              irc-msg-info-pre irc-msg-info-post))
  8975.         (t (setq irc-userinfo inf)
  8976.            (irc-insert "%sThe information string is: \"%s\"%s"
  8977.                irc-msg-info-pre
  8978.                irc-userinfo
  8979.                irc-msg-info-post)))))
  8980.   (setq irc-idle-last-sent (irc-current-time)))
  8981.  
  8982.  
  8983. (defun irc-execute-kill (user-etc)
  8984.   "Usage: /KILL user comment
  8985.  
  8986. Forcibly remove a user from IRC. The mandotory comment will be displayed to
  8987. the victim and to all the IRC operators online. The topic should be in English,
  8988. which after all is the lingua franca of IRC.
  8989.  
  8990. This command is reserved for IRC operators."
  8991.   (interactive '(""))
  8992.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\(.\\|\n\\)+ *$"
  8993.                     user-etc)
  8994.               (cons (subfield user-etc 1) (subfield user-etc 2)))
  8995.              ((string-match "^ *\\([^ ]+\\) *$" user-etc)
  8996.               (cons (subfield user-etc 1) ""))
  8997.              (t (cons "" ""))))
  8998.      (u (irc-nuke-whitespace (car pair)))
  8999.      (user (irc-nuke-whitespace
  9000.         (if (and (string= "" u) (not irc-called-from-buffer))
  9001.             (irc-read-object "Nuke which user? "
  9002.                      ""
  9003.                      (irc-recall-all 'irc-nicknames))
  9004.             u)))
  9005.      (c (irc-nuke-whitespace (cdr pair)))
  9006.      (comm (irc-nuke-whitespace
  9007.         (if (and (string= "" c)
  9008.              (string< "" user)
  9009.              (not irc-called-from-buffer))
  9010.             (read-string "Comment? (In English please) ")
  9011.             c))))
  9012.     (if (string< "" user)
  9013.     (if (string< "" comm)
  9014.         (progn (if (not irc-called-from-buffer)
  9015.                (progn (irc-insert "")
  9016.                   (irc-insert "/KILL %s %s" user comm)))
  9017.            (irc-send (concat "KILL " user " " comm)))
  9018.         (irc-insert "%%No comment given to /KILL command."))
  9019.     (irc-insert "%%No user given, no killing take place.")))
  9020.   (setq irc-idle-last-sent (irc-current-time)))
  9021.  
  9022.  
  9023. (defun irc-execute-invite (user)
  9024.   "Usage: /INVITE user [ channel ]
  9025.  
  9026. Ask \"user\" on IRC to join \"channel\".  If channel is 0, * or not provided
  9027. then the invitation de faults to your current channel, ie the on you're talking
  9028. to. If you are not talking to any channel and channel is 0 or not provided then
  9029. no invitation is sent -- you can't invite someone to \"go private\". When
  9030. called interactively, channel is set to the prefix argument; with no argument
  9031. or - the current channel is assumed."
  9032.   (interactive '(""))
  9033.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$"
  9034.                     user)
  9035.               (cons
  9036.                (substring user (match-beginning 1) (match-end 1))
  9037.                (substring user (match-beginning 2) (match-end 2))))
  9038.              ((string-match " *\\([^ ]+\\) *$" user)
  9039.               (cons (substring user (match-beginning 1) (match-end 1))
  9040.                 ""))
  9041.              (t (cons "" ""))))
  9042.      (usr (irc-nuke-whitespace
  9043.            (if (and (string= "" (car pair)) (not irc-called-from-buffer))
  9044.            (irc-read-object "Invite which user? "
  9045.                     ""
  9046.                     (irc-recall-all 'irc-nicknames))
  9047.            (car pair))))
  9048.      (c1 (irc-nuke-whitespace
  9049.           (if (and (string= "" (cdr pair))
  9050.                (string< "" usr)
  9051.                (not irc-called-from-buffer))
  9052.           (irc-read-object
  9053.            (if (string= "0" irc-channel)
  9054.                (format "Invite \"%s\" to which channel? " usr)
  9055.                (format "Invite \"%s\" %s \"%s\") "
  9056.                    usr
  9057.                    "to which channel? (RET for"
  9058.                    irc-channel))
  9059.            ""
  9060.            (irc-recall-all 'irc-subscribed-channels))
  9061.           (cdr pair))))
  9062.      (chn (if (string= "" c1) irc-channel c1)))
  9063.     (cond ((string= "" usr) (irc-insert "%%No users nick given."))
  9064.       ((string= "0" chn) (irc-insert "%%Can't invite to \"channel\" 0."))
  9065.       (t (if (not irc-called-from-buffer)
  9066.          (progn (irc-insert "")
  9067.             (irc-insert "/INVITE %s %s"
  9068.                     usr
  9069.                     (irc-clean-up-message chn))))
  9070.          (irc-send (format "INVITE %s %s" usr chn)))))
  9071.   (setq irc-idle-last-sent (irc-current-time)))
  9072.  
  9073.  
  9074. (defun irc-execute-names (channel)
  9075.   "Usage: /NAMES [ channel ]
  9076.  
  9077. Show which channels everyone is on.  Optional argument \"channel\" means
  9078. to show just the users on that channel.  * means to show people on the
  9079. current channel.
  9080.  
  9081. Each line starts with a column for the channel number and is followed
  9082. by the nicknames of the people on that channel.  Users who are on
  9083. private channels or who are not on any channel are listed as
  9084. \"Private\".  Users who are on secret channels (channels less than 0)
  9085. are not shown at all.  A %-sign is appended to the current channel's
  9086. name or number."
  9087.   (interactive '(""))
  9088.   (let* ((c (if (and (string= "" channel) (not irc-called-from-buffer))
  9089.          (irc-read-object (format
  9090.                   "Names of persons on which channel? (%s) "
  9091.                   (if (string= "0" irc-channel)
  9092.                       "RET for all"
  9093.                       (concat "RET for all, * for "
  9094.                           irc-channel)))
  9095.                  ""
  9096.                  (irc-recall-all 'irc-subscribed-channels))
  9097.         channel))
  9098.      (chn (if (string= "*" c) irc-channel c)))
  9099.     (if (string= "" chn)
  9100.      (let ((lst (irc-recall-all 'irc-services)))
  9101.       (irc-forget-all 'irc-nicknames)
  9102.       (while lst
  9103.         (irc-remember (car lst) 'irc-nicknames)
  9104.         (setq lst (cdr lst)))))
  9105.     (if (not irc-called-from-buffer)
  9106.      (progn (irc-insert "")
  9107.            (irc-insert "/NAMES %s" chn)))
  9108.     (irc-send (concat "NAMES " chn))
  9109.     (if (not (and (irc-terminal-is-slow)
  9110.           (irc-server-has-end-of-names)))
  9111.     (progn (irc-insert "")
  9112.            (irc-insert "Name of channel Users Nicknames")
  9113.            (irc-insert "--------------- ----- ---------")
  9114.            (set-buffer-modified-p (buffer-modified-p)))))
  9115.   (setq irc-idle-last-sent (irc-current-time)))
  9116.  
  9117.  
  9118. (defun irc-execute-wall (message)
  9119.   "Usage: /WALL message
  9120.  
  9121. Send 'message' to everyone on IRC.  This can only be done by IRC Operators."
  9122.   (interactive '(""))
  9123.   (let ((msg (if (and (string= "" message) (not irc-called-from-buffer))
  9124.          (read-string "Message to send to everyone? ")
  9125.          message)))
  9126.     (if (string= "" msg)
  9127.     (irc-insert "%%No message.")
  9128.     (if (not irc-called-from-buffer)
  9129.         (progn (irc-insert "")
  9130.            (irc-insert "/WALL %s" msg)))
  9131.     (irc-send (concat "WALL " msg))))
  9132.   (setq irc-idle-last-sent (irc-current-time)))
  9133.  
  9134.  
  9135. (defun irc-execute-wallops (message)
  9136.   "Usage: /WALLOPS message
  9137.  
  9138. Send 'message' to every enabled IRC-operator on IRC.
  9139. If you got any problems you think an enabled IRC operator might be the right
  9140. person to help you with, *use* /WALLOPS. (But please don't *ABuse* it)."
  9141.   (interactive '(""))
  9142.   (let ((msg (if (and (string= "" message) (not irc-called-from-buffer))
  9143.          (read-string "Message to send to all enabled IRC operators? ")
  9144.          message)))
  9145.     (if (string< "" msg)
  9146.     (let ((data (format irc-msg-sent "all ENABLED operators of IRC")))
  9147.       (if (not irc-called-from-buffer)
  9148.           (progn (irc-insert "")
  9149.              (irc-insert "/WALLOPS %s" msg)))
  9150.       (irc-send (concat "WALLOPS " msg))
  9151.       (if irc-confirm
  9152.           (irc-insert "%s%s" (make-string
  9153.                   (max 0 (- (window-width
  9154.                          (get-buffer-window
  9155.                           (current-buffer)))
  9156.                         (length data)
  9157.                         1))
  9158.                   ? )
  9159.               data)))
  9160.     (irc-insert "%%No message given, no message sent.")))
  9161.   (setq irc-idle-last-sent (irc-current-time)))
  9162.  
  9163.  
  9164. (defun irc-execute-rehash (cruft)
  9165.   "Usage: /REHASH
  9166.  
  9167. Force the server to which you are connected to reread it's irc.conf file.
  9168. Arguments are ignored.  This command is only available to IRC Operators."
  9169.   (interactive '(""))
  9170.   (if (not irc-called-from-buffer)
  9171.       (progn (irc-insert "")
  9172.          (irc-insert "/REHASH")))
  9173.   (irc-send "REHASH")
  9174.   (setq irc-idle-last-sent (irc-current-time)))
  9175.  
  9176.  
  9177. (defun irc-execute-trace (server)
  9178.   "Usage: /TRACE [ server ]
  9179.  
  9180. Find the route from the server to which you are attached to 'server'; if the
  9181. server argument is not provided then the servers to which the current server
  9182. is directly connected are listed.  This command is only available to IRC
  9183. Operators."
  9184.   (interactive '(""))
  9185.   (let ((srvr (if (and (string= "" server) (not irc-called-from-buffer))
  9186.           (irc-read-object (concat "Trace route to server/user?"
  9187.                        " (RET for " irc-server ") ")
  9188.                    ""
  9189.                    (irc-get-names-and-servers))
  9190.           server)))
  9191.     (if (not irc-called-from-buffer)
  9192.     (progn (irc-insert "")
  9193.            (irc-insert "/TRACE %s" srvr)))
  9194.     (irc-send (concat "TRACE " srvr)))
  9195.   (setq irc-idle-last-sent (irc-current-time)))
  9196.  
  9197.  
  9198. (defun irc-execute-squit (server)
  9199.   "Usage: /SQUIT [ server ]
  9200.  
  9201. Shut down a server-to-server link.
  9202. The link shut down is the the one next farest away from you, ie if you do a
  9203. /SQUIT BYE.EDU and the path to it is your.server.edu!a!b!bye.edu, then the
  9204. link between b and bye.edu will be disconnected.
  9205.  
  9206. You have to be an enabled IRC operator to issue this conmmand."
  9207.   (interactive '(""))
  9208.   (let ((srvr (if (and (string= "" server) (not irc-called-from-buffer))
  9209.           (irc-read-object "Shut down link to which server? "
  9210.                    ""
  9211.                    (irc-recall-all 'irc-servernames))
  9212.           server)))
  9213.     (if (not irc-called-from-buffer)
  9214.     (progn (irc-insert "")
  9215.            (irc-insert "/SQUIT %s" srvr)))
  9216.     (irc-send (concat "SQUIT " srvr))
  9217.     (irc-insert "%sClosing the link to server %s%s"
  9218.         irc-msg-info-pre srvr irc-msg-info-post))
  9219.   (setq irc-idle-last-sent (irc-current-time)))
  9220.  
  9221.  
  9222. (defun irc-execute-connect (new)
  9223.   "Usage: /CONNECT [ newhost [ port [remoteserver ] ] ]
  9224.  
  9225. Connect the local server to SERVER on tcp-port PORT.
  9226.  
  9227. You have to be an enabled IRC operator to issue this conmmand."
  9228.   (interactive '(""))
  9229.   (let* ((tri (cond ((string-match
  9230.               (concat "^ *\\([^ ]+\\) +\\([^ ]+\\) +"
  9231.                   "\\([^ ]+\\) *$")
  9232.               new)
  9233.              (cons (subfield new 1)
  9234.                (cons (subfield new 2)
  9235.                  (subfield new 3))))
  9236.             ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$"
  9237.                    new)
  9238.              (cons (subfield new 1)
  9239.                (cons (subfield new 2)
  9240.                  "")))
  9241.             ((string-match "^ *\\([^ ]+\\) *$" new)
  9242.              (cons (subfield new 1) (cons "" "")))
  9243.             (t (cons "" (cons "" "")))))
  9244.      (h1 (car tri))
  9245.      (h2 (if (and (string= "" h1) (not irc-called-from-buffer))
  9246.          (irc-read-object (concat "Connect server-link to which"
  9247.                       " internet host? ")
  9248.                   ""
  9249.                   (irc-recall-all 'irc-servernames))
  9250.          h1))
  9251.      (new-host (irc-nuke-whitespace h2))
  9252.      (p1 (car (cdr tri)))
  9253.      (p2 (if (and (string= "" p1)
  9254.               (string< "" new-host)
  9255.               (not irc-called-from-buffer))
  9256.          (irc-read-object (concat "Use which TCP-port for"
  9257.                       " server-link? (RET for 6667) ")
  9258.                   ""
  9259.                   (list "194" "6667"))
  9260.          p1))
  9261.      (p3 (irc-nuke-whitespace p2))
  9262.      (new-port (if (string= "" p3)
  9263.                6667 
  9264.                (string-to-int p3)))
  9265.      (s1 (cdr (cdr tri)))
  9266.      (s2 (if (and (string= "" s1)
  9267.               (string< "" new-host)
  9268.               (not irc-called-from-buffer))
  9269.          (irc-read-object (concat "Execute connect command at which"
  9270.                       " (reachable) server? (RET for"
  9271.                       " local) ")
  9272.                   ""
  9273.                   (irc-recall-all 'irc-servernames))
  9274.          s1))
  9275.      (s3 (irc-nuke-whitespace s2))
  9276.      (remote-server (if (string= "" s3) irc-server s3)))
  9277.     (cond ((string-match " " new-host)
  9278.        (irc-insert "%%Spaces aren't allowed in hostnames (%s)." new-host))
  9279.       ((string-match " " remote-server)
  9280.        (irc-insert "%%Spaces aren't allowed in servername (%s)."
  9281.                remote-server))
  9282.       (t (if (not irc-called-from-buffer)
  9283.          (progn (irc-insert "")
  9284.             (if (string= "" new-host)
  9285.                 (irc-insert "/CONNECT")
  9286.                 (irc-insert "/CONNECT %s %d %s"
  9287.                     new-host new-port remote-server))))
  9288.          (if (string= "" new-host)
  9289.          (irc-insert "%%No host to connect too given.")
  9290.          (irc-send (format "CONNECT %s %d %s"
  9291.                    new-host new-port remote-server))
  9292.          (irc-insert (concat "%sConnecting a server-link to host %s on"
  9293.                      " port %d from server %s%s")
  9294.                  irc-msg-info-pre
  9295.                  (upcase new-host)
  9296.                  new-port
  9297.                  (upcase remote-server)
  9298.                  irc-msg-info-post)))
  9299.       (setq irc-idle-last-sent (irc-current-time)))))
  9300.  
  9301. ;; /command just for the client  (need /stamp /alias /unalias)
  9302. (defun irc-execute-send (slist)
  9303.   "Usage: /SEND [ sendlist | - ]
  9304.  
  9305. Set the default sendlist for IRC messages.  This is a comma separated list
  9306. of the intended recipient(s) of messages which do not have an explicit
  9307. sendlist.  '-' as an argument means to disable the default sendlist; every
  9308. message sent then must have an explicit recipient provided with the message.
  9309. Without any arguments this command just displays the current default sendlist.
  9310.  
  9311. Each item specified is checked to see whether you can send there; ambiguous
  9312. references to users are not allowed.
  9313.  
  9314. \"*\" is always allowed and means to send to the current channel, ie the
  9315. channel you are talking to.
  9316. If no item in the new list can be set then the sendlist is not changed."
  9317.   (interactive "sDefault recipient(s) for messages? ")
  9318.   ;; blast some whitespace
  9319.   (setq slist (irc-nuke-whitespace slist))
  9320.   (let (matches)
  9321.     ;; first the easiest case
  9322.     (if (string= "-" slist) (setq irc-default-to nil)
  9323.     (setq matches
  9324.           (delq nil                   ; more indentation fun.  can someone
  9325.             (mapcar               ; recommend a good style manual?
  9326.              (function (lambda (arg)
  9327.                (setq matches (irc-check-list
  9328.                       (irc-recall-all 'irc-nicknames)
  9329.                       arg))
  9330.                (cond
  9331.              ((string= arg "*") arg)
  9332.              ((string= arg "0")
  9333.               (irc-insert "%%You can't send to channel 0.")
  9334.               nil)
  9335.              ((= (length matches) 1) (car matches))
  9336.              ((eq matches nil)
  9337.               (irc-insert "%%No names found to match \"%s\"." arg)
  9338.               nil)
  9339.              (t (irc-insert (concat "%%Ambiguous recipient %s;"
  9340.                         " could be %s.")
  9341.                     arg
  9342.                     (irc-subst-comma
  9343.                      (mapconcat (function (lambda (arg)
  9344.                               (concat "\"" arg "\"")))
  9345.                             matches
  9346.                             ", ")
  9347.                      "or"))
  9348.                 nil))))
  9349.              (irc-burst-comma slist))))
  9350.     (if matches
  9351.         (setq irc-default-to (concat (mapconcat 'eval matches ",") ";"))
  9352.         (or (string= "" slist)  ; only print the error if tried to set it.
  9353.         (irc-insert "%%No matches -- sendlist not changed."))))
  9354.     (cond ((not irc-default-to)
  9355.        (irc-insert (concat "%%Your default sendlist is disabled. (Ie you"
  9356.                    " are not sending to anyone when failing to"
  9357.                    " give an explicit receiver)")))
  9358.       ((string= irc-default-to "*;")
  9359.        (irc-insert (concat "%sYou are now using the default send list (ie"
  9360.                    " sending to the current channel (%s) when"
  9361.                    " failing to give an explicit receiver)%s")
  9362.                irc-msg-info-pre
  9363.                (if (string= "0" irc-channel) "none" irc-channel)
  9364.                irc-msg-info-post))
  9365.       (t (irc-insert (concat "%sYou are sending to %s, use /SEND * to"
  9366.                  " get back default sendlist%s")
  9367.              irc-msg-info-pre
  9368.              (irc-subst-comma
  9369.               (mapconcat 'eval
  9370.                      (irc-burst-comma
  9371.                       (substring irc-default-to 0
  9372.                          (1- (length irc-default-to))))
  9373.                      ", ")
  9374.               "and")
  9375.              irc-msg-info-post))))
  9376.   (setq irc-idle-last-sent (irc-current-time)))
  9377.  
  9378.  
  9379. (defun irc-execute-service (service)
  9380.   "Usage: /SERVICE [ [+]nick | -nick ]
  9381.  
  9382. Show or update list of services. A service is an automaton which looks
  9383. like a normal user, ie it has a nickname. It doesn't act as a normal
  9384. user though; normaly you can ask it for some service. For instance, at
  9385. NICKSERV you can register your nick name (do \"nickserv; help\" for
  9386. more information). Services often talk to you with so called NOTICE's.
  9387. When a service isn't marked as being one, these messages will be
  9388. displayed in a somewhat annoying format. Use this command to get a
  9389. nicer display.
  9390.  
  9391. With no argument, show which nicknames are assumed to be services."
  9392.   (interactive '(""))
  9393.   (let* ((pair (cond ((string-match (concat "^ *\\(+\\|-\\) *"
  9394.                         "\\([^ ]+\\) *$")
  9395.                     service)
  9396.               (cons (subfield service 1) (subfield service 2)))
  9397.              ((string-match "^ *\\([^ ]+\\) *$" service)
  9398.               (cons "+" (subfield service 1)))
  9399.              (t (cons "" ""))))
  9400.      (a (car pair))
  9401.      (a2 (irc-nuke-whitespace
  9402.           (if (and (string= "" a) (not irc-called-from-buffer))
  9403.           (irc-read-object (concat "Mark or unmark nick as"
  9404.                        " service? (RET to mark) ")
  9405.                    ""
  9406.                    '("mark" "unmark"))
  9407.           a)))
  9408.      (action (if (string-match "\\(unmark\\|-\\)" (downcase a2)) nil t))
  9409.      (n (cdr pair))
  9410.      (nick (irc-nuke-whitespace
  9411.         (if (and (string= "" n) (not irc-called-from-buffer))
  9412.             (irc-read-object (format "%sark which %s as service? (%s) "
  9413.                          (if action "M" "Unm")
  9414.                          (if action "nick" "service")
  9415.                          "RET to view existing")
  9416.                      ""
  9417.                      (if action
  9418.                      (irc-recall-all 'irc-nicknames)
  9419.                      (irc-recall-all 'irc-services)))
  9420.             n)))
  9421.      (s-list (irc-recall-all 'irc-services))
  9422.      (s-len (length s-list))
  9423.      (plural (if (= 1 s-len) "" "s"))
  9424.      (lst (irc-listify s-list ", " "and")))
  9425.     (if (not irc-called-from-buffer)
  9426.     (progn (irc-insert "")
  9427.            (irc-insert "/SERVICE %s%s" (if action "+" "-") nick)))
  9428.     (if (string= "" nick)
  9429.     (if (irc-nothing-remembered-p 'irc-services)
  9430.         (irc-insert "%sNo users marked as automatons%s"
  9431.             irc-msg-info-pre irc-msg-info-post)
  9432.         (irc-insert (concat "%s%d \"user%s\" marked as being"
  9433.                 " automaton%s (which provide some service):"
  9434.                 " %s%s")
  9435.             irc-msg-info-pre s-len plural plural lst
  9436.             irc-msg-info-post))
  9437.     (let ((irc-called-from-buffer t))
  9438.       (irc-insert "%s%sing \"%s\" %s being treated as a service%s"
  9439.               irc-msg-info-pre
  9440.               (if action "Add" "Remov")
  9441.               nick
  9442.               (if action "as" "from")
  9443.               irc-msg-info-post)
  9444.       (if action
  9445.           (irc-remember nick 'irc-services)
  9446.           (irc-forget nick 'irc-services))
  9447.       (irc-execute-service ""))))
  9448.   (setq irc-idle-last-sent (irc-current-time)))
  9449.  
  9450.  
  9451. (defun irc-execute-event (events)
  9452.   "Usage: /EVENT [ [+]event | -event ] [...]
  9453.  
  9454. Set the list of events to notify you about with a message.  Notification
  9455. is a one-line message inserted when someone causes that event to occur.
  9456. Events are added with +event or simply event; they are removed with -event.
  9457. + adds all supported events and - removes all supported events.  More than
  9458. one event can be specified in the arguments.  In case of conflict, the argument
  9459. which appears later overrides the argument with which it conflicts.
  9460.  
  9461. Currently supported by /EVENT are the \"ctcp\", \"join\", \"nick\", \"quit\"
  9462. and \"topic\" events.
  9463.  
  9464. CTCP happens whenever someone send you a CTCP query.
  9465. Join happens whenever someone enters or leaves a channel which you are on.
  9466. Nick occurs when someone changes nicknames; recognition of this event is
  9467. currently limited to when the person making the change is on the same channel
  9468. as you.
  9469. Quit happens when someone quits from IRC and you see it.
  9470. Topic happens when the topic of a channel you listen to is changed.
  9471.  
  9472.  
  9473. "
  9474.   (interactive "sNotify for events: ")
  9475.   ;; die scurvy whitespace
  9476.   (setq events (irc-nuke-whitespace events))
  9477.   (let ((recog '(ctcp join nick quit topic))
  9478.     (str events)
  9479.     sym
  9480.     off
  9481.     event
  9482.     (count 0))
  9483.     (while (string< "" events)
  9484.       ;; multiple args are okay.  we'll do one at a time.
  9485.       (setq str (substring events 0 (or (string-match " +" events)
  9486.                     (string-match "$" events)))
  9487.         events (substring events (match-end 0)))
  9488.       (string-match "^\\([---+]?\\)" str)
  9489.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  9490.         event (substring str (match-end 0))
  9491.         sym (if (string= "" event) nil
  9492.             (car (delq nil    ; do some minor pattern matching
  9493.                    (mapcar    ; to find the intended event
  9494.                 (function
  9495.                  (lambda (arg)
  9496.                   (if (string-match
  9497.                        (concat "^" (regexp-quote event))
  9498.                        (prin1-to-string arg))
  9499.                       arg))) recog)))))
  9500.       (cond
  9501.     ((and (string= "" event) off) (setq irc-events nil))
  9502.     ;; the only way for this to happen and not the above is str == "+"
  9503.     ((string= "" event) (setq irc-events recog))
  9504.     ((null sym)
  9505.      (irc-insert "%sEvent: Unknown argument \"%s\"%s"
  9506.              irc-msg-info-pre
  9507.              event
  9508.              irc-msg-info-post))
  9509.     (t (setq irc-events (if off (delq sym irc-events)
  9510.                   (if (not (memq sym irc-events)) ; avoid
  9511.                       (cons sym irc-events) ; redundancy
  9512.                       irc-events))))))
  9513.     (if irc-events
  9514.     (irc-insert "%sEvent notification is currently enabled for %s%s"
  9515.             irc-msg-info-pre
  9516.             (irc-subst-comma (mapconcat 'prin1-to-string irc-events
  9517.                         ", ") "and")
  9518.             irc-msg-info-post)
  9519.     (irc-insert "%sNotification is currently disabled%s"
  9520.             irc-msg-info-pre
  9521.             irc-msg-info-post)))
  9522.   (setq irc-idle-last-sent (irc-current-time)))
  9523.  
  9524.  
  9525. (defun irc-execute-confirm (str)
  9526.   "Usage: /CONFIRM [ + | - ]
  9527.  
  9528. Turn on message confirmation with + or off with -.  Any other arguments or no
  9529. arguments just gives a message about the current setting.
  9530.  
  9531. Message confirmation is a line indicating to whom a message was sent.
  9532. Occasionally this will say that a message has been sent to someone who
  9533. was not present but another message soon after will set the record straight."
  9534.   (interactive '(""))
  9535.   (let* ((c1 (irc-nuke-whitespace
  9536.           (if (and (string= "" str) (not irc-called-from-buffer))
  9537.           (irc-read-object "Turn confirm on or off? (RET to view) "
  9538.                    ""
  9539.                    '("+" "on" "-" "off"))
  9540.           str)))
  9541.      (conf (cond ((string-match "^\\(on\\|+\\)$" c1) "+")
  9542.              ((string-match "^\\(off\\|-\\)$" c1) "-")
  9543.              ((string= "" c1) "")
  9544.              (t nil))))
  9545.     (if (not conf)
  9546.     (irc-insert "%Huh? Try /HELP CONFIRM.")
  9547.     (progn (if (string= "+" conf) (setq irc-confirm t))
  9548.            (if (string= "-" conf) (setq irc-confirm nil))
  9549.            (irc-insert "%sMessage confirmation is %s%s"
  9550.                irc-msg-info-pre
  9551.                (if irc-confirm "on" "off")
  9552.                irc-msg-info-post))))
  9553.   (setq irc-idle-last-sent (irc-current-time)))
  9554.  
  9555.  
  9556. (defun irc-execute-notify (users)
  9557.   "Usage: /NOTIFY [ + | [-]nick ... ]
  9558.  
  9559. Add and delete nicknames from your notifylist. When people on the list get
  9560. detected, you will be notified. When they quit IRC, you will be notified of
  9561. this fact too.
  9562.  
  9563. With no argument, show the people on list, no matter if they've been
  9564. detected or not.
  9565.  
  9566. With a list of nicknames as the argument (each optionally prepended by
  9567. a \"-\"), add those nicknames to the list, unless a \"-\" was
  9568. prepended, in which case the nickname is removed."
  9569.   (interactive '(""))
  9570.   (let* ((str (irc-nuke-whitespace
  9571.            (if (and (string= "" users) (not irc-called-from-buffer))
  9572.            (irc-read-object
  9573.             "Notify when detecting whom? (RET to show list) "
  9574.             ""
  9575.             (irc-recall-all 'irc-nicknames))
  9576.            users)))
  9577.      (list (mapcar 'irc-nuke-whitespace (reverse (irc-burst-comma str))))
  9578.      (added ())
  9579.      (removed ())
  9580.      (show-current (null list)))
  9581.     (while (not (null list))
  9582.       (let* ((subtract (= ?- (aref (car list) 0)))
  9583.          (name (if subtract (substring (car list) 1) (car list)))
  9584.          (is-in-list (irc-recall name 'irc-notify-looked-for)))
  9585.     (cond ((not (irc-is-nickname name))
  9586.            (irc-insert "%%This doesn't look like a nickname: \"%s\"."
  9587.                name))
  9588.           (subtract
  9589.            (if is-in-list
  9590.            (setq removed (cons name removed)))
  9591.            (irc-forget (substring (car list) 1) 'irc-notify-looked-for))
  9592.           (t (if (not is-in-list)
  9593.              (setq added (cons name added)))
  9594.          (irc-remember (car list) 'irc-notify-looked-for))))
  9595.       (setq list (cdr list)))
  9596.     (irc-who-is-on (irc-recall-all 'irc-notify-looked-for))
  9597.     (if show-current
  9598.     (let* ((detected (irc-recall-all 'irc-notify-detected))
  9599.            (looked-for (irc-recall-all 'irc-notify-looked-for))
  9600.            (pre (format "%sOf the persons "
  9601.                 irc-msg-info-pre))
  9602.            (irc-msg-cont-used (make-string (length pre) ? )))
  9603.       (if (null looked-for)
  9604.           (irc-insert "%sYou're not looking for anybody%s"
  9605.               irc-msg-info-pre irc-msg-info-post)
  9606.           (progn
  9607.         (irc-insert "%syou want notifications for (%s),"
  9608.                 pre
  9609.                 (irc-listify looked-for ", " "and"))
  9610.         (setq irc-msg-cont-used (substring
  9611.                      irc-msg-cont-used
  9612.                      0
  9613.                      (- (length "the persons "))))
  9614.         (irc-insert "%s%s on IRC at the moment%s"
  9615.                 irc-msg-cont-used
  9616.                 (if (null detected)
  9617.                 "no one is"
  9618.                 (concat
  9619.                  "the person"
  9620.                  (if (= 1 (length detected)) " " "s ")
  9621.                  (irc-listify detected ", " "and")
  9622.                  (if (= 1 (length detected)) " is" " are")))
  9623.                 irc-msg-info-post))))
  9624.     (let* ((a (if added
  9625.               (format "Added %s to"
  9626.                   (irc-listify (reverse added) ", " "and"))))
  9627.            (r (if removed
  9628.               (format "%semoved %s from"
  9629.                   (if added ", and r" "R")
  9630.                   (irc-listify (reverse removed) ", " "and"))))
  9631.            (str (cond ((and added removed) (format "%s%s" a r))
  9632.               (added a)
  9633.               (removed r)
  9634.               (t "No change to")))
  9635.            (indent (or (and (string-match " " str) (1+ (match-end 0)))
  9636.                irc-msg-cont-used))
  9637.            (irc-msg-cont-used (make-string indent ? )))
  9638.       (irc-insert "%s%s the notification list%s"
  9639.               irc-msg-info-pre str irc-msg-info-post)))))
  9640.  
  9641.  
  9642. (defun irc-execute-unignore (user)
  9643.   "Usage: /UNIGNORE user | + | -
  9644.  
  9645. Stop ignoring a user who has been /IGNOREd.  The special arguments + or -
  9646. mean to stop ignoring everyone who is being ignored."
  9647.   (interactive '(""))
  9648.   (let ((usr (irc-nuke-whitespace
  9649.           (if (and (string= "" user) (not irc-called-from-buffer))
  9650.           (irc-read-object "Stop ignoring whom? (RET to view) "
  9651.                    ""
  9652.                    (irc-recall-all 'irc-ignored-ppl))
  9653.           user))))
  9654.     (if (string= "" usr)
  9655.     (if (irc-nothing-remembered-p 'irc-ignored-ppl)
  9656.         (irc-insert "%sYou are not ignoring anyone%s"
  9657.             irc-msg-info-pre
  9658.             irc-msg-info-post)
  9659.         (irc-insert "%sYou are currently ignoring %s%s"
  9660.             irc-msg-info-pre
  9661.             (irc-subst-comma
  9662.              (mapconcat 'eval
  9663.                     (irc-recall-all 'irc-ignored-ppl)
  9664.                     ", ")
  9665.              "and")
  9666.             irc-msg-info-post))
  9667.     (if (string-match "^[---+]$" usr)
  9668.         (progn (irc-forget-all 'irc-ignored-ppl)
  9669.            (irc-insert "%sYou are no longer ignoring anyone%s"
  9670.                    irc-msg-info-pre
  9671.                    irc-msg-info-post))
  9672.         (if (string< "" user)
  9673.         (progn (irc-forget user 'irc-ignored-ppl)
  9674.                (irc-insert "%sYou are no longer ignoring %s%s"
  9675.                    irc-msg-info-pre
  9676.                    user
  9677.                    irc-msg-info-post))))))
  9678.   (setq irc-idle-last-sent (irc-current-time)))
  9679.  
  9680.  
  9681. (defun irc-execute-kick (kick)
  9682.   "Usage: /KICK user [channel]
  9683.    or: /KICK channel user
  9684.  
  9685. Kick user out from a channel. If no channel is given, defaults to the channel
  9686. you are currently talking to."
  9687.   (interactive)
  9688.   (let* ((c (if (string-match "^ *[^: ]+ +\\([^: ]+\\) *$" kick)
  9689.         (substring kick (match-beginning 1) (match-end 1))
  9690.         irc-channel))
  9691.      (chn (if (string= c "*") irc-channel c))
  9692.      (usr (if (string-match "^ *\\([^: ]+\\) +[^: ]+ *$" kick)
  9693.            (substring kick (match-beginning 1) (match-end 1))
  9694.            kick))
  9695.      (reversed (and (or (irc-is-channelname usr)
  9696.                 (string= usr "*"))
  9697.             (irc-is-nickname chn)))
  9698.      (chan (if reversed (if (string= "*" usr) irc-channel usr) chn))
  9699.      (user (if reversed chn usr)))
  9700.     (if (string-match "^ *$" user)
  9701.     (irc-insert "%%No user given, use /HELP KICK for help.")
  9702.     (if (not irc-called-from-buffer)
  9703.         (progn (irc-insert "")
  9704.            (irc-insert "/KICK %s %s" user chan)))
  9705.     (irc-send (concat "KICK " chan " :" user))))
  9706.   (setq irc-idle-last-sent (irc-current-time)))
  9707.  
  9708.  
  9709. (defun irc-execute-mail (m)
  9710.   "Usage: /MAIL [command [arguments]]
  9711.  
  9712. Give commands to the MAIL subsystem of IRC. This has nothing to do with
  9713. \"regular email\".
  9714. Do \"/MAIL HELP\" for seeing what commands are supported and how to use them.
  9715. Be warned though, the syntax in the help is somewhat ... nonstandard."
  9716.   (interactive)
  9717.   (if (not irc-called-from-buffer)
  9718.       (progn (irc-insert "")
  9719.          (irc-insert "/MAIL %s" m)))
  9720.   (irc-send (concat "MAIL " m))
  9721.   (setq irc-idle-last-sent (irc-current-time)))
  9722.  
  9723.  
  9724. (defun irc-execute-stats (args)
  9725.   "Usage: /STATS [ type [ server ] ]
  9726.  
  9727. Get statistics from a server. There are different kind of statistics
  9728. one can obtain:
  9729.     C    tells which other servers etc a server will accept
  9730.         connections from and will connect to
  9731.     H    tells which servers are treated as HUBS and LEAVES
  9732.     I    tells which masks are used to allow client connections
  9733.         at a server
  9734.     K    tells which user isn't allowed to use a specific server
  9735.     L    tells how much data has passed over the currently
  9736.         active links
  9737.         M       tells how many times the different (server level) commands
  9738.                 has been seen by the server
  9739.         N       same as C
  9740.     Q    tells which servers are in quarantine, ie for which servers
  9741.         a server disconnects its local link in that direction
  9742.         R       tells some internal resource statistics regarding traffic on
  9743.                 the server
  9744.         S       tells which services are connected to a server
  9745.         U       tells the uptime of a server
  9746.     Y    tells the connection classes in effect at a server
  9747.         Z       tells some internal resource statistics regarding the servers
  9748.                 memory usage
  9749.  
  9750. If no server is given, the current server (ie the one your client is
  9751. connected to at the time of the command) is used."
  9752.   (interactive '(""))
  9753.   (let* ((pair (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) *$" args)
  9754.               (cons (subfield args 1) (subfield args 2)))
  9755.              ((string-match "^ *\\([^ ]+\\) *$" args)
  9756.               (cons (subfield args 1) ""))
  9757.              (t (cons "" ""))))
  9758.      (c (car pair))
  9759.      (s (cdr pair))
  9760.      (cmd (irc-nuke-whitespace
  9761.            (if (and (string= "" c) (not irc-called-from-buffer))
  9762.            (irc-read-object (concat "Which STATS command? (C, I, K, L,"
  9763.                         " M, Q, R, S, U, Y or Z) ")
  9764.                     ""
  9765.                     '("C" "I" "K" "L" "M" "Q" "R" "S" "U" "Y"
  9766.                       "Z"))
  9767.            c)))
  9768.      (server (irc-nuke-whitespace
  9769.           (if (and (string= "" s) (not irc-called-from-buffer))
  9770.               (irc-read-object (concat "STATS at which server? "
  9771.                            "(RET for "
  9772.                            irc-server
  9773.                            ") ")
  9774.                        ""
  9775.                        (irc-recall-all 'irc-servernames))
  9776.               s))))
  9777.     (if (not irc-called-from-buffer)
  9778.     (progn (irc-insert "")
  9779.            (irc-insert "/STATS %s"
  9780.                (concat (upcase cmd)
  9781.                    (if (not (string= "" cmd))
  9782.                        " "
  9783.                        "")
  9784.                    server))))
  9785.     (irc-send (concat "STATS " (concat cmd " " server)))
  9786.     (setq irc-idle-last-sent (irc-current-time))))
  9787.  
  9788.  
  9789. (defun irc-execute-mode (mode)
  9790.   "Usage: /MODE [channel [commands [arguments]]]
  9791.    or: /MODE nick [commands [arguments]]
  9792.  
  9793. Change or inspect the mode of a channel or a user.
  9794. The following modes exist for channels:
  9795.    a      Make channel anonymous (not supported by any servers yet)
  9796.    b      Manipulate a channels list of banned people
  9797.    i      Make channel joinable only with an invitation
  9798.    k      Add or remove channel key (password)
  9799.    l      Limit the number of users on the channel (argument: count)
  9800.    m      Make channel moderated
  9801.    n      Forbid /MSG's into channel
  9802.    o      Make someone a channel operator of this channel (argument: user)
  9803.    p      Make the channel private (ie channel invisible, users shown as being
  9804.           on some private channel)
  9805.    s      Make the channel secret (ie both channel and users invisible)
  9806.    t      Lock the topic of the channel (only settable by channel operators)
  9807.    v      Gives a user a voice on a moderated channel
  9808.  
  9809. The following modes exist for a user:
  9810.    i      Invisible
  9811.    o      Operator on IRC - can only be set with /OPER command
  9812.    s      Statusmessages, receive from server
  9813.    w      WALLOPS, receive from server
  9814. At the moment, only one self can be manipulated, and only i, s and w
  9815. can be set.
  9816.  
  9817. Prepend the mode command character with a + to turn the correspending
  9818. mode on, or with a - to turn it off.
  9819.  
  9820. Examples:
  9821.     /mode                    Show the mode of the current channel.
  9822.     /mode #foo               Show the mode of the channel named \"#foo\".
  9823.     /mode #foo +t            Locks the topic of channel \"#foo\".
  9824.     /mode * +i+o WiZ         Makes the current channel invite only and
  9825.                              gives user WiZ channel operator status.
  9826.     /mode * -o+l+o WiZ 3 `   Removes channel operator status for the
  9827.                              current channel from user WiZ, sets the
  9828.                              maximum number of users to 3 and makes
  9829.                              user ` a channel operator.
  9830.  
  9831.     /mode WiZ                Show the mode of user WiZ.
  9832.     /mode WiZ +s             Start receiving local status messages, such as
  9833.                              other servers connecting to this server etc.
  9834.     /mode WiZ +i-w           Become invisible and stop receiving WALLOPS.
  9835.  
  9836. "
  9837.   (interactive '(""))
  9838.   (let* ((tri (cond ((string-match "^ *\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]\\)"
  9839.                    mode)
  9840.              (cons (subfield mode 1)
  9841.                (cons (subfield mode 2)
  9842.                  (concat (subfield mode 3)
  9843.                      (substring mode (match-end 0))))))
  9844.             ((string-match "^ *\\([^ ]+\\) +\\([^ ]\\)" mode)
  9845.              (cons (subfield mode 1)
  9846.                (cons (concat (subfield mode 2)
  9847.                      (substring mode (match-end 0)))
  9848.                  "")))
  9849.             ((string-match "^ *[^ ]" mode)
  9850.              (cons (irc-nuke-whitespace mode) (cons "" "")))
  9851.             (t (cons "" (cons "" "")))))
  9852.      (ch1 (irc-nuke-whitespace (car tri)))
  9853.      (ch2 (irc-nuke-whitespace
  9854.            (if (and (string= "" ch1) (not irc-called-from-buffer))
  9855.            (irc-read-object (concat "Get/set mode of what channel/user"
  9856.                         "? "
  9857.                         (if (not (string= "0" irc-channel))
  9858.                         (format "(RET for %s) "
  9859.                             irc-channel)))
  9860.                     ""
  9861.                     (append
  9862.                      (irc-recall-all 'irc-subscribed-channels)
  9863.                      (list irc-nick)))
  9864.            ch1)))
  9865.      (channel (if (or (string= "" ch2) (string= "*" ch2)) irc-channel ch2))
  9866.      (is-nick (irc-is-nickname channel))
  9867.      (cmd1 (irc-nuke-whitespace (car (cdr tri))))
  9868.      (command (irc-nuke-whitespace
  9869.            (if (and (string= "" cmd1)
  9870.                 (string< "" channel)
  9871.                 (not irc-called-from-buffer))
  9872.                (irc-read-object (format (concat "Mode commands for"
  9873.                             " channel %s? (RET to"
  9874.                             " view) ")
  9875.                         channel)
  9876.                     ""
  9877.                     (if is-nick
  9878.                         '("+" "-" "i" "o" "s" "w")
  9879.                         '("+" "-" "b" "i" "k" "l" "m" "n"
  9880.                           "o" "p" "s" "t" "v")))
  9881.                cmd1)))
  9882.      (a1 (irc-nuke-whitespace (cdr (cdr tri))))
  9883.      (arg (irc-nuke-whitespace
  9884.            (if (and (string= "" a1)
  9885.             (string< "" channel)
  9886.             (string-match "[LOlo]" command)    ;Needs arguments?
  9887.             (not irc-called-from-buffer))
  9888.            (irc-read-object (format "Arguments to \"/MODE %s %s\"? "
  9889.                         channel command)
  9890.                     ""
  9891.                     (irc-recall-all 'irc-nicknames))
  9892.            a1))))
  9893.     (if (not irc-called-from-buffer)
  9894.     (progn (irc-insert "")
  9895.            (irc-insert "/MODE %s %s %s" channel command arg))) 
  9896.     (irc-send (format "MODE %s %s %s" channel command arg)))
  9897.   (setq irc-idle-last-sent (irc-current-time)))
  9898.  
  9899.  
  9900. (defun irc-execute-die (&optional dummy)
  9901.   "Usage: /DIE
  9902.  
  9903. Tells your local server to go belly-up."
  9904.   (interactive)
  9905.   (if (not irc-called-from-buffer)
  9906.       (progn (irc-insert "")
  9907.          (irc-insert "/DIE")))
  9908.   (irc-send (concat "DIE"))
  9909.   (setq irc-idle-last-sent (irc-current-time)))
  9910.  
  9911.  
  9912. (defun irc-execute-finger (nick)
  9913.   "Usage: /FINGER user
  9914.  
  9915. Query a users client to get users finger information. As some clients don't
  9916. understand this query, you might or might not get back a valid answer.
  9917. Sometime you'll get back a confused \"What?\" from user instead."
  9918.   (interactive '(""))
  9919.   (let* ((u (irc-nuke-whitespace nick))
  9920.      (user (irc-nuke-whitespace
  9921.         (if (and (string= "" u) (not irc-called-from-buffer))
  9922.             (irc-read-object "Get FINGER info from whom? "
  9923.                      ""
  9924.                      (irc-recall-all 'irc-nicknames))
  9925.             u))))
  9926.     (if (string= "" user)
  9927.     (irc-insert "%%No nick name given.")
  9928.     (if (not irc-called-from-buffer)
  9929.         (progn (irc-insert "")
  9930.            (irc-insert "/FINGER %s" user)))
  9931.     (irc-send (concat "PRIVMSG " user " :\001FINGER\001"))))
  9932.   (setq irc-idle-last-sent (irc-current-time)))
  9933.  
  9934.  
  9935. (defun irc-execute-describe (str)
  9936.    "Usage: /DESCRIBE user action
  9937.  
  9938. Send a CTCP ACTION message to a user. As some clients don't understand
  9939. this message, you might get back a confused \"What?\" from user instead.
  9940.  
  9941. See also: /ME"
  9942.    (interactive '(""))
  9943.    (let* ((nick (substring str 0 (string-match " +\\|$" str)))
  9944.       (action (substring str (match-end 0)))
  9945.       (u (irc-nuke-whitespace nick))
  9946.       (user (irc-nuke-whitespace
  9947.          (if (and (string= "" u) (not irc-called-from-buffer))
  9948.              (irc-read-object "Send a ACTION message to whom? "
  9949.                       ""
  9950.                       (irc-recall-all 'irc-nicknames))
  9951.              u)))
  9952.       (m (irc-nuke-whitespace action))
  9953.       (msg (irc-nuke-whitespace
  9954.             (if (and (string= "" m) (not irc-called-from-buffer))
  9955.             (irc-read-object "What is your action? "
  9956.                      ""
  9957.                     nil)
  9958.            m))))
  9959.      (if (string= "" user)
  9960.      (irc-insert "%%No nick name given.")
  9961.     (if (string= "" msg)
  9962.        (irc-insert "%%No action given.")
  9963.       (if (not irc-called-from-buffer)
  9964.          (progn (irc-insert "")
  9965.             (irc-insert "/DESCRIBE %s %s" user msg)))
  9966.      (irc-send (concat "PRIVMSG " user " :\001ACTION " msg "\001")))))
  9967.    (setq irc-idle-last-sent (irc-current-time)))
  9968.  
  9969.  
  9970. (defun irc-execute-me (action)
  9971.    "Usage: /ME action
  9972.  
  9973. Send a CTCP ACTION message to current channel. As some clients don't
  9974. understand this message, you might get back a confused \"What?\" from
  9975. some users.
  9976.  
  9977. See also: /DESCRIBE"
  9978.    (interactive '(""))
  9979.    (let* ((m (irc-nuke-whitespace action))
  9980.       (msg (irc-nuke-whitespace
  9981.             (if (and (string= "" m) (not irc-called-from-buffer))
  9982.             (irc-read-object "What is your action? "
  9983.                     ""
  9984.                     nil)
  9985.            m)))
  9986.       (on-hash (irc-is-multijoinable-channel irc-channel))
  9987.       (newsrvr (irc-server-has-multijoinable-channels)))
  9988.      (if (string= "" msg)
  9989.      (irc-insert "%%No action given.")
  9990.     (if (not irc-called-from-buffer)
  9991.        (progn (irc-insert "")
  9992.           (irc-insert "/ME %s" msg)))
  9993.        (irc-send (concat (if (and newsrvr on-hash)
  9994.                  (concat "PRIVMSG " irc-channel)
  9995.                 "MSG")
  9996.              " :\001ACTION " msg "\001"))
  9997.        (let* ((confirm (format "(Description sent to channel %s)" irc-channel))
  9998.           (padding (make-string (max 0 (- (window-width
  9999.                            (get-buffer-window
  10000.                         (current-buffer)))
  10001.                           (length confirm)
  10002.                           1))
  10003.                     ? )))
  10004.      (irc-insert "%s%s" padding confirm))
  10005.        ))
  10006.    (setq irc-idle-last-sent (irc-current-time)))
  10007.  
  10008.  
  10009. (defun irc-execute-ping (nicks)
  10010.   "Usage: /PING nick ...
  10011.  
  10012. Query a user's client (using CTCP) and calculate the distance between
  10013. the two of you in tenth of seconds. As some clients don't understans this
  10014. query, you might or might not get back a valid answer. Sometimes you
  10015. might even get back a confused \"What?\" from the user of the client.
  10016.  
  10017. Due to some technical limits and sojges laziness, the measurment isn't
  10018. foolproof. If the result seems to be totally wrong, resubmit the query.
  10019.  
  10020. The granularity is 500 ms."
  10021.   (interactive '(""))
  10022.   (while (string-match "^ *\\([^ :]+\\) *" nicks)
  10023.     (sit-for 0)
  10024.     (let* ((nick (subfield nicks 1))
  10025.        (dummy (setq nicks (substring nicks (match-end 1))))
  10026.        (n (irc-nuke-whitespace nick))
  10027.        (v (irc-nuke-whitespace
  10028.            (if (and (string= "" n) (not irc-called-from-buffer))
  10029.            (irc-read-object "Get PING distance to whom? "
  10030.                     ""
  10031.                     (irc-recall-all 'irc-nicknames))
  10032.            n)))
  10033.        (victim (if (string= "*" v) irc-channel v)))
  10034.       (if (string= "" victim)
  10035.       (irc-insert "%%No name given.")
  10036.       (if (not irc-called-from-buffer)
  10037.           (progn (irc-insert "")
  10038.              (irc-insert "/PING %s" victim)))
  10039.       (irc-send (format (concat "PRIVMSG %s :"
  10040.                     "\001ERRMSG PING RELAY %d\001"
  10041.                     "\001PING %d\001")
  10042.                 victim
  10043.                 (car (cdr (irc-current-time)))
  10044.                 (car (cdr (irc-current-time))))))))
  10045.   (setq irc-idle-last-sent (irc-current-time)))
  10046.  
  10047.  
  10048. (defun irc-execute-memberships (&optional dummy)
  10049.   "Usage: /MEMBERSHIPS
  10050.  
  10051. Show which channels you're listening to, and which one you're talking to.
  10052.  
  10053. Use /JOIN to join more or other channels, /LEAVE to leave some."
  10054.   (interactive '(""))
  10055.   (if (not irc-called-from-buffer)
  10056.       (progn (irc-insert "")
  10057.          (irc-insert "/MEMBERSHIPS")))
  10058.   (irc-show-subscribed-channels)
  10059.   (setq irc-idle-last-sent (irc-current-time)))
  10060.  
  10061.  
  10062. (defun irc-execute-signal (sigs)
  10063.   "Usage: /SIGNAL [ + | - | [+]event | -event ] [...]
  10064.  
  10065. Set the events which will get signals (aks bells or dings) when they
  10066. occur.  Events supported are:
  10067.  
  10068. backtalk -- your nick is mentioned            private  -- private messages
  10069. detect   -- nick in notify list seen/gone     public   -- public messages
  10070. invite   -- invitations                       topic    -- channel topic changes
  10071. join     -- channel changes                   wall     -- broadcast messages
  10072. nick     -- nickname changes                  
  10073.  
  10074. Without any arguments /SIGNAL simply prints a message about what signals
  10075. are currently enabled.  With event or +event turn on all signalling for that
  10076. event.  Remove all signals for an event with -event.  /SIGNAL + or /SIGNAL -
  10077. adds or removes all signals respectively.  Multiple arguments are accepted;
  10078. later ones take precedence over the ones which came before them.  For example,
  10079. \"/SIGNAL - +w +i\" would turn off all signals and then turn on signalling only
  10080. for wall messages and invitations."
  10081.   (interactive "sSet signal: ")
  10082.   ;; blow some whitespace away.  curiously this doesn't work correctly in debug
  10083.   (setq sigs (irc-nuke-whitespace sigs))
  10084.   (let ((recog '(backtalk
  10085.          detect
  10086.          invite
  10087.          join
  10088.          nick
  10089.          private
  10090.          public
  10091.          wall
  10092.          topic))
  10093.     str
  10094.     sym
  10095.     on
  10096.     off
  10097.     event)
  10098.     (while (string< "" sigs)
  10099.       ;; take one argument at a time
  10100.       (setq str  (substring sigs 0 (string-match " +\\|$" sigs))
  10101.         sigs (substring sigs (match-end 0)))
  10102.       (string-match "^\\([---+]?\\)" str)
  10103.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  10104.         event (substring str (match-end 0))
  10105.         sym (if (string= "" event) nil
  10106.             (car (delq nil
  10107.                    (mapcar
  10108.                 (function
  10109.                  (lambda (arg)
  10110.                   (if (string-match
  10111.                        (concat "^" (regexp-quote event))
  10112.                        (prin1-to-string arg))
  10113.                       arg))) recog)))))
  10114.       (cond
  10115.     ((and (string= "" event) off)
  10116.      (setq irc-signals (mapcar 'list recog)))
  10117.     ((string= "" event)
  10118.      (setq irc-signals (mapcar
  10119.                 (function (lambda (arg) (list arg t))) recog)))
  10120.     ((null sym)
  10121.      (irc-insert "%%Signal: Unknown argument %s."
  10122.              irc-msg-info-pre
  10123.              event
  10124.              irc-msg-info-post))
  10125.     (t (if off (setcdr (assoc sym irc-signals) nil)
  10126.            (setcdr (assoc sym irc-signals) '(t))))))
  10127.     (setq on (delq nil
  10128.            (mapcar        ; test against t because I have plans
  10129.             (function     ; to couple users and events
  10130.              (lambda (arg)
  10131.               (if (eq (nth 1 (assoc arg irc-signals)) t)
  10132.               arg))) recog)))
  10133.     (if on
  10134.     (irc-insert "%sSignalling is enabled for %s%s"
  10135.             irc-msg-info-pre
  10136.             (irc-subst-comma
  10137.              (mapconcat 'prin1-to-string on ", ") "and")
  10138.             irc-msg-info-post)
  10139.     (irc-insert "%sAll signalling is currently disabled%s"
  10140.             irc-msg-info-pre
  10141.             irc-msg-info-post)))
  10142.   (setq irc-idle-last-sent (irc-current-time)))
  10143.  
  10144.  
  10145. (defun irc-execute-stamp (stamp)
  10146.   "Usage: /STAMP [ + | - | [+]event | -event | interval ] [...]
  10147.  
  10148. Set time-stamping for IRC.  + means to turn it on for all messages from users
  10149. and - means to turn it off for them.  +event or just event will turn it on for
  10150. that class of message and -event means to disable it for those messages.  An
  10151. integer interval means to insert a message indicating the time every N minutes,
  10152. where N is the interval.  With no arguments simply insert a message indicating
  10153. the current time-stamps.
  10154.  
  10155. The current time in HH:MM format can appear two different ways in IRC.  One is
  10156. to have it associate with 'event'; two events, 'private' and 'public' messages,
  10157. are supported this way.  The other is to have it as a stand-alone message
  10158. indicating the current time.  Both can be very useful in noting when someone
  10159. actually sent you a message or when another event happened if you happen to be
  10160. away for a while.  The accuracy of the interval timer is currently limited to
  10161. 0-2 minutes beyond the interval if display-time is not running; accuracy is
  10162. greatly improved if it is.  It can be turned off by setting the interval
  10163. to 0."
  10164.   (interactive "sSet time-stamp: ")
  10165.   ;; whee.  napalm would feel particularly good here.
  10166.   (setq stamp (irc-nuke-whitespace stamp))
  10167.   (let (str sym event off)
  10168.     (while (string< "" stamp)
  10169.       ;; as the args go marching one by one the last one stopped ... <ahem>
  10170.       (setq str   (substring stamp 0 (string-match " +\\|$" stamp))
  10171.         stamp (substring stamp (match-end 0)))
  10172.       (string-match "^\\([---+]?\\)" str)
  10173.       (setq off (string= "-" (substring str (match-beginning 1) (match-end 1)))
  10174.         event (substring str (match-end 1))
  10175.         sym (cond ((string= "" event) nil)
  10176.               ((string-match (concat "^" (regexp-quote event))
  10177.                      "private") 'private)
  10178.               ((string-match (concat "^" (regexp-quote event))
  10179.                      "public")  'public)
  10180.               ((natnump (car (read-from-string event)))
  10181.                (car (read-from-string event)))))
  10182.       ;; the following cond is really what sets eveything
  10183.       (cond ((and (string= "" event) off) (setq irc-message-stamp nil))
  10184.         ((string= "" event) (setq irc-message-stamp t))
  10185.         ((null sym) (irc-insert "%%Stamp: Unknown argument %s."
  10186.                     irc-msg-info-pre
  10187.                     event
  10188.                     irc-msg-info-post))
  10189.         ((natnump sym) (setq irc-time-stamp sym))
  10190.         (off (setq irc-message-stamp
  10191.                (car (delq sym (if (eq irc-message-stamp t)
  10192.                       '(private public)
  10193.                       (list irc-message-stamp))))))
  10194.         (t (setq irc-message-stamp
  10195.              (cond ((null irc-message-stamp) sym)
  10196.                ((or (eq irc-message-stamp t)
  10197.                 (eq irc-message-stamp sym)) irc-message-stamp)
  10198.                (t t)))))))
  10199.   (irc-insert "%s%s messages get time-stamps.%s%s"
  10200.           irc-msg-info-pre
  10201.           (cond ((eq irc-message-stamp t) "Private and public")
  10202.             ((null irc-message-stamp) "No")
  10203.             (t (capitalize (prin1-to-string irc-message-stamp))))
  10204.           (if (zerop irc-time-stamp) ""
  10205.           (format "  The time interval is %d minutes."
  10206.               irc-time-stamp))
  10207.           irc-msg-info-post)
  10208.   (setq irc-idle-last-sent (irc-current-time)))
  10209.  
  10210.  
  10211. (defun irc-execute-alias (alias)
  10212.   "Usage: /ALIAS alias [command] [args for command]]]
  10213.  
  10214. Allow 'alias' to be equivalent to 'command'.
  10215. For example, \"/ALIAS tf time tut.fi\" will make typing \"/tf\" be equivalent
  10216. to having issued the command \"/time tut.fi\".  Aliases can only be made
  10217. to existing commands, not other aliases.  They are also only recognized when
  10218. in the command name position of a line.  If given with no arguments then
  10219. all aliases are displayed; if given with just an alias name then the alias
  10220. with that name will be shown.  Aliases can be removed with /UNALIAS."
  10221.   (interactive "sWhat name should the new alias have? (RET to view all) ")
  10222.   (if (and (interactive-p) (string-match "[^: ]+" alias))
  10223.       (setq alias (concat
  10224.            alias
  10225.            " "
  10226.            (irc-read-object
  10227.             (format (concat "Alias \"%s\" to which command? "
  10228.                     "(Including optional arguments) ")
  10229.                 alias)
  10230.             ""
  10231.             (mapcar (function (lambda (pair)
  10232.                   (upcase (cdr pair))))
  10233.                 (append irc-alias-alist
  10234.                     (append irc-command-alist
  10235.                         irc-operator-alist)))))))
  10236.   (setq alias (irc-nuke-whitespace alias))
  10237.   (string-match "^/?\\([^: ]*\\) */?\\([^: ]*\\) *" alias)
  10238.   (let ((new (upcase (subfield alias 1)))
  10239.     (cmd (upcase (subfield alias 2)))
  10240.     (arg (irc-nuke-whitespace (substring alias (match-end 2))))
  10241.     match)
  10242.     (cond
  10243.       ((string= "" new)
  10244.        (let ((aliases irc-alias-alist))
  10245.      (cond ((> (length aliases) 0)
  10246.         (while aliases
  10247.           (irc-insert "%s/%s is aliased to mean \"/%s\"%s"
  10248.                   irc-msg-info-pre
  10249.                   (car (car aliases))
  10250.                   (cdr (car aliases))
  10251.                   irc-msg-info-post)
  10252.           (setq aliases (cdr aliases)))
  10253.         (irc-insert "%sListed all aliases%s"
  10254.                 irc-msg-info-pre
  10255.                 irc-msg-info-post))
  10256.            (t (irc-insert "%sYou don't have any aliases%s"
  10257.                   irc-msg-info-pre
  10258.                   irc-msg-info-post)))))
  10259.       ((string= "" cmd)
  10260.        (let ((alias (assoc new irc-alias-alist)))
  10261.      (if alias
  10262.          (irc-insert "%s/%s is aliased to mean \"/%s\"%s"
  10263.              irc-msg-info-pre
  10264.              (car alias)
  10265.              (cdr alias)
  10266.              irc-msg-info-post)
  10267.          ;; this could possibly have done some matching to see whether
  10268.          ;; just an abbrev was being given, but we'll just take it as given
  10269.          (irc-insert "%s\"/%s\" is not aliased%s"
  10270.              irc-msg-info-pre
  10271.              new
  10272.              irc-msg-info-post))))
  10273.       (t
  10274.        ;; Okay, we've got at least a command.  let's try and make this as
  10275.        ;; painless as possible. 
  10276.        (setq match (irc-check-list
  10277.             (mapcar 'car (append irc-command-alist
  10278.                      irc-operator-alist))
  10279.             cmd
  10280.             'start-only))
  10281.        (if (/= (length match) 1)
  10282.        (if match
  10283.            (irc-insert "%%Ambiguous command /%s; could be %s."
  10284.                cmd
  10285.                (irc-subst-comma
  10286.                 (mapconcat (function (lambda (arg)
  10287.                      (concat "\"" arg "\"")))
  10288.                        match
  10289.                        ", ")
  10290.                 "or"))
  10291.            (irc-insert "%%Command not found: /%s." cmd))
  10292.        (irc-change-alias new
  10293.                  (concat (downcase (car match))
  10294.                      ;; no trailing space if no arg
  10295.                      (if (string= "" arg)
  10296.                      ""
  10297.                      " ")
  10298.                      arg)
  10299.                  'add)
  10300.        (irc-insert "%s\"/%s\" has been aliased to mean \"/%s\"%s"
  10301.                irc-msg-info-pre
  10302.                new 
  10303.                (cdr (assoc new irc-alias-alist))
  10304.                irc-msg-info-post)))))
  10305.   (setq irc-idle-last-sent (irc-current-time)))
  10306.  
  10307.  
  10308. (defun irc-execute-unalias (alias)
  10309.   "Usage: /UNALIAS alias
  10310.  
  10311. Remove the 'alias' for a command."
  10312.   (interactive '(""))
  10313.   (let* ((tmpalias (if (and (string= "" alias) (not irc-called-from-buffer))
  10314.                (irc-read-object "Remove which alias? "
  10315.                     ""
  10316.                     (mapcar (function (lambda (p)
  10317.                           (upcase (car p))))
  10318.                         (irc-recall-all
  10319.                          'irc-alias-alist)))
  10320.                alias))
  10321.      (a (irc-nuke-whitespace tmpalias)) 
  10322.      (match (irc-check-list (mapcar 'car irc-alias-alist) a t)))
  10323.     (if (/= (length match) 1)
  10324.     (if match (irc-insert "%%%s is an ambiguous alias. Could be %s."
  10325.                   (upcase alias)
  10326.                   (irc-subst-comma
  10327.                    (mapconcat (function (lambda (arg)
  10328.                         (concat "\"" arg "\"")))
  10329.                       match
  10330.                       ", ")
  10331.                    "or"))
  10332.         (irc-insert "%%No alias found to match %s." (upcase alias)))
  10333.     (irc-change-alias (car match) nil 'remove)
  10334.     (irc-insert "%s\"%s\" is no longer aliased%s"
  10335.             irc-msg-info-pre (car match) irc-msg-info-post)))
  10336.   (setq irc-idle-last-sent (irc-current-time)))
  10337.  
  10338.  
  10339. ;;START of code by Per StarbΣck (starback@Student.DoCS.UU.SE)
  10340. (defun irc-execute-help (topic)
  10341.   "Usage: /HELP topic
  10342.  
  10343. Get the documentation for \"command\".  If no command is given then a list
  10344. of the possible topics is shown.  Note that commands for IRC Operators will
  10345. not appear in the help topics when not an IRC Operator."
  10346.   (interactive '(""))
  10347.   (let* ((normal-commands (mapcar (function car) irc-command-alist))
  10348.      (oper-commands (mapcar (function car) irc-operator-alist))
  10349.      (alias-commands (mapcar (function car) irc-alias-alist))
  10350.      (help-topics (mapcar (function car) irc-help-topic-alist))
  10351.      (top (irc-nuke-whitespace
  10352.            (if (and (string= "" topic) (not irc-called-from-buffer))
  10353.            (irc-read-object
  10354.             "Help for which command or topic? "
  10355.             ""
  10356.             (append normal-commands
  10357.                 (if irc-operator oper-commands '())
  10358.                 alias-commands
  10359.                 help-topics))
  10360.          topic))))
  10361.     (if (not irc-called-from-buffer)
  10362.     (progn (irc-insert "")
  10363.            (irc-insert "/HELP %s" top)))
  10364.     (if (string= top "")
  10365.     (let* ((str (concat "Help is available for the following IRC-mode"
  10366.                 " commands:\n"))
  10367.            (topics (sort (append normal-commands
  10368.                      (if irc-operator oper-commands nil)
  10369.                      alias-commands
  10370.                      help-topics)
  10371.                  (function string<))))
  10372.       (while topics
  10373.         (setq str (concat str
  10374.                   (format "\n%14s%14s%14s%14s%14s"
  10375.                       (nth 0 topics)
  10376.                       (or (nth 1 topics) "")
  10377.                       (or (nth 2 topics) "")
  10378.                       (or (nth 3 topics) "")
  10379.                       (or (nth 4 topics) "")))
  10380.           topics (nthcdr 5 topics)))
  10381.       (with-output-to-temp-buffer "*Help*" (princ str)))
  10382.       (let* ((matches (irc-check-list
  10383.                (append normal-commands
  10384.                    (if irc-operator oper-commands '())
  10385.                    alias-commands
  10386.                    help-topics)
  10387.                top t))
  10388.          ;;(matches-normal (irc-common-element matches normal-commands))
  10389.          (matches-oper (irc-common-element matches oper-commands))
  10390.          (matches-alias (irc-common-element matches alias-commands))
  10391.          (matches-topic (irc-common-element matches help-topics))
  10392.          (shadowingalias nil))
  10393.     ;; If there is an alias with the same name as a command,
  10394.     ;; the alias is preferred.  Other collisions shouldn't be possible.
  10395.     (if (and (cdr matches)        ;== (> (length matches) 1)
  10396.          (irc-all-true (mapcar (function (lambda (x)
  10397.                            (string= x (car matches))))
  10398.                        (cdr matches))))
  10399.         (if matches-alias
  10400.         (setq matches (list (car matches))
  10401.               shadowingalias (concat
  10402.                       "\n\nThis shadows the "
  10403.                       (cond (matches-topic
  10404.                          "general help on the topic")
  10405.                         (matches-oper "operator command")
  10406.                         (t "command"))
  10407.                       " with the same name."))
  10408.           (with-output-to-temp-buffer "*Help*"
  10409.         (princ (format (concat "There are several things called %s, "
  10410.                        "and no way to know \nwhich one you "
  10411.                        "want help on.  This is a bug--please "
  10412.                        "contact \n%s.")
  10413.                    (car matches) irc-hacker)))))
  10414.     ;; If nothing else matches even a non-oper gets to see
  10415.     ;; help on oper commands.
  10416.     (if (and (null matches) (not irc-operator))
  10417.         (setq matches (irc-check-list oper-commands top t)
  10418.           matches-oper matches))
  10419.     (cond ((null matches)
  10420.            (irc-insert "%%No help is available for \"%s\"."
  10421.                (upcase top)))
  10422.           ((cdr matches)        ;== (> (length matches) 1)
  10423.            (irc-insert "%%Ambiguous help topic %s; could be %s."
  10424.                (upcase top)
  10425.                (irc-subst-comma
  10426.                 (mapconcat (function (lambda (arg)
  10427.                            (concat "\"" arg "\"")))
  10428.                        matches
  10429.                        ", ")
  10430.                 "or")))
  10431.           (t ;;Exactly one match:
  10432.            (let ((match (car matches)))
  10433.          (with-output-to-temp-buffer "*Help*"
  10434.            (cond (matches-alias
  10435.               (let ((aliasfor (cdr (assoc match irc-alias-alist))))
  10436.                 (princ (format "%s is an alias for \"/%s\"."
  10437.                        match aliasfor))
  10438.                 (if shadowingalias (princ shadowingalias))
  10439.                 (princ (format "\n\n%s"
  10440.                        (irc-help-for-command
  10441.                         (upcase
  10442.                          (substring 
  10443.                           aliasfor 0
  10444.                           (string-match " "
  10445.                                 aliasfor))))))))
  10446.              (matches-topic
  10447.               (princ (cdr (assoc match irc-help-topic-alist))))
  10448.              (t (princ (irc-help-for-command match))))))))))))
  10449.  
  10450.  
  10451. (defun irc-help-for-command (command)
  10452.   "Returns the documentation string for the irc command COMMAND."
  10453.   (documentation
  10454.    (or (intern-soft (concat "irc-execute-"
  10455.                 (or (cdr (assoc command irc-command-alist))
  10456.                 (cdr (assoc command irc-operator-alist)))))
  10457.        'irc-internal-error-dummy)))
  10458.  
  10459.  
  10460. (defun irc-common-element (list1 list2)
  10461.   "True if two lists have at least one common element.
  10462. The predicate eq is used for the comparisions."
  10463.   (cond ((null list1) nil)
  10464.     ((memq (car list1) list2) t)
  10465.     (t (irc-common-element (cdr list1) list2))))
  10466.  
  10467.  
  10468. (defun irc-all-true (list)
  10469.   "Is true if all args in LIST are true."
  10470.   ;; This is needed as special forms (like AND) can't be given to FUNCALL.
  10471.   (if (null list) t (and (car list) (irc-all-true (cdr list)))))
  10472. ;;;END of code by Per StarbΣck.
  10473.  
  10474.  
  10475. (defun irc-later-execute-lusers ()
  10476.   "Dummy function. Used when it's desired to do a irc-execute-lusers in a
  10477. little while. Not implemented yet."
  10478.   nil)
  10479.  
  10480.  
  10481. (defun irc-internal-error-dummy ()
  10482.   "Internal error.
  10483.  
  10484. No internal function associated with this command. This should never happen.
  10485. Please report this to the person mentioned in variable irc-hacker."
  10486.   nil)
  10487.  
  10488.  
  10489.  
  10490. ;; miscellaneous irc-* commands
  10491. (defun irc-truncate-buffer (max min)
  10492.   "Remove as many lines from the beginning of the buffer as is
  10493. necessary to get it under MAX number of characters, downto MIN number
  10494. of characters. This function is used by irc-mode to prevent an
  10495. irc-session from consuming gross amounts of space.
  10496.  
  10497. See irc-filter about not truncating the Kiwi buffer at all."
  10498.   (if (>= (buffer-size) max)
  10499.       (save-excursion
  10500.     ;; first go to the lowest point posssible that would do it
  10501.     (goto-char min)
  10502.     ;; get to the end of this line
  10503.     (end-of-line)
  10504.     (if (< (point) irc-mark)
  10505.         ;; just to make sure we don't toast pending input
  10506.         (delete-region 1 (1+ (point)))
  10507.         (message "Warning: %s exceeding %s characters.  Couldn't truncate."
  10508.              (buffer-name (current-buffer)) max)))))
  10509.  
  10510.  
  10511. (defun irc-read-passwd (&optional prompt)
  10512.   "Allow user to type a string without it showing.  Returns string.
  10513. If optional PROMPT non-nil, use it as the prompt string in the minibuffer."
  10514.   ;; this is based on a similar function in telnet.el
  10515.   ;; the major drawback is that while being prompted for a password
  10516.   ;; it stays in this routine until C-g, RET or LFD is typed.
  10517.   (let ((passwd "") (echo-keystrokes 0) char)
  10518.     (if prompt (message prompt))
  10519.     (while (not (or (= (setq char (read-char)) 13) (= char 10)))
  10520.       ;; naughty bit.  take C-h to mean DEL.
  10521.       (if (or (= char 8) (= char 127))
  10522.       (if (> (length passwd) 0)
  10523.           (setq passwd (substring passwd 0 (1- (length passwd)))))
  10524.       (setq passwd (concat passwd (char-to-string char))))
  10525.       (if prompt (message (concat prompt (make-string (length passwd) ?*)))))
  10526.     (if prompt (message ""))
  10527.     passwd))
  10528.  
  10529.  
  10530. (defun irc-read-object (prompt object list)
  10531.   "Prompting with PROMPT, read an IRC objects name from the minibuffer.
  10532. Second argument OBJECT is a string which is checked for a non-ambiguous match
  10533. before the minibuffer read is done.  Optional third argument LIST is a
  10534. list to use for checking rather than the irc-nicknames.
  10535.  
  10536. It returns either the name of a object or an empty string (\"\")."
  10537.   (if (not (string-match "^ *\\([^: ]*\\)" object)) ; just want one name
  10538.       "" 
  10539.       (let ((completion-ignore-case t)
  10540.         (object (substring object (match-beginning 1) (match-end 1)))
  10541.         (match nil))
  10542.     (if (or (string= "" object)
  10543.         (/= (length (setq match (irc-check-list list object))) 1))
  10544.         (completing-read (format "%s%s"
  10545.                      (if (string= "" object)
  10546.                      ""
  10547.                      (format (if (zerop (length match))
  10548.                              "No names match %s.  "
  10549.                              "\"%s\" is ambiguous.  ")
  10550.                          object))
  10551.                      prompt)
  10552.                  ;; build the list for completing-read.  a
  10553.                  ;; null string is there so that it can exit
  10554.                  ;; without anything, since we require matches
  10555.                  (mapcar 'list (cons "" list))
  10556.                  nil
  10557.                  nil        ;Also non exact matches are OK.
  10558.                  object)
  10559.         (car match)))))
  10560.  
  10561. (defun irc-nuke-whitespace (str)
  10562.   "One string argument.  Returns it with surrounding whitespace removed."
  10563.   (let* ((tmp (and (string-match "^ *" str)
  10564.            (substring str (match-end 0)))))
  10565.     (if (not tmp)
  10566.     str
  10567.     (and (string-match " *$" tmp)
  10568.          (substring tmp 0 (match-beginning 0))))))
  10569.  
  10570.  
  10571. (defun irc-stringlist-to-string (list &optional sep)
  10572.   "Take a LIST of strings and concate all string into one single string.
  10573. Optionally takes as a second argument a string to use as a seperator."
  10574.   (mapconcat (function (lambda (arg) arg)) list sep))
  10575.  
  10576.  
  10577. (defun irc-subst-comma (str newsep)
  10578.   "Return the string formed by substituting for the last \", \" in STR
  10579. the string NEWSEP followed by a space.  For example:
  10580.   (irc-subst-comma \"1, 2, 3\" \"or\") => \"1, 2 or 3\"
  10581.  
  10582. This function is especially designed for making message from irc-mode
  10583. more grammatically correct and the strings which it operates on should
  10584. be carefully chosen so as to avoid possibly blowing away a comma that
  10585. really wasn't separating elements in a list."
  10586.   ;; did you know that example up there can't appear starting in column 0
  10587.   ;; without screwing up lisp-indent-line?
  10588.   (if (string-match ", [^,]*$" str)
  10589.       (concat (substring str 0 (match-beginning 0)) " " newsep
  10590.           (substring str (1+ (match-beginning 0))))
  10591.       str))
  10592.  
  10593.  
  10594. (defun irc-listify (list sep conn)
  10595.   "Take a LIST of strings, and put them together into one single string, using
  10596. the SEPerator string between every pair of string, except the last pair where
  10597. the CONNector is used.
  10598. Example: (irc-listify '(\"a\" \"b\" \"c\") \", \" \"and\") returns
  10599. \"a, b and c\"."
  10600.   (irc-subst-comma (irc-stringlist-to-string list sep) conn))
  10601.  
  10602.  
  10603. (defun irc-get-time ()
  10604.   "Return the hour and minutes of the current time in the form \"HH:MM\"."
  10605.   (let ((time (current-time-string)))
  10606.     (substring time
  10607.            (string-match "[0-2][0-9]:[0-5][0-9]" time)
  10608.            (match-end 0))))
  10609.  
  10610.  
  10611. ;;;(defun irc-current-time ()
  10612. ;;;  "Return current time as number of seconds since 1-jan-1970 0:00:00.
  10613. ;;;As this is a 32 bit number but GNU Emacs only handles 16 bit numbers, split
  10614. ;;;it up in a cons with the car being the high order 16 bit numer and th cdr
  10615. ;;;the low order 16 bit number."
  10616. ;;;  (if (= 0 (buffer-size))
  10617. ;;;      (irc-insert ""))
  10618. ;;;  (write-region (point-max) (1- (point-max)) irc-idle-scratch-file nil 'silent)
  10619. ;;;  (nth 6 (file-attributes irc-idle-scratch-file)))
  10620.  
  10621.  
  10622. (defun irc-current-time ()
  10623.   "Return current time as number of seconds since 1-jan-1970 0:00:00.
  10624. As this is a 32 bit number but GNU Emacs only handles 16 bit numbers, split
  10625. it up in a cons with the car being the high order 16 bit numer and the cdr
  10626. the low order 16 bit number.
  10627.  
  10628. Written by Stephen Ma <ma_s@maths.su.oz.au>"
  10629.   (irc-time-to-int (current-time-string)))
  10630.  
  10631.  
  10632. (defun irc-time-to-int (timestr)
  10633.   "Convert from time in string format as returned by current-time-string
  10634. to a double integer format, as returned by file-attributes.
  10635.  
  10636. Written by Stephen Ma <ma_s@maths.su.oz.au>"
  10637.   (let* ((norm+ '(lambda (num1 num2)
  10638.           (let ((sumh (+ (car num1) (car num2)))
  10639.             (suml (+ (car (cdr num1)) (car (cdr num2)))))
  10640.             (list (+ sumh (/ suml 65536)) (% suml 65536)))))
  10641.      (norm* '(lambda (num1 num2)
  10642.           (let ((prodh (* num1 (car num2)))
  10643.             (prodl (* num1 (car (cdr num2)))))
  10644.             (list (+ prodh (/ prodl 65536)) (% prodl 65536)))))
  10645.      (seconds (string-to-int (substring timestr 17 19)))
  10646.      (minutes (string-to-int (substring timestr 14 16)))
  10647.      (hours (string-to-int (substring timestr 11 13)))
  10648.      (partdays (1- (string-to-int (substring timestr 8 10))))
  10649.      (years (string-to-int (substring timestr 20 24)))
  10650.      (days (+ partdays
  10651.           (cond ((and (= (% years 4) 0)
  10652.                   (/= (% years 100) 0))
  10653.              (cdr (assoc (substring timestr 4 7)
  10654.                      '(("Jan" . 0)
  10655.                        ("Feb" . 31)
  10656.                        ("Mar" . 60)
  10657.                        ("Apr" . 91)
  10658.                        ("May" . 121)
  10659.                        ("Jun" . 152)
  10660.                        ("Jul" . 182)
  10661.                        ("Aug" . 213)
  10662.                        ("Sep" . 244)
  10663.                        ("Oct" . 274)
  10664.                        ("Nov" . 305)
  10665.                        ("Dec" . 335)))))
  10666.             (t (cdr (assoc (substring timestr 4 7)
  10667.                        '(("Jan" . 0)
  10668.                      ("Feb" . 31)
  10669.                      ("Mar" . 59)
  10670.                      ("Apr" . 90)
  10671.                      ("May" . 120)
  10672.                      ("Jun" . 151)
  10673.                      ("Jul" . 181)
  10674.                      ("Aug" . 212)
  10675.                      ("Sep" . 243)
  10676.                      ("Oct" . 273)
  10677.                      ("Nov" . 304)
  10678.                      ("Dec" . 334))))))
  10679.           (* (- years 1970) 365)
  10680.           (/ (- years 1969) 4)
  10681.           (- (/ (- years 1901) 100)))))
  10682.     (funcall norm+
  10683.          (funcall norm*
  10684.               60
  10685.               (funcall norm+
  10686.                    (funcall norm*
  10687.                     60
  10688.                     (funcall norm+
  10689.                          (funcall norm*
  10690.                               24
  10691.                               (list 0 days))
  10692.                          (list 0 hours)))
  10693.                    (list 0 minutes)))
  10694.          (list 0 seconds))))
  10695.  
  10696.  
  10697. (defun irc-time= (a b)
  10698.   "Compare two time, return true if they're equal."
  10699.   (and (= (nth 0 a) (nth 0 b))
  10700.        (= (nth 1 a) (nth 1 b))))
  10701.  
  10702.  
  10703. (defun irc-time< (a b)
  10704.   "Compare two times, return t if the first is earlier than the second."
  10705.   (or (< (nth 0 a) (nth 0 b))
  10706.       (and (= (nth 0 a) (nth 0 b))
  10707.        (< (nth 1 a) (nth 1 b)))))
  10708.  
  10709.  
  10710. (defun irc-time-diff (a b)
  10711.   "Return the difference between two times. This functions requires
  10712. the first argument to be later in time than the second argument."
  10713.   (cond ((= (nth 0 a) (nth 0 b)) (list 0 (- (nth 1 a) (nth 1  b))))
  10714.     ((> (nth 1 b) (nth 1 a)) (list (- (nth 0 a) (nth 0 b) 1)
  10715.                        (- (+ 65536 (nth 1 a)) (nth 1 b))))
  10716.     (t (list (- (nth 0 a) (nth 0 b))
  10717.          (- (nth 1 a) (nth 1 b))))))
  10718.  
  10719.  
  10720. (defun irc-idle-time ()
  10721.   "Return a approximation of the idle time. The time is the number of seconds
  10722. which have passed since the last write to the server. If a valid idle-time
  10723. can't be returned, -1 is returned instead."
  10724.   (let ((now (irc-current-time))
  10725.     (then irc-idle-last-sent))
  10726.     (if (or (numberp irc-idle-last-sent)
  10727.         (not (= (car now) (car then))))
  10728.     -1
  10729.     (- (car (cdr now))
  10730.        (car (cdr then))))))
  10731.  
  10732.  
  10733. (defun irc-internal-time ()
  10734.   "Return a new value every time irc-internal-time is called. The new value is
  10735. larger than the latest returned, starting at 0."
  10736.   (if (not (boundp 'irc-internal-time))
  10737.       (set (make-local-variable 'irc-internal-time) nil))
  10738.   (if (not (integerp irc-internal-time))
  10739.       (setq irc-internal-time 0)
  10740.       (setq irc-internal-time (1+ irc-internal-time))))
  10741.  
  10742.  
  10743. (defun irc-check-time ()
  10744.   "Check to see whether it is time to insert a current-time message into
  10745. the *IRC* buffer."
  10746.   (if (null irc-last-time)
  10747.       (setq irc-last-time 0))
  10748.   (let* ((time (irc-get-time))
  10749.      (last (if (and (boundp 'irc-last-time) (stringp irc-last-time))
  10750.            irc-last-time
  10751.            time))
  10752.       (old-minute (string-to-int (substring last 3)))
  10753.       (new-minute (string-to-int (substring time 3)))
  10754.       (total-time (if (numberp irc-total-time) irc-total-time 0)))
  10755.     (if (and (zerop irc-time-stamp) (zerop irc-notify-interval))
  10756.      ()
  10757.     ;; check the time sentinel
  10758.     (if (string= irc-last-time time)
  10759.         ()
  10760.         ;; time has gone stomping on by ...
  10761.         (setq new-minute (+ new-minute (if (< new-minute old-minute) 60 0))
  10762.           irc-last-time time
  10763.           irc-total-time (+ total-time (- new-minute old-minute)))
  10764.         (if (not (zerop irc-time-stamp))
  10765.         (if (not (< (- irc-total-time irc-last-stamp) irc-time-stamp))
  10766.             (progn (irc-wrap-display-time)
  10767.                (irc-send "TIME")
  10768.                (setq irc-last-stamp irc-total-time))))
  10769.         (if (not (zerop irc-notify-interval))
  10770.         (if (not (< (- irc-total-time irc-last-notify)
  10771.                 irc-notify-interval))
  10772.             (progn (irc-wrap-display-time)
  10773.                (irc-who-is-on
  10774.                 (irc-recall-all 'irc-notify-looked-for))
  10775.                (setq irc-last-notify irc-total-time))))))))
  10776.  
  10777.  
  10778. (defun irc-wrap-display-time ()
  10779.   "Set up a wrapper around the display-time-filter to hopefully provide a
  10780. little better accuracy for the time stamps."
  10781.   (if (and (fboundp 'display-time-filter)
  10782.            (not (fboundp 'original-display-time-filter)))
  10783.       (progn
  10784.         (fset 'original-display-time-filter
  10785.               (symbol-function 'display-time-filter))
  10786.         ;; a nested defun seems to do funny things to the byte-compiler, so
  10787.         ;; instead we find a way around it.
  10788.         (fset 'display-time-filter
  10789.               (function
  10790.                (lambda (proc str)
  10791.         "
  10792. The filter for the display-time-process.  This function has been modified
  10793. for IRC-mode to call irc-check-time before calling the original
  10794. display-time-filter."
  10795.         (save-excursion
  10796.           (let ((procs (irc-active-servers)))
  10797.             (while procs
  10798.               (let ((buf (buffer-name (process-buffer (car procs)))))
  10799.             (if buf (progn (set-buffer buf) (irc-check-time)))
  10800.             (setq procs (cdr procs))))))
  10801.         (original-display-time-filter proc str)))))))
  10802.  
  10803.  
  10804. (defun irc-who-is-on (&optional list)
  10805.   (if (or (not (boundp 'irc-last-who-is-on))
  10806.       (not (and (listp irc-last-who-is-on)
  10807.             (numberp (nth 0 irc-last-who-is-on))
  10808.             (numberp (nth 1 irc-last-who-is-on)))))
  10809.       (set (make-local-variable 'irc-last-who-is-on) '(0 0)))
  10810.   (let* ((now (irc-current-time))
  10811.      (diff (irc-time-diff now irc-last-who-is-on)))
  10812.     (cond ((or (not (= 0 (nth 0 diff)))
  10813.            (> (nth 1 diff) 60))
  10814.        (setq irc-last-who-is-on (irc-current-time))
  10815.        (let ((str "")
  10816.          (namelist (if (null list)
  10817.                    (irc-recall-all 'irc-notify-looked-for)
  10818.                    list)))
  10819.          (while (not (null namelist))
  10820.            (setq str (concat str " " (car namelist))
  10821.              namelist (cdr namelist)))
  10822.          (irc-send (format "ISON :%s" str)))))))
  10823.  
  10824.  
  10825. (defun irc-change-alias (alias cmd add)
  10826.   "Modify ALIAS for CMD in the irc-alias-alist.  ADD non-nil means to put the
  10827. alias in the list, nil (or the symbol \"remove\") means to clear it.  This
  10828. function does no hand-holding like /ALIAS; its intended use is in
  10829. irc-mode-hook."
  10830.   (let ((entry (assoc (upcase alias) irc-alias-alist)))
  10831.     (if (or (null add) (eq add 'remove))
  10832.         (setq irc-alias-alist (delq entry irc-alias-alist))
  10833.     (if entry (setcdr entry cmd)
  10834.         (setq irc-alias-alist
  10835.           (cons (cons (upcase alias) cmd) irc-alias-alist))))))
  10836.  
  10837.  
  10838. (defun irc-signal (user event)
  10839.   "Return t if a ding should be issued for a USER/EVENT pair.
  10840. Currently only the event part of things is supported by /SIGNAL."
  10841.   (let ((signal (cdr (assoc event irc-signals))))
  10842.     (or (memq t signal)
  10843.     (irc-member-general user signal 'string=)
  10844.         (irc-member-general user
  10845.                 (cdr (assoc 'user irc-signals))
  10846.                 'string=))))
  10847.  
  10848.  
  10849. (defun irc-check-list (list item &optional start-only)
  10850.   "See if LIST has string ITEM.  Returns a list of possible matches.  The list
  10851. returned is based on the following precedence rules:  if there is an exact
  10852. match, it is returned.  If there are any strings in the list whose beginning
  10853. match the item, they are returned.  If that fails and optional argument
  10854. START-ONLY is missing or nil, strings which have the item match anywhere are
  10855. returned.  As a last resort, nil is returned.
  10856. This function is not case-sensitive."
  10857.   (let ((return nil)
  10858.     (case-fold-search t)
  10859.     (item (regexp-quote item)))
  10860.     (if (setq return
  10861.               (delq nil                         ; whole words
  10862.                     (mapcar (function   
  10863.                              (lambda (arg)
  10864.                   (if (string-match (concat "^" item "$") arg)
  10865.                   arg))) list)))
  10866.         return
  10867.     (if (setq return
  10868.           (delq nil                       ; beginnings
  10869.             (mapcar (function
  10870.                  (lambda (arg)
  10871.                   (if (string-match (concat "^" item) arg)
  10872.                       arg))) list)))
  10873.         return
  10874.         (if start-only
  10875.         nil
  10876.         (delq nil
  10877.               (mapcar (function               ; anywhere
  10878.                    (lambda (arg)        
  10879.                 (if (string-match (concat "." item) arg) arg)))
  10880.                   list)))))))
  10881.  
  10882.  
  10883. (defun irc-list-remember (item list)
  10884.   "Add string ITEM to ordered LIST destructivly, returning the new list in
  10885. reversed order. The intended way to call this is like:
  10886.   (setq lst (irc-list-remember \"foo\" lst)).
  10887.  
  10888. This function is case insensitive."
  10889.   (let ((ui (upcase item)))
  10890.     (cond ((null list) (cons item nil))
  10891.       ((string< (upcase (car list)) ui) (cons item list))
  10892.       ((string= (upcase (car list)) ui)
  10893.        (rplaca list item)
  10894.        list)
  10895.       (t (let ((ptr list))
  10896.            (while (and (not (null (cdr ptr)))
  10897.                (string< ui (upcase (car (cdr ptr)))))
  10898.          (setq ptr (cdr ptr)))
  10899.            (cond ((null (cdr ptr)) (rplacd ptr (cons item nil)))
  10900.              ((string= (upcase (car (cdr ptr))) ui)
  10901.               (rplaca (cdr ptr) item))
  10902.              ((string< (upcase (car (cdr ptr))) ui)
  10903.               (rplacd ptr (cons item (cdr ptr))))
  10904.              (t (error
  10905.              (format "NOT possible! item=%s, list=%s, ptr=%s."
  10906.                  item list ptr)))))
  10907.          list))))
  10908.          
  10909.          
  10910. (defun irc-hash-value (str tbl-size)
  10911.   "Return a hash value (index into a hash table) for string ITEM according to
  10912. a table of size SIZE."
  10913.   (let ((h 0)
  10914.     (i 0)
  10915.     (l (min 4 (length str))))
  10916.     (while (< i l)
  10917.       (setq h (% (+ (* h 256) (upcase (aref str i))) tbl-size)
  10918.         i (1+ i)))
  10919.     h))
  10920.  
  10921.  
  10922. (defconst irc-hash-index-size 0
  10923.   "Index of size field in a Kiwi hash table.")
  10924. (defconst irc-hash-index-timestamp 1
  10925.   "Index of timestamp field in a Kiwi hash table.")
  10926. (defconst irc-hash-index-cleanflag 2
  10927.   "Index of cleanstamp in a Kiwi hash table. Either a symbol or a list.")
  10928. (defconst irc-hash-index-bucketarray 3
  10929.   "Index of bucketarray in a Kiwi hash table.")
  10930.  
  10931.  
  10932. (defun irc-create-new-hash-table (size)
  10933.   "Create a empty hash table of size SIZE." 
  10934.   ;; [size write-date cleanflag bucketarray]
  10935.   ;; cleanflag is a list = non-dirty, valid sorted list representation of
  10936.   ;; the hashed data. Else only data to be found is in the hashtable. The hash
  10937.   ;; table is always clean.
  10938.   (let ((htbl (make-vector 4 nil)))
  10939.     (aset htbl irc-hash-index-size size)
  10940.     (aset htbl irc-hash-index-timestamp (irc-internal-time))
  10941.     (aset htbl irc-hash-index-cleanflag 'empty)
  10942.     (aset htbl irc-hash-index-bucketarray (make-vector size nil))
  10943.     htbl))
  10944.  
  10945.  
  10946. (defun irc-nothing-remembered-p (bag)
  10947.   "True if the BAG is empty."
  10948.   (let* ((htbl (symbol-value bag))
  10949.      (flg (aref htbl irc-hash-index-cleanflag)))
  10950.     (cond ((and (symbolp flg) (eq 'empty flg)) flg)
  10951.       (t (let* ((a (aref htbl irc-hash-index-bucketarray))
  10952.             (size (aref htbl irc-hash-index-size))
  10953.             (i size)
  10954.             (empty t))
  10955.            (while (and empty (> i 0))
  10956.          (setq i (1- i)
  10957.                empty (null (aref a i))))
  10958.            (if empty
  10959.            (irc-forget-all bag))
  10960.            empty)))))
  10961.  
  10962.  
  10963. (defun irc-remember (item bag)
  10964.   "Store a string ITEM in the named BAG."
  10965.   (let* ((htbl (symbol-value bag))
  10966.      (a (aref htbl irc-hash-index-bucketarray))
  10967.      (fixed (cond ((eq bag 'irc-servernames)
  10968.                (let ((i (irc-extract-hostname (upcase item))))
  10969.              (cond ((not i) nil)
  10970.                    ((string-match "^ *$" i)
  10971.                 (irc-insert (concat "%%Function irc-remember"
  10972.                             " found a space in"
  10973.                             " a hostname %s).")
  10974.                         item)
  10975.                 (if debug-on-error
  10976.                     (error "SPC in hostname"))
  10977.                 nil)
  10978.                    (t i))))
  10979.               ((or (eq bag 'irc-linksinfo)
  10980.                (eq bag 'irc-namtree)
  10981.                (eq bag 'irc-whotree)
  10982.                (eq bag 'irc-listtree))
  10983.                item)
  10984.               ((or (eq bag 'irc-nicknames)
  10985.                (eq bag 'irc-notify-detected)
  10986.                (eq bag 'irc-notify-looked-for))
  10987.                (cond ((string= "" item)
  10988.                   (irc-insert "%%Skipped \"\" in irc-nicknames.")
  10989.                   nil)
  10990.                  ((= ?@ (aref item 0))
  10991.                   (substring item 1))
  10992.                  ((string-match " " item)
  10993.                   (irc-insert (concat "%%Function irc-remember"
  10994.                           " found a space in a"
  10995.                           " nickname (%s).")
  10996.                       item)
  10997.                   (if debug-on-error
  10998.                   (error "SPC in nickname"))
  10999.                   nil)
  11000.                  ((string-match "\\." item)
  11001.                   (irc-insert (concat "%%Function irc-remember"
  11002.                           " found a dot in a"
  11003.                           " nickname (%s).")
  11004.                       item)
  11005.                   (if debug-on-error
  11006.                   (error "Dot in nickname"))
  11007.                   nil)
  11008.                  (t item)))
  11009.               ((string-match " " item)
  11010.                (irc-insert (concat "%%Function irc-remember"
  11011.                        " found a space in an item"
  11012.                        " (%s).")
  11013.                    item)
  11014.                (if debug-on-error
  11015.                (error "SPC in item"))
  11016.                nil)
  11017.               (t item))))
  11018.     (cond (fixed
  11019.        (let* ((idx (irc-hash-value fixed (aref htbl irc-hash-index-size)))
  11020.           (oldlen (length (aref a idx))))
  11021.          (aset a idx (irc-list-remember fixed (aref a idx)))
  11022.          (cond ((not (= oldlen (length (aref a idx))))
  11023.             (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11024.             (aset htbl irc-hash-index-cleanflag 'dirty)))
  11025.          (if (and (eq bag 'irc-nicknames)
  11026.               (not (irc-recall fixed 'irc-notify-detected))
  11027.               (irc-recall fixed 'irc-notify-looked-for))
  11028.          (irc-who-is-on (irc-recall-all 'irc-notify-looked-for))))))))
  11029.  
  11030.  
  11031. (defun irc-debug-check-all-hashtables ()
  11032.   ""
  11033.   (let ((n (irc-internal-time)))
  11034.     (setq irc-userinfo (format "DEBUGGING CLIENT -- %s." n))
  11035.     (mapcar (function (lambda (p)
  11036.           (irc-debug-check-hashtable (car p) (cdr p) n)))
  11037.         '((irc-nicknames . irc-is-nickname)
  11038.           (irc-ignored-ppl . irc-is-nickname)
  11039.           (irc-linksinfo . nil)
  11040.           (irc-listtree . nil)
  11041.           (irc-notify-looked-for . irc-is-nickname)
  11042.           (irc-notify-detected . irc-is-nickname)
  11043.           (irc-namtree . nil)
  11044.           (irc-servernames . irc-is-hostname)
  11045.           (irc-subscribed-channels . irc-is-channelname)
  11046.           (irc-services . irc-is-nickname)
  11047.           (irc-whotree . nil)))))
  11048.  
  11049.  
  11050. (defun irc-debug-check-hashtable (bag chkfcn &optional mark)
  11051.   ""
  11052.   (let* ((data (irc-recall-all bag))
  11053.      (lst data)
  11054.      (id (if (null mark) "" mark))
  11055.      (consistent t)
  11056.      (doublettes nil))
  11057.     (sit-for 0)
  11058.     (irc-insert "DEBUG: %s checking if hashtable %s is consistent using %s."
  11059.         id bag chkfcn)
  11060.     (irc-insert "DEBUG: %s = %s." bag data)
  11061.     (while (not (null lst))
  11062.       (let* ((matches (irc-check-list data (car lst)))
  11063.          (l (length matches)))
  11064.     (cond ((= 1 l) (irc-insert "DEBUG: %s  OK, \"%s\" found once."
  11065.                    id (car lst)))
  11066.           ((= 0 l)
  11067.            (irc-insert "DEBUG: %s Huh? \"%s\" not found."
  11068.                id (car lst))
  11069.            (setq doublettes t))
  11070.           (t (irc-insert "DEBUG: %s ERROR \"%s\" FOUND %d TIMES."
  11071.                  id (car lst) l)
  11072.          (setq doublettes t)))
  11073.     (setq lst (cdr lst))))
  11074.     (irc-insert "DEBUG: %s checked for doublettes, done." id)
  11075.     (sit-for 0)
  11076.     (if (not (null chkfcn))
  11077.     (let ((lst data))
  11078.       (while (not (null lst))
  11079.         (cond ((funcall chkfcn (car lst))
  11080.            (irc-insert "DEBUG: %s item \"%s\" of %s -- OK."
  11081.                    id (car lst) bag))
  11082.           (t (irc-insert "DEBUG: %s item \"%s\" of %s FAILED CHECK."
  11083.                  id (car lst) bag)
  11084.              (setq consistent nil)))
  11085.         (setq lst (cdr lst)))))
  11086.     (irc-insert "DEBUG: %s done checking: doublettes %s, consistent %s"
  11087.         id (if doublettes "FAILED" "OK") (if consistent "OK" "FAILED"))
  11088.     (irc-insert "DEBUG: %s --------------" id)
  11089.     (sit-for 0)))
  11090.  
  11091.  
  11092. (defun irc-list-recall (item list)
  11093.   "Check if a string ITEM is in the LIST. The comparsion is not case
  11094. sensitive. If the item is found, return the stored spelling, else nil."
  11095.   (let ((ui (upcase item)))
  11096.     (while (and (not (null list))
  11097.         (string< ui (upcase (car list))))
  11098.       (setq list (cdr list)))
  11099.     (if (and (not (null list)) (string= (upcase (car list)) ui))
  11100.     (car list)
  11101.     nil)))
  11102.  
  11103.  
  11104. (defun irc-recall (item bag)
  11105.   "Check if a string ITEM is in the BAG. If so, return the stored spelling,
  11106. else ni. All checking is done without being case sensitive."
  11107.   (let* ((htbl (symbol-value bag))
  11108.      (idx (irc-hash-value item (aref htbl irc-hash-index-size))))
  11109.     (irc-list-recall item (aref (aref htbl irc-hash-index-bucketarray)
  11110.         (irc-hash-value item (aref htbl irc-hash-index-size))))))
  11111.  
  11112.  
  11113. (defun irc-recall-all (bag)
  11114.   "Return a sorted list representation of all strings in the BAG."
  11115.   ;; [size write-date cleanflag bucketarray]
  11116.   (let* ((htbl (symbol-value bag))
  11117.      (cached-data (aref htbl irc-hash-index-cleanflag))
  11118.      (is-clean (listp cached-data))
  11119.      (buckets (aref htbl irc-hash-index-bucketarray))
  11120.      (size (aref htbl irc-hash-index-size)))
  11121.     (cond ((not (= size (length buckets)))
  11122.        (irc-insert "%%Bad hash list %s, size != length bucketarray." bag)))
  11123.     (cond (is-clean cached-data)
  11124.       (t (let ((r nil)
  11125.            (i size)
  11126.            (a nil))
  11127.            (while (> i 0)
  11128.          (setq i (1- i)
  11129.                a (aref buckets i))
  11130.          (while (not (null a))
  11131.            (setq r (cons (car a) r)
  11132.              a (cdr a))))
  11133.            (let ((s (sort r '(lambda (a b)
  11134.                   (string< (upcase a) (upcase b))))))
  11135.          (aset htbl irc-hash-index-cleanflag s)
  11136.          s))))))
  11137.  
  11138.  
  11139. (defun irc-recall-all-and-display (bag ind &optional plur sing)
  11140.   "Enter the nodes in the BAG as seperate lines in the irc buffer. Entries
  11141. longer than 1 line are continued with an indentation of IND, a number.
  11142.  
  11143. If you supply the optional arguments PLUR and SING, then after the lines
  11144. a short message of the form \"[%d %s]\" is printed. If only PLUR is supplied,
  11145. it is always used. If both PLUS and SING is supplied, then SING is used if
  11146. exactly one line was printed, else PLUR is used."
  11147.   (let ((lst (irc-recall-all bag))
  11148.     (n 0)
  11149.     (irc-msg-cont-used (make-string ind ? )))
  11150.     (while lst
  11151.       (irc-insert "%s" (car lst))
  11152.       (setq n (1+ n)
  11153.         lst (cdr lst)))
  11154.     (if (stringp plur)
  11155.     (if (zerop n)            ;List empty?
  11156.         (if (irc-terminal-is-slow) ;When on a slow terminal, no list
  11157.         (irc-insert "%%No %s." plur) ; is kept.
  11158.         (irc-insert "%sEnd of (unsorted) %s list%s"
  11159.                 irc-msg-info-pre
  11160.                 plur
  11161.                 irc-msg-info-post))
  11162.         (irc-insert "%s%d %s%s"
  11163.             irc-msg-info-pre
  11164.             n
  11165.             (if (= n 1)
  11166.                 (if (stringp sing) sing plur)
  11167.                 plur)
  11168.             irc-msg-info-post))
  11169.     (irc-insert "%sEnd of (unsorted) list%s"
  11170.             irc-msg-info-pre
  11171.             irc-msg-info-post)))
  11172.   (irc-insert ""))
  11173.  
  11174.  
  11175. (defun irc-list-forget (item list)
  11176.   "Remove a string ITEM from a LIST of string, if it's found. The comparsions
  11177. are not case sensitive."
  11178.   (let ((ui (upcase item)))
  11179.     (cond ((null list) list)
  11180.       ((string< (upcase (car list)) ui) list)
  11181.       ((string= (upcase (car list)) ui) (cdr list))
  11182.       (t (let ((ptr list))
  11183.            (while (and (not (null (cdr ptr)))
  11184.                (string< ui (upcase (car (cdr ptr)))))
  11185.          (setq ptr (cdr ptr)))
  11186.            (cond ((null (cdr ptr)) nil)
  11187.              ((string< (upcase (car (cdr ptr))) ui) nil)
  11188.              ((string= (upcase (car (cdr ptr))) ui)
  11189.               (rplacd ptr (cdr (cdr ptr))))
  11190.              (t (error (concat  "irc-list-forget: NOT possible!"
  11191.                     " item=%s, list=%s, ptr=%s.")
  11192.                    item list ptr))))
  11193.          list))))
  11194.  
  11195.  
  11196. (defun irc-forget (item bag)
  11197.   "Remove a string ITEM from the BAG, if the item was there. Not case
  11198. sensitive."
  11199.   (let* ((htbl (symbol-value bag))
  11200.      (idx (irc-hash-value item (aref htbl irc-hash-index-size)))
  11201.      (a (aref htbl irc-hash-index-bucketarray))
  11202.      (oldlen (length (aref a idx))))
  11203.     (aset a idx (irc-list-forget item (aref a idx)))
  11204.     (if (and (eq bag 'irc-nicknames)
  11205.          (irc-recall item 'irc-notify-detected)
  11206.          (irc-recall item 'irc-notify-looked-for))
  11207.     (irc-who-is-on (irc-recall-all 'irc-notify-looked-for)))
  11208.     (cond ((not (= oldlen (length (aref a idx))))
  11209.        (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11210.        (aset htbl irc-hash-index-cleanflag 'dirty)))))
  11211.  
  11212.  
  11213. (defun irc-forget-all (bag)
  11214.   "Empty BAG."
  11215.   (let* ((htbl (symbol-value bag))
  11216.      (size (aref htbl irc-hash-index-size))
  11217.      (a (aref htbl irc-hash-index-bucketarray))
  11218.      (i 0))
  11219.     (while (< i size)
  11220.       (aset a i nil)
  11221.       (setq i (1+ i)))
  11222.     (aset htbl irc-hash-index-timestamp (irc-internal-time))
  11223.     (aset htbl irc-hash-index-cleanflag 'empty)))
  11224.  
  11225.  
  11226. (defun irc-get-names-and-servers ()
  11227.   "Return a alphabetically sorted list of all the nick- and servernames which
  11228. are known by the client."
  11229.   (if (not (boundp 'irc-cache-n+s))
  11230.       (set (make-local-variable 'irc-cache-n+s) nil))
  11231.   (if (or (null irc-cache-n+s)        ;No data yet?
  11232.       (< (car irc-cache-n+s)    ;Nicknames updated?
  11233.          (aref irc-nicknames irc-hash-index-timestamp))
  11234.       (< (car irc-cache-n+s)    ;Servernames updated?
  11235.          (aref irc-servernames irc-hash-index-timestamp)))
  11236.       (let* ((servers (irc-recall-all 'irc-servernames))
  11237.          (names (irc-recall-all 'irc-nicknames))
  11238.          (data nil))
  11239.     (while (not (null servers))
  11240.       (setq data (cons (car servers) data)
  11241.         servers (cdr servers)))
  11242.     (while (not (null names))
  11243.       (setq data (cons (car names) data)
  11244.         names (cdr names)))
  11245.     (let ((s (sort data '(lambda (a b) (string< (upcase a) (upcase b))))))
  11246.       (setq irc-cache-n+s (cons (irc-internal-time) s)))))
  11247.   (cdr irc-cache-n+s))
  11248.  
  11249.  
  11250. (defun irc-get-channels-and-nicks-and-servers ()
  11251.   "Return a alphabetically sorted list of all the channel-, nick- and server-
  11252. names which are known by the client."
  11253.   (if (not (boundp 'irc-cache-c+n+s))
  11254.       (set (make-local-variable 'irc-cache-c+n+s) nil))
  11255.   (if (or (null irc-cache-c+n+s)
  11256.       (< (car irc-cache-c+n+s)
  11257.          (aref irc-subscribed-channels irc-hash-index-timestamp))
  11258.       (< (car irc-cache-c+n+s)
  11259.          (aref irc-nicknames irc-hash-index-timestamp))
  11260.       (< (car irc-cache-c+n+s)
  11261.          (aref irc-servernames irc-hash-index-timestamp)))
  11262.       (let* ((channels (irc-recall-all 'irc-subscribed-channels))
  11263.          (nicks (irc-recall-all 'irc-nicknames))
  11264.          (servers (irc-recall-all 'irc-servernames))
  11265.          (data nil))
  11266.     (while (not (null channels))
  11267.       (setq data (cons (car channels) data)
  11268.         channels (cdr channels)))
  11269.     (while (not (null nicks))
  11270.       (setq data (cons (car nicks) data)
  11271.         nicks (cdr nicks)))
  11272.     (while (not (null servers))
  11273.       (setq data (cons (car servers) data)
  11274.         servers (cdr servers)))
  11275.     (let ((s (sort data '(lambda (a b) (string< (upcase a) (upcase b))))))
  11276.       (setq irc-cache-c+n+s (cons (irc-internal-time) s)))))
  11277.   (cdr irc-cache-c+n+s))
  11278.  
  11279.  
  11280. (defun irc-sec-to-time (n)
  11281.   "Convert number of SECONDS into a time string of one of the following
  11282. formats \"SS seconds\" or \"MM minutes and SS seconds\"
  11283. or \"HH hours, MM minutes and SS seconds\"
  11284. or \"DD days, HH hourse, MM minutes and SS seconds\"."
  11285.   (let* ((one-minute 60)
  11286.      (one-hour (* 60 one-minute))
  11287.      (one-day (* 24 one-hour))
  11288.      (days (/ n one-day))
  11289.      (day-string (cond ((= 0 days) "")
  11290.                ((= 1 days) "1 day")
  11291.                (t (format "%d days" days))))
  11292.      (m (% n one-day))
  11293.      (hours (/ m one-hour))
  11294.      (hour-string (cond ((= 0 hours) "")
  11295.                 ((= 1 hours) "1 hour")
  11296.                 (t (format "%d hours" hours))))
  11297.      (l (% m one-hour))
  11298.      (minutes (/ l one-minute))
  11299.      (min-string (cond ((= 0 minutes) "")
  11300.                ((= 1 minutes) "1 minute")
  11301.                (t (format "%d minutes" minutes))))
  11302.      (seconds (% l one-minute))
  11303.      (sec-string (cond ((= 0 seconds) "")
  11304.                ((= 1 seconds) "1 second")
  11305.                (t (format "%d seconds" seconds)))))
  11306.     ;; Possible combinations:
  11307.     ;; D H M S
  11308.     ;; 0 0 0 0 = none
  11309.     ;; 0 0 0 1 = S
  11310.     ;; 0 0 1 0 = M
  11311.     ;; 0 0 1 1 = MS
  11312.     ;; 0 1 0 0 = H
  11313.     ;; 0 1 0 1 = HS
  11314.     ;; 0 1 1 0 = HM
  11315.     ;; 0 1 1 1 = HMS
  11316.     ;; 1 0 0 0 = D
  11317.     ;; 1 0 0 1 = DS
  11318.     ;; 1 0 1 0 = DM
  11319.     (let ((acc nil))
  11320.       (if (not (string= "" sec-string)) (setq acc (cons sec-string acc)))
  11321.       (if (not (string= "" min-string)) (setq acc (cons min-string acc)))
  11322.       (if (not (string= "" hour-string)) (setq acc (cons hour-string acc)))
  11323.       (if (not (string= "" day-string)) (setq acc (cons day-string acc)))
  11324.       (cond ((= 0 (length acc)) "0 seconds")
  11325.         ((= 1 (length acc)) (car acc))
  11326.         ((= 2 (length acc)) (format "%s and %s" (nth 0 acc) (nth 1 acc)))
  11327.         ((= 3 (length acc))
  11328.          (format "%s, %s and %s" (nth 0 acc) (nth 1 acc) (nth 2 acc)))
  11329.         (t (format "%s, %s, %s and %s"
  11330.                (nth 0 acc) (nth 1 acc) (nth 2 acc) (nth 3 acc)))))))
  11331.  
  11332.  
  11333. (defun irc-burst-comma (str)
  11334.   "Take a comma or space separated STR and turn it into a list of its elements.
  11335. Example: \"1, 2,3,4,  6  7\" becomes the list
  11336. (\"7\" \"6\" \"4\" \"3\" \"2\" \"1\")."
  11337.   (let (list sub (beg 0))
  11338.     (string-match "" str)
  11339.     (while (string-match ",+\\| +\\|,+ +" str beg)
  11340.       (if (not (string= (setq sub (substring str beg (match-beginning 0))) ""))
  11341.           (setq list (cons sub list)))
  11342.       (setq beg (match-end 0)))
  11343.     (if (/= (length str) beg) (cons (substring str beg) list) list)))
  11344.  
  11345.  
  11346.  
  11347. ;; miscellaneous other commands (usually from other sources)
  11348.  
  11349. ;; this makes up for not being able to provide a :test to memq.
  11350. ;; irc-member-general by Bard Bloom <bard@theory.lcs.mit.com>
  11351. (defun irc-member-general (x l comparison)
  11352.   "Is X a member of L under COMPARISON?"
  11353.   (let ((not-found t))
  11354.     (while (and l not-found)
  11355.       (setq not-found (not (funcall comparison x (car l)))
  11356.             l         (cdr-safe l)))
  11357.     (not not-found)))
  11358.  
  11359.  
  11360. ;; wish i could remember who I got this from; I had to patch it to work
  11361. ;; with the minibuffer correctly but it is mostly untouched.
  11362. (defun irc-walk-windows (proc &optional no-mini)
  11363.   "Applies PROC to each visible window (after selecting it, for convenience).
  11364. Optional arg NO-MINI non-nil means don't apply PROC to the minibuffer
  11365. even if it is active."
  11366.   (let* ((real-start (selected-window))
  11367.      (start (next-window real-start no-mini))
  11368.      (current start) done)
  11369.     (while (not done)
  11370.       (select-window current)
  11371.       (funcall proc)
  11372.       (setq current (next-window current no-mini))
  11373.       (setq done (eq current start)))
  11374.     (select-window real-start)))
  11375.  
  11376.  
  11377. (defun irc-count-windows (&optional no-mini)
  11378.   "Returns the number of visible windows.
  11379. Optional arg NO-MINI non-nil means don't count the minibuffer
  11380. even if it is active."
  11381.   (let ((count 0))
  11382.     (irc-walk-windows (function (lambda () (setq count (1+ count)))) no-mini)
  11383.     count))
  11384.  
  11385.  
  11386. ;; swiped from minibuf.el, but made exclusive to * Minibuf-n*.
  11387. (defun irc-minibuffer-message (format &rest args)
  11388.   "Print a temporary message at the end of the Minibuffer.
  11389. After 2 seconds or when a key is typed, erase it."
  11390.   (if (zerop (minibuffer-depth)) (apply 'message format args)
  11391.       (let (p)
  11392.     (save-excursion
  11393.       (set-buffer (concat " *Minibuf-" (1- (minibuffer-depth)) "*"))
  11394.       (unwind-protect
  11395.            (progn
  11396.          (setq p (goto-char (point-max)))
  11397.          (insert (apply 'format format args))
  11398.          (sit-for 2))
  11399.         (delete-region p (point-max)))))))
  11400.  
  11401.  
  11402. (defun irc-find-to (str &optional explicit)
  11403.   "Find the part of STRING that IRC-mode will interpret as the sendlist.
  11404. If no explicit list is found, irc-default-to is returned.  The string returned
  11405. is either : or ; terminated.
  11406.  
  11407. If optional EXPLICIT is non-nil, then return t if a sendlist was explicitly
  11408. specified, nil if the sendlist was implicit."
  11409.   (let* ((part (if (string-match "^ *\\([^;:]*\\) *\\([:;]\\)" str)
  11410.            (subfield str 1)
  11411.            nil))
  11412.      (retval (if (not part)
  11413.              ""
  11414.              (concat part (subfield str 2))))
  11415.      (matched (and part
  11416.                (or (string= "" part)
  11417.                (let ((s part))
  11418.                  (while (string-match (concat "^ *\\([^ ,]+\\)"
  11419.                               " *, *")
  11420.                           s)
  11421.                    (let ((b1 (match-beginning 1))
  11422.                      (e0 (match-end 0))
  11423.                      (e1 (match-end 1)))
  11424.                  (if (irc-is-receiver (substring s b1 e1))
  11425.                      (setq s (substring s e0))
  11426.                      (setq s ":"))))
  11427.                  (irc-is-receiver s))))))
  11428.     (if explicit matched (if matched retval irc-default-to))))
  11429.  
  11430.  
  11431. (defun irc-find-message (string)
  11432.   "Find the message that IRC will see if STR were sent.  For messages
  11433. sent with explicit lists, this is everything following the colon or
  11434. semi-colon.  For everything else, it is just the string."
  11435.   (substring string (length (irc-find-to string))))
  11436.  
  11437.  
  11438.  
  11439. ;; functions for the irc-history list
  11440. (defun irc-add-to-hist (str)
  11441.   "Put STRING at the head of the irc-history list."
  11442.   (if (string-match "^[;:]" str)
  11443.       (setq str
  11444.             (concat irc-last-explicit (substring str 1 (length str)))))
  11445.   (setq irc-history (append (list str) irc-history))
  11446.   (and (> (length irc-history) irc-max-history)
  11447.        (setq irc-history (reverse (cdr (reverse irc-history))))))
  11448.  
  11449.  
  11450. (defun irc-yank-prev-command ()
  11451.   "Put the last IRC /command in the input-region."
  11452.   (interactive)
  11453.   (delete-region irc-mark (goto-char (point-max)))
  11454.   (insert "/" irc-last-command)
  11455.   (goto-char (1+ irc-mark)))
  11456.  
  11457.  
  11458. (defun irc-history-prev (arg)
  11459.   "Select the previous message in the IRC history list.  ARG means
  11460. select that message out of the list (0 is the first)."
  11461.   (interactive "P")
  11462.   (let ((str (nth (or arg (1+ (or irc-history-index 0))) irc-history)))
  11463.     (if (not str)
  11464.         (message "No message %d in history." (or arg (1+ irc-history-index)))
  11465.     (delete-region irc-mark (goto-char (point-max)))
  11466.     (insert str)
  11467.     (goto-char irc-mark)
  11468.     (setq irc-history-index (or arg (1+ irc-history-index))))))
  11469.  
  11470.  
  11471. (defun irc-history-next (arg)
  11472.   "Select the next message in the IRC history list.  With prefix ARG
  11473. select that message out of the list (same as irc-history-prev if
  11474. called with a prefix arg)."
  11475.   (interactive "P")
  11476.   (if arg (irc-history-prev arg)
  11477.       (if (= irc-history-index -1)
  11478.       (message "No next message in history.")
  11479.       (delete-region irc-mark (goto-char (point-max)))
  11480.       (insert (if (zerop irc-history-index) ""
  11481.               (nth (1- irc-history-index) irc-history)))
  11482.       (setq irc-history-index (1- irc-history-index)))))
  11483.  
  11484.  
  11485. (defun irc-kill-input ()
  11486.   "Delete the input region and start out fresh.  This function is recommended
  11487. over any other way of killing the input-region interactively because it
  11488. also resets the index for the history list."
  11489.   (interactive)
  11490.   (delete-region irc-mark (goto-char (point-max)))
  11491.   (setq irc-history-index -1))
  11492.  
  11493.  
  11494. (defun irc-complete-name ()
  11495.   "Not completed yet."
  11496.   (interactive)
  11497.   (let* ((end (point))
  11498.      (beg (save-excursion
  11499.         (while
  11500.             (and (not (= (point) (point-min)))
  11501.              (irc-is-receiver (buffer-substring (1- (point)) end)))
  11502.           (backward-char 1))
  11503.         (point)))
  11504.      (pattern (downcase (buffer-substring beg end)))
  11505.      (alist (mapcar (function (lambda (s)
  11506.               (list (downcase s))))
  11507.             (irc-get-names-and-servers)))
  11508.      (completion (try-completion pattern alist)))
  11509.     (cond ((eq completion t))        ;Exact match.
  11510.       ((null completion)        ;No match at all.
  11511.        (ding)
  11512.        (message "Can't find completion for \"%s\"" pattern))
  11513.       ((not (string= pattern completion)) ;Complete (but maybe not unique).
  11514.        (delete-region beg end)
  11515.        (insert completion)) 
  11516.       (t (let* ((name (irc-nuke-whitespace
  11517.                (completing-read "Who? "
  11518.                         alist
  11519.                         nil
  11520.                         nil
  11521.                         pattern))))
  11522.            (delete-region beg end)
  11523.            (insert name))))))
  11524.  
  11525.  
  11526. (defun irc-line-count (buf)
  11527.   "Returns the size of the buffer BUF."
  11528.   (save-excursion (set-buffer buf)
  11529.           (goto-line 1)
  11530.           (count-lines (point-min) (1+ (buffer-size)))))
  11531.  
  11532.  
  11533. (defun irc-log-in-debug-buffer (line)
  11534.   "Append a LINE to the debug buffer associated with a session, appending a
  11535. newline to the line. If the debug buffer doesn't exist, do nothing."
  11536.   (let ((debug-buffer (concat (buffer-name (current-buffer))
  11537.                   "-*debug*")))
  11538.     (if (get-buffer debug-buffer)
  11539.     (irc-append-string-to-buffer line (get-buffer debug-buffer)))))
  11540.  
  11541.  
  11542. (defun irc-append-string-to-buffer (str buf)
  11543.   "Append the string STR to the buffer BUF as a line."
  11544.   (save-excursion (set-buffer buf)
  11545.           (goto-char (1+ (buffer-size)))
  11546.           (insert str "\n")))
  11547.  
  11548.  
  11549. (defun irc-get-buffers-nth-line (n buf)
  11550.   "Returns the line number N in the buffer BUF as a string.
  11551. The first line inb the buffer is line number 1.
  11552. If the buffer is empty, returns \"\"."
  11553.   (if (>= (irc-line-count buf) n)
  11554.       (save-excursion (set-buffer buf)
  11555.               (goto-line n)
  11556.               (let ((p (point)))
  11557.             (search-forward "\n" (1+ (buffer-size)) 'non-nil-non-t)
  11558.             (buffer-substring p (1- (point)))))
  11559.     ""))
  11560.  
  11561.  
  11562. (defun irc-sort-lines-in-buffer (buf &optional reverse)
  11563.   "Sort the lines in buffer BUF.
  11564. An optional argument REVERSE can be supplied as non-nil to sort the buffer
  11565. in reversed order."
  11566.   (save-excursion (set-buffer buf)
  11567.           (sort-lines reverse (point-min) (1+ (buffer-size)))))
  11568.  
  11569.  
  11570. (defun irc-history-menu ()
  11571.   "List the history of messages kept by irc-mode in another buffer."
  11572.   (interactive)
  11573.   (let ((pop-up-windows t) (hist irc-history) (line 0))
  11574.     (save-excursion
  11575.       (set-buffer (get-buffer-create "*IRC History*"))
  11576.       (fundamental-mode)
  11577.       (erase-buffer)
  11578.       (while hist
  11579.         (insert (format "%2d: %s\n" line (car hist)))
  11580.         (setq hist (cdr hist))
  11581.         (setq line (1+ line)))
  11582.       (if (zerop line)
  11583.           (insert "No messages have been sent to IRC yet."))
  11584.       (set-buffer-modified-p nil)
  11585.       (goto-char (point-min)))
  11586.     (display-buffer "*IRC History*")))
  11587.  
  11588.  
  11589.  
  11590. ;; stuff about irc-mode
  11591. (defun irc-version (&optional arg)
  11592.   "Print the current version of irc.el in the minibuffer.  With optional
  11593. ARG, insert it in the current buffer."
  11594.   (interactive "P")
  11595.   (if arg
  11596.       (insert irc-version)
  11597.       (princ irc-version)))
  11598.  
  11599.  
  11600. (defun irc-fatal (msg item)
  11601.   (irc-insert "FATAL ERROR: \"%s\" \"%s\"." msg item))
  11602.  
  11603.  
  11604. ;;; Force GC to prevent GC bug in older (pre 18.57) GNU Emacs'es.
  11605. (garbage-collect)
  11606.  
  11607. (defun irc-execute-news (dummy)
  11608.   "Shows news about latest changes to this GNU Emacs client.
  11609. Even shows news about old changes -- what a wonderous function indeed.
  11610.  
  11611. Latest changes to IRC mode, oldest at bottom, newest at top:
  11612.  
  11613. *** NEEDS TO BE UPDATED ***"
  11614.   (interactive '(""))
  11615.   (save-excursion
  11616.     (set-buffer (get-buffer-create "*IRC-mode News*"))
  11617.     (erase-buffer)
  11618.     (insert (documentation 'irc-execute-news))
  11619.     (goto-char (point-min)))
  11620.   (display-buffer "*IRC-mode News*"))
  11621.  
  11622.  
  11623. (defun irc-report-bug (client-message server-message type)
  11624.   ""
  11625.   (irc-insert "%%%s" client-message)
  11626.   (irc-insert "%% \"%s\" (%s)." server-message type)
  11627.   (irc-insert "%% Please tell %s, it might be a bug." irc-hacker)
  11628.   (irc-insert "%% (Client \"%s\", server %s version %d.%d)."
  11629.           irc-version irc-major-version irc-minor-version))
  11630.  
  11631.  
  11632. ;; We're done defining an irc mode, so let's provide it.
  11633. (provide 'irc)
  11634.