tkabber-plugins-0.11.1/0000755000175000017500000000000011076120366014203 5ustar sergeisergeitkabber-plugins-0.11.1/receipts/0000755000175000017500000000000011076120366016021 5ustar sergeisergeitkabber-plugins-0.11.1/receipts/README0000644000175000017500000000364311013755307016707 0ustar sergeisergei$Id: README 1426 2008-05-18 07:29:11Z sergei $ "Message receipts" -- plugin for Tkabber. I. The Idea This plugin implements XEP-0184 "Message receipts": in one-to-one chat sessions it is able to request confirmations of reception of outgoing messages and reply to such requests coming from remote party. Rception status is tracked for each message placed in the chat log window of a chat session using special icon: when the message is sent, the icon depicts "unconfirmed" status, when the confirmation arrives for this message, the icon associated with this message is changed to depict "confirmed" status. Receipts are only sent when all these conditions hold: * Receipt is requested (attached to a message). * Replying receipt requests isn't explicitly prohibited using the "reply" Customize option (see below). * The receipt request is attached to a message which is either received in a MUC's private chat or is originated from a user which is subscribed to our presence. In all other cases receipt requests are silently ignored. This is done in order not to leak presence information. Note that unlike some other IM clients Tkabber doesn't wait for receipt to arrive -- it just changes the status icon assotiated with particular message when its receipt is received. II. Configuration This plugin can be configured using Tkabber's Customize mechanism. Two configuration options are available under the "Plugins -> Message Receipts" group of settings (also available under "Chat -> Message Receipts"): * ::plugins::options::receipts(request) -- Attach request for receipt to each outgoing chat message. Default is true. * ::plugins::options::receipts(reply) -- Issue message receipts for messages that request them. Default is true. Note that issuing of receipts is further restricted based on privacy considerations (see above). III. Limitations Some functionality is missing. See TODO for details. # vim:tw=64:noet tkabber-plugins-0.11.1/receipts/msgs/0000755000175000017500000000000011076120366016772 5ustar sergeisergeitkabber-plugins-0.11.1/receipts/msgs/pl.msg0000644000175000017500000000167011021551246020114 0ustar sergeisergei# Polish messages file for receipts plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Error" "Błąd" ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "Issue receipts for incoming messages." "Wysyłaj potwierdzenia odbioru dla przychodzących wiadomości." ::msgcat::mcset pl "Request receipts for outgoing messages." "Żądaj potwierdzeń odbioru dla wysyłanych wiadomości." ::msgcat::mcset pl "Request receipts for outgoing messages and reply to such requests originating from chat peers. Message reception state is displayed next to each chat message using special icon." "Żądania potwierdzeń odbioru dla wychodzących wiadomości i odpowiadaj na takie żądania pochodzące od rozmówcy. Status potwierdzenia odbioru jest wyświetlany przy każdej wiadomości w rozmowie za pomocą odpowiedniej ikony." tkabber-plugins-0.11.1/receipts/msgs/es.msg0000644000175000017500000000131611021551246020105 0ustar sergeisergei# /home/bernar/insta/tkabber/tkabber/tkabber-plugins/receipts/receipts.tcl ::msgcat::mcset es "Issue receipts for incoming messages." "*Issue receipts for incoming messages." ::msgcat::mcset es "Plugins options." "*Plugins options." ::msgcat::mcset es "Request receipts for outgoing messages and reply to such requests originating from chat peers. Message reception state is displayed next to each chat message using special icon." "*Request receipts for outgoing messages and reply to such requests originating from chat peers. Message reception state is displayed next to each chat message using special icon." ::msgcat::mcset es "Request receipts for outgoing messages." "*Request receipts for outgoing messages." tkabber-plugins-0.11.1/receipts/msgs/de.msg0000644000175000017500000000153411014027517020071 0ustar sergeisergei # German messages file # Roger Sondermann 18.05.2008 ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "Issue receipts for incoming messages." "Empfangsbesttigungen fr eingehende Nachrichten ausstellen." ::msgcat::mcset de "Request receipts for outgoing messages and reply to such requests originating from chat peers. Message reception state is displayed next to each chat message using special icon." "Optionen fr Empfangsbesttigungen.\nEmpfangsbesttigungen fr ausgehende Nachrichten anfordern und derartige Anfragen von Chat-Partnern beantworten. Der Empfangs-Status wird durch ein spezielles Icon neben jeder Chat-Nachricht angezeigt." ::msgcat::mcset de "Request receipts for outgoing messages." "Empfangsbesttigungen fr ausgehende Nachrichten anfordern." tkabber-plugins-0.11.1/receipts/msgs/ru.msg0000644000175000017500000000224111015364576020135 0ustar sergeisergei# $Id: ru.msg 1444 2008-05-22 21:45:34Z sergei $ # Russian message catalog for the "receipts" plugin. ::msgcat::mcset ru "Issue receipts for incoming messages." "Подтверждать\ приём входящих сообщений." ::msgcat::mcset ru "Plugins options." "Настройки расширений." ::msgcat::mcset ru "Request receipts for outgoing messages and reply to such\ requests originating from chat peers. Message reception state is\ displayed next to each chat message using special icon." "Запрашивать\ подтверждения приёма исходящих сообщений и удовлетворять подобные\ запросы для сообщений других пользователей. Факт подтверждения приёма\ сообщения отображается рядом с сообщением в окне разговора при помощи\ специальной картинки." ::msgcat::mcset ru "Request receipts for outgoing messages." "Запрашивать\ подтверждения приёма исходящих сообщений." # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/receipts/TODO0000644000175000017500000000260411013755307016513 0ustar sergeisergei$Id: TODO 1426 2008-05-18 07:29:11Z sergei $ HIGH * Implement per-chat or per-JID enabling/disabling of message receipts. This presumably suggests implementing some general framework for "client-side privacy handling" on which this and other parts of Tkabber should be based (such as chat events and MUC ignoring). * Provide for sending receipts along with normal messages. And displaying of "reception confirmed" status. It appears to require a patch to Tkabber. Also it probably will fit more naturally to the "mailbox" concept which will probably be eventually implemented for handling "normal" messages. LOW * Honor peer's features, if available. * Think of implementing displaying of reception requests originating from chat peer: i.e. if peer reqtested a receipt for a given message, display an "empty" icon next to this message; if this request was satisfied, display "filled" icon, otherwise display "denied" icon. In fact this doesn't have much sense other than providing for better lineup of messages in a chat window which appears to be rather ragged now. * Receipts should probably be sent when a message is displayed, not when it's received. This also fits more cleanly with displaying of remote reception requests. * Try to decrease the size of icons (at least make them twice as this horizontally) -- may be they will look better. # vim:tw=64:noet tkabber-plugins-0.11.1/receipts/images/0000755000175000017500000000000011076120366017266 5ustar sergeisergeitkabber-plugins-0.11.1/receipts/images/confirmed.gif0000644000175000017500000000054211011605241021711 0ustar sergeisergeiGIF89a0qqqtttsss~~~{{{yyyvvvwww!0,@pH,D4J'͆xFʡb ԑ%r4h8..ñ(hq 0y&gyq * h + -)IKMO(RFEA;tkabber-plugins-0.11.1/receipts/images/unconfirmed.gif0000644000175000017500000000054711011605241022261 0ustar sergeisergeiGIF89a/qqqyyy䅅~~~sssttt{{{߇wwwvvv!/,pH,S 6hHX T'c8 |Z\/E"(_oq| y{  hj rs}*&&)IKMO+RFEA;tkabber-plugins-0.11.1/receipts/license.terms0000644000175000017500000000211211012353630020503 0ustar sergeisergeiCopyright (c) 2008 Konstantin Khomoutov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/receipts/INSTALL0000644000175000017500000000047311012353630017046 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/receipts/ ~/.tkabber/plugins/receipts/receipts.tcl Restart Tkabber, to get the plugin loaded. Consult the README file for the details about using this plugin. tkabber-plugins-0.11.1/receipts/AUTHORS0000644000175000017500000000016311012353630017061 0ustar sergeisergeiKonstantin Khomoutov Artwork by Artem Bannikov tkabber-plugins-0.11.1/receipts/receipts.tcl0000644000175000017500000000776311013755307020360 0ustar sergeisergei# $Id: receipts.tcl 1426 2008-05-18 07:29:11Z sergei $ # Support for XEP-0184 "Message Receipts" (v1.0). # Written by Konstantin Khomoutov # Artwork by Artem Bannikov # See README for usage guidelines. # See license.terms for legal details on usage and distribution. package require msgcat namespace eval receipts { set ::NS(receipts) urn:xmpp:receipts ::msgcat::mcload [file join [file dirname [info script]] msgs] foreach item {confirmed unconfirmed} { image create photo receipts/$item \ -file [file join [file dirname [info script]] images $item.gif] } unset item hook::add process_message_hook \ [namespace current]::process_message hook::add chat_send_message_xlist_hook \ [namespace current]::attach_confirmation_request hook::add draw_message_hook \ [namespace current]::add_receipt_icon 5 disco::register_feature $::NS(receipts) variable options custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup "Message Receipts" \ [::msgcat::mc "Request receipts for outgoing\ messages and reply to such requests originating from chat peers.\ Message reception state is displayed next to each chat message\ using special icon."] \ -group Plugins \ -group Chat custom::defvar options(request) 1 \ [::msgcat::mc "Request receipts for outgoing messages."] \ -group "Message Receipts" \ -type boolean custom::defvar options(reply) 1 \ [::msgcat::mc "Issue receipts for incoming messages."] \ -group "Message Receipts" \ -type boolean } # Receipts are only sent when all these conditions hold: # * They aren't disabled via Customize options. # * Receipt request is attached to a groupchat private # message or to a message from a user who subscribed # to our presence. proc receipts::reply_allowed {connid from type} { variable options if {!$options(reply)} { return 0 } if {[string equal $type chat]} { set chatid [chat::chatid $connid [node_and_server_from_jid $from]] if {[chat::is_groupchat $chatid]} { return 1 } } return [roster::is_trusted $connid $from] } proc receipts::process_message \ {connid from id type is_subject subject body err thread priority x} { foreach element $x { jlib::wrapper:splitxml $element tag vars isempty chdata children switch -- $tag { request { set xmlns [jlib::wrapper:getattr $vars xmlns] if {![string equal $xmlns $::NS(receipts)]} continue if {![reply_allowed $connid $from $type]} continue process_receipt_request $connid $from $id } received { set xmlns [jlib::wrapper:getattr $vars xmlns] if {![string equal $xmlns $::NS(receipts)]} continue process_receipt_response $connid $from $id $type } } } } proc receipts::process_receipt_request {connid from id} { jlib::send_msg $from -id $id \ -xlist [list [jlib::wrapper:createtag received \ -vars [list xmlns $::NS(receipts)]]] \ -connection $connid } proc receipts::process_receipt_response {connid from id type} { variable requests set chatid [chat::chatid $connid $from] if {![chat::is_opened $chatid]} return set cw [chat::chat_win $chatid] set name msgid_$id if {[lsearch -exact [$cw image names] $name] >= 0} { $cw image configure $name -image receipts/confirmed return } } proc receipts::add_receipt_icon {chatid from type body x} { if {![string equal $type chat]} return if {![richtext::property_exists msgid]} return set id [richtext::property_get msgid] set cw [chat::chat_win $chatid] $cw image create end -name msgid_$id -image receipts/unconfirmed } proc receipts::attach_confirmation_request {xlistVar chatid user body type} { variable options if {!$options(request) || ![chat::is_chat $chatid]} return global chat_msg_id upvar 2 $xlistVar xlist lappend xlist [jlib::wrapper:createtag request \ -vars [list xmlns $::NS(receipts)]] richtext::property_update msgid $chat_msg_id } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/README0000644000175000017500000001276311075425335015077 0ustar sergeisergeiExternal Plugins for Tkabber To install the desired plugins copy the plugin directories to $HOME/.tkabber/plugins (on UNIX), to %APPDATA%\Tkabber\plugins (on Windows), or to $HOME/Library/Application Support/Tkabber (on MacOS X) directory. Tkabber will automatically load the plugins when it's started. The plugins that you will surely want to try are: Chess, GeoRoster and Whiteboard. Short Description of the Included Plugins aniemoticons Plugin which adds support of animated emoticons. attline Plugin which draws so-called attention line - a line before the first message in a chat window where the window has lost keyboard focus. All messages after the line are unread messages. bc A word game. Inludes a russian file. browser Plugin which implements Jabber Browser (XEP-0011). This protocol is deprecated in favor of Service Discovery (XEP-0030), but may be useful for pre-XMPP servers/transports. checkers Checkers game for two players (including Straight, Russian, Spanish, Brazilian, Pool, Italian checkers). When installed, you can send an invitation to your contact (contextual menu on the roster). If the other player has also Tkabber and the plugin installed, he will recieve the invitation. If he accepts, a window will open on both. chess Chess game for two players. When installed, you can send an invitation to your contact (contextual menu on the roster). If the other player has also Tkabber and the plugin installed, he will recieve the invitation. If he accepts, a window will open on both. ctcomp Plugin adds support for "text completion" in Tkabber's chat input windows which works like the similar features of the Vim and Emacs text editors. The matching words are picked from the corresponding chat log and input windows. custom-urls Provides regexp-based mechanism to convert strings with numbers to URLs in chat windows. cyrillize Utility to translate misprinted characters to cyrillic pressing Ctrl+'. debug Allows to see debug messages in separate tab/window. ejabberd Utility to check your Ejabberd Jabber server remotely. floatinglog Plugin reports incoming messages, presence changes, status changes in a separate floating window. georoster World map. It tries to position your contacts using the data on vcard. You can also drag and drop your contacts from the roster on their possitions. gmail Plugin allows Gmail/Googlemail users to receive mail notifications. iconsets Several iconsets, borrowed from other Jabber clients, now are represented in this plugin. jidlink Implements Jidlink file transfer protocol. It's undocumented and obsolete, but may be useful for transferring files to old Tkabber versions. latex Displays formulas in LaTeX notation as embedded images, generated by LaTeX and ImageMagick. mute Experimental implementation of XEP-0058: Multi-User Text Editing, now deferred. openurl Plugin which adds several items to a URL popup menu. Each item allows to open the URL in a certain browser. osd Displays certain events (presence and chat messages) notification using osd_cat utility. presencecmd Plugin which adds several commands in a chat window. They change user's presence information (global or directed). quiz Adaptation of He3hauka (a russian quiz game for IRC). quotelastmsg Quote the very last message in a chat window. receipts Implements XEP-0184 "Message receipts": in one-to-one chat sessions it is able to request confirmations of reception of outgoing messages and reply to such requests coming from remote party. renju Gomoku and Renju (in fact, renju is not implemented yet) game for two players. When installed, you can send an invitation to your contact (contextual menu on the roster). If the other player has also Tkabber and the plugin installed, he will recieve the invitation. If he accepts, a window will open on both. reversi Reversi (othello) game for two players. When installed, you can send an invitation to your contact (contextual menu on the roster). If the other player has also Tkabber and the plugin installed, he will recieve the invitation. If he accepts, a window will open on both. singularity Keep conversation with one user in one window/tab. socials Adds many 'social' commands like /dance. Includes english and russian files. spy Logs your contacts presence changes to a window or to a file. Allows to setup alert window for certain contacts. stripes Colorises chat window background for odd and even messages differently. tclchat Plugin, which makes chatting in Tclers' chat (tcl@tach.tclers.tk) easier. It recognises a bot, which connects Jabber room with IRC channel, and maps IRC users to Jabber conference participants. tkabber-khim Plugin that adds KHIM (an alternative input method by Kevin Kenny) support to Tkabber. traffic Approximately accounts incoming and outgoing XMPP traffic by addressees. Traffic estimation is good only if no stream compression or encryption is used. But even if the absolute values are incorrect, it still allows to find which remote JID consumes the highest traffic amount. unixkeys Adds support for "Unix-style" (in fact, GNU Readline and GNU bash -style) keyboard shortcuts for text editing to all text entry widgets in Tkabber. whiteboard Shared whiteboard, allows two contacts or a whole chatroom to draw collaboratively. tkabber-plugins-0.11.1/jidlink/0000755000175000017500000000000011076120366015627 5ustar sergeisergeitkabber-plugins-0.11.1/jidlink/README0000644000175000017500000000162110666000372016505 0ustar sergeisergei$Id: README 1209 2007-08-31 11:52:26Z sergei $ Jidlink is a simple negotiation protocol for setting up a bytestream between two JIDs. With it you can specify what transports you can use, and via negotiation choose more appropriate one. There are three transport implementations: dtcp-active: that allows you to connect to any node that supports "dtcp-passive"; dtcp-passive: that allows any node that supports "dtcp-active" to connect to you; and, inband-bytestream: that uses your "Jabber" connection to transmit the data (which may slowdown other traffic to you). If your machine is behind a firewall, then you can't use the "dtcp-passive" transport, so you should disable it in a config file: set jidlink::transport(allowed,dtcp-passive) 0 Jidlink is undocumented and obsolete, but it may be useful for file transfer to old Tkabber clients which don't support Stream Initiation protocol. tkabber-plugins-0.11.1/jidlink/msgs/0000755000175000017500000000000011076120366016600 5ustar sergeisergeitkabber-plugins-0.11.1/jidlink/msgs/pl.msg0000644000175000017500000000322110667535014017726 0ustar sergeisergei# Polish messages file for jidlink plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies # jidlink.tcl ::msgcat::mcset pl "Enable Jidlink transport %s." "Włącz transport Jidlink %s." ::msgcat::mcset pl "Jidlink connection closed" "Otwieranie połączenia Jidlink" ::msgcat::mcset pl "Opening Jidlink connection" "Połączenie Jidlink zamknięte" # plugins/dtcp.tcl ::msgcat::mcset pl "Opening DTCP active connection" "Otwieranie aktywnego połączenia DTCP" ::msgcat::mcset pl "Opening DTCP passive connection" "Otwieranie pasywnego połączenia DTCP" # plugins/ibb.tcl ::msgcat::mcset pl "Opening IBB connection" "Otwieranie połącznia IBB" # plugins/filetransfer.tcl ::msgcat::mcset pl "Browse..." "Przeglądaj..." ::msgcat::mcset pl "Cancel" "Anuluj" ::msgcat::mcset pl "Connection closed" "Połączenie zamknięte" ::msgcat::mcset pl "Description:" "Opis:" ::msgcat::mcset pl "Jidlink connection failed" "Połączenie za pomocą protokołu Jidlink nie udało się" ::msgcat::mcset pl "Jidlink options." "Ustawienia protokołu Jidlink." ::msgcat::mcset pl "Jidlink transfer failed" "Przesłanie pliku za pomocą protokołu Jidlink nie udało się" ::msgcat::mcset pl "Name:" "Nazwa:" ::msgcat::mcset pl "Receive" "Odbierz" ::msgcat::mcset pl "Receive file from %s" "Odbierz plik od %s" ::msgcat::mcset pl "Receiving file failed: %s" "Nie udało się odebrać pliku: %s" ::msgcat::mcset pl "Request failed: %s" "Wywołanie nie powiodło się: %s" ::msgcat::mcset pl "Save as:" "Zapisz jako:" ::msgcat::mcset pl "Size:" "Rozmiar:" ::msgcat::mcset pl "Transferring..." "Przesyłanie..." tkabber-plugins-0.11.1/jidlink/msgs/es.msg0000644000175000017500000000244311021551246017715 0ustar sergeisergei::msgcat::mcset es "Browse..." "Navegar..." ::msgcat::mcset es "Cancel" "Cancelar" ::msgcat::mcset es "Connection closed" "Conexión cerrada" ::msgcat::mcset es "Description:" "Descripción:" ::msgcat::mcset es "Enable Jidlink transport %s." "Actibar transporte Jidlink %s." ::msgcat::mcset es "Jidlink connection closed" "Conexión Jidlink cerrada" ::msgcat::mcset es "Jidlink connection failed" "Falló la conexión Jidlink" ::msgcat::mcset es "Jidlink options." "Opciones Jidlink." ::msgcat::mcset es "Jidlink transfer failed" "Falló la transferencia Jidlink" ::msgcat::mcset es "Name:" "Nombre:" ::msgcat::mcset es "Opening DTCP active connection" "Abriendo conexión activa DTCP" ::msgcat::mcset es "Opening DTCP passive connection" "Abriendo conexión pasiva DTCP" ::msgcat::mcset es "Opening IBB connection" "Abriendo conexión IBB" ::msgcat::mcset es "Opening Jidlink connection" "Abriendo conexión Jidlink" ::msgcat::mcset es "Receive file from %s" "Recibir fichero de %s" ::msgcat::mcset es "Receive" "Recibir" ::msgcat::mcset es "Receiving file failed: %s" "Falló la recepción del fichero: %s" ::msgcat::mcset es "Request failed: %s" "Falló la petición: %s" ::msgcat::mcset es "Save as:" "Guardar como:" ::msgcat::mcset es "Size:" "Tamaño:" ::msgcat::mcset es "Transferring..." "Transfiriendo..." tkabber-plugins-0.11.1/jidlink/msgs/de.msg0000644000175000017500000000344010670567342017711 0ustar sergeisergei # German messages file # Roger Sondermann 08.09.2007 # .../jidlink.tcl ::msgcat::mcset de "Enable Jidlink transport %s." "'Jidlink'-Transport %s aktivieren." ::msgcat::mcset de "Jidlink connection closed" "'Jidlink'-Verbindung geschlossen" ::msgcat::mcset de "Opening Jidlink connection" "ffne 'Jidlink'-Verbindung" # .../plugins/ibb.tcl ::msgcat::mcset de "Opening IBB connection" "ffne IBB-Verbindung" # .../plugins/filetransfer.tcl ::msgcat::mcset de "Browse..." "Durchsuchen..." ::msgcat::mcset de "Cancel" "Abbrechen" ::msgcat::mcset de "Connection closed" "Verbindung geschlossen" ::msgcat::mcset de "Description:" "Beschreibung:" ::msgcat::mcset de "Jidlink connection failed" "'Jidlink'-Verbindung misslungen" ::msgcat::mcset de "Jidlink options." "Optionen fr 'Jidlink'." ::msgcat::mcset de "Jidlink transfer failed" "'Jidlink'-bertragung misslungen" ::msgcat::mcset de "Name:" "Name:" ::msgcat::mcset de "Receive" "Empfangen" ::msgcat::mcset de "Receive file from %s" "Empfange Datei von %s" ::msgcat::mcset de "Receiving file failed: %s" "Datei-Empfang misslungen: %s" ::msgcat::mcset de "Request failed: %s" "Anfrage misslungen: %s" ::msgcat::mcset de "Save as:" "Speichern als:" ::msgcat::mcset de "Size:" "Gre:" ::msgcat::mcset de "Transferring..." "bertrage . . ." # .../plugins/dtcp.tcl ::msgcat::mcset de "Opening DTCP active connection" "ffne aktive DTCP-Verbindung" ::msgcat::mcset de "Opening DTCP passive connection" "ffne passive DTCP-Verbindung" tkabber-plugins-0.11.1/jidlink/msgs/ru.msg0000644000175000017500000000324710666224632017751 0ustar sergeisergei# $Id: ru.msg 1214 2007-09-01 08:58:02Z sergei $ ::msgcat::mcset ru "Browse..." "Выбрать..." ::msgcat::mcset ru "Cancel" "Отменить" ::msgcat::mcset ru "Connection closed" "Соединение закрыто" ::msgcat::mcset ru "Description:" "Описание:" ::msgcat::mcset ru "Enable Jidlink transport %s." "Разрешить использование Jidlink-транспорта %s" ::msgcat::mcset ru "Jidlink connection closed" "Соединение Jidlink закрыто" ::msgcat::mcset ru "Jidlink connection failed" "Соединиться по Jidlink не удалось" ::msgcat::mcset ru "Jidlink options." "Параметры Jidlink-транспорта." ::msgcat::mcset ru "Jidlink transfer failed" "Передать файл по Jidlink не удалось" ::msgcat::mcset ru "Name:" "Имя:" ::msgcat::mcset ru "Opening DTCP active connection" "Открываем соединение DTCP" ::msgcat::mcset ru "Opening DTCP passive connection" "Соединение DTCP закрыто" ::msgcat::mcset ru "Opening IBB connection" "Открываем соединение IBB" ::msgcat::mcset ru "Opening Jidlink connection" "Открываем соединение Jidlink" ::msgcat::mcset ru "Receive" "Получить" ::msgcat::mcset ru "Receive file from %s" "Получение файла от %s" ::msgcat::mcset ru "Receiving file failed: %s" "Получение файла не удалось: %s" ::msgcat::mcset ru "Request failed: %s" "Запрос не удался: %s" ::msgcat::mcset ru "Save as:" "Сохранить как:" ::msgcat::mcset ru "Size:" "Размер:" ::msgcat::mcset ru "Transferring..." "Передача файла..." tkabber-plugins-0.11.1/jidlink/jidlink.tcl0000644000175000017500000001170310666000372017757 0ustar sergeisergei# $Id: jidlink.tcl 1209 2007-08-31 11:52:26Z sergei $ package require msgcat namespace eval ::jidlink { ::msgcat::mcload [file join [file dirname [info script]] msgs] set transport(list) {} } proc ::jidlink::connect {connid jid {key {}}} { variable connection if {$key == ""} { set key [rand 1000000000] } #set connection(sf,$key) $send_func #set connection(rf,$key) $recv_func set connection(connid,$key) $connid set connection(jid,$key) $jid set_status [::msgcat::mc "Opening Jidlink connection"] jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:jidlink} \ -subtags [list [jlib::wrapper:createtag key -chdata $key]]] \ -to $jid \ -command [list [namespace current]::connect_response $connid $jid $key] \ -connection $connid vwait [namespace current]::connection(status,$key) return connection(status,$key) } proc ::jidlink::connect_response {connid jid key res child} { variable connection variable transport if {$res != "OK"} { # TODO set connection(status,$key) 0 return } set trans [lsort -unique -index 1 $transport(list)] set options {} foreach t $trans { set name [lindex $t 0] if {![info exists transport(allowed,$name)] || \ $transport(allowed,$name)} { lappend options $name } } if {[llength $options] == 0} { # TODO set connection(status,$key) 0 return } lassign [negotiate::send_request $connid $jid jabber:iq:jidlink $options] res opts if {[llength $opts] == 1 && [lcontain $options [lindex $opts 0]]} { set name [lindex $opts 0] set connection(transport,$key) $name eval $transport(connect,$name) [list $connid $jid $key] set connection(status,$key) 1 return } set connection(status,$key) 0 } proc ::jidlink::set_readable_handler {key handler} { variable connection set connection(readable_handler,$key) $handler } proc ::jidlink::set_closed_handler {key handler} { variable connection set connection(closed_handler,$key) $handler } proc ::jidlink::send_data {key data} { variable connection variable transport eval $transport(send,$connection(transport,$key)) [list $key $data] } proc ::jidlink::recv_data {key data} { variable connection debugmsg jidlink "RECV_DATA [list $key $data]" append connection(data,$key) $data if {[info exists connection(readable_handler,$key)]} { eval $connection(readable_handler,$key) [list $key] } } proc ::jidlink::read_data {key} { variable connection set data $connection(data,$key) set connection(data,$key) {} return $data } proc ::jidlink::close {key} { variable connection variable transport eval $transport(close,$connection(transport,$key)) [list $key] set_status [::msgcat::mc "Jidlink connection closed"] } proc ::jidlink::closed {key} { variable connection if {[info exists connection(closed_handler,$key)]} { eval $connection(closed_handler,$key) [list $key] } } # TODO: connid proc ::jidlink::negotiate_handler {from type options} { variable transport set trans [lsort -unique -index 1 $transport(list)] set myoptions {} foreach t $trans { set name [lindex $t 0] if {![info exists transport(allowed,$name)] || \ $transport(allowed,$name)} { lappend myoptions $transport(oppos,$name) } } if {$options == {}} { return $myoptions } foreach opt $options { if {[lcontain $myoptions $opt]} { return [list $opt] } } return {} } negotiate::register_handler jabber:iq:jidlink ::jidlink::negotiate_handler proc ::jidlink::set_handler {connid from lang child} { debugmsg jidlink "set: [list $from $child]" jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 if {$tag1 == "key"} { set key $chdata1 debugmsg jidlink "KEY: $key" } } if {[info exists key]} { return [list result $child] } else { # TODO } } else { # TODO } } iq::register_handler set query jabber:iq:jidlink ::jidlink::set_handler proc ::jidlink::register_transport {name oppos prio connect send close} { variable transport lappend transport(list) [list $name $prio] set transport(oppos,$name) $oppos set transport(connect,$name) $connect set transport(send,$name) $send set transport(close,$name) $close } # Loading jidlink plugins foreach file [lsort [glob -nocomplain \ [file join [file dirname [info script]] plugins]/*.tcl]] { debugmsg jidlink "Loading plugin from $file" source $file } proc ::jidlink::setup_customize {} { variable transport set trans [lsort -unique -index 1 $transport(list)] foreach t $trans { lassign $t name prio custom::defvar transport(allowed,$name) 1 \ [format [::msgcat::mc "Enable Jidlink transport %s."] $name] \ -type boolean -group Jidlink } } hook::add finload_hook ::jidlink::setup_customize 40 tkabber-plugins-0.11.1/jidlink/plugins/0000755000175000017500000000000011076120366017310 5ustar sergeisergeitkabber-plugins-0.11.1/jidlink/plugins/filetransfer.tcl0000644000175000017500000002715710666000372022512 0ustar sergeisergei# $Id: filetransfer.tcl 1209 2007-08-31 11:52:26Z sergei $ ############################################################################### # File transfer via Jidlink namespace eval ftjl { set winid 0 set id 0 set chunk_size 1024 variable options custom::defgroup Jidlink \ [::msgcat::mc "Jidlink options."] \ -group {File Transfer} } ############################################################################### proc ftjl::send_file {token} { upvar #0 $token state variable id variable files if {![info exists state(fd)]} return incr id set state(id) $id set files(token,$id) $token jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:filexfer} \ -subtags [list [jlib::wrapper:createtag file \ -vars [list id $id \ name $state(name) \ size $state(size)] \ -chdata $state(desc)]]] \ -to $state(jid) \ -command [list [namespace current]::send_file_result $token] \ -connection $state(connid) } ############################################################################### proc ftjl::send_file_result {token res child} { upvar #0 $token state if {![info exists state(fd)]} return if {[cequal $res OK]} return eval $state(command) ERR \ [list [::msgcat::mc "Request failed: %s" [error_to_string $child]]] } ############################################################################### proc ftjl::send_file_request {connid from lang id offset} { variable files if {![info exists files(token,$id)]} { return [list error cancel not-allowed \ -text [::trans::trans $lang "Invalid file ID"]] } set token $files(token,$id) upvar #0 $token state if {![info exists state(fd)]} { return [list error cancel not-allowed \ -text [::trans::trans $lang "Transfer is expired"]] } if {$state(connid) != $connid || $state(jid) != $from} { return [list error cancel not-allowed \ -text [::trans::trans $lang "Invalid file ID"]] } set state(key) [rand 1000000000] set state(offset) $offset set res \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:filexfer} \ -subtags [list [jlib::wrapper:createtag file \ -vars [list id $id] \ -subtags [list [jlib::wrapper:createtag key \ -chdata $state(key)]]]]] after idle [list [namespace current]::send_file_setup_connection $token] return [list result $res] } ############################################################################### proc ftjl::send_file_setup_connection {token} { upvar #0 $token state variable chunk_size if {![info exists state(fd)]} return set res [jidlink::connect $state(connid) $state(jid) $state(key)] if {$res == 0} { if {[info exists state(command)]} { eval $state(command) ERR [::msgcat::mc "Jidlink connection failed"] } return } set_status [::msgcat::mc "Transferring..."] # Transfer window may be destroyed during jidlink::connect if {![info exists state(fd)]} return set chunk [read $state(fd) $chunk_size] if {[catch { while {$chunk != ""} { jidlink::send_data $state(key) $chunk update idletasks eval $state(command) [list PROGRESS [tell $state(fd)]] after 1000 set chunk [read $state(fd) $chunk_size] } }]} { if {[info exists state(command)]} { eval $state(command) ERR [::msgcat::mc "Jidlink transfer failed"] } return } eval $state(command) OK } ############################################################################### proc ftjl::send_file_close {token} { upvar #0 $token state variable files if {![info exists state(fd)]} return catch {unset files(token,$state(id))} catch {jidlink::close $state(key)} } ############################################################################### ############################################################################### proc ftjl::recv_file_dialog {connid from lang id name size date hash desc} { variable winid variable files variable result set w .rfd$winid while {[winfo exists $w]} { incr winid set w .rfd$winid } Dialog $w -title [format [::msgcat::mc "Receive file from %s"] $from] \ -separator 1 -anchor e \ -modal none -default 0 -cancel 1 set f [$w getframe] label $f.lname -text [::msgcat::mc "Name:"] label $f.name -text $name label $f.lsize -text [::msgcat::mc "Size:"] label $f.size -text $size label $f.ldesc -text [::msgcat::mc "Description:"] message $f.desc -width 10c -text $desc set dir $ft::options(download_dir) label $f.lsaveas -text [::msgcat::mc "Save as:"] entry $f.saveas -textvariable [namespace current]::saveas$winid variable saveas$winid [file join $dir $name] button $f.browsefile -text [::msgcat::mc "Browse..."] \ -command [list [namespace current]::set_receive_file_name $winid $dir $name] set pbvar [namespace current]::progress$f.pb ProgressBar $f.pb -variable $pbvar $f.pb configure -maximum $size set $pbvar 0 grid $f.lname -row 0 -column 0 -sticky e grid $f.name -row 0 -column 1 -sticky w grid $f.lsize -row 1 -column 0 -sticky e grid $f.size -row 1 -column 1 -sticky w grid $f.ldesc -row 2 -column 0 -sticky en grid $f.desc -row 2 -column 1 -sticky ewns -columnspan 2 -pady 1m grid $f.lsaveas -row 3 -column 0 -sticky e grid $f.saveas -row 3 -column 1 -sticky ew grid $f.browsefile -row 3 -column 2 -sticky ew grid $f.pb -row 4 -column 0 -sticky ew -columnspan 3 -pady 2m grid columnconfigure $f 1 -weight 1 -minsize 8c grid rowconfigure $f 2 -weight 1 $w add -text [::msgcat::mc "Receive"] -command \ [list [namespace current]::recv_file_start $winid $size $pbvar $connid $from $lang $id] $w add -text [::msgcat::mc "Cancel"] -command \ [list [namespace current]::recv_file_cancel $winid $lang] bind .rfd$winid \ [list [namespace current]::recv_file_failed $winid $lang] $w draw vwait [namespace current]::result($winid) set res $result($winid) unset result($winid) incr winid return $res } ############################################################################### proc ftjl::set_receive_file_name {winid dir fname} { variable saveas$winid set file [tk_getSaveFile -initialdir $dir -initialfile $fname] if {$file != ""} { set saveas$winid $file } } ############################################################################### proc ftjl::recv_file_start {winid size pbvar connid user lang id} { variable saveas$winid variable files set filename [set saveas$winid] .rfd$winid itemconfigure 0 -state disabled set $pbvar 0 #set files(filename,$key) $filename jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:filexfer} \ -subtags [list [jlib::wrapper:createtag file \ -vars [list id $id]]]] \ -to $user \ -command [list [namespace current]::recv_file_reply \ $winid $size $pbvar $user $lang $id $filename] \ -connection $connid } ############################################################################### proc ftjl::recv_file_reply {winid size pbvar user lang id filename res child} { variable files if {$res != "OK"} { recv_file_failed $winid $lang after idle \ [list MessageDlg .auth_err -aspect 50000 -icon error \ -message [format [::msgcat::mc "Receiving file failed: %s"] \ [error_to_string $child]] -type user \ -buttons ok -default 0 -cancel 0] return } jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 if {$tag1 == "file"} { foreach item1 $children1 { jlib::wrapper:splitxml $item1 tag2 vars2 isempty2 \ chdata2 children2 if {$tag2 == "key"} { set key $chdata2 set files(filename,$key) $filename debugmsg filetransfer "RECV KEY: $key" set fd [open $filename w] fconfigure $fd -translation binary set files(fd,$key) $fd jidlink::set_readable_handler \ $key [list [namespace current]::recv_file_chunk $pbvar] jidlink::set_closed_handler \ $key [list [namespace current]::recv_file_finish $winid $size] } } } } } } ############################################################################### proc ftjl::recv_file_chunk {pbvar key} { variable files if {[info exists files(filename,$key)]} { set data [jidlink::read_data $key] debugmsg filetransfer \ "RECV into $files(filename,$key) data length [string length $data]" puts -nonewline $files(fd,$key) $data incr $pbvar [string length $data] debugmsg filetransfer [set $pbvar] } } ############################################################################### proc ftjl::recv_file_failed {winid lang} { variable result bind .rfd$winid {} set result($winid) \ [list error modify undefined-condition \ -text [::trans::trans $lang "File transfer is failed"]] } ############################################################################### proc ftjl::recv_file_finish {winid size key} { variable files variable result if {[info exists files(filename,$key)]} { debugmsg filetransfer CLOSE catch { close $files(fd,$key) } set fsize [file size $files(filename,$key)] unset files(filename,$key) set_status [::msgcat::mc "Connection closed"] } if {[winfo exists .rfd$winid]} { bind .rfd$winid {} destroy .rfd$winid if {$fsize != $size} { if {$fsize < $size} { set msg "Transfer interrupted (File size is too small)" } else { set msg "File size is too large" } after idle \ [list MessageDlg .auth_err -aspect 50000 -icon error \ -message [format [::msgcat::mc "Receiving file failed: %s"] \ $msg] \ -type user \ -buttons ok -default 0 -cancel 0] } } set result($winid) {result {}} } ############################################################################### proc ftjl::recv_file_cancel {winid lang} { variable result catch { bind .rfd$winid {} destroy .rfd$winid } set result($winid) \ [list error cancel not-allowed \ -text [::trans::trans $lang "File transfer is refused"]] } ############################################################################### proc ftjl::iq_set_handler {connid from lang child} { debugmsg filetransfer "FTJL set: [list $from $child]" jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag != "query"} { return {error modify bad-request} } foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 if {$tag1 == "file"} { if {[jlib::wrapper:getattr $vars1 name] != ""} { return [recv_file_dialog $connid $from $lang \ [jlib::wrapper:getattr $vars1 id] \ [jlib::wrapper:getattr $vars1 name] \ [jlib::wrapper:getattr $vars1 size] \ [jlib::wrapper:getattr $vars1 date] \ [jlib::wrapper:getattr $vars1 hash] \ $chdata1] } else { return [send_file_request $connid $from $lang \ [jlib::wrapper:getattr $vars1 id] \ [jlib::wrapper:getattr $vars1 offset]] } } } } iq::register_handler set query jabber:iq:filexfer \ [namespace current]::ftjl::iq_set_handler ############################################################################### ft::register_protocol jidlink \ -priority 20 \ -label "Jidlink" \ -send [namespace current]::ftjl::send_file \ -close [namespace current]::ftjl::send_file_close ############################################################################### tkabber-plugins-0.11.1/jidlink/plugins/ibb.tcl0000644000175000017500000001113510666000372020547 0ustar sergeisergei# $Id: ibb.tcl 1209 2007-08-31 11:52:26Z sergei $ namespace eval ::ibb {} proc ::ibb::connect {connid jid key} { variable connection set_status [::msgcat::mc "Opening IBB connection"] jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:ibb} \ -subtags [list [jlib::wrapper:createtag comment \ -subtags [list [jlib::wrapper:createtag key \ -chdata $key]]]]] \ -to $jid -command [list ibb::recv_connect_response $connid $jid $key] \ -connection $connid vwait [namespace current]::connection(status,$key) } proc ::ibb::recv_connect_response {connid jid key res child} { variable connection if {$res != "OK"} { # TODO set connection(status,$key) 0 return } jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 if {$tag1 == "streamid"} { set streamid $chdata1 debugmsg jidlink "STREAMID: $streamid" } } if {[info exists streamid]} { variable stream_key variable key_stream set stream_key($streamid) $key set key_stream($key) $streamid set connection(connid,$key) $connid set connection(jid,$key) $jid set connection(status,$key) 1 } else { # TODO } } else { # TODO } set connection(status,$key) 0 } package require base64 proc ::ibb::send_data {key data} { variable connection variable key_stream debugmsg jidlink [array get stream_key] jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:inband} \ -subtags [list [jlib::wrapper:createtag streamid \ -chdata $key_stream($key)] \ [jlib::wrapper:createtag data \ -chdata [base64::encode $data]]]] \ -to $connection(jid,$key) \ -command [list ibb::send_data_ack $key] \ -connection $connection(connid,$key) vwait [namespace current]::connection(ack,$key) return $connection(ack,$key) } proc ::ibb::send_data_ack {key res child} { variable connection if {$res != "OK"} { # TODO set connection(ack,$key) 0 return } set connection(ack,$key) 1 } proc ::ibb::close {key} { variable connection variable key_stream jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:inband} \ -subtags [list [jlib::wrapper:createtag streamid \ -chdata $key_stream($key)] \ [jlib::wrapper:createtag close]]] \ -to $connection(jid,$key) \ -connection $connection(connid,$key) } proc ::ibb::iq_set_handler {connid from lang child} { jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 if {$tag1 == "comment"} { foreach item1 $children1 { jlib::wrapper:splitxml $item1 tag2 vars2 isempty2 \ chdata2 children2 if {$tag2 == "key"} { set key $chdata2 debugmsg jidlink "KEY: $key" } } } } if {[info exists key]} { variable stream_key variable key_stream set streamid [rand 1000000000] set stream_key($streamid) $key set key_stream($key) $streamid set res [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:ibb} \ -subtags [list [jlib::wrapper:createtag streamid \ -chdata $streamid]]] return [list result $res] } else { # TODO } } else { # TODO } } iq::register_handler set query jabber:iq:ibb ibb::iq_set_handler proc ::ibb::iq_inband_set_handler {connid from lang child} { variable stream_key jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 switch -- $tag1 { streamid { set streamid $chdata1 } data { set data $chdata1 } close { set close 1 } } } if {[info exists streamid] && [info exists stream_key($streamid)]} { if {[info exists data]} { if {[catch {set decoded [base64::decode $data]}]} { # TODO debugmsg jidlink "IBB: WRONG DATA" } else { debugmsg jidlink "IBB: RECV DATA [list $data]" jidlink::recv_data $stream_key($streamid) $decoded } } if {[info exists close]} { jidlink::closed $stream_key($streamid) } return [list result ""] } else { # TODO } } else { # TODO } } iq::register_handler set query jabber:iq:inband ibb::iq_inband_set_handler jidlink::register_transport inband-bytestream inband-bytestream 75 \ ibb::connect ibb::send_data ibb::close tkabber-plugins-0.11.1/jidlink/plugins/dtcp.tcl0000644000175000017500000002137110666000372020750 0ustar sergeisergei# $Id: dtcp.tcl 1209 2007-08-31 11:52:26Z sergei $ namespace eval ::dtcp {} namespace eval ::dtcp::active {} namespace eval ::dtcp::passive {} proc ::dtcp::active::connect {connid jid key} { variable connection set_status [::msgcat::mc "Opening DTCP active connection"] jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:dtcp} \ -subtags [list \ [jlib::wrapper:createtag key \ -chdata $key] \ [jlib::wrapper:createtag comment \ -subtags [list [jlib::wrapper:createtag key \ -chdata $key]]]]] \ -to $jid \ -command [list ::dtcp::active::recv_connect_response $connid $jid $key] \ -connection $connid vwait [namespace current]::connection(status,$key) } proc ::dtcp::active::recv_connect_response {connid jid key res child} { variable connection if {$res != "OK"} { # TODO set connection(status,$key) 0 return } jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { set hosts {} foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 switch -- $tag1 { verify { set verify $chdata1 debugmsg jidlink "VERIFY: $verify" } host { lappend hosts [list $chdata1 \ [jlib::wrapper:getattr $vars1 port]] } } } if {[info exists verify]} { variable verify_key variable key_verify set verify_key($verify) $key set key_verify($key) $verify set connection(connid,$key) $connid set connection(jid,$key) $jid foreach host $hosts { lassign $host addr port debugmsg jidlink "CONNECTING TO $addr:$port..." if {[catch {set sock [socket $addr $port]}]} continue debugmsg jidlink "CONNECTED" fconfigure $sock -encoding binary set connection(sock,$key) $sock puts $sock "key:$key" flush $sock fileevent $sock readable \ [list ::dtcp::active::wait_for_verify $key $sock] return } debugmsg jidlink "FAILED" set connection(status,$key) 0 return } else { # TODO } } else { # TODO } set connection(status,$key) 0 } proc ::dtcp::active::sock_connect {key hosts} { variable connection variable verify_key variable key_verify foreach host $hosts { lassign $host addr port debugmsg jidlink "CONNECTING TO $addr:$port..." if {[catch {set sock [socket $addr $port]}]} continue debugmsg jidlink "CONNECTED" fconfigure $sock -encoding binary set connection(sock,$key) $sock puts $sock "key:$key" flush $sock fileevent $sock readable \ [list ::dtcp::active::wait_for_verify $key $sock] return } debugmsg jidlink "FAILED" set connection(status,$key) 0 } proc ::dtcp::active::send_data {key data} { variable connection variable key_stream puts -nonewline $connection(sock,$key) $data flush $connection(sock,$key) return 1 } proc ::dtcp::active::close {key} { variable connection variable key_stream ::close $connection(sock,$key) } proc ::dtcp::active::wait_for_verify {key chan} { variable connection variable key_verify set s [gets $chan] debugmsg jidlink "WFV: [list $s]" if {[crange $s 0 6] == "verify:"} { set verify [crange $s 7 end] if {$verify == $key_verify($key)} { fconfigure $chan -translation binary -blocking no fileevent $chan readable \ [list ::dtcp::readable $key $chan] set connection(status,$key) 1 return } } ::close $chan jidlink::closed $key } jidlink::register_transport dtcp-active dtcp-passive 25 \ ::dtcp::active::connect ::dtcp::active::send_data ::dtcp::active::close proc ::dtcp::passive::connect {connid jid key} { variable connection set_status [::msgcat::mc "Opening DTCP passive connection"] set servsock [socket -server [list ::dtcp::passive::accept $key] 0] lassign [fconfigure $servsock -sockname] addr hostname port set ip [lindex [fconfigure $jlib::lib($connid,sck) -sockname] 0] jlib::send_iq set \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:dtcp} \ -subtags [list \ [jlib::wrapper:createtag key \ -chdata $key] \ [jlib::wrapper:createtag host \ -vars [list port $port] \ -chdata $ip] \ [jlib::wrapper:createtag comment \ -subtags [list [jlib::wrapper:createtag key \ -chdata $key]]]]] \ -to $jid \ -command [list ::dtcp::passive::recv_connect_response $connid $jid $key] \ -connection $connid vwait [namespace current]::connection(status,$key) } proc ::dtcp::passive::recv_connect_response {connid jid key res child} { variable connection if {$res != "OK"} { # TODO set connection(status,$key) 0 return } jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { set hosts {} foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 switch -- $tag1 { verify { set verify $chdata1 debugmsg jidlink "VERIFY: $verify" } host { lappend hosts [list $chdata1 \ [jlib::wrapper:getattr $vars port]] } } } if {[info exists verify]} { variable verify_key variable key_verify set verify_key($verify) $key set key_verify($key) $verify set connection(connid,$key) $connid set connection(jid,$key) $jid #set connection(status,$key) 1 return } else { # TODO } } else { # TODO } set connection(status,$key) 0 } proc ::dtcp::passive::send_data {key data} { variable connection variable key_stream puts -nonewline $connection(sock,$key) $data flush $connection(sock,$key) return 1 } proc ::dtcp::passive::close {key} { variable connection variable key_stream ::close $connection(sock,$key) } proc ::dtcp::passive::accept {key chan addr port} { variable connection variable key_verify debugmsg jidlink "CONNECT FROM $addr:$port" set connection(sock,$key) $chan fileevent $chan readable \ [list ::dtcp::passive::wait_for_key $key $chan] } proc ::dtcp::passive::wait_for_key {key chan} { variable connection variable key_verify set s [gets $chan] if {[crange $s 0 3] == "key:"} { set key2 [crange $s 4 end] if {$key == $key2} { debugmsg jidlink [array get key_verify] puts $chan "verify:$key_verify($key)" flush $chan fconfigure $chan -translation binary -blocking no fileevent $chan readable \ [list ::dtcp::readable $key $chan] set connection(status,$key) 1 return } } puts $chan error flush $chan } proc ::dtcp::readable {key chan} { if {![eof $chan]} { set buf [read $chan 4096] jidlink::recv_data $key $buf } else { fileevent $chan readable {} jidlink::closed $key } } proc ::dtcp::iq_set_handler {connid from lang child} { jlib::wrapper:splitxml $child tag vars isempty chdata children if {$tag == "query"} { set hosts {} foreach item $children { jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1 switch -- $tag1 { comment { foreach item1 $children1 { jlib::wrapper:splitxml $item1 tag2 vars2 isempty2 \ chdata2 children2 if {$tag2 == "key"} { set key $chdata2 debugmsg jidlink "KEY: $key" } } } key { set key $chdata1 debugmsg jidlink "KEY: $key" } host { lappend hosts [list $chdata1 \ [jlib::wrapper:getattr $vars1 port]] } } } if {[info exists key]} { set verify [rand 1000000000] if {$hosts == {}} { variable passive::verify_key variable passive::key_verify set passive::verify_key($verify) $key set passive::key_verify($key) $verify set servsock \ [socket -server \ [list ::dtcp::passive::accept $key] 0] lassign [fconfigure $servsock -sockname] addr hostname port set ip [lindex [fconfigure $jlib::lib($connid,sck) -sockname] 0] set res [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:dtcp} \ -subtags [list \ [jlib::wrapper:createtag verify \ -chdata $verify] \ [jlib::wrapper:createtag host \ -vars [list port $port] \ -chdata $ip]]] } else { variable active::verify_key variable active::key_verify set active::verify_key($verify) $key set active::key_verify($key) $verify debugmsg jidlink [list $hosts] after idle [list ::dtcp::active::sock_connect $key $hosts] set res [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:dtcp} \ -subtags [list [jlib::wrapper:createtag verify \ -chdata $verify]]] } return [list result $res] } else { # TODO } } else { # TODO } } iq::register_handler set query jabber:iq:dtcp ::dtcp::iq_set_handler jidlink::register_transport dtcp-passive dtcp-active 50 \ ::dtcp::passive::connect ::dtcp::passive::send_data ::dtcp::passive::close tkabber-plugins-0.11.1/quiz/0000755000175000017500000000000011076120366015173 5ustar sergeisergeitkabber-plugins-0.11.1/quiz/quizdata.txt0000644000175000017500000000076310563656425017576 0ustar sergeisergei .| , .| , .| .| ( , ).| tkabber-plugins-0.11.1/quiz/quiz.tcl0000644000175000017500000002400210657346175016701 0ustar sergeisergei# $Id: quiz.tcl 1183 2007-08-11 14:49:33Z sergei $ namespace eval quiz { set prefix {[QUIZ]: } } proc quiz::load_file {filename {enc utf-8}} { variable questions set fd [open $filename] fconfigure $fd -encoding $enc set questions(qa) {} set questions(qpos) {} set n 0 while {![eof $fd]} { set s [gets $fd] set s [string trim $s] lappend questions(qa) [split $s |] lappend questions(qpos) $n incr n } close $fd } namespace eval quiz { # A hack (reload the script in koi8-r encoding) if {![info exists questions(qa)]} { set file [file join [file dirname [info script]] quizdata.txt] if {[catch {load_file $file koi8-r}]} { puts "Can't load file $file" return } set fd [open [info script]] fconfigure $fd -encoding koi8-r uplevel 1 [read $fd] close $fd return } } proc quiz::get_question {} { variable questions if {![info exists questions(qa)]} return if {![llength $questions(qpos)]} { for {set i 0} "\$i < [llength $questions(qa)]" {incr i} { lappend questions(qpos) $i } } set idx [rand [llength $questions(qpos)]] set qidx [lindex $questions(qpos) $idx] set questions(qpos) [lreplace $questions(qpos) $idx $idx] return [lindex $questions(qa) $qidx] } proc quiz::commands_comps {chatid compsvar wordstart line} { upvar 0 $compsvar comps if {!$wordstart} { lappend comps "/quizstart " "/quizstop " "/quiznext " "/quiztop " } } hook::add generate_completions_hook \ [namespace current]::quiz::commands_comps proc quiz::handle_commands {chatid user body type} { variable game if {$type != "groupchat"} return if {[string index $body 0] != "/"} return set command [string trim $body] switch -- $command { /quizstart { start $chatid return stop } /quizstop { stop $chatid return stop } /quiznext { next $chatid return stop } /quiztop { top $chatid return stop } } return } hook::add chat_send_message_hook \ [namespace current]::quiz::handle_commands 50 proc quiz::handle_messages {chatid from type body x} { variable game variable question variable answer variable points variable asktime variable prefix set connid [chat::get_connid $chatid] set group [chat::get_jid $chatid] set s [string trim $body] switch -- $s { !topscores - !topscore { top $chatid return } } if {![info exists game($chatid)] || ![info exists answer($chatid)]} return switch -- $s { ! - !hint { after 5000 [list [namespace current]::hint $chatid] } default { if {[filter $body] == [filter $answer($chatid)]} { set time [expr [clock seconds] - $asktime($chatid)] if {[catch { chat::get_nick $connid $from $type } nick]} { set nick [chat::get_nick $from $type] } set msg_time "" variable last if {[info exists last(nick,$chatid)] && \ $last(nick,$chatid) == $nick} { incr last(num,$chatid) if {$last(num,$chatid) > 2} { set msg_cont "$nick \ $last(num,$chatid) [lindex {. } [numgrp \ $last(num,$chatid)]] !" } } else { set last(nick,$chatid) $nick set last(num,$chatid) 1 } variable stats if {![info exists stats(quick,$chatid/$nick)]} { set stats(quick,$chatid/$nick) $time } elseif {$stats(quick,$chatid/$nick) > $time} { set msg_time ", ," set stats(quick,$chatid/$nick) $time } if {![info exists stats(quick,$chatid)]} { set stats(quick,$chatid) $time } elseif {$stats(quick,$chatid) > $time} { set msg_time ", ," set stats(quick,$chatid) $time } message::send_msg $group -type groupchat \ -body "${prefix}, $nick! \ \"$answer($chatid)\" $time [lindex {. \ } [numgrp $time]]$msg_time\ Σ $points($chatid) [lindex {. } [numgrp \ $points($chatid)]]." \ -connection $connid if {[info exists msg_cont]} { message::send_msg $group -type groupchat \ -body $msg_cont \ -connection $connid } add_score $chatid $nick $points($chatid) $time catch { unset question($chatid) } variable lost set lost($chatid) 0 next $chatid } } } } hook::add draw_message_hook [namespace current]::quiz::handle_messages 79 proc quiz::start {chatid} { variable game variable prefix set connid [chat::get_connid $chatid] set group [chat::get_jid $chatid] if {![info exists game($chatid)]} { set game($chatid) "" message::send_msg $group -type groupchat \ -body "${prefix} ! ." \ -connection $connid variable lost set lost($chatid) 0 next $chatid } else { chat::add_message $chatid $group error " " {} } } proc quiz::stop {chatid} { variable game variable question variable prefix set connid [chat::get_connid $chatid] set group [chat::get_jid $chatid] if {[info exists game($chatid)]} { after cancel [list [namespace current]::ask $chatid] after cancel [list [namespace current]::next $chatid] after cancel [list [namespace current]::hint $chatid] after cancel [list [namespace current]::hint $chatid 1] catch { unset question($chatid) } catch { unset answer($chatid) } unset game($chatid) message::send_msg $group -type groupchat \ -body "${prefix} ." \ -connection $connid top $chatid } else { chat::add_message $chatid $group error " " {} } } proc quiz::next {chatid} { variable game variable question variable answer variable hint variable prefix set connid [chat::get_connid $chatid] set group [chat::get_jid $chatid] after cancel [list [namespace current]::ask $chatid] after cancel [list [namespace current]::next $chatid] after cancel [list [namespace current]::hint $chatid] after cancel [list [namespace current]::hint $chatid 1] if {[info exists game($chatid)]} { if {[info exists question($chatid)]} { variable lost incr lost($chatid) if {$lost($chatid) > 4} { message::send_msg $group -type groupchat \ -body "${prefix} \ -- :-/" \ -connection $connid stop $chatid return } variable last catch { unset last(nick,$chatid) } catch { unset last(num,$chatid) } message::send_msg $group -type groupchat \ -body "${prefix} , \ 5 . \"$answer($chatid)\"." \ -connection $connid } catch { unset question($chatid) } catch { unset answer($chatid) } catch { unset hint($chatid) } after 5000 [list [namespace current]::ask $chatid] } else { chat::add_message $chatid $group error " " {} } } proc quiz::ask {chatid} { variable game variable question variable answer variable points variable asktime variable prefix set connid [chat::get_connid $chatid] set group [chat::get_jid $chatid] after cancel [list [namespace current]::ask $chatid] after cancel [list [namespace current]::next $chatid] lassign [get_question] question($chatid) answer($chatid) set points($chatid) 3 set asktime($chatid) [clock seconds] message::send_msg $group -type groupchat \ -body "${prefix}$question($chatid)" \ -connection $connid after 60000 [list [namespace current]::next $chatid] } proc quiz::hint {chatid {cont 0}} { variable game variable answer variable hint variable points variable prefix set connid [chat::get_connid $chatid] set group [chat::get_jid $chatid] if {![info exists game($chatid)] || \ ![info exists answer($chatid)] || \ ([info exists hint($chatid)] && !$cont)} return set hint($chatid) "" if {![incr points($chatid) -1]} { next $chatid return } message::send_msg $group -type groupchat \ -body "${prefix}: [crange $answer($chatid) \ 0 [expr 3 - $points($chatid)]]...?" \ -connection $connid after 20000 [list [namespace current]::hint $chatid 1] } proc quiz::filter {text} { regsub -all {[;:()\[\]!?.,/\\{}]} [string tolower $text] "" text return [string trim $text] } proc quiz::numgrp {number} { switch -glob -- $number { *11 {return 3} *12 {return 3} *13 {return 3} *14 {return 3} *1 {return 1} *2 {return 2} *3 {return 2} *4 {return 2} default {return 3} } } proc quiz::top {chatid} { variable top variable prefix variable stats set connid [chat::get_connid $chatid] set group [chat::get_jid $chatid] if {[info exists top($chatid)]} { set t [lsort -integer -decreasing -index 1 $top($chatid)] set ts "" foreach item $t { lassign $item nick score set avgp [format "%.4f" \ [expr $score * 1.0 / $stats(answ,$chatid/$nick)]] set answ $stats(answ,$chatid/$nick) set quick $stats(quick,$chatid/$nick) set avgt [format "%.4f" [expr $stats(time,$chatid/$nick) * 1.0 / \ $stats(answ,$chatid/$nick)]] append ts "$score\t$avgp\t$answ\t$quick\t$avgt\t$nick\n" } message::send_msg $group -type groupchat \ -body "${prefix}Top scores: points\tavg p\tansw\tmin t\tavg t\tnick\n$ts" \ -connection $connid } else { chat::add_message $chatid $group error " top scores" {} } } proc quiz::add_score {chatid nick points time} { variable top if {![info exists top($chatid)]} { set top($chatid) {} } set t {} set b 1 foreach item $top($chatid) { lassign $item n s if {$n == $nick} { incr s $points set b 0 } lappend t [list $n $s] } if {$b} { lappend t [list $nick $points] } set top($chatid) $t variable stats if {![info exists stats(answ,$chatid/$nick)]} { set stats(answ,$chatid/$nick) 1 } else { incr stats(answ,$chatid/$nick) } if {![info exists stats(time,$chatid/$nick)]} { set stats(time,$chatid/$nick) $time } else { incr stats(time,$chatid/$nick) $time } } tkabber-plugins-0.11.1/COPYING0000644000175000017500000004311011014607213015226 0ustar sergeisergei GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. tkabber-plugins-0.11.1/browser/0000755000175000017500000000000011076120366015666 5ustar sergeisergeitkabber-plugins-0.11.1/browser/msgs/0000755000175000017500000000000011076120366016637 5ustar sergeisergeitkabber-plugins-0.11.1/browser/msgs/pl.msg0000644000175000017500000000204310667535014017766 0ustar sergeisergei# Polish messages file for browser plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies # browser.tcl ::msgcat::mcset pl "Add conference..." "Dodaj konferencję..." ::msgcat::mcset pl "Browse" "Przeglądaj" ::msgcat::mcset pl "Browse error: %s" "Błąd przeglądania: %s" ::msgcat::mcset pl "Browser" "Przeglądarka usług" ::msgcat::mcset pl "Description:" "Opis:" ::msgcat::mcset pl "Discover service" "Przeglądaj usługę" ::msgcat::mcset pl "JID:" "JID:" ::msgcat::mcset pl "Jabber Browser" "Przeglądarka usług" ::msgcat::mcset pl "Join group..." "Dołącz do konferencji..." ::msgcat::mcset pl "List of browsed JIDs." "Lista przeglądanych JabberID" ::msgcat::mcset pl "Number of children:" "Ilość elementów:" ::msgcat::mcset pl "Service Discovery" "Przeglądarka usług (protokół‚ Discovery)" ::msgcat::mcset pl "Sort items by JID" "Sortuj według JID" ::msgcat::mcset pl "Sort items by name" "Sortuj według nazwy" ::msgcat::mcset pl "Version:" "Wersja:" tkabber-plugins-0.11.1/browser/msgs/es.msg0000644000175000017500000000147211021551246017755 0ustar sergeisergei::msgcat::mcset es "Add conference..." "Añadir sala..." ::msgcat::mcset es "Browse error: %s" "Error navegando: %s" ::msgcat::mcset es "Browse" "Navegar" ::msgcat::mcset es "Browser" "Navegador" ::msgcat::mcset es "Description:" "Descripción:" ::msgcat::mcset es "Discover service" "Descubrir servicio" ::msgcat::mcset es "JID:" "JID:" ::msgcat::mcset es "Jabber Browser" "Navegador Jabber" ::msgcat::mcset es "Join group..." "Entrar en grupo..." ::msgcat::mcset es "List of browsed JIDs." "Lista de JIDs navegados." ::msgcat::mcset es "Number of children:" "Número de hijos:" ::msgcat::mcset es "Service Discovery" "Descubridor de servicios" ::msgcat::mcset es "Sort items by JID" "Ordenar elementos por JID" ::msgcat::mcset es "Sort items by name" "Ordenar elementos por nombre" ::msgcat::mcset es "Version:" "Versión:" tkabber-plugins-0.11.1/browser/msgs/de.msg0000644000175000017500000000203310666224632017742 0ustar sergeisergei# $Id: de.msg 1214 2007-09-01 08:58:02Z sergei $ # German messages file # Roger Sondermann 30.08.2007 ::msgcat::mcset de "Add conference..." "Konferenz hinzufgen..." ::msgcat::mcset de "Browse" "Durchsuchen" ::msgcat::mcset de "Browse error: %s" "Durchsuchen-Fehler: %s" ::msgcat::mcset de "Browser" "Jabber-Browser" ::msgcat::mcset de "Description:" "Beschreibung:" ::msgcat::mcset de "Discover service" "Service-Discovery" ::msgcat::mcset de "JID:" "JID:" ::msgcat::mcset de "Jabber Browser" "Jabber-Browser" ::msgcat::mcset de "Join group..." "Konferenz beitreten..." ::msgcat::mcset de "List of browsed JIDs." "Liste durchsuchter JIDs." ::msgcat::mcset de "Number of children:" "Anzahl Eintrge:" ::msgcat::mcset de "Service Discovery" "Service-Discovery" ::msgcat::mcset de "Sort items by JID" "Nach JID sortieren" ::msgcat::mcset de "Sort items by name" "Nach Namen sortieren" ::msgcat::mcset de "Version:" "Version:" tkabber-plugins-0.11.1/browser/msgs/ru.msg0000644000175000017500000000210110666224632017774 0ustar sergeisergei# $Id: ru.msg 1214 2007-09-01 08:58:02Z sergei $ ::msgcat::mcset ru "Add conference..." "Добавить конференцию..." ::msgcat::mcset ru "Browse" "Просмотреть" ::msgcat::mcset ru "Browse error: %s" "Ошибка просмотра: %s" ::msgcat::mcset ru "Browser" "Просмотр" ::msgcat::mcset ru "Description:" "Описание:" ::msgcat::mcset ru "Discover service" "Просмотреть возможности" ::msgcat::mcset ru "Jabber Browser" "Просмотр служб" ::msgcat::mcset ru "JID:" ::msgcat::mcset ru "Join group..." "Присоединиться к группе..." ::msgcat::mcset ru "List of browsed JIDs." "Список просмотренных JID." ::msgcat::mcset ru "Number of children:" "Число ветвей:" # Using translation from Tkabber itself #::msgcat::mcset ru "Service Discovery" "Обзор служб" ::msgcat::mcset ru "Sort items by JID" "Сортировать по JID" ::msgcat::mcset ru "Sort items by name" "Сортировать по имени" ::msgcat::mcset ru "Version:" "Версия:" tkabber-plugins-0.11.1/browser/browser.tcl0000644000175000017500000004356710747411465020103 0ustar sergeisergei# $Id: browser.tcl 1354 2008-01-28 17:39:01Z sergei $ # Jabber Browser (XEP-0011) implementation. This XEP is deprecated, # so its code is moved to a plugin. package require msgcat namespace eval browser { ::msgcat::mcload [file join [file dirname [info script]] msgs] set brwid 0 custom::defvar browse_list {} [::msgcat::mc "List of browsed JIDs."] \ -group Hidden } proc browser::open {args} { variable brwid variable browser variable config variable browse_list global brwserver$brwid if {[llength [jlib::connections]] == 0} return foreach {opt val} $args { switch -- $opt { -connection { set connid $val } } } if {![info exists connid]} { set connid [lindex [jlib::connections] 0] } set brwserver$brwid [jlib::connection_server $connid] set bw .brw$brwid set browser(connid,$bw) $connid add_win $bw -title [::msgcat::mc "Jabber Browser"] \ -tabtitle [::msgcat::mc "Browser"] \ -raisecmd [list focus $bw.tree] \ -class JDisco \ -raise 1 set config(fill) [option get $bw fill JDisco] set config(nscolor) [option get $bw featurecolor JDisco] bind $bw [list [namespace current]::destroy_state $bw] frame $bw.navigate button $bw.navigate.back -text <- \ -command [list [namespace current]::history_move $bw 1] button $bw.navigate.forward -text -> \ -command [list [namespace current]::history_move $bw -1] label $bw.navigate.lab -text [::msgcat::mc "JID:"] ComboBox $bw.navigate.entry -textvariable brwserver$brwid \ -dropenabled 1 -droptypes {JID {}} \ -dropcmd [list [namespace current]::entrydropcmd $bw] \ -command [list [namespace current]::go $bw] \ -values $browse_list button $bw.navigate.browse -text [::msgcat::mc "Browse"] \ -command [list [namespace current]::go $bw] #bind $bw.navigate.entry [list [namespace current]::go $bw] pack $bw.navigate.back $bw.navigate.forward $bw.navigate.lab -side left pack $bw.navigate.browse -side right pack $bw.navigate.entry -side left -expand yes -fill x pack $bw.navigate -fill x set sw [ScrolledWindow $bw.sw] set tw [Tree $bw.tree -deltax 16 -deltay 18 -dragenabled 1 \ -draginitcmd [list [namespace current]::draginitcmd $bw]] $sw setwidget $tw pack $sw -side top -expand yes -fill both set browser(tree,$bw) $tw $tw bindText [list [namespace current]::textaction $bw] $tw bindText [list [namespace current]::textpopup $bw] balloon::setup $tw -command [list [namespace current]::textballoon $bw] bindscroll $tw.c # HACK bind $tw.c \ "[namespace current]::textaction [list $bw] \[[list $tw] selection get\]" set browser(ypos,$bw) 1 set browser(width,$bw) 0 set browser(hist,$bw) {} set browser(histpos,$bw) 0 hook::run open_browser_post_hook $bw $sw $tw incr brwid go $bw } proc browser::enter {bw} { variable browser set jid [$bw.navigate.entry.e get] jlib::send_iq get \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:browse}] \ -to $jid -command [list [namespace current]::recv $bw $jid] \ -connection $browser(connid,$bw) } proc browser::go {bw} { variable browser variable browse_list if {[winfo exists $bw]} { set jid [$bw.navigate.entry.e get] history_add $bw $jid set browse_list [update_combo_list $browse_list $jid 20] $bw.navigate.entry configure -values $browse_list jlib::send_iq get \ [jlib::wrapper:createtag query \ -vars {xmlns jabber:iq:browse}] \ -to $jid -command [list [namespace current]::recv $bw $jid] \ -connection $browser(connid,$bw) } } proc browser::recv {bw jid res child} { variable config variable browser debugmsg browser "$res $child" if {[winfo exists $bw]} { if {![cequal $res OK]} { add_item_line $bw 0 $jid {} {} {} {} $jid set tw $browser(tree,$bw) foreach c [$tw nodes [jid_to_tag $jid]] { $tw delete $c } set tnode [jid_to_tag "error $jid"] set data [list error $jid] set parent_tag [jid_to_tag $jid] set desc [format [::msgcat::mc "Browse error: %s"] [error_to_string $child]] set icon "" add_line $tw $parent_tag $tnode $icon $desc $data \ -fill $config(fill) set browser(nchilds,$bw,$jid) 1 } else { process $bw $jid $child 0 } } } proc browser::process {bw from item level} { variable browser jlib::wrapper:splitxml $item tag vars isempty chdata children switch -- $tag { ns { debugmsg browser "$level; ns $chdata" if {![cequal $chdata ""]} { return [add_ns_line $bw $from $level $chdata] } return "" } query - item { set category [jlib::wrapper:getattr $vars category] } default { set category $tag } } set jid [jlib::wrapper:getattr $vars jid] if {[cequal $jid ""]} { set jid $from } set type [jlib::wrapper:getattr $vars type] set name [jlib::wrapper:getattr $vars name] set version [jlib::wrapper:getattr $vars version] debugmsg browser "$level; $jid; $category; $type; $name; $version" add_item_line $bw $level $jid $category $type $name $version $from set tw $browser(tree,$bw) set childs {} set nchilds 0 foreach child $children { lappend childs [process $bw $jid $child [expr {$level+1}]] incr nchilds } set browser(nchilds,$bw,$jid) $nchilds set node [jid_to_tag $jid] if {![info exists browser(sort,$bw,$node)]} { set browser(sort,$bw,$node) sort } set curchilds [$tw nodes $node] if {$level == 0} { foreach c $curchilds { if {![lcontain $childs $c]} { $tw delete $c } } browser_action $browser(sort,$bw,$node) $bw $node update idletasks } debugmsg browser [list $childs $curchilds] return $node } image create photo "" proc browser::item_icon {category type} { switch -- $category { service - gateway - application { if {[lsearch -exact [image names] browser/$type] >= 0} { return browser/$type } else { return "" } } default { if {[lsearch -exact [image names] browser/$category] >= 0} { return browser/$category } else { return "" } } } } proc browser::add_line {tw parent node icon desc data args} { if {[$tw exists $node]} { if {[$tw parent $node] != $parent && [$tw exists $parent] && \ $parent != $node} { if {[catch { $tw move $parent $node end }]} { debugmsg browser "MOVE FAILED: $parent $node" } else { debugmsg browser "MOVE: $parent $node" } } if {[$tw itemcget $node -data] != $data} { debugmsg browser RECONF $tw itemconfigure $node -text $desc -image $icon -data $data } } elseif {[$tw exists $parent]} { eval {$tw insert end $parent $node -text $desc -open 1 -image $icon \ -data $data} $args } else { eval {$tw insert end root $node -text $desc -open 1 -image $icon \ -data $data} $args } } proc browser::add_item_line {bw level jid category type name version parent} { variable browser variable config set icon [item_icon $category $type] set tw $browser(tree,$bw) set desc [item_desc $jid $name] set data [list jid $jid $category $type $name $version] set parent_tag [jid_to_tag $parent] set node [jid_to_tag $jid] add_line $tw $parent_tag $node $icon $desc $data \ -fill $config(fill) } proc browser::item_text {jid name} { if {![cequal $name ""]} { return $name } else { return $jid } } proc browser::item_desc {jid name} { if {![cequal $name ""]} { return "$name ($jid)" } else { return $jid } } proc browser::item_balloon_text {bw jid category type name version} { variable browser set text "$jid: " set delim "" if {![cequal $category {}] || ![cequal $type {}]} { append text "$delim$category/$type" set delim ", " } if {![cequal $name {}]} { append text "$delim[::msgcat::mc Description:] $name" set delim ", " } if {![cequal $version {}]} { append text "$delim[::msgcat::mc Version:] $version" } append text "\n[::msgcat::mc {Number of children:}] $browser(nchilds,$bw,$jid)" return $text } proc browser::add_ns_line {bw jid level ns} { variable browser variable config set tw $browser(tree,$bw) set node ${ns}\#[jid_to_tag $jid] set parent_tag [jid_to_tag $jid] lassign [$tw itemcget $parent_tag -data] ignore1 ignore2 category type set data [list ns $jid $ns $category $type] set desc $ns if {[info exists browser(ns_handler_desc,$ns)]} { array set tmp $browser(ns_handler_desc,$ns) if {[info exists tmp($category)]} { set desc "$tmp($category) ($ns)" } elseif {[info exists tmp(*)]} { set desc "$tmp(*) ($ns)" } } set icon "" add_line $tw $parent_tag $node $icon $desc $data -fill $config(nscolor) return $node } proc browser::history_move {bw shift} { variable browser set newpos [expr {$browser(histpos,$bw) + $shift}] if {$newpos < 0} { return } if {$newpos >= [llength $browser(hist,$bw)]} { return } set newjid [lindex $browser(hist,$bw) $newpos] set browser(histpos,$bw) $newpos $bw.navigate.entry.e delete 0 end $bw.navigate.entry.e insert 0 $newjid enter $bw } proc browser::history_add {bw jid} { variable browser set browser(hist,$bw) [lreplace $browser(hist,$bw) 0 \ [expr {$browser(histpos,$bw) - 1}]] lvarpush browser(hist,$bw) $jid set browser(histpos,$bw) 0 debugmsg browser $browser(hist,$bw) } proc browser::parse_items {from item} { variable browser debugmsg browser "BR: $item" jlib::wrapper:splitxml $item tag vars isempty chdata children switch -- $tag { ns { return } item { set category [jlib::wrapper:getattr $vars service] } default { set category $tag } } set jid [jlib::wrapper:getattr $vars jid] if {[cequal $jid ""]} { set jid $from } set type [jlib::wrapper:getattr $vars type] set name [jlib::wrapper:getattr $vars name] set version [jlib::wrapper:getattr $vars version] debugmsg browser "$jid; $category; $type; $name; $version" set browser(name,$jid) $name set browser(category,$jid) $category set browser(type,$jid) $type foreach child $children { parse_items $jid $child } } proc browser::goto {bw jid} { $bw.navigate.entry.e delete 0 end $bw.navigate.entry.e insert 0 $jid go $bw } proc browser::textaction {bw node} { variable browser set tw $browser(tree,$bw) set data [$tw itemcget $node -data] set data2 [lassign $data type] switch -- $type { jid { lassign $data2 jid goto $bw $jid } ns { lassign $data2 jid ns category subtype debugmsg browser "$jid $ns" if {[info exists browser(ns_handler,$ns)]} { if {$browser(ns_handler_node,$ns)} { eval $browser(ns_handler,$ns) [list $jid "" \ -category $category -type $subtype \ -connection $browser(connid,$bw)] } else { eval $browser(ns_handler,$ns) [list $jid \ -category $category -type $subtype \ -connection $browser(connid,$bw)] } } } } } if {[winfo exists [set m .b2popmenu]]} { destroy $m } menu $m -tearoff 0 $m add command -label [::msgcat::mc "Join group..."] -command { join_group_dialog -server [server_from_jid $::plugins::browser::headjid] \ -group [node_from_jid $::plugins::browser::headjid] \ -connection $::plugins::browser::browser(connid,$::plugins::browser::headwindow) } $m add command -label [::msgcat::mc "Add conference..."] -command { plugins::conferences::add_conference_dialog \ -group [node_from_jid $::plugins::browser::headjid] \ -server [server_from_jid $::plugins::browser::headjid] \ -connection $::plugins::browser::browser(connid,$::plugins::browser::headwindow) } $m add separator $m add command -label [::msgcat::mc "Browse"] \ -command {::plugins::browser::browser_action browse \ $::plugins::browser::headwindow $::plugins::browser::headnode} $m add command -label [::msgcat::mc "Sort items by name"] \ -command {::plugins::browser::browser_action sort \ $::plugins::browser::headwindow $::browser::headnode} $m add command -label [::msgcat::mc "Sort items by JID"] \ -command {::plugins::browser::browser_action sortjid \ $::plugins::browser::headwindow $::plugins::browser::headnode} if {[winfo exists [set m .b3popmenu]]} { destroy $m } menu $m -tearoff 0 $m add command -label [::msgcat::mc "Browse"] \ -command {::plugins::browser::browser_action browse \ $::plugins::browser::headwindow $::plugins::browser::headnode} $m add command -label [::msgcat::mc "Sort items by name"] \ -command {::plugins::browser::browser_action sort \ $::plugins::browser::headwindow $::plugins::browser::headnode} $m add command -label [::msgcat::mc "Sort items by JID"] \ -command {::plugins::browser::browser_action sortjid \ $::plugins::browser::headwindow $::plugins::browser::headnode} if {[winfo exists [set m .b4popmenu]]} { destroy $m } menu $m -tearoff 0 $m add command -label [::msgcat::mc "Browse"] \ -command {::plugins::browser::browser_action browse \ $::plugins::browser::headwindow $::plugins::browser::headnode} proc browser::textpopup {bw node} { variable browser variable headwindow $bw variable headnode $node variable headjid if {[catch { [set tw $browser(tree,$bw)] itemcget $node -data } data]} { return } set type [lindex $data 0] switch -- $type { jid { switch -- [lindex $data 2] { user { message::subject_menu [set bm .b1popmenu] $browser(connid,$bw) \ [lindex $data 1] message } conference { if {[string first @ [set headjid [lindex $data 1]]] > 0} { set bm .b2popmenu } else { set bm .b3popmenu } } service - default { set bm .b3popmenu } } } ns { set bm .b4popmenu } } tk_popup $bm [winfo pointerx .] [winfo pointery .] } proc browser::browser_action {action bw node} { variable browser if {[catch { [set tw $browser(tree,$bw)] itemcget $node -data } data]} { return } set type [lindex $data 0] switch -glob -- $type/$action { jid/browse - ns/browse { textaction $bw $node } jid/sort { set browser(sort,$bw,$node) sort set namespaces {} set children {} foreach child [$tw nodes $node] { set data [$tw itemcget $child -data] switch -- [lindex $data 0] { ns { lappend namespaces [list $child [lindex $data 4]] } default { lappend children [list $child [lindex $data 4]] } } } set neworder {} foreach child [concat $namespaces \ [lsort -dictionary -index 1 $children]] { lappend neworder [lindex $child 0] } $tw reorder $node $neworder foreach child [$tw nodes $node] { browser_action $action $bw $child } } jid/sortjid { set browser(sort,$bw,$node) sortjid set namespaces {} set children {} foreach child [$tw nodes $node] { set data [$tw itemcget $child -data] switch -- [lindex $data 0] { ns { lappend namespaces [list $child [lindex $data 1]] } default { lappend children [list $child [lindex $data 1]] } } } set neworder {} foreach child [concat $namespaces \ [lsort -dictionary -index 1 $children]] { lappend neworder [lindex $child 0] } $tw reorder $node $neworder foreach child [$tw nodes $node] { browser_action $action $bw $child } } default { } } } proc browser::textballoon {bw node} { variable browser set tw $browser(tree,$bw) set data [lassign [$tw itemcget $node -data] \ type jid category subtype name version] if {$type == "jid"} { return [list $bw:$node \ [item_balloon_text \ $bw $jid $category $subtype $name $version]] } else { return [list $bw:$node ""] } } proc browser::draginitcmd {bw t node top} { set connid browser(connid,$bw) set data [$t itemcget $node -data] set data2 [linsert [lassign $data type] 0 $connid] if {$type == "jid"} { if {[set img [$t itemcget $node -image]] != ""} { pack [label $top.l -image $img -padx 0 -pady 0] } return [list JID {copy} $data2] } else { return {} } } proc browser::entrydropcmd {bw target source pos op type data} { set jid [lindex $data 1] goto $bw $jid } proc browser::register_ns_handler {ns handler args} { variable browser set node 0 set desc "" foreach {attr val} $args { switch -- $attr { -node {set node $val} -desc {set desc $val} } } set browser(ns_handler,$ns) $handler set browser(ns_handler_node,$ns) $node if {$desc != ""} { set browser(ns_handler_desc,$ns) $desc } } hook::add browser_register_feature_handler_hook \ [namespace current]::browser::register_ns_handler # Destroy all (global) state assotiated with the given browser window. # Intended to be bound to a event handler for browser windows. proc browser::destroy_state {bw} { variable browser array unset browser *,$bw array unset browser *,$bw,* } # Register disco#info and disco#items in browser only. hook::add postload_hook \ [list [namespace current]::browser::register_ns_handler \ $::NS(disco_info) disco::browser::open_win \ -desc [list * [::msgcat::mc "Discover service"]]] hook::add postload_hook \ [list [namespace current]::browser::register_ns_handler \ $::NS(disco_items) disco::browser::open_win \ -desc [list * [::msgcat::mc "Discover service"]]] # Menu setup proc browser::setup_menu {} { catch { set m [.mainframe getmenu services] set idx [$m index [::msgcat::mc "Service Discovery"]] $m insert $idx command -label [::msgcat::mc "Jabber Browser"] \ -command [list [namespace current]::open] } } hook::add finload_hook [namespace current]::browser::setup_menu tkabber-plugins-0.11.1/presencecmd/0000755000175000017500000000000011076120366016473 5ustar sergeisergeitkabber-plugins-0.11.1/presencecmd/README0000644000175000017500000000750210661352400017352 0ustar sergeisergei"Presence command" chat plugin for Tkabber. $Id: README 1190 2007-08-17 17:04:00Z sergei $ I. The idea. This plugin provides additional set of what are called "IRC-style chat commands" in Tkabber -- specially formatted messages which are recognized as commands to Tkabber. They are parsed and executed, then their text is thrown away (widely known examples of standard chat commands are: /clear, /nick, /ban, /leave, etc). Provided commands are: * /presence allows to change "master" (i.e. basic, main, global) presence of the user [1]; * /chatpresence (or its alias /thispresence) allows to change the presence in this chat session (which may be a MUC room) only, in other words it sends what is called "directed presence" to the chat peer or room [2]. (See also "Notes" section below.) II. Usage. Both commands have identical syntax and they behave identically -- changes only the presence they operate on. The formal syntax is: /presence ?presence|clear[status]? ?status message? Fields surrounded by "?" represent optional parts, so does text in [...]. "|" specifies alteration (a set of mutually exclusive options). Note that while both presence and status message fields are marked optional at least one of them MUST appear. Otherwise the command has no sense and the usage info is shown in the chat log window. The presence field may have this (standard) values, literally: * available -- user is available; * avail -- shortcut for "available"; * away -- user is away; * xa -- user is extended away; * dnd -- user doesn't want to be disturbed; * chat -- user is free for chat. Note that there's currently no support for "unavailable" presence. The special value of the presence field is "clearstatus" ("clear" is a shortcut to it). When spceified, the status message is set to the empty string; the presence itself isn't changed. (See also section "Notes" below.) The status message field may be used to provide status message for the presence. Any text, on a new line after the command (and the presence value, if specified) is treated as the status message, so it can span multiple lines and have empty lines in between. The only transformation that is applied to the status message is removal of any leading and trailing whitespace. Any of this fields both) may be omitted. In this case the current value for the omitted field is kept intact. III. Examples: Set the "do not disturb" master presence: /presence dnd Set the "free to chat" presence with a fancy status message: /presence chat Hey girls! Just change the status message while keeping the presence intact: /presence To be, or not to be -- That is the question. Send directed presence to the chat peer (or to the room you're in): /chatpresence xa Gone shopping Just change the status message seen by the chat peer (or in the room): /thispresence Gone nuts emerging ebuilds IV. Notes. 1. You should understand that directed presence is somewhat odd in its behaviour to many (not to say most) users: any change in master presence invalidates any directed presences which were set before. In other words if you set, say, "dnd" presence in some MUC room and then change your master presence to "chat", this one will be broadcasted to that room also changing your presence there to "chat". 2. Oddly enough, but currently there's no easy way in Tkabber to sent *really* empty status message: if Tkabber is told to send one it replaces it with the "canonical" spelling of the presence being set in your locale. I.e. when you set the available presence with the empty status message and have an English locale, Tkabber will cook the "Available" status message for you. This is done so that presence stanzas can be PGP-signed, if PGP encryption is enabled. V. References: 1. http://www.xmpp.org/rfcs/rfc3921.html#presence 2. http://www.xmpp.org/rfcs/rfc3921.html#presence-resp-directed vim:et:ts=4:sw=4:tw=64 tkabber-plugins-0.11.1/presencecmd/msgs/0000755000175000017500000000000011076120366017444 5ustar sergeisergeitkabber-plugins-0.11.1/presencecmd/msgs/pl.msg0000644000175000017500000000250110714530322020560 0ustar sergeisergei# Polish messages file for presencecmd plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Unknown presence \"%s\". Must be avail\[able\], away, xa, dnd, chat or clear\[status\]" \ "Nieznany status \"%s\". Prawidłowe wartości to avail\[able\], away, xa, dnd, chat lub clear\[status\]" ::msgcat::mcset pl "Usage: \t/presence ?presence|clear\[status\]?\n\ \t?status message?\n\ or\n\ \t/chatpresence ?presence|clear\[status\]?\n\ \t?status message?\n\ Where presence is one of: avail\[able\], away, xa, dnd, chat.\n\ Special presence \"clear\[status\]\" just clears the current status.\n\ /thispresence is an alias for /chatpresence" \ "Użycie: \t/presence ?presence|clear\[status\]?\n\ \t?opis statusu?\n\ lub\n \t/chatpresence ?presence|clear\[status\]?\n\ \t?opis statusu?\n\ gdzie presence jest jednym z: avail\[able\], away, xa, dnd, chat.\n\ Status specjalny \"clear\[status\]\" tylko czyści aktualny status.\n\ /thispresence jest aliasem dla /chatpresence" tkabber-plugins-0.11.1/presencecmd/msgs/es.msg0000644000175000017500000000156510712161173020567 0ustar sergeisergei::msgcat::mcset es "Unknown presence \"%s\". Must be avail\[able\], away, xa, dnd, chat or clear\[status\]" "Presencia desconocida \"%s\". Debe ser: avail\[able\], away, xa, dnd, chat o clear\[status\]" ::msgcat::mcset es "Usage: \t/presence ?presence|clear\[status\]?\n \t?status message?\n or\n \t/chatpresence ?presence|clear\[status\]?\n \t?status message?\n Where presence is one of: avail\[able\], away, xa, dnd, chat.\n Special presence \"clear\[status\]\" just clears the current status.\n /thispresence is an alias for /chatpresence" "Modo de uso: \t/presence ?presence|clear\[status\]?\n \t?status message?\n or\n \t/chatpresence ?presence|clear\[status\]?\n \t?status message?\n Donde presence es uno de estos: avail\[able\], away, xa, dnd, chat.\n La presencia especial \"clear\[status\]\" simplemente limpia el estado actual.\n /thispresence es un alias de /chatpresence" tkabber-plugins-0.11.1/presencecmd/msgs/de.msg0000644000175000017500000000171510671275723020560 0ustar sergeisergei # German messages file # Roger Sondermann 09.09.2007 ::msgcat::mcset de "Unknown presence \"%s\". Must be avail\[able\], away, xa, dnd, chat or clear\[status\]" "Unbekannte Prsenz \"%s\". Erlaubt sind avail\[able\], away, xa, dnd, chat oder clear\[status\]." ::msgcat::mcset de "Usage: \t/presence ?presence|clear\[status\]?\n \t?status message?\n or\n \t/chatpresence ?presence|clear\[status\]?\n \t?status message?\n Where presence is one of: avail\[able\], away, xa, dnd, chat.\n Special presence \"clear\[status\]\" just clears the current status.\n /thispresence is an alias for /chatpresence" "Benutzung:\t/presence ?presence|clear\[status\]?\n \t\t?Status-Nachricht?\n oder:\n \t\t/chatpresence ?presence|clear\[status\]?\n \t\t?Status-Nachricht?\n\n Wobei 'presence' eines der folgenden ist: avail\[able\], away, xa, dnd, chat.\n Die spezielle Prsenz 'clear\[status\]' setzt den derzeitigen Status zurck.\n ('/thispresence' ist ein Alias fr '/chatpresence')" tkabber-plugins-0.11.1/presencecmd/msgs/ru.msg0000644000175000017500000000225610667535014020614 0ustar sergeisergei# $Id: ru.msg 1224 2007-09-05 14:15:40Z sergei $ ::msgcat::mcset ru "Unknown presence \"%s\". Must be avail\[able\], away, xa, dnd, chat or clear\[status\]" \ "Неизвестное присутствие \"%s\". Должно быть avail\[able\], away, xa, dnd, chat или clear\[status\]" ::msgcat::mcset ru "Usage: \t/presence ?presence|clear\[status\]?\n\ \t?status message?\n\ or\n\ \t/chatpresence ?presence|clear\[status\]?\n\ \t?status message?\n\ Where presence is one of: avail\[able\], away, xa, dnd, chat.\n\ Special presence \"clear\[status\]\" just clears the current status.\n\ /thispresence is an alias for /chatpresence" \ "Синтаксис: \t/presence ?presence|clear\[status\]?\n\ \t?статусное сообщение?\n\ или\n\ \t/chatpresence ?presence|clear\[status\]?\n\ \t?статусное сообщение?\n\ Где presence - одно из: avail\[able\], away, xa, dnd, chat.\n\ Особое присутствие \"clear\[status\]\" очищает статусное сообщение.\n\ /thispresence является синонимом /chatpresence" tkabber-plugins-0.11.1/presencecmd/presencecmd.tcl0000644000175000017500000000662510667535014021505 0ustar sergeisergei# $Id: presencecmd.tcl 1224 2007-09-05 14:15:40Z sergei $ # "Presence commands" -- Tkabber chat plugin. # Provides two IRC-style chat commands that provide # for manipulating user's presence and/or assotiated status message # as well as sending directed presence to the chat peer (or room). # Written by Konstantin Khomoutov # See license.terms for details on distribution. # See INSTALL and README for details on installation and usage. package require msgcat namespace eval presencecmd { ::msgcat::mcload [file join [file dirname [info script]] msgs] hook::add generate_completions_hook [namespace current]::command_comps hook::add chat_send_message_hook [namespace current]::handle_command 15 } proc presencecmd::command_comps {chatid compsvar wordstart line} { upvar 0 $compsvar comps if {!$wordstart} { lappend comps {/presence } {/chatpresence } {/thispresence } } } proc presencecmd::handle_command {chatid user body type} { global userstatus if {[string match {/presence*} $body]} { set cmd /presence } elseif {[string match {/chatpresence*} $body]} { set cmd /chatpresence } elseif {[string match {/thispresence*} $body]} { set cmd /thispresence } else return set fields [split $body \n] set pres [string trim [string range [lindex $fields 0] [string length $cmd] end]] set status [string trim [join [lrange $fields 1 end] \n]] set sendstatus [expr {$status != ""}] if {$pres == "" && !$sendstatus} { show_usage $chatid return stop } if {$pres != ""} { switch -- $pres { avail { set pres available } available - away - xa - dnd - chat { } clear - clearstatus { set sendstatus true set pres $userstatus set status "" } default { show error $chatid [::msgcat::mc "Unknown presence \"%s\".\ Must be avail\[able\], away, xa, dnd, chat or clear\[status\]" $pres] return stop } } } else { set pres $userstatus } switch -- $cmd { /presence { set_master_presence $pres $status $sendstatus } /chatpresence - /thispresence { send_directed_presence $chatid $pres $status $sendstatus } } return stop } proc presencecmd::set_master_presence {pres status sendstatus} { global userstatus textstatus if {$sendstatus} { set textstatus $status } # the following assignment triggers sending the presence set userstatus $pres } proc presencecmd::send_directed_presence {chatid pres status sendstatus} { global userpriority set cmd [list send_presence $pres \ -to [chat::get_jid $chatid] \ -pri $userpriority \ -connection [chat::get_connid $chatid]] if {$sendstatus} { lappend cmd -stat $status } eval $cmd } proc presencecmd::show_usage chatid { show error $chatid [::msgcat::mc "Usage:\ \t/presence ?presence|clear\[status\]?\n\ \t?status message?\n\ or\n\ \t/chatpresence ?presence|clear\[status\]?\n\ \t?status message?\n\ Where presence is one of: avail\[able\], away, xa, dnd, chat.\n\ Special presence \"clear\[status\]\" just clears the current status.\n\ /thispresence is an alias for /chatpresence"] } # $type should be either "info" or "error" proc presencecmd::show {type chatid msg} { set jid [chat::get_jid $chatid] set cw [chat::chat_win $chatid] chat::add_message $chatid $jid $type $msg {} } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/presencecmd/TODO0000644000175000017500000000020510661352400017153 0ustar sergeisergei$Id: TODO 1190 2007-08-17 17:04:00Z sergei $ HIGH: LOW: * Write provide ChangeLog and VERSION files. * Russian message catalog. tkabber-plugins-0.11.1/presencecmd/license.terms0000644000175000017500000000211210661352400021160 0ustar sergeisergeiCopyright (c) 2007 Konstantin Khomoutov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/presencecmd/INSTALL0000644000175000017500000000050510661352400017517 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/presencecmd/ ~/.tkabber/plugins/presencecmdv/presencecmd.tcl Restart Tkabber, to get the plugin loaded. Consult the README file for the details about using this plugin. tkabber-plugins-0.11.1/presencecmd/AUTHORS0000644000175000017500000000006610661352400017540 0ustar sergeisergeiKonstantin Khomoutov tkabber-plugins-0.11.1/presencecmd/VERSION0000644000175000017500000000002210661352400017530 0ustar sergeisergei0.2, 14-July-2007 tkabber-plugins-0.11.1/renju/0000755000175000017500000000000011076120366015326 5ustar sergeisergeitkabber-plugins-0.11.1/renju/msgs/0000755000175000017500000000000011076120366016277 5ustar sergeisergeitkabber-plugins-0.11.1/renju/msgs/es.msg0000644000175000017500000000772411021551246017423 0ustar sergeisergei::msgcat::mcset es " (Opponent)" " (Oponente)" ::msgcat::mcset es " (You)" " (Tu)" ::msgcat::mcset es "%s (%s) has refused Gomoku/Renju invitation: %s" "%s (%s) ha rechazado la invitación a Gomoku/Renju: %s" ::msgcat::mcset es "%s wants play %s." "%s quiere jugar a %s." ::msgcat::mcset es "%s wants to move first." "%s quiere mover primero." ::msgcat::mcset es "%s wants to move second." "%s quiere que muevas primero." ::msgcat::mcset es "%s with %s" "%s con %s" ::msgcat::mcset es "Accept opponent illegal moves (useful for debugging)." "Aceptar movimientos ilegales del oponente (útil para depuración)." ::msgcat::mcset es "Accept the draw proposal" "Aceptar la propuesta de empate" ::msgcat::mcset es "Agree to play" "Aceptar a jugar" ::msgcat::mcset es "Allow illegal moves (useful for debugging)." "Permitir movimientos ilegales (últil para depuración)." ::msgcat::mcset es "Black" "Negras" ::msgcat::mcset es "Cancel invitation" "Cancelar invitación" ::msgcat::mcset es "Default game variant." "Variante de juego por defecto." ::msgcat::mcset es "Draw (Both players skipped move)" "Empate (ambos jugadores pasaron turno)" ::msgcat::mcset es "Draw (Opponent accepted)" "Empate (el oponente aceptó)" ::msgcat::mcset es "Draw (You accepted)" "Empate (aceptaste)" ::msgcat::mcset es "Draw" "Empate" ::msgcat::mcset es "Free-style Gomoku" "Gomoku de estilo libre" ::msgcat::mcset es "Games" "Juegos" ::msgcat::mcset es "Gomoku/Renju Invitation from %s" "Invitación a Gomoku/Renju de %s" ::msgcat::mcset es "Gomoku/Renju Invitation" "Invitación a Gomoku/Renju" ::msgcat::mcset es "Gomoku/Renju figures theme." "Tipo de fichas de Gomoku/Renju." ::msgcat::mcset es "Gomoku/Renju game invitation from %s (%s) is received." "Se ha recibido invitación a Gomoku/Renju de %s (%s)." ::msgcat::mcset es "Gomoku/Renju plugin options." "Opciones de plugin de Gomoku/Renju." ::msgcat::mcset es "Gomoku/Renju..." "Gomoku/Renju..." ::msgcat::mcset es "History" "Historial" ::msgcat::mcset es "I want to move first" "Quiero mover primero" ::msgcat::mcset es "I want to move second" "Quiero que el oponente mueva primero" ::msgcat::mcset es "Move: " "Mover: " ::msgcat::mcset es "Opponent wins (You resigned)" "El oponente gana (te has rendido)" ::msgcat::mcset es "Opponent wins" "El oponente gana" ::msgcat::mcset es "Plugins options." "Opciones de plugin." ::msgcat::mcset es "Press button and make move if you want propose draw" "Pulsa el botón y haz un movimiento para proponer un empate" ::msgcat::mcset es "Press button if you want accept the draw proposal" "Pulsa el botón para aceptar la propuesta de empate" ::msgcat::mcset es "Press button if you want resign" "Pulsa el botón para rendirte" ::msgcat::mcset es "Press button if you want skip current move" "Pulsa el botón si quieres pasar el turno" ::msgcat::mcset es "Propose a draw" "Proponer un empate" ::msgcat::mcset es "Refuse to play" "Rechazar la partida" ::msgcat::mcset es "Renju" "Renju" ::msgcat::mcset es "Resign the game" "Rendirte" ::msgcat::mcset es "Sending Gomoku/Renju game invitation to %s (%s)" "Enviando invitación de Gomoku/Renju a %s (%s)" ::msgcat::mcset es "Show last move by default." "Mostrar por defecto el último movimiento." ::msgcat::mcset es "Show last move" "Mostrar el último movimiento" ::msgcat::mcset es "Show tooltips with short instructions." "Mostrar ventanitas con pequeñas instrucciones." ::msgcat::mcset es "Skip the move" "Saltar el movimiento" ::msgcat::mcset es "Sound to play after opponent's turn" "Sonido a reproducir cuando el oponente mueva pieza" ::msgcat::mcset es "Standard Gomoku" "Gomoku convencional" ::msgcat::mcset es "Tournament Gomoku" "Gomoku de torneo" ::msgcat::mcset es "White" "Blancas" ::msgcat::mcset es "You win (Opponent resigned)" "Has ganado (el oponente se rinde)" ::msgcat::mcset es "You win" "Has ganado" ::msgcat::mcset es "\n\n Opponent proposes a draw\n\n" "\n\n El oponente propone un empate\n\n" ::msgcat::mcset es "\n\n Opponent rejected move:\n %s\n\n" "\n\n El oponente rechazó el movimiento:\n %s\n\n" tkabber-plugins-0.11.1/renju/msgs/ru.msg0000644000175000017500000001207310573755632017453 0ustar sergeisergei ::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Show last move by default." "По умолчанию показывать последний ход." ::msgcat::mcset ru " (You)" " (Вы)" ::msgcat::mcset ru " (Opponent)" " (Оппонент)" ::msgcat::mcset ru "Gomoku/Renju plugin options." "Параметры расширения Гомоку/Рэндзю." ::msgcat::mcset ru "Gomoku/Renju figures theme." "Тема фишек Гомоку/Рэндзю." ::msgcat::mcset ru "Free-style Gomoku" "Свободное Гомоку" ::msgcat::mcset ru "Standard Gomoku" "Стандартное Гомоку" ::msgcat::mcset ru "Tournament Gomoku" "Турнирное Гомоку" ::msgcat::mcset ru "Renju" "Рэндзю" ::msgcat::mcset ru "Show tooltips with short instructions." "Показывать всплывающие подсказки к элементам интерфейса." ::msgcat::mcset ru "Allow illegal moves (useful for debugging)." "Разрешать неправильные ходы (используется при отладке)." ::msgcat::mcset ru "Accept opponent illegal moves (useful for debugging)." "Принимать неправильные ходы от оппонента (используется при отладке)." ::msgcat::mcset ru "Default game variant." "Вариант игры по умолчанию." ::msgcat::mcset ru "Gomoku/Renju Invitation" "Приглашение сыграть в Гомоку/Рэндзю" ::msgcat::mcset ru "Sending Gomoku/Renju game invitation to %s (%s)" "Посылаем приглашение сыграть в Гомоку/Рэндзю с %s (%s)" ::msgcat::mcset ru "I want to move first" "Хочу ходить первым" ::msgcat::mcset ru "I want to move second" "Хочу ходить вторым" ::msgcat::mcset ru "Cancel invitation" "Отменить приглашение" ::msgcat::mcset ru "%s (%s) has refused Gomoku/Renju invitation: %s" "%s (%s) отказался играть в Гомоку/Рэндзю: %s" ::msgcat::mcset ru "Gomoku/Renju Invitation from %s" "Приглашение сыграть в Гомоку/Рэндзю с %s" ::msgcat::mcset ru "Gomoku/Renju game invitation from %s (%s) is received." "Получено приглашение сыграть в Гомоку/Рэндзю с %s (%s)" ::msgcat::mcset ru "%s wants play %s." "%s хочет играть в %s" ::msgcat::mcset ru "%s wants to move first." "%s хочет ходить первым." ::msgcat::mcset ru "%s wants to move second." "%s хочет ходить вторым." ::msgcat::mcset ru "Agree to play" "Согласиться играть" ::msgcat::mcset ru "Refuse to play" "Отказаться играть" ::msgcat::mcset ru "%s with %s" "%s с %s" ::msgcat::mcset ru "Show last move" "Показывать последний ход" ::msgcat::mcset ru "Move: " "Ход: " ::msgcat::mcset ru "Propose a draw" "Предложить ничью" ::msgcat::mcset ru "Accept the draw proposal" "Принять предложенную ничью" ::msgcat::mcset ru "Resign the game" "Сдать партию" ::msgcat::mcset ru "History" "Запись партии" ::msgcat::mcset ru "Gomoku/Renju..." "Гомоку/Рэндзю..." ::msgcat::mcset ru "White" "Белые" ::msgcat::mcset ru "Black" "Чёрные" ::msgcat::mcset ru "Opponent wins" "Оппонент выиграл" ::msgcat::mcset ru "You win" "Вы выиграли" ::msgcat::mcset ru "Opponent wins (You resigned)" "Оппонент выиграл (Вы сдались)" ::msgcat::mcset ru "You win (Opponent resigned)" "Вы выиграли (Оппонент сдался)" ::msgcat::mcset ru "Draw" "Ничья" ::msgcat::mcset ru "Draw (Both players skipped move)" "Ничья (Оба игрока пропустили ход)" ::msgcat::mcset ru "Draw (You accepted)" "Ничья (Вы приняли)" ::msgcat::mcset ru "Draw (Opponent accepted)" "Ничья (Оппонент принял)" ::msgcat::mcset ru "Press button and make move if you want propose draw" "Нажмите кнопку и сделайте ход, если хотите предложить ничью" ::msgcat::mcset ru "Press button if you want accept the draw proposal" "Нажмите кнопку, если хотите принять предложенную ничью" ::msgcat::mcset ru "Press button if you want resign" "Нажмите кнопку, если хотите сдаться" ::msgcat::mcset ru "Press button if you want skip current move" "Нажмите кнопку, если хотите пропустить ход" ::msgcat::mcset ru "Skip the move" "Пропустить ход" ::msgcat::mcset ru "\n\n Opponent proposes a draw\n\n" "\n\n Оппонент предлагает ничью\n\n" ::msgcat::mcset ru "\n\n Opponent rejected move:\n %s\n\n" "\n\n Оппонент отверг ход:\n %s\n\n" ::msgcat::mcset ru "Games" "Игры" ::msgcat::mcset ru "Sound to play after opponent's turn" "Звук, который проигрывается после хода оппонента" # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/renju/renju.tcl0000644000175000017500000011320611047022175017155 0ustar sergeisergei# $Id: renju.tcl 1481 2008-08-08 10:48:29Z sergei $ package require msgcat namespace eval renju { variable scriptdir [file dirname [info script]] ::msgcat::mcload [file join $scriptdir msgs] variable square_size 31 variable line_width 1 variable themes set dirs [glob -nocomplain -directory [file join $scriptdir pixmaps] *] foreach dir $dirs { pixmaps::load_theme_name [namespace current]::themes $dir } set values {} foreach theme [lsort [array names themes]] { lappend values $theme $theme } set game_names_list \ [list \ renju [::msgcat::mc "Renju"] \ gomoku:freestyle [::msgcat::mc "Free-style Gomoku"] \ gomoku:standard [::msgcat::mc "Standard Gomoku"] \ gomoku:tournament [::msgcat::mc "Tournament Gomoku"] \ ] array set game_names $game_names_list custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup Gomoku/Renju [::msgcat::mc "Gomoku/Renju plugin options."] -group Plugins custom::defvar options(theme) Stones \ [::msgcat::mc "Gomoku/Renju figures theme."] -group Gomoku/Renju \ -type options -values $values \ -command [namespace current]::load_stored_theme custom::defvar options(game) renju \ [::msgcat::mc "Default game variant."] -group Gomoku/Renju \ -type options \ -values $game_names_list custom::defvar options(show_last_move) 0 \ [::msgcat::mc "Show last move by default."] \ -type boolean -group Gomoku/Renju custom::defvar options(show_tooltips) 1 \ [::msgcat::mc "Show tooltips with short instructions."] \ -type boolean -group Gomoku/Renju \ -command [list [namespace current]::set_tooltips] custom::defvar options(sound) "" \ [::msgcat::mc "Sound to play after opponent's turn"] \ -type file -group Gomoku/Renju custom::defvar options(allow_illegal) 0 \ [::msgcat::mc "Allow illegal moves (useful for debugging)."] \ -type boolean -group Gomoku/Renju custom::defvar options(accept_illegal) 0 \ [::msgcat::mc "Accept opponent illegal moves (useful for debugging)."] \ -type boolean -group Gomoku/Renju } proc renju::load_stored_theme {args} { variable options variable themes pixmaps::load_dir $themes($options(theme)) } hook::add postload_hook [namespace current]::renju::load_stored_theme 70 proc renju::get_nick {connid jid type} { if {[catch {chat::get_nick $connid $jid $type} nick]} { return [chat::get_nick $jid $type] } else { return $nick } } proc renju::invite_dialog {connid jid} { variable options set w .renju_invite if {[winfo exists $w]} { destroy $w } Dialog $w -title [::msgcat::mc "Gomoku/Renju Invitation"] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] message $wf.message -aspect 50000 \ -text [format [::msgcat::mc "Sending Gomoku/Renju game invitation to %s (%s)"] \ [get_nick $connid $jid chat] \ $jid] pack $wf.message -pady 2m variable game $options(game) radiobutton $wf.renju -text [::msgcat::mc "Renju"] \ -value renju -variable [namespace current]::game pack $wf.renju -padx 15m -anchor w radiobutton $wf.freestyle -text [::msgcat::mc "Free-style Gomoku"] \ -value gomoku:freestyle -variable [namespace current]::game pack $wf.freestyle -padx 15m -anchor w radiobutton $wf.standard -text [::msgcat::mc "Standard Gomoku"] \ -value gomoku:standard -variable [namespace current]::game pack $wf.standard -padx 15m -anchor w radiobutton $wf.tournament -text [::msgcat::mc "Tournament Gomoku"] \ -value gomoku:tournament -variable [namespace current]::game pack $wf.tournament -padx 15m -anchor w $w add -text [::msgcat::mc "I want to move first"] \ -command [list [namespace current]::invite $connid $jid black] $w add -text [::msgcat::mc "I want to move second"] \ -command [list [namespace current]::invite $connid $jid white] $w add -text [::msgcat::mc "Cancel invitation"] \ -command [list destroy $w] $w draw } proc renju::invite {connid jid color} { variable game destroy .renju_invite set id renju[rand 1000000000] # FIX #set rjid [get_jid_of_user $jid] jlib::send_iq set \ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type $game id $id color $color]] \ -to $jid \ -command [list [namespace current]::invite_res $game $connid $jid $id $color] \ -connection $connid } proc renju::invite_res {game connid jid id color res child} { if {![cequal $res OK]} { after idle [list NonmodalMessageDlg .renju_invite_error -aspect 50000 -icon error \ -message [format [::msgcat::mc "%s (%s) has refused Gomoku/Renju invitation: %s"] \ [get_nick $connid $jid chat] \ $jid [error_to_string $child]]] return "" } start_play $game $connid $jid $id $color } proc renju::invited_dialog {game connid jid id color} { variable invited_result variable game_names set w .renju_invited if {[winfo exists $w]} { destroy $w } Dialog $w -title [format [::msgcat::mc "Gomoku/Renju Invitation from %s"] $jid] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] bind $wf [list [namespace current]::set_invited_res ""] set nick [get_nick $connid $jid chat] set message1 [format [::msgcat::mc "Gomoku/Renju game invitation from %s (%s) is received."] \ $nick $jid] set message2 [format [::msgcat::mc "%s wants play %s."] $nick $game_names($game)] switch -- $color { white { set message3 [format [::msgcat::mc "%s wants to move second."] $nick] } black { set message3 [format [::msgcat::mc "%s wants to move first."] $nick] } default { return [list error modify bad-request] } } message $wf.message1 -aspect 50000 -text $message1 message $wf.message2 -aspect 50000 -text $message2 message $wf.message3 -aspect 50000 -text $message3 pack $wf.message1 -pady 1m pack $wf.message2 -pady 1m pack $wf.message3 -pady 1m $w add -text [::msgcat::mc "Agree to play"] \ -command [list [namespace current]::set_invited_res 0] $w add -text [::msgcat::mc "Refuse to play"] \ -command [list [namespace current]::set_invited_res 1] $w draw vwait [namespace current]::invited_result catch { bind $wf {} destroy $w } if {$invited_result == 0} { switch -- $color { white { start_play $game $connid $jid $id black } black { start_play $game $connid $jid $id white } default { return [list error modify bad-request] } } return [list result\ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type $game id $id]]] } else { return [list error modify not-acceptable] } } proc renju::set_invited_res {res} { variable invited_result set invited_result $res } proc renju::start_play {game connid jid id color} { set gid [make_gid $jid $id] variable $gid upvar 0 $gid flags set flags(window) [win_id renju $gid] set flags(connid) $connid set flags(opponent) $jid set flags(id) $id set flags(game) $game set flags(our_color) $color trace variable [namespace current]::${gid}(position,turn) w \ [list [namespace current]::set_label_move $gid] make_default_position $gid open $gid } proc renju::set_label_move {gid args} { variable $gid upvar 0 $gid flags switch -- $flags(position,turn) { white { set flags(move_label) [::msgcat::mc "White"] set move 1 } black { set flags(move_label) [::msgcat::mc "Black"] set move 1 } default { set move 0 } } if {$move && [is_my_move $gid]} { append flags(move_label) [::msgcat::mc " (You)"] } else { append flags(move_label) [::msgcat::mc " (Opponent)"] } } proc renju::make_default_position {gid} { variable $gid upvar 0 $gid flags for {set c 0} {$c < 15} {incr c} { for {set r 0} {$r < 15} {incr r} { set flags(position,$c,$r) "" } } set flags(position,turn) black catch {unset flags(position,last_move)} set flags(position,draw) 0 set flags(position,halfmove) 0 set flags(position,history) {} } proc renju::save_position {gid} { variable $gid upvar 0 $gid flags set flags(saved_position) [array get flags position,*] } proc renju::restore_position {gid} { variable $gid upvar 0 $gid flags array set flags $flags(saved_position) draw_position $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc renju::make_gid {jid id} { jid_to_tag [concat $jid $id] } proc renju::turn_recv {gid children} { variable options variable $gid upvar 0 $gid flags set move 0 set skip 0 set draw 0 foreach child $children { jlib::wrapper:splitxml $child tag vars isempty chdata children1 switch -- $tag { put { set pos [jlib::wrapper:getattr $vars pos] set poss [split $pos ","] if {[llength $poss] == 2} { set ct [lindex $poss 0] set rt [lindex $poss 1] set move 1 if {$options(sound) != "" && ![::sound::is_mute]} { ::sound::play $options(sound) } } } skip { set skip 1 add_move_to_history $gid if {[is_white $flags(position,turn)]} { set flags(position,turn) black } else { set flags(position,turn) white } find_legal_moves $gid $flags(position,turn) } resign { end_game $gid 1 [::msgcat::mc "You win (Opponent resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type $flags(game) \ id $flags(id)]]] } accept { if {$flags(position,draw)} { end_game $gid 0.5 [::msgcat::mc "Draw (Opponent accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type $flags(game) \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } draw { set draw 1 } } } if {$skip || ($move && [do_move $gid $ct $rt $draw])} { if {[lindex $flags(position,history) end] == "skip" && \ [lindex $flags(position,history) end-1] == "skip"} { end_game $gid 0.5 [::msgcat::mc "Draw (Both players skipped move)"] } update_controls $gid $draw draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type $flags(game) \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } ############################################################################### proc renju::calc_moves {} { variable moves for {set c 0} {$c < 15} {incr c} { for {set r 0} {$r < 15} {incr r} { for {set moves(d1,$c,$r) {}; set x [expr {$c+1}]; set y [expr {$r+1}]} \ {($x < 15) && ($y < 15)} {incr x; incr y} { lappend moves(d1,$c,$r) $x $y } for {set moves(d2,$c,$r) {}; set x [expr {$c-1}]; set y [expr {$r+1}]} \ {($x >= 0) && ($y < 15)} {incr x -1; incr y} { lappend moves(d2,$c,$r) $x $y } for {set moves(d3,$c,$r) {}; set x [expr {$c-1}]; set y [expr {$r-1}]} \ {($x >= 0) && ($y >= 0)} {incr x -1; incr y -1} { lappend moves(d3,$c,$r) $x $y } for {set moves(d4,$c,$r) {}; set x [expr {$c+1}]; set y [expr {$r-1}]} \ {($x < 15) && ($y >= 0)} {incr x; incr y -1} { lappend moves(d4,$c,$r) $x $y } for {set moves(h1,$c,$r) {}; set x [expr {$c+1}]} {$x < 15} {incr x} { lappend moves(h1,$c,$r) $x $r } for {set moves(h2,$c,$r) {}; set x [expr {$c-1}]} {$x >= 0} {incr x -1} { lappend moves(h2,$c,$r) $x $r } for {set moves(v1,$c,$r) {}; set y [expr {$r+1}]} {$y < 15} {incr y} { lappend moves(v1,$c,$r) $c $y } for {set moves(v2,$c,$r) {}; set y [expr {$r-1}]} {$y >= 0} {incr y -1} { lappend moves(v2,$c,$r) $c $y } } } } hook::add finload_hook [namespace current]::renju::calc_moves 100 proc renju::center {c r} { variable square_size variable line_width set r [expr {14 - $r}] list [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $c)}] \ [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $r)}] } proc renju::close {gid} { variable $gid upvar 0 $gid flags array unset flags } proc renju::exists {gid} { variable $gid info exists $gid } proc renju::open {gid} { variable options variable game_names variable square_size variable line_width variable $gid upvar 0 $gid flags set jid $flags(opponent) set w $flags(window) if {[winfo exists $w]} { raise_win $w return } set title [::msgcat::mc "%s with %s" $game_names($flags(game)) \ [get_nick $flags(connid) $jid chat]] add_win $w -title $title \ -tabtitle $title \ -class renju \ -raise 1 set board [canvas $w.board \ -width [expr {($square_size + $line_width) * 15}] \ -height [expr {($square_size + $line_width) * 15}]] pack $board -side left -anchor w -padx 10 set flags(board) $board set flags(show_last_move) $options(show_last_move) set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] set slm [Button $w.show_last_move -text [::msgcat::mc "Show last move"] \ -relief $relief \ -command [list [namespace current]::toggle_show_last_move $gid]] pack $slm -side top -anchor w -fill x set flags(show_last_move_button) $slm frame $w.move pack $w.move -side top -anchor w label $w.move.title -text [::msgcat::mc "Move: "] pack $w.move.title -side left label $w.move.on_move -anchor w \ -textvariable [namespace current]::${gid}(move_label) pack $w.move.on_move -side left -anchor w set bbox [ButtonBox $w.bbox -orient vertical -spacing 0] $bbox add -text [::msgcat::mc "Skip the move"] \ -command [list [namespace current]::send_skip $gid] $bbox add -text [::msgcat::mc "Propose a draw"] \ -command [list [namespace current]::toggle_draw $gid] $bbox add -text [::msgcat::mc "Accept the draw proposal"] \ -state disabled \ -command [list [namespace current]::accept_draw $gid] $bbox add -text [::msgcat::mc "Resign the game"] \ -command [list [namespace current]::send_resign $gid] grid columnconfigure $bbox 0 -weight 1 pack $bbox -side bottom -anchor w -fill x set flags(bbox) $bbox set_tooltips #label $w.history -text [::msgcat::mc "History"] #pack $w.history -side top -anchor w set hsw [ScrolledWindow $w.hsw] pack $hsw -side top -fill x -expand yes set ht [text $w.text -wrap word -height 60 -state disabled] set font [$ht cget -font] set tabstop1 [font measure $font "99.."] set tabstop2 [font measure $font "99..Qa8-a8+= "] $ht configure -tabs "$tabstop1 $tabstop2" $ht tag configure attention -foreground [option get $ht errorForeground Text] $hsw setwidget $ht set flags(hw) $ht set dsq_color #77a26d set lsq_color #c8c365 for {set c 0} {$c < 15} {incr c} { for {set r 0} {$r < 15} {incr r} { set x1 [expr {$line_width + (($square_size + $line_width) * $c)}] set x2 [expr {($square_size + $line_width) * ($c + 1)}] set y1 [expr {$line_width + (($square_size + $line_width) * $r)}] set y2 [expr {($square_size + $line_width) * ($r + 1)}] set color [expr {($c+$r) % 2 ? $dsq_color : $lsq_color}] if {$c == 0 && $r == 0} { set img "ltf" } elseif {$c == 0 && $r == 14} { set img "lbf" } elseif {$c == 0} { set img "lf" } elseif {$c == 14 && $r == 0} { set img "rtf" } elseif {$c == 14 && $r == 14} { set img "rbf" } elseif {$c == 14} { set img "rf" } elseif {$r == 0} { set img "tf" } elseif {$r == 14} { set img "bf" } elseif {($c == 7 && $r == 7) || ($c == 3 && $r == 3) || \ ($c == 3 && $r == 11) || ($c == 11 && $r == 3) || \ ($c == 11 && $r == 11)} { set img "cf" } else { set img "mf" } $board create image $x1 $y1 -image renju/$img -anchor nw \ -tags [list background [list cr $c [expr {14-$r}]]] $board create rectangle $x1 $y1 $x2 $y2 \ -outline {} \ -tags [list last [list cr $c [expr {14-$r}]]] $board create rectangle $x1 $y1 $x2 $y2 \ -outline {} \ -tags [list square [list cr $c [expr {14-$r}]]] } } bind $board \ [list [namespace current]::motion $gid %x %y] bind $board \ [list [namespace current]::motion $gid %x %y] bind $board \ [list [namespace current]::leave $gid %x %y] bind $board \ [list [namespace current]::release $gid %x %y] bind $w [list [namespace current]::close $gid] make_default_position $gid draw_position $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc renju::set_tooltips {args} { variable options if {$options(show_tooltips)} { set tooltip0 [::msgcat::mc "Press button if you want skip current move"] set tooltip1 [::msgcat::mc "Press button and make move if you want propose draw"] set tooltip2 [::msgcat::mc "Press button if you want accept the draw proposal"] set tooltip3 [::msgcat::mc "Press button if you want resign"] } else { set tooltip0 "" set tooltip1 "" set tooltip2 "" set tooltip3 "" } foreach var [info vars [namespace current]::*] { upvar 0 $var flags if {[info exists flags(bbox)]} { catch { $flags(bbox) itemconfigure 0 -helptext $tooltip0 $flags(bbox) itemconfigure 1 -helptext $tooltip1 $flags(bbox) itemconfigure 2 -helptext $tooltip2 $flags(bbox) itemconfigure 3 -helptext $tooltip3 } } } } proc renju::toggle_show_last_move {gid} { variable $gid upvar 0 $gid flags set flags(show_last_move) [expr {!$flags(show_last_move)}] set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] $flags(show_last_move_button) configure -relief $relief highlight_last_move $gid } proc renju::toggle_draw {gid} { variable $gid upvar 0 $gid flags set flags(position,draw) [expr {!$flags(position,draw)}] if {$flags(position,draw)} { $flags(bbox) itemconfigure 0 -relief sunken } else { $flags(bbox) itemconfigure 0 -relief raised } } proc renju::update_controls {gid {draw_proposed 0}} { variable $gid upvar 0 $gid flags $flags(bbox) itemconfigure 0 -relief raised if {[is_my_move $gid]} { $flags(board) config -cursor "" set flags(position,draw) 0 if {$draw_proposed} { $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state normal $flags(bbox) itemconfigure 3 -state disabled } else { $flags(bbox) itemconfigure 0 -state normal $flags(bbox) itemconfigure 1 -state normal $flags(bbox) itemconfigure 2 -state disabled $flags(bbox) itemconfigure 3 -state normal } } elseif {![is_white $flags(position,turn)] && \ ![is_black $flags(position,turn)]} { $flags(board) config -cursor "" $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled $flags(bbox) itemconfigure 3 -state disabled } else { $flags(board) config -cursor watch $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled $flags(bbox) itemconfigure 3 -state disabled } } proc renju::end_game {gid my_score message} { variable $gid upvar 0 $gid flags set opponent_score [expr {1 - $my_score}] if {[is_black $flags(our_color)]} { set score "$my_score : $opponent_score" } else { set score "$opponent_score : $my_score" } set flags(position,turn) none set flags(move_label) $message set hw $flags(hw) $hw configure -state normal catch {$hw delete attention.first attention.last} $hw delete {end -1 char} end $hw insert end "\n\t\t$score\n" $hw see end $hw configure -state disabled } proc renju::draw_position {gid} { variable $gid upvar 0 $gid flags $flags(board) delete figure for {set c 0} {$c < 15} {incr c} { for {set r 0} {$r < 15} {incr r} { if {$flags(position,$c,$r) != ""} { $flags(board) create image [center $c $r] \ -image renju/$flags(position,$c,$r) \ -tags [list figure $flags(position,$c,$r) [list cr $c $r]] } } } } proc renju::motion {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq $board addtag dst_sq overlapping $x $y $x $y set tags [$board gettags dst_sq&&background] lassign [lindex $tags [lsearch $tags cr*]] cr c r $board addtag dst_sq withtag [list cr $c $r]&&square if {[info exists flags(position,$c,$r)] && $flags(position,$c,$r) == ""} { $board itemconfigure dst_sq&&square -outline red $board itemconfigure dst_sq&&legal&&square -outline blue } } proc renju::leave {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq highlight_last_move $gid } proc renju::release {gid x y} { variable options variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq $board addtag dst_sq overlapping $x $y $x $y set tags [$board gettags dst_sq&&background] lassign [lindex $tags [lsearch $tags cr*]] cr c r $board dtag dst_sq if {$options(allow_illegal) || [is_my_move $gid]} { if {[do_move $gid $c $r $flags(position,draw)]} { $board itemconfigure [list cr $c $r]&&square -outline "" } } update_controls $gid draw_position $gid highlight_last_move $gid } proc renju::highlight_last_move {gid} { variable $gid upvar 0 $gid flags $flags(board) itemconfigure last -outline "" if {[catch {lassign $flags(position,last_move) ct rt}]} { return } if {$flags(show_last_move)} { set color white } else { set color {} } $flags(board) itemconfigure [list cr $ct $rt]&&last -outline $color } proc renju::do_move {gid ct rt draw} { variable options variable moves variable $gid upvar 0 $gid flags if {$ct == "" || $rt == ""} { return 0 } set my_move [is_my_move $gid] if {![is_move_legal $gid $ct $rt]} { if {$my_move && !$options(allow_illegal)} { return 0 } if {!$my_move && !$options(accept_illegal)} { return 0 } } save_position $gid if {[is_white $flags(position,turn)]} { set mover w set opp b } else { set mover b set opp w } set flags(position,$ct,$rt) $mover set flags(position,last_move) [list $ct $rt] set checkmate [test_checkmate $gid $ct $rt] if {[is_white $flags(position,turn)]} { find_legal_moves $gid black } else { find_legal_moves $gid white } set skip [lempty $flags(legal_moves)] add_move_to_history $gid $ct $rt if {!$checkmate && $draw && !$my_move} { attention_message $gid \ [::msgcat::mc "\n\n Opponent proposes a draw\n\n"] } if {$my_move} { send_move $gid $ct $rt } if {!$skip} { if {[is_white $flags(position,turn)]} { set flags(position,turn) black } else { set flags(position,turn) white } } find_legal_moves $gid $flags(position,turn) set endgame 0 if {$skip && [lempty $flags(legal_moves)]} { # Can't find any move for both sides set endgame 1 } elseif {$skip} { add_move_to_history $gid } if {$checkmate} { if {$my_move} { # I win end_game $gid 1 [::msgcat::mc "You win"] } else { # Opponent wins end_game $gid 0 [::msgcat::mc "Opponent wins"] } } elseif {$endgame} { # Draw end_game $gid 0.5 [::msgcat::mc "Draw"] } tab_set_updated [winfo parent $flags(board)] 1 mesg_to_user return 1 } proc renju::accept_draw {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type $flags(game) \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag accept]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0.5 [::msgcat::mc "Draw (You accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc renju::send_skip {gid} { variable $gid upvar 0 $gid flags add_move_to_history $gid if {[is_white $flags(position,turn)]} { set flags(position,turn) black } else { set flags(position,turn) white } find_legal_moves $gid $flags(position,turn) jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type $flags(game) \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag skip]]] \ -to $flags(opponent) \ -connection $flags(connid) \ -command [list [namespace current]::send_result $gid] if {[lindex $flags(position,history) end] == "skip" && \ [lindex $flags(position,history) end-1] == "skip"} { end_game $gid 0.5 [::msgcat::mc "Draw (Both players skipped move)"] } update_controls $gid draw_position $gid highlight_last_move $gid } proc renju::send_resign {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type $flags(game) \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag resign]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0 [::msgcat::mc "Opponent wins (You resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc renju::send_move {gid ct rt} { variable $gid upvar 0 $gid flags set put_tags [list [jlib::wrapper:createtag put -vars [list pos "$ct,$rt"]]] if {$flags(position,draw)} { lappend put_tags [jlib::wrapper:createtag draw] } jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type $flags(game) \ id $flags(id)] \ -subtags $put_tags] \ -to $flags(opponent) \ -connection $flags(connid) \ -command [list [namespace current]::send_result $gid] } proc renju::send_result {gid res child} { if {$res == "ERR"} { attention_message $gid \ [format [::msgcat::mc "\n\n Opponent rejected move:\n %s\n\n"] \ [error_to_string $child]] restore_position $gid } } proc renju::count_pieces {gid} { variable $gid upvar 0 $gid flags set b 0 set w 0 for {set ct 0} {$ct < 15} {incr ct} { for {set rt 0} {$rt < 15} {incr rt} { switch -- $flags(position,$ct,$rt) { b { incr b } w { incr w } } } } return [list $b $w] } proc renju::add_move_to_history {gid {ct ""} {rt ""}} { variable $gid upvar 0 $gid flags incr flags(position,halfmove) if {$ct != "" && $rt != ""} { lappend flags(position,history) [list $ct $rt] } else { lappend flags(position,history) skip } set hw $flags(hw) $hw configure -state normal $hw delete 0.0 end $hw insert end "\t[::msgcat::mc Black]\t[::msgcat::mc White]\n" set i 1 foreach {b w} $flags(position,history) { $hw insert end "${i}.\t" if {$b == "skip"} { $hw insert end "--\t" } elseif {$b != {}} { lassign $b ct rt incr rt set lt [format %c [expr {$ct+97}]] $hw insert end "$lt$rt\t" } if {$w == "skip"} { $hw insert end "--\n" } elseif {$w != {}} { lassign $w ct rt incr rt set lt [format %c [expr {$ct+97}]] $hw insert end "$lt$rt\n" } else { $hw insert end "\n" } incr i } $hw see end $hw configure -state disabled } proc renju::test_checkmate {gid ct rt} { variable $gid upvar 0 $gid flags variable moves if {$flags(position,$ct,$rt) == ""} { return 0 } set mover $flags(position,$ct,$rt) foreach dir {d1 d2 d3 d4 h1 h2 v1 v2} { set str($dir) 0 foreach {x y} $moves($dir,$ct,$rt) { if {$flags(position,$x,$y) == $mover} { incr str($dir) } else { break } } } set s1 [expr {1 + $str(d1) + $str(d3)}] set s2 [expr {1 + $str(d2) + $str(d4)}] set s3 [expr {1 + $str(h1) + $str(h2)}] set s4 [expr {1 + $str(v1) + $str(v2)}] switch -- $flags(game) { gomoku:freestyle - gomoku:tournament { return [expr {$s1 >= 5 || $s2 >= 5 || $s3 >= 5 || $s4 >= 5}] } gomoku:standard { return [expr {$s1 == 5 || $s2 == 5 || $s3 == 5 || $s4 == 5}] } renju { if {[is_black $mover]} { return [expr {$s1 == 5 || $s2 == 5 || $s3 == 5 || $s4 == 5}] } else { return [expr {$s1 >= 5 || $s2 >= 5 || $s3 >= 5 || $s4 >= 5}] } } } } proc renju::find_legal_moves {gid color} { variable $gid upvar 0 $gid flags set flags(legal_moves) {} for {set ct 0} {$ct < 15} {incr ct} { for {set rt 0} {$rt < 15} {incr rt} { if {$flags(position,$ct,$rt) != "" && \ [test_checkmate $gid $ct $rt]} { highlight_legal_moves $gid return } } } for {set ct 0} {$ct < 15} {incr ct} { for {set rt 0} {$rt < 15} {incr rt} { if {$flags(position,$ct,$rt) == "" && \ [check_legal $gid $ct $rt $color]} { lappend flags(legal_moves) [list $ct $rt] } } } highlight_legal_moves $gid } proc renju::is_overline {gid ct rt color} { variable moves variable $gid upvar 0 $gid flags # Assume that $ct $rt cell is empty set mover [expr {[is_black $color] ? "b" : "w"}] foreach dir {d1 d2 d3 d4 h1 h2 v1 v2} { set str($dir) 0 foreach {x y} $moves($dir,$ct,$rt) { if {$flags(position,$x,$y) == $mover} { incr str($dir) } else { break } } } set s1 [expr {1 + $str(d1) + $str(d3)}] set s2 [expr {1 + $str(d2) + $str(d4)}] set s3 [expr {1 + $str(h1) + $str(h2)}] set s4 [expr {1 + $str(v1) + $str(v2)}] return [expr {$s1 > 5 || $s2 > 5 || $s3 > 5 || $s4 > 5}] } proc renju::five {gid ct rt color dir} { variable moves variable $gid upvar 0 $gid flags # Assume that $ct $rt cell is empty set mover [expr {[is_black $color] ? "b" : "w"}] switch -- $dir { d1 { set dir2 d3 } d2 { set dir2 d4 } d3 { set dir2 d1 } d4 { set dir2 d2 } h1 { set dir2 h2 } h2 { set dir2 h1 } v1 { set dir2 v2 } v2 { set dir2 v1 } } set str {} foreach d [list $dir $dir2] { foreach {x y} $moves($d,$ct,$rt) { if {$flags(position,$x,$y) == $mover} { lappend str [list $x $y] } else { break } } } # Return a list of row cells (all except $ct $rt) if {[llength $str] == 4} { return [lsort $str] } else { return {} } } proc renju::straight_four {gid ct rt color dir} { variable moves variable $gid upvar 0 $gid flags # Assume that $ct $rt cell is empty set mover [expr {[is_black $color] ? "b" : "w"}] switch -- $dir { d1 { set dir2 d3 } d2 { set dir2 d4 } d3 { set dir2 d1 } d4 { set dir2 d2 } h1 { set dir2 h2 } h2 { set dir2 h1 } v1 { set dir2 v2 } v2 { set dir2 v1 } } set str {} foreach d [list $dir $dir2] { set open 0 foreach {x y} $moves($d,$ct,$rt) { if {!$open} { if {$flags(position,$x,$y) == $mover} { lappend str [list $x $y] } elseif {$flags(position,$x,$y) == ""} { # The row is open from $d side set open 1 } else { # The row is blocked return {} } } else { if {$flags(position,$x,$y) == $mover} { # The row is blocked by own stone return {} } else { break } } } if {!$open} { # The row is blocked by a border return {} } } # Return a list of row cells (all except $ct $rt) if {[llength $str] == 3} { return [lsort $str] } else { return {} } } proc renju::threes_and_fours {gid ct rt color dir} { variable moves variable $gid upvar 0 $gid flags # Assume that $ct $rt cell is empty set mover [expr {[is_black $color] ? "b" : "w"}] switch -- $dir { d1 { set dir2 d3 } d2 { set dir2 d4 } d3 { set dir2 d1 } d4 { set dir2 d2 } h1 { set dir2 h2 } h2 { set dir2 h1 } v1 { set dir2 v2 } v2 { set dir2 v1 } } foreach d [list $dir $dir2] { set str4($d) {} set str5($d) {} foreach {x y} $moves($d,$ct,$rt) { if {$flags(position,$x,$y) == ""} { # The row is open from $d side set flags(position,$ct,$rt) $mover set str4($d) [straight_four $gid $x $y $color $d] if {$str4($d) == {}} { set str5($d) [five $gid $x $y $color $d] } set flags(position,$ct,$rt) "" break } elseif {$flags(position,$x,$y) != $mover} { break } } } if {$str4($dir) == {} && $str4($dir2) == {}} { set th 0 } elseif {$str4($dir) == $str4($dir2)} { set th 1 } elseif {$str4($dir) == {} || $str4($dir2) == {}} { set th 1 } else { set th 2 } if {$str5($dir) == {} && $str5($dir2) == {}} { set fo 0 } elseif {$str5($dir) == $str5($dir2)} { set fo 1 } elseif {$str5($dir) == {} || $str5($dir2) == {}} { set fo 1 } else { set fo 2 } return [list $th $fo] } proc renju::check_legal {gid ct rt color} { variable moves variable $gid upvar 0 $gid flags set me [expr {[is_black $color] ? "b" : "w"}] set opp [expr {[is_black $color] ? "w" : "b"}] switch -- $flags(game) { gomoku:freestyle { return 1 } gomoku:standard { return 1 } gomoku:tournament { if {![is_black $color]} { return 1 } else { set hist [llength $flags(position,history)] if {$hist == 0} { if {$ct == 7 && $rt == 7} { return 1 } else { return 0 } } elseif {$hist == 2} { if {$ct >= 5 && $ct <= 9 && $rt >= 5 && $rt <= 9} { return 0 } else { return 1 } } else { return 1 } } } renju { if {![is_black $color]} { return 1 } else { set hist [llength $flags(position,history)] if {$hist == 0} { if {$ct == 7 && $rt == 7} { return 1 } else { return 0 } } foreach dir {d1 d2 h1 v1} { if {[llength [five $gid $ct $rt $color $dir]] == 4} { return 1 } } if {[is_overline $gid $ct $rt $color]} { return 0 } set threes 0 set fours 0 foreach dir {d1 d2 h1 v1} { lassign [threes_and_fours $gid $ct $rt $color $dir] th fo incr threes $th incr fours $fo } if {$fours > 1 || $threes > 1} { return 0 } else { return 1 } } } } } proc renju::is_move_legal {gid ct rt} { variable $gid upvar 0 $gid flags expr {[lmatch -regexp $flags(legal_moves) ^[list $ct $rt]] != {}} } proc renju::highlight_legal_moves {gid} { variable $gid upvar 0 $gid flags set board $flags(board) $board dtag legal foreach move $flags(legal_moves) { lassign $move ct rt $board addtag legal withtag [list cr $ct $rt]&&square } } proc renju::attention_message {gid message} { variable $gid upvar 0 $gid flags set hw $flags(hw) $hw configure -state normal $hw delete {end -1 char} end $hw insert end $message attention $hw see end $hw configure -state disabled } proc renju::is_my_move {gid} { variable $gid upvar 0 $gid flags is_same_color $flags(position,turn) $flags(our_color) } proc renju::is_white {f} { string equal -length 1 $f w } proc renju::is_black {f} { string equal -length 1 $f b } proc renju::is_same_color {f1 f2} { string equal -length 1 $f1 $f2 } proc renju::add_groupchat_user_menu_item {m connid jid} { set mm $m.gamesmenu if {![winfo exists $mm]} { menu $mm -tearoff 0 $m add cascade -label [::msgcat::mc "Games"] -menu $mm } $mm add command -label [::msgcat::mc "Gomoku/Renju..."] \ -command [list [namespace current]::invite_dialog $connid $jid] } hook::add roster_create_groupchat_user_menu_hook \ [namespace current]::renju::add_groupchat_user_menu_item 51 hook::add chat_create_user_menu_hook \ [namespace current]::renju::add_groupchat_user_menu_item 51 hook::add roster_jid_popup_menu_hook \ [namespace current]::renju::add_groupchat_user_menu_item 51 proc renju::iq_create {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children set game [jlib::wrapper:getattr $vars type] switch -- $game { gomoku:freestyle - gomoku:standard - gomoku:tournament - renju {} default { return } } if {[jlib::wrapper:isattr $vars color]} { set color [jlib::wrapper:getattr $vars color] switch -- $color { white - black { } default { set var [list error modify bad-request] } } } else { set color white } set var [[namespace current]::invited_dialog \ $game $connid $from \ [jlib::wrapper:getattr $vars id] \ $color] } hook::add games_board_create_hook [namespace current]::renju::iq_create proc renju::iq_turn {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children switch -- [jlib::wrapper:getattr $vars type] { gomoku:freestyle - gomoku:standard - gomoku:tournament - renju {} default { return } } set gid [make_gid $from [jlib::wrapper:getattr $vars id]] if {[exists $gid]} { set var [[namespace current]::turn_recv $gid $children] } else { set var [list error cancel item-not-found] } } hook::add games_board_turn_hook [namespace current]::renju::iq_turn # Common games:board part proc iq_games_board_create {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_create_hook res $connid $from $child return $res } iq::register_handler set create games:board \ [namespace current]::iq_games_board_create proc iq_games_board_turn {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_turn_hook res $connid $from $child return $res } iq::register_handler set turn games:board \ [namespace current]::iq_games_board_turn tkabber-plugins-0.11.1/renju/proto0000644000175000017500000000331710565141770016424 0ustar sergeisergeiRequest: 600 -- for all players 10 -- if on black side played Kasparov Positive response: or simply ? Turn: 'pos' attribute contains coordinates of piece. Coordinate is a comma-separated list of integers >= 0. Skipping the move: Proposing draw: Accepting draw proposal: Resigning: Also we need and tags for games where we must put or remove pieces. can have 'type' and 'color' attributes. move, put & destroy tags may have some game-specific subtags. Response: if move accepted, or error 'Not Acceptable' if other side thinks that this move illegal. tkabber-plugins-0.11.1/renju/pixmaps/0000755000175000017500000000000011076120366017007 5ustar sergeisergeitkabber-plugins-0.11.1/renju/pixmaps/stones/0000755000175000017500000000000011076120366020322 5ustar sergeisergeitkabber-plugins-0.11.1/renju/pixmaps/stones/w.gif0000644000175000017500000000327210565141770021267 0ustar sergeisergeiGIF89a% / ]T3gP.kX(kY5lZ0l\=t[3w])z[.u`*t`/ob6xb%pbZ,#&Guinصeۄ @QeC-WjJ4VCn^>~+n2 S5'r+ԭyׯ>s+հINI4Gy#Wo5 4‹!B!cLC0pT<< 5ָ$t*fPA%09Î>Ï9ެ^5R*H$Ta4c:c=FL3ڤ 4J#$H dC4C 5Tӎ65@$I*LRdd M4,S/b54 2tK)Xp!*P 8lLR -K/ܹH"1 B  1rh5VX'bH)#Y0P3431,s 54s -.As!D<@A5K.B%jBtE. K,/K t'4Bp‹*-JX!W\ $`CArJ*"-|q$3j7T@!!%bI1 MpFܐ -}dȚ$ #a{\QxA8BEnD҈!  <_QE,Ep AC~{fHF!7  @sF/hCDAA0`p @z̰C,P@5L_3  H @;tkabber-plugins-0.11.1/renju/pixmaps/stones/right_bot.gif0000644000175000017500000000303510565141770022777 0ustar sergeisergeiGIF89a >`0өSԪT֩UժUשUڧXשVիU֫U֫VլVլWѮX֬V֬X֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ް]߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]_޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0, W`#  sdb peEK+P X>B…,BH9zG'b,!'gXu!T z0h R L:¦Gd(hRU6|AT (q6R dҘp%$"f2H- hyȃLLTrhKc2Lǡ墑WlsFܔ>m +\Y l4ȳc\ @+J$pf h1%z|@gP{Kn!*D SmkfBG hF25 C!wбZ4C2m}r!AG/oPc8rKّK`0өSԪT֩UժUשUڧXשVիU֫U֫VլVլWѮX֬V֬X֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ް]߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]_޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0, W`#  sdb peEK+P X>B…,BH9zG'b,!'gXu!T z0h R L:¦Gd(hRU6|AT (q6R dҘp%$"f2H- hyȃLLTrhKc2Lǡ墑WlsFܔ>m +\Y l4Ȱc\ @*J$pf hBD%z|fPQF>`.Y";҆1>k*=  "+E_ 30D!)r AEН pF[P9C tVqK-H UA"DZ%UK;w BP4 M"1IQ`4C]O5L;tkabber-plugins-0.11.1/renju/pixmaps/stones/bot.gif0000644000175000017500000000302210565141770021576 0ustar sergeisergeiGIF89a >`0өSԪT֩UժUשUڧXשVիU֫U֫VլVլWѮX֬V֬X֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ް]߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]_޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, W`#  sdb peEK+P X>B…,BH9zG'b,!'gXu!T z0h R L:¦Gd(hRU6|AT (q6R dҘp%$"f2H- hyȃLLTrhKc2Lǡ墑WlsFܔ>m +\Y lw E4 P_!K0md5FQ`A=EU;tkabber-plugins-0.11.1/renju/pixmaps/stones/b.gif0000644000175000017500000000313410565141770021237 0ustar sergeisergeiGIF89a               $!"! '%#$"%#$"2 0"3$&(&5%)+(0+:*7*"0,+-.,=,:,70=-01/=1C135375):5%954686D79;8C9*<>;S: ?A?<@MM@'LC#U@BDAZ??FHVC+MG1GHFPI.QG7HIQJKIUL,\K!PNAMOLMQSVOINSUcQ'cR.]QGdT*cS4_U5TVScU;`UEkW'hZ"XZXkY/hZ4k\%jZ;r\ h[EtZ,\^[h]Aq]-c^]r_4_a^{_$cebee]ifYd*hh`~h+gifwilnkqnaznRpCnYo@rtqptwxtms=tNuwtuittwUyKyQxHxN}{{}z|>{Ew|{R{URNdTbj_TfUogmĠ]doçghnǩcȬ_Ƭr˪rƯgխVӭ\۬WߪWܭQϳXׯXԯdٰRԲYҲ_̴eвlشL״S`ڲZٲ`߰[ްaԵhWٴp]طdܵd߶^X׸qݷl޻ab! , 8p7c$3nJ[O}9 !7,j6Du"D3`0BOL \+K,YJ40SԈBm&i+D }ӈ"`0өSԪT֩UժUשUڧXשVիU֫U֫VլVլWѮX֬V֬X׬W֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ް]ް^߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]ݳ__޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0, Yd c̝ vh0ĢL& pҀL,р YD"B…-BH"9zd-$'i^y#!LVz` S!XBІHf*tb0qDRpġز UTp QA&1[x!,K,ğމdԇ u@%GPH Gx,ShH_iXf\ve`)d)_@+b`0 %0K}KqE4A*m~"R[> >B (*mVBBE̩mT ,,B,XTB0jLP_S>`$fJQ{) M&kŊ!Ȗ,k)ZI% uf,hyQFFim.]!<aKoK!S>, 2Gl c!3@"*$G ÑEu>D+C{&2h"#rwF%r-jbĄ$*XqG r`0өSԪT֩UժUשUڧXשVիU֫U֫VլVլWѮX֬V֬X׬W֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ް]ް^߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]ݳ__޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, Yd c̝ vh0ĢL& pҀL,р YD"B…-BH"9zd-$'i^y#!LVz` S!XBІHf*tb0qDRpġز UTp QA&1[x!,K,ğމdԇ u@%GPH Gx,ShH_iXfX.%Mi`edid.o}dZ" Z@j x,GаGJ P o"R,`( i0¢Y  ЧRQE,TG ibP {P1C}M ** pv Fkh) k Mkή!ů,Ql)ZI% ,hy`Q!FFm.]!<aK6+pK!> , 2C׬c!3@"*$G E>+C&2h*#rwF%Ps-&1! VQ#E\&9/!G,8B% RWg.I a0h;6y=S@;tkabber-plugins-0.11.1/renju/pixmaps/stones/left_bot.gif0000644000175000017500000000305210565141770022613 0ustar sergeisergeiGIF89a >`0өS֨TԪT֩UժUשUڧXשVիU֫U֫VتWլVլWѮX֬V֬XѬf֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮W׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ٳZް]߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]߲^_޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[޶^^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`c޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, _p1Ì ypHM'%N/g \NRGB…0BH9zDH) g 13#)lh8!X$ V#hZgPJi.V} -d l<8K鏨w܈k㳓',;9şSA?'Ί 3i =|-An xy7GK9q(<lsȶ[8cL$ A''^X:BDCz7Ρ.7fc"  DS d tX,eh )KwixɁ曟]"9/N` ~lJPc)Bn%DJsr)EU􂣢PA&1: C+CA F H0n`Dhw1TːjCS1#>hlQ D,J'Bf hUP'zfTF.5Z"?"G Oi<+A@|bJL/H qskhUP j̋d=༑C P-͚Ȓb%-d lmDD)uGp Z`-dFhcT'.!Qu_tL;tkabber-plugins-0.11.1/renju/pixmaps/stones/left.gif0000644000175000017500000000304510565141770021751 0ustar sergeisergeiGIF89a >`0өS֨TԪT֩UժUשUڧXשVիU֫U֫VتWլVլWѮX֬V֬XѬf֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮W׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ٳZް]߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]߲^_޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[޶^^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`c޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0, _p1Ì ypHM'%N/g \NRGB…0BH9zDH) g 13#)lh8!X$ V#hZgPJi.V} -d l<8K鏨w܈k㳓',;9şSA?'Ί 3i =|-An xy7GK9q(<lsȶ[8cL$ A''^X:BDCz7Ρ.7fc"  DS d tX,eh )Kw`xɁ曟I8/N` ~lJPF JĢ[,A f&p&"+QE/8*Z dC0 ]SA`T jQDRm{$Ƨ/l64%DCT¾@tq)T`F/DuGN! lKndoR%C.rT Zo29÷,6(}R%2 G,B#}@ZD %`sj9@g'k"K'HDuQtG@ W`v5K)U i`H m;Dqô;tkabber-plugins-0.11.1/renju/pixmaps/stones/right.gif0000644000175000017500000000302610565141770022133 0ustar sergeisergeiGIF89a >`0өSԪT֩UժUשUڧXשVիU֫U֫VլVլWѮX֬V֬X֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ް]߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]_޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, W`#  sdb peEK+P X>B…,BH9zG'b,!'gXu!T z0h R L:¦Gd(hRU6|AT (q6R dҘp%$"f2H- hyȃLLTrhKc2Lǡ墑WlsFܔ>m +\Y l4Ȳc\ @*J$pf hBD!%z|@gPFn.Y";҆1^ofBGhFK6L+ QH ABnpkm2l#gAG,oPqҩlvd K`0өS֨TԪT֩UժUשUڧXשVիU֫U֫VتWլVլWѮX֬V֬XѬf׬W֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮W׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ٳZް]ް^߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]߲^ݳ__޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[޶^^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`c޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0, atIM |t`C uEP0 ]TGB…1BH"9z%d i1CF)nn#!LZ0H W$tb2ǐLk0 3}(#)EV| %E# JaYi'5,)H F _,%FEi"5@KH0?Bf( Уz+[d$GڞAwѢ-ީA恃7V\c[C# Tߡד'L[|'«~<3 %{p |~JYb\B UTu` a'1[x!&.O,ğ̐މԇ P'K\@IX~ Stones 1.0 Renju Stones Theme. 2007-02-15 renju/b b.gif renju/w w.gif renju/bf bot.gif renju/tf top.gif renju/rf right.gif renju/lf left.gif renju/rbf right_bot.gif renju/rtf right_top.gif renju/lbf left_bot.gif renju/ltf left_top.gif renju/mf middle.gif renju/cf center.gif tkabber-plugins-0.11.1/renju/pixmaps/stones/center.gif0000644000175000017500000000300710565141770022275 0ustar sergeisergeiGIF89a >`0өSԪT֩UժUשUڧXשVիU֫U֫VլVլWѮX֬V֬X֭UխX٫X٫Y֭WүX֭XүY׭W٬W٬Xҭf׭YҭgحWիjحXڬX׮V֮YڬYӭg׮X٭XӰYӰZخXخYׯWׯXٮXخ[ۭYدWۭZدXۭ[دYԲTԱZدZԲUԱ[ձYٯYܭ\ٯZۮZۮ[گZܮZٰXܮ[ճUֲXճVݮ\ڰZܯ[ֳVٱYڰ\زYڱYݯ\ִVִWٲZݰZޯ]۱[ݰ\߯]ܱ[ް[ݰ^ܱ\ް\ް]߰]ޱ[߰^ܲ\ޱ]߱[ݲ\ܲ_ڴ[߱^ܳ\ܳ]`^ݳ]_޳]_ݴ]ܵ\_޴^ݵ\_ܶZaܶ]`ݶ[c޵^aݶ]ݶ^aߵ_`ݷ[^ߵaa_bݷ]`ݷ^߶^޷\`c޷^a޷_b`c޸\߷_b߷`޸^߷a߸]߸^߸_߸``ca`ad߹_aabdecbcbde>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, W`#  sdb peEK+P X>B…,BH9zG'b,!'gXu!T z0h R L:¦Gd(hRU6|AT (q6R dҘp%$"f2H- hyȃLLTrhKc2Lǡ墑WlsFܔ>m +\Y l =yBg)hJ2BERmT w(Cb* Ӧ=tTn`QwzVc$*CS>4ȯc\ @*J$pf hBD%z|pfPF> .).Y";҆1K**ӝ=  "Üݷk^ 30D!)r Eʐ `<ƅXP9Cm&qK@G+/H UA"DZ%8K7w >4 qIO4L9Q`4qCYW;tkabber-plugins-0.11.1/renju/pixmaps/black/0000755000175000017500000000000011076120366020063 5ustar sergeisergeitkabber-plugins-0.11.1/renju/pixmaps/black/w.gif0000644000175000017500000000033010570623670021020 0ustar sergeisergeiGIF89a % /&icXwri! ,IE9It`(hf*;s.(,(rQŖ?D @* UJ x1_&Ӱs#u)ѾT{X~fRIrM7oG >fB.D[.0P6%@+S ;tkabber-plugins-0.11.1/renju/pixmaps/black/right_bot.gif0000644000175000017500000000013210570623670022533 0ustar sergeisergeiGIF87a , 9T,@}S(>d1訮f;;|y jĢL*̦ ;tkabber-plugins-0.11.1/renju/pixmaps/black/middle.gif0000644000175000017500000000015010570623670022010 0ustar sergeisergeiGIF87a , GT,@}S(>d1訮f;;| ˸B%a5tsdAҭA ;tkabber-plugins-0.11.1/renju/pixmaps/black/bot.gif0000644000175000017500000000013310570623670021337 0ustar sergeisergeiGIF87a , :T,@}S(>d1訮f;;| L*̦ J9;tkabber-plugins-0.11.1/renju/pixmaps/black/b.gif0000644000175000017500000000033010570623670020773 0ustar sergeisergeiGIF89a  R b! ,IE9It`(hf*;s.(,(rQŖ?D @* UJ x1_&Ӱs#u)ѾT{X~fRIrM7oG >fB.D[.0P6%@+S ;tkabber-plugins-0.11.1/renju/pixmaps/black/top.gif0000644000175000017500000000012610570623670021357 0ustar sergeisergeiGIF87a , 5ڋ޼扦ʶ,]XIF;tkabber-plugins-0.11.1/renju/pixmaps/black/right_top.gif0000644000175000017500000000012410570623670022552 0ustar sergeisergeiGIF87a , 3ڋ޼扖dʚ ў᜾bXAR;tkabber-plugins-0.11.1/renju/pixmaps/black/left_bot.gif0000644000175000017500000000013210570623670022350 0ustar sergeisergeiGIF87a , 9T,@}S(>d1訮f;;|; jĢL*̦ r ;tkabber-plugins-0.11.1/renju/pixmaps/black/left.gif0000644000175000017500000000015010570623670021504 0ustar sergeisergeiGIF87a , GT,@}S(>d1訮f;;|; 򀰚!B(f)~Dhn.[;tkabber-plugins-0.11.1/renju/pixmaps/black/right.gif0000644000175000017500000000015010570623670021667 0ustar sergeisergeiGIF87a , GT,@}S(>d1訮f;;|y VCTt%?KNsDAaZZ,B[[;tkabber-plugins-0.11.1/renju/pixmaps/black/left_top.gif0000644000175000017500000000012510570623670022370 0ustar sergeisergeiGIF87a , 4ڋ޼扖Sʞk@¡: }uC!x4n;tkabber-plugins-0.11.1/renju/pixmaps/black/icondef.xml0000644000175000017500000000302110570623670022214 0ustar sergeisergei Black 1.0 Renju Black Theme. 2007-02-26 renju/b b.gif renju/w w.gif renju/bf bot.gif renju/tf top.gif renju/rf right.gif renju/lf left.gif renju/rbf right_bot.gif renju/rtf right_top.gif renju/lbf left_bot.gif renju/ltf left_top.gif renju/mf middle.gif renju/cf center.gif tkabber-plugins-0.11.1/renju/pixmaps/black/center.gif0000644000175000017500000000015410570623670022036 0ustar sergeisergeiGIF87a , KT,@}S(>d1訮f릱k] D Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/stripes/INSTALL0000644000175000017500000000070011075425335016725 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/stripes/ ~/.tkabber/plugins/stripes/stripes.tcl Restart Tkabber, to get the plugin loaded. Consult the README file for the details about using this plugin. Usually you'll want to set the stripes' color which can be done either via XRDB (on Unix) or using Tk option database (on any system). tkabber-plugins-0.11.1/stripes/AUTHORS0000644000175000017500000000006611075425335016751 0ustar sergeisergeiKonstantin Khomoutov tkabber-plugins-0.11.1/stripes/stripes.tcl0000644000175000017500000000345011075425335020076 0ustar sergeisergei# $Id: stripes.tcl 1513 2008-10-15 17:39:41Z sergei $ # "Stripes" chat plugin for Tkabber -- colorizes background of # whole messages in chat windows. # # Written by Konstantin Khomoutov # See license.terms for the terms of distribution. # See README for usage details. # Color for odd and even messages can be tuned separately # using the Tk option database (or XRDB) like this: # option add *Chat.oddBackground gray77 # option add *Chat.evenBackground gray84 namespace eval stripes { variable state hook::add open_chat_post_hook \ [namespace current]::setup_chat_window hook::add draw_message_post_hook \ [namespace current]::on_message_drawn } proc stripes::setup_chat_window {chatid type} { variable state set cw [::chat::chat_win $chatid] set mw [::chat::winid $chatid] set bgodd [option get $mw oddBackground Chat] if {$bgodd != ""} { $cw tag configure odd -background $bgodd } set bgeven [option get $mw evenBackground Chat] if {$bgeven != ""} { $cw tag configure even -background $bgeven } set state($cw,last) 1.0 set state($cw,tag) odd bind $cw +[list [namespace current]::cleanup $cw %W] } proc stripes::cleanup {w1 w2} { if {![string equal $w1 $w2]} return variable state unset state($w1,last) unset state($w1,tag) } proc stripes::on_message_drawn {chatid from type body x} { if {![chat::is_opened $chatid]} return set cw [::chat::chat_win $chatid] variable state upvar 0 state($cw,last) last upvar 0 state($cw,tag) tag set now [$cw index {end - 1 char}] if {[$cw compare $last < $now]} { $cw tag add $tag $last $now if {[string equal $tag even]} { set tag odd } else { set tag even } } set last $now } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/georoster/0000755000175000017500000000000011076120366016214 5ustar sergeisergeitkabber-plugins-0.11.1/georoster/earth.ru0000644000175000017500000001717610211463346017701 0ustar sergeisergei # Longitudes and latitudes are from # http://www.getty.edu/research/tools/vocabulary/tgn/index.html # http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_431.html 90.00 0.00 "Северный полюс" color=LightBlue # North Pole -90.00 0.00 "Южный полюс" color=LightBlue # South Pole 43.25 76.95 "Алматы" timezone=Asia/Almaty # Kazakhstan 37.97 23.72 "Афины" timezone=Europe/Athens # Greece 61.22 -149.90 "Анкоридж" timezone=America/Anchorage # Canada 33.35 44.42 "Багдад" timezone=Asia/Baghdad # Iraq 12.97 77.58 "Бенгалуру" timezone=Asia/Calcutta # India 13.73 100.50 "Бангкок" timezone=Asia/Bangkok # Thailand 52.53 13.42 "Берлин" timezone=Europe/Berlin # Germany 39.92 116.43 "Пекин" timezone=Asia/Shanghai # China 4.63 -74.08 "Богота" timezone=America/Bogota # Colombia # 42.35 -71.05 "Бостон" timezone=US/Eastern # USA -34.67 -58.50 "Буэнос-Айрес" timezone=America/Buenos_Aires # Argentina 30.05 31.25 "Каир" timezone=Africa/Cairo # Egypt 22.50 88.33 "Калькутта" timezone=Asia/Calcutta # India 10.50 -66.92 "Каракас" timezone=America/Caracas # Venezuela # 13.08 80.30 "Мадрас" timezone=Asia/Calcutta # India 41.85 -87.65 "Чикаго" timezone=America/Chicago # USA 30.65 103.68 "Чэнду" timezone=Asia/Chongqing # China 32.78 -96.80 "Даллас" timezone=America/Chicago # USA 28.67 77.22 "Дели" timezone=Asia/Calcutta # India # 42.32 -83.03 "Детройт" timezone=America/Detroit # USA 23.72 90.37 "Дакка" timezone=Asia/Dhaka # Bangladesh # 51.45 6.95 "Эссен" timezone=Europe/Berlin # Germany 22.28 114.15 "Гонконг" timezone=Hongkong # China 17.37 78.43 "Хайдарабад" timezone=Asia/Calcutta # India 52.27 104.33 "Иркутск" timezone=Asia/Irkutsk # Russia 41.03 28.95 "Стамбул" timezone=Asia/Istanbul # Turkey -6.13 106.75 "Джакарта" timezone=Asia/Jakarta # Indonesia -26.17 28.03 "Йоханнесбург" timezone=Africa/Johannesburg # South Africa 24.85 67.03 "Карачи" timezone=Asia/Karachi # Pakistan 15.55 32.53 "Хартум" timezone=Africa/Khartoum # Sudan 50.43 30.52 "Киев" timezone=Europe/Kiew # Ukraine -4.30 15.30 "Киншаса" timezone=Africa/Kinshasa # Congo 6.45 3.47 "Лагос" timezone=Africa/Lagos # Nigeria # 31.57 74.37 "Лахор" timezone=Asia/Karachi # Pakistan -12.05 -77.05 "Лима" timezone=America/Lima # Peru 51.50 -0.17 "Лондон" timezone=GB # United Kingdom 34.05 -118.23 "Лос-Анжелес" timezone=US/Pacific # USA 40.42 -3.72 "Мадрид" timezone=Europe/Madrid # Spain 14.62 120.97 "Манила" timezone=Asia/Manila # Philippines -37.75 144.97 "Мельбурн" timezone=Australia/Melbourne # Australia 19.40 -99.15 "Мехико" timezone=America/Mexico_City # Mexico 45.52 -73.57 "Монреаль" timezone=America/Montreal # Canada 55.75 37.70 "Москва" timezone=Europe/Moscow # Russia 18.93 72.85 "Бомбей" timezone=Asia/Calcutta # India 40.70 -74.00 "Нью-Йорк" timezone=US/Eastern # USA 55.07 83.08 "Новосибирск" timezone=Asia/Novosibirsk # Russia 55.00 73.37 "Омск" timezone=Asia/Omsk # Russia 34.67 135.50 "Осака" timezone=Asia/Tokyo # Japan 48.87 2.33 "Париж" timezone=Europe/Paris # France 53.02 158.65 "Петропавловск-К." timezone=Asia/Kamchatka # Russia # 39.95 -75.15 "Филадельфия" timezone=US/Eastern # USA -22.88 -43.28 "Рио-де-Жанейро" timezone=America/Sao_Paulo # Brazil 37.77 -122.42 "Сан-Франциско" timezone=America/Los_Angeles # USA -33.45 -70.67 "Сантьяго" timezone=Chile/Continental # Chile 44.50 34.00 "Севастополь" timezone=Europe/Simferopol # Ukraine -23.55 -46.65 "Сан-Паулу" timezone=America/Sao_Paulo # Brazil 37.53 127.00 "Сеул" timezone=Asia/Seoul # South Korea -33.92 151.17 "Сидней" timezone=Australia/Sydney # Australia 1.28 103.85 "Сингапур" timezone=Asia/Singapore # Singapore 59.33 18.08 "Стокгольм" timezone=Europe/Stockholm # Russia 31.10 121.37 "Шанхай" timezone=Asia/Shanghai # China 59.88 30.25 "Санкт-Петербург" timezone=Europe/Moscow # Russia 25.02 121.37 "Тайбэй" timezone=Asia/Taipei # Taiwan 35.67 51.43 "Тегеран" timezone=Asia/Tehran # Iran # 39.13 117.20 "Таншань" timezone=Asia/Shanghai # China 35.75 139.50 "Токио" timezone=Japan # Japan # 43.70 -79.42 "Торонто" timezone=America/Montreal # Canada 49.27 -123.12 "Ванкувер" timezone=America/Vancouver # Canada 43.15 131.88 "Владивосток" timezone=Asia/Vladivostok # Russia 38.88 -77.03 "Вашингтон" timezone=US/Eastern # USA 56.87 60.58 "Екатеринбург" timezone=Asia/Yekaterinburg # Russia # Some other big cities # 23.05 72.67 "Ахмадабад" timezone=Asia/Calcutta # India # 31.20 29.90 "Александрия" timezone=Africa/Cairo # Egypt # 39.92 32.83 "Анкара" timezone=Asia/Istanbul # Turkey # 30.62 104.10 "Чэнду" timezone=Asia/Chongqing # China # 23.13 113.33 "Гуанчжоу" timezone=Asia/Shanghai # China # 45.75 126.68 "Харбин" timezone=Asia/Harbin # China # 10.75 106.67 "Хо-Ши-Мин" timezone=Asia/Saigon # Vietnam # 35.13 136.88 "Нагоя" timezone=Asia/Tokyo # Japan # 35.08 129.03 "Пусан" timezone=Asia/Seoul # South Korea # 39.00 125.78 "Пхеньян" timezone=Asia/Pyongyang # North Korea # 41.83 123.43 "Шеньян" timezone=Asia/Shanghai # China # 30.58 114.32 "Ухань" timezone=Asia/Shanghai # China # 34.27 108.90 "Сиань" timezone=Asia/Shanghai # China # 35.47 139.63 "Йокогама" timezone=Asia/Tokyo # Japan tkabber-plugins-0.11.1/georoster/msgs/0000755000175000017500000000000011076120366017165 5ustar sergeisergeitkabber-plugins-0.11.1/georoster/msgs/pl.msg0000644000175000017500000000252110667535014020315 0ustar sergeisergei# Polish messages file for georoster plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "Automatically open Georoster window." "Pokazuj automatycznie okno Georostera po uruchomieniu." ::msgcat::mcset pl "Default country to use when looking at a vCard." "Domyślnie używany kod kraju przy wyszukiwaniu w wizytówkach." ::msgcat::mcset pl "Automatically look at vCard to find users coordinates." "Automatycznie wyszukuj koordynaty geograficzne w wizytówkach." ::msgcat::mcset pl "Display users who are no longer available." "Pokazuj użytkowników niedostępnych." ::msgcat::mcset pl "Georoster" "Georoster" ::msgcat::mcset pl "Latitude: %.2f Longitude: %.2f" "Szerokość: %.2f Długość: %.2f" ::msgcat::mcset pl "Georoster plugin options." "Ustawienia wtyczki Georoster." ::msgcat::mcset pl "Don't show cities" "Nie pokazuj miast" ::msgcat::mcset pl "Show only city markers" "Pokaż miasta jako punkty" ::msgcat::mcset pl "Show city markers and names" "Pokaż miasta jako punkty z nazwami" ::msgcat::mcset pl "Specify how to show cities at the map." "Wybierz sposób prezentacji miast na mapie." ::msgcat::mcset pl "Store" "Zapisz" ::msgcat::mcset pl "Connection: %s" "Połączenie: %s" tkabber-plugins-0.11.1/georoster/msgs/es.msg0000644000175000017500000000226710712161173020310 0ustar sergeisergei::msgcat::mcset es "Automatically look at vCard to find users coordinates." "Mirar automáticamente las coordenadas del otro contacto en su vCard." ::msgcat::mcset es "Automatically open Georoster window." "Abrir automáticamente la ventana de Georoster." ::msgcat::mcset es "Connection: %s" "Conexión: %s" ::msgcat::mcset es "Default country to use when looking at a vCard." "País por defecto para usar cuando se busca un vCard." ::msgcat::mcset es "Display users who are no longer available." "Mostrar usuarios que no están disponibles." ::msgcat::mcset es "Don't show cities" "No mostrar ciudades" ::msgcat::mcset es "Georoster plugin options." "Opciones del plugin Georoster." ::msgcat::mcset es "Georoster" "Georoster" ::msgcat::mcset es "Latitude: %.2f Longitude: %.2f" "Latitud: %.2f Longitud: %.2f" ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Show city markers and names" "Mostrar marcadores y nombres de las ciudades" ::msgcat::mcset es "Show only city markers" "Mostrar solo los marcadores de ciudades" ::msgcat::mcset es "Specify how to show cities at the map." "Especificar como mostrar las ciudades en el mapa." ::msgcat::mcset es "Store" "Almacenar" tkabber-plugins-0.11.1/georoster/msgs/ro.msg0000644000175000017500000000034710241713355020320 0ustar sergeisergei ::msgcat::mcset ro "Georoster" "Listă geografică" ::msgcat::mcset ro "Store" "Salvare" ::msgcat::mcset ro "Show cities" "Arată oraşe" ::msgcat::mcset ro "Latitude: %.2f Longitude: %.2f" "Latitudine: %.2f Longitudine: %.2f" tkabber-plugins-0.11.1/georoster/msgs/de.msg0000644000175000017500000000315410633320620020261 0ustar sergeisergei # German messages file # Roger Sondermann 11.06.2007 ::msgcat::mcset de "Automatically look at vCard to find users coordinates." "Fr die Koordinaten des Benutzers automatisch in seine Visitenkarte schauen." ::msgcat::mcset de "Automatically open Georoster window." "Das Georoster-Fenster automatisch ffnen." ::msgcat::mcset de "Connection: %s" "Verbindung: %s" ::msgcat::mcset de "Default country to use when looking at a vCard." "Voreingestelltes Land beim Schauen in die Visitenkarte." ::msgcat::mcset de "Display users who are no longer available." "Auch Benutzer, die nicht lnger verfgbar sind, anzeigen." ::msgcat::mcset de "Don't show cities" "Keine Stdte anzeigen" ::msgcat::mcset de "Georoster plugin options." "Optionen fr das Georoster-Plugin." ::msgcat::mcset de "Georoster" "Georoster" ::msgcat::mcset de "Latitude: %.2f Longitude: %.2f" "Breitengrad: %.2f / Lngengrad: %.2f" ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "Show city markers and names" "Markierungen und Namen anzeigen" ::msgcat::mcset de "Show only city markers" "Markierungen anzeigen" ::msgcat::mcset de "Specify how to show cities at the map." "Angeben, wie Stdte auf der Karte angezeigt werden sollen." ::msgcat::mcset de "Store" "Speichern" tkabber-plugins-0.11.1/georoster/msgs/ru.msg0000644000175000017500000000275210633274437020340 0ustar sergeisergei::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Georoster plugin options." "Параметры расширения Геоконтакты" ::msgcat::mcset ru "Don't show cities" "Не показывать города" ::msgcat::mcset ru "Show only city markers" "Показывать только метки городов" ::msgcat::mcset ru "Show city markers and names" "Показывать метки городов и названия" ::msgcat::mcset ru "Specify how to show cities at the map." "Как показывать города на карте." ::msgcat::mcset ru "Georoster" "Геоконтакты" ::msgcat::mcset ru "Connection: %s" "Соединение: %s" ::msgcat::mcset ru "Store" "Сохранить" ::msgcat::mcset ru "Latitude: %.2f Longitude: %.2f" "Широта: %.2f Долгота: %.2f" ::msgcat::mcset ru "Automatically open Georoster window." "Автоматически открывать окно Геоконтактов." ::msgcat::mcset ru "Automatically look at vCard to find users coordinates." "Автоматически искать координаты пользователей во vCard." ::msgcat::mcset ru "Display users who are no longer available." "Отображать недоступных пользователей." ::msgcat::mcset ru "Default country to use when looking at a vCard." "Страна, используемая по умолчанию (если не указана во vCard)." tkabber-plugins-0.11.1/georoster/msgs/uk.msg0000644000175000017500000000271510633274437020330 0ustar sergeisergei ::msgcat::mcset uk "Plugins options." "Параметри плагінів." ::msgcat::mcset uk "Georoster plugin options." "Параметри плагіна Геоконтакти" ::msgcat::mcset uk "Don't show cities" "Не показувати міста" ::msgcat::mcset uk "Show only city markers" "Показувати тільки мітки міст" ::msgcat::mcset uk "Show city markers and names" "Показувати мітки міст і назви" ::msgcat::mcset uk "Specify how to show cities at the map." "Як показувати міста на карті." ::msgcat::mcset uk "Georoster" "Геоконтакти" ::msgcat::mcset uk "Connection: %s" "З'єднання: %s" ::msgcat::mcset uk "Store" "Зберегти" ::msgcat::mcset uk "Latitude: %.2f Longitude: %.2f" "Широта: %.2f Довгота: %.2f" ::msgcat::mcset uk "Automatically open Georoster window." "Автоматично відкривати вікно Геоконтактів." ::msgcat::mcset uk "Automatically look at vCard to find users coordinates." "Автоматично шукати координати користувачів у vCard." ::msgcat::mcset uk "Display users who are no longer available." "Відображати недоступних користувачів." ::msgcat::mcset uk "Default country to use when looking at a vCard." "Країна, використовувана за замовчуванням (якщо не зазначена в vCard)." tkabber-plugins-0.11.1/georoster/msgs/nl.msg0000644000175000017500000000241510277726732020323 0ustar sergeisergei# Dutch messages file # Author: Sander Devrieze s.devrieze@pandora.be # Please notify me of errors or incoherencies. ::msgcat::mcset nl "Georoster" "Georoster" ::msgcat::mcset nl "Store" "Opslaan" ::msgcat::mcset nl "Latitude: %.2f Longitude: %.2f" "Breedtegraad: %.2f Lengtegraad: %.2f" ::msgcat::mcset nl "Automatically open Georoster window." "Venster van Georoster automatisch openen." ::msgcat::mcset nl "Automatically look at vCard to find users coordinates." "Automatisch in vCard kijken om de coördinaten van gebruikers te vinden." ::msgcat::mcset nl "Display users who are no longer available." "Toon gebruikers die niet langer beschikbaar zijn." ::msgcat::mcset nl "Default country to use when looking at a vCard." "Standaard land dat gebruikt wordt tijdens het kijken naar een vCard." ::msgcat::mcset nl "Plugins options." "Pluginopties." ::msgcat::mcset nl "Georoster plugin options." "Pluginopties van Georoster." ::msgcat::mcset nl "Don't show cities" "Steden verbergen" ::msgcat::mcset nl "Show only city markers" "Enkel markeringen voor steden laten zien" ::msgcat::mcset nl "Show city markers and names" "Markeringen voor steden en stadsnamen laten zien" ::msgcat::mcset nl "Specify how to show cities at the map." "Geef op hoe steden op de map getoond moeten worden." tkabber-plugins-0.11.1/georoster/ua.coords0000644000175000017500000000064507647460220020046 0ustar sergeisergei# # a coords file has two parts: # # - a section that normalizes region names # 0: normalized name # 1: any variation # # - a section that maps a region/locality to a lat/lon pair # 0: normalized region name # 1: locality name # 2: latitude # 3: longitude # # all fields must be are tab-separated # all strings must are lower-case # # # region normalization # # # locality coordinates # sevastopol 47.62 33.52 tkabber-plugins-0.11.1/georoster/iso31660000644000175000017500000001261507647460220017263 0ustar sergeisergei# # the iso3166 file has mappings for 2-letter iso3166 codes # # 0: normalized code # 1: any variation # # all fields must be are tab-separated # all strings must are lower-case # af afg af afghanistan al alb al albania dz dza dz algeria as asm as american samoa ad and ad andorra ao ago ao angola ai aia ai anguilla aq ata aq antarctica ag atg ag antigua and barbuda ar arg ar argentina am arm am armenia aw abw aw aruba au aus au australia at aut at austria az aze az azerbaijan bs bhs bs bahamas bh bhr bh bahrain bd bgd bd bangladesh bb brb bb barbados by blr by belarus be bel be belgium bz blz bz belize bj ben bj benin bm bmu bm bermuda bt btn bt bhutan bo bol bo bolivia ba bih ba bosnia and herzegowina bw bwa bw botswana bv bvt bv bouvet island br bra br brazil io iot io british indian ocean territory bn brn bn brunei darussalam bg bgr bg bulgaria bf bfa bf burkina faso bi bdi bi burundi kh khm kh cambodia cm cmr cm cameroon ca can ca canada cv cpv cv cape verde ky cym ky cayman islands cf caf cf central african republic td tcd td chad cl chl cl chile cn chn cn china cx cxr cx christmas island cc cck cc cocos islands cc keeling islands co col co colombia km com km comoros cg cog cg congo ck cok ck cook islands cr cri cr costa rica ci civ ci cote d'ivoire hr hrv hr croatia hr hrvatska cu cub cu cuba cy cyp cy cyprus cz cze cz czech republic dk dnk dk denmark dj dji dj djibouti dm dma dm dominica do dom do dominican republic tp tmp tp east timor ec ecu ec ecuador eg egy eg egypt sv slv sv el salvador gq gnq gq equatorial guinea er eri er eritrea ee est ee estonia et eth et ethiopia fk flk fk falkland islands fk malvinas fo fro fo faroe islands fj fji fj fiji fi fin fi finland fr fra fr france fx fxx fx metropolitan france gf guf gf french guiana pf pyf pf french polynesia tf atf tf french southern territories ga gab ga gabon gm gmb gm gambia ge geo ge georgia de deu de germany gh gha gh ghana gi gib gi gibraltar gr grc gr greece gl grl gl greenland gd grd gd grenada gp glp gp guadeloupe gu gum gu guam gt gtm gt guatemala gn gin gn guinea gw gnb gw guinea-bissau gy guy gy guyana ht hti ht haiti hm hmd hm heard and mc donald islands va vat va holy see va vatican city state hn hnd hn honduras hk hkg hk hong kong hu hun hu hungary is isl is iceland in ind in india id idn id indonesia ir irn ir iran iq irq iq iraq ie irl ie ireland il isr il israel it ita it italy jm jam jm jamaica jp jpn jp japan jo jor jo jordan kz kaz kz kazakhstan ke ken ke kenya ki kir ki kiribati kp prk kp democratic people's republic of korea kr kor kr republic of korea kw kwt kw kuwait kg kgz kg kyrgyzstan la lao la lao people's democratic republic lv lva lv latvia lb lbn lb lebanon ls lso ls lesotho lr lbr lr liberia ly lby ly libyan arab jamahiriya li lie li liechtenstein lt ltu lt lithuania lu lux lu luxembourg mo mac mo macau mk mkd mk macedonia mg mdg mg madagascar mw mwi mw malawi my mys my malaysia mv mdv mv maldives ml mli ml mali mt mlt mt malta mh mhl mh marshall islands mq mtq mq martinique mr mrt mr mauritania mu mus mu mauritius yt myt yt mayotte mx mex mx mexico fm fsm fm micronesia fm federated states of micronesia md mda md moldova md republic of moldova mc mco mc monaco mn mng mn mongolia ms msr ms montserrat ma mar ma morocco mz moz mz mozambique mm mmr mm myanmar na nam na namibia nr nru nr nauru np npl np nepal nl nld nl netherlands nl the netherlands an ant an netherlands antilles nc ncl nc new caledonia nz nzl nz new zealand ni nic ni nicaragua ne ner ne niger ng nga ng nigeria nu niu nu niue nf nfk nf norfolk island mp mnp mp northern mariana islands no nor no norway om omn om oman pk pak pk pakistan pw plw pw palau pa pan pa panama pg png pg papua new guinea py pry py paraguay pe per pe peru ph phl ph philippines pn pcn pn pitcairn pl pol pl poland pt prt pt portugal pr pri pr puerto rico qa qat qa qatar re reu re reunion ro rom ro romania ru rus ru russia ru russian federation rw rwa rw rwanda kn kna kn saint kitts and nevis lc lca lc saint lucia vc vct vc saint vincent and the grenadines ws wsm ws samoa sm smr sm san marino st stp st sao tome and principe sa sau sa saudi arabia sn sen sn senegal sc syc sc seychelles sl sle sl sierra leone sg sgp sg singapore sk svk sk slovakia sk slovak republic si svn si slovenia sb slb sb solomon islands so som so somalia za zaf za south africa gs sgs gs south georgia and the south sandwich islands es esp es spain lk lka lk sri lanka sh shn sh st. helena pm spm pm st. pierre and miquelon sd sdn sd sudan sr sur sr suriname sj sjm sj svalbard and jan mayen islands sz swz sz swaziland se swe se sweden ch che ch switzerland sy syr sy syrian arab republic tw twn tw taiwan tj tjk tj tajikistan tz tza tz tanzania th tha th thailand tg tgo tg togo tk tkl tk tokelau to ton to tonga tt tto tt trinidad and tobago tn tun tn tunisia tr tur tr turkey tm tkm tm turkmenistan tc tca tc turks and caicos islands tv tuv tv tuvalu ug uga ug uganda ua ukr ua ukraine ae are ae united arab emirates gb gbr gb united kingdom us usa us united states um umi um united states minor outlying islands um u.s. minor outlying islands um us minor outlying islands uy ury uy uruguay uz uzb uz uzbekistan vu vut vu vanuatu ve ven ve venezuela vn vnm vn viet nam vg vgb vg british virgin islands vi vir vi united states virgin islands vi u.s. virgin islands vi us virgin islands wf wlf wf wallis and futuna islands eh esh eh western sahara ye yem ye yemen yu yug yu yugoslavia zr zar zr zaire zm zmb zm zambia zw zwe zw zimbabwe tkabber-plugins-0.11.1/georoster/nl.coords0000644000175000017500000000064307647460220020050 0ustar sergeisergei# # a coords file has two parts: # # - a section that normalizes region names # 0: normalized name # 1: any variation # # - a section that maps a region/locality to a lat/lon pair # 0: normalized region name # 1: locality name # 2: latitude # 3: longitude # # all fields must be are tab-separated # all strings must are lower-case # # # region normalization # # # locality coordinates # eindhoven 51.75 5.62 tkabber-plugins-0.11.1/georoster/ru.coords0000644000175000017500000000064107647460220020063 0ustar sergeisergei# # a coords file has two parts: # # - a section that normalizes region names # 0: normalized name # 1: any variation # # - a section that maps a region/locality to a lat/lon pair # 0: normalized region name # 1: locality name # 2: latitude # 3: longitude # # all fields must be are tab-separated # all strings must are lower-case # # # region normalization # # # locality coordinates # moscow 55.75 37.70 tkabber-plugins-0.11.1/georoster/colormap.jpg0000644000175000017500000046624310501561725020551 0ustar sergeisergeiJFIFHHC       C " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? $<ը[ر8<- ۺ_;z֒+&MnE-guR[Uhu?sYO˖' cO֙[˗)jɚ'~1NTDP©UcpZ1g1UyWaA֥m>!a0W 4GSKLj)go?J|rQ f:#(̬si4`r>RKk$}dT[w P"M fh@ۣRjar l5.s5u(M+6MʎM7c<y@g$RZ^^[tGɎ4JjPrp}ijUKד|b37aP~G9oGm5 xS$.h>:NSIgyOc6oa6d% I`+Ϭ'jZ$~٤En2OyǠ#^2)Wvgm{r ;[4q{'@8yJ]'K$FXsS$n{㇅`[=1\CTk{V.mfͽ˱$wz`drM$4To:4x&XgW5' ؋Si\c!GWxSY=f'S{{Hex6H+cе? Oj1rDїt.:dy4eʖ?oYJ#ƺ sJe6:x1Jm^-4^񧆧].Lw{edBx+m^])Ec }Ib?ޣIik"yc'Ifk՟+k1d-GĘ{V u2:%!1I}rGfGk]f 4+6'YSZdNMM. `[(-y}Wú͊ . ۡ*TdcEz< o/cԯb]A\ÎC튽gP^j6!*ۺ lUW2yKx?~G4k`As'.ZcKs/s -#/KW#<3f VIV{-~!M4㋭.es|,oY<=u&"tVC|]*WŬo/[ r2H$9Dlc(b˖@NncXL(*w9х]d~sI8whQ|T[Cinːnܮbi= 5uNUL zB}.Ƞ9ѭ6Ƶxڽ41X*M{~1~ǿ|;[j6kBYny'Ԛꭾ6 iuݒp7UHlʡ27uA&5e̙9"l)F!"j \.u"-d t\mSM~f$-Xһ> H^=gFZVMiLNk5&f,qؒqҵS;DT)SǼ_*izy~&kM6MFIaA #ی,>0]Ow⎉0*G7&7Lھo mW˨ʆc)3ǽ|ŠxT0 u/:7:z;vlN9]UFw1$axʗzbVUImp kox^d_ZMD#=+-?m߃~Lm>H"FTϯ:}3^5~~զWkQFʃf*TPx#AxjUrŠgU8DB꧌Q_=Ofk߂k3c \fxGL~ˣڥ0ӬH#?/0=x #x: 53<$10b%b_ql? ݆gi4ڄ Q_^>n^wsS~7yku7dd9VS_> ۧzaFsy?j&A7b kfpwzq_v~!X+%u8 y {₰eΪ;{U Ώox3kwn[nY8ٌ &ĝޱS|s^6Ʋ[D*j~8}?=(Y-@vtTOWFT`< tZ?Zz솟ڙ+iEKK//mS]ϟtT}Om0ˏn.ed\k_qyq)ݺ>:M/ZH#Y lKARn_q~?)p8k8q[0~_DmKٶc*^wgcw/Hӊd \F|W?j$8.r-`2sBN7^: }劵ϫFr)m^FLR+cK⛕ɑTA9 XkF1#xU1c|\fw?gĒAs*u?'Ryj7O^Ekd0%~4Dqd,4xȲw5u;L6A'l P ~+NZK+ U'ԡn96cR ?7ә>8!`\)|?ֱ~ާ['q_ij68>r# {S<56]LA"9C{M`g,ҴW7?DkOm yNb{ Zt_Kcm΋}2,D 7aこ]& g_YXB;U<kl昚݊gݧJ2%b1}_&u?ۣv\Aw׶\J i6Vy`UHoRCt;ԼJ>[A9cv<1Y–v47~T3}[L#Tvat߶oY\$&Y1Í ]^鲳LlATwmm,I8$0 9k7*饧L_.<1/y^w&IAIuKo~k莯V: OPFNko6=Z̹ ޙsVTQ߅V_+>$SrS_JK'_ڳtgr_JU5L1jb?rmc=8[,O#Y=.U>va~d~6^Gjo[~ӿAx ͨ-?Rn5%E,p+OWt'q,tjhld-QuBY?MduܳzqP]dI0;~xKߴ&ӼFb =ckl/✱/M l?rTYTW:uRi/>ڏ0oܝ YiW&DnX_ߵ/<=IDk0RXR+Ӵ?Z o$1*LAvTjGގPQogϧ|Mğ|ձ0˥I.e>>xIDe`IkOI+ºT o)=j*&\Qca(| sO)9zwqJ n.;ĭaKIn^֓K=վ!^u+ҭ/3'8\כxW?o(m Ė7K1c]i:s |Z48uu./ !1ʞ'BMo9N}*p+}Ir"`AUu!@mض*p 3Ã]%㊂M"̴2 qнއ$3j̟o 'OnkMLr0ÏRǤ( #-Ɯ7=.uީ͒q |tKGn<'ӣȈ@@ZbA0ՙO4%ZhkAx"E?֬O$b¨Fö Nc!R~H#fzmҡ\z){G#g^1$~Uf }nSl*u]bY-=[?Sb^yLs#}2\T+9hX," :h50fdYqns_³ena}U+9N;ߘcsRnܶOr+C0xuPnGi 6zL>j0*jHAziBJ4̋j͙\FG}@y wz̊hnasr2 P䋝1V/z\H-cU4&b1،՛}IBW AdOxĈÞ-b'qGN$^j$ld)@bcCRB@>ԯX֖Yx8#0(LV0$R3ߚ$v̸%cU!ڬdipxZ't4iKg<䚚)7|A f>ZӗRxqF ϧjt(WV@rE4:'XA+8ǯ[GtSKқJØ( :yRdžP@s~lt=9dW@>;{U3M Ih Nx) >ydqnғzƒmmrjPv>VR'8󩣹;@sӎ)\,h,,r8G,OVx̃ } r=\p`853/ܝ/cT-+}ޮֱmc`~$D\Z/2q". UL caũEVg 1]ePm)Kdg17V9-U d'ֲjr0qphvc5&1l˜S,q0?dɩJT<ŇU XcW3m+A R 3ze^'*+m?AQ[HK:HC8kitֺK430 ֽ =>tekh #&8snTYڗw*`1_l%g`5jMlaԡQ,vJUfL}?J}[{/n# :;g3$D=O2Ou1.$Lar-,tOݷ<;{UW{[т%6dc֋xq/@Rјu 9cSi#}uo6{IfV}5*4p I/t|UnpmIlpIמ_.5mGB-$Vkɝ4;l@l+KOokoa}YʒIk;>  vrV?Wkʱ##ۼeRĎ2I9r)̮9k> .4;mc;o.'=AxP5ht>!|$ӯ}2f[`jx{S/ IjM;r2y,N^MOXtWlD{nH3j\3i\jz>cY51$ژ>Ɇ*ga$gG^YiM*T H?+KxfZռ4ni/ pFNm>\ׂ<'EKYH;IWJ1^e*Z>N]C^S 4p}YN3܎h#My:+#1$6.F23\[|V69 dG#玃Gu/LL:rUbw@OYir7 Og`񗆴Krb><x2cm %e}`g8ڭx▟a2 xF|\Y%f[ (PNY^;k׍'9*t<%lz&07ͦ2`+Xv"(4| 8AP~'MZ->ռtubm-:V{~^41ԍ7:}$}K3r8|DN$U}ik ^||FIQ湻 žմ9ˀ` yY >;ƺ"{)%9mCJAL|% };X= pTTH)c#VKy5L]pKΕsG1EW[/#38+6'X$ldVmQ*&09E[<Զe x'NAԀn:ьӱzP<:R4qqRcڀR6\JU\|xGS;-v ;o1DAs+\IE O T,])T9sI].#U:_ٱӮvoZ'_k ; tH !94|[}o$OG#1P}~R ^{ aqbT(2C3b#ç&חa%r&ዺ#O7:-`ulP7D/1ְniХ>' IsmAӸp*kʴZLKfp؊x^0zl_|;_?|,2H&(gpH'Է<3$fQcڞdiߥc>=OBd̲qԜC*AJ[:KsMzkZ.Y%EmȰDG%Ͻ!=}qZdFėLA~)թ虴j9Sh-nxVӣyf`^wxⲼczW tyr$}gO^Ox&;71r^[* ߶z+?-.-WA[yt+R km2yb|j.?6V41%~{|hi[XobLfBW% n)[X'uU$bO !ƩM26wD}A4|[\xIlp9fyl! )OnԤh/Fb1en?}my{ȊZ?+ȭ> K y$=Ҷ CTGa<8>YrQ_mGEhzW0,9Vp܍Ѽ`?J'~.o >9#'N+bMOMcT$zB3P+ǡ2X=bD# [\ҬZvx5ui%ݶTdYXތ'ΰzdUnpܱ`^Uce85`q6FHךA;Ԟ"[xG24g8^[5(9&t+!ehNYsj9A )$'qO ' [H"`s PrqzURD|Qv+" m4'bJ^qiAj-ĖF(c."i^MzcbBmU#Az\q۪#4VDxƌ۾QMsr611XF:VnX$qQ%6XZȒ5 ;gXɕ%J#`=Xn8@\N8iB $ 9'?ƹO*9#ѩnj)s}7&v˞yEs~B#L1+ ]@?< mFR+?Rc i \۞ɬH5!fHbF[&oq\ \6FHpA^TRUؤRˑ4^娝xͫڶ! )Y1H9-ֲۚmى,k*\9Qqv4G;19׀~Gl=],j6D ϖUU`Ur5N;aBGijZoco{UFx$W|C>x/փu@9b2K`$g"'1G&:!S`GA k~=:mGj<6RLl уFsv t`twH˸#p8ctjJ Q+ӌmݭJ? xEw%ב.LGR;#ZNh5Z Dg#Ʉ/lvg纸_K O,1t;VLPKDX3G9c8cOH|`q=su3|QH$p9N[3"Fqgy4?2XZ2Av\8#`dd} ^_~klnP>ZxJ3q_% RGy$eWt9 F?p>׵kimu{gy;@';xh'ڽ?E焴XrTo,=rZ,FGS#* w+Zrr:/q~N nn&Gs4x7u ;SCp 9`3WxHxm_ˉst=r5x6Wl%['<䃎kJJK슊ϝFcE, }*$$7/b{zW m|J櫧ks*Dn#)8 @(?{[η *TNy\jp2]H:15򧃠umh6ϛqsn$3ӊ_/ 3kĿv"( bްuUNU`{\tܣJi.>èKgbVD.I_|ZKx%[ d}+;_l[j诶C9`3]5o^NcUc28!\f x8ҚS9O>yvVCǟ~ j 6t<L}_?x#~ڷJ2Jz TcHZ\V:ژ,wAq<3>#|;Hdonlu,A#׊\y3oKHs y5 z{/{KkP"RgAʼc4fFoFԫUMB>"ZCcGN [i 8#${sھL'җ>;VYԳLRwPωRm`㕁zd||}mo< 2T>ݸSՙHUYE3Zy"/߳^~!iݺ2^T-ٓOZOH+sykՀ{:oϊO9g^UZR?g5V)?#VOZq6Fb)rEXR1*9UKddx c;žĶY4SVBJ!]ܣpO3`9Q'_`_6h񆡨aso d(a^ JwhHAE+#SF)ĒO9=飚T;1P9hc- tsAȣ8K@Ɯ6ө90AN1@!_J6Өq(RLQuc=)vq95-U +uy'tse Ȫ "ǻo^mcSdH t0G'5=eLLS=Yx_y'S}ml@c$G]/W)DjF=@Ѽ) $~ Wjz毬ڞ5:l (f8N{-ʕ08_vwb,^E̊>}He~Nݠݰ|\RW|pJҔ,lz$z#|q i4!j:dLjnݬu60F'ڨN I'[QТN)3tDgOƯi7(٣jm)I843Op[s@^jZ`8" ǭ>-m#(?>)etAnaWFI6FUxE IM $@I|?{XՉ ٭X63X ]٘ t+C Np21ԗ#C N;k^rΘ`pp?x~'幹=RTxsEE$vN>y-a7lϷ5|^3-߀Uu6vcC +RZЬghnf2ŋBBH3ZY[I%-5M+#- YKݨCp['%Sق G+eѴ2^1VSlcqgh:=ѓO"/G_Ϊ8zUJ ozj^B\۪+<_i6q*MNλmctm e`#5? j%Ŧ[C,#vnrBTUn9έ6'p:Rl%?0E?/U ;5i&P2X7X4* 1WpqSͧ(AA0L!.=Gw$jO^F{UqGt4q-_6=W]ֵۃsSG'JmXg]@c?JK6]ۼgUj,xYJj^m4fpV> I8G߃CJ/AEcsޜ )J%*8OgԿ~#1u& %i׳4{[|n'>޵j=:1xz0WJHJ13 1+S^""2m^?u -5q^+ eLjFA;6:ҿk^t^:9ۋ#o2juX&k=9)8L±u?:aft~R>1|<ͮ 6<4l?tZGb{%PY"r;~fqd& @`O@uY?:4fi@f Vӯ5keJ@68')ͮ8aSj1+E4[UL;O C4.ܠ{nAL[K$*-mʽ:v^9f\eA&maޠǞHj[)nH$%T$d $¿x 7 0rzTUfzGv>ho-}\} V1D䑓{צIY_E}e/ 2 G_Ukk~0n[9#=;խ;&iwm88 g$fy|ыs§rJcYU*(p-sG voIdyΥmk"e \51%6p4?F"z% '1㿵Hڲ:$n1־|k IIسHt+DwH%itixbis菴/GcM_ܬV'jpOJT>xK6#r c`ۭ|oruiV(%2nxn<=+wr KoHե:GmSCJT̽l~ OOjv{AC3Aq}>GF&iq |↢;FpZΈls]TsJ>E(?䝻||Wj_omnLr+yh8l^լl|sj@{ bJY~z\?<깶2:535V4^n8n^}[ U@|#qWO;c ynwfmOhUJ2GWb5IIF\;}JŋLik&Oi'uB2ȪOai&'[фvx3q8ǥja~@;7{Vlβxj/sꖶիꏪxb7tM :}+F߈, bpȞ+ kǧK( pE[<7㩃j~ a̭?¾V\1^u[{msqV*'BO]}ODu[]X).nynr29{zMռ6kkdw d_R#bEe`{^->,./tED"Qs8py2k\  Tr&"":a3[[~ʲ: Zzޱjr\W3D"h`kFDdk)7DQY` VHnHhXFSo޾eZ3G)Q^h}"n!Nvalu"rSUIJh].9r8ּ1[Hv䢤@ï F\W=wGYEwy(J2)*Ug>h#^hB>= Bu2O֤o~p, g^ LԴ?ZZqy,Ďv39o2,̱s1`=Ќ1tpt&[xVbN2텐fye9%jAڼ𖵦@fMaG_Q>/{&iZ|1p}3]M+k2sl%`0,y’ߵ{s{8*zQ;#_@|xLaqvN'N8#v |`2G*H[z݊2 ;B鑟b5J+OdCk-ݰpXAy8 ~7|3=͵Ι(@!#SFj3xq/}iFH29PIWq5~7w{]iYiז{̼cIᏊ~wsy"^tk swR)/^U*n^#>8Q5GO^h+)3E@n!}kdQOVIˠCd-xY7¸x翥yN {t"M&|2YKw؇)9f js -;ioJ1V#hUv$d:T85 ixJH " \ ~\.3KFj.+zL{ӱF3ځm,tr<{яzѰѯ)DVvHH@8ֺ> |A%ndªcYʬ!qRM&O/+co';u[_֯o`Wt͞;Zv\ YHuZw6u( $dO|2F ^{*5_0 f~7(2@m=j#Hi-1*gZiOONS:]}kVMV3NcмD>UFp+Co4#'Jx0Ee%dt%T{v$J4Zu ź ~5|{ܼ>t_a)T_Xs{x{HK:HYԮ$"FI;p+'֭H}=9 LK|k 'y z< БǾ%խ ɪeV;qG5ОO=C!U.d,ȁXqԊ}L yC>A^gg;z;EGc&ǸZG9[e(zcַ Z pk'+ f`c< V|rw]ƨ/.dXۂ94L>Ww8ǵB vݫ>i$w.TgwQH" b8.Uk ygbD5~VeXLLv (Q`ޥḒPR\ngWF|֕::陘"5?_ n9=x:Tn $!SѧvHv {eA3W- KpQzsfksY :W/.,dp1dc +/Jq%Dr?7ݏ_k- >`[2GO 0ݒFNǵzdZ6rDzQx6οTHW\֎SF3cK U*τ-5Zj.W>lv<>ڣMhT_ =R1I$Y듚</ 'zVkmWw{)n>jY&9k?u\.djm8#֫y_4"n ˋZY nOxNQkOr?/ޓzh QtVIb-2Zqqc2viCm16OlVpf-In0Z b l_`x8@cDK-&y &y# d܏´k>&It 1lwx{fpshSb;?5=4ݼfc;cYקM2xG/0 "18v֊"b3ןz7/xjCBb Gwpι׼t˖R2'cܬ,<ҾIֿZo+> _42%gt+$Gneԯ8- wJXJX;ZAɩF@}3Ee9}S`ܽOCͧ"iWxҽ+:g6 .渔?dP&mݷk)ktGrJ]ƁO_ȗR C"r8['VSS{aT%}B6x[Z+K>̭r=VfxX_NT2'yl\lJXc |cPxTeW7j樧ʏR3=Nٖڎwoc̒E=k9hxt5Lg#=+O).R d4F&_Tg>)0[ZZScR/F{nG6xI 6I㽻mMzxWx>s.lXy Pҹ4錑Ha8/pM*:,G#gdMr9QHJ#vib%JFz2e!nU@ojŒ 5 JHq&n 0OԹ9=ΨIjnZUvWc?֧ (Ywu/IL>cҴmo%.21}J)jkTu&ofդS^~8t 1ӟZKX1ͽHEGzĽuZE$#e~Auzqs)fl[Sڼ{x+U?`%F[g3^Q ±ȳp)Vt ..]jzḩtQr?'W[x^&K*f`Xcֵ%eim߉. 0iſMϼm F z2 $*rxNM#G sgv FvfӭghϧZit{ݎ*Ӕ8e4G w~vC\&e݆ݳ8#ҽS׃ ?ab<668iH!B c9ݴ!v’U?s"9%f_t=*x-^ĺ3$ e=:ִKgnn%7 [u]mxZ_鶍l^Te C$6ӺkZOGz:!%pkut;#B,N/(GԖkHѮ]@Aa7cN.5/Va_6Ub|Y~mҼ*=STVҵXFqޣ5_|C-5D+%ܛ^elafP9|>.N"WS .gN΍ta )w{q^yq|BztΗSMr;LqdJ|K5soؠYW%H$=+nx]-#^ev@=ziG;XXFqQ#콤xk~EnQ]7nV8景|)M?6(Xt=JƎ4%0I%F\fմ>\jޟIoi)%eqhpqzWeǟ5:m.DYmZ6Y'jB HFx"prׯZË_\818$, sg5k>*jm G?G]KK<_'e>gةm.l[K!y#q{v=FVPVd~*񿂬 sCkHubYx?vois+8$}kꤩ)켏(Rnmns x\lAH3nn4Ksђ]Dc@6c#׊;EFNBSPHR2@sDGi n 4r,uly,+?ĭ?75;e6U y_ËB׆AcN+?܇͚GS<̇lJ顂]],V:/[˱ 7L:R8٠e .+o<}u'ڑvϮ(V9m%$V_#ޟR"OW! [x QޚBrx =q)#I8=zm<5\HU.c@!O,I|Ҽk:5VV ˃$ZBNL&k 0fh?gIH,)ek/u?x|=Եu9$k/q^N-^;( <9(]N =Gj~Q4TI;vfy7S~'(Vq ܮ.8;-G2y.eȈwv\x" m<{e:v3Ž̷Dcmj4on.l""3y@=1}j7pYB3! k*6%9r7*sڽJtogk5us~_iCX$g8>B?*uτ/]<)W#i#I#[zotS'eC61]*a+ygўEk\ѹtɢRN{ 3⽇~:ZkFIT9Zk'+.tiCߩcp0S .u~ R+dRA\cߧX.tm%qxz+9ntf1Glax<OƳ,x.A;zm 5TlO-J0jw :n\iHӴeq$>&>Ha mOӊo cXX0MUIaev B\Bws҆QE:rmr'6=]]~lYbߌչ/m(p88 RpArcɛFE3M徠C)PWgDvKԱ3A5,5%)_9e5 Tqztw,brIjW,m1[A֒9MBEzl@^sҼsNV;9o|\GpH>*{t5[{7ukr<]nTa jyuiw ^q5 |Ya(ҩIYl6k{p_Pq*^X]ʗ3et:OZrc,s?ΰ,􂗢o89*G5^՚kc9ڝ5ֻXӑ%hMNFd 3ӌV3K,pX²mcm$P]7Mqx8`߅uMo*9;@ϰiu*,6P2GaZ\Iq#drv`y]N`oSGw-Ms=>#8[+64џ= h4qo6f t|ke$-Ygmtpsj3sճ95k4y.9?tN|o([d2}y>*iLWqbᜱ'M79EXvQ v+g>9(4D~ZlsJALR{{}.#]|Z'*xo(JHFOiYAє/nrSU}(3y*2.@L,2ί8TlΤI$NYҌ${ؤW+W.fPі*H`gmb>\IA+sM- W#c&{_;[ܵ$6e]'gM Hޥ|JvpXrl[HT7?*I(;0+W5_ͭ,VI-+hSһ9ImcP5'sp:=*͖=!e9 z^ïj_ | okoOLb4V'JgLӅv/5Jq*3zCTekxQ-`bX_}E>3=r9w 89 :mq}A4^Yk\ڡHιG?S8F 7xԼu!F1#2ѰjXՒ).Q\˰z^y䁢T+rՋom<һF$dW3N)M+OB\/fG=+_)lW4]Iqh~' cƖ4³:A=1hzF(DqpI8To 5DYN8 qmh`8?hݙdǽidEǪ8 z*?1iޑF/ιmudP1+\ܳ0ʊx8\ֱNG|,$`=+Ӽ"gu4W=z{{m ${,NT VrUU|9VJ1W JN/Vlq<8D$tcvm]Ua3J;1 JO5ƐN\\,[X9 ^ )亏s fsCM[9v[⋿ :$c)q#;+D-C[emɈ7|纺u(22:WK/jխ!5dyv @RN }' L6IoϛRi[cu==7MR ad=>\|9yֱW{`U:/5%#|[>M)moGb`<k<[VP)nfoNs~+ǥz^Iе)dt֛u: މXm )%1?17:u^C:vZ(DX;Oq^Ko[C0L&^0f C<WV)娹5[}Q̰ӣIvp!oO>Ԡx4Ӈ D3ۿ<ׯ?֮|eqvVe0p+a9w)}6ÒiwW*Le˞NQҾs C^أLHGn>8KQ<FeΛ_>/xkg%t p2`8PC_E⟉Gɂ4P'{\֣}zo.) He{Yw>c0*c*= a-7s} ϐBagWM~ĺ~./e2ɰar}+/q5p]j|'^RvBy]Kss3Y1=5X'9ǥtv.)G=ii@ ( uK=ȥVDPYss`MY>aymFG y0*+ݼ/pVXHa<''+kd~M4NJ&Ÿ_|$US% ^'.*T߻cpyA*u %|7̶pL%rIa=I-/@|Q}ʈ$7}pp1+qO\Z>:b{˻{G;$ӥg7oB4uk÷$HZG29}^W*HK6GxZXYaMe,rqJS G,#Jԁ ;`jN ޕ#$$3m4ii3 #aF<tT.ZjB ]~ͨk6od3mFy4V^__|)Gz>>7kT__ʓ?^Wf9U7 >jjuo:(ukXGUPUۓJuNw\H7?NSmmTsFNWn2{s\#eiK8n{ʾJsm"Dn ?To/zZ\KJRexi0xES'^cXe\ϲ7lykŒܓ?v=_Dyږi]S5K˗/; UTn+v=W͞8yNx𭝔loq#uæl!s,>(&<_5?bghzBp{Uy/< y?OJ:By%=j6ozw|4|ǻ*Җ dy?*֘wx ,Hެ4$0cڷ9E= wGz5u(c8#=jVF@{WAk^@>jφt72ij-a5yӍZ?C6GI"tʒUJmAd}3*`0NzZƌɧZ1xfi#8x*qAk3#Zv9́lIAS='U|1I*|'i֑vMYЮIR&ӁS q=$ f>T(슌9d Y0 Զ]P0>t'@ 2{T:˹r :Z| T-ۿV+GEfhhX)p8x֥vJ%qʻ}ku$=kZTަKwEy-.d^ jNAuiv & ē$L)cH]͊J6;v~chw" I t?*5!8lnBR1*Đ9v#]E ߗ~E+׌sYWʏٕUЂ2}WqWʫNGZFSӰ%/" ǥh]\Ź <5q{c}kqJ17dwboloi-'1E*FzAU~m Zjolv/__oQPND?jVG܅MIa9ڣVj01>޹z+g{wY G8P]y|ƹ\̖i s 쑳yaNHF]F$2T~٬SS+]R춚K|7ǧIj_jcF B틳IV# IgkV_͐sޗ-ŭkg'G-ɝC^>5R\TμbRvEp}&5k;$rp1}))0=ZD-$+ïL"섓M ʉ=}~xt{V=zע]k۪3g#j^E;Zu&at`+ionl#`zuj䕝!es-tY,]2?J˲oS tT s'+7VWvsk䴪B.J5,!sMUC\&@vAW4wrfVGh|U_]A[y-fv<0>Tnꮤ^KDO[s_DcţpR R 7k]FHukN.A"9Qct걥>CϤ8%dsJ`LGu_)]qwwe*]7`Kː-OvZ.YL."z/B` n+Oq4諳x?e98DnGz_qd7y,O{c=Gz/ Ҳ@;ԅ_kˇWkj0AILk'x;ȇk$=z{:)Ӌ^x{Cy$fR£H\{Wu}jW,'FFw?XдhGbw5|4{uPFs򤦢GiQ\y>ӄ|H{S5UaD!73q?z Dh##ڻJr=/yI#y|˷ Y' ?a6i; y;Fx1j-ǭu/魗Zf˖~5#mM⵸Yc|U硯0jZRZS5iӽ)g]{O <0䝪c]/>%h~lϨ:E-&=ϧ\N(Z.3sBJPEkPGv<8?¼W񿈮.'[[O1YX=}+jյ0,a!%W*nP5;hvsz|vS9',r}Mzit}i:n䨐`tGoyePLJo"Z;B3ڲr8pJZaxg0-{w{[ WMUOUf{` G#?:K w:Q!ۘdm}WKSR&H]ޜE|N;&ZLڎ&\Wt ^X;X|Urw{&ԮA(1ZxQѠ"&QʜcK-D\30;7]=8N33<w=ݹBB+јzפ@>/Aym޴bD\x?62q+t?}1qF䳒paּĭoǞ"%(i؜q^Otǘf+ WݏAmǞsQ*>FWx֩[(tn+۞qEP%ޤ+՛]5ꃍpϥr3!6p{`WEl޵hFb•ITm-d%T]Wh]-*2k7W kOȭ='W.~Ӣ2 oqf#UI#K# x"K,n]UP^qγ[P)sXMUZT&Iry+Z# ]x_ӣeYXq5?fV>$dHb0~S0h_OaᏛ:~;OF;T.5LSRA< a!s@Y~_% S6\Ls!E qnno[<ɬO. 1͂O9C_8Ygee8 kepwMZIFK?h~.h#77\mYr5_~;զ$ (wcEq|[$f/'{.[g޸xYv5-n*{Q BFqENwv1OLzRbSFᡴci.M QNN Hzq NMfq@ BI1ހHњQҞ"8XCT:R88I™7 zUGVo.eW{ ~HS9V#mcgnQ{Ա[+h8fY 4lGu#}]pҐ;n8Uu ౸wE4LS a*iksc'4\$ C2сuO|s]j\i2IʈeJ`zV?ώ6> Zye*>RG< xNm$PN1IAՌ}եbXF~KSԵm/4[ܨS)ϭrW5/'َYrA޳4o$sj77Q9Y'u=+5H-d)+ &y44K ?*r=E~'_[i |.cF4;J;VBJ\lBX _[9'Eu?tL< I!YrrV4bTrXaY&_:A6TY pK9]ޙkd[2yT>koC-tvɨݡ$:#UaP[ңWR%JVKDxo*ˁ]}(V7:nsKuu>i[õaD$;?Z1ؚr8_gI7}+Tn G#*g}j]CS=ͬ I<Z5B{Cci\^}ZZUW9F؛':qQr\B]#s}im"0221R7v cmZqw m$vTA;RĦB䚷8VIc*ݛRBӰњl]sHzcaVmCݷ !$Qҫˠm dWI~ ~> h06cֶE- sl,G_u3@coZ)n:MՓQ9|?tFiltcFH}ބu}eysS L26ŲG9"V{orIb,i?0xopra'qE}6]!{>|H9SVL2ӭ7AI'`Zݖ=E1nx(ؤcYVH8M^:Tdc*:^- ci8zt*anb)pXz3RqVWPB9XU dO(#+'6Ro4yʬ8촛U5P$zW.Kn2:֮YkڎvIT͵.-ʷ:B ۂ8\ d2iȤ7=,>K1S$Ꜻ$Qn{\ЙuS4k>N$ qCA, VN?9Պs&olqypIrgunn<cXW.Q`[YHʗ8$ 'qX𪔚6>[<`WSj܁^hC7XP[el4okW&Ӕ*͈)$w@C? "O WIo \CMgRѤc v14;a eY#E'`A6k'6kސ pT𕭀kk 6ݘ8sք\A^awztHr҇P]QI^-Reh]?P]Q\$rv4HFCqЎبqZ۶-ɹ򞞟tȳ)IGmϭ6`+xxT%=jx{LKT`:_6h?O:XHR9$vy~yʵQZOh<.5ʬh\W%NחFy5y>ff}: krai\}֋3qzb?4u^Κ G'nduumQ̗r~nҳO馾01J_x-tT`NkR9\I@\B0a?jƅ$O&98w(?E8JU*xNxNmoxiHXfL >DPaCQF;s끟V5qYM:S* k8/.K;4I&`f^X [hao<EE2NR7qrwWo.^V!;Z{fE'\99V f8 ԱnE|%Bm+pb+_3 rynx+7k2Zl,p30x>٩4wP42_h Ups\[w#w 7^麽]H({Ia9PO,[_a1*l޺%Ϙ d?ăO^`:zvj&-ǪzW'xn533\Ku$ra\ ەA<Է0_G#CM{yj<#˩:_mXIw6ҼnEDH}Ͽj*Tcgk3FK!KdnoZ i0XK#|E8O0F׵iAk-IX$4G= #ils^R8bZq[q[SXԮ^kԴ뗹O;2JZQ\hbq܌p*FNS= qx-y'5>ha/͜œ'-Te.s=cj觴ٿvYShq\Ͷ& Al}ɪF;VMU- ZҪ%Jy 08>Z¾D"7hc:5+y b5ކIj ֞uQH֒il$%Q(1y%eGU>mhGb1IxGH"윏EQ55{p.98o~9 |^IkKoJ6֯6 RUё:##3]"P>%aX`H=A^zͶLn-DY[\v.;e6e+OA+u[Yw68K0#:Tx${ߥK+zx}]^ݺњ9tc.;Һly -I'& Q@ ékr,Tv3_*f~F.C*Vl6Jc=Mqׄ,uZ^Fϵ'!#TL)HlǴsT,,/3(*A)s߯5,DIJv1MUVOxcJ&Sa~\N2?ϥ{i6#\ͮN8R_z/L7zQ*Ӕۻ6(+YXGÄڞEk;1 ;rϥys~2|7}}dqy`% T݃yW׆]kKgLFi#ڿO:Rw?32a1th3ziesQdvh6FHWbWVҜړ'9rqJGAp~)M!SiⓎ B3IJyU LfRDzJ9.v=i8' ǁSH# ]ӄljn|p~aXvwL"|g 5 y0GfNyЊIodtaW=C[(QMu, =oDřm%[o/2h` '}ͼY]ins2Ns_/c,S֚Z:ciRmE_^6WQF3}F`rl$OKW@iK?VUhRV)RR95h -_[YLr%8O.5̧$pҶtp0ʀ"q{{U+/ 6wrחZȈ2HI+ǒVI<+ԠmҮ,ŪDPj3vow;\<1Pk su.yb9=kFx dڙҾw'__2ǣ҂k}3up(_˷`?ax9ZY J$[~忑jqn-Ťu.DÐy{[]V-́D@;[J@vMMLGI?ҿ4ѝWm40cVhwi5{dF {N_ F2BWQgs 6cTO)")Fq^rQDZR +P:pJt,a^X#y>º$<$Չ"]=E)bOSʮla,TM ;9 0ź;e H5QgzEFi Z7Io4)9XI.A? ͏ʴc]ϱIc8gwT){cOҚcKu]t֐N% l˹dHP4&"oEeB ʜUhkݶUO1ڬQ%D2U_}D%$ W#wN|EDry=5JXu Kxpsfi3s!A)r# ǖVKp2:J8ː1=t;1 ڵCk=2 1gάͣ~C5$yjRex<]S;2m$j晈p浅~ Ir L攫AnP0C+SbIF0)-sC~ֈ<"1\K6F-.k/oM'q8I1tO*?RUYE"iqBIJ-|;q+iJ[WYƖfgc8 ZkfdI^6c p$Z,nO!b |GAZxf2D^x-m с!ۑ?Jh'hS9i6Fq.z4ҢI$XOn t/linL0Dw빳ӿSi(SWlRknȊZ"',’8i6R˧E弎~S{U+p˥ؽohi]R[X]AvrGvqߵ6oMslk;T/:wu*9'8VZ^ky[+L##io4ZSVJom \OZmHdVGPw1Zͮ_R쥣9 Ij0 RZ 6q bqU<rks>&-Mc<`+P3LE"6e8iZ5; =:֤^gV-߳ZbmKGnz5R}JyovO6dO+\KGPg-c,oqkc7|'9]>.0?5hg qW[/$7 FA  /drf#Y aI7u<L c{}dva^4Pjd rno~&DŽ&xtlu)j1WoN4yޟxnKC{^#S54 7!U}~Oxum% ;259? 'lF9k?_yytۿK$eWVcL S 3ھ%d|Չ֍sK)F8B CB`I>ow2Ag G98-氊FJ cJᯃ^Uyj _Ĺ\-E^dl1uH Kx-L;sN;Wxn#ksdbLcn1]xƺƕwor4A[qns)2HybB2uUy*g*`;=_[6*8GN_K>ʂJBҢKsp.n^b7l&TY6 ~]`$T8ǵ5/R2;撝F*qR=)hq@4b#iyj$sO0T.$j)kvf[MeR>!/Ϡt֢+dM(T26W-#u8}ޝ,}kۥwE*r{ɒyIb{jBziGJp``sNy#j6yQPNݧ@ȣQun3Kҁ;oh8RM8 1ޘzSWi@ n!bV;GQ/6CV/RH=ҵK"s,dJH)9Hz^}|PJOGvp_s ơ%$P ; c%Fg.v'v=cּS-Lj#U #)'(p0 J-͵[2#DIl \&G1TH`]:@d`18?¶4{AmBv`:p:UzؑH[xSҤh]6sqϵpJ:tʴz#|#se\DFwc8?r"]4j K$WSɠuwZ.`\a݅*9Tʄd,<ij#Tݟt MaNuQWﴩt}f8x4VD>ҀyWyWQK4k'N6q^_mCqǜt#v`Bs_XZ_ccMnmz-b (u\truk5Yp65t;̇y; 3Jb\hꟗ,yVyKm.o,d,O^0)ض&B)EI6RY+ribj]:03 ?m3‘2J mMd`c'ךx:q3޶YEЦ9RrBO*юOגx)_i_z֪m+ßj|KZc.%F}W!oVgybw>/B8"OJX6# ӷ{d;}]5xUīvU"1wMm~8nxwjiL>b%fU|pssZfM 9,>oPhڲ- ]|Ci=Os V7mD 3~5}W0̊8SkYto>tŴ|gG50%l+/*.b11HY`qbcJm]0?lo^T!>A9uf;8XOLwxݝ̖ͅw<3dG\2B+C\Ҧ,U2Cn0pq_[[jW6S<JI".0zq_piѬџ!8 >^S<*`TXth@{.)R.R9%(z(❎Mx4;+!ܞ>&84F(t"F9@yz T{HsJXz,pF<`!*͍Ms D@j<& B@UBMd(^RH>emR Юߕl_˻(cXlBv"z溳xD-UnŠ#O:xb) I'_XlniV2tf6ԚRsoM\ bbJ6;qz=YI-ecn'F+ns ?9 P][ `Z.1Ӊ1XƔ9\Ĵ8/77{gk"8bnw5DsڻrgFHP>ɱo)HRhsG\+WѳqԼ^d4+1T{ ,/$mVu{M.ulc=$2GiG/gFр犏=KztL ovk oE"Qys3| zbyGÀtۭMraQ|?ykmbҒFK$MsWMIw"HٹRԐֳnEl#Զ"}BDMďXǓRQ.+hIi$.eO?JxcFB\2ȹOA[dC!>wVLFךy.T=?hF[+wGg$؃Ji^$"hK^퀎9ea.m5u557ʠm]ח*=,:>"hTA-&JMY;MgTCϺ,3{Ku9H#bJO:jh'r 3mByX|}j2ɔB9A}x,`>GnZFF =6y5^4 c{TOX#_z̓̐P[/R-NGݗ>vy#oZ6p=1W"R26 cJITSinJ?(Ҝ1M vׂsKn-Js[6p=+8BR4L͹0!]C"BzD;{G }fq$[==* 9\3`R.VEIjFANk:@K` `#\d'ReN?kRYEgb0sڹe[jx{NmlVO(n] )T=, o=jr5Jf]C&V~kƾf~K-R0܌̪X5ލ:{Dv2;u;b, y6:HJh҇,JSfی֒/+j[Vk&z[}DXʝpFczkգ9Kިմ_1]â'^1[>xhwrzw<Ǹ'hS:Ѽ9i; ՒFb>vQg5|#dCtw]]$ !N:}zc~7km=8de=ְ5MT Iʅ@X֡S-e#3qmϚ#)UB}CU6쪦 ՘t'>Bz\VqalQX<28 ?ZܱIcH*g9[R0ansnki$Jt k \״-{ends}kSZo!g[3~e\v5%tpŒC9B|&m)gs/Z۳ڵXLׯyktn(u`w5xKCoa.͟1xT7cd4եtv9` <) 㚣O>ac>qqrg898WoKdʖK͜:R8nL6 i$rï ӓOUU$f|xc6m\4/-TqV5_sZ}>kpOUXVb% =qP%k^[ZmݛtǷ־[v )fU4fb,4)1@_z@9`~t;`&qn9cPWir`P 1@ځ Ks@ǵzr)zr)v:Oֺ\t=7E}ib%i$Hs(O~BN5gǚ"r.DžN=+2ګIˣO85}W꺟c_3 Z>$I mQ>_6Ti(b@*GuM,[BՃ#GSl7efiھKC)-ך1nk^ΉQVKm/#oq {o0\Rv* WYn%U@M+2QYefGGl#9)'cSsohػabOgT5&hAgҹ7:ZtiU2x۵vk60Ymb})'qՏ35+qvy'%:K( p}kVUYGًdn^bPe<8:)5<4F ũpUW 94ԭ<~pFکx&@ۉlr=e'sHդUԬ|?ZqXIv6/,n'(c4Y[#+:Bvev]y`*L CpHXgߊ˸$.Uj-Y,7i#1c3j~`Gq%\U&N[ p?(vTy-Kn([ Baܙ~M{[ZOk9KD'>Wv̵/M:0YF2#p@5+[=y]4>IIY]:c>|8i[ݬvR' !qӥzB{6d޺ۜsJ5*%-FcTwg&w[# k7ela]^' VmX̲ܣ8הNgwȫk 83oJcvEL(rt>d%o9Tqt$hN6}Ҳ){F?-ⷌ?.85_Úl4 gF1N@;ONOJt{F(ߍ`4%;ϙͥ/,B'X$rMkfP!@H,՗WU.B3🇬.#+T #-QHz±dզZx-q_uSVp^[ӯFZ6g½nzWQH5Q >"45(U٣*қ]9:1V3M HGj6Չa -X$ƁG/8P11ޗ@U₤pE1i4ݼbA*HȤH=3rZZmx`:զg$JA=M )`d Ґ1ҝЃ{O="h]`G9 zUmqD2=RxCDӮVs+m@ֲ)WT;_%(9O5}.ah.oǩQ^뚶mO_.+o6i\*\S"gxGFѦ#L2p:Zc˩-҉"U9 c3^g ݴoǻ%esαl V:iS9$˸ }M%Ȋ&@on.?Mܟ]x3${| luh +,XTe\&Ҭon āC7uif9MAyN_g|M#XTyj2;-.h@,B?>ȥ[i>d sVزW\da$QL/䰷FeVicLg޾T9=S·zsBQV9Wr.]݆G[Y"*+_BM)o,ekźJ@ٰܪ0Nq|~6Z{$ [ dLHfM!;xoY]ko/cxw < ?ֹdtFoC6zf,[dG =R vn۞Mqx56OJI35E2ޮ<& ۰힕JQ OZl]c繬Ef۞zקK]"*Sv[Bj@- ԱyĴqzV%ʂ,oi+pC8L)(B*Rܯon@|d='o[U=H89 +B9v#{ =zW;ݑ vZ)Ӗދ1ֹ2҉Y0ĜZo#)y1ݭ&TcQߚTwc(QvnKOA֫|cqsdL?x4慘*7>ww?0=E>k籸IQY TfS>i}?OQ&{nIr@P,%u*P z|fO>ֲ|13yv[^Tkt;m2Pia#>ش,FQZI_%aQAO3;agigwM+;[y66pU8yrm3xGCϠz{{{8'VO|t!O4جdG>F+CqioZʮ&TX `2A^+b @%:k*hc8 ZظBIi0$A3]Yt١CfTFאn^Wjt 5 J(T1TeEȎ78ǭgQjXwV:qrw܅$qǥly#< h!}:Wx7:M5NO\/oνc5f#G!zRTڢ%)4GSxcRbLCQ ]=3eJArxO2]D`wcJ(l][;ZTt=l=%e4z{KH"ZydA7٭Ad x;%3kw(D, s]-@\B1pkUuNc3̬#,kËՈ]t %a(>ڽ.噭 j)g"\=҅NzzZwUEE䮼AtƑ30`d@Uӑ\,V# tV֟k3i<*\.i,wb, :w?o)=J_ʲ]^SqHw2Q\c4f |pp}:u&id׊U`Prq[!|{|o-~rh4?.MedL=Օ{v% F(S# aW俟Q@sH0ſ+6[;hKgamis3..avV0pzV$R4V;iqTjFKU@GΡ})x,sp=% zqNY&tQˎWNoeVIO@=O]9d9]b엻&3*c#'=*pEs lQ@=]V}o<+JG)\H7qGFEom 2BoZ~{I X_˶bg -ɔ]{DKTǿ.uQT2<)>eX/%vi%Q#Ak~o6L 2x$r2O\fs}#"09P*C$5M(ɦ K##I r5Zx^dɅ4" hZ^׬\1'gQayƟR[.hٺ~gp!^UI҄Uߥl1*8jn4o$^j7W[DRJy6k3~+c[+M^Tz{g"FvF2e|\EِLk<ޮ*?_)Z%S+Qn;S`B5y@8',1 ʃ"hiLNr\v qU-^ndAo9ڠ`PܐfV!,f┹4OG>a\b(I S٦zPCHM=p)FybH; cґ+ b8 fIQkYӨ4ͯԟRyyRh+-&)./)@44q \bƗ7;m&q@bBm})}QJ\bv;t xSM*E隢XSB9LL3 ƌ)O^ҽ;6PXeidrJuqyÛTݘnc=&_Zm(Qr1a DeR7"a;22KF5+ yxAneI;&C#jk]2(fKdt4knIj ow"'f7N{D0@U''1W21$JOepYSdIq?ƪpM{Ia"=ċN{g׽b]K ȥЅI# ) 3[\[I,[Gz&o>n^#FovCT2~Q,NX㠨-4Ē\Wke#*eXFVnYN-nϡ(+Hb }xZ ?/yAIJEC[n$(Yy_5˔,yMX .G}$mE[,ilq䎧<]KȰ1m>pEhu ~EkWf@N'I/QvVsIxVa1W=:X[jA%A;W|?5akV2AqlW I+vȥepr8=k1wJwqvTj_i4gQX>u4eל`=]2i*g} [Vlj[-&ɢP=^g{]mP~:릫bi^$)|~Gӯ!N(_Z OE*ةq0*b5E|k:%Ɲ=ȵI wt:!2/8׊鴨$*FPuvN$0C`}묱̑pZF `FY;=EaO{hvI^B?~Q<l.gЂ0Hkz_4B /6;Iynb`69MBb"\y>^MJ93,Fqy򩵈}6Yw#<+ZS0i䪇eTsRiz\} "/@Ü};>uOKb4Rp 6ۄsMcu6 s[?@7Q(_^]cJ f8N*U=W9E` >+o vMqpø_լ.SZIy!r1:Vp6̲9 }1^s] G01q_8jvPq_og'<|OZQ$mJ@=:ƛ-wWiA]}8_sR:*ZKTוEd%q áq^աmմ+@2Ur?<ំ.-"QkB:cqɯrÚi3\yϖ$aA8:}18ڔM?_CkhBF}1{U-KĖV̑sz~,S@}Ww xA2bV嘀8> ׋dk4RVoK3eRTiFvo}my,Ѐw}9X4#9ƙir`f8<9@›ޟ(nc@W8=ϣ"EygHLvhm֡5;xI`"՟) z ~O#DIBjƽc]Ys*jqHd+_oz9pv ]l,4n]>95цQu#<]H7E.n|i;U]%\lx;6ndМ<:qanufp {]/+R5SrV~U})z0^SwF^g F2\C{;.Iu﷽H" #рwAм+mp&B*߽sh>&mCBkH)ppsް:e>ܧZAȑݱ3ɠjtRx]Rݣ ($wJ}^qӜ *W|`Tjz49$ ս^h~.!|q~8{ҽg^9]>'-/\eж7nد./,]&3ra+Nΰ5^ ¼:ߑqJ`Ʈ:O\Wg!6? {fym6ʌNw٤ӯ_#F8:[GELWӞCNރO<6έe(FWWyk#ٞmQq&pH#^cp6Aǽ>d?xQ]Hґ b2qb\wO&sր)ps]Cץ~ӏb7sKzE1N(Nɥހ 0{Pj)P@N¸bb@yqzښ8B Q8zQLH6oku\ミ}urrz gk4efqӕI+~lJ+VUfK<+\>X!H3U4[c VLJ{[9̩t6I;`zuIb&MiԷAq,p>WOKC9;9'TC Ud^)(払weiMU ,{7d8?5|堈+i~mNU׬4kԆkw᷂-kir+i _Eduu/%$Llm:Riuge&|H8o<=g:M:vTnIڻ=o@u}&k&md6,>8_([ź١jNrpZ%Ctޜm{ݽ/m*UaRi-o{.X;/k1^ m+*M*&x늻/ ֹ+q#5otO J-`"+<,W?,N:WBƟr4vLv9$rUJP(g}~rz"b:O8 ؞գ(2K`oAK{T\X)ju<K8I~5Z *leQF̣$s>$jAөRJEӨ׮;Uqco% wWz#F7C pzchX4 =oTz9FgS7Fm(ڏ]AZ)`>L'*@둏ʼ\5Rc~ 18z5BLm!d3c4*_qRy+'Đݺy >laTI7{X'eԞMӌHv|MWW^\rzgdUf -'H. ~sn]LQ',NWӃjv =FZ+(exyOlWӾ=nl.#)@`d=G^9BSHO ϙ#}e൧9ocs v_LdIz\tV.fGwCw%^FJ+~/>$J%cxKBL+I+=5|8֭/(G#]U tD\ʼHF=k* k+5?GU)r,m]ך&}i /5DG#ku#!X@9ǽ|àxUMvO,2} jhqQU#fI;t2I e b,C?J7u}"]FV9W/J*;5旚:gMה+N o~Mc.|:|K޻xܐ9ƙf8X7k\!awҼf5MHC9Rzm6::Q4TD|S|MxCk͌:孜yf\%ι5jF՚7>խ <.R+_j~jv{3 2́tWwO&k=¯1ƙ kSZܞ$N$@žU/Ҭql'afo~"I]JtU0ub߆VkfR֖;Wx24I6I]kVG tG\zđC HausPM--F,۷ry kXEiH~{h=1H{:/v‰0vO:ڎw%YI{5_]lDNno>W4 kޗ}1oui bKfp= x-cbcOOs{4yeu"n].oOVkCvKkczBʂ1H;r}dWG3uciiUѐ 6A#׮={Ν Jy:(]V@W{,KVN  {W)?x1n.HE93qzn^GdkiHʰz˽g/!,O'&{ÑxU-tѶO#֫IaM&]Ksz9$?˚Y'8^8~YA_O񒳿R%WM?{SvqqIybi&vg^j"!,:VQ%QSJTt/JyV^`Ax2jx~+ yD&hJIGK[x 1m}kz݋q15Bu*d֙U0^#li]+ʕΉ|_8fYekF~oν'IJ  $gҼ4@c_F:\^IJ+Ǘ)yʥ_:?.sRj*݀ǞF?fuxz Nݸ?tҲ 8#. *张\ p89^\ZA",rCyM;} Rc"@01q_zn2iX.lQ{ѰaE8a4fҘ i^ ivs@SRƪԨ)JlV@RG#= <v;:]# r}iRDdl2GTDJulu?VD ,R8Pvi-Og#|GѼ Ɨ:]J Ou&b|W|ugkT9h \5yfdCo7|GMRmJfc?q2HQX۰8_a!Cf~M*ZݯYlTr}j50:)fۼA&Ìze9l随4S=},qo!%HH-lթe꺄M-"1\&0ܟ:qx6I$Eh9RFr {x^0کݬnfJO#;Y;x?^X143!8R[cR<kΗqFutʓ"wbC3(Uu]MS K㜗zh{'z PTW;'C^orǠ7+ڨL~wgsJm>vBcU!ԱwFKfpY?/c蟊wΓcwK CBcmP#ξ{{ $q?\R3?K$K2( JWk^[]9>k_WZ7o/jZwv;AKHТ#2I;/|20K ͆bkū [%ͷ ƾulȅ,o }14q8\TeOuc"$ᑰ;qVHc1V &Oh\AzDWVKK݀Y)ƢnIӵJ<e x9xZ -@J__ Oy.%M~]}8]$@!>a8iЧI($**Ih-Y!'kB1$Px {)Ru9ZCw6zCiu&"F*s+W(w*PtpI0 Wk☭l } 1c@k]xNYl_j%]3(P\WA]iziIjuH __ƻiBj[eRߙU.gg{x֞\S:XAq#\j~8u GtK3e(U%,8!?Zxd0E~SS/?*N3o|7λ5mRIԐ~cGm_vR4)Js'޼s<<ӚyN@H𧉵 ^mm>D !A{W\iQ(gpj0Sedp&kfs݈#WYk/*5 (Vu ֊}pFp 䮵ѵpvٜ8#_!ZOZ-k_- /P'ڹw7sk7"c sUo\2ARcu>>fڄp^f-fwtsV,WO]|qZ>ΰ]tand$@XS* kv"܏BçC&݉ 5xFДXX䝱+չVIYH@o&~io)r?*rץmNf|_KYBLc {W1H+0ë!%sӭ{o\,ŴvsÁ\G̰ ;*~G42e#5 G'ҨMdU^@+{kr՝-q36G@1^4j\ZQ<V&CHGZLɂkQcz6{#ygn0ՉYǶi&1VQ^*XDy]-16䕳6@~i[IyI0ܬ9T 3egub{D7=M /qٗ +G417ӊ}*pj]B!Xޯ\i&NXtڜԥu*焚T%r8ȧf[\+ܾ<K:,`ռ졣zU9kG߻h4&$pYǁ:%iKN$I0yjw)qw=ԗ +NxU|\f`Wq.ǽkNvrW8bYM\HAq5Oxt75-ԳDXk2.| McZ\E$qWU1MukVpcixt>I2im΍|`>izkSš 5Xs8<SXZW5}oYӬb1lN?)R6i$xzf?x_ h"XI`1ZMiamzxnd1ۺ<2>{*x^ZZ>VGKKS{+gxw-oH.P眏_rϋ> 6p2whXk^)1=kz|N3EF=Gƅl6"P}TD $)싎@9So&קcvd+оr+v J͐x?rZ5VXKpΪ"prG5ׇ<$Ӥky{PB' I鎕QQB엧sp*bUV2v \Oi#= By+.y tO,OV;YҽX<%:wi_%Ԝ10hzӱ@=)@'?g=tZvdL&*V4ݽ谓VعBOhM)O6{c+[^;Ѹq5ˎ itJCȸ#ִo5[h\_ μ^8=G=.x{MiZCXȪAuW*|~OsyCz XadPܒ0<}sk3I,̊qGWgq5I<~?ZFt*6 PQ+k.aeKUO͵IZvы,[_e#) ʻqcY7-C/5~fяa\|Զozs:ɺԖzsy A$xřL8 +мMr2,#;T9ּGQNÁc]hsp&KD\,7l9dcǩC.k!fʔ92z]ɡ^md.XgьetaB C2dKk{S+Ӧ1Ckg}p G@v댶ms12b: VV~o/Q}Oq!f B9oofuF+1ܞ5ӋY ǧ?=BL[NB)MC̎_ z#\<̭zfPYR[*, 9>JumzklUNS2ci`i?{)JcS\HK`V5c|]qE8撑ijK1ӊ~0 &;S`tǵHAHcBiiQ) 2DLMUXؑ/uyY]Id6 v^RT,%Cq0YIT~Z9wnj3Q{K׾hzq,@@ ?ξPՏ.-Q$*yy8Ʒ:\dҙ[0x3ž2/׭2QkxF5"5W>o)Ɯ]in $ hh2Gzn{{^>\q\sBǂ;W52n%i,&sޢ*ROQ>94+MLm& WXxRy uĚƥjZZ[DhHf`~'ھֽGkaxWc*n4hg _=׷C/Fj6m 9-Cy?#kXBuOzS],̤z@Uf@|=_=NQz<kךk{ % P9ƽ—p*VIaӎMn!Hx+tk? ۭQÿ'Mv{8+>'2V@slz_>w˩VG T|y6e>\g*}뗞4fkxIwO w&ROzPˍ28S8OΧb*^w:0}>Z*%ժ[sHRtk=vɖ4f ʏupA6Y=zR 69!l~?a*h{Qe[/"ͮñ9=+о6q}xj7ֽm(g-pc,H[ʻ < P.u]Epģmuc#֮l[M"mA $5T1"G8fҧFi0|;O|{sR UY0X" * ϯtR=&\s=t)9sJ*ZUhv 20SɢIHѕH={;˶2wl횷&E  ~qKByݤWЯ!DH_髶3*dk.d̯9_(I_͝mVRͳ9ֳn 893ryّXdA3e`l#]d+nr&RCj<*@tۊIͺ&+\#S ̎H$+2y⳺[*5i @Ti:\Ƴ\=δl |𻗞^[ō) |;_Zά91qH|]osX[rf5ҬcB61.:kuQf9P[;8ox_2a,Rd%n==k %dooin\(f_0" X\ɥK*YbHݶ8TΑxfEL͆#95N ߽@r9X%?즶Ut.b'$+\Č5ć*nud~$xt8F’咐v1^!j+ͨ_M;9ۂ~;O~5Q nN+ȱ_jP_ic>b4KkwG5۝WR1$u*ԩ`Q'o~$|C ]VkKz~WMW6zaiF:y> ^:u);uhvǞUJ1JͿӼ'ZgӴ[nCak]zNִ-U[aaRp75>.Z[X ;CtwOΠ7,ӼExfi@2e'Jଡ଼#?gN*Y6嫲KoO.Pw%=/Jlx_L 2i< 9=~*S}Ph 83-\ZR9?bj47" HǶk5ok{;z[{Wjck\˽r\jR9ٞ}SF=IrAIiQ.RjXi{S4&#h<sQz ;Kւ3F) *H2Us0zT+"qpAiv-M.(oQ)9@v& ٞ{ Ds "aAZz:º=}:ToɣM&{zmV;fnFXz괽L`1LɸF=s^/nG~#IܪHA9@> ~$A:P֬&~dr^'iyeJR B1eqw{mpY# 9XgE$YJW I#q#97}g >Ad{'oxPOucۥf_Irp!G-eϙgyfd2/32;r9ϭeRVFrvmc\omƟ1R;WA vcIRG-gҸ4ɴ19]j0$L)yb^vė"ebJqrG^o{2j?F 'ZrQ8u$KvSg OqE(~CCQB'da:·9ic8US)$q|> aa2 :OtZ'q*{%Bb1]qطe9_1zUL|iOc+-^%vRPW6Y2l(?\qr] ƻxN{kW`SdWe>Ce]sqYex9WVN*Myi*qFudgRmvBB{6JC08W|=,%5Jm| J>zT$`MJ1ޝF3ަøI8;TސqKުIq4b94K1!7m-8Zi@D&ۥ;o=)@Zloݤ4g!  J@8]HKg@qM)JZm*9#(),[nA=a $lo_zđހ<';r0OXK0T<丈݇u杬.kOcR:'#{w<5/1i[$zW< =hpY UG끜WB5I}n@fPO8;q{vְX*tƔaռ18d~kUvbݗ޹ @c阺*I=5h`.f Jw;ܭN%c"rČb&X54n7uU;x#Rn )RܙkZ`G+1H"Y}+ynҲLctDh+/eNsqa̲ .O|Lem#,IDmVԋ{ ǭc ul=_kNM?#U">Z׿f'J$kɡ XpGcbŞ]Ӈ`" }]55ku\(s^k|,/)+> |]kagÔlGnxhMOhӓO>hzI,jDیm t?0ϵ}V7Oc;~ؾUI[4|)"6R-m'Jv1E;cp+>KZhkot NOCXn(RNPG~C+^HKu^S;OGI^M{ëuY4xU$Iwiah'ǘ;JpSO_bd+uf е2Gigb'-^=[Pѭ/n2o:ҐReR0V ?6,k BbbOeO2Ҫ՟'v8J*kz~$qy߉O$!=uG)$ 㵍.o3j?c4EhOkjfDҺMΏ+܀wu \CnT㕯/g5 눤oo6ݫVI]>+#A8kjL%kčRu *J &H`]sqN+&ibr<es>MWH֖Pwsp5=o&{~j?Uf>C!jmw˶`l29Sҭ-\D@Ax*BiZ8hgy_u;r FU$ /a.[G|X$ᓓ|{_k/5 Q\ZޜW&chfӵ?k.fE6ѻ>W#ӟzITNG@zWs$ rrZMm\ HXy3\U#t妹ck "Օ@xԲQOk"aϽkΩyo?p]}:RԤ1yQBgj/2E.dzθV23TE1˭@\̖*6tUEw%BK .&hZ68 ?־u&/uY4gC22@?{T4Rghk#;'זB՛[y])l$ ~qS5VjΚ~צKs8Z)-n{w0cy[l;xOs&[N֒$Ѩ>ݫ׮^_2]ͩFFV0xvnnR}: )/7ğ2+̲M9d]S/ "ҲCwZZ\1zmC򬷞BHQ,s)uB1qI݈cZ' Uu\3VqԒ[8p2= W/ߋ}Eڰ{M>+?s5i}{EI0K&JYӮUF͇c⺟JPj&X s_6xxBKoL&.zz]_Go9`&re9_WTk}F 5eITku͎0̏js8F6,/*p3Kq"G'GUM$nSx>/SRȐ 5fJDb ߁\G^\7:u5~ ωrĦ8ϻ=,,$ `b5jKq}_TWښ%b_Ey &fНXk_pI6^寒fu^XXinnNnUj6,qQd~QNFr+aU֥IwbTr@g#GPj#2 ioR&̊s?Z]OI:v#& Xcy56> mOB-V38+X=_m\=R3u0[~g'EC?1`OIV E H=Fh֧$NT8>qp^y ӱڀ;ұME;)L.4SqJsbJQK@iqɧ؀O"i* )2tNiǎi%~74җ;Jv┊n()ɤJ\@9ҁ< d_Ӵ9YmM8;|`ƫجĈ84YHQcTI{x`FR<=ɢ{MZŋ~N#=j_ }F\81-DLo gӴ gLkH$&>QZך$d$c9x<.G+ݽOr>,1ު6_Zj"+aodt>#|8t Yi}ɜ" &Cj#dg٭Rx48WvϹ\,đJYt>l,cˑGSJ|K-5!Զ  4gidy$C[w Tj5ǰ 73&T5塅X,J:)Τa viqo1̮А0*Hp9'PS,3Hq.ԛՈ: U#&3#MH,qYoos,Fww71ViMTIF]Bێk uQt0g#GȶʰG V+F}2YSV;-!\$;ZܹԾ7k.nV`[*88$c^wd#V>qFaV"-;)$mnXKHW^Sߩ()&)`ҥ) A^)t]h U񊶶i}g5i$N<_~$K[?a8ys2NsvR1p' AL d s¨b@s+LN2*7xDu)Jz36:Gtvp7:*x|k>཮7.=H+ ;#$}@kǾ=iCPOnh  0>ٕcqVٵf/Ǚa0E^TӺ{{g~@wܒG1O]EW7r>߾A|MǷԟNLvؿ|E/f'OYS,8=ёpQѮW="FA\2cj< V ip$.͇=KFl$?LWNGxr;Oqڹ wK]6  W\zUݾe4)4X;27nt+ݿe,&Jv2څcsYxѮce&kqcw=Mđ9Fs}3_R{+7%#8:ƐxKk[2T8kd2OvE T~4E_m[Ufzz(ux3Luq+fnnT7fPh|e]&̵a \ݖ ϛkpAߨėv(u,Ԟڰu;rA;{4)Dup~IKI !vW|)ɬhlpkS,]G}t"9EnM8) :`s mգvai'Q b2U=A=Ok3w$P퐇?^6M[/uFoC n ]6f#y> :1)G#NRB9=S|Ow#-i sa$m0Bqί^^͉"_( q]ӨZ-Wn|I,uKxl2GZj:%ɢ-$oϬM>2-Iʝ#וxKqjqZFD_JF&q$oC9M_i6,dS$WS !2ۏsX. 9XǷ<I9ٝEj^ZaA?0^9>i!մa\9jqv;i*R? oAeϔAI9[orQ7KGgg=YyimTdz[iۆCJgl5.g|Iy8_Ҳk+'֩UMK:cdX%m._jZk, #x"8Rk=:[:nb@+`"nNIkN eU.bV5SL `t`f K}ܒNگ_) *@fzC+1ٌ8=+&k`U0oCR-JVHMj32𗅘VRAsQDBҒ*2G 8)0}Bp(^~)y4¸4\Gj9 p= ;(4vPEd{=`EFx\ H$t!tu5m&g+chP#B:4G̈S g0&4GjP=G()h3@\NԣE.08WK9aqfnOZ^+ISъ,\SK7Pǽ(dWYO77?g$!8@8>1έ5Z=ˣUЫ-? ?o4zb$BA?oGk=3Q?w($z\UO{og"NIT)GJaF?_H7ďwnL3&8l1j:EG>-Ӽ^cfydvhAda:xjMy15j6ߘIE}fd9x?ʼn zfm)%[BG9$ ~7SՈG|wlk1/w~~t:yGw-1Es >nSN41)?-jʶ6E iqN&s;3t$jb Ur̮>u 2&,h8QֵaXI2˸EZ}~Xđ}L+3/\XFM$M8j85WuHŻI9|nj:{M9dHW#ʬ_7T D23ޠI&k'%{-_K3*Q|1 lUTUqb1TL{ѱV5MXPWސ6ҔA\iv sOh+@jPQހڔ 1E8U=S"T >R#a"qM֠4sOIoJP1@;R\tc*/^:SBHf"[Gz_ >!XG%<$`8~W@rԪI`@ {5'\,Va4:d% ;y?z-x-W@z_[-IP3Sݙn9WwMY%"y{vQL-$ҝ>y0ܲy"n1J4C"ITv璳6EW[mJePjRX(!W ¸MrƓ$ ܃K]Ќ~smĞ<4RCDc$;c?zǤ$SGmp9'Bm'{;\3}kJNkfe>M˯ xO$lnV=k~]1­XG xZ^ z{DH}+y kKh?b k ^e,%M2@S5YxC·?hW&dA8$!`x/'Jr9Fs^mSsHTW9v;G%ɶ5T1Kn++uc32x);Y[tO~*qpʙ 30kj"ދn."#5>8-]hZاsldUֱw6owg+C*7fSЏB8w <;M vzn|.9ET|goC/>'F{/Ⱦa$qӓqUū-Ο*35otֺڟSާ??--lYjQEn'Zmĉ}cH^sAYHcݷ#{⽏ἒ+sR sf䐝=Gb}xy',}$.ƴ~wfMy{%;px klM<kUkZE +Fix`w'|-jR}j1U,xgYozgְ"unc /?瑩 As1ȟWx GhPqK,SsgKc ¸%`u##_-~4\/ ou!?jوǦ噛rzԂ{qYUii$u]kݾU r 9EF_Ao7OI'WׄSV3$ya1k8cW/XKo$^7I/kf.JŦm;ʕ?ֱ=URVA9ŀvV!2B&p̀g#ֺ -\[FpdZF)B73d)'ϧ9+ԡtT-Cb ~7|+kvmo)v82qְ9y3nӓW3F#XbD85~LЦ3+遟^?74Qh`/{ k +2Q5iW7Z^˶Y )AO1fykDf3[#|z$Fť@rsߥoͨ- kHdxaFx <55h亼14g oƟ54F4mJXE1[UAo,`JDF1ǩʒM>-*9 G}F;ӚXm`r|lEe}8X^~[T^7f͹ }Me[h%I%[$N6T]=u/be tUH-n64߿УRoʼ4RP1؏5^}ÖjPG:yH=ε5|?ЭdV-,jB9&`'UߒqɁxXzlqoާ kvվ٭ ou)W"O{'ŋs%ammdQ?*::>&-wPٸ?J?g=3IԾ(~h89@M`ze>+kߟfki$AĂbYPG/ԩջ%Vx'+/Eq%er."%y ߹YٶWW}=kr ,s!$:5!8I8 ̷cB`0U;r*=z0=jh4Oⅸ=Q#Rj4cgQ֬7/Rdh{NZ@[,qph9<&hsғn{SQPqF<;a#h{ҎiNz4ZP4 po+Ҟ2pZ~tc5IdH#E484PQךC9 i Pry$֒," w6NytR>q!nb 1\vU ;՛KG đtb0z{Qn½;85|W1[]Q[tyL=q8+*Uh)gFkR' nmd 8ؤٓqiF=)q '=(NZq@N!M&=qN7`S)0ivҗN i ;G,נpġzwtVc rDw!@k&>Փ>'hݽMz2 r,~3ty is[[h8fR)VSS7CGXLSZC AtRZ[ vqǴW-/fQ83һ^xk՜yvcQ/Qᆲo$B355:WWkw(Xt8W5ih+#/= BKIX1Mx3csXԯkh]OK:pN'w O^h5bfXL«xMMt]]3X#`Gyxj2N2ii;t5x-m6 vrK%熥a\>ȯ=Y"Y@#S=vfRyA~*|o+>GCOz3,ֶ 8ea=j9~ӂ&{m⏊v]xnLs'7.pCc=:iC'RasֽbSlly-UxhTr[4[ӯ}bmN[^+k"I:cµxuXXwc뼶/#@>dϴQߙt[ah}'V;V]j%E.MQ!y#+/I"qw:ȶ2qϦkΗ Fy Ӗ̀%تsjkKؠ1;~R:z\N8X@a=ꬌ$=~>{Il!oPDnc#ڰZ,IBd (=]p+>qpun* e-.t@fUfT&n! "Qާ-*Ęⶊm\Q+2cMᶞ >[DETfq/}E(l-R7y7x;Wꓒđ'+hw.wg,Q_qZ {$}(cd<=ֻKlfHibbTԤƍehL$գ,m  ;zjHY?#-jyQq^e;t3H=Ms:žOҺ p;2@?:#;aIK6et3ڹ{&k+|lJYZ@̱$caJjJWcCPjygqԶrd:`q~++42E"22rĨؑ_#j6oWrCҾ濕.-ڡS9QՏ_|]xe:˝ȯx/9N&~{JZݯ_>6-%B{u I>+ѭėR(YH<7O_<_Eb숇 X>==}VбÒ@־wv.ۚKlQ5掽oOH=iri(z"tN->4Ф9_q/j5iƽ7J{2U 7ZqZ@ҵeyq4-KR" GHʭ c^xwb@3ҽJa9Xs`0 ~䴲O-Ywg|_$*Q}|ĨI 4,rwqtA$RPyS] 6v|Aj++{ j-GEZϩ-68=sV sּDH-c?0r0OZ .Y̊d\ּʩiw=3+V8o/_,AJNj`RN*ߜIxRt+-SRQG(ߚ@p^9 ؖXWE<μjԇ|gpNkEk=ǢFHXW^0ԵfPG r(W85͉3Fr5JW?1c6J߇􍣥kg%~nx +K*#u _wt$PDɌZiT_XYxq)·¿ N"t%T Guc:cYZLv'%qW5xR2%DNA5ܾMe$|ݩ!r~}k.o5 k5!On+Dž^=?n /JBƎpx$ƟxX%88#vOfѬ?595)MHmzu8ۚ &P ɫljfꘊyOeoŮF/#319$$m)LqQI._DݏIYҵ'QPOJιpGN\bCWSDڲf)p3q\~j,h# S1O9ZN0C@O'RSlЀR1P)zT!`hċ(|=9 J{ХN+Y\c6򎞵@+튔i6JȻ=zԱø `x%=(0O*QEƤ<0V0(RthpiISga!y3'֚E:9<oPG8`w)ޔs@\n;vb F:ӶҗnOZaqozwJ:PE(Jp!m=ԣ1 J^)z({(▔fON})fq@@}FgM(bu}mb]53,eNH#WzݶZ4岺nuwU]ïoM(WB #|^ߙgngNy#֨'b" ==?i#ZGv fa:L 'd{%xcTuwLYˇ`A5fXenjXIofuPF JVktygd6gR7uڼ\'5~>MinL6Üܜᗊ}*L}qҿENSj]uz~f1r Z-Dr"B ,Nֺ4{ jRx)ӕ5)rMY<$1Eqo| ,S 9uHRRgkp(׹6sy ܶp$G- 0{Yᯉ־WS3l 8ǯJdqDT֡Oj+.ijPvh~>#fҥ,p#`;t+|PTVEtM>q9@\L ]z:1N.mӡjt<3- 1ެ@1b4pL:)xV-]ƚ[Vr]XYuN1U@9z 3+T6!>@OMH14m 4JgUN^:DudMfL)guxyP9fxVwk d%N0yKQRh3֡M£\1+գg|A9:#O2[Hhȑ?]E0~[hSt{Xr *qj zXk#Kv`x[]b!5^sn|kLVWi6Ğx'hʞיC/`>0o/qV@XnM! ǭtBt`s-Yҫ7@"2ѣ9Nk^{D6pT(* I=fHnŠ* >c|m˫.ws::RP[\`Ͻr2[pqu;J֓[Bl%ޢ,|cd`ˀ}?쭬 |Er˻6k?g-leryk$ӥx'oEx\޽Ji/'Kk-c)#ք[jt$T9Wc`+*ޫpy}~Tk>$_~(_ۮ#wߌɷʾq״{+Pd# |$ŐRP?8s K1UW2~Cxnd=ZO_(]qt)eTUC:`ۡ-SX5&dY0σDz,R"eqzͼJ 23rqO)}knRrHPsT]y]IC%ԼѺȡ+~7|bҾBKFk-u*B^0ss@|L/A=`+LF&I.kBj5u_SӍ'Z8yoAڅog'%95A;qJ@*+}7: Q@/QPH9 @-9潓c^Z1IǏ^- +J?V>ս]xKCd6w0J(Pqg{rYUu(HҴo%'[-B)c5j]7?WuH][]nrdь~7֞Ѯoucq|Jm&y-VHCA^_oϮ8qՉk8zl*]C9g4iS_neYL6X!ݜrOEZ+d~[WU֬'(4Q[,ogeFF Ǩ9>:gvJ} LM0jR_0|MADVlcH5Ub3Qwi;oSY ,D쬴G%jwRKpK՝(?_MD+7px'T}I+QkevdyM]|d%`QKp#41N%o˭~K.7w:u㍢0X7oII.rUȹhYc9<{V~or_ FIʟ9sVWeE>^v2c(򞤗54kW73o3L'5$}qsqCrp둜Q&R躓fsI :8'z# 7'ѮC@H&H׊3;iT=?0ϲ^'ghӣaz֥jwrwN^YsY팞=`d$(kT"d,.ijʄ 椗m `*K:/G![\\~23@'o7I𨻟IӤ%HMʠcz57ۧ>._,03zY:IxmBX^Gy;!Qs_7מuNTo%IC B,KR_^ 1҂{sV2zRXE}R!"m<ԄTءp0=4$&bdӀ+JAGNh|݈HKvπ}ET= {ɿ?ALd8j{HHY˒{eOLQ:Ðe8&5ɧg=rd0昘;]qq\3 8@g֧TsҡzBvW&8\Ґ1Q`枹b4&n )qCcfQ] |3QF;S,rzTx־2CZx R$tmZ$QTJJ NeNiGt4O%DdXktiFq߰SmIY-V9LiX0=*ԙ;[kY\-89<VHrV'WV&5ryB=}?mg 9RI mЧK{frG$g NxLś9?,-Ӯ^3 *xz$uTv sq,>6V,Q{m=\In€7aG=~ձXѰ9 rGkE=I\{5c eoAv&ors\%葍W=?K'E99ZiV(&<1lKq*iO>WʑCVr3miZ۵l+JijJ].6;[~\ҙ.RG`@_\ޱ N&M +2m}-IG1rOc)RGB"0Q8<ތ2 B ڼY%a(]LJ%?.3ڲ3*v[ƲN/QT)WpZE @kq.ӌ`iZ(RZSKF`ndȨN7(<&G ,wxOIܠ`py\2U'bFe9=2;URHLx8޸u2Þ?ȫ7f30\ǟ7'ӌ3-c渖CNqJ̙` Ͽח˃~ޕ^rq  [ҡIɛƃ٭m,Xc?μ59Ke(͔:bl7mJ7db^8N1\E}%B]fi_cn\G[۰@QMKM.a;X[&7m]0F߁ō?hh;]E#̫hW'< W񝵵h?MNW㞗hOy*8G\kGᣩo\Q f 38_qg cw'{ٯ>+8jFpjKk]?;l}#f-"\\Rp1M|cׅ?o#-; z{W0-AlZn Û=y!nZa.gϊ/9qma_gѿk 衰0 Xr}:]K+ϭ7n͜;qdV$/haI#*POȨPOψ3|fg'*v_/);~SۭkZ$]6{qny0k\YCwp@O^Nzo9UK[͟qC*r[ (E(J:ԌS4){Mnd:|jj 37"ÁD%̮Lgc>^dtl8FNSU|Af};ChBv8u^xuyZ9bz^VE$$[S~{K甔]~CYeI]AmfՖYiK\[IKxx>M>da70k[G :L cϩ?*<5cz+dRG? f7UUtq [#찙pO+jn SWMgP $qg^]l$5WjZ?ǩKu\ɥz'jZ &)C?Ʌb&fo ~kU]aOOF0Aדh]n b=/%u r֡-?A`v֛V(rN|dҘ}Yq'+p⟳Qa7`d椊2t~Bֽ `aޞȝ1f>  id2R8*|6ac֒̇n٤er>  zѸ`H*ʍOuH uS)Ԩ_-g"Yݏ2[,ON҅N8aF}X< a)rB@g4μPGJRrF}@&*DXt4=;b# ?:) Ҋ~4\#ZD8iwM^88?J65.cqڗs@!?ha\@)hapǽ.=)1ww)g'h Gz:( NAĥc)H4hg(_z.{z!6n:'=jZp(z^H i֜A481JøwWi ]NrHSTo(*Btok>z´jgo ZUĀ[*q@Ow?ZoM]D.WdJ2PGw-ZzyB&Ey+v33Զ+ 磏]:sxznso,Pq%$21Ϸm{isci:i׮)•a#ڽŚPM{K4oDꝤIѿ3<=X'u F[3‡hչ?^/FS|3iZ]ѥ;]|l6wי:НGHs~4ֵ9>`Fx};_\ve9$^giL->%̘>|;A9׵y#'h$'OY+ OJKK+[ 3WĿ 3dPA3JǏRzς ƾvqkcm+JQ;_=헊w5Ȍaߞkti:O1ia3%ӇLqQ^8:| 5ۍ, Qe0-+kAEԥ$E$ 3u-Oneqʓ}O,-MZit>g7e8+]{1%E=sV^61MX {6iyuyQ1_8ՎV6-a(Y5mZ0QM a!H?(=MX:9At5X.!Ɲчu42L2[9y%0pwcv.Gv)$w\!XrrLb㊓βYKKc4X+gP27gUkĺ`C=N+3DZ$SGF6r ¹'Uh.ܱok浘YH@V&٭Sx;jU>xqQs8(#Og\kYϛa\cʁ*b>[Kg-$hV3994Z!Y{좰rYЬkqVK8d&1ai6#3jM&2sMSw:c]5{i^"3Vj+,$sʫ嘶FaO-f"`KzC/m}Yz񢴳3 ]4%*_ڸ2؈2X"!>@8VR͹u-~8I>⹗Z0yzS5H ORkUȐ+S\ivuڧEygj2` ^ + |2k`$(8V\Kvlg,4\RU{e rJH 2r] aw]YL.x|XKŷ!|%c]N2.o(m6kSbo /`wn ro][GG0cjuzjqH"Gs&R.q[a zZpr5~?5fd8a¯8^/꺔_bA{ztm [1 ~_ې [^vf"op~[JN#z&ݗW_~9>EFcؚO 1kQ޽+^,h쬵[k>LqlWY)Nz|} fj-!g7F-.D[FLT} x#+ӭ-(o9˖#'p똖6V}V[*4";ʒI>c3~jʫmy[K~IRǖ/C֜SG4!\MjP_呝TRF8 <Գhê8'ޑ2 v&\𭩽,qebVXt1sMUYxH}JhⶆS;~@X~WKqxԻ^in>XTb 5PҥSp|޿;/FZMJSWKue ;YF3WhO ~u'esbֿu M'W]Be"L3#Ug=|<6#I5{nq_ lԯRD#I g 򯊟uPŌ.m'+/G:Ku#"(|Uc;x,0o.&o[zvgGS3v_ʓ֣XؑXj]_Mk#_38TsҜ$j#9ۜⅮznQxfd#SS$Q[rه= ];bWzզN :Krʽ8|t+1"41TVcԻݠg&NWOt:2SEOU[b\<.M}M_XOӤ:}C,P헧e=|Ct#_,wuϲiuYP1w< xNY{m|6CX[wk^?Znu$1$l摟t[-v?`~XZMwjp\]?|,IBVGxH|=yiG5#uqʫՂݶ>'9y5kpM>lB?5NKU2*Kybj[lI =j-׉ZEiHL }-:'ևOEcZ *ν#7^4ԞGi8'Y&kJkyTWӁ0)M$y?@Ebڼ(J8m.i:kMʫnc䜨Nz\N k^`aӑS(jJ:? ka^W9q2s\O|m$61EuoF|Fdža < $Ԩ~]<VTۚo?S2ƢP}[(&&wpqK*+i``H{u5Mw7cͷjC`ڇHJ tI{+zg ^CgyeK֎dzf&I争m@=7gl6 @=|Q{X'-R٣1 wP~I^LŦBzrM}.kW*||+hї.^oEN)XV&nϔ19q~yͤ Yvߟʮ(' 3^>lLBq8v'K]SO2WL9ss,r016 ]+=jլ79bdd}*xQٗ7cּ4̮uixڤ(2%%H<#fD9e*%A$jǃZd"’ңvA~wjch¿OU7!HgbZ2= {wTG{~nܺxҭPW7+ r T-7ˎ Cv@Iz>dp[0p1HMF!ʅ׊ Ggt?Z3^…Ճ8Mu#GMXji6A,K ~7QLGű^R7zs"8 @'@'[1t$XNTqԄZӸᤙA!T}ޜV~\<ҶPqR>}x1GNx5g|ڑu ro=FG rDPqsdsڒ;fJp;^kͤ+rH@߁ܷn%&2=.ITJQ|./>c:JIz7O5efiaB:;oydk˿JҖø2Ye'xC_-Xm8p1ސ{ҀNx:J))){U&Kg)1\0&)¬!AU*sTQ>I@X.0t$ c&Y ,v̻\)Yb^ fIZvv[1Up|~xڀH^ݏ*Ž8R)HIűnգ 2 q5|d|ydzo l!Kk6-*+\9GkCS?eI]pw[dW7w ܯ.s梯;ψ]jX6ʵ> j.g1W6<^Nh^Iֺǧfz9g~MF%kӵ[s=gW_9/WZG-!+*z{W3C-[Ld8=GgpMZq2W̞YMddtҝI_DxdriJc'8TR&jZwm3$q;;U$ڷMcSAi$ |E^d\~{p$#t|yxMEmZ}^B;`!?p!p͢3C H3zZ]kw=q!sOx|qiimj':l 0_[w)SX`֞Wxp)…W)91HTbZI<3TAj!KNhc9˝ǯJ#1*ݒP(8S'UE pe 2F$HOa$1RPcS';be'tp{t/Ӏܠc d;HjCIM HT4 .mm\wDVYZ5=23U\@$ dm}ScSSNe |1D=+H {`sBǥ-ICPO,~HGHryWAu)G4)X` EP!A4`xE,HyDzңs|29Z{hDqm.=ivR:Ȥip(PF(&QJ:(;(hRQ@R<L:RE2XӀ78bRJ@:As@~zS;)sKRh6ڔsNSiA'; ךr'{R$}) V*&|?Ƶf+g#b^37(^kBgNpN1Jz?imW*; ǰ8=x1* ܧ;({秾|3Vmi Pzƽ];RʒGO^!ү4~,%0̇p$@_MJvso{)FʩܟOjueVMAm4jj-]d[+# #lan9=1\KkuI dA\BϒS;GQh.ioVsF,7rq=x7ݮnd' *wqzhZSw#UkX-44mmI9g8;ֹq)A$ƣaW硯@]Dh6఑^ضK*y87FJ[XVW7j<) $._O8 (/z:yȸ$c>#CIdWIDxl1iNwg~e+執WZF ʬR-85ϫ.2՘\.бc^8\3rcžg%:[k >diͨ!i1"icq#Gc A`cߟjtƴNh-\c']إͼ;U]2;Z-ֽrݱ>q] a'VemxS}NbcR)-&>x%1XޱT~?IBI<Ϝdeh@_72]]JI!3u5?ns/U P 7$IUO&[iw?.J~4P0$֛4*j\FO^RdJ2iR,*,`Аg=jT*s89̤YOjv & h!zQZJA֤SsKr:Q&͏J_k'[Z&hrH[!d=9XԮ\R 6Dt䮟F\585-wImojWl9_?šOaJ~.ë/鈍gvZ)P&+z*:φK{]HplrA |J|[a*_Mk3(Rq4k_':]_H,NdVk6pB]#_.kk*k7RK}\1?U׾Nh{)%=kZF Oo¸etUU%ezq$+ QrԦ]8#(,2G v扞9LqyaT)9 rek_#߅B"S_oO I׬죻>7B*I]c*8q#;W|2+]_Y zscZtm^i5)֍$e۵wuj "MPb81,I$u,1ENg%yz}EJ.+2oٿŗ.DA#S2(6W%q5c\^S:e\Gp+>1z wFIEs|;Z5:rwMY ڑ~o.9M!bI9{m*PK X^IF;W+Ѥ50rye15\EKsӓ2N4C2/iK"0IF$`]<#jچ$fK4򍫿cbz}*7(ZdpON3o(I[M3fE2PpE$v5A6-9(HOap hՍx*ٗZMӞ z*= љK4@1N <51LTb&!zRUP9S &@.g)j R)TdTTHn(>iI@=)4\%XFHGՃd2\ɷ'8;DF;j ;SpHҌ(G9%Fh(1Gր}E7Kɦ+)@Xx8iUP!B4{c=h4̞qE l@9E֗i<ZJ@gғ$PudQEv:ⷵ%xdHVq_ֹnly<@U.ĕSrN.˪\\TZj2$a1A3ִ3@TrY qִ<=stۙẊGh`N R|r*+I=g i'K ~LaFOshZ]dҜ^ۙYN?656e L`?OzɋkSXUpsQ&Ug)y;籍qKd_$y\AO7ΐ tuk>7?|#Jێ~Ngy [*y<A\KRc6 ~Җ&m݆_SɭK5-^f|lA^b:dxG! FݽJ5QWt٧~7G!upqe ɇ;YGuui\sckAhiV$I#q#Z^Sr3RMF夹mfZȷf[+MYy {5cd QYaA gCSW#KNzqCnT2C&1jH= g;j?y}ƱO4V[}@&95HCGp#c*,YƦviE- MQ/<"FeuS>jwޘ-p@~xbjޱ_jR%bYPaG4EM7OJ˪M9y骰p{2Xΰo=+:X$6SEz."ֺEXz8m9j ?+0fǙ[V+ .W?\@n^0kolu>iTKq8\!Ih˂+p8*]JjY8UVj4)zՆt䌊ջFI<џz]T;q OSQapɲ8╔PcKz;yǭ0N)86jG_@2wRZb{Rzv;t;uqwfy⏥ցjaE>ZQ4}Yi"h"銪5Dw"=ڔя!#1aQs$D=vEzo--eVCb~_ʢ9-,}A_Mw_k:KfNI`zw$wQۆFGsZ6mՐu=gMnJfP?aԓ Ϣq5EݍѲ sL l<֪¶dÜ}jb,iBfZHI.su;šAcҷɕǸ80M ЌdbzB5A2#"^mdFQcV$&;G2Œ8AeX̹UX@rQ{u>{-u Z¾֯@l.{#~5zn|k>;@GPުv-q4,QƩ%/O\o5K/ϮF}66{fEiTH@}`2W"%u|freh7Wn8y%O.ELNy=?q>7fxs!0:˽f AOQQx|hKяA޾F#sv7KW/Ryg2Hij{O\qjuɐRԤJ@:SZ`Ji vұHYU& 4F\RԕadSrh恎\@ <FKL$9]E੤'4gi铼}iD ذSϥ}ZKjGm趍%in+&'W Ewa}*$wG*"s\^.}G4J䛋=W'K/ƥny=O4}fXtkʵ;5ljAsJƑxvDHv$їnH?Lםx:$Gc|c<cӮﭖuK}adExS9f"1& [to٦ H5чΰNV7gz5i< ԒE$2SyV#*Tیm׬Vkkqki631MARtNt$^:0V!Sm'<'|"EyRm goAڼ ֭jƇvH>-`,bF l\ƿQV).abNps_jYԪYRv EPC wvr0P' M[mc ,q+4[hjr].7 -THĆ6<};|W-}(IVr=Ć49pW(O6TIXno+=~"$kDu;sDie[:ۻ}) UVlӚQmYQ:V'ҮD_cZilvNO'A+"!+`FsNliecծviD+zVz5!'30``g9hepUSxI !pGF+9֝9)ne}ȉl!Qڴ‘: Cs 9\~YeZI$)$}|k82sʄ4,@=?״M1e'2?A/CJ7]>ݒH0vF}~NhN2 |szuj*UJVeE=kPY$' 󻑆j Ve.^E/ b߈^n0L\2,S-=V P@>r)ʜNUok`v/-b[$i iFm3Q4-zYht8-킻"lGA^c⯆v1-OKẗ́ WNkxkjd7V<8^Ul*Q?_>=u:HQѫ~5|7բi_&Y[9î3^ZOZWa㉡o,=o?{Sr{F'4t\:qM. :Ӏxp$OzF+JVqWBl4)Q*JBc3,iT恏)Hj,OS. -1CGB+tBPEy\c yҥ$IC+:)W/z:gc&h\5ˑK)qv'+ہu(ù7crE̒-|(fLuFzӒ:flhZV&!.ɮhO-ry=h’#]:@&]g 8'д(o3gjKixEL`HW;T]VbZqoCji#2,@}VmSOӥ'&9`1J}pj Rw+񀻂ڝz`F;ğ) k&?߉c`^PN@g$g`Ǟ?:{eV2[MGd#mm;3Vֲin֘iN~m&dȀg=ۧ8sUޢ(:x7Ľe/uVbW$wӳLrIs"kL E}<,~."idHka-4]G2hhQH'2p9N) \1}*xդ;;Ҍ4oQARw8MbIn<ؚkaXg$2I@;si.u4جO(4hj SOsQs*8gޘ;Pxt$n~n)c\Z'i7wj3O[з0CjJL!jNc/o]|2,04ˉ% x8Ӧ+#H/(ە¾gAR1ׯi[ ExP*¾0O־xbJ]>ۇ4cek-RzdV.x=sW[,|)EK4\/Sդ2>>^+``u40yvW(aR ξi5}_ݏhm$0LH2=q._Y$S^ˑhT|9tKxgH6,tW WtOgJuW+ӊ$88#5k m HԒ@n9ϵs E8'=-;qMN{;UW;_gOC8xȞ!G^Ջjf$Z~A'??~͖&F(xIzT 'Vn>c[:1YcQrOk| 6Ǘ:Ƽ)xyӟ|5oh4킠}ܜڍ65w :3xj5}U\pjP#kwN;Ϲ: Mt`Czdd.Vy9aNsz7iZ2N6(ᑻ z~"xG j/=ۖH;ҿV!Դ6K0PrN1^e?6aDv?ȯ<;{Ko*$ӏ[gΛ$ isbl{?Sq;.ю?#ÖO-=8y:j׾$;H-@(9OašV+ٟAex%X+pI$¿U\Vb#-,kzS|FUtuK\$ԥ"cL3tcĞҭEH4FI6p {]ω$-z _ėz̲y7plp2}lg*_Wz馿"ORy4]>c8q[&4ZHjV]y(g5dzPj+NTݚni `ÊF펕D>6(# ihǨqM4Lf&1p GFl:RXq)\$sҚH## tp 4sHOnf&ٵ6z 'qXp֊B8Q0QRTcqޞ8(H4#vDGLhrIbSݎOn(OLy$uZ)B ,pW`qSS,z&9⑈rGJ,1gޓJ(R`PEڀi9J9w4w0xEi 0) Hz$JhKQ`>dbMvi 4IhޝT᱓֢5udC^:Itmچ92.Gv_o6o$aqp!G,1{W^MׅKVFq3_ zjwy#}Ab++{zJѩ[?7T~4G>4];eE@sؐ@Ͻ`LG1@85_tI ST4n.a-®W+nԏ( Ǔ"oVz[hsM;ȰPxMIe+H aIC%qS9$wX -H7s޺R~-$LnsO6*86?.fv߱\wwkhirdp9舩-rwGn&KdXUbzbMYP\r6=}k TV4 kmB3:L.Urk~- VHbHpČu__\j{`؎+uZmdjL^E cq՝J.p~&2Q:0ۦ>l1~F#_eߐW9k"y^H͵;:joCdZY$F33( )Y!ӏɁ4أZeztVZFʮ6H`cqM@C$铁s{e,i%r1Xz4"Et4on]a}}t YC( $~X X^Es7[nOnkG-c!8操Hc8^Hӥ 8tbmMYDC q?sq$ l=+vc+R~HxoS4hz?|ǟJڗ%u<; 9$R3LݎԠڂH;@Jx#,xF R)Chc /n0My3֔iCBJSKvb=<␒3SAK7íGڜ LZ&՘O5YGx*KJF2R?3wv. ̈m&ݼkGvD~Xst\0ҿG z+r3aVҹWZm֑o,&G+D\HFGqQ\C RF*.S)-N1zW0:n q2GrzT4Ut睦' G9U=)4[ۻ64'T,mFR5Z\l?VUi- [\ߣ͘6קet;wꡕ&@YGy흘j%L+1=?*.5[]7q':4q* wsa:pj_oS-:΋ 9=Ow n yI'ϩڪm2dz4dӁDXybꫥ뜝MϜ[zyxMzX"ÁF@T;#8⛚\P`RL>26I4t~r)LGj3Hcץ!agBx=*ʲ+`B85Hn i-s<Iӡ4Dhb]ѮArFG(~ks+VIx$0@$~U?QøYWx9=]׆yT}hq_̮}<.ze,24,K7="Ωe*ܭ?y=#OVrK,m$}fh)oeр\=ǚy6e\ Epڝog U'8{eSZo#m-m3^*B^ ɾ~.&nZA ]> Ur0|Xz_ kGSmJ}@H/$b.NI5~(KFlA:bzWo&2ě9~W(6X G=c;uY3y$q>8i(_ֿ#I )f4뷵nX)̐ʒ0SUaۭgݏj-w?u3HsMCaF(R~:} >IGckB-~=2M&UIP%=G?JO\[~_Dhs+T{-?;~,K6L˸ܩP{YISȮ:awKtdwRzV1$gO]QN7U(T[=1M%l53cӎG Ա hUF tl)#8p(ޜT(Pzb@20:)@N`)DDsEY g9#+84ПjddqUr-9H&xA4$FzR)3C4fLP!1Mݞ)NOzóR#BiA<0xz@h$;4tIE;}is4ך.+gZZŸjޅ>~rE3I; RM=>BM&CGg N)\b7Qҕbki|ٞ }-x~> RҘ"#qW‡=GQ^ TMW-Gd x_RnkxՁ'?Z?sxf+j&4 5YKqx7㌁ڼ:zƘd!b(9}ŞSaH0<ҼJ@QXm2;x,yç~E(ja[v>7-; -I1$g?ʽWoI|-CZ/ q?yAp-OɜS5N>NY&P6-»^A|Y2 w5Qnt{E2C+0n{tZlՆ89@ $5+);Sx H+''z6ë'Q\nN>ՔXVݑiPDIm$zlʤ: "#2vq] |?[3xICWE9׷VԜe4_%Ɨ餝q*ֵ5gm8xҨi:e},\I*sҷ-t/ulnacۃ1-F\qᓶ:4"9T4*۰,WAk*I9 כiu2Ef!B9К}. V `t>m0Yܳ[;H"x-y?Edb*xW7c8R '߭t<+$ [:*I5]F$j)-H5_& iPæ ][Mo_ƱE=@־Y9nb;gh8iw ,w,P0>njPcnyц5(oe_ʹ)-B)&C1R9+#8"]!w$WdEG0 C qu2:8xVSAwTL_gsQiÊF- sVOZ*X M=Iеp(&4݉ZmQVDqM'i!Hͅ5 zVA'CQ¬rH, >N:W.u  tKw$]#N~V\uI qP"QԸɡ{pB[RxÑ|jҟjEM6&0]sNrGj@ئ-F{_JQ `H#qqȢ.&cQ\cyzi6@ wIM%WJ̀C.j)>;pJ /HXKXXCUl>SM7"M'57*Ô֞\(LV$Թ03GJPF:iQU P$r1֥XV@X7C${!B;!&TpҦYZ9NĦ*gCu4 ^C@Fic75%X;u\ K)R(:f#֛\,;>Ja4֘ W'7#=(MaN)7&zs@Xu(iz7,?!#4zqvQi Px-) 3FzA)A@Z\=w*zpsU$ԥ^ ߡ'] Ȋ#bcY02uHXg"unUZZΤ{~5o?&tq!㌚4*#\bb,{š'tjd&̸/9W~ɳ65  #c_b `#eO #8?p\ldK)<)Say|Q h Ȥo8=U*?L$`ْa+l.da*"!8*}ao~;pyg,uukr|qm]td]ilLNe<_ehe}yQL;@q&q ~U~% Riu:|Dyvr!Q/]߈zֶg]Ii#m 236֢>UqynuX5խAd(Њ|/ͨ=(<`jl8_,4ed2;q}*ƋY rn|5`ӌ1_K}GK&+Rju9FN,$1s#HUD`96%|0Km;1ב>oS)G[k“I̫V #}=+ikڢ>k[I1K@ 2}%b`t8t$~e <|lF);SI-־`,i MԇKciMpce(=E4I &STBjhDiSKgړAñmo01{z·=jSڪCvP$D{_ϑμ v~?w}s#goWظS[(W۷k爱jz߯&IZЯ5B+h.ߠQo Fs^2H4K#0p}O^x[B܍WJogh=E!#RĐ@?Z\M4-DЫ+/qsV!F`?~5񶯨\jzΡv繕YOkh՚N5v\NZߡ[#4ݚ\#aYoª''],1T{.:zSY}iqؔFP)q bj2ߥ)4֤441"jBrhXjuD)TRF힧I@[9.O+Q'Ehҫ`u7 Q#6xg㩤c !~1MG\&#*ZR担^N=j_'X[4&A@=C `hH\qJ.0)hF3QF1W:U5L\PsFQB OQYF 03 RNYлq׾+ e#x*B`zUȏ<؎:xg?J}g l>kK_XZ<`7p_znim*A{d<(ek2eoOM4ыW_7YLap=kt{ou8ɱTUy]̜~X<,A,&$vkolim' #JhO*PCHO~՗fx\ƒWOUpGP[m67VکƻkZŤٸQ.2/hsãE$Gv7׷x{FtR"ϷJTz#WcHYUݨTmsLxC|֧k뗚Efhnx gE9FTz*rq6_znNzҾ^Hll5+ (s)RH,8FQ:R3t׊M"F jheFQƓ΃<3i+GCe3F2BHܧSQ˗ܨ({ FBx AklIcpD;cͪCVvR"w/Dq8ɭW]2Vwca#q&U# (FCQnA)HHH;Ub[&9pA7Z^𬯖f$,zitxT"<LTI$ihey*Z(cL 1\RUFTais?ւiҝ@ wJ94bݝдf9B0%e[؊WVve]@-Fҏ1t02 F4;QpdJwB?Zj O+GSk?V*{SJP=hX^7M'~M(c҃@2M.#`?w♸Pyd[I)=(^iNi '4FxtCFsޙ"L'@9<Ҹ$=3(Z .0/Q֛ۊz ѨOi4~p) F )Zܬv4`;bʿ[|= ̶VLm/q>n|" 9,=N݄H=Q_~&y=7;6~_gZt15new__/uO cS׈Ll6kex+#d8''8> A\s+$*sC̋l[p:U9EE(^GiȖ4@w9#ڷoM¨2<-!(3j / VShC.AGJQp1_ye85f3OֳNh_nD7RߌN{׮y(SM4k|%&M4g4Ļf5Cp94Niۏ@֗wT6'SzbhsLV47=ޕ7)!4S7Ra>ԛh҃M=B8O=k>t[T!m_}Gp^wj,rjnB8R=ʣkCxMb1d!  k[Kco_ےr1W,0>l?')Hk7y{9Y}v+ʍNG8LD1hi$aʸkvIA=k$q #*cv7HNC'uvt HyJ摦ں1DpWn=sLȕG_zZHFLU.11*14oDf˙Z֎mH`v@-"De[-? Ɗ6WX|ݑtz父ti\D*=Zgk9;DEc5mmZ[Ґcjm{7$gv֦F{_\.;rbHF0zs\ɒkncUYԗV~UҧB'=N0j OV<H^6c: 9xW?xKsu;}L,Y[t`ۃ_Uh;N?ƿ8*ynW}o~ԓRm[D?i^6I=Fk$[!|cEpR12ȯ&'޿F\3epF>V6_vcR:❂;HhN|$Q`h<9Jp4uܣRr9AIXg֐njYBOcFr) v}Oxi335$y-֡8a 6)prÞ'>v2x a {:wp4R*I57=aӉQ@Xv}iӁ3@Xi[p%Xu.Uu2 A#H$-?Au;kga+#'VRI/0JirӋoȤNk~oXo.o!V<9_A_΃QH 1Ϧk*XF18s_|M %)K~ou<7X\\Tv]["|;V !y滭+PgO1vsGzm-PInLl.a.;|ܐg79s3 J)r_#H e^yPL TשXX*7.rL9\ǽ5SY#ٴ:D o$<4#GgktiG ; r/8QjӺ=9^X&GMd>ѧ|s~{^ul$D jVho?Ȯ:ѓ{ج J5"𝼲02(^*鶻eP1E={{mBmy)qm!:PI-hIs}:#(Nޕ f߅4?Z5xcyܶ/ W..R{kyp_axZx ;T|8%dCS^b(ٵn va"՝c%r:EVfJmѶeda';zg?\+[ EfQj+πQM NmAᡪ]]EG:Ǽܙ{zsUč̄aNiԕDk릝CYՔ4߹fs'&'F;Tri/GLTP ?RAVⳓ Bߊ*6qE ñ{iAE˱ >EҗvzhM҂pp8LsLV>pHbBHM&G7x,3J6s ò=h:gzMhA2rت+O"mB8;p~4+M F=z NQ@34{PqM>gژ'=Ƌ–z HM4'2)R&x)>dr@''֓#!jvMޛ\rǓRPdӥ#IiVM#z4?4hJ[(euv*2,Jz¿AxB U}?֩[+7+5ndEB'A~sĕ>^KOxZ'E|\ZE.ksr{9mpȢ%Ć!N}I[i<vՆ| OYPkTs׉R<\+#Q{ .ҼqĞ?nF,zW8-=qҺ}*hgGʽN c\Q] m3SvU?Z|s3Ku`# h](.vMy^dG7'dq1zbQa%J0Ӟ%-6uܞzO2'5Y←j2kY ysM%$=ێini z\Ι(ڋ&GL҃z`8Bh҂*0}0;cI4wzii <RchG >rzU53{hc槊B3U*DnA;G񕷇kmjuy#e,7'gnv?~WĚ3?*`N8VA|aoMUYGWqjªK?FEJz%96Y1 b`XL0yDՎZSX+8unݥuKi4sIhY6HldL6wۛVGdUPsqZě+[{Tc$55r*~sF}jkym`d)&j+[.e 3/%t tvՎqu*,O$OsECѴ̱lG|KΙAw̤oqOEݰ8,Jb&\ɪʮ_FSߕƳzq>Ԑj{(u <38{+F" ;^.N(Bbni)%sM"4(n)Bpi\vGx4w~*T)bN17KBZ"'NaZp6ё*r+RqokKm]KQg S2\H_1!@$Uדy *\+70+ vkͫ:ذu8"8=>H dI ڤW/1U%MGsne9{?:]w]@60 }@VB8OYs$!UO><xb)+M)QG}71U[k8'WRthGrĜzc5IpqFF~Iq.ۣDF~rEB&Bq֕ҽK8lLϒz 0*IQO'qX𷊵okz<%t*; tgXoFtŐ)GQ!bMdzsLY|g5U;IVCbT䚯s7c+ŏ\Drj ޢ2wn4CޡlϥEy)n%+9l8QQvsXXp9 )d҃QvAP\2=iAs@X~h{ X^)A{҃NaZM=( )8eILK)vэc2v#)AsL4PTyZw iw~5=wP$Z\[A,JX֌dVzQ)CQqfnii2Pd>٤A-&ZB y3pS \ qG"iAe)j3@X+880j0} f!?iqF c'J]qzBÜ Hm' Q=֟xY~BWc'J;cw_bKtE>X81 EӴh"G8?(d8B5&fUGy}[J/ww~/4vG #jp3 6k֌O$acTNj^񯩾8#;;23ԂE|ZwuN6-3yZ役)r3RGuJInjqX1U6Ѯ~ ԮMXP2pX{džYԢЮEDy"s6Y G^2H!fnI'$Z5iisiZ"\mǟ yd+J] ZVv?8jNXRoݎqZB{IQ }gJsɰ3azF`4E+i'oJ)J9jK3KyKLMiARS$xj yO$&X⃌qM8@OJ M&1rh&y!4)<4H=@= ` sޝpÁJ*6bO'5W6H5"Sc+cFG@SAkMm{ះ\<6Hw?kk?هƐ %LlAJ~-aaU}Y,\?'L3a]\]dRzJl二[˴ y5YiSΝG4+;Mc]IxoJՓd..JVrv}VkY1ɪ=EIw= S.W,ri7PVzKBL֍޵sKHvz3L'@?qSsU"GIr.qLV&4u4h $R֐)8wIA#a㊖Cg5_954L^-$gRAl8j^CiҀOD,~R{Q7qO֓Rw(&sO&&íRsu ~l; ɮWV<6\'߁5͏ӿ)uMj}}] \sskY4.\6r8kkщӤֽZkƚ$HP1_PQbdm2rc7RNP0za$14INF:-N%U DnFo*T* USrO i *94WYG#Y$G!eXO*?^Բ\m+$RR,ڂ`&k/TViʰ Fk?Zcuye=.ie?ٝZH*eAɦSs6χVo*e^ 88V4L I{]#E<vW qeq[\]vv{[sJk3 '/1>0`s'{{%rsxҶk3(`gSVsLid}=Mhݵտۡsp@r ޕi^/Khdm6}rOZoāEcZvZRP;RKwDIMfR#7zQp6zL ( ióhɤ,)sҐXvGZPxuÁ\i8Fjaa۹9ih;u)l 7PLNans@X~@i2)\v gfËds7{SXx=L&&4܊7R.s@9LnH,; R1SNo+V%OÃ:~uGUs4^$5wu+5gsv"%݂r ?j{ {ykYezdwYQh5-[y 8ss6Y,VbV-0 [Mai[C:wtu1s޵tKY',:+Ah>g,H q(0:ҴmDdXcy@W>YK ٛ4kKK./vUQVC֟4 \i;{.;:G4e]7LF$.څl@NN2OIsO&/hSJZ$~MVZhi3Mm oZn*HE$'K0yw.sžAq2S`FyjJs҃ޛ֗8) p8&JpV;84ږIiJO̎N)HRq֓4n֤vuy8JÇ4E00Q M 搞yi7{R(~qN^jrhZ]goxZMOM"|%AYc9Ք}:^EtNL=EV?VUht>kLW'*v`ss_4~=iWN["wT~ʽ.}=ȯ1iq f e x=$^ \s:e qIe}xVtKUĊ,U-M##SU?;zAS=[Ē#-Z~aq}IC.3Jڻ ZbѬ"Kw(.pBA_93#9,IMixijx_e8Y: k|,[I~ZGyc<µ#JNU''֧,UK 53ˊ( T֤XCqM$^)0Y # ='&5&XpdќiҐ`0BTe\V_ƙڍåbM;uES4\,_I Z/#5}ُ$||MqT#~:(< z>)f2IOOQ׾AaX̌LʤQxd(7{i1U 'ĺMZ5-zrdzZqF,yX=UnLCб@NuCBq%üa8ՁxHI-K"48tj8YǖKAupov*Wyң,emW5-7&(O$GVdj0#*9lutX;]*Z6O=ʹ,X3i颺j ݼ!!Ƿ"/S!cz*k-~:%4*D _8|qjy82NU;=O^ a_3&:*xZj{HwbnD;SfG5:jAQyֈ͌K&OJjddS:L(Y9EƓN{LԬpU>4|sڠJ&&mxRLgTiIBମLvI46=(ah9R}i8(\掴sڌ&u FқAz.+IL(Xpjp'4h LM6*<ѻ֝'|k~))vy'E.{-Ѻݓ4ā&$bNz\`97a  Mސ7sH,-^b=4px}i3HO4qA4‚PM&nќr:v{P SK{Pn뚽[r3E4pS)(''ԨͨW-xHo1xVxm,(A' .+@VV= N \8clj E)n |c5sϛ%YI[=A>WةH߻o?bGϵhsL& $)` `~7#ͼ6H+5߰$23߻p*W۩e2!IZ*]M.ƛwcju=٭)ri-&ً21l]Gp{m`dGImɎ푀\cu(pbjsMt4m-TO ,`}LU,:VsbٵC +Ҿ&z;ڸ'G1]_~h/q$Hcz~u)%NI֩UφpuktsojJmя$w8WHfrIMjxė&#cbDh: ^zWy._Q-_|ͳWGZ/10j64yV%,sI,OzMEI҇ 7Qq cI3Pg&U83d;:ўޜ:PJ9Q8 8T\@= 0z;Z$2^G#' 'LH=މOȼrM&IP;9>dvqviHQ҃\'KNjw֩;s> ,ďu"*g1޾f̨[Y0# w? _ jE *m ^ܟ{!qxjF<ɤ-ϸ 5o^ O8vƲEasy򁃅#~5lg_qSIJߧCwK AZk[S խ9xe_-tK;i-LoXqI+|Zֵ2O& tsYUilֱj+NW'u tI.?Spq6}]wm{-.@$ƼLj%I XNr@7\Ijs%5ne1S^ s{obZv75?kZľe;!GҩGws4W2ʲcYIPz*tS$"ԩV}NLm*Euxf- %HHVRFH{ϡkgAZxFD[?ȡV1SNJO>%gNN*o{꭯áĩޟ:xlp0Ts¶5-oKѼخvdp3J {R sjQȌƻX6(_.@92F^#2Xsnldl윅Gz5guX&M&kU$Q_Z '%!OiQ9 BAW7F(BF6FBMm,7s~UΓSm5p[?Qڕy2섐'cv񇈧64;A}kԿhYa%AyK7؋/bıkaC ^_Z8*~;C`R)JHf=OJsުC'PMLZȒL{=F>S ) zRzrHyE84WreUu&:hɴ8`4i mRhW{ *6;,i74g4 0R@ϭgp)p N8 ɠgPON.zgڂh7.L ڀTy@XvisL'ލXx=dA=@Ҍ3G4#4ϵ0M(\7sMlbcޙ#7<ҳ TdcIEb\L4$Qp/8dupaހxi84 b(FhXp; rF~+ T%YaLc%A ~&tvU]\wHAWSy^beKhz5(ũK}U ?xJgn0Ӿjgyc'ؕ x2r=³<156w=A*pxږb%1f H/ӌ8Z_Cl)Mu<)ama2]t*:w2\)~AOOJc#~x aw(b0l!Vzg1v].VfGOD͞I#!ѓ?w0Phi7=(8j"85 굌 9ӚnsKC_4ST1(Pzn#dO3֥' i $ }h&ILIA> 4NG>Q+P޴}\K.}G\+ }O=J;&zPE * P!CxuNR8b4SiuMcSIAؔ(z`9Kv4\V% )fz4+ h><\hbqFi9%sKIGj@I+ؾWTkYI .dw8א%A̒:RN}{{7J",xÎFq#U*Q8+%{Y$ae)?%=+X:JG$d~U{]Υ=+ܖ,$As;5.`ʷ'vywrJ&8WU?Q5BWtx";HDoCn\zo4<]>rgC2cz-&*)3ki 9-*۽zYV]:[J/f2_`х;+ɱعc+έݤK?8`Y$urHX蓱FzniZ\w5HvFLӲ(KM'Ҍ拀4n&E!oJ."@h'4sK9VҜ=0M(4aRV1J3ښJ[0SZb:$wi p(vZe&}XRyLҨR(Oz5/0zlO+1)((p&Ay@9I$#)SIoJib{jB~Ѻ;'5*cGZM4)9ڏ0z$<ӽC<!p9 

Z^OKj5h/e͝GyQt短q|iYɤq.J1OdOYWv'4֜E&mc1#i╀i$QG'Xz y7))ܫ9)ܰ횏&.挚L4g&IHyRdvph'M4Q.qMz3--4ӸR Rz14v)AQ4&yyjw2l(֘ )BJB} ;HM&HZ7gL88iџSHc\asK@dh 7&ā14,.IS7>\7)iө(ӂ3 󵼏:N"^qMwќ }*sNwfCoJP*ĔM(4a٢7SqSs4gҐXvOj3&ƝĠJ Ev\ќSsК3NH (=0إLV%3u8`h 4P 8<;X\ᓜ rii?H\˜sj3Jy=) qI8cqAlMjLp3)zR:RSqAbzO\曞٥pM晒hyNSM(B$qR*.?"[?79zfCm\O`

cC^ƞE0){SXPRi'ɤ9>Ԣ&S5UJr*Zǽ74CuG"X~Ի=ќq@Xwwz4&6}(Qz怰Hi2h RdRz(&M!>( IqIA@&H}h')3MQ4Η& I4ޝh'4 E*HshE;b&FFܧr*tg-׊.&7ARjSxF cҹK.^i-5_$ EL6F6o*VY%7{83QC94u4IsC֐E)9ޚ -@H!5]wOIs)?\0v³Z4 OdT)ʬ#ž7c4W$yqX~y߃Z/(ˉʠO4i-XSXr}SHgգ"7Ͽ\WsRcj6hRa&j$p{QK!(I=JJ 3 ў( cH 7<րqhj^ړ>gvQj(0hM'׽,R{zJxh>@ h #hLu.M3'48Pq)F)'g=(4M Nh'-cH4bKus <'15նh~\WwM֐KY7bBq 9A85wtm4Ѝyi[nN z}]M DY{Gw$~oH^$ckZdgJ NٯC+5=DEn@,<{= />`6 UϾ+BoǣݻohV`}} 9퐵e]8/}*{ڦ–x!m%G2 8}kkx7!wm?mֿM)b~E ,Cx4<3QHIg4YĊy9T-W jz/,HxVcLF<69=3ޏΐKܚPiFLRP!曐:P@B)sL 8)J7=lSsLӸH 85E4+FHC?b9!=&s@m&{QHRN()=(z)qL=(@0䅦OFy)$g-4i@7^>iҀ3Oon߭G2zRޝb])jߓLTFyEľa(T J$#2*w ,̇Ҥ[ bC5TOhX'80RdC\fHwHsOEvZx"&E#GH u/WUZmP}g ҇RK)>)(F2w8O(;TdzVϣjWTE,ϱ&% 8$ '֍ӳGA4ߕ!8=xڍ担n54CEāQϽ0$4{S7w&ƀ$4I7Z)& MhsAH:\h&Rg֓g(4џz,Q R})t(hg҂y恃҃h`&MH*r)TBL rWtMA 4q#AMCJpLPqa{b.f]9RG:rgvV"`}jRVdITuƗl&7!x9S@#8fk{I噎I?Zfi0+*JvJ)7ԺVV'QKb7i44m*Jώ=J4rGZT\FE7=3ǽ Zu34(w4}iM{SEFoJ7EK`2GJ.$ԡę*0ݚ\c< oe ZL@pQcnk迍^.|I˵}Ή H#U%XO|J(K)uUTQMF8}r~Wv6Qbڢ65_ı]F#ID8G5~6ZDm,wH'}t:x}ZnHB1$8;Ɩw\\h.z͒Pq_M/߽GVwldֺ۶02?*Lg&H>sVWLԜ>Fy<ӋyVeB+V %k=y֏𢟫B IEs9!c28՝KTo$'2)*=kdݗ6-+ OG4IҸ;AF0;QQqؑBҜWCԮ+j.x8;'4ڑKA@# !n9(@Fx8Қ? "Ɋ:PFi3F} 9(9CCS3ڀi s)ޚڐ94B'44dւ}1ISw#dhS7&0@Gҗ9ތ) LE'H9p PsCqFqi !婹L,I4J =8 14IA(^G4M!\MHT*3qE7QXy9:x)[ր}i7 S3@9qxc֧Y@杸qM2\nYsҬ^ ġb9 3YOr)C\\בr3%Ori*XXhZ!1 ͑95IfBTdT$ڬtqI'}Bh縦FE3pQL Hhif8K43i,?<&Xq>M4JM@qMAn9ǽ&ئIPS7P4ĹqQJ qXGn4\,H4ns@&N)iM!#FNH F{HN)9ހ8>dў2(P^ץ.s(!a/AVưQr aAy5iIK/k)irHWrSұ8J;v8{`SL59954D '$QR{R;4zҸXv}hE;g0zR}F)'?ZQzѐ)iqoJ3i'{SG٥98sP&&r1NC@!u@XqRHO!n Rsړwj @;)EGo4 ĿJuBQ* t4i֐h $MFXcvE&nh+HOJi8IhXwjL{Pxq(/Ԝɦg;y+girj-ɦc4PP78K@]ئf.+FHMݚB9qL`h+<֌ -ԙ̌◭ isQ4ZW 8 =0hiA晟CA8?w8ޝq.F{S8UqXvN)A=,4 d Zw|҆3LOZzLv;iTfP>G(:M,H'i3MKROVUrsK`qT[-4}Hy$hr rӥFT(Զ\[IcaAi=u(98h yy@'=)CFqAVK2iV4:^)PiiN)ii8FqޔZnh8#.;X qPO0w7Lɣ@g÷@cS &FlTY>OZ3MҀ&:Rn=( ڛu<.'9EZ3F   .3ڙIH䄉܁Rp=h j8e<NHNi" ?:B44`q3JLFHcKDU\le( 0檻yLq{ўh('Oz\.02M4٠7 !aښ[b@ЭvJ1QZw4E47KCj2}h2h( Znsޓ<,I3LNz @}@.p3A>G8h#ړM8g /4q6ÁKQ☚G֌qXwQ{Ӂ힔):uր`%v4=}h.x ֘y4Ҍɤ1 Aށy4Q@ KӜSsK4\@Is@ OڀuP(M/4t`F .G:R3HCL'E&}酇Lnx#4;>4n@g7#h84Hj.cқשڌ z֕É#.O7arh ֌.H !'֓4\,8hJnp(pN)3AaA׭&٧p׭ F} 1٥`.qրi)3ހ &h=h49;4M @P)9ۉ=(&) q i D3?Nki]3Ԏ5$ZvvZh$MRD$mePǸM7R=>6JZKP[<IS)(b Tvm;WڒΠi>P;y4҉K<3'(yz&}E,lCy RnvǽxĽ.W⸲1,c'=;ӭ Ү= ~1M$7V'ݞj T!f4\,MҚ[3NbF;=i:SsGJ>i3&ą&OqLޗ4\,8\,;4}{֓wԔf44!<`.h"y4/IP Qi3A<O8Gj R\QW7\|U}Y@t<pW6 !+cTwK=lZgu}F@J[6׃ݭkqsxH@-6BEsSSWfdDc$)JLOh3G"6=i׃*~g%RW_4ۼ51yr.uVf(cJ.[3\ǷYqȨlN_jvvP\p'җn{`ǥQRyd{㇎a^u0qs{8>Uj>2pML{%;< \ڿJ>>>x^;KSRc 10\#{~?4)Z]ZKSNzv,u5啥k,24RQeau~|Fq'zdC#c8fW׏?chA;*_w~`д6N㼽.QP? fЧAgwnoH3\q5d0-8V@Ϸzc7vKcQoq(1=3ھʷЭ,P3OsթFf ;ROe+Ņ\kK>] rO.Rҽ9_TcM\:.6pvLga>_σpѠ= %zZiY;،`N*~raKߕϤ%YKi^ '#3J`+{8F#7۸~[*)T U^s4ȫ#zl-~Xj?#m=ZK;;]%϶cW(XytntyAu&n\K1qn_}|w>9|FM7Ae̺]q@P\g|oᏃ:tn&HbcBK99gK^Xw5~C_:7+X@F05~MmW0aU{ePJͻ?#tاㆫ;Z; ̫T86m6iaTDAB0}9zʡc܎jr^-'NbeWƶRaFBG]ї[WJ澧4mm% PGs^2kzZՍm2;ʪ,OPMz3h٣4bLlS7RJb>PRC (.M4EތsE"EE#[CҊ))(@ފ(`E!E N(hER) (E҃Ҋ(QE6#(z}ip2(zRcS` LQE&0J(Dy"袟b__51:%o21$$T p0(+g^GXJOrp+*U]p;:(_ėOb% F^ _#~ź~imk15KVB08<<|!4:(a07E,=i?󢊒֐J(n!Ph@Aڊ(.z (){Ei((5-PA(NQ@Aڊ(lEHESD1қB( QEQR.Ph:'"UC`~GQI W~z?E{=q2Eۆ|dxR kE>Ï\jx?I[aHO* c]i3CU m*(~nއ֨[TP+kU^Hcۊ(_É3KF?mA sU lp__k5#xv3f*"ƍ\*,e;Щ򪷚qhy`-28-%c&ox&2GGH~}QVr|"_4- I!efdp{qVmD0{O_-+Wu;:Th,g(C95+ڊ+ܣ+>iQVp]ukG5YEAgx-1i(HEw4$~#Ҭ`L[hrqw<ꢲ94Q_5SsVoJR?W+8$Ս^k>5 iϱpy0Z(z2";[Ŗi&,lAF`k."[;+['/WқLhR);E!Bh=({})J([ u 9EQHtkabber-plugins-0.11.1/georoster/bwmap4.gif0000644000175000017500000003706007676542400020113 0ustar sergeisergeiGIF89aR}}}{{{yyywwwuuusssqqqooommmkkkiiigggeeecccaaa___]]][[[YYYWWWUUUSSSQQQOOOMMMKKKIIIGGGEEECCCAAA???===;;;999777555333111///---+++)))'''%%%###!!! ~~~|||zzzxxxvvvtttrrrpppnnnllljjjhhhfffdddbbb```^^^\\\ZZZXXXVVVTTTRRRPPPNNNLLLJJJHHHFFFDDDBBB@@@>>><<<:::888666444222000...,,,***(((&&&$$$"""  !,Rg H*\ȰÇ#JH"A92f#G 3YIɓ(S\ɲ˗0cʜF89#@ )ѣH*]ʴӧP:uPX5SU`rĺٳhӪ]˶J9rfJU]SW*U{pX+^̸c*ٰ塒'_̹c\qFL:cr^ͺkbˮ۸m7Vs 4^7) %I]NjyA6ԪoR9y#;'8Y2;tw"Ͽx xm` 4G6ؙ\Fas0} HA=h8`ppߋ0*A9(0v@Ёlbb Sz A`L*hǔ )P6ر FU|C-Ǔ1iJ^B@vciCt'T v䏘 VfأCi (?4A"vrP<,hv֤騑ւJ*N̂>z꬧qɢpN0*Z-(<]-v,A]BkLÎzԂ P`r]-Gr{̂G}D+=v ˳UTR 0֒;& ;8,O+8i<48  G}@`0ŅnAr@@ 1+,sK3mK$,s2U#Tۺ,ĠBlsGF3'|?}KplQJmxJg]K6$,>T_QBr2V.D0/¡/Ap,SL-ߐ%E:=X@s;Ac f.6 B=tnKOp_{o;0% Oe{Sh @V| ^x <" @r yA_>:Ё|'! ѷ>(0FhFGgёlYؠ:x?3&%X̉qQnź#d3΁b,K|pAY7K%JX*\&4Ϙ 1*OTRn+q%5>Ҏ2Ena>Z7 6Ǧ8b-7#|UH(BP*>RLKewARz;P.9Ep]qr*QS; `9bՂ !br Ak%(BnGd׸ޠvC z6(GN<0{KYOV!Io)\ (H;8XD",J@۰j@LSDGYx:c5`tchSujKtv]_GehRJA 0:,5vMԡ1lY4GFݵq7ٶH;dQc!:FP]x~?qo=mSO$ғom3Nȼ=vp׳@ Er"H0?)Q5ͮA/e^P83ȸ@- pNyLM }Ѓ7AM jӂEAC}Pzݍ-W>^#x_Yy_I{gv(Ӟܽ*?-cuX6=7_W6J IY`@P#VO$._큢I\ gVCY1E~[ ` ڛ|G3D~ =&\n߼{;7|`+69W@AA+ 57#~)ח}`Ј?0 ȸ8:yGP ؋ЌC!@>;M)G x"뀎( E؍p! hѸH ( ! L1G@   9 )::yp@I2 y0ȢB ufaKVq@ qЋ7R9qLq@2ѓ^)a0,Ye99q( RYgt !U w :I B!ip)fٙ3Xa `iB (P cY\4Db`ɔ !1QnJ 𕮉=y" Y'8nr0 0չd"M31YpiT ٹ 0 9 si䙠 Jb P eIwUQ@ "F j9j& Р4Z\#f2z)jP!D@ĝ!:ZzD0@ :w`ypO*Bzwў^w1 >x aj@1pPeʦQ! Ԥ ߄ 7Mb!X-! Ap101 `zw KjzIPdoʢLVbjp`ZztnJŰ\ :`jw000J zI:?I@ЮyP@ :"QQ 0#r &q`#AK$\~eI0+`ՙ[ {I^1[CaF0Z<A 0gaC0a %#>#v1F(1f `Ks`lT+h #x3_`b̽h@7Ug&vAлk ke  |&gFnK@eȂ;Hp`$Q[LgQZk `LhP8ahp Hʫ8 H@Q% XH@ ɠkX  !@eȄ`|,l~L͍ r>@zu#̸C> \5K%>P@M =icpȁGq֫ +AAmq@{Pa-գA "i (@W:x} J`&qB k״W @3۫h0)ݑ`ҥ iG R ss,zCmx -g }(0{M( ޷ h]0 n1 & *m˰,&fbf &`1 { )`a6.WK L`f! @--@H0 b.-p0}m,sp)Q}9]ongp>f g{Npt/2 gpr:n 0 Fs0aN6b 0 3r0 g>m MP>J+fq峐q!9sh~.b`N0s  00 ͐@b B+6rСn+f3 F*F0 p0 $.O~1@13O@@P`];?Q,_CO3PUK >ϠAQF_0'$gU_P0  ?Jΐ9 _'Yp  BQe , X@/7VH1Q`Q,?2?هR􊄖 &  `mto(后 OO`j6Qopm (  A"(1KDPB >QD-^ĘQ#Ɓ8#R`#MDRJ-] GgmbgDP% XYHRMQ>#t E;^ŚUV6;'Xe͞e Ǯmݢ :0< Ǭ#^ZA5[… F|+}?6X;=AYd|^RCM/U@]kOƝ;fTdK|hVIZxԑZ/ [zRYc|~[vtS$NQ S -E q& $RH?܋=|"iK@P&4Tӄ@D%IWdQ%|BqQ$^0'EȤ ĆHA xDC FBIXTC0 Iܚ1J{jp"Yp5$LH&6( " bDT#& wFyR f c!QXwP$4." YL0$VD,H&(ȗx`$F.P%EA&X2EJhM $!%Od]&ʇL\%" i𱗒+ 7ari,B%5!s ᜈ; !MF qG:SD֤'6MMȡ꼠B%BOi NEP#)  n aAJʂsT7dz ʔ"$>K.BdjSp%:IPz  99"5- ,tҢ"F `U LzZք)@ӑ̃()Q ,HC #PHZ L!1m'] Q #+XxvZ% ΂v)E2: HI8O0 w[H1DKm Gʈbv hK2[vMBsaB։@ [-IڔaDBY-o)@&=wWU*[#X%B d;y2iY@Y0%Ѷ@.mCShh Bl$0F6Vц)q+d0A~O̲HV KVDd(rY00Gbod`ņ  r¼\Y$xmCYALy 454lY 1`tHH,daG$d>eQЕˢ>F$nE `ZY0AtS}+< Z!J",P+hH2gaQEuAWvd%n611D1nj@{3½ G[vV=i4Bm^9fxJxBSxo| 8|^uMyGMz3gWb 1b薔CI! ,u)Hr(E)qKؤn\k5.@H@ x!AwB ! P & @bJ. ~ w֐q" Z#RG8"#@G "Uxnh'q+\a<` <Jj/`\7xORXc+k tHz^$OH^$ {`-m$ϲ ) *?(A@? $=xBP?[CR רnP{ Wq@lC!$9@{ $ \ /k>kDA3xWWんsAppLx,8LIAWア!t9 TuhYHd(*k; CkLH4Ј$;C/dsC])pk cCL5XDp=#.Ȋ+XěHLL CLĮIKdXDXP?RLăEhYP=D(4SdTHta S8,#S4Bp;k$FPpoTy9GhFHBŝkvlǓD:9GQDlrHprcD `Xu؆w܉GțۆAȬ$ǃ(RrTȊH$(@hĆ9Ƀ"Qss,&l谛Xɕ*`74Dz@3Hs@StJ "@ ːۆ#KhˁXK)KXq}̈0Lh6-KɂƼ e0Lq\I$@"\LREʔtFȄ,,MX: J \P(( @ a$`@z w- n᥀`_ߕ*ZnlCҁ_3X@x8&(#f#ub{dg⊰u⾠nHcb8r %0b3F`?*@P#b``d`b:NH^ :.dCK7f8X>1# Ӥ a`T~g`KL塲Q3$=CAa~ @|` llzfX[f\d(]vЍjvQM.0n ygк{nYΐ9v>CNׅ ^"}*(pg;X׀Y؁ pa#9PQh7bƒ"^1拄Th EiۺjyلPjKiPΘD稆(fM5^ybUxfhpkPwq$%q!NhhykIr\эi;Y聈X =QvlXzioX ƀYqΆ(bT큰b0j0/ǀ"& xv *HۡMX*(䮇!8E잕@BPT!0offX ϖbZ/xoo)|kP!o΄0hA nllދ HYn A`m97w0Є0M?g^YoXLp1 _H/0~qDB6^oaPa*̦%.P_ >rI&WxHMa `qr .nLLȚs; ` M() l7-ߚ jp #0w6 LHvP;a NT)LpxtK$)9QЀ=~T`/!un>:[iu/uuPIHJ`Ll IO6s`wnxoW'{eWr_|Ў 9ЀDЀnw}7i { %yxbDAtW ͹jxx_j'Ƣi7 )n79v-i F"Ma_g1|H02>xz8}`U{Jnț 嶝1vpQ}oW}O7!*oh0u(k} n()kHjP(S%}ذZ^ Fgh8qY,h „ 24 Ĉ'Rh"h 7rja,i$J"Al`54$y ("ˠB-j(Ҥ-ylҨRfrjjISxlRXm-ܸ ҵ ܼT=ycBfa7 k=l2Bw г<(nh\@nBbVL$t‡ǭ]oeqwojJ%n4kw"ud7Vn<]]-uoGj"3e=D`DXA%(XN;%7!Y"VT(U|58I]GXzc("9 zU(<㣎CDASE uD fP]OB0#!N9A G,"7ܰFdr)Jct gKzLd,7d%݉T"p`|J*<|CXqcA.ԡBIzD)%ci%0Mz*r{uԪI*qC+% ʍDCխ, 9A,N[g%T4Ptʐ{QADyMA.)8 .lXF%No%#qB+7tFS/$2 |Mh,Cr3\4w\3&1E}X@&r KW@(59,c#=<[@d pB"?=TN4]wp͞7Er-e=1> (DWŃ}@WKtCxFTA僛!VOz᫳pA0@F|2rUP5|+#c7lD[W^=v8aA?󢍅2F?BzkxV9  KqE1"lf,,yyAA [qlafL94 < %X@Pp~$4l2σqqC99rh }XAAa#?|#HMr 5HC% ^x#ĉdAp%cdI!ĂW'X;1|0IF25GN:C/"A`b (d$H,rLڸޘSb0-biYnFJIt _'\2Md(+ą )d/A ̾Oxe/ @ H&Df`0! 1 SD04MI᭔&(3@d$Q& (Hp}"?0w2tJ<7P & @рN2a90ρL 6Ј pDvX޻EVjM!Z( ːT 8C# H$:9jQ `T ֎,é)ET ukYOS4캑 QݫQzFX^#ZjNj@bcEnP a@c:$kVXxP_qZ@# Y8:.{6Wd"-QbVlh (DB2 *gU 9٥K [`#baRwnD{,% I lFb"0z(oi u$eH "@`," t'2 *Ě*l3D vg!%H0+Y.(xuWh|c*A qfSLjzn$C%" *ypV-D2+,$r%d4>. %DY$m(b J(): 0?ϫsśgb q@Od9u\tAKO汪 vc YM:u K_c.sEMg  HH׊bl{Alyc}qQ,=n{fdn ".䵝yW$5 n5p┥tw"'юi|]ܜtv Y5T ayL9sa#`\*8y]Wd ^HEzcF΁r|MJ:EQm {bǚ>86q@!;1ׅDEaq%BpG 6hҲӬtQyhXbtF,P3?zr^{Yx=ʿq yB0{jsk`АS DjC=|>`h)O7cE=eL)Xq*#,EDB 5meS,`Bt—4P!^C0J,D | I |L6D7B P4 @ IL9G "D8 ]N 4DBI8 {X HaUSDs!@uqԟ`&ޟ)Qa=t)Q yXJ! bf@$@!agE|@":bz"J(-_²jArhxIl_¾oɢ*4_/W_ָuA-(;-[,\ #z4#]⸍-J4F8`<(V:6ʇ ty8FOU`I]ā*@8У|أ;GGU9*] ("<@*dsP@ EaQ9E\Gr+N}\$q$dsUFJFJr_IG0LU&$E GVD DtGADP:E\x@IC!FǨlU>DҸlCT2ͮtIBn@͹I 2H$^D0VDX-.[I؆@tXXC\HDپ-rrEA.v۲nEC"W;Ѓ*f'`fC .DD0Af\'h: ~\u쮮.V.//&./6>/FN/V^/fn/o-t/G-p/G-hZF-Ap=|o\,B-hB-lC?`/ ؀ D`@OTЀCDC?P+EN^NtRl&_o/þ/Ғ  ݿ j;hh &@@%a,9EFQ5 3f0?!sL)MBҤEx"ى4鼜1}NZS[M{zj 'kb.{FjdzܹoN~4O ޽cwljU S"E7b+U za=֪&;{2rФ^JԬ[! ڝh3)ƦPț*idM6\Kٻ3ns:_hLJo2HK|sP&`3G~G[VMyMȜq {q߆„օy<@aHH Q+~GEHRq@ی[fc5kB^bx+x䄯pbIn^D"2&Kf(%b V,_Fv::vEift`hh<('T7z6 Z]/Mv%\y)ʩ jhb&|>SRZ/r>}cFzwd :Luh:ef),_jI 3əF򸈉JϮV{ⷊd@(G fYX+lzd0/֩ [0p8h]e0"Qx17 㰱.ȹ\ {*uipr4ۢ@ =1\㊻:?s#0x$Kup.ZQKpOq ?kveZ~d=W{kz Qs'B or87wF(o^,gGN1sV/E杹ýlJ/s-9G[.MgN*+}w2<(粦2N< =w33;z_7_'мeI\3 ?ξP+ P?Ow\[/Hr c~-h}n48: |{P8-,σxW6{ {t9nO#>S7VpJdU%Ĉ,(@|Z x2N ".2Eup.^PtxGͣ/,R2p!D!#'؈ǐIo]]gRɀN:C%XJ~($a/PgI]W:~@k| 0CR 1ʬdBI R|v2FDT3 A[NCxH %ؠ7$n|":Cjd @0+KL޲wIzt~Аrj1cUY4gZ{PrrkNmiB> LYƮSE@$[ĊY~ԬSmP+6BI#6[`q-86 nTq[7xckJ9(Kze)Ywx!)wҖh*7ݕӔ* U6ia"wt R>o S/k_6~d)qAiZgn9`f pbwjqoߎ Y~p_LZBr%1M|:Mӊ{ y3,**n/sQ۪yd\0Ç伾Iq|XaIdN</2{] 智t6Ed@Wc+͹΄*N}{H&z2U1sɅ4jْngrt1tcKś. bqjk4limdڗcyל5Qvj onk5GZw{dA{0ze䧶U/heM|c9a{/5= <㚮ַÇ.('|!+O['޲VS|vJMN 6;SsA{7L7+;cܯ3нm#LON7X /]-{y&oץvao٧tyz]7)^tonv5O6ֳ~o[]} 0_a "~=-\o̻IÊ%5y+l;/>Esߕ'*u>۝Mv&I^^>5Xo> ??=E&rY_m >:b9rsܗU@6wd>FbЧ2A|"n~xjh7~G;%7vIwsxXGwׁ} h}4=#vW&*X)9s5Thd6SSy[98 5:9$qOm빤L.NP6m]SGG#7, "R3fJVeЄ)ZX}J}:UJ\q6BfI駊B[ZA;Ze 6Z7Éw4Qbi`?qfiJ6JcDc>(06F<ʪ6C):}k:zجU X4b:ZTZ*ؤp 'њP2Munb酪*%ծI^BٹuN𪧲x -6هj N sJk0 am-J{1Q;<K#[g8')ٗ<ɱ$SD8,{˵Qذy&K圱jh x]C+iBuv;T2GRk\1\(YK[m=˰؊'E$jꊷҥd4/[ K;j˸븏 +Kk˹빟 J-[3~%EJںKk˻Yۻ˺k#+{ +K%K[[KɋKk狾+^˼׽+{! ˿ Sz< ,L+%L<';L%l' i;DȻ%-L5l7 ` 8ÏC*^͡?lGIl:O WY¿줺Z'/`lg]i,}dnlwclly<ǙZ$LJȉǭT7Ęəɛl<<Ϋɩʫɞ iX{,Ǘ|ʬ˹ɮƭ(̥Mڀ۶ Qɹ=}P ؓtW-H3--yumʛǑ20 md^fŰ\@(m6}_z,.F2]/ vcܚPL{ȶٮލU.ƣANꊼSM$ínáF n뤽~+OE.[|fnȜVN.ݐew^þ؞^v>qI틬|5NnOp(>ԙZ -~ _N38  b? y-CzN5*O%MQ|0/ ?ǭfYޯ=? TB? o6Fo iJʞNM.':~]7!"t'no4TUOj7M>>|׳.~hoN1s>_J&\UN L?~oiO M[`m#KTɯ6/o׏ٯ?}l|MOO?O1u!hV{q֛wPI':T]}Xi\yn{#(f$#t6OZ^+8ua\6i=q wuކRu#%+-/-X & DKMOH=0_ace[Qkmfsu47Y\ACoV$8wKČ&~9k4ٕq!)i  8UAɔaT׏bEfq#=,0CDJ/\Ď7qփsfN8C!C(HaKO\Mx?f+R_E(fJ 뺖rT n9myG7}dK Q*B{u,˽!K1rp 㜼3Np?ǰ<4 KA$ͧav\c UmB6mNh{'TwGt ۾e.ѧ,}{r};a{?|G>L)Ңo!LA"lo&jsp ALBFLq%cB.JQTCNb;Qȟ!C#&ZDRJ"hJѱ-A+KôL/+͜ԴM1)(;MY- SK<3+PA$OAFg䊦9Ro!$H9NbQUuR7VQ z8V5Q]W3\o-֊TuUYY\]Ä Yc"E֒4Zh`qcJsZFt- \pơ=rȴב`RԷ-CBp3߅ hDY)1S1~߇3&+I K6YyEnYMYfU)zstr.g11F})E Yz(ÙаI[R?l#~*ܚkΎۻ);怫5v[]%1z(y .=%;pYn\@\泜V{Q !/#t֧>C u?[jzpn`Av!_m(L 0r{# ݇JB!1tĴ0, w!EA:-Ey1y XD*EWcw%.0Y-4ƃΌA.уuc:x̣E"я `I9=R,+5opD$4(IRҍy2MȄe<4^7[2/"DUp#&%a.{K(>)yNuҋ)L&-j*tdS ٴ uA#[ &  Y J&bمVHgg%XRpKWӞ6jJ3cJ G3?ϗzfRw,vQ Qmv@+>vݻ.zOV|/7+ڦGI'W N'=^WoyіmzɛKIfþv쾎bl0kז!$3n c)\3<8}`lX2q| qP2!yƔu ]\IŚrN۝Cʦ3o A{9&G,sGhN`Eu,g{Vҷ-4` i9V%Q:j~qt[jI:wQ}c[wֵ4Y[\dV/fSɩXTWUW6ljj'8ǝQwm˒IDymvuzH2@ﶾõV񖬯K׃ N6bw!zK*eT|1(g9)r'ZqU۬r˻p%o]ܒInC#i,!ƷuM=azslO;sSznE޽V5Ų{zsrL|_72'_œ2@-)CyJwVL =UTmd{ lu 0 pmpet LPZx PP PHPҐ0K p| [K0/b(,[OAwm# /Ffp31CS&%e25|6C7*f\ff3F8s-8%LZh54LS:t<CF_09q;3:xf1 m%׳l!>\ 3&cX:Ts@[21P0YAMpRBѓ>COC3QekSD1XH6(-YtDIԚ`_0ABFm"K|6HH4n OJƜR t$fC$JGJ6”[s9LǔHKHuF >ŒM7c޴JdWydIN/6I&?%3EkIPW: GQ1@IM7QWw?;6S؈Q05STA-TYG;`6j0=ob_%`<281c#dMve:VPNd'PdGv])*gt^VeSaeVK gC[69_g1Wmf71Y#VSieWiojUBѸlg8vO*hm5mNvB.hu9_XuљPKo+CoLѕXeSlWPwJ,%N6RP+kYp!e+./m6s59n"kFDLLg++hi5YL54Bc4DuqqP*@O.\Lwxix;ZuGl.5"4DY&OPxijrM?Ɨt)v;7`~O(7~w/ #v$PΎxaISs4 YvʐVHZ3!@wF$V/RB]3ɱhI]?t:gvE7Ea/jٖєO=IքFQ؉؎#ٙ@o* sFr9Y9ϓbÙ#5xǝCсk8'n+phY*'Az5@`.#3:=)ڑ1ڡ5/?w%CڵZzr'ns;@z'Yq]!Zմw{+85G;;זDw۾Htλ[][盖WnTø1K{oo~<һuO{yUI?Z=^=iXa|W[4uݡ7\yަi֏t zYua|꩞m+敾:神͞}>߾㾢Fվ[{)3]>槵_Y^J+ӝپ|=7vE_֛rNE.Me(iM1_G{sk_s?/zv]}[/*!vG[__ ]E?_ˣ5{b: >.?rj/z?P'+ۺ/03]#;z?0(Fx#2\'4*RV3M]/c+^sw^7<.m;k[>``a! b"#cS$d%P&g^'hhTT*k+*,mmm졭.noh!pܰ2srOs35vvMxw98zz6>󳿀v$# O%5!D 'h"%1A,IE$zl%A2gҀY&(\8Uڬ'P =M(ȡ2mNSFFT*V6J-ŵp_ǖI6S֢ot돭2zK_|x=.d̒1do#YL90f/sn&Gy}y4_S+Zr%#_nb`n ;!os"k3쀀bd0o>whmc}Wj֗?UL V ~W8vN@JBsTwz苈1T4U",+]e0ơ{kֹׅL7uy{q߁7} bm8{+8RLx2Z[gf9與G?1:>Ŀ;>twˬ9Ȟ;hۻtS<^|&<6By=κ^u+=}MT>r__>w>??"'ܿA!َ6`Ƈ@7[`>p<C2 g7PY9ZB&<6ij! cxɰ6 oJs !Ft֎%.L|%<(sTXin9bk,FMqa &EoblhpLB<걏\(Hq2|dAxgM-a9)Jy%*yI~0Y)_)r]-or[ )Lr[1L5h\&4V'qѼJ.J&u" FByunK:b'<)yF'>}'@*Ё=(BЅ2}(D#*щR(F3эr(HC*ґ&=)JSҕ.})Lc*әҴ6)NsSs>3*ԨpsF- 措S-ySRV qwխb*XԏUS,+Z[ôx|I[㪍ʵYPiWVi4ժiL*u5}8k԰eF$l^  Z6ml_IH& k pH falΰ[҈O+M!Rnis93B~C.S%q0-*Chؒ=o0*^)IzދZ}i|󛬊֗{=n+niT0TY_$;tkabber-plugins-0.11.1/georoster/jm.coords0000644000175000017500000000071007662234345020044 0ustar sergeisergei# # a coords file has two parts: # # - a section that normalizes region names # 0: normalized name # 1: any variation # # - a section that maps a region/locality to a lat/lon pair # 0: normalized region name # 1: locality name # 2: latitude # 3: longitude # # all fields must be tab-separated # all strings must are lower-case # # # region normalization # # # locality coordinates # http://www.heavens-above.com/countries.asp # kingston 18.00 -76.80 tkabber-plugins-0.11.1/georoster/georoster.tcl0000644000175000017500000006374610747411465020760 0ustar sergeisergei# $Id: georoster.tcl 1354 2008-01-28 17:39:01Z sergei $ ############################################################################### package require msgcat package require http 2 ############################################################################### option add *GeoRoster.cityforeground green3 widgetDefault ############################################################################### namespace eval georoster { variable georoster variable options ::msgcat::mcload [file join [file dirname [info script]] msgs] if {![info exists options(citiesfile)]} { set options(citiesfile) [file join [file dirname [info script]] earth] foreach pr [::msgcat::mcpreferences] { set f [file join [file dirname [info script]] "earth.$pr"] if {[file exists $f]} { set options(citiesfile) $f break } } unset pr f } if {![info exists options(3166file)]} { set options(3166file) [file join [file dirname [info script]] iso3166] } if {![info exists georoster(3166)]} { set georoster(3166) {} } foreach file [glob -nocomplain \ [file join [file dirname [info script]] ??.coords]] { set c [file tail [file rootname $file]] if {![info exists options(coords,$c)]} { set options(coords,$c) $file } } if {![info exists options(mapfile)]} { set options(mapfile) \ [file join [file dirname [info script]] bwmap2.gif] proc lo {x y} {expr {($x - 649)*18/65 + 10}} proc la {x y} {expr {(371 - $y)*9/40}} proc x {lo la} {expr {649+(($lo-10)*65/18)}} proc y {lo la} {expr {371-($la * 40/9)}} } custom::defgroup Plugins [::msgcat::mc "Plugins options."] \ -group Tkabber custom::defgroup Georoster [::msgcat::mc "Georoster plugin options."] \ -group Plugins custom::defvar options(automatic) 0 \ [::msgcat::mc "Automatically open Georoster window."] \ -group Georoster -type boolean custom::defvar options(check_vcard) 0 \ [::msgcat::mc "Automatically look at vCard to find users coordinates."] \ -group Georoster -type boolean custom::defvar options(show_last_known) 0 \ [::msgcat::mc "Display users who are no longer available."] \ -group Georoster -type boolean custom::defvar options(default_country) us \ [::msgcat::mc "Default country to use when looking at a vCard."] \ -group Georoster -type string set opt2label_list [list none [::msgcat::mc "Don't show cities"] \ markers [::msgcat::mc "Show only city markers"] \ all [::msgcat::mc "Show city markers and names"]] array set opt2label $opt2label_list array set label2opt [list [::msgcat::mc "Don't show cities"] none \ [::msgcat::mc "Show only city markers"] markers \ [::msgcat::mc "Show city markers and names"] all] custom::defvar options(showcities) all \ [::msgcat::mc "Specify how to show cities at the map."] \ -group Georoster -type options \ -values $opt2label_list -command [namespace current]::set_showcities variable showcities $opt2label($options(showcities)) trace variable [namespace current]::showcities w \ [namespace current]::set_option_showcities } ############################################################################### proc georoster::set_showcities {args} { variable options variable showcities variable opt2label set showcities $opt2label($options(showcities)) } ############################################################################### proc georoster::set_option_showcities {args} { variable options variable showcities variable label2opt set options(showcities) $label2opt($showcities) } ############################################################################### proc georoster::setup {} { variable mapimage variable options set mapimage [image create photo -file $options(mapfile)] load_cities load_3166 set m [.mainframe getmenu roster] $m add command \ -label [::msgcat::mc "Georoster"] \ -command [list [namespace current]::open_georoster -raise 1] } hook::add finload_hook [namespace current]::georoster::setup ############################################################################### proc georoster::open_georoster {args} { variable options variable mapimage set raise 0 foreach {key val} $args { switch -- $key { -raise { set raise $val } } } set w .georoster if {[winfo exists $w]} { if {$raise} { raise_win $w } return } set title [::msgcat::mc "Georoster"] add_win $w -title $title \ -tabtitle $title \ -class GeoRoster \ -raise $raise set sw [ScrolledWindow $w.sw] pack $sw -side top -fill both -expand yes set c [canvas $w.c] $sw setwidget $c DropSite::register $c -droptypes {JID {}} \ -dropcmd [list [namespace current]::drop_jid $c] set tb [frame $w.tb] pack $tb -side bottom -fill x set status [label $tb.status -textvariable [namespace current]::status] pack $status -side left -anchor w set store [button $tb.store -text [::msgcat::mc "Store"] \ -command [namespace current]::store] pack $store -side right set cities [OptionMenu $tb.cities \ [namespace current]::showcities \ [::msgcat::mc "Don't show cities"] \ [::msgcat::mc "Show only city markers"] \ [::msgcat::mc "Show city markers and names"]] pack $tb.cities -side right trace variable [namespace current]::options(showcities) w \ "[list [namespace current]::redraw $c] ; #" $c create image 0 0 -image $mapimage -anchor nw -tags map $w.c configure -scrollregion [$w.c bbox all] bind $c [list [namespace current]::on_mouse_move $c %x %y] bind $c [list set [namespace current]::status ""] bind $c \ [list [namespace current]::move_b1p \ [double% $c] %x %y] bind $c [list [namespace current]::move_b1m \ [double% $c] %x %y] bind $c \ [list [namespace current]::move_b1r [double% $c]] bind $c \ [list [namespace current]::delete [double% $c] %x %y] bind $c \ [list [namespace current]::delete [double% $c] %x %y] redraw $c } ############################################################################### proc georoster::on_mouse_move {c x y} { variable georoster variable status set x [$c canvasx $x] set y [$c canvasy $y] set lo [lo $x $y] set la [la $x $y] set georoster(cur_lo) $lo set georoster(cur_la) $la set status [format [::msgcat::mc "Latitude: %.2f Longitude: %.2f"] $la $lo] } ############################################################################### proc georoster::drop_jid {c target source x y op type data} { variable georoster lassign $data connid jid set x [$c canvasx [expr {$x - [winfo rootx $c]}]] set y [$c canvasy [expr {$y - [winfo rooty $c]}]] set lo [lo $x $y] set la [la $x $y] update_jid $c $connid $jid $la $lo } ############################################################################### proc georoster::redraw {c} { variable georoster if {![winfo exists $c]} return $c delete icon redraw_cities $c foreach nconnid [array names georoster jids,*] { set connid [string range $nconnid 5 end] foreach jid $georoster(jids,$connid) { set lo $georoster(lo,$connid,$jid) set la $georoster(la,$connid,$jid) set x [x $lo $la] set y [y $lo $la] set icon roster/user/unavailable catch {set icon [ifacetk::roster::get_jid_icon $connid $jid]} set tag [jid_to_tag $jid] $c create image $x $y -image $icon \ -tags [list icon connid$connid jid$tag] -anchor c set doubledjid [double% $jid] set jids [ifacetk::roster::get_jids_of_user $connid $jid] if {[llength $jids] > 0} { set doubledjids [double% $jids] } else { set jids [list $jid] if {$ifacetk::roster::use_aliases && \ [info exists roster::aliases($jid)]} { set jids [concat $jids $roster::aliases($jid)] } set doubledjids [double% $jids] } #$c bind jid$tag \ # +[list eval balloon::set_text \ # \[roster::jids_popup_info [list $doubledjids]\]] # #$c bind jid$tag \ # [list eval balloon::on_mouse_move \ # \[roster::jids_popup_info [list $doubledjids]\] %X %Y] $c bind jid$tag \ +[list [namespace current]::set_balloon_text \ balloon::set_text \ $connid $doubledjid %X %Y] $c bind jid$tag \ [list [namespace current]::set_balloon_text \ balloon::on_mouse_move \ $connid $doubledjid %X %Y] $c bind jid$tag {+ balloon::destroy } } } } ############################################################################### proc georoster::set_balloon_text {op connid jid sx sy} { set c .georoster.c set x [$c canvasx [expr {$sx - [winfo rootx $c]}]] set y [$c canvasy [expr {$sy - [winfo rooty $c]}]] set ids [$c find overlapping \ [expr {$x-2}] [expr {$y-2}] \ [expr {$x+2}] [expr {$y+2}]] set city_prefix "" foreach id $ids { set tags [$c gettags $id] if {[lcontain $tags city] && [lcontain $tags oval]} { set name [crange [lmatch -glob $tags name*] 4 end] append city_prefix "$name\n" } } set all_jids {} foreach id $ids { set tags [$c gettags $id] if {![lcontain $tags icon]} continue set connid [crange [lmatch -glob $tags connid*] 6 end] set jidtag [crange [lmatch -glob $tags jid*] 3 end] set jid [tag_to_jid $jidtag] set jids {} foreach j [ifacetk::roster::get_jids_of_user $connid $jid] { lappend jids [list $connid $j] } if {[llength $jids] == 0} { if {[catch { list [list $connid $jid] } jids]} { set jids {} } if {$ifacetk::roster::use_aliases && [info exists roster::aliases($jid)]} { foreach j $roster::aliases($jid) { lappend jids [list $connid $j] } } } set all_jids [concat $all_jids $jids] } set all_jids [lrmdups $all_jids] set text "" set i 0 foreach cj $all_jids { lassign $cj connid j append text "\n" append text [::msgcat::mc "Connection: %s" [jlib::connection_jid $connid]] append text "\n" append text [ifacetk::roster::user_popup_info $connid $j $i] incr i } set text [string trimleft $text "\n"] if {$op == "balloon::set_text"} { $op "${city_prefix}$text" } else { $op "${city_prefix}$text" $sx $sy } } ############################################################################### proc georoster::presence_change {connid from type x args} { variable options variable georoster if {![info exists georoster(jids,$connid)]} { set georoster(jids,$connid) {} } set jid [node_and_server_from_jid $from] switch -- $type { error - subscribe - subscribed - unsubscribe - unsubscribed - probe { return } unavailable { if {!$options(show_last_known)} { if {[set x [lsearch -exact $georoster(jids,$connid) $jid]] >= 0} { set georoster(jids,$connid) [lreplace $georoster(jids,$connid) $x $x] } return } set to $jid } available - default { set to $from } } if {($options(check_vcard)) \ && ([lsearch -exact $georoster(jids,$connid) $jid] < 0) \ && ([string compare conference \ [lindex [roster::get_category_and_subtype $connid \ $jid] 0]])} { jlib::send_iq get \ [jlib::wrapper:createtag vCard -vars [list xmlns vcard-temp]] \ -to $to \ -connection $connid \ -command [list [namespace current]::parse_vcard .georoster.c $connid $jid] } if {$options(automatic)} { open_georoster -raise 0 } redraw .georoster.c } hook::add client_presence_hook [namespace current]::georoster::presence_change ############################################################################### proc georoster::parse_vcard {w connid jid res child} { variable geo3166 variable georoster variable options if {![cequal $res OK]} { return } jlib::wrapper:splitxml $child tag vars isempty chdata children array set info [list CTRY "" COUNTRY ""] foreach item $children { jlib::wrapper:splitxml $item tag vars isempty chdata children switch -- $tag { ADR { foreach item $children { jlib::wrapper:splitxml $item tag vars isempty chdata \ children array set info [list $tag [string trim $chdata]] } } EMAIL { set georoster(email,$connid,$jid) [string trim $chdata] } GEO { foreach item $children { jlib::wrapper:splitxml $item tag vars isempty chdata \ children array set info [list $tag [string trim $chdata]] } if {([info exists info(LAT)]) \ && ([string is double -strict $info(LAT)]) \ && ([info exists info(LON)]) \ && ([string is double -strict $info(LON)])} { update_jid $w $connid $jid $info(LAT) $info(LON) return } } } } if {(![cequal $info(CTRY) ""]) && ([cequal $info(COUNTRY) ""])} { set info(COUNTRY) $info(CTRY) } unset info(CTRY) if {[cequal $info(COUNTRY) ""]} { set args [list $jid] if {[info exists georoster(email,$connid,$jid)]} { lappend args $georoster(email,$connid,$jid) } foreach addr $args { if {([set x [string last . $addr]] > 0) \ && ([lsearch -exact $georoster(3166) \ [set c [string range $addr [expr $x+1] \ end]]] >= 0)} { set info(COUNTRY) $c break } } if {[cequal $info(COUNTRY) ""]} { set info(COUNTRY) $options(default_country) } } set info(COUNTRY) [set c [string tolower $info(COUNTRY)]] if {[info exists geo3166($c)]} { set info(COUNTRY) $geo3166($c) } foreach {k v} [array get info] { if {[cequal $v ""]} { unset info($k) } } switch -- $info(COUNTRY) { us { set args {} foreach {k v} [list PCODE zip REGION state LOCALITY city] { if {([info exists info($k)]) && (![cequal $info($k) ""])} { lappend args $v $info($k) } } if {[llength $args] > 0} { set query [eval ::http::formatQuery $args] if {![catch { ::http::geturl \ http://www.census.gov/cgi-bin/gazetteer?$query \ -timeout 300 \ -command [list [namespace current]::parse_vcard_aux $w \ $connid $jid [array get info]] }]} { debugmsg georoster "async http: $connid $jid" return } } } default { } } parse_vcard_aux2 $w $connid $jid [array get info] } ############################################################################### proc georoster::parse_vcard_aux {w connid jid xinfo httpT} { debugmsg georoster " aux http: $connid $jid" set data "" if {![cequal [set status [::http::status $httpT]] ok]} { debugmsg georoster " gazetteer: $status" } elseif {![string match 2* [::http::ncode $httpT]]} { debugmsg georoster " gazetteer: [::http::code $httpT]" } else { set data [::http::data $httpT] } catch { ::http::cleanup $httpT } if {([set x [string first "lat=" $data]] > 0) \ && ([set x \ [string first "&wid" \ [set data [string range $data \ [expr $x+4] \ end]]]] > 0) \ && ([set x \ [string first "&lon=" \ [set data \ [string range $data 0 \ [expr $x-1]]]]] > 0) \ && ([string is double -strict \ [set la [string range $data 0 [expr $x-1]]]]) \ && ([string is double -strict \ [set lo [string range $data [expr $x+5] end]]])} { debugmsg georoster " gazetteer: $connid $jid $la $lo" update_jid $w $connid $jid $la $lo return } parse_vcard_aux2 $w $connid $jid $xinfo } ############################################################################### proc georoster::parse_vcard_aux2 {w connid jid xinfo} { variable options debugmsg georoster " vcard: $connid $jid $xinfo" array set info $xinfo if {([info exists info(LOCALITY)]) \ && ([info exists options(coords,$info(COUNTRY))]) \ && (![catch { open $options(coords,$info(COUNTRY)) \ { RDONLY } } fd])} { if {[catch { string tolower $info(REGION) } region]} { set region "" } set locality [string tolower $info(LOCALITY)] fconfigure $fd -encoding utf-8 while {[gets $fd line] >= 0} { if {[set x [string first "#" $line]] >= 0} { set line [string range $line 0 [expr $x-1]] } if {[catch { split $line "\t" } elems]} { continue } switch -- [llength $elems] { 0 - 3 { continue } 2 { if {[cequal $region [lindex $elems 1]]} { set region [lindex $elems 0] debugmsg georoster \ " vcard: normalize region to $region" } continue } 4 - default { if {([cequal $region [lindex $elems 0]]) \ && ([cequal $locality [lindex $elems 1]])} { if {([string is double -strict \ [set la [lindex $elems 2]]]) \ && ([string is double -strict \ [set lo [lindex $elems 3]]])} { close $fd debugmsg georoster " coords: $connid $jid $la $lo" update_jid $w $connid $jid $la $lo return } debugmsg georoster " vcard: invalid line: $line" break } } } } close $fd } hook::run georoster:locate_hook $connid $jid \ [list [namespace current]::update_jid $w $connid $jid] } ############################################################################### proc georoster::update_jid {w connid jid latitude longitude} { variable georoster if {![lcontain $georoster(jids,$connid) $jid]} { lappend georoster(jids,$connid) $jid } set georoster(la,$connid,$jid) $latitude set georoster(lo,$connid,$jid) $longitude redraw $w } ############################################################################### proc georoster::move_b1p {c x y} { variable move set tags [$c gettags current] #puts $tags if {[lcontain $tags icon]} { set x [$c canvasx $x] set y [$c canvasy $y] set move(startx) $x set move(starty) $y set move(lastx) $x set move(lasty) $y set connid [crange [lmatch -glob $tags connid*] 6 end] set move(connid) $connid set jidtag [crange [lmatch -glob $tags jid*] 3 end] set jid [tag_to_jid $jidtag] set move(jid) $jid } else { catch {unset move(jid)} } } ############################################################################### proc georoster::move_b1m {c x y} { variable move variable georoster variable status if {[info exists move(jid)]} { set ctag connid$move(connid) set tag jid[jid_to_tag $move(jid)] set x [$c canvasx $x] set y [$c canvasy $y] set connid $move(connid) set jid $move(jid) set lo $georoster(lo,$connid,$jid) set la $georoster(la,$connid,$jid) set oldx [x $lo $la] set oldy [y $lo $la] set newx [expr {$oldx + $x - $move(startx)}] set newy [expr {$oldy + $y - $move(starty)}] set newlo [lo $newx $newy] set newla [la $newx $newy] set status [format [::msgcat::mc "Latitude: %.2f Longitude: %.2f"] $newla $newlo] $c move icon&&$ctag&&$tag [expr {$x - $move(lastx)}] [expr {$y - $move(lasty)}] set move(lastx) $x set move(lasty) $y } } ############################################################################### proc georoster::move_b1r {c} { variable move variable georoster if {[info exists move(jid)]} { set ctag connid$move(connid) set tag jid[jid_to_tag $move(jid)] set connid $move(connid) set jid $move(jid) set x $move(lastx) set y $move(lasty) set lo $georoster(lo,$connid,$jid) set la $georoster(la,$connid,$jid) set oldx [x $lo $la] set oldy [y $lo $la] set newx [expr {$oldx + $x - $move(startx)}] set newy [expr {$oldy + $y - $move(starty)}] set newlo [lo $newx $newy] set newla [la $newx $newy] update_jid $c $connid $jid $newla $newlo } } ############################################################################### proc georoster::delete {c x y} { variable georoster set tags [$c gettags current] #puts $tags if {[lcontain $tags icon]} { set x [$c canvasx $x] set y [$c canvasy $y] set connid [crange [lmatch -glob $tags connid*] 6 end] set jidtag [crange [lmatch -glob $tags jid*] 3 end] set jid [tag_to_jid $jidtag] set idx [lsearch -exact $georoster(jids,$connid) $jid] set georoster(jids,$connid) [lreplace $georoster(jids,$connid) $idx $idx] redraw $c } } ############################################################################### proc georoster::store {} { variable georoster foreach nconnid [array names georoster jids,*] { set connid [string range $nconnid 5 end] set items($connid) {} foreach jid $georoster(jids,$connid) { set lo $georoster(lo,$connid,$jid) set la $georoster(la,$connid,$jid) lappend items($connid) [jlib::wrapper:createtag item \ -vars [list jid $jid lo $lo la $la]] } } foreach connid [array names items] { private::store [list [jlib::wrapper:createtag query \ -vars {xmlns tkabber:georoster} \ -subtags $items($connid)]] \ -connection $connid } } ############################################################################### proc georoster::init {connid} { variable georoster if {![info exists georoster(jids,$connid)]} { set georoster(jids,$connid) {} } } hook::add connected_hook [namespace current]::georoster::init 1 ############################################################################### proc georoster::retrieve {connid} { private::retrieve [list [jlib::wrapper:createtag query \ -vars {xmlns tkabber:georoster}]] \ -command [list [namespace current]::recv $connid] \ -connection $connid } hook::add connected_hook [namespace current]::georoster::retrieve ############################################################################### proc georoster::recv {connid res child} { variable georoster if {$res != "OK"} { return } set georoster(jids,$connid) {} jlib::wrapper:splitxml $child tag vars isempty chdata children foreach ch $children { jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1 foreach item $children1 { jlib::wrapper:splitxml $item tag2 vars2 isempty2 chdata2 children2 set jid [jlib::wrapper:getattr $vars2 jid] if {$jid != ""} { lappend georoster(jids,$connid) $jid set georoster(lo,$connid,$jid) [jlib::wrapper:getattr $vars2 lo] set georoster(la,$connid,$jid) [jlib::wrapper:getattr $vars2 la] } } } #after idle [list [namespace current]::redraw .georoster.c] } ############################################################################### proc georoster::compare_lo {namex namey} { variable cities set x $cities(lo,$namex) set y $cities(lo,$namey) if {$x < $y} { return 1 } if {$x > $y} { return -1 } return 0 } proc georoster::load_cities {} { variable options variable cities set cities(list) {} set fd [open $options(citiesfile) r] fconfigure $fd -encoding utf-8 while {![eof $fd]} { set s [gets $fd] if {[cindex $s 0] == "#"} continue set la [lindex $s 0] set lo [lindex $s 1] set name [lindex $s 2] if {![string is double -strict $lo]} continue if {![string is double -strict $la]} continue lappend cities(list) $name set cities(lo,$name) $lo set cities(la,$name) $la } close $fd set cities(list) \ [lsort -command [namespace current]::compare_lo $cities(list)] } #georoster::load_cities ############################################################################### proc georoster::redraw_cities {c} { variable georoster variable cities variable options set moves [list -3 6 -9 12 -15 18 -21 24 -12] if {![winfo exists $c]} return $c delete city if {$options(showcities) == "none"} return foreach name $cities(list) { set lo $cities(lo,$name) set la $cities(la,$name) #puts "$name: LO: $lo LA: $la" set x [x $lo $la] set y [y $lo $la] #set tag [jid_to_tag $name] set id [$c create oval \ [expr {$x-2}] [expr {$y-2}] \ [expr {$x+2}] [expr {$y+2}] \ -tags [list city oval name$name] \ -outline red] $c bind $id \ +[list balloon::set_text $name] $c bind $id \ [list balloon::on_mouse_move $name %X %Y] $c bind $id {+ balloon::destroy } if {$options(showcities) == "all"} { set txt [$c create text [expr {$x+4}] $y -text $name -anchor w \ -fill [option get [winfo parent $c] cityforeground GeoRoster] \ -tags [list city text name$name]] lassign [$c bbox $txt] x1 y1 x2 y2 set overlap [$c find overlapping $x1 $y1 $x2 $y2] foreach ym $moves { if {[llength $overlap] > 2} { $c move $txt 0 $ym lassign [$c bbox $txt] x1 y1 x2 y2 set overlap [$c find overlapping $x1 $y1 $x2 $y2] } else { break } } } } $c lower city icon $c lower text oval } #georoster::redraw_cities .georoster.c ############################################################################### proc georoster::load_3166 {} { variable options variable geo3166 variable georoster if {[catch { open $options(3166file) { RDONLY } } fd]} { return } while {[gets $fd line] >= 0} { if {[set x [string first "#" $line]] >= 0} { set line [string range $line 0 [expr $x-1]] } if {[catch { split $line "\t" } elems]} { continue } switch -- [llength $elems] { 0 - 1 { continue } 2 - default { set geo3166([lindex $elems 1]) [set c [lindex $elems 0]] if {[lsearch -exact $georoster(3166) $c] < 0} { lappend georoster(3166) $c } } } } close $fd } ############################################################################## proc georoster::restore_window {args} { open_georoster -raise 1 } proc georoster::save_session {vsession} { upvar 2 $vsession session global usetabbar # We don't need JID at all, so make it empty (special case) set user "" set server "" set resource "" # TODO if {!$usetabbar} return set prio 0 foreach page [.nb pages] { set path [ifacetk::nbpath $page] if {[string equal $path .georoster]} { lappend session [list $prio $user $server $resource \ [list [namespace current]::restore_window] \ ] } incr prio } } hook::add save_session_hook [namespace current]::georoster::save_session ############################################################################### # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/georoster/de.coords0000644000175000017500000000341407673666203020036 0ustar sergeisergei# # a coords file has two parts: # # - a section that normalizes region names # 0: normalized name # 1: any variation # # - a section that maps a region/locality to a lat/lon pair # 0: normalized region name # 1: locality name # 2: latitude # 3: longitude # # all fields must be tab-separated # all strings must are lower-case # # # region normalization # # # locality coordinates # http://www.heavens-above.com/countries.asp # aachen 50.77 6.10 baden-baden 48.75 8.25 bamberg 49.87 10.87 bayreuth 49.95 11.58 berlin 52.52 13.40 bielefeld 52.03 8.53 bocholt 51.83 6.60 bonn 50.73 7.10 bremen 53.08 8.80 celle 52.62 10.08 cuxhaven 53.88 8.70 coburg 50.25 10.97 darmstadt 49.87 8.65 dortmund 51.52 7.45 dresden 51.05 13.75 duisburg 51.43 6.75 düsseldorf 51.22 6.76 emsdetten 52.18 7.53 erfurt 50.98 11.03 essen 51.45 7.02 flensburg 54.78 9.43 frankfurt 50.12 8.68 friedrichshafen 47.65 9.48 fulda 50.55 9.67 gera 50.73 10.85 hannover 52.37 9.72 hamburg 53.55 10.00 heilbronn 49.14 9.22 jena 50.93 11.58 kaarst 51.23 6.62 karlsruhe 49.01 8.39 kleve 52.08 8.30 konstanz 47.67 9.18 köln 50.93 6.95 krefeld 51.33 6.57 leipzig 51.30 12.33 lingen 52.52 7.32 magdeburg 52.17 11.67 mannheim 49.49 8.47 marburg 50.82 8.77 meerbusch 51.28 6.67 minden 52.28 8.92 moers 51.45 6.65 mönchengladbach 51.20 6.43 münchen 48.15 11.58 neuss 51.20 6.68 norderstedt 53.70 10.02 nürnberg 49.45 11.08 nütterden 51.78 6.05 passau 48.58 13.48 recklinghausen 51.62 7.20 regensburg 49.02 12.10 schwerin 52.20 13.88 siegen 50.87 8.03 stade 53.60 9.48 stralsund 54.30 13.10 stuttgart 48.77 9.18 trier 49.75 6.63 viersen 51.25 6.38 weitramsdorf 50.25 10.88 wetzlar 50.55 8.50 wiesbaden 50.08 8.25 winzerhausen 49.02 9.26 würzburg 49.80 9.95 tkabber-plugins-0.11.1/georoster/howto.txt0000644000175000017500000000644207645260047020133 0ustar sergeisergei[ howto.txt - Wed Apr 9 14:49:00 2003 - the georoster plugin - /mtr ] 0. configuration options: # automatically open GeoRoster window set georoster::options(automatic) 1 # show cities on map (none, markers, or all) set georoster::options(showcities) all # file defining city names & locations, localized for XX set georoster::options(citiesfile) .../earth.XX # file defining ISO 3166 country codes set georoster::options(3166file) iso3166 # default country to use, if unspecified in vCard set georoster::options(default_country) us # file defining region/locality names & locations, for country XX set georoster::options(coords,XX) .../XX.coords # file containing gif to use as background for map set georoster::options(mapfile) .../bwmap2.gif # procedures to map from x/y to lo/la, and back again proc georoster::lo {x y} proc georoster::la {x y} proc georoster::x {lo la} proc georoster::y {lo la} # hook to locate a given jid: proc XX {jid update} { if {$success} { eval $update [list $la $lo] return stop } } hook::add georoster:locate_hook [namespace current]::XX 1. how it works (manual mode) you are free to drag-and-drop entries from your roster to arbitrary locations on the GeoRoster window. click on "Store" to save those values. 2. how it works (automatic mode) set georoster::options(check_vcard) 1 whenever someone on your roster updates their presence, tkabber with fetch their vCard. if the vCard contains lat/long coordinates, those values are used directly. otherwise, tkabber tries to figure out the country associated with the user using: - country information from the vCard, if present - country information from the jid (e.g., fred@example.XX), if it's a 3166 code - country information from the vCard email address, if present - otherwise, the georoster::options(default_country) is used now, there's a switch statement that knows how to find someone, based on the addressing information in the vCard (locality, region, pcode) for a given country code. at present, there's only one case in the switch, for "us" -- it does an HTTP lookup at www.census.gov. if you know of a similar service for other countries, please contribute code! if there isn't a lookup routine, or if the routine fails, then a coordinates file for the country code is consulted. this file maps region/locality information to coordinates. if you know of coordinate information for a given country code, please contribute to the relevant the coordinates file. finally, if there isn't a match based on the vCard, then the georoster:locate_hook is invoked. 3. coordinates files a coordinates file contains two parts. the first part does normalization of region names, and the second part maps region/locality name pairs to coordinates. the file itself consists of tab-separated fields, containing lower-case strings take a look at .../us.coords for an example. ####### tkabber-plugins-0.11.1/georoster/bwmap2.gif0000644000175000017500000003167007570234134020105 0ustar sergeisergeiGIF89a! ,ڋ޼ʶ L b(L** JԪj\#ۍ|N t||(8HXhxԷY8IYiyiiVSIZz‰j* I1 &k̷p * -=M|mZqVK->N^NtRl&_o/þ/Ғ  ݿ j;hh &@@%a,9EFQ5 3f0?!sL)MBҤEx"ى4鼜1}NZS[M{zj 'kb.{FjdzܹoN~4O ޽cwljU S"E7b+U za=֪&;{2rФ^JԬ[! ڝh3)ƦPț*idM6\Kٻ3ns:_hLJo2HK|sP&`3G~G[VMyMȜq {q߆„օy<@aHH Q+~GEHRq@ی[fc5kB^bx+x䄯pbIn^D"2&Kf(%b V,_Fv::vEift`hh<('T7z6 Z]/Mv%\y)ʩ jhb&|>SRZ/r>}cFzwd :Luh:ef),_jI 3əF򸈉JϮV{ⷊd@(G fYX+lzd0/֩ [0p8h]e0"Qx17 㰱.ȹ\ {*uipr4ۢ@ =1\㊻:?s#0x$Kup.ZQKpOq ?kveZ~d=W{kz Qs'B or87wF(o^,gGN1sV/E杹ýlJ/s-9G[.MgN*+}w2<(粦2N< =w33;z_7_'мeI\3 ?ξP+ P?Ow\[/Hr c~-h}n48: |{P8-,σxW6{ {t9nO#>S7VpJdU%Ĉ,(@|Z x2N ".2Eup.^PtxGͣ/,R2p!D!#'؈ǐIo]]gRɀN:C%XJ~($a/PgI]W:~@k| 0CR 1ʬdBI R|v2FDT3 A[NCxH %ؠ7$n|":Cjd @0+KL޲wIzt~Аrj1cUY4gZ{PrrkNmiB> LYƮSE@$[ĊY~ԬSmP+6BI#6[`q-86 nTq[7xckJ9(Kze)Ywx!)wҖh*7ݕӔ* U6ia"wt R>o S/k_6~d)qAiZgn9`f pbwjqoߎ Y~p_LZBr%1M|:Mӊ{ y3,**n/sQ۪yd\0Ç伾Iq|XaIdN</2{] 智t6Ed@Wc+͹΄*N}{H&z2U1sɅ4jْngrt1tcKś. bqjk4limdڗcyל5Qvj onk5GZw{dA{0ze䧶U/heM|c9a{/5= <㚮ַÇ.('|!+O['޲VS|vJMN 6;SsA{7L7+;cܯ3нm#LON7X /]-{y&oץvao٧tyz]7)^tonv5O6ֳ~o[]} 0_a "~=-\o̻IÊ%5y+l;/>Esߕ'*u>۝Mv&I^^>5Xo> ??=E&rY_m >:b9rsܗU@6wd>FbЧ2A|"n~xjh7~G;%7vIwsxXGwׁ} h}4=#vW&*X)9s5Thd6SSy[98 5:9$qOm빤L.NP6m]SGG#7, "R3fJVeЄ)ZX}J}:UJ\q6BfI駊B[ZA;Ze 6Z7Éw4Qbi`?qfiJ6JcDc>(06F<ʪ6C):}k:zجU X4b:ZTZ*ؤp 'њP2Munb酪*%ծI^BٹuN𪧲x -6هj N sJk0 am-J{1Q;<K#[g8')ٗ<ɱ$SD8,{˵Qذy&K圱jh x]C+iBuv;T2GRk\1\(YK[m=˰؊'E$jꊷҥd4/[ K;j˸븏 +Kk˹빟 J-[3~%EJںKk˻Yۻ˺k#+{ +K%K[[KɋKk狾+^˼׽+{! ˿ Sz< ,L+%L<';L%l' i;DȻ%-L5l7 ` 8ÏC*^͡?lGIl:O WY¿줺Z'/`lg]i,}dnlwclly<ǙZ$LJȉǭT7Ęəɛl<<Ϋɩʫɞ iX{,Ǘ|ʬ˹ɮƭ(̥Mڀ۶ Qɹ=}P ؓtW-H3--yumʛǑ20 md^fŰ\@(m6}_z,.F2]/ vcܚPL{ȶٮލU.ƣANꊼSM$ínáF n뤽~+OE.[|fnȜVN.ݐew^þ؞^v>qI틬|5NnOp(>ԙZ -~ _N38  b? y-CzN5*O%MQ|0/ ?ǭfYޯ=? TB? o6Fo iJʞNM.':~]7!"t'no4TUOj7M>>|׳.~hoN1s>_J&\UN L?~oiO M[`m#KTɯ6/o׏ٯ?}l|MOO?O1u!hV{q֛wPI':T]}Xi\yn{#(f$#t6OZ^+8ua\6i=q wuކRu#%+-/-X & DKMOH=0_ace[Qkmfsu47Y\ACoV$8wKČ&~9k4ٕq!)i  8UAɔaT׏bEfq#=,0CDJ/\Ď7qփsfN8C!C(HaKO\Mx?f+R_E(fJ 뺖rT n9myG7}dK Q*B{u,˽!K1rp 㜼3Np?ǰ<4 KA$ͧav\c UmB6mNh{'TwGt ۾e.ѧ,}{r};a{?|G>L)Ңo!LA"lo&jsp ALBFLq%cB.JQTCNb;Qȟ!C#&ZDRJ"hJѱ-A+KôL/+͜ԴM1)(;MY- SK<3+PA$OAFg䊦9Ro!$H9NbQUuR7VQ z8V5Q]W3\o-֊TuUYY\]Ä Yc"E֒4Zh`qcJsZFt- \pơ=rȴב`RԷ-CBp3߅ hDY)1S1~߇3&+I K6YyEnYMYfU)zstr.g11F})E Yz(ÙаI[R?l#~*ܚkΎۻ);怫5v[]%1z(y .=%;pYn\@\泜V{Q !/#t֧>C u?[jzpn`Av!_m(L 0r{# ݇JB!1tĴ0, w!EA:-Ey1y XD*EWcw%.0Y-4ƃΌA.уuc:x̣E"я `I9=R,+5opD$4(IRҍy2MȄe<4^7[2/"DUp#&%a.{K(>)yNuҋ)L&-j*tdS ٴ uA#[ &  Y J&bمVHgg%XRpKWӞ6jJ3cJ G3?ϗzfRw,vQ Qmv@+>vݻ.zOV|/7+ڦGI'W N'=^WoyіmzɛKIfþv쾎bl0kז!$3n c)\3<8}`lX2q| qP2!yƔu ]\IŚrN۝Cʦ3o A{9&G,sGhN`Eu,g{Vҷ-4` i9V%Q:j~qt[jI:wQ}c[wֵ4Y[\dV/fSɩXTWUW6ljj'8ǝQwm˒IDymvuzH2@ﶾõV񖬯K׃ N6bw!zK*eT|1(g9)r'ZqU۬r˻p%o]ܒInC#i,!ƷuM=azslO;sSznE޽V5Ų{zsrL|_72'_œ2@-)CyJwVL =UTmd{ lu 0 pmpet LPZx PP PHPҐ0K p| [K0/b(,[OAwm# /Ffp31CS&%e25|6C7*f\ff3F8s-8%LZh54LS:t<CF_09q;3:xf1 m%׳l!>\ 3&cX:Ts@[21P0YAMpRBѓ>COC3QekSD1XH6(-YtDIԚ`_0ABFm"K|6HH4n OJƜR t$fC$JGJ6”[s9LǔHKHuF >ŒM7c޴JdWydIN/6I&?%3EkIPW: GQ1@IM7QWw?;6S؈Q05STA-TYG;`6j0=ob_%`<281c#dMve:VPNd'PdGv])*gt^VeSaeVK gC[69_g1Wmf71Y#VSieWiojUBѸlg8vO*hm5mNvB.hu9_XuљPKo+CoLѕXeSlWPwJ,%N6RP+kYp!e+./m6s59n"kFDLLg++hi5YL54Bc4DuqqP*@O.\Lwxix;ZuGl.5"4DY&OPxijrM?Ɨt)v;7`~O(7~w/ #v$PΎxaISs4 YvʐVHZ3!@wF$V/RB]3ɱhI]?t:gvE7Ea/jٖєO=IքFQ؉؎#ٙ@o* sFr9Y9ϓbÙ#5xǝCсk8'n+phY*'Az5@`.#3:=)ڑ1ڡ5/?w%CڵZzr'ns;@z'Yq]!Zմw{+85G;;זDw۾Htλ[][盖WnTø1K{oo~<һuO{yUI?Z=^=iXa|W[4uݡ7\yަi֏t zYua|꩞m+敾:神͞}>߾㾢Fվ[{)3]>槵_Y^J+ӝپ|=7vE_֛rNE.Me(iM1_G{sk_s?/zv]}[/*!vG[__ ]E?_ˣ5{b: >.?rj/z?P'+ۺ/03]#;z?0(Fx#2\'4*RV3M]/c+^sw^7<.m;k[>``a! b"#cS$d%P&g^'hhTT*k+*,mmm졭.noh!pܰ2srOs35vvMxw98zz6>󳿀v$# O%5!D 'h"%1A,IE$zl%A2gҀY&(\8Uڬ'P =M(ȡ2mNSFFT*V6J-ŵp_ǖI6S֢ot돭2zK_|x=.d̒1do#YL90f/sn&Gy}y4_S+Zr%#_nb`n ;!os"k3쀀bd0o>whmc}Wj֗?UL V ~W8vN@JBsTwz苈1T4U",+]e0ơ{kֹׅL7uy{q߁7} bm8{+8RLx2Z[gf9與G?1:>Ŀ;>twˬ9Ȟ;hۻtS<^|&<6By=κ^u+=}MT>r__>w>??"'ܿA!َ6`Ƈ@7[`>p<C2 g7PY9ZB&<6ij! cxɰ6 oJs !Ft֎%.L|%<(sTXin9bk,FMqa &EoblhpLB<걏\(Hq2|dAxgM-a9)Jy%*yI~0Y)_)r]-or[ )Lr[1L5h\&4V'qѼJ.J&u" FByunK:b'<)yF'>}'@*Ё=(BЅ2}(D#*щR(F3эr(HC*ґ&=)JSҕ.})Lc*әҴ6)NsSs>3*ԨpsF- 措S-ySRV qwխb*XԏUS,+Z[ôx|I[㪍ʵYPiWVi4ժiL*u5}8k԰eF$l^  Z6ml_IH& k pH falΰ[҈O+M!Rnis93B~C.S%q0-*Chؒ=o0*^)IzދZ}i|󛬊֗{=n+niT0TY_$;tkabber-plugins-0.11.1/georoster/earth0000644000175000017500000001702610211463346017246 0ustar sergeisergei # Longitudes and latitudes are available from: # http://www.heavens-above.com/countries.asp # http://www.getty.edu/research/tools/vocabulary/tgn/index.html 90.00 0.00 "North Pole" # North Pole -90.00 0.00 "South Pole" # South Pole # 23.05 72.67 "Ahmadabad" timezone=Asia/Calcutta # India # 31.20 29.90 "Alexandria" timezone=Africa/Cairo # Egypt 43.25 76.95 "Almaty" timezone=Asia/Almaty # Kazakhstan 61.22 -149.90 "Anchorage" timezone=America/Anchorage # Canada # 39.92 32.83 "Ankara" timezone=Asia/Istanbul # Turkey 37.97 23.72 "Athens" timezone=Europe/Athens # Greece 33.35 44.42 "Baghdad" timezone=Asia/Baghdad # Iraq # 12.97 77.58 "Bangalore" timezone=Asia/Calcutta # India 13.73 100.50 "Bangkok" timezone=Asia/Bangkok # Thailand 52.53 13.42 "Berlin" timezone=Europe/Berlin # Germany # 39.92 116.43 "Beijing" timezone=Asia/Shanghai # China 4.63 -74.08 "Bogot" timezone=America/Bogota # Colombia # 42.35 -71.05 "Boston" timezone=US/Eastern # USA -34.67 -58.50 "Buenos Aires" timezone=America/Buenos_Aires # Argentina 30.05 31.25 "Cairo" timezone=Africa/Cairo # Egypt 22.50 88.33 "Calcutta" timezone=Asia/Calcutta # India 10.50 -66.92 "Caracas" timezone=America/Caracas # Venezuela # 30.62 104.10 "Chengdu" timezone=Asia/Chongqing # China # 13.08 80.30 "Chennai" timezone=Asia/Calcutta # India 41.85 -87.65 "Chicago" timezone=America/Chicago # USA # 30.65 103.68 "Chongqing" timezone=Asia/Chongqing # China 32.78 -96.80 "Dallas" timezone=America/Chicago # USA 14.67 -17.43 "Dakar" timezone=Africa/Dakar # Senegal 28.67 77.22 "Delhi" timezone=Asia/Calcutta # India # 42.32 -83.03 "Detroit" timezone=America/Detroit # USA # 23.72 90.37 "Dhaka" timezone=Asia/Dhaka # Bangladesh # 51.15 7.00 "Dsseldorf" timezone=Europe/Berlin # Germany # 51.45 6.95 "Essen" timezone=Europe/Berlin # Germany # 23.13 113.33 "Guangzhou" timezone=Asia/Shanghai # China # 45.75 126.68 "Harbin" timezone=Asia/Harbin # China # 10.75 106.67 "Ho Chi Minh City" timezone=Asia/Saigon # Vietnam 22.28 114.15 "Hong Kong" timezone=Hongkong # China # 17.37 78.43 "Hyderabad" timezone=Asia/Calcutta # India 52.27 104.33 "Irkutsk" timezone=Asia/Irkutsk # Russia 41.03 28.95 "Istanbul" timezone=Asia/Istanbul # Turkey -6.13 106.75 "Jakarta" timezone=Asia/Jakarta # Indonesia -26.17 28.03 "Johannesburg" timezone=Africa/Johannesburg # South Africa # 51.15 6.37 "Kaarst" timezone=Europe/Berlin # Germany 24.85 67.03 "Karachi" timezone=Asia/Karachi # Pakistan 27.72 85.32 "Katmandu" timezone=Asia/Katmandu # Nepal 15.55 32.53 "Khartoum" timezone=Africa/Khartoum # Sudan 50.43 30.52 "Kiev" timezone=Europe/Kiew # Ukraine 18.00 -76.80 "Kingston" timezone=America/Jamaica # Jamaica -4.30 15.30 "Kinshasa" timezone=Africa/Kinshasa # Congo 6.45 3.47 "Lagos" timezone=Africa/Lagos # Nigeria # 31.57 74.37 "Lahore" timezone=Asia/Karachi # Pakistan -12.05 -77.05 "Lima" timezone=America/Lima # Peru 51.50 -0.17 "London" timezone=Europe/London # United Kingdom 34.05 -118.23 "Los Angeles" timezone=US/Pacific # USA 40.42 -3.72 "Madrid" timezone=Europe/Madrid # Spain 14.62 120.97 "Manila" timezone=Asia/Manila # Philippines -37.75 144.97 "Melbourne" timezone=Australia/Melbourne # Australia 19.40 -99.15 "Mexico City" timezone=America/Mexico_City # Mexico 45.52 -73.57 "Montreal" timezone=America/Montreal # Canada 55.75 37.70 "Moscow" timezone=Europe/Moscow # Russia # 18.93 72.85 "Mumbai" timezone=Asia/Calcutta # India # 35.13 136.88 "Nagoya" timezone=Asia/Tokyo # Japan -1.28 36.82 "Nairobi" timezone=Africa/Nairobi # Kenia 40.70 -74.00 "New York" timezone=US/Eastern # USA 55.07 83.08 "Novosibirsk" timezone=Asia/Novosibirsk # Russia 55.00 73.37 "Omsk" timezone=Asia/Omsk # Russia 34.67 135.50 "Osaka" timezone=Asia/Tokyo # Japan 48.87 2.33 "Paris" timezone=Europe/Paris # France 53.02 158.65 "Petropavlovsk-K." timezone=Asia/Kamchatka # Russia # 39.95 -75.15 "Philadelphia" timezone=US/Eastern # USA # 35.08 129.03 "Pusan" timezone=Asia/Seoul # South Korea # 39.00 125.78 "Pyongyang" timezone=Asia/Pyongyang # North Korea -22.88 -43.28 "Rio de Janeiro" timezone=America/Sao_Paulo # Brazil 41.90 12.48 "Rom" timezone=Europe/Rom # Italy 37.77 -122.42 "San Francisco" timezone=America/Los_Angeles # USA -33.45 -70.67 "Santiago" timezone=Chile/Continental # Chile -23.55 -46.65 "So Paulo" timezone=America/Sao_Paulo # Brazil 37.53 127.00 "Seoul" timezone=Asia/Seoul # South Korea 44.50 34.00 "Sevastopol" timezone=Europe/Simferopol # Ukraine 31.10 121.37 "Shanghai" timezone=Asia/Shanghai # China # 41.83 123.43 "Shenyang" timezone=Asia/Shanghai # China 1.28 103.85 "Singapore" timezone=Asia/Singapore # Singapore 59.88 30.25 "St. Petersburg" timezone=Europe/Moscow # Russia 59.33 18.08 "Stockholm" timezone=Europe/Stockholm # Russia -33.92 151.17 "Sydney" timezone=Australia/Sydney # Australia # 25.02 121.37 "Taipei" timezone=Asia/Taipei # Taiwan 35.67 51.43 "Teheran" timezone=Asia/Tehran # Iran # 39.13 117.20 "Tianjin" timezone=Asia/Shanghai # China 35.75 139.50 "Tokyo" timezone=Asia/Tokyo # Japan # 43.70 -79.42 "Toronto" timezone=America/Montreal # Canada 49.27 -123.12 "Vancouver" timezone=America/Vancouver # Canada 43.15 131.88 "Vladivostok" timezone=Asia/Vladivostok # Russia 38.88 -77.03 "Washington" timezone=US/Eastern # USA # 30.58 114.32 "Wuhan" timezone=Asia/Shanghai # China # 34.27 108.90 "Xian" timezone=Asia/Shanghai # China 56.87 60.58 "Yekaterinburg" timezone=Asia/Yekaterinburg # Russia # 35.47 139.63 "Yokohama" timezone=Asia/Tokyo # Japan tkabber-plugins-0.11.1/georoster/ChangeLog0000644000175000017500000001076210424225136017771 0ustar sergeisergei2006-04-27 Alexey Shchepin * msgs/ru.msg: Updated (thanks to Sergei Golovan) 2006-04-09 Alexey Shchepin * msgs/es.msg: Updated (thanks to Badlop) 2006-02-26 Alexey Shchepin * georoster.tcl: Updated (thanks to Sergei Golovan) 2005-08-14 Alexey Shchepin * msgs/nl.msg: Updated (thanks to Sander Devrieze) 2005-05-15 Alexey Shchepin * msgs/: Updated (thanks to Sergei Golovan) * georoster.tcl: Replaced "GeoRoster" with "Georoster" (thanks to Sergei Golovan) 2005-03-03 Alexey Shchepin * msgs/ru.msg: Updated (thanks to Sergei Golovan) * georoster.tcl: Don't store translated strings in options, better labels placement (thanks to Sergei Golovan) * earth.ru: Better aligment (thanks to Sergei Golovan) * earth: More cities (thanks to Sergei Golovan) 2004-12-22 Alexey Shchepin * georoster.tcl: Allows translation of more strings (thanks to Badlop) 2004-07-17 Alexey Shchepin * msgs/nl.msg: Dutch translation (thanks to Sander Devrieze) 2004-04-03 Alexey Shchepin * georoster.tcl: Fix to prevent some spurious bgerrors (thanks to Marshall T. Rose) 2004-02-17 Alexey Shchepin * georoster.tcl: Updated to latest tkabber cvs version (thanks to Badlop) 2003-11-17 Alexey Shchepin * georoster.tcl: Don't ask for a vcard if we're looking at the presence from a conference room (thanks to Marshall T. Rose) 2003-10-01 Alexey Shchepin * msgs/es.msg: Spanish translation (thanks to Badlop) 2003-08-16 Alexey Shchepin * georoster.tcl: Minor fix (thanks to Marshall T. Rose) 2003-07-22 Alexey Shchepin * georoster.tcl: Bugfix (thanks to Marshall T. Rose) 2003-06-26 Alexey Shchepin * bwmap4.gif: Update (thanks to Marshall T. Rose) * georoster.tcl: Added a -timeout to one of the http calls (thanks to Marshall T. Rose) 2003-06-24 Alexey Shchepin * georoster.tcl: Now works with latest tkabber cvs version 2003-06-17 Alexey Shchepin * de.coords: Updated (thanks to Roger Sondermann) 2003-06-16 Alexey Shchepin * georoster.tcl (georoster::retrieve): Updated due to changes in connected_hook call * georoster.tcl: Removed canvas background setting (thanks to Marshall T. Rose) 2003-05-20 Alexey Shchepin * de.coords: Fixed tabs (thanks to Roger Sondermann) 2003-05-19 Alexey Shchepin * georoster.tcl: More debugging (thanks to Marshall T. Rose) * jm.coords: Coordinates for Jamaica (thanks to Roger Sondermann) * earth: Updated (thanks to Roger Sondermann) * de.coords: Likewise 2003-05-17 Alexey Shchepin * msgs/ru.msg: Updated (thanks to Sergei Golovan) 2003-04-29 Alexey Shchepin * georoster.tcl: Make the http lookup for US localities asynchronous 2003-04-19 Alexey Shchepin * de.coords: Coords for German cities (thanks to Roger Sondermann) 2003-04-17 Alexey Shchepin * (ru|ua|nl).coords: Not-completed coords files (thanks to Marshall T. Rose) * iso3166: Updated (thanks to Marshall T. Rose) * georoster.tcl: Updated (thanks to Marshall T. Rose) 2003-04-12 Alexey Shchepin * georoster.tcl: New option show_last_known (thanks to Marshall T. Rose) 2003-04-10 Alexey Shchepin * us.coords: Coords for US cities (thanks to Marshall T. Rose) * iso3166: ISO3166 country codes (thanks to Marshall T. Rose) * howto.txt: GeoRoster HOWTO (thanks to Marshall T. Rose) * bwmap4.gif: New map image (thanks to Marshall T. Rose) * darkmap.gif: Likewise * colormap.jpg: New color map (thanks to Roger Sondermann) * georoster.tcl: More methods to find coordinates, many other changes (thanks to Marshall T. Rose) 2003-04-07 Alexey Shchepin * georoster.tcl: Now uses customization interface, added option to make vCard lookups optional (and off by default) 2003-04-06 Alexey Shchepin * georoster.tcl: Now this plugin also looks at vCard to find user coordinates (LAT/LON fields or REGION/LOCALITY and/or PCODE for US) (thanks to Marshall T. Rose) * earth.ru: Added russian translation * earth: Removed overlapped cities, added some new cities (thanks to Roger Sondermann) tkabber-plugins-0.11.1/gmail/0000755000175000017500000000000011076120366015274 5ustar sergeisergeitkabber-plugins-0.11.1/gmail/msgs/0000755000175000017500000000000011076120366016245 5ustar sergeisergeitkabber-plugins-0.11.1/gmail/msgs/pl.msg0000644000175000017500000000314410714530322017365 0ustar sergeisergei# Polish messages file for gmail plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Browse" "Przeglądaj" ::msgcat::mcset pl "Delete" "Usuń" ::msgcat::mcset pl "Delete Gmail notifications, which are older than 24 hours." \ "Usuwaj powiadomienia Gmail starsze niż 24 godziny." ::msgcat::mcset pl "Delete all messages" "Usuń wszystkie wiadomości" ::msgcat::mcset pl "Delete messages older than 24 hours" "Usuń wszystkie wiadomości starsze niż 24 godziny" ::msgcat::mcset pl "Delete seen messages" "Usuń przeczytane wiadomości" ::msgcat::mcset pl "Format of timestamp in Gmail tree view. Set to empty string if you don't want to see timestamps." \ "Format znacznika czasu w widoku wiadomości Gmail. Aby wyłączyć znaczniki czasu pozostaw to pole puste." ::msgcat::mcset pl "Gmail" "Gmail" ::msgcat::mcset pl "Gmail notifications" "Powiadomienia Gmail" ::msgcat::mcset pl "Google Talk XMPP extensions." "Rozszerzenia XMPP dla Google Talk." ::msgcat::mcset pl "Last Gmail message time." "Czas ostatniego powiadomienia Gmail." ::msgcat::mcset pl "Mark all seen" "Oznacz wszystkie jako przeczytane" ::msgcat::mcset pl "Mark all unseen" "Oznacz wszystkie jako nieprzeczytane" ::msgcat::mcset pl "Mark seen" "Oznacz jako przeczytane" ::msgcat::mcset pl "Mark unseen" "Oznacz jako nieprzeczytane" ::msgcat::mcset pl "Open Gmail notifications" "Pokaż okno powiadomień Gmail" ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "Request Gmail notifications." "Odbieraj powiadomienia Gmail."tkabber-plugins-0.11.1/gmail/msgs/es.msg0000644000175000017500000000257310712161173017370 0ustar sergeisergei::msgcat::mcset es "Browse" "Navegar" ::msgcat::mcset es "Delete Gmail notifications, which are older than 24 hours." "Borrar notificaciones de Gmail que sean anteriores a 24 horas." ::msgcat::mcset es "Delete all messages" "Borrar todos los mensajes" ::msgcat::mcset es "Delete messages older than 24 hours" "Borrar los mensajes anteriores a 24 horas" ::msgcat::mcset es "Delete seen messages" "Borrar mensajes ya leídos" ::msgcat::mcset es "Delete" "Borrar" ::msgcat::mcset es "Format of timestamp in Gmail tree view. Set to empty string if you don't want to see timestamps." "Formato de la fecha en el árbol de Gmail. Si no pones nada, no se verán las fechas." ::msgcat::mcset es "Gmail notifications" "Notificaciones de Gmail" ::msgcat::mcset es "Gmail" "Gmail" ::msgcat::mcset es "Google Talk XMPP extensions." "Extensiones XMPP de Google Talk." ::msgcat::mcset es "Last Gmail message time." "Hora del último mensaje de Gmail." ::msgcat::mcset es "Mark all seen" "Marcar todos como leídos" ::msgcat::mcset es "Mark all unseen" "Marcar todos como no leídos" ::msgcat::mcset es "Mark seen" "Marcar como leído" ::msgcat::mcset es "Mark unseen" "Marcar como no leído" ::msgcat::mcset es "Open Gmail notifications" "Abrir Notificaciones de Gmail" ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Request Gmail notifications." "Solicitar notificaciones de Gmail." tkabber-plugins-0.11.1/gmail/msgs/de.msg0000644000175000017500000000343610714530322017346 0ustar sergeisergei # German messages file # Roger Sondermann 05.11.2007 ::msgcat::mcset de "Browse" "Durchsuchen" ::msgcat::mcset de "Delete" "Lschen" ::msgcat::mcset de "Delete Gmail notifications, which are older than 24 hours." "Gmail-Benachrichtigungen lschen, die lter als 24 Stunden sind." ::msgcat::mcset de "Delete all messages" "Alle Nachrichten lschen" ::msgcat::mcset de "Delete messages older than 24 hours" "Nachrichten lschen, die lter als 24 Stunden sind" ::msgcat::mcset de "Delete seen messages" "Gelesene Nachrichten lschen" ::msgcat::mcset de "Format of timestamp in Gmail tree view. Set to empty string if you don't want to see timestamps." "Format des Zeitstempels in der Gmail-Baumansicht (frei lassen, wenn keine Zeitstempel angezeigt werden sollen)." ::msgcat::mcset de "Gmail" "Gmail" ::msgcat::mcset de "Gmail notifications" "Gmail-Benachrichtigungen" ::msgcat::mcset de "Google Talk XMPP extensions." "Google Talk XMPP-Erweiterungen." ::msgcat::mcset de "Last Gmail message time." "Zeit der letzten Gmail-Nachricht." ::msgcat::mcset de "Mark all seen" "Alle Gelesenen markieren" ::msgcat::mcset de "Mark all unseen" "Alle Ungelesenen markieren" ::msgcat::mcset de "Mark seen" "Gelesene markieren" ::msgcat::mcset de "Mark unseen" "Ungelesene markieren" ::msgcat::mcset de "Open Gmail notifications" "Gmail-Benachrichtigungen" ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "Request Gmail notifications." "Gmail-Benachrichtigungen abfragen." tkabber-plugins-0.11.1/gmail/msgs/ru.msg0000644000175000017500000000374110667535014017415 0ustar sergeisergei# $Id: ru.msg 1224 2007-09-05 14:15:40Z sergei $ ::msgcat::mcset ru "Browse" "Просмотреть" ::msgcat::mcset ru "Delete" "Удалить" ::msgcat::mcset ru "Delete Gmail notifications, which are older than 24 hours." \ "Удалять уведомления Gmail старше 24 часов." ::msgcat::mcset ru "Delete all messages" "Удалить все сообщения" ::msgcat::mcset ru "Delete messages older than 24 hours" "Удалить сообщения старше 24 часов" ::msgcat::mcset ru "Delete seen messages" "Удалить просмотренные сообщения" ::msgcat::mcset ru "Format of timestamp in Gmail tree view. Set to empty string if you don't want to see timestamps." \ "Формат вывода даты/времени в окне уведомлений Gmail. Для того, чтобы не показывать дату/время совсем, установите эту опцию в пустую строку." ::msgcat::mcset ru "Gmail" ::msgcat::mcset ru "Gmail notifications" "Уведомления Gmail" ::msgcat::mcset ru "Google Talk XMPP extensions." "Расширения XMPP для Google Talk." ::msgcat::mcset ru "Last Gmail message time." "Время последнего сообщения Gmail." ::msgcat::mcset ru "Mark all seen" "Пометить все как просмотренные" ::msgcat::mcset ru "Mark all unseen" "Пометить все как непросмотренные" ::msgcat::mcset ru "Mark seen" ::msgcat::mcset ru "Mark unseen" ::msgcat::mcset ru "Mark seen" "Пометить как просмотренное" ::msgcat::mcset ru "Mark unseen" "Пометить как непросмотренное" ::msgcat::mcset ru "Open Gmail notifications" "Открыть окно уведомлений Gmail" ::msgcat::mcset ru "Plugins options." "Настройки расширений." ::msgcat::mcset ru "Request Gmail notifications." "Запрашивать уведомления Gmail." tkabber-plugins-0.11.1/gmail/gmail.tcl0000644000175000017500000003705310747411465017110 0ustar sergeisergei# Gmail notifications support. package require msgcat namespace eval gmail { ::msgcat::mcload [file join [file dirname [info script]] msgs] set ::NS(gnotify) "google:mail:notify" custom::defgroup Plugins \ [::msgcat::mc "Plugins options."] \ -group Tkabber custom::defgroup {Gmail Notifications} \ [::msgcat::mc "Google Talk XMPP extensions."] \ -group Plugins custom::defvar options(gmail_notifications) 1 \ [::msgcat::mc "Request Gmail notifications."] \ -type boolean -group {Gmail Notifications} \ -command [namespace current]::request_all_notifications custom::defvar options(delete_old_notifications) 1 \ [::msgcat::mc "Delete Gmail notifications, which are older than 24 hours."] \ -type boolean -group {Gmail Notifications} \ -command [namespace current]::request_all_notifications custom::defvar options(timestamp_format) {[%m/%d %R] } \ [::msgcat::mc "Format of timestamp in Gmail tree view. Set to\ empty string if you don't want to see timestamps."] \ -group {Gmail Notifications} -type string custom::defvar last_mail_time {} \ [::msgcat::mc "Last Gmail message time."] \ -type string -group Hidden } ############################################################################ proc gmail::request_all_notifications {args} { foreach connid [jlib::connections] { request_notifications $connid } } ############################################################################ proc gmail::request_notifications {connid} { variable options variable last_mail_time set jid [jlib::connection_bare_jid $connid] catch {array set tmp $last_mail_time} if {[info exists tmp($jid)]} { set time $tmp($jid) } else { set time 0 } if {$options(gmail_notifications)} { jlib::send_iq get \ [jlib::wrapper:createtag query \ -vars [list xmlns $::NS(gnotify) \ newer-than-time $time]] \ -command [list [namespace current]::receive_notifications $jid] \ -connection $connid } } hook::add connected_hook [namespace current]::gmail::request_notifications ############################################################################ proc gmail::receive_notifications {jid res child} { variable last_mail_time if {$res != "OK"} { return } jlib::wrapper:splitxml $child tag vars isempty cdata children if {[jlib::wrapper:isattr $vars result-time]} { catch {array set tmp $last_mail_time} set tmp($jid) [jlib::wrapper:getattr $vars result-time] set last_mail_time [array get tmp] } fill_tree $jid $children } ############################################################################# proc gmail::create_menu {} { set menu [.mainframe getmenu plugins] $menu add command \ -label [::msgcat::mc "Open Gmail notifications"] \ -command [list [namespace current]::open_window -raise 1] } hook::add finload_hook [namespace current]::gmail::create_menu ############################################################################# proc gmail::open_window {args} { global tcl_platform variable options set raise 0 foreach {key val} $args { switch -- $key { -raise { set raise $val } } } set w .gmail_messages if {[winfo exists $w]} { if {$raise} { raise_win $w } return } add_win $w -title [::msgcat::mc "Gmail notifications"] \ -tabtitle [::msgcat::mc "Gmail"] \ -raisecmd [list focus $w.tree] \ -class JDisco \ -raise $raise if {![info exists options(seencolor)]} { if {[cequal $tcl_platform(platform) unix] && \ ![string equal [option get $w disabledForeground JDisco] ""]} { set options(seencolor) [option get $w disabledForeground JDisco] } else { set options(seencolor) [option get $w featurecolor JDisco] } } if {![info exists options(unseencolor)]} { set options(unseencolor) [option get $w fill JDisco] } set sw [ScrolledWindow $w.sw] set tw [Tree $w.tree -deltax 16 -deltay 18 -dragenabled 0] $sw setwidget $tw pack $sw -side top -expand yes -fill both $tw bindText \ [list [namespace current]::message_popup $tw] $tw bindText \ [list [namespace current]::message_action browse $tw] # HACK bind $tw.c \ "[namespace current]::message_action browse $tw \[$tw selection get\]" bindscroll $tw.c messages_restore } ############################################################################# proc gmail::fill_tree {jid children} { variable options if {[lempty $children]} { return } open_window foreach ch $children { jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1 switch -- $tag1 { mail-thread-info { set tid [jlib::wrapper:getattr $vars1 tid] set messages [jlib::wrapper:getattr $vars1 messages] set date [jlib::wrapper:getattr $vars1 date] set url [jlib::wrapper:getattr $vars1 url] add_thread $jid $tid $messages $date $url $children1 1 } } } } package require md5 proc gmail::add_thread {jid tid messages date url children unseen} { variable options set w .gmail_messages set tw $w.tree set fnode [str2node $jid] if {![$tw exists $fnode]} { $tw insert end root $fnode -text $jid -open 1 \ -fill $options(unseencolor) -image browser/user \ -data [list type jid jid $jid unseen $unseen] } set senders [list] set subject "" foreach ch $children { jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1 switch -- $tag1 { senders { foreach ch1 $children1 { jlib::wrapper:splitxml $ch1 tag2 vars2 isempty2 cdata2 children2 if {$tag2 == "sender"} { lappend senders [jlib::wrapper:getattr $vars2 name] } } } subject { set subject $cdata1 } } } set snode [str2node "$tid $jid"] if {[$tw exists $snode]} { $tw delete $snode } set timestamp [clock format [string range $date 0 end-3] -format $options(timestamp_format)] set names [senders2names $senders] $tw insert end $fnode $snode \ -text "$timestamp$names ($messages) $subject" -open 1 \ -fill $options(unseencolor) \ -data [list type thread jid $jid tid $tid \ messages $messages date $date url $url \ children $children unseen $unseen] if {$options(delete_old_notifications)} { message_action deleteold $tw $fnode } else { messages_store $tw } message_update $tw $snode sort_nodes $tw $fnode -date tab_set_updated $w 1 message } proc gmail::senders2names {senders} { if {[llength $senders] <= 1} { return [lindex $senders 0] } else { set names {} foreach s $senders { lappend names [lindex [split [string trim $s]] 0] } if {[llength $names] <= 3} { return [join $names ", "] } else { return "[lindex $names 0] .. [join [lrange $names end-1 end] {, }]" } } } proc gmail::str2node {string} { set utf8str [encoding convertto utf-8 $string] if {[catch { ::md5::md5 -hex $utf8str } ret]} { return [::md5::md5 $utf8str] } else { return $ret } } proc gmail::message_popup {tw node} { $tw selection set $node if {[catch { array set props [$tw itemcget $node -data] }]} { return } set m .gmail_popup_menu if {[winfo exists $m]} { destroy $m } menu $m -tearoff 0 switch -- $props(type) { jid { # $m add command -label [::msgcat::mc "Mark all seen"] \ # -command [list [namespace current]::message_action markseen $tw $node] # $m add command -label [::msgcat::mc "Mark all unseen"] \ # -command [list [namespace current]::message_action markunseen $tw $node] $m add command -label [::msgcat::mc "Delete messages older than 24 hours"] \ -command [list [namespace current]::message_action deleteold $tw $node] # $m add command -label [::msgcat::mc "Delete seen messages"] \ # -command [list [namespace current]::message_action deleteseen $tw $node] $m add command -label [::msgcat::mc "Delete all messages"] \ -command [list [namespace current]::message_action delete $tw $node] } thread { $m add command -label [::msgcat::mc "Browse"] \ -command [list [namespace current]::message_action browse $tw $node] # $m add command -label [::msgcat::mc "Mark seen"] \ # -command [list [namespace current]::message_action markseen $tw $node] # $m add command -label [::msgcat::mc "Mark unseen"] \ # -command [list [namespace current]::message_action markunseen $tw $node] $m add command -label [::msgcat::mc "Delete"] \ -command [list [namespace current]::message_action delete $tw $node] } default { return } } tk_popup $m [winfo pointerx .] [winfo pointery .] } proc gmail::message_action {action tw node} { message_action_aux $action $tw $node messages_store $tw } proc gmail::message_action_aux {action tw node} { variable options if {[catch { array set props [$tw itemcget $node -data] }]} { return } switch -glob -- $props(type)/$action { jid/markseen { foreach child [$tw nodes $node] { message_action_aux markseen $tw $child } } jid/markunseen { foreach child [$tw nodes $node] { message_action_aux markunseen $tw $child } } jid/deleteold { foreach child [$tw nodes $node] { message_action_aux deleteold $tw $child } } jid/deleteseen { foreach child [$tw nodes $node] { message_action_aux deleteseen $tw $child } } jid/delete { foreach child [$tw nodes $node] { message_action_aux delete $tw $child } } thread/browse { if {$props(url) != ""} { browseurl $props(url) } } thread/markseen { set props(unseen) 0 } thread/markunseen { set props(unseen) 1 } thread/deleteold { set datediff [expr {[clock seconds] - [string range $props(date) 0 end-3]}] if {$datediff > 86400} { message_action_aux delete $tw $node } } thread/deleteseen { if {!$props(unseen)} { message_action_aux delete $tw $node } } thread/delete { set props(unseen) 0 $tw itemconfigure $node -data [array get props] message_update $tw $node # Deduce the node to select after $node is deleted: # Next sibling is tried first, then previous, then parent node. set p [$tw parent $node] set end [expr {[llength [$tw nodes $p]] - 1}] set ix [$tw index $node] if {$ix < $end} { set next [$tw nodes $p [incr ix]] } elseif {$ix > 0} { set next [$tw nodes $p [incr ix -1]] } else { set next $p } $tw delete $node if {![string equal $next root]} { $tw selection set $next } } default { return } } } proc gmail::sort_nodes {tw node type} { if {[string range $type 0 0] == "-"} { set order -decreasing set type [string range $type 1 end] } elseif {[string range $type 0 0] == "+"} { set order -increasing set type [string range $type 1 end] } else { set order -increasing } set children {} foreach child [$tw nodes $node] { catch { unset props } array set props [$tw itemcget $child -data] lappend children [list $child $props($type)] } set neworder {} foreach child [lsort $order -index 1 $children] { lappend neworder [lindex $child 0] } $tw reorder $node $neworder } proc gmail::message_update {tw node} { variable options for {set parent [$tw parent $node]} \ {![cequal $parent root]} \ {set parent [$tw parent $parent]} { set unseen 0 foreach child [$tw nodes $parent] { catch { unset props } array set props [$tw itemcget $child -data] incr unseen $props(unseen) } catch { unset props } array set props [$tw itemcget $parent -data] set props(unseen) $unseen set text $props(jid) set myfill $options(seencolor) if {$unseen > 0} { append text " ($unseen)" set myfill $options(unseencolor) } $tw itemconfigure $parent -text $text -fill $myfill \ -data [array get props] } } ############################################################################# proc gmail::messages_store {tw} { set file [file join $::configdir gmail-notifications.tcl] set file0 [file join $::configdir gmail-notifications0.tcl] set file1 [file join $::configdir gmail-notifications1.tcl] if {[catch {open $file1 {WRONLY CREAT TRUNC}} fd]} { debugmsg plugins "unable to open $file1: $fd" return } fconfigure $fd -encoding utf-8 set code [catch {messages_store_aux $tw root $fd} result] catch {close $fd} if {$code} { debugmsg plugins $result catch {file delete $file1} return } set renameP 0 if {![file exists $file]} { } elseif {[file size $file] == 0} { catch {file delete -force $file} } else { set renameP 1 catch {file rename -force $file $file0} } if {![catch {file rename $file1 $file} result]} { return } debugmsg plugins "unable to rename $file1 to $file: $result" if {($renameP) && ([catch {file rename -force $file0 $file} result])} { debugmsg plugins "unable to rename $file0 back to $file: $result" } catch {file delete $file1} return } ############################################################################# proc gmail::messages_store_aux {tw node fd} { if {![winfo exists $tw]} { return } if {[llength [set children [$tw nodes $node]]] > 0} { foreach child $children { messages_store_aux $tw $child $fd } } elseif {![catch {array set props [$tw itemcget $node -data]}]} { puts $fd [list [namespace current]::add_thread \ $props(jid) $props(tid) $props(messages) \ $props(date) $props(url) $props(children) \ $props(unseen)] } } ############################################################################# proc gmail::messages_restore {} { set file [file join $::configdir gmail-notifications.tcl] if {[file exists $file]} { catch { set fd [open $file "r"] fconfigure $fd -encoding utf-8 uplevel #0 [read $fd] close $fd } } return "" } ############################################################################# proc gmail::notify_response {connid from lang child} { variable options if {$from != "" && \ $from != [jlib::connection_bare_jid $connid] && \ $from != [jlib::connection_jid $connid]} { return {error cancel not-allowed} } jlib::wrapper:splitxml $child tag vars isempty cdata children if {$tag != "new-mail"} { return {error modify bad-request} } request_notifications $connid return [list result ""] } iq::register_handler set "" $::NS(gnotify) \ [namespace current]::gmail::notify_response ############################################################################# proc gmail::restore_window {from connid jid} { open_window -raise 1 } ############################################################################# proc gmail::save_session {vsession} { upvar 2 $vsession session global usetabbar # We don't need JID at all, so make it empty (special case) set user "" set server "" set resource "" # TODO if {!$usetabbar} return set prio 0 foreach page [.nb pages] { set path [ifacetk::nbpath $page] if {[string equal $path .gmail_messages]} { lappend session \ [list $prio $user $server $resource \ [list [namespace current]::restore_window ""]] } incr prio } } hook::add save_session_hook [namespace current]::gmail::save_session ############################################################################# tkabber-plugins-0.11.1/debug/0000755000175000017500000000000011076120366015271 5ustar sergeisergeitkabber-plugins-0.11.1/debug/msgs/0000755000175000017500000000000011076120366016242 5ustar sergeisergeitkabber-plugins-0.11.1/debug/msgs/pl.msg0000644000175000017500000000152510667535014017375 0ustar sergeisergei# Polish messages file for debug plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Debug" "Debugowanie" ::msgcat::mcset pl "Debug live plugin options." "Ustawienia wtyczki debugowania." ::msgcat::mcset pl "Log debug messages for module %s to a tab/window." "Zapisuj komunikaty debugowania dla modułu %s do karty/okna." ::msgcat::mcset pl "Log debug messages to a separate tab/window." "Zapisuj komunikaty debugowania do oddzielnej karty/okna." ::msgcat::mcset pl "Log debug messages to file %s." "Zapisuj komunikaty debugowania do pliku %s." ::msgcat::mcset pl "Log to file" "Zapisuj do pliku" ::msgcat::mcset pl "Log to window" "Zapisuj do okna" ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/debug/msgs/es.msg0000644000175000017500000000124510577062431017366 0ustar sergeisergei::msgcat::mcset es "Debug live plugin options." "Opciones del plugin de depurado en vivo." ::msgcat::mcset es "Debug" "Depurar" ::msgcat::mcset es "Log debug messages for module %s to a tab/window." "Mostrar mensajes de depurado para el módulo %s en una pestaña/ventana." ::msgcat::mcset es "Log debug messages to a separate tab/window." "Mostrar mensajes de depurado en una pestaña/ventana separada." ::msgcat::mcset es "Log debug messages to file %s." "Guardar mensajes de depurado en el fichero %s." ::msgcat::mcset es "Log to file" "Guardar en fichero" ::msgcat::mcset es "Log to window" "Mostrar en ventana" ::msgcat::mcset es "Plugins options." "Opciones de plugins." tkabber-plugins-0.11.1/debug/msgs/de.msg0000644000175000017500000000160310661625761017352 0ustar sergeisergei # German messages file # Roger Sondermann 18.08.2007 ::msgcat::mcset de "Debug live plugin options." "Optionen fr das Debug-Plugin." ::msgcat::mcset de "Debug" "Debuggen" ::msgcat::mcset de "Log debug messages for module %s to a tab/window." "Debug-Nachrichten fr Modul '%s' in Tab/Fenster schreiben." ::msgcat::mcset de "Log debug messages to a separate tab/window." "Debug-Nachrichten in separates Tab/Fenster schreiben." ::msgcat::mcset de "Log debug messages to file %s." "Debug-Nachrichten in Datei %s schreiben." ::msgcat::mcset de "Log to file" "In Datei schreiben" ::msgcat::mcset de "Log to window" "In Tab/Fenster schreiben" ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." tkabber-plugins-0.11.1/debug/msgs/ru.msg0000644000175000017500000000163010573755632017413 0ustar sergeisergei::msgcat::mcset ru "Debug" "Отладка" ::msgcat::mcset ru "Debug live plugin options." "Настройки расширения отладки." ::msgcat::mcset ru "Log debug messages for module %s to a tab/window." \ "Сохранять отладочные сообщения для модуля %s во вкладку или окно." ::msgcat::mcset ru "Log debug messages to a separate tab/window." \ "Сохранять отладочные сообщения в отдельную вкладку или окно." ::msgcat::mcset ru "Log debug messages to file %s." \ "Сохранять отладочные сообщения в файл %s." ::msgcat::mcset ru "Log to file" "Сохранять в файл" ::msgcat::mcset ru "Log to window" "Сохранять в окно" ::msgcat::mcset ru "Plugins options." "Настройки расширений." # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/debug/msgs/uk.msg0000644000175000017500000000032010546743545017377 0ustar sergeisergei::msgcat::mcset uk "Debug live" "Дебаггер" ::msgcat::mcset uk "Debug to window" "Виводити налагоджувальну інформацію у вікно" # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/debug/debug.tcl0000644000175000017500000001441211011605241017052 0ustar sergeisergei# Tkabber debugging procedures # (c) Marshall T. Rose # Some tweaks by Badlop # Options changed by Sergei Golovan package require msgcat namespace eval debug { ::msgcat::mcload [file join [file dirname [info script]] msgs] custom::defgroup Plugins [::msgcat::mc "Plugins options."] \ -group Tkabber custom::defgroup Debug [::msgcat::mc "Debug live plugin options."] \ -group Plugins custom::defvar options(log_to_file) 0 \ [::msgcat::mc "Log debug messages to file %s." \ [file join $::configdir tkabber.log]] \ -group Debug \ -type boolean custom::defvar options(log_to_window) 0 \ [::msgcat::mc "Log debug messages to a separate tab/window."] \ -group Debug \ -type boolean variable modules [list attline \ avatar \ browser \ browseurl \ chat \ conference \ custom \ disco \ emoticons \ filetransfer \ filters \ georoster \ headlines \ hook \ http \ iface \ iq \ jidlink \ jlib \ jlib::route \ logger \ login \ message \ mucignore \ negotiate \ nick \ pep \ plugins \ popupmenu \ presence \ privacy \ pubsub \ register \ richtext \ roster \ search \ si \ ssj \ sw \ tclchat \ tkabber \ userinfo \ utils \ warning \ zerobot] foreach module $modules { custom::defvar debug($module) 0 \ [::msgcat::mc "Log debug messages for module %s to a tab/window." \ $module] \ -group Debug -type boolean } } proc debug::setup_menu {} { variable options variable modules variable debug set m [.mainframe getmenu plugins] set ind [$m index end] set buttons [menu $m.devel -tearoff $ifacetk::options(show_tearoffs)] $buttons add checkbutton -label [::msgcat::mc "Log to file"] \ -variable [namespace current]::options(log_to_file) $buttons add checkbutton -label [::msgcat::mc "Log to window"] \ -variable [namespace current]::options(log_to_window) $buttons add separator set n 0 foreach module $modules { if {$n == 0} { set submodules [list $module] } else { lappend submodules $module } incr n if {$n == 8 || $module == [lindex $modules end]} { set n 0 set me [menu $buttons.[lindex $submodules 0] \ -tearoff $::ifacetk::options(show_tearoffs)] $buttons add cascade \ -label [lindex $submodules 0]-[lindex $submodules end] \ -menu $me foreach mod $submodules { $me add checkbutton -label $mod \ -variable [namespace current]::debug($mod) } } } $m add cascade -label [::msgcat::mc "Debug"] -menu $buttons } hook::add finload_hook [namespace current]::debug::setup_menu proc ::debugmsg {module msg} \ [list eval [namespace current]::debug::debugmsg \$module \$msg] proc debug::debugmsg {module msg} { variable options variable debug variable debug_fd if {$options(log_to_file)} { if {![info exists debug_fd]} { catch { file rename -force -- $::configdir/tkabber.log \ $::configdir/tkabber0.log } set debug_fd [open $::configdir/tkabber.log w] fconfigure $debug_fd -buffering line } puts $debug_fd [format "%s %-12.12s %s" \ [clock format [clock seconds] -format "%m/%d %T"] \ $module $msg] } if {!$options(log_to_window) || ![info exists debug($module)] || \ !$debug($module)} { return } set dw .debug if {![winfo exists $dw]} { if {[catch {add_win $dw -title [::msgcat::mc Debug] \ -tabtitle [::msgcat::mc Debug] \ -class Chat \ -raisecmd [list focus $dw.body]}]} { # Main window isn't created yet return } [ScrolledWindow $dw.sw] setwidget \ [text $dw.body -yscrollcommand [list $dw.scroll set] \ -state disabled -takefocus 1] bind $dw.body <1> [list focus $dw.body] pack $dw.sw -side bottom -fill both -expand yes $dw.body tag configure module \ -foreground [option get $dw theyforeground Chat] $dw.body tag configure proc \ -foreground [option get $dw meforeground Chat] $dw.body tag configure error \ -foreground [option get $dw errforeground Chat] search::setup_panel $dw } $dw.body configure -state normal set scroll [expr {[lindex [$dw.body yview] 1] == 1}] $dw.body insert end [format "%s: %-12.12s" [clock format [clock seconds] -format "%m/%d %T"] \ $module] module " " set tag normal switch -- $module { jlib { if {[set x [string first "(jlib" $msg]] > 0} { set tag error } if {[set y [string first ")" $msg]] > 0} { $dw.body insert end \ [string range $msg [expr $x+1] [expr $y-1]] proc \ "\n" set msg [string trimleft \ [string range $msg [expr $y+1] end]] } } default { } } $dw.body insert end [string trimright $msg] $tag $dw.body insert end "\n\n" if {!$chat::options(stop_scroll) && \ (!$chat::options(smart_scroll) || \ ($chat::options(smart_scroll) && $scroll))} { $dw.body see end } $dw.body configure -state disabled } namespace eval debug::search {} proc debug::search::open_panel {w sf} { pack $sf -side bottom -anchor w -fill x -before $w.sw update idletasks $w.body see end } proc debug::search::close_panel {w sf} { $w.body tag remove search_highlight 0.0 end pack forget $sf focus $w.body } proc debug::search::setup_panel {w} { set body $w.body $body mark set sel_start end $body mark set sel_end 0.0 set sf [plugins::search::spanel [winfo parent $body].search \ -searchcommand [list ::plugins::search::do_text_search $body] \ -closecommand [list [namespace current]::close_panel $w]] bind $w.body <> \ [double% [list [namespace current]::open_panel $w $sf]] } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/tclchat/0000755000175000017500000000000011076120366015625 5ustar sergeisergeitkabber-plugins-0.11.1/tclchat/msgs/0000755000175000017500000000000011076120366016576 5ustar sergeisergeitkabber-plugins-0.11.1/tclchat/msgs/es.msg0000644000175000017500000000405211021551246017711 0ustar sergeisergei::msgcat::mcset es "%s has changed nick to %s in the IRC channel, but %s is already in Jabber room" "%s se ha cambiado el apodo a %s en el canal de IRC, pero %s ya está en la sala de charla" ::msgcat::mcset es "%s has changed nick to %s in the IRC channel, but %s is still in Jabber room and %s is already in Jabber room" "%s se ha cambiado el apodo a %s en el canal de IRC, but %s is still in Jabber room and %s is already in Jabber room" ::msgcat::mcset es "%s has changed nick to %s in the IRC channel, but %s is still in Jabber room" "%s se ha cambiado el apodo a %s en el canal de IRC, but %s is still in Jabber room" ::msgcat::mcset es "%s has joined IRC channel, but %s is already in Jabber room" "%s ha entrado en el canal de IRC, pero %s ya está en la sala Jabber" ::msgcat::mcset es "%s has joined IRC channel, but he/she is already in Jabber room" "%s ha entrado en el canal de IRC, pero ya está en la sala de charla" ::msgcat::mcset es "%s has left IRC channel, but %s is still in Jabber room" "%s ha salido del canal de IRC, pero %s aún está en la sala Jabber " ::msgcat::mcset es "JID of Tclers' chat." "JID de la sala de Tclers." ::msgcat::mcset es "Nickname of Tclers' chat bridge to IRC channel. Groupchat messages from this participant are treated specially, replacing his nickname by corresponding IRC user nickname." "Apodo del puente de la sala Tclers al canal IRC. Los mensajes de charla de este participante se tratan de forma especial, reemplazando su apodo con el correspondiente del usuario de IRC." ::msgcat::mcset es "Plugins options." "Opciones de plugin." ::msgcat::mcset es "Real JID of Tclers' chat bridge to IRC channel. If set to nonempty string, the list of IRC users will be requested before entering the conference room." "JID real del puente entre la sala de Tclers y el canal de IRC. Si se pone la palabra vacía, se pedirá la lista de usuarios IRC antes de entrar en la sala de charla." ::msgcat::mcset es "Tclchat plugin options." "Opciones de plugin Tclchat." ::msgcat::mcset es "Use TkChat embedded colors." "Usar colores embebidos TkChat." tkabber-plugins-0.11.1/tclchat/msgs/ru.msg0000644000175000017500000000543710573755632017760 0ustar sergeisergei::msgcat::mcset ru "%s has changed nick to %s in the IRC channel, but %s is already in Jabber room" \ "%s сменил псевдоним на %s в канале IRC, но %s уже присутствует в конференции Jabber" ::msgcat::mcset ru "%s has changed nick to %s in the IRC channel, but %s is still in Jabber room" \ "%s сменил псевдоним на %s в канале IRC, но %s все еще присутствует в конференции Jabber" ::msgcat::mcset ru "%s has changed nick to %s in the IRC channel, but %s is still in Jabber room and %s is already in Jabber room" \ "%s сменил псевдоним на %s в канале IRC, но и %s все еще присутствует, и %s уже присутствует в конференции Jabber" ::msgcat::mcset ru "%s has joined IRC channel, but %s is already in Jabber room" \ "%s присоединился к каналу IRC, но %s уже присутствует в конференции Jabber" ::msgcat::mcset ru "%s has joined IRC channel, but he/she is already in Jabber room" \ "%s присоединился к каналу IRC, но он уже присутствует в конференции Jabber" ::msgcat::mcset ru "%s has left IRC channel, but %s is still in Jabber room" \ "%s ушел с канала IRC, но %s все еще присутствует в конференции Jabber" ::msgcat::mcset ru "JID of Tclers' chat." "Jabber ID чата Tcler'ов" ::msgcat::mcset ru "Nickname of Tclers' chat bridge to IRC channel. Groupchat messages from this participant are treated specially, replacing his nickname by corresponding IRC user nickname." \ "Псевдоним моста из чата Tcler'ов в канал IRC. Сообщения в конференцию от этого участника обрабатываются особым образом. В них подменяется псевдоним на соответствующий псевдоним из канала IRC." ::msgcat::mcset ru "Real JID of Tclers' chat bridge to IRC channel. If set to nonempty string, the list of IRC users will be requested before entering the conference room." \ "Реальный Jabber ID моста из чата Tcler'ов в канал IRC. Если параметр непуст, то во время входа в конференцию у него запрашивается список посетителей канала IRC." ::msgcat::mcset ru "Plugins options." "Настройки расширений." ::msgcat::mcset ru "Tclchat plugin options." "Настройки расширения Tclchat" ::msgcat::mcset ru "Use TkChat embedded colors." "Использовать встроенные цвета TkChat." # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/tclchat/tclchat_messages.tcl0000644000175000017500000002401310722255471021645 0ustar sergeisergei# $Id: tclchat_messages.tcl 1320 2007-11-25 11:23:37Z sergei $ # # This does the same job and draw_normal_message but is capable of filtering # the extra nicks generated by the various bridges used in the tclers chats. # Namely ircbridge and ijbridge. # # This plugin processes messages from ijbridge in Tclers' chat only # (tcl@tach.tclers.tk) # # Includes support for nick_colors.tcl (now incorporated into tkabber proper) # and also supports the tclers chat embedded color. # # Originally by Steve Redler. # Modified by Pat Thoyts. # Rewritten by Sergei Golovan namespace eval tclchat { custom::defvar options(tclers_chat_jid) "tcl@tach.tclers.tk" \ [::msgcat::mc "JID of Tclers' chat."] \ -group Tclchat -type string custom::defvar options(bridge_jid) "ijchain@all.tclers.tk/ijbridge" \ [::msgcat::mc "Real JID of Tclers' chat bridge to IRC channel.\ If set to nonempty string, the list of IRC users\ will be requested before entering the conference room."] \ -group Tclchat -type string custom::defvar options(bridge_nickname) "ijchain" \ [::msgcat::mc "Nickname of Tclers' chat bridge to IRC channel.\ Groupchat messages from this participant\ are treated specially, replacing his nickname by\ corresponding IRC user nickname."] \ -group Tclchat -type string hook::add presence_xlist_hook [namespace current]::request_users_list hook::add process_message_hook [namespace current]::fill_irc_users 30 hook::add process_message_hook [namespace current]::process_ijchain_message 30 hook::add draw_message_hook [namespace current]::check_color 62 } # VERY DIRTY HACK. Tkabber doesn't have appropriate hook, so using inappropriate proc tclchat::request_users_list {vxlist connid stat} { upvar 2 newargs args variable irc_users variable options # Don't request IRC users list if bridge JID is empty if {[cequal $options(bridge_jid) ""]} return # HACK: Extract conference name from directed presence. If it isn't # a directed presence then do nothing array set tmp $args if {![info exists tmp(-to)]} return set to $tmp(-to) set group [node_and_server_from_jid $to] # If the presence doesn't go to Tclers' chat, do nothing if {![cequal $group $options(tclers_chat_jid)]} return set chatid [chat::chatid $connid $group] # If the chat is disconnected then we're trying to connect. Then it's # time to request IRC users list if {[chat::is_opened $chatid] && [chat::is_groupchat $chatid] && \ $chat::chats(status,$chatid) == "disconnected"} { # Setting the flag to show that the answer is to be processed # programmatically set irc_users($connid) {} message::send_msg $options(bridge_jid) \ -type chat \ -body names \ -connection $connid } } proc tclchat::fill_irc_users \ {connid from id type is_subject subject body err thread priority x} { variable irc_users variable options # Don't process message if we didn't ask the list or this message isn't # from bridge JID if {![info exists irc_users($connid)]} return if {![cequal $from $options(bridge_jid)]} return unset irc_users($connid) after idle [list [namespace current]::inject_irc_users $connid $body] return stop } proc tclchat::inject_irc_users {connid users args} { variable options set group $options(tclers_chat_jid) set chatid [chat::chatid $connid $group] trace vdelete chat::chats(status,$chatid) w \ [list [namespace current]::inject_irc_users $connid $users] if {![chat::is_opened $chatid]} return # If we're still disconnected, schedule the IRC users injection after # a change in chat status if {$chat::chats(status,$chatid) == "disconnected"} { trace variable chat::chats(status,$chatid) w \ [list [namespace current]::inject_irc_users $connid $users] return } set px [jlib::wrapper:createtag x \ -vars [list xmlns $::NS(muc#user)] \ -subtags [list [jlib::wrapper:createtag item \ -vars [list affiliation none]]]] foreach nick $users { set nickid $group/$nick if {[lsearch -exact $::grouproster(users,$chatid) $nickid] < 0 || \ [cequal $::muc::users(role,$connid,$nickid) ""]} { client:presence $connid $nickid available [list $px] } else { client:message $connid $group "" groupchat 0 "" \ [::msgcat::mc "%s has joined IRC channel,\ but he/she is already in Jabber room" \ $nick] [list "" ""] "" "" {} } } } ############################################################################### proc tclchat::jid_in_chat {chatid jid} { set connid [chat::get_connid $chatid] return [expr {[lsearch -exact $::grouproster(users,$chatid) $jid] >= 0 && \ ![cequal $::muc::users(role,$connid,$jid) ""]}] } proc tclchat::process_ijchain_message \ {connid from id type is_subject subject body err thread priority x} { variable options # Filter groupchat messages only if {![cequal $type groupchat]} return set group [node_and_server_from_jid $from] set chatid [chat::chatid $connid $group] # Filter messages from tcl@tach.tclers.tk only if {![cequal $group $options(tclers_chat_jid)]} return set nick [chat::get_nick $connid $from $type] # Filter messages from ijchain only if {$nick != $options(bridge_nickname)} return set lbody [split $body " "] # Update userlist on "*** nick leaves" and "*** nick joins" messages # Update userlist on "* nick left" and "* nick entered" messages if {[llength $lbody] == 3 && [cequal [lindex $lbody 0] "***"]} { set nick [lindex $lbody 1] set nickid $group/$nick switch -- [lindex $lbody 2] { joins { debugmsg chat "Handle \"$nick\" joined message." set px [jlib::wrapper:createtag x \ -vars [list xmlns $::NS(muc#user)] \ -subtags [list [jlib::wrapper:createtag item \ -vars [list affiliation none]]]] if {![jid_in_chat $chatid $nickid]} { client:presence $connid $nickid available [list $px] } else { client:message $connid $group $id $type 0 "" \ [::msgcat::mc "%s has joined IRC channel,\ but %s is already in Jabber room" \ $nick $nick] \ $err $thread $priority $x } } leaves { debugmsg chat "Handle \"$nick\" left message." if {![jid_in_chat $chatid $nickid]} { client:presence $connid $nickid unavailable {} } else { client:message $connid $group $id $type 0 "" \ [::msgcat::mc "%s has left IRC channel,\ but %s is still in Jabber room" \ $nick $nick] \ $err $thread $priority $x } } default { return } } return stop } if {[llength $lbody] == 7 && [cequal [lindex $lbody 0] "***"]} { set from_nick [lindex $lbody 1] set to_nick [lindex $lbody 6] if {[cequal [join [lrange $lbody 2 5] " "] "is now known as"]} { set ux [jlib::wrapper:createtag x \ -vars [list xmlns $::NS(muc#user)] \ -subtags [list [jlib::wrapper:createtag item \ -vars [list affiliation none \ nick $to_nick]] \ [jlib::wrapper:createtag status \ -vars [list code 303]]]] set px [jlib::wrapper:createtag x \ -vars [list xmlns $::NS(muc#user)] \ -subtags [list [jlib::wrapper:createtag item \ -vars [list affiliation none]]]] set from_nickid $group/$from_nick set to_nickid $group/$to_nick if {![jid_in_chat $chatid $from_nickid]} { if {![jid_in_chat $chatid $to_nickid]} { client:presence $connid $from_nickid unavailable [list $ux] client:presence $connid $to_nickid available [list $px] } else { client:presence $connid $from_nickid unavailable {} client:message $connid $group $id $type 0 "" \ [::msgcat::mc "%s has changed nick to %s in the IRC channel,\ but %s is already in Jabber room" \ $from_nick $to_nick $to_nick] \ $err $thread $priority $x } } else { if {![jid_in_chat $chatid $to_nickid]} { client:message $connid $group $id $type 0 "" \ [::msgcat::mc "%s has changed nick to %s in the IRC channel,\ but %s is still in Jabber room" \ $from_nick $to_nick $from_nick] \ $err $thread $priority $x client:presence $connid $to_nickid available [list $px] } else { client:message $connid $group $id $type 0 "" \ [::msgcat::mc "%s has changed nick to %s in the IRC channel,\ but %s is still in Jabber room and\ %s is already in Jabber room" \ $from_nick $to_nick $from_nick $to_nick] \ $err $thread $priority $x } } return stop } return } # Filter out nicks if {[regexp {^<(\S+)>\s+(.*)} $body -> nick body]} { set nickid $group/$nick client:message $connid $nickid $id $type $is_subject $subject $body \ $err $thread $priority $x return stop } elseif {[regexp {^\*\s+(\S+)\s+(.*)} $body -> nick body]} { set nickid $group/$nick client:message $connid $nickid $id $type $is_subject $subject "/me $body" \ $err $thread $priority $x return stop } return } # TODO: Use of tkchat colors # tclchat::check_color -- # # The tclers chat client 'tkchat' likes to embed the users choice of # color into the 'x' elements of each jabber message. In this procedure # we check that our idea of their color agrees. If not we'll update # and refresh. # proc tclchat::check_color {chatid from type body x} { set connid [chat::get_connid $chatid] set nick [chat::get_nick $connid $from $type] foreach node $x { jlib::wrapper:splitxml $node tag attr isempty body children if {[jlib::wrapper:getattr $attr xmlns] == "urn:tkchat:chat"} { set color [string trim [jlib::wrapper:getattr $attr "color"] "#"] if {[string length $color] > 0} { set orig [::plugins::nickcolors::get_color $nick] debugmsg chat "Checking color for $nick ('$orig' eq '#$color')" if {"$orig" != "#$color"} { ::plugins::nickcolors::set_color $chatid $nick "#$color" } } } } } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/tclchat/tclchat_commands.tcl0000644000175000017500000000466110564411474021647 0ustar sergeisergei# tclchat_commands.tcl - Copyright (C) 2004 Pat Thoyts # # # $Id: tclchat_commands.tcl 937 2007-02-13 19:36:28Z sergei $ namespace eval tclchat { hook::add chat_send_message_hook \ [namespace current]::send_commands 50 hook::add generate_completions_hook \ [namespace current]::command_completion } proc tclchat::command_completion {chatid compsvar wordstart line} { upvar 0 $compsvar comps if {!$wordstart} { lappend comps {/google } lappend comps {/googlefight } lappend comps {/tip } lappend comps {/bug } } } proc tclchat::send_commands {chatid user body type} { if {$type == "groupchat"} { set body [string trim $body] if {[string match /* $body]} { switch -regexp -- $body { {^/google\s} { set body [string range $body 8 end] debugmsg tclchat "google \"$body\"" if {[string length $body] > 0} { set q {http://www.google.com/search?ie=UTF-8&oe=UTF-8&} append q [::http::formatQuery q $body] browseurl $q return stop } } {^/googlefight\s} { googlefight $body return stop } {^/(urn:)?tip[: ]\d+} { if {[regexp {(?:urn:)?tip[: ](\d+)} $body -> tip]} { browseurl http://tip.tcl.tk/$tip return stop } } {^/bug[: ]} { dobug [split $body ": "] return stop } } } } } proc tclchat::dobug {msg} { # msg should be of form: ^/bug[: ]id if {[llength $msg] != 2} { debugmsg tclchat "wrong # args: must be /bug id" return } set id [lindex $msg end] set url "http://sourceforge.net/support/tracker.php?aid=$id" browseurl $url } proc tclchat::googlefight {msg} { set q {http://www.googlefight.com/cgi-bin/compare.pl} set n 1 foreach word [lrange $msg 1 end] { append q [expr {($n == 1) ? "?" : "&"}] append q q$n=$word incr n } if {[string match fr_* [msgcat::mclocale]]} { append q &langue=fr } else { append q &langue=us } browseurl $q } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/tclchat/tclchat.tcl0000644000175000017500000003042210747411465017763 0ustar sergeisergei# tclchat.tcl - Copyright (C) 2004 Pat Thoyts # # Inject the history from the tclers chat logs into the current chat window. # This hook only activates if you open a groupchat to a site that # we know is linked to the tclers chat. ie: tach.tclers.tk or the irc channel. # # $Id: tclchat.tcl 1354 2008-01-28 17:39:01Z sergei $ package require msgcat namespace eval tclchat { ::msgcat::mcload [file join [file dirname [info script]] msgs] custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup Tclchat [::msgcat::mc "Tclchat plugin options."] -group Plugins custom::defvar options(use_tkchat_colors) 1 \ [::msgcat::mc "Use TkChat embedded colors."] \ -group Chat -group Tclchat -type boolean hook::add finload_hook [namespace current]::on_init 30 hook::add open_chat_post_hook [namespace current]::on_open_chat hook::add chat_send_message_xlist_hook [namespace current]::add_color } # Load in the additional files that are part of the tclchat plugin. # source [file join [file dirname [info script]] tclchat_messages.tcl] source [file join [file dirname [info script]] tclchat_commands.tcl] proc tclchat::on_init {} { global tcl_platform global loginconf variable Options variable urlid 0 set menu [.mainframe getmenu plugins] $menu add checkbutton -label [msgcat::mc "Tkchat colors"] \ -underline 0 -variable [namespace current]::options(use_tkchat_colors) array set Options { auth {} HistoryLines 0 url "http://tclers.tk/conferences/tcl" sel "/?pattern=*.tcl" RE {.*\s([0-9]+) bytes} } package require http if {![info exists loginconf(proxyuseragent)]} { set loginconf(proxyuseragent) [http::config -useragent] } http::config \ -proxyfilter [namespace origin proxyfilter] \ -useragent $loginconf(proxyuseragent) if {[package provide tls] != {}} { http::register https 443 ::tls::socket } if {$loginconf(proxy) == "https"} { if {[string length $loginconf(proxyusername)] > 0} { set Options(auth) [list Proxy-Authorization \ [concat Basic [base64::encode \ "$loginconf(proxyusername):$loginconf(proxypassword)"]]] } } } proc tclchat::proxyfilter {host} { global loginconf if {[string match "localhost*" $host] || [string match "127.*" $host]} { return {} } if {$loginconf(proxy) == "https"} { return [list $loginconf(proxyhost) $loginconf(proxyport)] } return {} } proc tclchat::on_open_chat {chatid type} { variable Options if {[string equal $type "groupchat"]} { switch -glob -- [set mucjid [chat::get_jid $chatid]] { *@tach.tclers.tk { set muc [lindex [split $mucjid @] 0] set Options(url) "http://tclers.tk/conferences/$muc" after 400 [LoadHistory $chatid] } } } set W [chat::chat_win $chatid] $W tag configure URL -underline 1 $W tag bind URL [list $W configure -cursor hand2] $W tag bind URL [list $W configure -cursor xterm] return } # ------------------------------------------------------------------------- # Check the HTTP response for redirecting URLs. - PT proc tclchat::checkForRedirection {tok} { set ncode [::http::ncode $tok] if {[expr {$ncode == 302 || $ncode == 301 || $ncode == 307}]} { upvar \#0 $tok state array set meta $state(meta) if {[info exists meta(Location)]} { return $meta(Location) } } return {} } proc tclchat::FetchHistoryIndex {url} { variable Options set loglist {} set tok [::http::geturl ${url}$Options(sel) -headers $Options(auth)] switch -- [::http::status $tok] { ok { if {[::http::ncode $tok] >= 500} { debugmsg tclchat "error [::http::code $tok]" } elseif {[http::ncode $tok] >= 400} { debugmsg tclchat "error [::http::code $tok]" } else { if {[set _url [checkForRedirection $tok]] != {}} { regsub {/\?M=D} $_url {} $_url set loglist [FetchHistoryIndex $_url] } else { foreach line [split [::http::data $tok] \n] { if { [regexp -- $Options(RE) $line -> logname size] } { set logname [string map {"%2d" -} $logname] set size [expr {$size / 1024}]k set loglist [linsert $loglist 0 $logname $size] } } } } } reset { debugmsg tclchat "reset" } timeout { debugmsg tclchat "timeout" } error { debugmsg tclchat "error [::http::error $tok]" } default { debugmsg tclchat "????? [::http::error $tok]" } } ::http::cleanup $tok return $loglist } proc tclchat::ParseHistLog {log {reverse 0}} { variable Options set retList {} set MsgRE {^\s*(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun).+?\[([^\]]+)\]\s+([^:]+):?\s*(.*)$} set ircRE {ircbridge: \*\*\* (.+) (.+)$} set TimeRE {^(.+?)\s+(.+?)\s+(\d{1,2})\s+(\d\d:\d\d:\d\d)\s+(\d{4})} set logtime 0 # fetch log set url "$Options(url)/$log" debugmsg tclchat "fetch log \"$url\"" set tok [::http::geturl $url -headers $Options(auth)] debugmsg tclchat "status [::http::status $tok] [::http::code $tok]" switch -- [::http::status $tok] { ok { # Tcl Jabber logs set I [interp create -safe] interp alias $I m {} [namespace current]::ParseLogMsg if { $reverse } { set histTmp [set [namespace current]::History] set Options(History) {} } $I eval [::http::data $tok] if { $reverse } { set Options(History) [concat $Options(History) $histTmp] } } reset { debugmsg tclchat "reset" } timeout { debugmsg tclchat "timeout" } error { debugmsg tclchat "error [::http::error $tok]" } default { debugmsg tclchat "????? [::http::error $tok]" } } ::http::cleanup $tok return $retList } # this called on first logon and after a purge # so not bothering to backgound it proc tclchat::LoadHistory {chatid} { variable Options set FinalList {} if {$Options(HistoryLines) == 0} { # don't even bother } elseif {$Options(HistoryLines) < 0} { set loglist [FetchHistoryIndex $Options(url)] if {[set len [llength $loglist]] > 0} { if {$len > 18} { set loglist [lrange $loglist 0 17] } # ask user set t [toplevel .histQ -class dialog] wm withdraw $t wm transient $t wm protocol $t WM_DELETE_WINDOW { } wm title $t "Load History From Logs" grid [label $t.lbl \ -text "Please select how far back you want to load:"] \ -sticky ew -pady 5 set i 0 variable HistQueryNum [expr {[llength $loglist] / 2}] set loglist [lpairreverse $loglist] foreach {l s} $loglist { grid [radiobutton $t.rb$i -text "$l $s" \ -val $i -var [namespace current]::HistQueryNum] \ -sticky w -padx 15 -pady 0 incr i } grid [radiobutton $t.rb$i -text "None" \ -val $i -var [namespace current]::HistQueryNum] \ -sticky w -padx 15 -pady 0 grid [button $t.ok -text Ok -width 8 \ -command [list destroy $t] -default active] \ -sticky e -padx 5 -pady 10 grid columnconfigure $t 0 -weight 1 bind $t [list $t.ok invoke] catch {::tk::PlaceWindow $t widget .} wm deiconify $t tkwait visibility $t focus $t.ok grab $t tkwait window $t foreach {l s} [lrange $loglist [expr {$HistQueryNum * 2}] end] { debugmsg tclchat "loading history \"$l\" (${s}k)" if {[catch {ParseHistLog $l} new]} { debugmsg tclchat "ERROR: $new" } } } } else { set loglist [FetchHistoryIndex $Options(url)] # go thru logs in reverse until N lines loaded foreach {log size} $loglist { # fetch log if {[catch {ParseHistLog $log} new]} { debugmsg tclchat "ERROR: $new" } if {[llength $Options(History)] >= $Options(HistoryLines)} { break } } } set W [chat::chat_win $chatid] # Set a mark for the history insertion point. if {[lsearch -exact [$W mark names] HISTORY] == -1} { $W config -state normal $W insert 0.0 \ "+++++++++++++++ Loading History +++++++++++++\n" $W mark set HISTORY 0.0 $W config -state disabled } LoadHistoryLines $chatid $W see end } proc tclchat::LoadHistoryLines {chatid} { variable Options set w [chat::chat_win $chatid] set state [$w cget -state] $w configure -state normal if {![info exists Options(History)]} {set Options(History) {}} set count 0 foreach {time nick msg} $Options(History) { #$w insert HISTORY "<$nick> $msg\n" [list they NICK-$nick] Insert $w $nick $msg $time incr count 3 if {$count > 100} { break } } $w see end set Options(History) [lrange $Options(History) $count end] if {$Options(History) == {}} { $w configure -state normal $w delete "HISTORY + 1 char" "HISTORY + 1 line" $w insert "HISTORY + 1 char" \ "+++++++++++++++ End Of History +++++++++++++\n" } else { after idle [list [namespace origin LoadHistoryLines] $chatid] } $w configure -state $state } proc tclchat::gotourl {url} { debugmsg tclchat "goto url \"$url\"" browseurl $url } proc tclchat::Insert {w nick msg time} { variable urlid if {[info exists ::plugins::options(delayed_timestamp_format)]} { set fmt $::plugins::options(delayed_timestamp_format) } else { set fmt "\[%m/%d %R\]" } if {[string equal $nick "ijchain"]} { set nick "" regexp {^<(\w+)> (.*)$} $msg -> nick msg } set nk "<$nick>" if {[string length $nick] < 1} {set nk "*"} $w insert HISTORY \ [clock format $time -format $fmt] {} \ "$nk " [list they NICK-$nick] while {[regexp -nocase -- {^(.*?)(.*?)(.*?)$} \ $msg -> pre url link post]} { if {[string length $pre]} { $w insert HISTORY $pre [list they NICK-$nick] } set id URL-[incr urlid] $w insert HISTORY $link [list they NICK-$nick URL $id] $w tag bind $id <1> [list [namespace origin gotourl] $link] set msg $post } $w insert HISTORY "$msg\n" [list they NICK-$nick] } proc tclchat::ParseLogMsg { when nick msg {opts ""} args } { variable Options set Options(HaveHistory) 1 set time [clock scan ${when} -gmt 1] lappend Options(History) $time $nick $msg if { [llength $args] > 0 } { debugmsg tclchat "WARNING: Log incorrect log format." } #debugmsg tclchat "[clock format $time] $nick :: $msg $opts $args" } proc tclchat::lpairreverse {L} { set res {} set i [llength $L] while {$i} { lappend res [lindex $L [incr i -2]] [lindex $L [incr i]] incr i -1 } set res } proc tclchat::color_to_hex {color} { lassign [winfo rgb . $color] r g b return [format "%02x%02x%02x" \ [expr {$r % 256}] [expr {$g % 256}] [expr {$b % 256}]] } # tclchat::add_color -- # # In our tclers groupchat window, we want to add additional 'x' # elements to add our own color specification. # proc tclchat::add_color {varname chatid user body type} { variable options upvar 2 $varname var set jid [chat::get_jid $chatid] if {$options(use_tkchat_colors) && \ [cequal $type "groupchat"] && \ [string match "*@tach.tclers.tk" $jid]} { set color [plugins::nickcolors::get_color $user] if {[string length $color] > 0} { lappend var [jlib::wrapper:createtag x \ -vars [list xmlns urn:tkchat:chat \ color [color_to_hex $color]]] } } } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/quotelastmsg/0000755000175000017500000000000011076120366016733 5ustar sergeisergeitkabber-plugins-0.11.1/quotelastmsg/README0000644000175000017500000000465411075425335017627 0ustar sergeisergei$Id: README 1513 2008-10-15 17:39:41Z sergei $ "Quote last message" -- chat plugin for Tkabber. I. The idea This plugin provides a way to "quote" the message located at the very bottom of the conversation log of a chat window -- that is, to copy such message into the input box of the same chat window with some decorations added (by default the ">> " string is prepeneded to the message). By default, quoting is done using the keyboard shortcut. The functionality provided by this plugin might come in handy when you want to refer to someone else's (or your own) message appeared in the course of the conversation. II. Configuration You can configure two parameters affecting the operation of this plugin: actions triggering the quotation of the last message and the format string used to decorate the message being quoted. Message quoting action is bound to a Tk virtual event named <>. By default, it's bound to (also to to accound for certain Unix systems). To change the binding you will have to add appropriate command(s) to the Tkabber configuration file. For instance, to unbind this action from and bind it to write this into your condig.tcl: event delete <> event delete <> event add <> Full details about the "event" command can be found in [1]. Note that you can use any event specifier, not just keyboard shortcuts. Refer to [2] for full details. The format string used to decorate the message being quoted can be changed using the Customize interface in the "Plugins -> Quote Last Message" group of settings (also reachable as "Chat -> Quote Last Message"). The actual setting is named ::plugins::quotelastmsg::options(format) and it defaults to the string ">> %m". In the format string the format specifier "%m" is substituted by the whole message as seen in the conversation log window, and the specifier "%%" is replaced by a single character "%". III. Bugs and limitations * There's currently no way to separately refer to the parts of the message being quoted (such as its timestamp, poster's nickname and the message body) in the format string. * It's impossible to embed "special chanracters" into the format string (such as \n or \t). IV. References 1. http://www.tcl.tk/man/tcl8.5/TkCmd/event.htm 2. http://www.tcl.tk/man/tcl8.5/TkCmd/bind.htm vim:et:ts=4:sw=4:tw=64 tkabber-plugins-0.11.1/quotelastmsg/msgs/0000755000175000017500000000000011076120366017704 5ustar sergeisergeitkabber-plugins-0.11.1/quotelastmsg/quotelastmsg.tcl0000644000175000017500000000506711075425335022202 0ustar sergeisergei# $Id: quotelastmsg.tcl 1513 2008-10-15 17:39:41Z sergei $ # "Quote last message" chat plugin for Tkabber -- # Allows to copy message located at the bottom of the # conversation log in the chat window to the input box # of that chat window. # # Written by Konstantin Khomoutov # See license.terms for the terms of distribution. # See README for usage details. event add <> event add <> namespace eval quotelastmsg { variable state variable options ::msgcat::mcload [file join [file dirname [info script]] msgs] custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup {Quote Last Message} \ [::msgcat::mc "Quote Last Message plugin options.\ This plugin provides a way to copy a message located\ at the bottom of a chat window conversation log\ to the input box of that chat window."] \ -group Plugins \ -group Chat custom::defvar options(format) {>> %m} \ [::msgcat::mc "Format string used to quote the message.\ Format specifer \"%m\" is replaced by the whole message\ being quoted. Format specifier \"%%\" is replaced by\ a single character \"%\"."] \ -group {Quote Last Message} \ -type string hook::add open_chat_post_hook \ [namespace current]::setup_chat_window hook::add draw_message_post_hook \ [namespace current]::on_message_drawn } proc quotelastmsg::setup_chat_window {chatid type} { variable state set iw [::chat::input_win $chatid] bind $iw <> [list [namespace current]::quote $chatid] set cw [::chat::chat_win $chatid] set state($cw,last) 1.0 bind $cw +[list [namespace current]::cleanup $cw %W] } proc quotelastmsg::cleanup {w1 w2} { if {![string equal $w1 $w2]} return variable state unset state($w1,last) } proc quotelastmsg::on_message_drawn {chatid from type body x} { if {![chat::is_opened $chatid]} return set cw [::chat::chat_win $chatid] variable state upvar 0 state($cw,last) last set now [$cw index {end - 1 char}] if {[$cw compare $last < $now]} { $cw tag delete lastmsg $cw tag add lastmsg $last $now } set last $now } proc quotelastmsg::quote chatid { variable options set cw [::chat::chat_win $chatid] set iw [::chat::input_win $chatid] set range [$cw tag prevrange lastmsg end] if {$range == ""} return lassign $range x y $iw insert end [string map \ [list %% % %m [$cw get $x $y]] $options(format)] $iw see end } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/quotelastmsg/license.terms0000644000175000017500000000211211075425335021430 0ustar sergeisergeiCopyright (c) 2008 Konstantin Khomoutov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/quotelastmsg/INSTALL0000644000175000017500000000051011075425335017763 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/quotelastmsg/ ~/.tkabber/plugins/quotelastmsg/quotelastmsg.tcl Restart Tkabber, to get the plugin loaded. Consult the README file for the details about using this plugin. tkabber-plugins-0.11.1/quotelastmsg/AUTHORS0000644000175000017500000000006611075425335020010 0ustar sergeisergeiKonstantin Khomoutov tkabber-plugins-0.11.1/osd/0000755000175000017500000000000011076120366014770 5ustar sergeisergeitkabber-plugins-0.11.1/osd/osd.tcl0000644000175000017500000000537210771407202016266 0ustar sergeisergei# Tkabber OSD Module # Author: Jan Hudec # http://www.ucw.cz/~0rfelyus/twiki/view/Wishlist/TkabberOsdModule if {![info exists ::osd] || $::osd == ""} {return} namespace eval ::osd { set options "" set delay 5 set osdfont "" set pipe "" array set statuses {} } proc ::osd::open_osd_cat {} { variable pipe variable options variable delay variable osdfont if {$pipe != ""} { close $pipe set pipe "" } set command "|osd_cat $options -d $delay -a$delay" if {$osdfont != ""} { append command " -f $osdfont" } debugmsg osd $command set pipe [open $command w] fconfigure $pipe -buffering line } proc ::osd::try_write {text} { variable pipe if {[catch {puts $pipe $text}]} { osd::open_osd_cat if {[catch {puts $pipe $text}]} { debugmsg osd "Can't write to OSD" } } } proc ::osd::presence_notify {connid from type x args} { variable statuses if {[catch { set nick [get_nick $connid $from chat] }]} { set nick "$from" } if { "$nick"!="$from" } { set thefrom "$nick ($from)" } else { set thefrom "$from" } if { "$type"=="" } { set type "available" } set status "" set show "" foreach {attr val} $args { switch -- $attr { -status {set status $val} -show {set show $val} } } if {"$status"!=""} { set status " ($status)" } if {"$show"!=""} { set type "$type/$show" } set newstatus "$thefrom: $type$status" if {[catch { set oldstatus $statuses($from) } ]} { set oldstatus "$newstatus" } if { "$newstatus"!="$oldstatus" } { osd::try_write "$newstatus" } set statuses($from) "$newstatus" } proc ::osd::chat_message_notify {chatid from type body extras} { if {[chat::is_our_jid $chatid $from] || ![cequal $type chat]} { return } foreach xelem $extras { jlib::wrapper:splitxml $xelem tag vars isempty chdata children # Don't notify if this 'empty' tag is present. It indicates # messages history in chat window. if {[cequal $tag ""] && \ [cequal [jlib::wrapper:getattr $vars xmlns] tkabber:x:nolog]} { return } } set nick [get_nick [chat::get_connid $chatid] $from $type] osd::try_write "New message from $nick" } proc ::osd::get_nick {connid jid type} { if {[catch {chat::get_nick $connid $jid $type} nick]} { return [chat::get_nick $jid $type] } else { return $nick } } hook::add postload_hook ::osd::open_osd_cat 100 foreach event $::osd { switch -- $event { presence { hook::add client_presence_hook ::osd::presence_notify 100 } chat_message { hook::add draw_message_hook ::osd::chat_message_notify 20 } default { debugmsg osd "Unsupported notify type $event" } } } # vim: set sw=4 sts=4: tkabber-plugins-0.11.1/osd/ChangeLog0000644000175000017500000000126110162142132016530 0ustar sergeisergei2004-12-22 Alexey Shchepin * osd.tcl: Updated to work with xosd 2.2.12 (thanks to Krzysztof Kotlenga) 2003-06-27 Alexey Shchepin * osd.tcl (::osd::presence_notify): Accept connid argument (thanks to Maciek Pasternacki) 2003-06-09 Alexey Shchepin * osd.tcl: Better presence displaying (thanks to Maciek Pasternacki) 2003-04-08 Alexey Shchepin * osd.tcl: Now possible to show messages notifications (thanks to Vincent Ricard) 2003-04-07 Alexey Shchepin * osd.tcl: Now it works again with recent versions of osd_cat, added osdfont variable (thanks to Jan Hudec) tkabber-plugins-0.11.1/traffic/0000755000175000017500000000000011076120366015621 5ustar sergeisergeitkabber-plugins-0.11.1/traffic/msgs/0000755000175000017500000000000011076120366016572 5ustar sergeisergeitkabber-plugins-0.11.1/traffic/msgs/pl.msg0000644000175000017500000000254510667535014017730 0ustar sergeisergei# Polish messages file for traffic plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "JID" "JID" ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "Pres IN" "Status WCH" ::msgcat::mcset pl "Pres OUT" "Status WYCH" ::msgcat::mcset pl "Iq IN" "Iq WCH" ::msgcat::mcset pl "Iq OUT" "Iq WYCH" ::msgcat::mcset pl "Msg IN" "Wiad WCH" ::msgcat::mcset pl "Msg OUT" "Wiad WYCH" ::msgcat::mcset pl "All IN" "Wsz WCH" ::msgcat::mcset pl "All OUT" "Wsz WYCH" ::msgcat::mcset pl "On" "Włącz" ::msgcat::mcset pl "Off" "Wyłącz" ::msgcat::mcset pl "Traffic plugin options." "Ustawienia wtyczki statystyki ruchu." ::msgcat::mcset pl "Show nick instead of JID." "Pokaż nazwy kontaktów zamiast JID." ::msgcat::mcset pl "Use human-readable counters with K, M, G." "Użyj jednostek łatwych do odczytania (Kilo, Mega, Giga)." ::msgcat::mcset pl "Traffic statistics" "Statystyka ruchu" ::msgcat::mcset pl "Traffic" "Statystyka ruchu" ::msgcat::mcset pl "Refresh" "Odśwież" ::msgcat::mcset pl "Show XML" "Pokaż konsolę XML" ::msgcat::mcset pl "Reset" "Wyzeruj" ::msgcat::mcset pl "Save" "Zapisz" ::msgcat::mcset pl "Timer:" ::msgcat::mcset pl "Total" "Razem" ::msgcat::mcset pl "Are you sure you want to reset counters?" "Czy na pewno wyzerować liczniki?" tkabber-plugins-0.11.1/traffic/msgs/es.msg0000644000175000017500000000223410512234573017712 0ustar sergeisergei::msgcat::mcset es "All IN" "Todo IN" ::msgcat::mcset es "All OUT" "Todo OUT" ::msgcat::mcset es "Are you sure you want to reset counters?" "¿Estás seguro de que deseas reiniciar los contadores?" ::msgcat::mcset es "Iq IN" "Iq IN" ::msgcat::mcset es "Iq OUT" "Iq OUT" ::msgcat::mcset es "JID" "JID" ::msgcat::mcset es "Msg IN" "Msg IN" ::msgcat::mcset es "Msg OUT" "Msg OUT" ::msgcat::mcset es "Off" "No" ::msgcat::mcset es "On" "Sí" ::msgcat::mcset es "Plugins options." "Opciones de plugin." ::msgcat::mcset es "Pres IN" "Pres IN" ::msgcat::mcset es "Pres OUT" "Pres OUT" ::msgcat::mcset es "Refresh" "Actualizar" ::msgcat::mcset es "Reset" "Reiniciar" ::msgcat::mcset es "Save" "Guardar" ::msgcat::mcset es "Show XML" "Mostrar XML" ::msgcat::mcset es "Show nick instead of JID." "Mostrar apodo en vez del JID." ::msgcat::mcset es "Timer:" "Reloj:" ::msgcat::mcset es "Total" "Total" ::msgcat::mcset es "Traffic plugin options." "Opciones del plugin de Tráfico." ::msgcat::mcset es "Traffic statistics" "Estadísticas de tráfico" ::msgcat::mcset es "Traffic" "Tráfico" ::msgcat::mcset es "Use human-readable counters with K, M, G." "Usar contadores legibles con K, M, G." tkabber-plugins-0.11.1/traffic/msgs/de.msg0000644000175000017500000000370010600555322017666 0ustar sergeisergei # German messages file # Roger Sondermann 21.03.2007 ::msgcat::mcset de "All IN" "Alle <-" ::msgcat::mcset de "All OUT" "Alle ->" ::msgcat::mcset de "Are you sure you want to reset counters?" "Wirklich alle Zhler zurcksetzen?" ::msgcat::mcset de "Iq IN" "IQ <-" ::msgcat::mcset de "Iq OUT" "IQ ->" ::msgcat::mcset de "JID" "JID" ::msgcat::mcset de "Msg IN" "Nachr. <-" ::msgcat::mcset de "Msg OUT" "Nachr. ->" ::msgcat::mcset de "Off" "Aus" ::msgcat::mcset de "On" "An" ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "Pres IN" "Prs. <-" ::msgcat::mcset de "Pres OUT" "Prs. ->" ::msgcat::mcset de "Refresh" "Abfragen" ::msgcat::mcset de "Reset" "Zurcksetzen" ::msgcat::mcset de "Save" "Speichern" ::msgcat::mcset de "Show XML" "XML" ::msgcat::mcset de "Show nick instead of JID." "Nicknamen an Stelle JID anzeigen." ::msgcat::mcset de "Timer:" "Intervall:" ::msgcat::mcset de "Total" "Datenverkehr insgesamt:" ::msgcat::mcset de "Traffic plugin options." "Optionen fr das Datenverkehr-Plugin." ::msgcat::mcset de "Traffic statistics" "Datenverkehr-Statistik" ::msgcat::mcset de "Traffic" "Datenverkehr-Statistik" ::msgcat::mcset de "Use human-readable counters with K, M, G." "Menschen-lesbare Zhler mit K, M, G benutzen." tkabber-plugins-0.11.1/traffic/msgs/ru.msg0000644000175000017500000000247210545463157017745 0ustar sergeisergei# $Id: ru.msg 851 2006-12-30 13:15:27Z sergei $ ::msgcat::mcset ru "Pres IN" ::msgcat::mcset ru "Pres OUT" ::msgcat::mcset ru "Iq IN" ::msgcat::mcset ru "Iq OUT" ::msgcat::mcset ru "Msg IN" ::msgcat::mcset ru "Msg OUT" ::msgcat::mcset ru "All IN" ::msgcat::mcset ru "All OUT" ::msgcat::mcset ru "On" "Вкл" ::msgcat::mcset ru "Off" "Выкл" ::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Traffic plugin options." "Параметры модуля по подсчету трафика." ::msgcat::mcset ru "Show nick instead of JID." "Показывать ник вместо JID-а." ::msgcat::mcset ru "Use human-readable counters with K, M, G." "Использовать читабельные счетчики с K, M, G." ::msgcat::mcset ru "Traffic statistics" "Статистика по трафику" ::msgcat::mcset ru "Traffic" "Трафик" ::msgcat::mcset ru "Refresh" "Обновить" ::msgcat::mcset ru "Show XML" "XML" ::msgcat::mcset ru "Save" "Сохранить" ::msgcat::mcset ru "Reset" "Сбросить" ::msgcat::mcset ru "Timer:" "Таймер:" ::msgcat::mcset ru "JID" ::msgcat::mcset ru "Total" "Всего" ::msgcat::mcset ru "Are you sure you want to reset counters?" "Вы уверены, что хотите сбросить счетчики?" tkabber-plugins-0.11.1/traffic/msgs/uk.msg0000644000175000017500000000244710545463157017740 0ustar sergeisergei ::msgcat::mcset uk "Pres IN" ::msgcat::mcset uk "Pres OUT" ::msgcat::mcset uk "Iq IN" ::msgcat::mcset uk "Iq OUT" ::msgcat::mcset uk "Msg IN" ::msgcat::mcset uk "Msg OUT" ::msgcat::mcset uk "All IN" ::msgcat::mcset uk "All OUT" ::msgcat::mcset uk "On" "Увімкнути" ::msgcat::mcset uk "Off" "Вимкнути" ::msgcat::mcset uk "Plugins options." "Параметри плагінів." ::msgcat::mcset uk "Traffic plugin options." "Параметри модуля по підрахунку трафіка." ::msgcat::mcset uk "Show nick instead of JID." "Показувати нік замість JID-а." ::msgcat::mcset uk "Use human-readable counters with K, M, G." "Використовувати читабельні лічильники з K, M, G." ::msgcat::mcset uk "Traffic statistics" "Статистика по трафіку" ::msgcat::mcset uk "Traffic" "Трафік" ::msgcat::mcset uk "Refresh" "Оновити" ::msgcat::mcset uk "Show XML" "XML" ::msgcat::mcset uk "Save" "Зберегти" ::msgcat::mcset uk "Reset" "Скинути" ::msgcat::mcset uk "Timer:" "Таймер:" ::msgcat::mcset uk "JID" ::msgcat::mcset uk "Total" "Всього" ::msgcat::mcset uk "Are you sure you want to reset counters?" "Ви впевнені, що хочете скинути лічильники?" tkabber-plugins-0.11.1/traffic/version.txt0000644000175000017500000000000410503042643020034 0ustar sergeisergei0.3 tkabber-plugins-0.11.1/traffic/traffic.tcl0000644000175000017500000002774210771407202017755 0ustar sergeisergei# $Id: traffic.tcl 1396 2008-03-23 08:02:10Z sergei $ # This plugin counts in and out bytes per JID. # # Bugs and feature request send to feez@jabber.ru namespace eval traffic { ::msgcat::mcload [file join [file dirname [info script]] msgs] array set stats {} array set jids {} # for table array set names [list \ presence,in [::msgcat::mc "Pres IN"] \ presence,out [::msgcat::mc "Pres OUT"] \ iq,in [::msgcat::mc "Iq IN"] \ iq,out [::msgcat::mc "Iq OUT"] \ message,in [::msgcat::mc "Msg IN"] \ message,out [::msgcat::mc "Msg OUT"] \ total,in [::msgcat::mc "All IN"] \ total,out [::msgcat::mc "All OUT"]] set columns [list presence,in presence,out iq,in iq,out message,in message,out total,in total,out] set sort_order total,in set current_connid 0 set wished_connid "0 None" set timer 5 set timer_state 0 set timer_id {} array set timer_names [list 0 [::msgcat::mc "On"] 1 [::msgcat::mc "Off"]] # Options custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup Traffic [::msgcat::mc "Traffic plugin options."] -group Plugins custom::defvar options(show_nick) 1 \ [::msgcat::mc "Show nick instead of JID."] \ -type boolean -group Traffic custom::defvar options(human_readable) 1 \ [::msgcat::mc "Use human-readable counters with K, M, G."] \ -type boolean -group Traffic trace variable options(show_nick) w [list [namespace current]::clear_and_refresh] } # ############################ # Handlers proc traffic::handle_inout {connid xmldata size prefix attr} { variable stat variable jids variable columns variable names jlib::wrapper:splitxml $xmldata tag vars isempty chdata children set jid [jlib::wrapper:getattr $vars $attr] if {[cequal $jid ""]} { set jid "SERVER" } else { catch { set jid [node_and_server_from_jid $jid] } } if {![info exists jids($connid,$jid)]} { # create set jids($connid,$jid) 1 lappend jids($connid,jids) $jid # initialize counters foreach column $columns { set stat($connid,$jid,$column) 0 } } # increment counters if {[info exists names($tag,$prefix)]} { incr stat($connid,$jid,$tag,$prefix) $size } incr stat($connid,$jid,total,$prefix) $size } proc ::LOG_INPUT_SIZE {connid xmldata size} \ "[namespace current]::traffic::handle_inout \$connid \$xmldata \$size in from" proc ::LOG_OUTPUT_SIZE {connid xmldata size} \ "[namespace current]::traffic::handle_inout \$connid \$xmldata \$size out to" # ############################ # GUI proc traffic::get_connections {} { set res [list "0 None"] foreach con [jlib::connections] { lappend res [list $con [jlib::connection_jid $con]] } return $res } proc traffic::open_window {} { variable columns variable names variable current_connid variable timer_state variable timer_names # create widgets set w .traffic_stats if {[winfo exists $w]} { raise_win $w return } # base widget add_win $w -title [::msgcat::mc "Traffic statistics"] \ -tabtitle [::msgcat::mc "Traffic"] \ -class Traffic \ -raise 1 # button box set tools [frame $w.tools -borderwidth 5] pack $tools -side top -anchor w -fill x button $tools.refresh -text [::msgcat::mc "Refresh"] \ -command [list [namespace current]::refresh] pack $tools.refresh -side right -anchor w set connections [get_connections] ComboBox $tools.connection -textvariable [namespace current]::wished_connid \ -values $connections -height [expr [llength $connections] + 1] -editable 0 \ -modifycmd [list [namespace current]::refresh] pack $tools.connection -side right -anchor w unset connections button $tools.show_xml -text [::msgcat::mc "Show XML"] \ -command [list ::plugins::rawxml::open_window] pack $tools.show_xml -side left -anchor w button $tools.save -text [::msgcat::mc "Save"] \ -command [list [namespace current]::save_stat] pack $tools.save -side left -anchor w button $tools.reset -text [::msgcat::mc "Reset"] \ -command [list [namespace current]::reset] pack $tools.reset -side left -anchor w pack [label $tools.timerlab -text [::msgcat::mc "Timer:"]] -side left -anchor w Spinbox $tools.timerspin 1 100000 1 [namespace current]::timer $tools.timerspin configure -width 4 pack $tools.timerspin -side left -anchor w button $tools.timer -text $timer_names($timer_state) \ -command [list [namespace current]::turn_timer] pack $tools.timer -side left -anchor w # create grid set sw [ScrolledWindow $w.sw -relief sunken -bd 1] pack $sw -side top -fill both -expand yes set sf [ScrollableFrame $w.sf] $sw setwidget $sf set f [$sf getframe] bindscroll $f $sf # fill grid header grid [label $f.titlejid -text [::msgcat::mc "JID"] -width 20] -row 0 -column 0 -sticky w bindscroll $f.titlejid $sf set i 1 foreach col $columns { set b [Button $f.titlelabel$i -text $names($col) \ -command [list [namespace current]::sort $col]] grid $b -row 0 -column $i -sticky we bindscroll $f.titlelabel$i $sf incr i } refresh } proc traffic::refresh {} { variable stat variable jids variable columns variable wished_connid variable current_connid variable options set w .traffic_stats if {![winfo exists $w]} return set f [$w.sf getframe] # clear if connection was changed if {![cequal [lindex $wished_connid 0] $current_connid]} { clear_table $f set current_connid [lindex $wished_connid 0] } if {!$current_connid} return # init sum counters array set sum {} foreach col $columns { set sum($col) 0 } # fill the table set row 1 foreach jid [lsort -decreasing -command compare $jids($current_connid,jids)] { set tag [jid_to_tag $jid] # set first column - jid if {![winfo exists $f.jid$tag]} { label $f.jid$tag -text $jid if {$options(show_nick)} { set nick [roster::itemconfig $current_connid [roster::find_jid $current_connid $jid] -name] if {$nick != ""} { $f.jid$tag configure -text $nick } } } grid $f.jid$tag -row $row -column 0 -sticky w bindscroll $f.jid$tag $w.sf set i 1 # set other columns - counters foreach col $columns { if {![winfo exists $f.value$i$tag]} { label $f.value$i$tag } set value $stat($current_connid,$jid,$col) incr sum($col) $value $f.value$i$tag configure -text [convert_to_hr $value 10] grid $f.value$i$tag -row $row -column $i -sticky e bindscroll $f.value$i$tag $w.sf incr i } incr row } # add sum if {![winfo exists $f.sumname]} { label $f.sumname -text [::msgcat::mc "Total"] } grid $f.sumname -row $row -column 0 -sticky w bindscroll $f.sumname $w.sf set i 1 foreach col $columns { if {![winfo exists $f.sumval$i]} { label $f.sumval$i } $f.sumval$i configure -text [convert_to_hr $sum($col) 10] grid $f.sumval$i -row $row -column $i -sticky e bindscroll $f.sumval$i $w.sf incr i } } proc traffic::convert_to_hr {value limit} { variable options if {!$options(human_readable)} { return $value } set cur "" foreach c {K M G} { if {($value / 1024) > $limit} { set value [expr {$value / 1024}] set cur $c } else { break } } return $value$cur } proc traffic::clear_table {f} { set max [expr [string length $f.title] - 1] foreach slave [grid slaves $f] { if {![cequal [string range $slave 0 $max] $f.title]} { grid remove $slave destroy $slave } } } proc traffic::clear_and_refresh {args} { set w .traffic_stats if {![winfo exists $w]} return set f [$w.sf getframe] clear_table $f refresh } proc traffic::update_connections {type connid} { variable wished_connid set w .traffic_stats if {![winfo exists $w]} return set connections [get_connections] if {[cequal $type off] && [lsearch $connections $wished_connid] < 0} { set wished_connid "0 None" } $w.tools.connection configure -values $connections -height [expr [llength $connections] + 1] if {[cequal $type on] && [cequal $wished_connid "0 None"]} { set wished_connid [list $connid [jlib::connection_jid $connid]] } refresh } proc traffic::tick {} { variable timer_id variable timer refresh set timer_id [after [expr $timer * 1000] [list [namespace current]::tick]] } proc traffic::turn_timer {args} { variable timer_state variable timer_names variable timer_id variable timer set timer_state [expr 1 - $timer_state] if {$timer_state} { set timer_id [after [expr $timer * 1000] [list [namespace current]::tick]] } else { after cancel $timer_id } set w .traffic_stats if {![winfo exists $w]} return $w.tools.timer configure -text $timer_names($timer_state) } # ############################ # Other functions proc traffic::compare {arg1 arg2} { variable stat variable sort_order variable current_connid return [expr $stat($current_connid,$arg1,$sort_order) - \ $stat($current_connid,$arg2,$sort_order)] } proc traffic::sort {tag} { variable sort_order set sort_order $tag refresh } proc traffic::save_stat {} { variable names variable columns variable stat variable current_connid variable jids set filename [tk_getSaveFile \ -initialdir $::configdir] if {$filename != ""} { set fd [open $filename w] # Header set str {} lappend str "JID" foreach col $columns { lappend str $names($col) } puts $fd [join $str "\t"] # Data foreach jid $jids($current_connid,jids) { set str {} lappend str $jid foreach col $columns { lappend str $stat($current_connid,$jid,$col) } puts $fd [join $str "\t"] } close $fd } } proc traffic::reset {} { variable current_connid variable columns variable jids variable stat if {!$current_connid} return if {[MessageDlg .request_reset_traffic \ -aspect 50000 \ -icon warning \ -type user \ -buttons {yes no} \ -default 1 \ -cancel 1 \ -message [::msgcat::mc "Are you sure you want to reset counters?"]]} { return } # clear stats foreach jid $jids($current_connid,jids) { foreach col $columns { unset stat($current_connid,$jid,$col) } unset jids($current_connid,$jid) } set jids($current_connid,jids) {} # clear table clear_and_refresh } # ############################ # Register in the main menu proc traffic::setup_menu {} { catch { set m [.mainframe getmenu plugins] set ind [$m index end] $m insert $ind command -label [::msgcat::mc "Traffic statistics"] \ -command [list [namespace current]::open_window] } } hook::add finload_hook [namespace current]::traffic::setup_menu # ############################################## # Hooks on connect and disconnect (update GUI) hook::add connected_hook \ [list [namespace current]::traffic::update_connections on] hook::add disconnected_hook \ [list [namespace current]::traffic::update_connections off] ############################################################################## proc traffic::restore_window {args} { open_window } proc traffic::save_session {vsession} { upvar 2 $vsession session global usetabbar # We don't need JID at all, so make it empty (special case) set user "" set server "" set resource "" # TODO if {!$usetabbar} return set prio 0 foreach page [.nb pages] { set path [ifacetk::nbpath $page] if {[string equal $path .traffic_stats]} { lappend session [list $prio $user $server $resource \ [list [namespace current]::restore_window] \ ] } incr prio } } hook::add save_session_hook [namespace current]::traffic::save_session tkabber-plugins-0.11.1/traffic/Changelog0000644000175000017500000000010010503042643017415 0ustar sergeisergeihttp://wiki.tkabber.jabe.ru/index.php/Plugins/Traffic/Changelog tkabber-plugins-0.11.1/singularity/0000755000175000017500000000000011076120366016555 5ustar sergeisergeitkabber-plugins-0.11.1/singularity/singularity.tcl0000644000175000017500000000560211075425335021641 0ustar sergeisergei# $Id: singularity.tcl 1513 2008-10-15 17:39:41Z sergei $ # When a new chat window is about to be opened this plugin # checks whether any chats with other resources of this chat peer # are currently opened and closes them all, if any. # In other words, it ensures that only one chat window per bare # JID is opened at any given time. # Written by Konstantin Khomoutov # See license.terms for the terms of distribution. # See README for usage details. namespace eval singularity { variable contexts variable options ::msgcat::mcload [file join [file dirname [info script]] msgs] custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup Singularity \ [::msgcat::mc "Singularity plugin options.\ What this plugin makes is to do cleanup by closing obsolete\ chat windows opened for different resources of the same\ contact ensuring only one chat window for a contact\ is opened at any given time."] \ -group Plugins \ -group IFace custom::defvar options(enabled) 1 \ [::msgcat::mc "Allows closing obsolete chat windows\ for a contact when a new chat session window\ with that contact is about to be opened."] \ -group Singularity \ -type boolean hook::add open_chat_pre_hook \ [namespace current]::process_new_chat_opening hook::add open_chat_post_hook \ [namespace current]::restore_chat_context } proc singularity::process_new_chat_opening {chatid type} { variable options if {!$options(enabled) || ![string equal $type chat]} return set from [chat::get_jid $chatid] set barejid [node_and_server_from_jid $from] if {[chat::is_groupchat [chat::chatid \ [chat::get_connid $chatid] $barejid]]} return variable contexts upvar 0 contexts(input,$chatid) savedinput upvar 0 contexts(history,$chatid) savedhistory variable [namespace parent]::history set savedinput "" set savedhistory [list] foreach cid [chat::opened] { set jid [chat::get_jid $cid] if {![string equal $from $jid] && [string equal $barejid [node_and_server_from_jid $jid]]} { if {$savedinput != ""} { append savedinput \n } append savedinput [[chat::input_win $cid] get 1.0 end-1c] set savedhistory [concat $savedhistory $history(stack,$cid)] chat::close $cid } } } proc singularity::restore_chat_context {chatid type} { variable options if {!$options(enabled) || ![string equal $type chat]} return variable contexts upvar 0 contexts(input,$chatid) savedinput upvar 0 contexts(history,$chatid) savedhistory if {![info exists savedinput]} return variable [namespace parent]::history [chat::input_win $chatid] insert end $contexts(input,$chatid) set history(stack,$chatid) $contexts(history,$chatid) set history(pos,$chatid) 0 unset contexts(input,$chatid) contexts(history,$chatid) } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/singularity/README0000644000175000017500000000510011075425335017434 0ustar sergeisergei$Id: README 1513 2008-10-15 17:39:41Z sergei $ "Singularity" -- main interface plugin for Tkabber. I. The Idea When you chat with someone in Tkabber, the corresponding chat window is opened for the full JID of that person (it is a JID with the resource part: node@server/resource). Since your peers can normally log into their XMPP accounts several times at once (with a different resource each time) Tkabber maintains clear distinction between these full JIDs. On the other hand, most people seldom chat from several connections to their account at once -- quite more often they move between two or more XMPP clients located in places which are geographically quite apart, such as their home and office. In this case it may be convenient to maintain just one chat window open for each person you're chatting with -- for instance, you start chatting whith your peer when he/she is at home, then your peer moves to their office and sends a message from the new location; at this point it might be convenient not to have two chat windows -- old and new -- open, but just the new one. This plugin implements the described functionality: when the new window for a one-on-one chat is about to be opened the plugin checks whether there are any active chat sessions with the same bare JID (that is, without the "/resource" part) as that of the new chat. If there are, they are closed with their conversation log and input history preserved, the new chat window is opened and then the saved data is inserted into the new window. So effectively this plugin makes Tkabber keep just one chat window per bare JID open. The plugin does not touch MUC private chats because in them resource part of the room JID is used to designate participants' nicknames. II. Usage Just install this plugin as usually and restart Tkabber. Currently there's no UI to control the plugin's behaviour. III. Bugs and limitations * Tkabber is currently unable to actually "switch" a chat window from one JID to another, so this plugin works by closing the existing window(s) and opening the new one. While in tabbed mode this looks mostly OK, in windowed mode this may be annoying because the new window will most probably not appear at the same location and layer as the closed window. * For some unknown reason the first line of the input history is lost when the chat state is transferred to the newly opened window. * If there are several chat windows to be closed when the new one is about to be opened, the order in which their conversation logs and input history records are collected is undefined. # vim:tw=64:noet tkabber-plugins-0.11.1/singularity/msgs/0000755000175000017500000000000011076120366017526 5ustar sergeisergeitkabber-plugins-0.11.1/singularity/license.terms0000644000175000017500000000211211075425335021252 0ustar sergeisergeiCopyright (c) 2008 Konstantin Khomoutov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/singularity/INSTALL0000644000175000017500000000050511075425335017611 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/singularity/ ~/.tkabber/plugins/singularity/singularity.tcl Restart Tkabber, to get the plugin loaded. Consult the README file for the details about using this plugin. tkabber-plugins-0.11.1/singularity/AUTHORS0000644000175000017500000000006611075425335017632 0ustar sergeisergeiKonstantin Khomoutov tkabber-plugins-0.11.1/ctcomp/0000755000175000017500000000000011076120366015470 5ustar sergeisergeitkabber-plugins-0.11.1/ctcomp/README0000644000175000017500000003211710716650273016361 0ustar sergeisergei$Id: README 1314 2007-11-14 19:47:07Z sergei $ "Chat text completions" -- chat plugin for Tkabber. I. The idea This plugin adds support for "text completion" in Tkabber's chat input windows, i.e. it's possible to make Tkabber offer you possible completions of a current partially typed word in a chat input window. Possible completions are looked up in both the input window and the chat log window (also it's possible to provide custom list of matches, see the "Customization" section). This feature is loosely modeled after the text completion implementations found in Vim [1] and Emacs [2] text editors; default text completion key bindings of this plugin are the same as default key bindings for this feature in those editors (see the "Using" section). Note though, that while both Vim and Emacs offer you possible completions in a "recently typed -- first" manner, this plugin offers them in a dictionary-sorted order. II. Using At first, note that we'll use "Emacsish" notation of describing keystrokes for the sake of brevity. For those who isn't familiar with it here's a quick explanation: * "C" stands for "Control" key (also known as "Ctrl"). * "M" stands for "Meta" key (also known as "Alt" on some computers/OSes). * Any other key symbols stand for themselves. * Key combinations (groups of keys that are required to be pressed simultaneously) are specified as a list of appropriate key symbols joined by dashes ("-"). For example, "C-M-a" stands for Control, Meta (Alt) and "a" keys pressed simultaneously. There are two major modes of operation possible: * Requesting menu with possible completions. * Traversing the list of possible completions "in place". Entering each mode is requested by pressing one of the available keystrokes (discussed below) just after the first character(s) of a word you want to complete. For example, suppose the current chat log window and/or the current input window contain these words: abba, abbot, abbatisse. Now suppose you have just typed "ab" and want to complete it -- type C-M-/ to get the menu listing top 20 words starting from "ab" found in mentioned windows or type C-n to enter the "in place" mode and get the first proposed completion right at your insert cursor (with the completed part visually emphasized). Any completion mode can be cancelled -- you return to that piece of the word you started with. The completion keybindings will be described just in a moment. So, let's recap: * Type some first letters of the word you want to complete, * Engage one of the available completion modes. * Pick the required completion or chancel the completion mode. 1. Using the completion menu The menu presenting the first 20 completions can be by default posted using C-M-/ gesture. Select whatever completion you're happy with or cancel the menu by clicking outside of it or pressing the key. If you have selected a completion, the word being completed in the input window will be replaced by the selected completion. If you have cancelled the completion menu no change will be made to the input window. This gesture is modeled after the Emacs text editor. 2. Using the "in place" traversing of possible completions This mode is modeled after the similar Vim text editor's facility and so the C-n and C-p keystrokes are used. They switch the input windows into the "completion mode" and insert the first or the last completion from the list of proposed completions at the insert cursor. The completed part of the inserted word is highlighted. Also the M-/ keystroke is equivalent to C-n -- this one is taken from Emacs. While being in the completion mode you can: * Continue using the C-n (and/or M-/) and C-p keystrokes to iterate through the list of proposed completions "up" and "down", respectively. * Hit the Return (Enter) key to accept the currently displayed completion and return to the normal editing mode. * Hit the Escape key to remove the currently displayed completion and return to the normal mode. In other words this cancels the completon mode. Hitting any other key not listed above (i.e. a key which doesn't have special meaning in the completion mode) accepts the currently displayed completion, returns the input window to the normal mode, and then this keystroke is passed to the input window so that if it would result in a printable character being inserted this character will be inserted just after the completed word. III. Customization 1. Keystrokes All the relevant bindings in Tkabber's chat input windows are done via Tk virtual events [3] so they are easily customizable. Here are these events and their default bindings: * Event: <> Default bindings: , , Action: show next possible completion "in place", activate the "in place" completion mode beforehang, if currently in the normal mode. * Event: <> Default bindings: Action: same as above but shows the previous possible completion. * Event: <> Default keybindings: Action: accept the completion currently proposed "in place" and return to normal mode. * Event: <> Default keybindings: Action: remove the completion currently proposed "in place" and return to normal mode. * Event: <> Default keybindings: , Action: show menu with possible completions. If you're not familiar with Tk [event] [3] and [bind] [4] commands, here's a quick reference: * To bind your keystroke to a virtual event use event add <<...event name...>> <...keystroke spec...> For example, to bind posting of the completion menu to the F5 key, put this in the Tkabber's config file: event add <> * To unbind existing binding from a virtual event use event delete <<...event name...>> <...keystroke spec...> For example to make the completion menu only be posted by the F5 key, add also this lines to the config file: event delete <> event delete <> * To "substitute" (all) the default bindings for a virtual event by yours you can use something like this: event delete <> event add <> The first line kills all bindings for the virtual event, the second adds one new. Be sure to read and understand [3] and [4] before proceeding! Specification of keystrokes is explained in [4], all keysyms known to Tk are listed in [5]. Note that due to a bug in the Windows port of Tk users of non-US keymaps in this OS can have problems with these shortcuts. Please read "Working around Tk Windows keyboard bug" below for the (partial) solution to this problem. 2. Highlighting colors of "in place" completion Two Tk option database resources are used, both are of class "Chat": * Resource: Chat.textCompletionForeground Default: black Meaning: foreground color of the "proposed" tail of the word being completed "in place". * Resourec: Chat.textCompletionBackground Default: pink Meaning: same as above but for the background color. 3. Search pattern The search pattern used to search for possible completions in Tk Text widgets is available via the ::plugins::ctcomp::options(pattern) setting. This is an ARE [6] pattern containing the "%s" token which is replaced before searching by the part of the word being completed. This pattern makes the searching engine to look for "any word starting with the specified letters". Note that you should think twice before changing this pattern: for example the "in place" completion mode assumes that completions start from the prefix being completed and if you, say, change the pattern so that it will match in a middle of words, you'll get unexpected results in this completion mode. 4. Hooks This plugin has four "hooks" [7] that run when certain chat text completion events occur. They can be used to fine-tune the operation of this plugin. Beware though that using them requires some knowledge of Tcl. These hooks are: * chat_text_completion_start_hook This hook is run when the plugin enters the "in place" completion mode and is about to show the first proposed completion. Two arguments are appended to the hook script before evaluation: * handle to the chat in which the completion mode is entered (usually referred to as "chatid"). * word being completed. Primary intent of this hook (and its "mirror" hook chat_text_completion_end_hook) is to be used to provide some sort of additional visual hint to the user indicating active "in place" completion mode. * chat_text_completion_end_hook This hook is run when the plugin leaves the "in place" completion mode. One argument is appended to the hook script before evaluation -- handle to the chat ("chatid"). * chat_text_completion_matches_hook This hook is run when the plugin builds a list of possible completions for the word being completed, just after the proposed completions have been gathered from the relevant input and chat log windows. Four arguments are appended to the hook script before evaluation: * handle to the chat in which the completion mode is entered ("chatid"). * word being completed. * stack level containing the variable with proposed completions. * name of the variable holding a list with proposed completions. To modify this variable inside a proc use the [upvar] command, for example: proc gencomp {chatid what level compsName} { upvar $level $compsName comps lappend comps ${what}not ${what}sup } hook::add chat_text_completion_matches_hook gencomp Note that scripts handling this hook must not do any assumptions about the list of proposed completions they operate on (like sorted/unsorted, uniquennes of the words, etc). Also note that while any strings can be added to the list of possible completions using this hook, the "in place" completion mode assumes that each proposed completion starts from the word being completed; when this assumption is not honored, strange things may happen. * chat_text_completion_menu_hook This hook is run just before the menu with proposed completions is shown to the user. Three arguments are appended to the hook script before evaluation: * handle to the chat in which the completion mode is entered ("chatid"). * word being completed. * name of the menu window populated with proposed completions. This hook can be used to tweak the menu before it will be popped up. IV. Limitations and bugs Default keybindings and used by this plugin effectively "hijack" the same keybindings built into the chat input windows (they are used for moving forth and back through the history of outgoing messages). The and keybindings can be used for the input history management but if you want to continue using and for this while using this plugin, you should unbind and from the ctcomp plugin (and possibly bind the relevant actions to some other combinations of keys), like this: # Take and away from ctcomp: event delete <> event delete <> # Use and to do the same actions: event add <> event add <> No "automatic" completion ("propose completions as I type" found in certain text editing tools like Writer from the OpenOffice.org suite or some mobile phones) is possible. The same holds for the "in place" completion mode: typing a regular keystroke terminates the completion mode, not narrows the list of possible completions (this is Vim-like). No guarantees of proper work are made if the user fiddles with the searching regexp pattern. The same is true for the case when the user modifies the list of proposed completion via the relevant hook. Not all completions will be shown in the completion menu if its number exceeds the hard-coded limit. V. Working around Tk Windows keyboard bug Tk has unfortunate long-standing bug which prevents certain key combinations involving "letter keys" from working with "non-ASCII" keymaps (e.g. Russian keymap) in Windows. For example, C-n, C-p, M-/ and C-M-/ work when the US keymap is active but don't work when a Russian keymap is. Users of Russian keymaps may add following lines to their config.tcl file to work around this bug: event add <> event add <> event add <> event add <> This will make C-n, C-p and C-M-/ to work as expected on both US and Russian ("QWERTY") keymaps. Note that if you change the default bindings you may also need to modify these "mirror" bindings. Please refer to the Russian Tkabber wiki [8] for more info. VI. Links 1. http://vim.sf.net 2. http://www.gnu.org/software/emacs/ 3. http://www.tcl.tk/man/tcl8.4/TkCmd/event.htm 4. http://www.tcl.tk/man/tcl8.4/TkCmd/bind.htm 5. http://www.tcl.tk/man/tcl8.4/TkCmd/keysyms.htm 6. http://www.tcl.tk/man/tcl8.4/TclCmd/re_syntax.htm 7. http://tkabber.jabber.ru/files/doc/tkabber.html#s.extensibility 8. http://ru.tkabber.jabe.ru # vim:tw=64:noet tkabber-plugins-0.11.1/ctcomp/TODO0000644000175000017500000000067310702150302016152 0ustar sergeisergei$Id: TODO 1256 2007-10-07 12:27:46Z sergei $ * Some way should be invented to allow foreground color to be picked up from the input window itself, if not specified directly by the user. * Finding of a word being completed is a bit broken: for the string "mumble ??_" with the cursor denoted by "_" pressing C-n will yield "mumble ??" instead of "??" or "". So probably something needs to be rethought/fine-tuned. # vim:tw=64:noet tkabber-plugins-0.11.1/ctcomp/license.terms0000644000175000017500000000211210702150302020146 0ustar sergeisergeiCopyright (c) 2007 Konstantin Khomoutov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/ctcomp/INSTALL0000644000175000017500000000046510702150302016512 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/ctcomp/ ~/.tkabber/plugins/ctcomp/ctcomp.tcl Restart Tkabber, to get the plugin loaded. Consult the README file for the details about using this plugin. tkabber-plugins-0.11.1/ctcomp/AUTHORS0000644000175000017500000000006610702150302016526 0ustar sergeisergeiKonstantin Khomoutov tkabber-plugins-0.11.1/ctcomp/ctcomp.tcl0000644000175000017500000001737010710405374017470 0ustar sergeisergei# $Id: ctcomp.tcl 1281 2007-10-26 15:42:52Z sergei $ # "Chat text completion -- Tkabber plugin. # Written by Konstantin Khomoutov # See "lisence.terms" for details about distribution. # Consult README for the information and usage guidelines. option add *Chat.textCompletionForeground black widgetDefault option add *Chat.textCompletionBackground pink widgetDefault namespace eval ctcomp { variable options set options(pattern) {\m%s\w+\M} event add <> event add <> event add <> event add <> event add <> event add <> event add <> event add <> bind ChatTextCompInactive <> [namespace code { if {[matches in %W]} { activate %W match first next in %W } break }] bind ChatTextCompInactive <> [namespace code { if {[matches in %W]} { activate %W match first prev in %W } break }] bind ChatTextCompInactive <> [namespace code { if {[matches in %W]} { show_matches in %W reset_state %W } break }] bind ChatTextCompActive <> [namespace code { match next next in %W break }] bind ChatTextCompActive <> [namespace code { match next prev in %W break }] bind ChatTextCompActive <> [namespace code { accept %W deactivate %W break }] bind ChatTextCompActive <> [namespace code { cancel %W deactivate %W break }] bind ChatTextCompActive [namespace code { accept %W deactivate %W }] hook::add open_chat_post_hook [namespace current]::prepare } proc ctcomp::initialize iw { set btags [bindtags $iw] set ix [lsearch -exact $btags $iw] bindtags $iw [linsert $btags $ix ChatTextCompInactive] reset_state $iw } proc ctcomp::activate iw { variable $iw upvar 0 $iw state set btags [bindtags $iw] set ix [lsearch -exact $btags ChatTextCompInactive] bindtags $iw [lreplace $btags $ix $ix ChatTextCompActive] hook::run chat_text_completion_start_hook $state(chatid) $state(what) } proc ctcomp::deactivate iw { variable $iw upvar 0 $iw state set btags [bindtags $iw] set ix [lsearch -exact $btags ChatTextCompActive] bindtags $iw [lreplace $btags $ix $ix ChatTextCompInactive] hook::run chat_text_completion_end_hook $state(chatid) reset_state $iw } proc ctcomp::prepare {chatid type} { variable options set iw [chat::input_win $chatid] set cw [chat::chat_win $chatid] variable $iw upvar 0 $iw state set state(chatid) $chatid initialize $iw bind $iw +[list [namespace current]::cleanup $iw %W] } proc ctcomp::cleanup {w1 w2} { if {![string equal $w1 $w2]} return variable $w1 unset $w1 } proc ctcomp::reset_state iw { variable $iw upvar 0 $iw state set state(matches) [list] set state(last) "" set state(what) "" } proc ctcomp::accept iw { $iw tag remove ctcomp/submatch comp_start comp_end $iw mark unset comp_start $iw mark unset comp_end } proc ctcomp::cancel iw { $iw delete comp_start comp_end $iw mark unset comp_start $iw mark unset comp_end } proc ctcomp::pattern what { variable options format $options(pattern) [string map { \\ \\\\ [ \\[ ] \\] \{ \\\{ \} \\\} ( \\( ) \\) $ \\$ . \\. * \\* ? \\? } $what] } proc ctcomp::matches {"in" iw} { variable $iw upvar 0 $iw state upvar 0 state(what) what upvar 0 state(matches) matches set what [word from $iw] if {[string length $what] == 0} { return false } set matches [get_matches for $what in $iw] if {[llength $matches] == 0} { show info $iw "No match for $what" return false } return true } proc ctcomp::startOfPreviousWord {str start} { if {[string equal $start end]} { set start [string length $str] } if {[regexp -indices {\m(\w+)\W*$} \ [string range $str 0 [expr {$start - 1}]] -> word]} { return [lindex $word 0] } return -1 } proc ctcomp::word {"from" t} { set from [tk::TextPrevPos $t insert \ [namespace current]::startOfPreviousWord] $t get $from insert } proc ctcomp::get_matches {"for" what "in" iw} { variable $iw upvar 0 $iw state upvar 0 state(chatid) chatid set completions [concat \ [get_text_matches for $what in [chat::chat_win $chatid]] \ [get_text_matches for $what in $iw]] hook::run chat_text_completion_matches_hook \ $chatid $what #[info level] completions lsort -dictionary -unique $completions } proc ctcomp::get_text_matches {"for" what "in" t} { set pos 1.0 set matches [list] while 1 { set at [$t search -count len -regexp [pattern $what] $pos end] if {$at == {}} break lappend matches [$t get $at "$at + $len chars"] set pos [$t index "$at + 1 char"] } set matches } proc ctcomp::last L { expr {[llength $L] - 1} } proc ctcomp::getopt {iw opt} { variable $iw upvar 0 $iw state option get [chat::winid $state(chatid)] $opt Chat } proc ctcomp::tail {what match} { string range $match [string length $what] end } proc ctcomp::match {seq dir "in" iw} { variable $iw upvar 0 $iw state upvar 0 state(what) what upvar 0 state(matches) matches upvar 0 state(last) last switch -- $seq { first { switch -- $dir { next { set last 0 } prev { set last [last $matches] } } $iw mark set comp_start insert $iw mark gravity comp_start left } next { advance to $dir in $iw $iw delete comp_start comp_end } } set submatch [tail $what [lindex $matches $last]] $iw tag configure ctcomp/submatch \ -foreground [getopt $iw textCompletionForeground] \ -background [getopt $iw textCompletionBackground] $iw insert comp_start $submatch ctcomp/submatch $iw mark set comp_end insert $iw mark gravity comp_end right } proc ctcomp::advance {"to" where "in" iw} { variable $iw upvar 0 $iw state upvar 0 state(last) last upvar 0 state(matches) matches set end [last $matches] switch -- $where { next { incr last if {$last > $end} { set last 0 wraparound in $iw } } prev { incr last -1 if {$last < 0} { set last $end wraparound in $iw } } } } proc ctcomp::wraparound {"in" iw} { show info $iw "Wrapped around" } proc ctcomp::show_matches {"in" iw} { set m $iw.matches if {![winfo exists $m]} { menu $iw.matches -tearoff no -postcommand [list \ [namespace current]::repopulate_matches_menu $iw $m] } lassign [lrange [$iw bbox insert] 0 1] x y set x [expr {[winfo rootx $iw] + $x}] set y [expr {[winfo rooty $iw] + $y}] tk_popup $m $x $y 0 } proc ctcomp::repopulate_matches_menu {iw m} { variable $iw upvar 0 $iw state upvar 0 state(what) what $m delete 0 end set i 0 foreach match $state(matches) { if {[incr i] > 20} break $m add command -label $match -command [list \ [namespace current]::menu_insert_match $iw [tail $what $match]] } hook::run chat_text_completion_menu_hook $state(chatid) $state(what) $m } proc ctcomp::menu_insert_match {iw tail} { variable $iw $iw insert insert $tail } # $type should be either "info" or "error" proc ctcomp::show {type iw msg} { variable $iw upvar 0 $iw state upvar 0 state(chatid) chatid set jid [chat::get_jid $chatid] set cw [chat::chat_win $chatid] chat::add_message $chatid $jid $type $msg {} } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/ctcomp/VERSION0000644000175000017500000000003710702150302016524 0ustar sergeisergeiVersion: 2.0 Date: 07-Oct-2007 tkabber-plugins-0.11.1/ctcomp/ChangeLog0000644000175000017500000000213410702150302017226 0ustar sergeisergei2007-10-07 Konstantin Khomoutov * Heavily redone using bindtags and virtual events. * Behaviour and keybindings are made more close to Vim/Emacs. * Added possibility to show a menu with possible completions. * Numerous bugfixes. * README re-written. * Now at version 2.0. 2007-02-25 Konstantin Khomoutov * Fixed bug occured when chatting with JIDs containing the "%s" character. * Stub ChangeLog file rewritten to reflect this project' state. 2007-02-18 Konstantin Khomoutov * Added support for Customize. * Misc bugfixes. * Added preliminary support for virtual events. * Added preliminary support for event validity checking. * Support for per-chat state. * Matching algorythm reworked. * Added keybindings for committing and cancelling the current match. * Proper deinitialization of completion mode. * Added files: AUTHORS, README, TODO, INSTALL, ChangeLog and license.terms 2007-02-15 Konstantin Khomoutov * Initial version. tkabber-plugins-0.11.1/aniemoticons/0000755000175000017500000000000011076120366016673 5ustar sergeisergeitkabber-plugins-0.11.1/aniemoticons/aniemoticons.tcl0000644000175000017500000000064610572520133022071 0ustar sergeisergei# $Id: aniemoticons.tcl 1001 2007-03-04 10:32:59Z sergei $ namespace eval :: { source [file join [file dirname [info script]] anigif.tcl] } namespace eval emoticons { proc create_image {name file} { if {[catch {::anigif::anigif $name $file} res]} { image create photo $name -file $file return $name } else { return $res } } proc delete_image {name} { ::anigif::destroy $name } } tkabber-plugins-0.11.1/aniemoticons/anigif.tcl0000644000175000017500000001316510675535176020657 0ustar sergeisergei# AniGif Package written in pure Tcl/Tk # # anigif.tcl v1.3 2002-09-09 (c) 2001-2002 Ryan Casey # # AniGif is distributed under the same license as Tcl/Tk. As of # AniGif 1.3, this license is applicable to all previous versions. # # Modified by Alexey Shchepin # # ############################### USAGE ################################# # # ::anigif::anigif IMAGE FILENAME INDEX # FILENAME: appropriate path and file to use for the animated gif # INDEX: what image to begin on (first image is 0) (Default: 0) # # ::anigif::stop IMAGE # ::anigif::restart IMAGE INDEX # INDEX: defaults to next index in loop # ::anigif::destroy IMAGE # # NOTES: # There is currently a -zoom and -subsample hack to keep transparency. # Anigif does not handle interlaced gifs properly. The image will look # distorted. # A delay of 0 renders as fast as possible, per the GIF specification. # This is currently set to 40 ms to approximate the IE default. # If you experience a problem with a compressed gif, try uncompressing # it. Search the web for gifsicle. # # ############################## HISTORY ################################# # # 1.3: Fixed error in disposal flag handling. # Added handling for non-valid comment/graphic blocks. # Searches for actual loop control block. If it extists, loops. # Added more comments. # 1.2: Now handles single playthrough gifs or gifs with partial images # Fixed bug in delay time (unsigned int was being treated as signed) # 1.1: Reads default timing instead of 100 ms or user-defined. # You can no longer set the delay manually. # 1.0: Moved all anigif variables to the anigif namespace # 0.9: Initial release # namespace eval ::anigif { variable image_number 0 } proc ::anigif::anigif2 {img list delay {idx 0}} { if {$idx >= [llength $list]} { set idx 0 if {$::anigif::img(repeat,$img) == 0} { # Non-repeating GIF ::anigif::stop $img return } } set disposal_idx $idx incr disposal_idx -1 if {$disposal_idx <= 0} { set disposal_idx 0 } if {$idx == 0} { set dispflag "010" } else { set dispflag [lindex $::anigif::img(disposal,$img) $disposal_idx] } switch -- "$dispflag" { "000" { # Do nothing } "100" { # Do not dispose } "010" { # Restore to background $::anigif::img(curimage,$img) blank } "110" { # Restore to previous - not supported # As recommended, since this is not supported, it is set to blank [set ::anigif::img(curimage,$img)] blank } default { puts "no match: $dispflag" } } $::anigif::img(curimage,$img) copy [lindex $list $idx] if {[lindex $delay $idx] == 0} { ::anigif::stop $img return } # # # update set ::anigif::img(asdf,$img) [list ::anigif::anigif2 $img $list] set ::anigif::img(loop,$img) \ [after [lindex $delay $idx] \ [list eval $::anigif::img(asdf,$img) [list $delay [expr {$idx + 1}]]]] set ::anigif::img(idx,$img) [incr idx] } proc ::anigif::anigif {img fnam {idx 0}} { variable image_number ::anigif::stop $img set n 0 set images {} set delay {} set disposal {} set reserved {} #set img anigifimage[incr image_number] #set img [image create photo] image create photo $img set fin [open $fnam r] fconfigure $fin -translation binary set data [read $fin [file size $fnam]] close $fin # Find Loop Record set start [string first "\x21\xFF\x0B" $data] if {$start < 0} { set repeat 0 } else { set repeat 1 } # Find Control Records set start [string first "\x21\xF9\x04" $data] while {![catch {image create photo xpic$n$img \ -file $fnam \ -format [list gif89 -index $n]}]} { set stop [expr $start + 7] set record [string range $data $start $stop] binary scan $record @4s thisdelay if {[info exists thisdelay]} { # Change to unsigned integer #set thisdelay [expr {$thisdelay & 0xFF}]; binary scan $record @3b5 disposalval set disposalval [string range $disposalval 2 end] lappend images pic$n$img image create photo pic$n$img pic$n$img copy xpic$n$img image delete xpic$n$img lappend disposal $disposalval # Convert hundreths to thousandths for after set thisdelay [expr {$thisdelay * 10}] # If 0, set to fastest (25 ms min to seem to match browser default) if {$thisdelay == 0} {set thisdelay 40} lappend delay $thisdelay unset thisdelay incr n } if {($start >= 0) && ($stop >= 0)} { set start [string first "\x21\xF9\x04" $data [expr {$stop + 1}]] } else { break } } set ::anigif::img(repeat,$img) $repeat set ::anigif::img(delay,$img) $delay set ::anigif::img(disposal,$img) $disposal set ::anigif::img(curimage,$img) $img $img blank $img copy pic0${img} #$img configure -image [set ::anigif::img(curimage,$img)] anigif2 $img $images $delay $idx return $img } proc ::anigif::stop {img} { catch { after cancel $::anigif::img(loop,$img) } } # TODO proc ::anigif::restart {img {idx -1}} { if {$idx == -1} { if {[lindex $::anigif::img(delay,$img) $idx] < 0} { set idx 0 } else { set idx $::anigif::img(idx,$img) } } catch { ::anigif::stop $img eval $::anigif::img(asdf,$img) [list $::anigif::img(delay,$img) $idx] } } proc ::anigif::destroy {img} { catch { ::anigif::stop $img foreach imagename [image names] { if {[regexp {^pic\d+(.*)} $imagename -> tail] && [string equal $tail $img]} { image delete $imagename } } image delete $img array unset ::anigif::img *,$img } } package provide anigif 2.0 tkabber-plugins-0.11.1/iconsets/0000755000175000017500000000000011076120366016032 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/psi/0000755000175000017500000000000011076120366016625 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/psi/tkabber/0000755000175000017500000000000011076120366020237 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/psi/tkabber/toolbar-show-offline.gif0000644000175000017500000000024410110221066024751 0ustar sergeisergeiGIF89asssYYY! ,ix0I pf b@xu*jA-]{. % ;tkabber-plugins-0.11.1/iconsets/psi/tkabber/toolbar-add-user.gif0000644000175000017500000000020310110221066024050 0ustar sergeisergeiGIF89aYEu!,HH0I0B8 cy*m\36쓶o Sc+h6e-'aH:=xI;tkabber-plugins-0.11.1/iconsets/psi/tkabber/toolbar-join-conference.gif0000644000175000017500000000060610110221066025417 0ustar sergeisergeiGIF89aU_U*?UUU?U_UUUߪU_Uԟԟ__UUU*?U?U_U_?UU?*! ?,pH,Ȥrl2" B Q(p*Dx PGP y{RRDu !K"#$%&^p''&H'(ObSNY(ਵA;tkabber-plugins-0.11.1/iconsets/psi/tkabber/toolbar-show-online.gif0000644000175000017500000000021010110221066024604 0ustar sergeisergeiGIF89a! ,MH0I@GxBbiiWlk {_r3ҏZTh#eFÈ:;tkabber-plugins-0.11.1/iconsets/psi/tkabber/toolbar-disco.gif0000644000175000017500000000023110110221066023446 0ustar sergeisergeiGIF89a!,^x0I #|!蜩9t .@ȷ2+fW; 8) sAL 'N@$pUޘ5ժv4V0~C;tkabber-plugins-0.11.1/iconsets/psi/roster/0000755000175000017500000000000011076120366020143 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/psi/roster/available-xa.gif0000644000175000017500000000017110110221066023142 0ustar sergeisergeiGIF89a޿! ,>H ^TԻސdL}0кM̶VϹ`B$ct4%FT9XB;tkabber-plugins-0.11.1/iconsets/psi/roster/available-dnd.gif0000644000175000017500000000020610110221066023276 0ustar sergeisergeiGIF89a޿! ,Kx ^TԻސdLA ~0!6Lm] Sddhi:f@ "踈8;tkabber-plugins-0.11.1/iconsets/psi/roster/available-away.gif0000644000175000017500000000020310110221066023467 0ustar sergeisergeiGIF89a޿h! ,Hx ^TԻސdL}0кa߶6[DYR+;F#$Yd"ћ%vI;tkabber-plugins-0.11.1/iconsets/psi/roster/group-opened.gif0000644000175000017500000000012710110221066023221 0ustar sergeisergeiGIF89a X! , H02@U B$0%P;tkabber-plugins-0.11.1/iconsets/psi/roster/available-chat.gif0000644000175000017500000000017510110221066023455 0ustar sergeisergeiGIF89a! ,BH ^TԻސdLh0 c9 7_Pn)9C* GVȹ$;tkabber-plugins-0.11.1/iconsets/psi/roster/available.gif0000644000175000017500000000017110110221066022534 0ustar sergeisergeiGIF89a! ,>H ^TԻސdL}0кM̶VϹ`B$ct4%FT9XB;tkabber-plugins-0.11.1/iconsets/psi/roster/stalker.gif0000644000175000017500000000016110110221066022260 0ustar sergeisergeiGIF89aZZZ:::uuuRRR! ,6x7ÐT{uB$ABx y ~3-`Ţ48];tkabber-plugins-0.11.1/iconsets/psi/roster/group-closed.gif0000644000175000017500000000013010110221066023212 0ustar sergeisergeiGIF89a Y! , H1|AXG0lK8rىwAWL$;tkabber-plugins-0.11.1/iconsets/psi/roster/unavailable.gif0000644000175000017500000000017110110221066023077 0ustar sergeisergeiGIF89asssYYY! ,>H ^TԻސdL}0кM̶VϹ`B$ct4%FT9XB;tkabber-plugins-0.11.1/iconsets/psi/icondef.xml0000644000175000017500000000507310500513112020745 0ustar sergeisergei Psi 1.0 Tkabber's Psi Iconset. 2006-01-21 toolbar/add-user tkabber/toolbar-add-user.gif toolbar/disco tkabber/toolbar-disco.gif toolbar/join-conference tkabber/toolbar-join-conference.gif toolbar/show-offline tkabber/toolbar-show-offline.gif toolbar/show-online tkabber/toolbar-show-online.gif browser/client roster/available.gif browser/user roster/available.gif roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/unavailable roster/unavailable.gif roster/user/unsubscribed roster/stalker.gif roster/user/error roster/unavailable.gif roster/group/closed roster/group-closed.gif roster/group/opened roster/group-opened.gif tkabber-plugins-0.11.1/iconsets/amibulb/0000755000175000017500000000000011076120366017445 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/amibulb/tkabber/0000755000175000017500000000000011076120366021057 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/amibulb/tkabber/toolbar-show-offline.gif0000644000175000017500000000024410110221066025571 0ustar sergeisergeiGIF89asssYYY! ,ix0I pf b@xu*jA-]{. % ;tkabber-plugins-0.11.1/iconsets/amibulb/tkabber/toolbar-add-user.gif0000644000175000017500000000020310110221066024670 0ustar sergeisergeiGIF89aYEu!,HH0I0B8 cy*m\36쓶o Sc+h6e-'aH:=xI;tkabber-plugins-0.11.1/iconsets/amibulb/tkabber/toolbar-join-conference.gif0000644000175000017500000000060610110221066026237 0ustar sergeisergeiGIF89aU_U*?UUU?U_UUUߪU_Uԟԟ__UUU*?U?U_U_?UU?*! ?,pH,Ȥrl2" B Q(p*Dx PGP y{RRDu !K"#$%&^p''&H'(ObSNY(ਵA;tkabber-plugins-0.11.1/iconsets/amibulb/tkabber/toolbar-show-online.gif0000644000175000017500000000021010110221066025424 0ustar sergeisergeiGIF89a! ,MH0I@GxBbiiWlk {_r3ҏZTh#eFÈ:;tkabber-plugins-0.11.1/iconsets/amibulb/tkabber/toolbar-disco.gif0000644000175000017500000000023110110221066024266 0ustar sergeisergeiGIF89a!,^x0I #|!蜩9t .@ȷ2+fW; 8) sAL 'N@$pUޘ5ժv4V0~C;tkabber-plugins-0.11.1/iconsets/amibulb/docking/0000755000175000017500000000000011076120366021063 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/amibulb/docking/tkabber.ico0000644000175000017500000005102610233301710023161 0ustar sergeisergeihhh hhVh&"h"h>( - N6 69hAhFGhL( (  &,?2F5L<$R3+YD-[<0\  #E0`:3a+:pG9iJ>n D~T?q1N]Hz>N(YOVgjvq}u ,&3?J};;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;; ;;;;;;;;&+%;;;;;;+-''(";;;;; //!*/)-';;;; ,////////- ;;;015861///.$;;;15:::7////# ;;;,7:::9////;;;;;5:::6//1/;;;;;;6852101;;;;;;;;0340/;;;;;;;;;; ;;;;;?( #./4A7fXU^e[ciBjfelsErsFeKhIw{FoX|rKjHxHzQpRqRzTtT~Yx\cpux¦ιҿ------------------------------ ----------- ---------- -------------- -----!!   ---- """""""!---##'*(#""" ---#&,,,)""" --- ),,,+""" -----',,,'""# ------'*'####--------#$%# ---------- -----?(  &,?2F5L<$R3+YD-[<0\  #E0`:3a+:pG9iJ>n* D~T?q1]Hz>NJ(Ygjv} ,&3?Jy8888888888888888888 8888888888888888888888 8888888888 88888888#&***"888888&**88888**%)$**8888 '********( 888-.253.***)!888.274*) 888'476*)8888827773*,,)888888352/.-.88888888-01-+8888888888 88888?(  &,?2FD-[ <0\  #+* D~1]Hz>(YOgj}u ,&3?J}(((((((((((((((((( (((((((( ((((((( ((((((  '''' ((((( '''' (((( (((( ((((((("%# ((( "'''$((($'''&((((("'''#((((((#%"(((((((( !((((((((((  (((((( JJJNTPEm_BjfEqsGyhKhIw{X|rKjHzRqR|TtS}\|dpu¦ҵؽ¾ιҿ....+-%+&.#-----"+,-. +-----'"----.--------,".---")*,+...-"-  ....- .... ... ! ... ((( ...((($..... ((( ...... !........  .......... .....( /.0546===DCEGFHLNPPRTX[\]bc`efekkhnnmsstzyz                ?( ?( *U*U*>*UUU?*?UU?U?UU?U_UUU?_UU_UU_U_UUU_UUUUUʦUU! -! #!+  #5!#  -!))5! ( .54 ,,,( #4).&((((245!(("!%3  0! 531%55!%1/#4$'-+&&45)+# -!-! 5*!5+!#55-+ -( U*U>**UU?UU?UU_U?U_UUU?U___U__UU         "" "" ##%"##%!& $ & ?Ç( @9N>UAZIe!Li#Pn%Vx(]*b.k.q3y1}<:;D=D;CJ>GRBIZY`                                  ( @'<AhUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPUUUUUUUUUUU3330UUUUUUUUUUPUUUUUUUUUPUUUUUUUUUP14DCUUUUUUUUUPD3D1UUUUUUUUUP3@41UUUUUUUUUP1@DUUUUUUUUUUUUUUUUUUUUUUUUUP333UUUUUU0UUUUUPCUUUUUPD!3AUUUUUPDD4@0D0UUUUUP2@D@!0AUUUUUP@D@3D0UUUUUUDD4@#$0UUUUUUP##1P2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU( @!)' 3:<2ADK3p);kF4oNAS5>e 0AoVu% %4& 4( 'sj;+CGKPS! 0O#"-/258AFFLORT5P157<>BEHM! .I#"+-/2489?C%$(*;@'&((),-0369( GGGIIIJJJKLKLLLMMMNNNOONOOOOOPPPPQQQQQRRRRRSRSSSTTTUUUVVVWWWXXXZYZZZZ\[\]\\]\]]]]^^__`_```bbbbbcedeeffghhihijjjkkkmmm  RUWZ\_bde MQTVX[^acI`EHKORUWZ]@YBE%$*,=A'&()+.0258;tkabber-plugins-0.11.1/iconsets/amibulb/roster/0000755000175000017500000000000011076120366020763 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/amibulb/roster/available-xa.gif0000644000175000017500000000110410110221066023757 0ustar sergeisergeiGIF89aAunJJJTI@]G35`G0bL6tZ>t\>u_?xeJwmKlBhrNdhPUWXZUZZVWZWWZZXZZZZNZVFLJзҽؾ! ,   '*( !& "*$#$(+..-) 5A,A49<@@A68=@A7?%12t b^0fcyTEi'iL;tkabber-plugins-0.11.1/iconsets/amibulb/roster/available-dnd.gif0000644000175000017500000000106110110221066024116 0ustar sergeisergeiGIF89aD$$$%%%(((d///000L>2S?-MNPDEJDEhhhT[ehhgiv|! ,8461!/@CA"%&3>B,#5C0)$2t\>u_?teNzjHtlNjEwmKupMrNPUWXZUZZVWZWWZZXZZZZZZZZзҷ˷ҽؾ! , %(&$("  "&!5K #' K4:K68ABHGK3.JKH<7EK@;,/=r+`Yȏ*Z0wE2& ;tkabber-plugins-0.11.1/iconsets/amibulb/roster/group-opened.gif0000644000175000017500000000012710110221066024041 0ustar sergeisergeiGIF89a X! , H02@U B$0%P;tkabber-plugins-0.11.1/iconsets/amibulb/roster/available-chat.gif0000644000175000017500000000106210110221066024271 0ustar sergeisergeiGIF89aE$$$%%%(((=(8,///000S0L>2S?-}DMNPDEJg[Dhhhk[ehgiv|! ,8461!/ADB"%&3?C,#5D0)$2<@9 +'.;B:*()7= +-#>>΃/  ܓ  ܽK@g&)D;tkabber-plugins-0.11.1/iconsets/amibulb/roster/invisible.gif0000644000175000017500000000073210110221066023423 0ustar sergeisergeiGIF89aU$$$%%%(((///000111L>2S?-\@&MNPDEFJT`abhhh[ehgi{{{zv|! ,7;tkabber-plugins-0.11.1/iconsets/amibulb/roster/available.gif0000644000175000017500000000106410110221066023356 0ustar sergeisergeiGIF89aU$$$%%%(((///000111L>2S?-\@&MNPDEFJT`abhhh[ehgi{{{zv|! ,$@<>9&6NSP'*+;KQ 2(=S7".):GMC%1,5EPD/-.?IR!13(BHOSAЅ64L FJ08 FP0  0O ;tkabber-plugins-0.11.1/iconsets/amibulb/roster/stalker.gif0000644000175000017500000000107110110221066023101 0ustar sergeisergeiGIF89aL<<??????<=>????????! ,  #7892,3@CA. ,/6CA 00;4$;?AC: *116>=5=@C")151=!65@+ߖ'&(&&%BIJGDEHc%< #aA ;tkabber-plugins-0.11.1/iconsets/amibulb/roster/group-closed.gif0000644000175000017500000000013010110221066024032 0ustar sergeisergeiGIF89a Y! , H1|AXG0lK8rىwAWL$;tkabber-plugins-0.11.1/iconsets/amibulb/roster/unavailable.gif0000644000175000017500000000052710110221066023724 0ustar sergeisergeiGIF89a$\Wg ih h lnu$$$%%%(((///000111L>2S?-MNP`abhhh{{{! ?,tPh(HiFϰdL, #\ WeoX Nq nkeC pznST~ GRRH!"C B#B ?A;tkabber-plugins-0.11.1/iconsets/amibulb/roster/icondef.xml0000644000175000017500000000213510372720523023114 0ustar sergeisergei Amirose Bulb 1.0 Amirose Jabber Bulb Iconset 2003-09-05 Tomasz Sterna (conversion) amirose (icons) status/online online.png status/offline offline.png status/away away.png status/xa xa.png status/dnd dnd.png status/invisible invisible.png status/chat ffc.png tkabber-plugins-0.11.1/iconsets/amibulb/icondef.xml0000644000175000017500000000554310500513112021567 0ustar sergeisergei Amibulb 1.0 Tkabber's Amibulb Iconset. 2006-01-21 toolbar/add-user tkabber/toolbar-add-user.gif toolbar/disco tkabber/toolbar-disco.gif toolbar/join-conference tkabber/toolbar-join-conference.gif toolbar/show-offline tkabber/toolbar-show-offline.gif toolbar/show-online tkabber/toolbar-show-online.gif browser/client roster/available.gif browser/user roster/available.gif docking/tkabber docking/tkabber.ico roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/invisible roster/invisible.gif roster/user/unavailable roster/unavailable.gif roster/user/unsubscribed roster/stalker.gif roster/user/error roster/unavailable.gif roster/group/closed roster/group-closed.gif roster/group/opened roster/group-opened.gif tkabber-plugins-0.11.1/iconsets/jarl/0000755000175000017500000000000011076120366016762 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/jarl/roster/0000755000175000017500000000000011076120366020300 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/jarl/roster/available-xa.gif0000644000175000017500000000035310110221066023301 0ustar sergeisergeiGIF89a333LLLfff! ,0RJ)R)R !L)J0Ƅ`J)1ƘH)!FXH)A)%! B)%8 )% )%D)$!$H)BBRJ)%RJ)RJ!RJ RJ)RJ0E;tkabber-plugins-0.11.1/iconsets/jarl/roster/available-dnd.gif0000644000175000017500000000035310110221066023436 0ustar sergeisergeiGIF89a333LLLfff!,!B!! ! D!P0 B!1ƘB!!hB! 1@bB! 1!B!!ЈR@!DR! C)! rH)!C)!ARAB!R@"B!!BE;tkabber-plugins-0.11.1/iconsets/jarl/roster/available-away.gif0000644000175000017500000000027710110221066023637 0ustar sergeisergeiGIF89a333LLL!,hfffffhfffhffffHDafffhADffhf3333hffUUUXUc6UU5fSPPUPchSPPXc6PX5fSUXUUcff8333cfhff fhfffhfffffhfff;tkabber-plugins-0.11.1/iconsets/jarl/roster/available-chat.gif0000644000175000017500000000027710110221066023615 0ustar sergeisergeiGIF89a333LLLfff!,XUUUUUXUUUXUUUUHDQUUUXADUUXUACCXUUACC8UU4HDUUUXACDUXUDDHPUUDDUUDDDPUX%@@@XUUD@HPUUHDPUUUXUU;tkabber-plugins-0.11.1/iconsets/jarl/roster/invisible.gif0000644000175000017500000000027710110221066022744 0ustar sergeisergeiGIF89a333LLLfff!,XUUUUUXUUUXUUUUXUQUUUXSU5UUXUQSSXUUSSS85UU5XUSUUUXSS5UUXUSSQXUUUSS8UUUUXSQUUUX%RUUXUU UXUUUXUUUUUXUUU;tkabber-plugins-0.11.1/iconsets/jarl/roster/available.gif0000644000175000017500000000027710110221066022700 0ustar sergeisergeiGIF89a333LLLfff!,XUUUUUXUUUXUUUUHDQUUUXADUUXUACCXUUACC8UU4HDCUUUXACUUXUCCQXUUUACUUUUHCQUUUX%RUUXUU UXUUUXUUUUUXUUU;tkabber-plugins-0.11.1/iconsets/jarl/roster/unavailable.gif0000644000175000017500000000027710110221066023243 0ustar sergeisergeiGIF89a333LLLfff!,XUUUUUXUUUXUUUUHDQUUUXADUUXUACCXUUACC8UU4HDCUUUXACUUXUCCQXUUUACUUUUHCQUUUX%RUUXUU UXUUUXUUUUUXUUU;tkabber-plugins-0.11.1/iconsets/jarl/icondef.xml0000644000175000017500000000245010366753724021127 0ustar sergeisergei Jarl 1.0 Tkabber's Jarl Iconset. 2006-01-21 roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/invisible roster/invisible.gif roster/user/unavailable roster/unavailable.gif roster/user/error roster/unavailable.gif tkabber-plugins-0.11.1/iconsets/jajc/0000755000175000017500000000000011076120366016741 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/jajc/services/0000755000175000017500000000000011076120366020564 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/jajc/services/msn_away.gif0000644000175000017500000000036610471326227023100 0ustar sergeisergeiGIF89a*UU**ԿԿ!,s %RG AQ XN ({L8^hNCX' 8<BBXZ$\ĨN6C!1'x%F02Y<1hp%HGcZG0Fce"!;tkabber-plugins-0.11.1/iconsets/jajc/services/msn_online.gif0000644000175000017500000000023210471326227023413 0ustar sergeisergeiGIF89aԿԿ! ,G0*WTqmhjGP-H H,Vp%;tkabber-plugins-0.11.1/iconsets/jajc/services/icq_offline.gif0000644000175000017500000000013210471326227023527 0ustar sergeisergeiGIF89a!,1ȸ[/k48J[e zGd*ŧu;9,DU+;tkabber-plugins-0.11.1/iconsets/jajc/services/jud.gif0000644000175000017500000000030010110221066022011 0ustar sergeisergeiGIF89a!,ܸqƍ7nܸqF1nܸq@nܸ @n8 @1n @1nDnD1nD1n8D7nܸD7nܸ"@7n87n܈q 7nܸqF7nܸqƍ7n;tkabber-plugins-0.11.1/iconsets/jajc/services/yahoo_dnd.gif0000644000175000017500000000024110471326227023216 0ustar sergeisergeiGIF89a ! ,NPIX`LV!gb&GbR:&u * 6fCMaY8Ғ&$Id *69;tkabber-plugins-0.11.1/iconsets/jajc/services/msn_chat.gif0000644000175000017500000000026210471326227023051 0ustar sergeisergeiGIF89a ԿԿ! ,_I&*!)XKlBęj00@ !8WX1(ve KB3ԊdF74,8l%sr;tkabber-plugins-0.11.1/iconsets/jajc/services/msn_xa.gif0000644000175000017500000000025510471326227022544 0ustar sergeisergeiGIF89a ԿԿ! ,Z)4װBZ%t2# Ypמ P3 Jfsv@J7*AGfJê.xru]ĺ"";tkabber-plugins-0.11.1/iconsets/jajc/services/yahoo_away.gif0000644000175000017500000000024710471326227023420 0ustar sergeisergeiGIF89a ! ,TIXPf["&K$WHj: @ F uA2X8;Q)!usʒf[! `\Ka>;tkabber-plugins-0.11.1/iconsets/jajc/services/aim_online.gif0000644000175000017500000000016510471326227023371 0ustar sergeisergeiGIF89a!,:h ^%5 F%'f˥N }К/@ r@+:EI;tkabber-plugins-0.11.1/iconsets/jajc/services/sms.gif0000644000175000017500000000033710471326227022062 0ustar sergeisergeiGIF89a***?*U*U*?U*_UU?UUU?UU_U_U_UԟԿUԿ!,\'c@D$+ "b dLf"q%Ӛ Qy'@eXT+se˦øp+_(!;tkabber-plugins-0.11.1/iconsets/jajc/services/aim_away.gif0000644000175000017500000000025010471326227023041 0ustar sergeisergeiGIF89a ! ,UPI`j@Cp% qv1vLo ҋc% 7硺L\MzBjM;tkabber-plugins-0.11.1/iconsets/jajc/services/yahoo_xa.gif0000644000175000017500000000024510471326227023065 0ustar sergeisergeiGIF89a ! ,RpIXpN^""J W/+.@,FI!PwŒ*tRU9$SŶ-)R* O;tkabber-plugins-0.11.1/iconsets/jajc/services/aim_chat.gif0000644000175000017500000000022410471326227023020 0ustar sergeisergeiGIF89aԿ! ,A0Ik`)@ hp[7%d9Vfv Ud ~?O3{ب-پJ;tkabber-plugins-0.11.1/iconsets/jajc/services/icq_away.gif0000644000175000017500000000017510501560571023051 0ustar sergeisergeiGIF89a!,BH@+ƻaAUV=*kZ&3*<= H[A)a EfI*.,;tkabber-plugins-0.11.1/iconsets/jajc/services/aim_xa.gif0000644000175000017500000000021310471326227022507 0ustar sergeisergeiGIF89a!,Pxzr E! 6PU8fMҼ pSD e"J08*S*/uB;tkabber-plugins-0.11.1/iconsets/jajc/services/msn_offline.gif0000644000175000017500000000023210471326227023551 0ustar sergeisergeiGIF89aԿԿ! ,G0*WTq(nѹY`@UH,V$$gF. !;tkabber-plugins-0.11.1/iconsets/jajc/services/icq_dnd.gif0000644000175000017500000000021610471326227022655 0ustar sergeisergeiGIF89a!,SX{5ZyAL (0ijy:1!m,N7Ӝ(4$ye.,jp+Uְ|HeE;tkabber-plugins-0.11.1/iconsets/jajc/services/icq_chat.gif0000644000175000017500000000021010471326227023021 0ustar sergeisergeiGIF89a!,MX"{5ZSWT4\6>` Kg{@nTjFՆtQyԄFb,W!";tkabber-plugins-0.11.1/iconsets/jajc/services/yahoo_offline.gif0000644000175000017500000000023310501560571024070 0ustar sergeisergeiGIF89a ԿԿ! ,HPIX0FVݑ Iw (W &;cBг &N)Q2Q!GL HVs1}hJ;tkabber-plugins-0.11.1/iconsets/jajc/services/aim_offline.gif0000644000175000017500000000023110471326227023521 0ustar sergeisergeiGIF89a ԿԿ! ,F09#nև YV@wP[{4bY "OD8p CP1N3u*FY(;tkabber-plugins-0.11.1/iconsets/jajc/services/yahoo_chat.gif0000644000175000017500000000034610471326227023376 0ustar sergeisergeiGIF89a*?UU?UU_U_UߪߪԿߪ!,c %diR01tKFmHnǛ368 TcH<'L\/r4qq`' Ei~H$y&slHzVy'F?$!;tkabber-plugins-0.11.1/iconsets/jajc/services/icq_online.gif0000644000175000017500000000017710471326227023402 0ustar sergeisergeiGIF89a!,DH{5ZyAL8J_b]9N7#DFjetStc;tkabber-plugins-0.11.1/iconsets/jajc/services/msn_dnd.gif0000644000175000017500000000025410501560571022674 0ustar sergeisergeiGIF89a ԿԿ!,Y)4K0VuN.AYM -r<@,TL[.wHWA'4Rt$JyIP傒%6{x;tkabber-plugins-0.11.1/iconsets/jajc/tkabber/0000755000175000017500000000000011076120366020353 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/jajc/tkabber/toolbar-show-offline.gif0000644000175000017500000000065410110221066025072 0ustar sergeisergeiGIF89aU_UU?UԿ*U*_U?*?UߪԟU?_UU?_*UUԟUU*U_?UUUUUUU*_UUU*__*?*! ?,pH,dr(ax"_)B8‡`pdZk \KAPjR  NJn OVu/Lj2X. j/ ( .J(eK./` -`C| *\pH;tkabber-plugins-0.11.1/iconsets/jajc/tkabber/toolbar-add-user.gif0000644000175000017500000000056510110221066024177 0ustar sergeisergeiGIF89a_U*?U*U*U?U?UU_UUԟU??__ԿUߪ*__?*?Կ*_?U_UU! ?,pH,Ȥrl:Y uP`H&[Q\0Mٸ7{MyyLr~KzJ O!! zN"!# $ N %M&'gT() bDA;tkabber-plugins-0.11.1/iconsets/jajc/tkabber/toolbar-join-conference.gif0000644000175000017500000000060610110221066025533 0ustar sergeisergeiGIF89aU_U*?UUU?U_UUUߪU_Uԟԟ__UUU*?U?U_U_?UU?*! ?,pH,Ȥrl2" B Q(p*Dx PGP y{RRDu !K"#$%&^p''&H'(ObSNY(ਵA;tkabber-plugins-0.11.1/iconsets/jajc/tkabber/toolbar-show-online.gif0000644000175000017500000000054410110221066024732 0ustar sergeisergeiGIF89aU?U*_U**?UUU?U_U_UߪԟU??_U_Կ_*?ԟ?_! ?,pH,Ȥrl:Y  0[aB!@,Œ Ʉ2tIh4v{>I{vcyIcccIccü&&&&&& &&&&&&&&& &&&&&&& &&&&&   &&&&&&   &&&&&&&& &&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&  # &&&&&&&&&" &&&&&&&&&& &&&&&&&&&&&$&&&&&&&&&&&!%&&&&&&&&&&&&&&&&&&&???( *U*U*?*UUU?*?UU?U?UU?U_UUU?_UU_UU_U_UUU_UUUUUʦUU! -! #!+  #7!#  -!))7! ( .76 ,,,( #6).&((((367!(("!%5  1! 752%77!%2/#6$'-0&&67)+# -!-! 4*!7+!#77-+ -( U*U?**UU?UUU?U?UU_U?U_UUU?U___U__UU      ! !!$$ $$"%%'$%%'#!( & ( ?Ç( @   $$$$(,L000(X(`<@ ##GSS8vdS--dGd8#vd?8x?( @4  $@(L(X4 $8l((((H((0 PP((((0x4444\000P88h88< @XP@@0DDDPXHHPPHPhlLLP(@PPTP(\\\h``\\`8DLh@hhhXhhLxXLttthxxP`\xx\h@lxxlĔxРhhLh@ppppppppppppppppppppppppppppppppppppppppppp)=ppppppppppppppppppppppppQaPH$pppppppppppppppppppp"Q9aaPHC4pppppppppppppppQa9aaSHCC:pppppppppppp*FZaAaaPCHHW!pppppppp1UM Za9aa[CHCR& ppppppppMF1MM ZaAaaPCHCW! ppppppppMB1UMQa;aaPHHC R! pppppppp MF1MM ZaAaaPHCA W!! ppppppppUF1UM Z_AaaP;CCR! pppppppp MF1MM Za_aa_P;9W! ppppppppUB1UM ZaaaaaSC;@ ppppppppMF1MM[aaaaaPHH3ppppppppMMFUM>aaaaaa[CHH N&pppppppp UMUMM#>_aaaaaPHHCN!ppppppp MUMUU>aaaaaa[CHC N! pppppp8MUMUM#>_aaaaaPHCHN! ppppppBUMUMU>_aaaaheCHC N!!ppppppBMMUUM#>__ahlngSHHN! ppppppBUMUMU>`elng`aa_K R!!ppppppBMUUMU'Gmn^7,=HKS>jE! ppppppBMUUdo0%cY%-$ -T\WL.ppppppBUdodMF* D]OD%I5+22?LppppppVoi1 (bjb]D pppppppV*/( 6kojbO????AY+4{6IeIe8@KO8;<Yq___LgggDThSxxxyyy{V|}~]Sdd\ffga`dadeefghii:x +-:*:3 6j: "^vOL)*|@avONN%>@`tONN(CGKPS! 0O#"-/258AFFLORT5P157<>BEHM! .I#"+-/2489?C%$(*;@'&((),-0369( GGGIIIJJJKLKLLLMMMNNNOONOOOOOPPPPQQQQQRRRRRSRSSSTTTUUUVVVWWWXXXZYZZZZ\[\]\\]\]]]]^^__`_```bbbbbcedeeffghhihijjjkkkmmm  RUWZ\_bde MQTVX[^acI`EHKORUWZ]@YBE%$*,=A'&()+.0258;tkabber-plugins-0.11.1/iconsets/jajc/docking/available-dnd.gif0000644000175000017500000000057010110221066023516 0ustar sergeisergeiGIF89aU_U*?Կ*UU?*?UUԟU???_UU?ԟUUU?U__U!Created with The GIMP,@pH,Ȥrl6 )($a`€DD$aRL2d4qSSM M!"#N$%&S ' #"hCA;tkabber-plugins-0.11.1/iconsets/jajc/docking/available-away.gif0000644000175000017500000000062310110221066023711 0ustar sergeisergeiGIF89aU_U*_U*UԿ*U?U?UUUUU*_ԿU_ԟ_**?U*?_??_U!Created with The GIMP,@pH,Ȥrl6`0DB8,Ƶ87#Ɂ>JbC.v xItj L M !"#$XC%&B%#'(#)* +N),L-./XP01FA;tkabber-plugins-0.11.1/iconsets/jajc/docking/available-chat.gif0000644000175000017500000000061110110221066023664 0ustar sergeisergeiGIF89aU_U*?U*U?_UUԟU?ԿU_*ԟ_?*?*?U?U*_U_U_*U!Created with The GIMP,@pH,Ȥrl6P(( kS@xՅxhx@"g<& {tjkK|XCB  !"#n N$#M"%%#X &'EA;tkabber-plugins-0.11.1/iconsets/jajc/docking/available.gif0000644000175000017500000000056610110221066022760 0ustar sergeisergeiGIF89aU?U*_U**?UUU?U_U_UߪԟU??_U_Կ_*?ԟ?_!Created with The GIMP,@pH,Ȥrl6 )18 ڡb1H0€HZƄRX aed xZ{~h h !Z fN" #M $% &Z hFA;tkabber-plugins-0.11.1/iconsets/jajc/docking/unavailable.gif0000644000175000017500000000040710110221066023315 0ustar sergeisergeiGIF89aU_UԿ*?U*_UU?UߪߪԿ*_U*?_ԟԟ*U!Created with The GIMP,s dihl@LǍ裄P C`  8BG<!bed @fLNw(D {vs1{- C|: j&!;tkabber-plugins-0.11.1/iconsets/jajc/roster/0000755000175000017500000000000011076120366020257 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/jajc/roster/available-xa.gif0000644000175000017500000000071110110221066023256 0ustar sergeisergeiGIF89a%***?*U*_UU??U?U_U_UU?_U__ԿUUUߪ!%,RT*@ ET*JRT*B$T*JRT*I@$T*JRT*IT*RT*}:(JRT*50H(JRT*12(JRT*}4f2)RT*>b!HRT*J D"H$JT*J̄D"H T*J̄D$Q*JEfB"H$Q*JEF3 HɡT*J%CDL&DT*JhL(GT ;tkabber-plugins-0.11.1/iconsets/jajc/roster/available-dnd.gif0000644000175000017500000000071110110221066023413 0ustar sergeisergeiGIF89a'**?*?UU??U?UU_U_U_U?_U??UԟԟUUUUԿ!',t:F t:Nt:HQt:Nt:E&t:Nt:Et:t:@c8Nt:-8Rs8Nt:6c8Nt:-8ϦB-t:"·BP*t:NBP(t:N d2L&Jt:N dL&q:N'ņRP( q:N'fSP(Jt:N'H(t:N< t ;tkabber-plugins-0.11.1/iconsets/jajc/roster/conference-available.gif0000644000175000017500000000071110110221066024755 0ustar sergeisergeiGIF89a**?UUU?U?UU_UUU**UU??U___U?UUU__U_UUԟԟߪ!*,@JT* PT* 2T* eT*  T@T* 2)@P*t"}T*T:!Sp*`DT* 2"'J|h*J\$cLJ\,GCP!CHX,R(C(\,CP(JRB*JRT*@"T*JRT*T*J ;tkabber-plugins-0.11.1/iconsets/jajc/roster/available-away.gif0000644000175000017500000000071110110221066023607 0ustar sergeisergeiGIF89a0**?*U*?U*_UUU??U?UU_U_U_U**_?__ԟԿUUUԿ!1,X,Vkx<t:2q0yt:Nt:}BOt:Nt:}>t:Nt:1 t:t:-F8Nt:)0's8Nt:12̆b8Nt:-0 r8Ot::M&C1Nt:NM&YNt:N e@Nt:NL t:N'KSt:N&Ss:NS t:N'<t ;tkabber-plugins-0.11.1/iconsets/jajc/roster/group-closed.gif0000644000175000017500000000027210110221066023335 0ustar sergeisergeiGIF89a!,L0a„ &L0a„ &L0a„ &L0a &L0a@ &L0a@ &L0a@&L0a@&L0a@&L0a@ &L0a@ &L0a &L0a„ &L0a„ &L0a„ &L0a„ &;tkabber-plugins-0.11.1/iconsets/jajc/roster/unavailable.gif0000644000175000017500000000051310110221066023213 0ustar sergeisergeiGIF89a**?*U*?U*_UU?UU_U_U_ԟԿԟԿߪߪ!,u]u1q]u]u]<C\uu]u-u]u]u!A^u]u)rq]u]udIh\u]u]JTc\u]u]GT= u]u]PUu]u]uC%u]u]u u]u]^-p4u]u]0ps]x]P p,u] JAJC 1.0 Tkabber's JAJC Iconset. 2006-01-20 toolbar/add-user tkabber/toolbar-add-user.gif toolbar/disco tkabber/toolbar-disco.gif toolbar/join-conference tkabber/toolbar-join-conference.gif toolbar/show-offline tkabber/toolbar-show-offline.gif toolbar/show-online tkabber/toolbar-show-online.gif browser/client roster/available.gif browser/user roster/available.gif browser/conference roster/conference-available.gif browser/directory services/jud.gif browser/jud services/jud.gif browser/sms services/sms.gif browser/aim services/aim_online.gif browser/icq services/icq_online.gif browser/msn services/msn_online.gif browser/yahoo services/yahoo_online.gif docking/chat docking/available-chat.gif docking/available docking/available.gif docking/away docking/available-away.gif docking/xa docking/available-xa.gif docking/dnd docking/available-dnd.gif docking/unavailable docking/unavailable.gif docking/tkabber docking/tkabber.ico roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/unavailable roster/unavailable.gif roster/user/error roster/unavailable.gif roster/conference/available roster/conference-available.gif roster/conference/unavailable roster/conference-unavailable.gif roster/group/closed roster/group-closed.gif roster/group/opened roster/group-opened.gif services/aim/away services/aim_away.gif services/aim/chat services/aim_chat.gif services/aim/dnd services/aim_dnd.gif services/aim/unavailable services/aim_offline.gif services/aim/available services/aim_online.gif services/aim/xa services/aim_xa.gif services/icq/away services/icq_away.gif services/icq/chat services/icq_chat.gif services/icq/dnd services/icq_dnd.gif services/icq/unavailable services/icq_offline.gif services/icq/available services/icq_online.gif services/icq/xa services/icq_xa.gif services/jud services/jud.gif services/msn/away services/msn_away.gif services/msn/chat services/msn_chat.gif services/msn/dnd services/msn_dnd.gif services/msn/unavailable services/msn_offline.gif services/msn/available services/msn_online.gif services/msn/xa services/msn_xa.gif services/sms services/sms.gif services/yahoo/away services/yahoo_away.gif services/yahoo/chat services/yahoo_chat.gif services/yahoo/dnd services/yahoo_dnd.gif services/yahoo/unavailable services/yahoo_offline.gif services/yahoo/available services/yahoo_online.gif services/yahoo/xa services/yahoo_xa.gif tkabber-plugins-0.11.1/iconsets/icq/0000755000175000017500000000000011076120366016606 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/icq/tkabber/0000755000175000017500000000000011076120366020220 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/icq/tkabber/toolbar-show-offline.gif0000644000175000017500000000030510110221066024730 0ustar sergeisergeiGIF89a#p! ,xPAI_MYaH j>\:wR@90Hr5*x@l`*b ag[ITC'4ze^v}{`eW{ZE>$xdO)vl$\m ?3z= ;tkabber-plugins-0.11.1/iconsets/icq/tkabber/toolbar-add-user.gif0000644000175000017500000000116610110221066024042 0ustar sergeisergeiGIF89aŌΒq§}ɶ윭~Ʋ盪ٙޘɒĐzr yޗz!*%iU$ѭ~xV#̽ꚑkuT&9 îҌg~z^O8o1gOyMwYON=x#XMCr6i%[%/bS HvIy! ,Ӏ  !"#$%&'()* +,-ʉ./0 123䪚456789:;<=>? ""E$%LpJ)ST,YhK/_3LG_01saФQ5lps E;tkabber-plugins-0.11.1/iconsets/icq/tkabber/toolbar-join-conference.gif0000644000175000017500000000117510110221066025402 0ustar sergeisergeiGIF89aŌΒq§}ɶ윭~Ʋ盪ٙޘɒĐzr yޗzѭ~̽ꚑkՔꝝuɑk! ,ڀ ʊДӗ݈ !"#$%&''()* +,-у\ > Ƌ1`-} >'cD*^7pGCrQH=Xd@DH$!;yIЈ>Zʴ)@;tkabber-plugins-0.11.1/iconsets/icq/tkabber/toolbar-show-online.gif0000644000175000017500000000031210110221066024570 0ustar sergeisergeiGIF89a! ,xPAI_MYaH jȁ ρ"@AhvoR4ʩ0VdoԹ, pJ5k _EFEX~`W}VNXp7 tS'yc23{7 ;tkabber-plugins-0.11.1/iconsets/icq/tkabber/toolbar-disco.gif0000644000175000017500000000104010110221066023426 0ustar sergeisergeiGIF89a Y՚CʔDIk.b*eIU>:G@cRy3iL!q.ÏDZAܢJÌ;Gȑ=`nP#י;p2](Z}1r.N9!?, pH,H#  PcP0Ʉ":\QD"$ PDAq8.ScH?? t~o GO ?q!CG  X?oG~"d?P  #$#\U`H ? IӨ+QB ~H8'nr@/iVQH 0P@d>p A (#B>b62 5" h'`J^T`$!RjF\Fb*۷p};tkabber-plugins-0.11.1/iconsets/icq/docking/0000755000175000017500000000000011076120366020224 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/icq/docking/available-xa.gif0000644000175000017500000000020110110221066023215 0ustar sergeisergeiGIF89a! ,FH {5ZyB hpTázvNZO ކ7tɞjmX>$$gF. !;tkabber-plugins-0.11.1/iconsets/icq/docking/available-dnd.gif0000644000175000017500000000021610110221066023360 0ustar sergeisergeiGIF89a! ,Sx {5ZyBL0(Aijy:q m,N7Ӝ(4$ye.,jp+Uְ|HeE;tkabber-plugins-0.11.1/iconsets/icq/docking/available-away.gif0000644000175000017500000000020410110221066023551 0ustar sergeisergeiGIF89a! ,Ix+F7f|GbkĬ; ﵔ뷃D`f@XD)iPǔUJEh[$;tkabber-plugins-0.11.1/iconsets/icq/docking/available-chat.gif0000644000175000017500000000017510110221066023536 0ustar sergeisergeiGIF89a! ,Bx 0B7O \U肐k3 88BGia*r&;tkabber-plugins-0.11.1/iconsets/icq/docking/invisible.gif0000644000175000017500000000017710110221066022667 0ustar sergeisergeiGIF89a! ,Dx{5ZyAL8J_b]9N7#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/icq/docking/available.gif0000644000175000017500000000017710110221066022623 0ustar sergeisergeiGIF89a! ,DH {5ZyBL8J_b]9N#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/icq/docking/unavailable.gif0000644000175000017500000000017710110221066023166 0ustar sergeisergeiGIF89a! ,DH {5ZyBL8J_b]9N#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/icq/roster/0000755000175000017500000000000011076120366020124 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/icq/roster/available-xa.gif0000644000175000017500000000020110110221066023115 0ustar sergeisergeiGIF89a! ,FH {5ZyB hpTázvNZO ކ7tɞjmX>$$gF. !;tkabber-plugins-0.11.1/iconsets/icq/roster/send.gif0000644000175000017500000000023010110221066021522 0ustar sergeisergeiGIF89a! ,EɉxrBY$ɕ@+@ZkZNʮn(v` H,-ΟTdP`gLG;tkabber-plugins-0.11.1/iconsets/icq/roster/available-dnd.gif0000644000175000017500000000021610110221066023260 0ustar sergeisergeiGIF89a! ,Sx {5ZyBL0(Aijy:q m,N7Ӝ(4$ye.,jp+Uְ|HeE;tkabber-plugins-0.11.1/iconsets/icq/roster/available-away.gif0000644000175000017500000000020410110221066023451 0ustar sergeisergeiGIF89a! ,Ix+F7f|GbkĬ; ﵔ뷃D`f@XD)iPǔUJEh[$;tkabber-plugins-0.11.1/iconsets/icq/roster/available-chat.gif0000644000175000017500000000017510110221066023436 0ustar sergeisergeiGIF89a! ,Bx 0B7O \U肐k3 88BGia*r&;tkabber-plugins-0.11.1/iconsets/icq/roster/invisible.gif0000644000175000017500000000017710110221066022567 0ustar sergeisergeiGIF89a! ,Dx{5ZyAL8J_b]9N7#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/icq/roster/available.gif0000644000175000017500000000017710110221066022523 0ustar sergeisergeiGIF89a! ,DH {5ZyBL8J_b]9N#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/icq/roster/stalker.gif0000644000175000017500000000017710110221066022250 0ustar sergeisergeiGIF89a#p%! ,DH {5ZyBL8J_b]9N#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/icq/roster/unavailable.gif0000644000175000017500000000017710110221066023066 0ustar sergeisergeiGIF89a! ,DH {5ZyBL8J_b]9N#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/icq/roster/message.gif0000644000175000017500000000023010110221066022215 0ustar sergeisergeiGIF89a! ,EɉxrBY$ɕ@+@ZkZNʮn(v` H,-ΟTdP`gLG;tkabber-plugins-0.11.1/iconsets/icq/icondef.xml0000644000175000017500000000610410563571241020742 0ustar sergeisergei ICQ 1.0 Tkabber's ICQ Iconset. 2006-01-20 toolbar/add-user tkabber/toolbar-add-user.gif toolbar/disco tkabber/toolbar-disco.gif toolbar/join-conference tkabber/toolbar-join-conference.gif toolbar/show-offline tkabber/toolbar-show-offline.gif toolbar/show-online tkabber/toolbar-show-online.gif docking/chat docking/available-chat.gif docking/available docking/available.gif docking/away docking/available-away.gif docking/xa docking/available-xa.gif docking/dnd docking/available-dnd.gif docking/invisible docking/invisible.gif docking/unavailable docking/unavailable.gif roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/invisible roster/invisible.gif roster/user/unavailable roster/unavailable.gif roster/user/unsubscribed roster/stalker.gif roster/user/error roster/unavailable.gif tkabber-plugins-0.11.1/iconsets/kroc/0000755000175000017500000000000011076120366016770 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/kroc/services/0000755000175000017500000000000011076120366020613 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/kroc/services/msn_away.gif0000644000175000017500000000036610471326227023127 0ustar sergeisergeiGIF89a*UU**ԿԿ!,s %RG AQ XN ({L8^hNCX' 8<BBXZ$\ĨN6C!1'x%F02Y<1hp%HGcZG0Fce"!;tkabber-plugins-0.11.1/iconsets/kroc/services/msn_online.gif0000644000175000017500000000023210471326227023442 0ustar sergeisergeiGIF89aԿԿ! ,G0*WTqmhjGP-H H,Vp%;tkabber-plugins-0.11.1/iconsets/kroc/services/icq_offline.gif0000644000175000017500000000013210471326227023556 0ustar sergeisergeiGIF89a!,1ȸ[/k48J[e zGd*ŧu;9,DU+;tkabber-plugins-0.11.1/iconsets/kroc/services/gg_xa.gif0000644000175000017500000000057210110221066022356 0ustar sergeisergeiGIF89a{fZRJB3)Rc{m{ffεέ!0,@pkȖ 946B'juEtD&%y}^xN,ҺX>% RUz(/!.K/ 00    BƱ 0 DCDA;tkabber-plugins-0.11.1/iconsets/kroc/services/jud.gif0000644000175000017500000000030010110221066022040 0ustar sergeisergeiGIF89a!,ܸqƍ7nܸqF1nܸq@nܸ @n8 @1n @1nDnD1nD1n8D7nܸD7nܸ"@7n87n܈q 7nܸqF7nܸqƍ7n;tkabber-plugins-0.11.1/iconsets/kroc/services/weather_away.gif0000644000175000017500000000016610110221066023750 0ustar sergeisergeiGIF89annn! ,;H aB ai癨yJBvÐ]ۨ;TH#(\24Dy$;tkabber-plugins-0.11.1/iconsets/kroc/services/yahoo_dnd.gif0000644000175000017500000000024110471326227023245 0ustar sergeisergeiGIF89a ! ,NPIX`LV!gb&GbR:&u * 6fCMaY8Ғ&$Id *69;tkabber-plugins-0.11.1/iconsets/kroc/services/msn_chat.gif0000644000175000017500000000026210471326227023100 0ustar sergeisergeiGIF89a ԿԿ! ,_I&*!)XKlBęj00@ !8WX1(ve KB3ԊdF74,8l%sr;tkabber-plugins-0.11.1/iconsets/kroc/services/weather_chat.gif0000644000175000017500000000022110110221066023716 0ustar sergeisergeiGIF89asJbHP2! ,Vx~ bNаUX 0M`b*!3U`ѽRR03ZAs@:*  , ⱘFbQ {~H;tkabber-plugins-0.11.1/iconsets/kroc/services/msn_xa.gif0000644000175000017500000000025510471326227022573 0ustar sergeisergeiGIF89a ԿԿ! ,Z)4װBZ%t2# Ypמ P3 Jfsv@J7*AGfJê.xru]ĺ"";tkabber-plugins-0.11.1/iconsets/kroc/services/yahoo_away.gif0000644000175000017500000000024710471326227023447 0ustar sergeisergeiGIF89a ! ,TIXPf["&K$WHj: @ F uA2X8;Q)!usʒf[! `\Ka>;tkabber-plugins-0.11.1/iconsets/kroc/services/gg_online.gif0000644000175000017500000000033610110221066023230 0ustar sergeisergeiGIF89aε{έ{!,[ &XEheٮKU%|V  . pHIJT  dETtA ,0PZc:x,,#!;tkabber-plugins-0.11.1/iconsets/kroc/services/aim_online.gif0000644000175000017500000000016510471326227023420 0ustar sergeisergeiGIF89a!,:h ^%5 F%'f˥N }К/@ r@+:EI;tkabber-plugins-0.11.1/iconsets/kroc/services/weather_offline.gif0000644000175000017500000000025010110221066024423 0ustar sergeisergeiGIF89abbb1UIsH=s%! ,UI!`%! [ EF9q۾B:Ӣ2„r4(&T+f{AD6R'š`_t;tkabber-plugins-0.11.1/iconsets/kroc/services/gg_offline.gif0000644000175000017500000000052410110221066023365 0ustar sergeisergeiGIF89a|y|rf^ &%+)33LJSQZW|y$!%,qpX946B'(t4": eK|!@`h2{R%!$ #z$ oB Z ZGJOPCdLA;tkabber-plugins-0.11.1/iconsets/kroc/services/weather_online.gif0000644000175000017500000000024610110221066024272 0ustar sergeisergeiGIF89asJbHP2! ,SI} ;¶Ye0v`0U2SWа{n?8%plJZ>U*kL|ȩ?";tkabber-plugins-0.11.1/iconsets/kroc/services/sms.gif0000644000175000017500000000033710471326227022111 0ustar sergeisergeiGIF89a***?*U*U*?U*_UU?UUU?UU_U_U_UԟԿUԿ!,\'c@D$+ "b dLf"q%Ӛ Qy'@eXT+se˦øp+_(!;tkabber-plugins-0.11.1/iconsets/kroc/services/aim_away.gif0000644000175000017500000000025010471326227023070 0ustar sergeisergeiGIF89a ! ,UPI`j@Cp% qv1vLo ҋc% 7硺L\MzBjM;tkabber-plugins-0.11.1/iconsets/kroc/services/yahoo_xa.gif0000644000175000017500000000024510471326227023114 0ustar sergeisergeiGIF89a ! ,RpIXpN^""J W/+.@,FI!PwŒ*tRU9$SŶ-)R* O;tkabber-plugins-0.11.1/iconsets/kroc/services/aim_chat.gif0000644000175000017500000000022410471326227023047 0ustar sergeisergeiGIF89aԿ! ,A0Ik`)@ hp[7%d9Vfv Ud ~?O3{ب-پJ;tkabber-plugins-0.11.1/iconsets/kroc/services/weather_xa.gif0000644000175000017500000000017010110221066023412 0ustar sergeisergeiGIF89annn! ,=x APuqؙbi^5| $bDN࢘,;tkabber-plugins-0.11.1/iconsets/kroc/services/icq_away.gif0000644000175000017500000000017510501560571023100 0ustar sergeisergeiGIF89a!,BH@+ƻaAUV=*kZ&3*<= H[A)a EfI*.,;tkabber-plugins-0.11.1/iconsets/kroc/services/aim_xa.gif0000644000175000017500000000021310471326227022536 0ustar sergeisergeiGIF89a!,Pxzr E! 6PU8fMҼ pSD e"J08*S*/uB;tkabber-plugins-0.11.1/iconsets/kroc/services/weather_dnd.gif0000644000175000017500000000016410110221066023552 0ustar sergeisergeiGIF89aJJJnnn! ,9x aB ]i癨 :g K0 ^;tkabber-plugins-0.11.1/iconsets/kroc/services/rss_chat.gif0000644000175000017500000000016710501560571023112 0ustar sergeisergeiGIF89a|Oqs"d!,% RUz(/!.K/ 00    BƱ 0 DCDA;tkabber-plugins-0.11.1/iconsets/kroc/services/aim_dnd.gif0000644000175000017500000000024110501560571022670 0ustar sergeisergeiGIF89a!,NI$@M'Qh}aQG릫' hE HC 3$d6H5o㬅E6 [;tkabber-plugins-0.11.1/iconsets/kroc/services/icq_xa.gif0000644000175000017500000000020110471326227022541 0ustar sergeisergeiGIF89a!,FH{5ZyAh:pTázvNZO ކ7tɞjmX>$$gF. !;tkabber-plugins-0.11.1/iconsets/kroc/services/icq_dnd.gif0000644000175000017500000000021610471326227022704 0ustar sergeisergeiGIF89a!,SX{5ZyAL (0ijy:1!m,N7Ӝ(4$ye.,jp+Uְ|HeE;tkabber-plugins-0.11.1/iconsets/kroc/services/rss_xa.gif0000644000175000017500000000016710501560571022603 0ustar sergeisergeiGIF89a߹Ӻyݱ!,` Kg{@nTjFՆtQyԄFb,W!";tkabber-plugins-0.11.1/iconsets/kroc/services/yahoo_offline.gif0000644000175000017500000000023310501560571024117 0ustar sergeisergeiGIF89a ԿԿ! ,HPIX0FVݑ Iw (W &;cBг &N)Q2Q!GL HVs1}hJ;tkabber-plugins-0.11.1/iconsets/kroc/services/aim_offline.gif0000644000175000017500000000023110471326227023550 0ustar sergeisergeiGIF89a ԿԿ! ,F09#nև YV@wP[{4bY "OD8p CP1N3u*FY(;tkabber-plugins-0.11.1/iconsets/kroc/services/rss_online.gif0000644000175000017500000000016710501560571023457 0ustar sergeisergeiGIF89a|Oqs"d!,% RUz(/!.K/ 00    BƱ 0 DCDA;tkabber-plugins-0.11.1/iconsets/kroc/services/rss_dnd.gif0000644000175000017500000000017510471326227022743 0ustar sergeisergeiGIF89a>߹Ӻyݱ!,Bx+0JȄ8z5sdqY*.tM".ڻ@!3p:_-DR;(;tkabber-plugins-0.11.1/iconsets/kroc/services/gg_chat.gif0000644000175000017500000000053410110221066022663 0ustar sergeisergeiGIF89aεέ{̵{{{! ,y@pHJ946B'H6  ʧ9RЖ^I;b5 ( nf ZPQ nySuEUUOOZZPJLLBxA;tkabber-plugins-0.11.1/iconsets/kroc/services/msn_dnd.gif0000644000175000017500000000025410501560571022723 0ustar sergeisergeiGIF89a ԿԿ!,Y)4K0VuN.AYM -r<@,TL[.wHWA'4Rt$JyIP傒%6{x;tkabber-plugins-0.11.1/iconsets/kroc/tkabber/0000755000175000017500000000000011076120366020402 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/kroc/tkabber/toolbar-show-offline.gif0000644000175000017500000000022410366753724025142 0ustar sergeisergeiGIF89a)%! ,Yx0I߸K:Ѝ(D( tܪѝp9$!@$F`a OT]6OnJ\M;tkabber-plugins-0.11.1/iconsets/kroc/tkabber/toolbar-add-user.gif0000644000175000017500000000020710366753724024247 0ustar sergeisergeiGIF89a)%*! ,Lx0Io#}qA H ˃opM6Vw.hQ21%[Zf7L.hI;tkabber-plugins-0.11.1/iconsets/kroc/tkabber/toolbar-join-conference.gif0000644000175000017500000000031610366753724025610 0ustar sergeisergeiGIF89a )%! ,{I8*WȍhiJJmРK( @!(("Pec6 Ьt Xlb+2͂xlDC۞ {l XsQxDn dnd000;tkabber-plugins-0.11.1/iconsets/kroc/tkabber/toolbar-show-online.gif0000644000175000017500000000016410366753724025007 0ustar sergeisergeiGIF89a)%*! ,9x0I8*]  eAjK\6L G `9$Ш;tkabber-plugins-0.11.1/iconsets/kroc/tkabber/gpg-signed.gif0000644000175000017500000000044010110221066023076 0ustar sergeisergeiGIF89a ===WYבYFIIIIJIHAыHHA>@DJJIDBF=CHIHIIIHEފG?GIIIIIIIII?ZGHIJMKJOPMIIJHJLOG;=:.|FQKKuFMdQRI;;@<0=?PJ|jHMR=EAADD73NQMQTMIBAIPRM?=CRN@lj[E?4A:J>=' Z<&vːc*!4v@رXC,/ʒI;tkabber-plugins-0.11.1/iconsets/kroc/roster/available-dnd.gif0000644000175000017500000000016510110221066023445 0ustar sergeisergeiGIF89afff!,:x=j=Z<&v c*!*4׶@رXC,/dʒI;tkabber-plugins-0.11.1/iconsets/kroc/roster/conference-available.gif0000644000175000017500000000071110110221066025004 0ustar sergeisergeiGIF89a**?UUU?U?UU_UUU**UU??U___U?UUU__U_UUԟԟߪ!*,@JT* PT* 2T* eT*  T@T* 2)@P*t"}T*T:!Sp*`DT* 2"'J|h*J\$cLJ\,GCP!CHX,R(C(\,CP(JRB*JRT*@"T*JRT*T*J ;tkabber-plugins-0.11.1/iconsets/kroc/roster/available-away.gif0000644000175000017500000000016510366753724023671 0ustar sergeisergeiGIF89afff)%!,:x=j=Z<&v c*!*4׶@رXC,/dʒI;tkabber-plugins-0.11.1/iconsets/kroc/roster/group-opened.gif0000644000175000017500000000027210110221066023365 0ustar sergeisergeiGIF89a!,L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L @&L0 @&L0!@&L0a@ &L0aB &L0a„ &L0a„ &L0a„ &L0a„ &;tkabber-plugins-0.11.1/iconsets/kroc/roster/unsubscribed.gif0000644000175000017500000000016610471326227023472 0ustar sergeisergeiGIF89afff!,;x=j=Z<&v c*!J4sp/^L$}2w(,'bb;tkabber-plugins-0.11.1/iconsets/kroc/roster/available-chat.gif0000644000175000017500000000016610366753724023650 0ustar sergeisergeiGIF89afff!,;x=j=Z<&v c*!*4׶@رXC,/0P d%;tkabber-plugins-0.11.1/iconsets/kroc/roster/invisible.gif0000644000175000017500000000016610366753724022777 0ustar sergeisergeiGIF89afff!,;x=j=Z<&v c*!J4sp/;|2wPJgȔ$;tkabber-plugins-0.11.1/iconsets/kroc/roster/available.gif0000644000175000017500000000016510366753724022732 0ustar sergeisergeiGIF89afff!,:x=j=Z<&v c*!*4׶@رXC,/dʒI;tkabber-plugins-0.11.1/iconsets/kroc/roster/stalker.gif0000644000175000017500000000051310110221066022424 0ustar sergeisergeiGIF89aK%R+\3c:h>!lA#rG'~R0pppY5a Kroc 1.0 Tkabber's Kroc Iconset. 2006-01-21 toolbar/add-user tkabber/toolbar-add-user.gif toolbar/disco tkabber/toolbar-disco.gif toolbar/join-conference tkabber/toolbar-join-conference.gif toolbar/show-offline tkabber/toolbar-show-offline.gif toolbar/show-online tkabber/toolbar-show-online.gif toolbar/gpg-signed tkabber/gpg-signed.gif toolbar/gpg-unsigned tkabber/gpg-unsigned.gif toolbar/gpg-encrypted tkabber/gpg-encrypted.gif toolbar/gpg-unencrypted tkabber/gpg-unencrypted.gif gpg/signed tkabber/gpg-signed.gif gpg/badsigned tkabber/gpg-badsigned.gif gpg/encrypted tkabber/gpg-encrypted.gif browser/client roster/available.gif browser/user roster/available.gif browser/conference roster/conference-available.gif browser/headline services/rss_online.gif browser/directory services/jud.gif browser/jud services/jud.gif browser/sms services/sms.gif browser/aim services/aim_online.gif browser/icq services/icq_online.gif browser/msn services/msn_online.gif browser/yahoo services/yahoo_online.gif browser/gadu-gadu services/gg_online.gif browser/x-weather services/weather_online.gif docking/chat docking/available-chat.gif docking/available docking/available.gif docking/away docking/available-away.gif docking/xa docking/available-xa.gif docking/dnd docking/available-dnd.gif docking/invisible docking/invisible.gif docking/unavailable docking/unavailable.gif roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/invisible roster/invisible.gif roster/user/unavailable roster/unavailable.gif roster/user/unsubscribed roster/unsubscribed.gif roster/user/error roster/unavailable.gif roster/conference/available roster/conference-available.gif roster/conference/unavailable roster/conference-unavailable.gif roster/group/closed roster/group-closed.gif roster/group/opened roster/group-opened.gif services/aim/away services/aim_away.gif services/aim/chat services/aim_chat.gif services/aim/dnd services/aim_dnd.gif services/aim/unavailable services/aim_offline.gif services/aim/available services/aim_online.gif services/aim/xa services/aim_xa.gif services/gadu-gadu/away services/gg_away.gif services/gadu-gadu/chat services/gg_chat.gif services/gadu-gadu/dnd services/gg_dnd.gif services/gadu-gadu/unavailable services/gg_offline.gif services/gadu-gadu/available services/gg_online.gif services/gadu-gadu/xa services/gg_xa.gif services/icq/away services/icq_away.gif services/icq/chat services/icq_chat.gif services/icq/dnd services/icq_dnd.gif services/icq/unavailable services/icq_offline.gif services/icq/available services/icq_online.gif services/icq/xa services/icq_xa.gif services/jud services/jud.gif services/msn/away services/msn_away.gif services/msn/chat services/msn_chat.gif services/msn/dnd services/msn_dnd.gif services/msn/unavailable services/msn_offline.gif services/msn/available services/msn_online.gif services/msn/xa services/msn_xa.gif services/rss/away services/rss_away.gif services/rss/chat services/rss_chat.gif services/rss/dnd services/rss_dnd.gif services/rss/unavailable services/rss_offline.gif services/rss/available services/rss_online.gif services/rss/xa services/rss_xa.gif services/sms services/sms.gif services/x-weather/away services/weather_away.gif services/x-weather/chat services/weather_chat.gif services/x-weather/dnd services/weather_dnd.gif services/x-weather/unavailable services/weather_offline.gif services/x-weather/available services/weather_online.gif services/x-weather/xa services/weather_xa.gif services/yahoo/away services/yahoo_away.gif services/yahoo/chat services/yahoo_chat.gif services/yahoo/dnd services/yahoo_dnd.gif services/yahoo/unavailable services/yahoo_offline.gif services/yahoo/available services/yahoo_online.gif services/yahoo/xa services/yahoo_xa.gif tkabber-plugins-0.11.1/iconsets/gabber/0000755000175000017500000000000011076120366017254 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gabber/services/0000755000175000017500000000000011076120366021077 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gabber/services/msn_away.gif0000644000175000017500000000024510501560571023403 0ustar sergeisergeiGIF89a9&Y(Pԑc$ x xP F JDKVODA;tkabber-plugins-0.11.1/iconsets/gabber/services/icq_offline.gif0000644000175000017500000000017710471326227024053 0ustar sergeisergeiGIF89ajLG!,DH{5ZyAL8J_b]9N7#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/gabber/services/jud.gif0000644000175000017500000000014210110221066022330 0ustar sergeisergeiGIF89aet!,3˜SRj#=]gvep.O P.AC>)@* ;tkabber-plugins-0.11.1/iconsets/gabber/services/yahoo_dnd.gif0000644000175000017500000000052410501560571023531 0ustar sergeisergeiGIF89a!^l))GGGD-!Ŗ&Ɨ'ș)ʛ*ѡ/ӣ1ק5ڪ8ޮ;AFGHMSW_aeintw{!!,qpH,H!0$CK &ifc<"@y2 J#<s>&Y(Pԑc$ x xP F JDKVODA;tkabber-plugins-0.11.1/iconsets/gabber/services/msn_chat.gif0000644000175000017500000000017010501560571023356 0ustar sergeisergeiGIF89a hxs&x!,=XѰ6ċ,Pj 67}M[$0Yٷ$B#D"Y1*V\3cZ;tkabber-plugins-0.11.1/iconsets/gabber/services/msn_xa.gif0000644000175000017500000000024510501560571023052 0ustar sergeisergeiGIF89a hxZ+0s&gOx!,R)4pu_fui1k`SDOT``0 ?xDzHdfD,H+iGWU5<p<NJ;tkabber-plugins-0.11.1/iconsets/gabber/services/yahoo_away.gif0000644000175000017500000000052410501560571023725 0ustar sergeisergeiGIF89a!^l))GGGD-!Ŗ&Ɨ'ș)ʛ*ѡ/ӣ1ק5ڪ8ޮ;AFGHMSW_aeintw{!!,qpH,H!0$CK &ifc<"@y2 J#<s>&Y(Pԑc$ x xP F JDKVODA;tkabber-plugins-0.11.1/iconsets/gabber/services/aim_online.gif0000644000175000017500000000062710501560571023703 0ustar sergeisergeiGIF89a* ()+'*))CBSXz.GcC+EK{Q @@@UUUgggnnnK Zh0-Knܓ8͠RUhĆ!*,@PUB@U BaI0>`U A\DSr@1Gt  #((t `  s`|tVt%"}%% Ѿpw Y  MD%'')CA;tkabber-plugins-0.11.1/iconsets/gabber/services/sms.gif0000644000175000017500000000033610501560571022370 0ustar sergeisergeiGIF89a***?.03*U*U*_UU?UUU?UU_EFEUQPdddpuwԟԿGů!,['@(+ "ҢA0 r*ʋ2XLkRgQ &b>0NQ'n+](!;tkabber-plugins-0.11.1/iconsets/gabber/services/aim_away.gif0000644000175000017500000000061110501560571023351 0ustar sergeisergeiGIF89a/ ?&1-22/%|O+l_+QQQfffppo|||.:J9eEto}̓k2KeʠGGf݃ӷ!/,uZmH4Q@S t(b(h4$`}FGCDTpK񈠞" !+ , &_ ,  %U %~' p X . *B )-CA;tkabber-plugins-0.11.1/iconsets/gabber/services/yahoo_xa.gif0000644000175000017500000000052410501560571023374 0ustar sergeisergeiGIF89a!^l))GGGD-!Ŗ&Ɨ'ș)ʛ*ѡ/ӣ1ק5ڪ8ޮ;AFGHMSW_aeintw{!!,qpH,H!0$CK &ifc<"@y2 J#<s>&Y(Pԑc$ x xP F JDKVODA;tkabber-plugins-0.11.1/iconsets/gabber/services/aim_chat.gif0000644000175000017500000000062710501560571023336 0ustar sergeisergeiGIF89a* ('$*&)(?BR=xc-_bB)EJyN @@@UUUgggnnn /-Knے7̜QTgý!*,@PUB@U BaI0>`U A\DSrՀ1Gt  #((t `  s`|tVt%"}%% Ѿpw Y  MD%'')CA;tkabber-plugins-0.11.1/iconsets/gabber/services/icq_away.gif0000644000175000017500000000020710471326227023364 0ustar sergeisergeiGIF89aĦ!,Lh@+F7fS|F#`td@<[ARb0Cv jJxHԅ끄I.bj;tkabber-plugins-0.11.1/iconsets/gabber/services/aim_xa.gif0000644000175000017500000000061210501560571023021 0ustar sergeisergeiGIF89a0 ?&1-22/%|0^'O+_Jl_+fffppo.:J9eEto}̓k2KeʠGGf݃ӷ!0,@r}ȅK5WEc â)b(t:'LGCUpL񈬞% "# $. # )_   (U (~*  p X ) -B ,/CA;tkabber-plugins-0.11.1/iconsets/gabber/services/rss_chat.gif0000644000175000017500000000033410471326227023376 0ustar sergeisergeiGIF89a!,Y $hb %zAn*q lk.X0|X*_K1h h},FKndҎ:aF^c|5wv}!;tkabber-plugins-0.11.1/iconsets/gabber/services/msn_offline.gif0000644000175000017500000000016610471326227024072 0ustar sergeisergeiGIF89aZ#(rrr!,;XҰ BxQjqe ȍ$8Y6[l0}{SL "gTL4@;tkabber-plugins-0.11.1/iconsets/gabber/services/aim_dnd.gif0000644000175000017500000000061210501560571023156 0ustar sergeisergeiGIF89a0 ?&1-22/%|O+[*!l_+fffppo.:J9eEto}̂<0I8k2w[KeʠGlGf݃ӷ!0,@r}HK5WEc â b(t:LG?hLာ% "# $.#)_  (U(~* p X -B,/CA;tkabber-plugins-0.11.1/iconsets/gabber/services/icq_xa.gif0000644000175000017500000000020610471326227023032 0ustar sergeisergeiGIF89aĦjL!,KX{5ZyAh:p4muڀ=_n9Iʔl:VXB3tMbCd0;tkabber-plugins-0.11.1/iconsets/gabber/services/icq_dnd.gif0000644000175000017500000000021610471326227023170 0ustar sergeisergeiGIF89af(-ĦjL!,SX"{5ZyBLU(0ijy:1!zm,N7Ӝ(4$ye.,jp+Uְ|HeE;tkabber-plugins-0.11.1/iconsets/gabber/services/rss_xa.gif0000644000175000017500000000024710501560571023066 0ustar sergeisergeiGIF89aA@AHGHPNPXVX`^`hjhqsqz}z!,T P0p^ Da\g#"\} ``fIy.oTʊ(6Ye>\Lnn;tkabber-plugins-0.11.1/iconsets/gabber/services/icq_chat.gif0000644000175000017500000000020710501560571023336 0ustar sergeisergeiGIF89aĦG!,LX"{5ZSWT4\6>` Kg{@n$ v 鲛& ĚY>iDk!E;tkabber-plugins-0.11.1/iconsets/gabber/services/yahoo_offline.gif0000644000175000017500000000052210501560571024404 0ustar sergeisergeiGIF89a"GGGGRTlcc}tr~ty~¿üž!",o@pH,Ha $EMFis@b` }4#<w@Ofb, 'g& x xPF JDKVODA;tkabber-plugins-0.11.1/iconsets/gabber/services/aim_offline.gif0000644000175000017500000000036010501560571024033 0ustar sergeisergeiGIF89a $$!%$"$$$$%'>;7999LLL]\X|!,m$Sd:J"R(H O  'Kb 8j1xH "! "_6`DБLAxo9 p?|o T"A"o+, e#F{I*#!;tkabber-plugins-0.11.1/iconsets/gabber/services/rss_online.gif0000644000175000017500000000033410471326227023743 0ustar sergeisergeiGIF89a!,Y $hb %zAn*q lk.X0|X*_K1h h},FKndҎ:aF^c|5wv}!;tkabber-plugins-0.11.1/iconsets/gabber/services/rss_offline.gif0000644000175000017500000000024710501560571024100 0ustar sergeisergeiGIF89aA@AHGHPNPXVX`^`hjhqsqz}z!,T P0p^ Da\g#"\} ``fIy.oTʊ(6Ye>\Lnn;tkabber-plugins-0.11.1/iconsets/gabber/services/yahoo_chat.gif0000644000175000017500000000052410501560571023703 0ustar sergeisergeiGIF89a!^l))GGGD-!Ŗ&Ɨ'ș)ʛ*ѡ/ӣ1ק5ڪ8ޮ;AFGHMSW_aeintw{!!,qpH,H!0$CK &ifc<"@y2 J#<s>&Y(Pԑc$ x xP F JDKVODA;tkabber-plugins-0.11.1/iconsets/gabber/services/icq_online.gif0000644000175000017500000000017710471326227023715 0ustar sergeisergeiGIF89aĦG!,DH{5ZyAL8J_b]9N7#͂DFjetW, Ԫ;tkabber-plugins-0.11.1/iconsets/gabber/services/rss_away.gif0000644000175000017500000000024710501560571023417 0ustar sergeisergeiGIF89aA@AHGHPNPXVX`^`hjhqsqz}z!,T P0p^ Da\g#"\} ``fIy.oTʊ(6Ye>\Lnn;tkabber-plugins-0.11.1/iconsets/gabber/services/rss_dnd.gif0000644000175000017500000000033410471326227023224 0ustar sergeisergeiGIF89a|jpv{Ĩ̮Ե俤ƩЯԵ׵!,Y $hb %zAn*q lk.X0|X*_K1h h},FKndҎ:aF^c|5wv}!;tkabber-plugins-0.11.1/iconsets/gabber/services/msn_dnd.gif0000644000175000017500000000023710501560571023210 0ustar sergeisergeiGIF89a hxZ+0s&gOx!,L)4pu_fui1k`SDOT```h: lBaI%]闫ecE;tkabber-plugins-0.11.1/iconsets/gabber/tkabber/0000755000175000017500000000000011076120366020666 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gabber/tkabber/toolbar-show-offline.gif0000644000175000017500000000062610110221066025404 0ustar sergeisergeiGIF89aiaFAtnWޮ;ק5{eMѡ/ʛ*wGӣ1Ŗ&ڪ8S!www^^^XXXș)H}}}oooRRRNNNƗ'_xxxdddGGGBBB___III???OOOiii;;;777```uuuQQQ! ?,pH,ȤRhI@@0w T,Idh^Aez{*iI-*YjS13_Zm ^~f ;tkabber-plugins-0.11.1/iconsets/gabber/tkabber/toolbar-show-online.gif0000644000175000017500000000052610110221066025245 0ustar sergeisergeiGIF89aiaFAtnWޮ;ק5{eMѡ/ʛ*wGӣ1Ŗ&HHH666ڪ8S!RRRș)H~~~Ɨ'_ͮyyy}}}zzzwww```QQQ???! ?,spH,Ȥrl:Ш@H`@F:xAD$080zSI5 $% { W?.pUTW3439:<3MA;tkabber-plugins-0.11.1/iconsets/gabber/tkabber/toolbar-disco.gif0000644000175000017500000000041410110221066024100 0ustar sergeisergeiGIF89aq5E+͑Ӊze-tt՗BV6ʉ֜PgAǀ}J``D$@XZ z00&s4Q?A9}68cF 1t  ;'3,!;tkabber-plugins-0.11.1/iconsets/gabber/docking/invisible.gif0000644000175000017500000000164710110221066023340 0ustar sergeisergeiGIF89a111999BBBJJJRRRZZZccckkksss{{{Ɣ!Μ)֥1BBJRZckkss{!,?H*\ȰA8 $:a4.CLCH! 0\@@@̓7TP?Jpa@ppXU ,@Ix HWʽ;tkabber-plugins-0.11.1/iconsets/gabber/docking/available.gif0000644000175000017500000000055210110221066023266 0ustar sergeisergeiGIF89aiaFAtnWޮ;ק5{eMѡ/ʛ*wGӣ1Ŗ&ڪ8S!ș)HƗ'_```QQQ???!Created with The GIMP! ?,npH,ȤrlPsZ0 풫X08 AD2Y#CNXG}  w SBlQP !"FA;tkabber-plugins-0.11.1/iconsets/gabber/docking/unavailable.gif0000644000175000017500000000040010110221066023621 0ustar sergeisergeiGIF89a|||www^^^XXX}}}oooRRRNNNxxxdddGGGBBB___III???OOOiii;;;777uuu```QQQ!Created with The GIMP! ,d'dihlk0@ օq ݊X00AD2YCJX't!p81,cHD qWUWLw.!;tkabber-plugins-0.11.1/iconsets/gabber/docking/message.gif0000644000175000017500000000026610110221066022774 0ustar sergeisergeiGIF89a! ,cI8@x0O8q$R_'am`,hscтa`nG6R4g%j(@K#jq+};tkabber-plugins-0.11.1/iconsets/gabber/roster/0000755000175000017500000000000011076120366020572 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gabber/roster/available-xa.gif0000644000175000017500000000037110110221066023573 0ustar sergeisergeiGIF89asjJ9y1m)aژnЊ1lbLR͈gHbT tWV[\  Y:/!;tkabber-plugins-0.11.1/iconsets/gabber/roster/conference-available.gif0000644000175000017500000000026010110221066025267 0ustar sergeisergeiGIF89aٴ<ɢ'hRhݹA! ,]!@Xշ  p5g:Ц0xBOaS OP>@e.R!Re/*PLO9k1JR WApJS};tkabber-plugins-0.11.1/iconsets/gabber/roster/available-away.gif0000644000175000017500000000050510110221066024123 0ustar sergeisergeiGIF89a#"zw'$qlصI(i d ({ia p}[ b yZ!uT```QQQ???! ,b@pH,A$H’,ĴXU,c;  P*o$SyH  p LeeJIHHGA;tkabber-plugins-0.11.1/iconsets/gabber/roster/group-opened.gif0000644000175000017500000000011410110221066023644 0ustar sergeisergeiGIF89a! ,y Aʶ.S;tkabber-plugins-0.11.1/iconsets/gabber/roster/available-chat.gif0000644000175000017500000000037010110221066024101 0ustar sergeisergeiGIF89aˤ)ʣ(ȡ&ϩ.ֱ7ٴ<ɢ'հ6ܸ@RΨ-ݹApZز9TV\Lh޺Bo! ,u'di~@ cQqJ։"X0|"@Ap4ALa@">`!lA#rG'~R0pppY5a>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~! ,@P @p.%aĊ3zbTnj$Ar H>R#(KOfdT.dDΞB!Qc҃ 7jp!AVES( V#Щ %J6-m;tkabber-plugins-0.11.1/iconsets/gabber/icondef.xml0000644000175000017500000002366310500620210021377 0ustar sergeisergei Gabber 1.0 Tkabber's Gabber Iconset. 2006-01-21 toolbar/add-user tkabber/toolbar-add-user.gif toolbar/disco tkabber/toolbar-disco.gif toolbar/join-conference tkabber/toolbar-join-conference.gif toolbar/show-offline tkabber/toolbar-show-offline.gif toolbar/show-online tkabber/toolbar-show-online.gif browser/client roster/available.gif browser/user roster/available.gif browser/conference roster/conference-available.gif browser/headline services/rss_online.gif browser/directory services/jud.gif browser/jud services/jud.gif browser/sms services/sms.gif browser/aim services/aim_online.gif browser/icq services/icq_online.gif browser/msn services/msn_online.gif browser/yahoo services/yahoo_online.gif docking/chat docking/available-chat.gif docking/available docking/available.gif docking/away docking/available-away.gif docking/xa docking/available-xa.gif docking/dnd docking/available-dnd.gif docking/invisible docking/invisible.gif docking/unavailable docking/unavailable.gif docking/message docking/message.gif docking/message-personal docking/message-personal.gif docking/message-server docking/message-server.gif docking/tkabber docking/tkabber.ico roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/invisible roster/invisible.gif roster/user/unavailable roster/unavailable.gif roster/user/unsubscribed roster/stalker.gif roster/user/error roster/unavailable.gif roster/conference/available roster/conference-available.gif roster/conference/unavailable roster/conference-unavailable.gif roster/group/closed roster/group-closed.gif roster/group/opened roster/group-opened.gif services/aim/away services/aim_away.gif services/aim/chat services/aim_chat.gif services/aim/dnd services/aim_dnd.gif services/aim/unavailable services/aim_offline.gif services/aim/available services/aim_online.gif services/aim/xa services/aim_xa.gif services/icq/away services/icq_away.gif services/icq/chat services/icq_chat.gif services/icq/dnd services/icq_dnd.gif services/icq/unavailable services/icq_offline.gif services/icq/available services/icq_online.gif services/icq/xa services/icq_xa.gif services/jud services/jud.gif services/msn/away services/msn_away.gif services/msn/chat services/msn_chat.gif services/msn/dnd services/msn_dnd.gif services/msn/unavailable services/msn_offline.gif services/msn/available services/msn_online.gif services/msn/xa services/msn_xa.gif services/rss/away services/rss_away.gif services/rss/chat services/rss_chat.gif services/rss/dnd services/rss_dnd.gif services/rss/unavailable services/rss_offline.gif services/rss/available services/rss_online.gif services/rss/xa services/rss_xa.gif services/sms services/sms.gif services/yahoo/away services/yahoo_away.gif services/yahoo/chat services/yahoo_chat.gif services/yahoo/dnd services/yahoo_dnd.gif services/yahoo/unavailable services/yahoo_offline.gif services/yahoo/available services/yahoo_online.gif services/yahoo/xa services/yahoo_xa.gif tkabber-plugins-0.11.1/iconsets/iconsets.tcl0000644000175000017500000000041610563066676020403 0ustar sergeisergei# $Id: iconsets.tcl 912 2007-02-09 12:49:02Z sergei $ # Several iconsets, borrowed from other Jabber clients. namespace eval iconsets { set ::pixmaps::theme_dirs \ [concat $::pixmaps::theme_dirs \ [glob -nocomplain -directory [file dirname [info script]] *]] } tkabber-plugins-0.11.1/iconsets/gush/0000755000175000017500000000000011076120366017000 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gush/tkabber/0000755000175000017500000000000011076120366020412 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gush/tkabber/toolbar-show-offline.gif0000644000175000017500000000070410110221066025125 0ustar sergeisergeiGIF89a8iaFAtnWޮ;ק5{eMѡ/ʛ*wGӣ1Ŗ&ڪ8S!www^^^XXXș)H}}}oooRRRNNNƗ'_xxxdddGGGBBB___III???OOOiii;;;777```uuuQQQ! ?,pH,Ȥ9eV%2C:i13R)YVΣNGV/?VZ,-Iyz])}-G %}- Fj&%- G- /4E''I1+, - J(1'-G1?-MGfzX(H 1@#DQ?CJ ;tkabber-plugins-0.11.1/iconsets/gush/tkabber/toolbar-add-user.gif0000644000175000017500000000020310110221066024223 0ustar sergeisergeiGIF89aYEu!,HH0I0B8 cy*m\36쓶o Sc+h6e-'aH:=xI;tkabber-plugins-0.11.1/iconsets/gush/tkabber/toolbar-join-conference.gif0000644000175000017500000000060610110221066025572 0ustar sergeisergeiGIF89aU_U*?UUU?U_UUUߪU_Uԟԟ__UUU*?U?U_U_?UU?*! ?,pH,Ȥrl2" B Q(p*Dx PGP y{RRDu !K"#$%&^p''&H'(ObSNY(ਵA;tkabber-plugins-0.11.1/iconsets/gush/tkabber/toolbar-show-online.gif0000644000175000017500000000055310110221066024771 0ustar sergeisergeiGIF89a8iaFAtnWޮ;ק5{eMѡ/ʛ*wGӣ1Ŗ&ڪ8S!www^^^XXXș)H}}}oooRRRNNNƗ'_xxxdddGGGBBB___III???OOOiii;;;777```uuuQQQ! ?,pH,Ȥrl:-V$6Æ@f6[z1hsψZWÜFXIW`uL,uQg -N-K-U?(,,B1' 1B41'0?A;tkabber-plugins-0.11.1/iconsets/gush/tkabber/toolbar-disco.gif0000644000175000017500000000023110110221066023621 0ustar sergeisergeiGIF89a!,^x0I #|!蜩9t .@ȷ2+fW; 8) sAL 'N@$pUޘ5ժv4V0~C;tkabber-plugins-0.11.1/iconsets/gush/docking/0000755000175000017500000000000011076120366020416 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gush/docking/tkabber.ico0000644000175000017500000005102610233301710022514 0ustar sergeisergeihhh hhVh&"h"h>( - N6 69hAhFGhL( (  &,?2F5L<$R3+YD-[<0\  #E0`:3a+:pG9iJ>n D~T?q1N]Hz>N(YOVgjvq}u ,&3?J};;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;; ;;;;;;;;&+%;;;;;;+-''(";;;;; //!*/)-';;;; ,////////- ;;;015861///.$;;;15:::7////# ;;;,7:::9////;;;;;5:::6//1/;;;;;;6852101;;;;;;;;0340/;;;;;;;;;; ;;;;;?( #./4A7fXU^e[ciBjfelsErsFeKhIw{FoX|rKjHxHzQpRqRzTtT~Yx\cpux¦ιҿ------------------------------ ----------- ---------- -------------- -----!!   ---- """""""!---##'*(#""" ---#&,,,)""" --- ),,,+""" -----',,,'""# ------'*'####--------#$%# ---------- -----?(  &,?2F5L<$R3+YD-[<0\  #E0`:3a+:pG9iJ>n* D~T?q1]Hz>NJ(Ygjv} ,&3?Jy8888888888888888888 8888888888888888888888 8888888888 88888888#&***"888888&**88888**%)$**8888 '********( 888-.253.***)!888.274*) 888'476*)8888827773*,,)888888352/.-.88888888-01-+8888888888 88888?(  &,?2FD-[ <0\  #+* D~1]Hz>(YOgj}u ,&3?J}(((((((((((((((((( (((((((( ((((((( ((((((  '''' ((((( '''' (((( (((( ((((((("%# ((( "'''$((($'''&((((("'''#((((((#%"(((((((( !((((((((((  (((((( JJJNTPEm_BjfEqsGyhKhIw{X|rKjHzRqR|TtS}\|dpu¦ҵؽ¾ιҿ....+-%+&.#-----"+,-. +-----'"----.--------,".---")*,+...-"-  ....- .... ... ! ... ((( ...((($..... ((( ...... !........  .......... .....( /.0546===DCEGFHLNPPRTX[\]bc`efekkhnnmsstzyz                ?( ?( *U*U*>*UUU?*?UU?U?UU?U_UUU?_UU_UU_U_UUU_UUUUUʦUU! -! #!+  #5!#  -!))5! ( .54 ,,,( #4).&((((245!(("!%3  0! 531%55!%1/#4$'-+&&45)+# -!-! 5*!5+!#55-+ -( U*U>**UU?UU?UU_U?U_UUU?U___U__UU         "" "" ##%"##%!& $ & ?Ç( @9N>UAZIe!Li#Pn%Vx(]*b.k.q3y1}<:;D=D;CJ>GRBIZY`                                  ( @'<AhUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPUUUUUUUUUUU3330UUUUUUUUUUPUUUUUUUUUPUUUUUUUUUP14DCUUUUUUUUUPD3D1UUUUUUUUUP3@41UUUUUUUUUP1@DUUUUUUUUUUUUUUUUUUUUUUUUUP333UUUUUU0UUUUUPCUUUUUPD!3AUUUUUPDD4@0D0UUUUUP2@D@!0AUUUUUP@D@3D0UUUUUUDD4@#$0UUUUUUP##1P2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU( @!)' 3:<2ADK3p);kF4oNAS5>e 0AoVu% %4& 4( 'sj;+CGKPS! 0O#"-/258AFFLORT5P157<>BEHM! .I#"+-/2489?C%$(*;@'&((),-0369( GGGIIIJJJKLKLLLMMMNNNOONOOOOOPPPPQQQQQRRRRRSRSSSTTTUUUVVVWWWXXXZYZZZZ\[\]\\]\]]]]^^__`_```bbbbbcedeeffghhihijjjkkkmmm  RUWZ\_bde MQTVX[^acI`EHKORUWZ]@YBE%$*,=A'&()+.0258;tkabber-plugins-0.11.1/iconsets/gush/roster/0000755000175000017500000000000011076120366020316 5ustar sergeisergeitkabber-plugins-0.11.1/iconsets/gush/roster/available-xa.gif0000644000175000017500000000113310110221066023314 0ustar sergeisergeiGIF89acJJJKKJKMJLMKNOJMPKNPLPTN_mEfjBnpDsqEhyGusEhK{wIt}Fr|XuHjKvHxHwJzH~IqR|RtT}S|\bdhlpppqruvwz{}’зҷ˷ҽؾҹΪҮҰӱԴֶغھ! ,  0340&@K>1..+=XWWB()*$"IWS(%.;H($ -,J*~D q?T1:NzH]>?JNJY(OVgjvwqs}uƂЎ֒  ,1-"&3?J}yp݆܌߂ޓߖ! , INOIFVZSMJJK!P^\]TBDG>9X][B?$JR]WB=- HLQYUJC. 8EC% *A@+" ӊ7<1޿07^^ S@j( @;tkabber-plugins-0.11.1/iconsets/gush/roster/available-away.gif0000644000175000017500000000110110110221066023640 0ustar sergeisergeiGIF89aZ#.A4/B62G<7MB;PGBXOJXSHZTL]SMV_?_ZOd[TXf>e^Uic[_mEfjBkd]npDslesrEusEeFhK{wIoFpFr|XjKvHxHzHwJ~IwKnNpQxLqRzRtT}S~TxWxY|\{\\\cbdhlmpppqrtuvwxz{}’ΪҮҰӱԴֶغھ! , HJKH=PUOIGGDNYXXQ@AC;9TXW@<!GLS@;( FEMVRG:*#9B?6&?>,5<4+7/382""10%.3')$-   0xP&4`p h8(;tkabber-plugins-0.11.1/iconsets/gush/roster/group-opened.gif0000644000175000017500000000012710110221066023374 0ustar sergeisergeiGIF89a X! , H02@U B$0%P;tkabber-plugins-0.11.1/iconsets/gush/roster/available-chat.gif0000644000175000017500000000110010110221066023615 0ustar sergeisergeiGIF89a_ &?,A.F2L5R$J*~D q?T1:NzH]>?JNJY(OVgjvwqs}uƂЎ֒  ,1-"&3?J}yp݆܌߂ޓߖ! , INOIFVZSMJJK!P^\]TBDG>9X][B?$JR]W=- HLQYUJBC. 8EBA:' *AB6?5B7  ,0/& %L(OQ $ (8(0E;tkabber-plugins-0.11.1/iconsets/gush/roster/invisible.gif0000644000175000017500000000011710110221066022753 0ustar sergeisergeiGIF89a! ,&P\@M^y_(Vbٙצ,~"ϯI Z;tkabber-plugins-0.11.1/iconsets/gush/roster/available.gif0000644000175000017500000000110210110221066022702 0ustar sergeisergeiGIF89a_ &?,A.F2L5R$J*~D q?T1:NzH]>?JNJY(OVgjvwqs}uƂЎ֒  ,1-"&3?J}yp݆܌߂ޓߖ! , INOIFVZSMJJK!P^\]TBDG>9X][B?$JR]WB=- HLQYUJC. 8EA:' *A@+6?5);37<1  24,07#("/& %Px0@E6\0pP;tkabber-plugins-0.11.1/iconsets/gush/roster/available2.gif0000644000175000017500000000110510110221066022767 0ustar sergeisergeiGIF89ah )))+++000644;;;DDDGF7JG:IG=IGGKKANL# BE;&$&=?6 J*~D q?T1:NzH]>?JNJY(OVgjvwqs}uƂЎ֒  ,1-"&3?J}yp݆܌߂ޓߖ! ,` !$  ' * % ڋ;tkabber-plugins-0.11.1/iconsets/gush/roster/group-closed.gif0000644000175000017500000000013010110221066023365 0ustar sergeisergeiGIF89a Y! , H1|AXG0lK8rىwAWL$;tkabber-plugins-0.11.1/iconsets/gush/roster/unavailable.gif0000644000175000017500000000107610110221066023257 0ustar sergeisergeiGIF89aQ0./1/0645:89===CCADCBECDFEDFFDHFGIHGJIHMKILLJNLMOMKOMMPNLRRRTRPUTQTTTUUQWVSXVTWWSYXUZYVZZVZZX\[X[[[_^Y__[cb]cc]ed_fe`ff`iickkennhooissmttnuvpxysyysyztz{u||v}}w}~x~~xyz{|}~! , ACDA6IMHB@@= GPOOJ9:<43LON95@EL94&?>FMK@4)3;80$87(/5.'1,.2---#+.!%* &( @ @;tkabber-plugins-0.11.1/iconsets/gush/icondef.xml0000644000175000017500000000553510500513112021123 0ustar sergeisergei Gush 1.0 Tkabber's Gush Iconset. 2006-01-21 toolbar/add-user tkabber/toolbar-add-user.gif toolbar/disco tkabber/toolbar-disco.gif toolbar/join-conference tkabber/toolbar-join-conference.gif toolbar/show-offline tkabber/toolbar-show-offline.gif toolbar/show-online tkabber/toolbar-show-online.gif browser/client roster/available.gif browser/user roster/available.gif docking/tkabber docking/tkabber.ico roster/user/chat roster/available-chat.gif roster/user/available roster/available.gif roster/user/away roster/available-away.gif roster/user/xa roster/available-xa.gif roster/user/dnd roster/available-dnd.gif roster/user/invisible roster/invisible.gif roster/user/unavailable roster/unavailable.gif roster/user/unsubscribed roster/stalker.gif roster/user/error roster/unavailable.gif roster/group/closed roster/group-closed.gif roster/group/opened roster/group-opened.gif tkabber-plugins-0.11.1/whiteboard/0000755000175000017500000000000011076120366016333 5ustar sergeisergeitkabber-plugins-0.11.1/whiteboard/msgs/0000755000175000017500000000000011076120366017304 5ustar sergeisergeitkabber-plugins-0.11.1/whiteboard/msgs/pl.msg0000644000175000017500000000227610667535014020443 0ustar sergeisergei# Polish messages file for whiteboard plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Whiteboard" "Tablica rysunkowa" ::msgcat::mcset pl "%s whiteboard" "Tablica: %s" ::msgcat::mcset pl "PolyLine" "Linia prosta" ::msgcat::mcset pl "FreeHand" "Linia odręczna" ::msgcat::mcset pl "Move" "Przesuń" ::msgcat::mcset pl "Text" "Tekst" ::msgcat::mcset pl "Text color" "Kolor tekstu" ::msgcat::mcset pl "Text font" "Czcionka tekstu" ::msgcat::mcset pl "Line width: " "Grubość linii: " ::msgcat::mcset pl "Line color" "Kolor linii" ::msgcat::mcset pl "Cancel" "Anuluj" ::msgcat::mcset pl "Clear" "Wyczyść" ::msgcat::mcset pl "OK" "OK" ::msgcat::mcset pl "Remove" "Usuń" ::msgcat::mcset pl "Circle" "Okrąg" ::msgcat::mcset pl "Fill" "Wypełnienie" ::msgcat::mcset pl "Fill color" "Kolor wypełnienia" ::msgcat::mcset pl "Polygon" "Wielokąt" ::msgcat::mcset pl "Save..." "Zapisz..." ::msgcat::mcset pl "%s created: %s" "%s utworzył: %s" ::msgcat::mcset pl "%s moved: %s" "%s przesunął: %s" ::msgcat::mcset pl "Enter text" "Wprowadź tekst" ::msgcat::mcset pl "Show balloons" "Pokaż dymki podpowiedzi"tkabber-plugins-0.11.1/whiteboard/msgs/es.msg0000644000175000017500000000175710564236742020444 0ustar sergeisergei::msgcat::mcset es "%s created: %s" "%s creado: %s" ::msgcat::mcset es "%s moved: %s" "%s movido: %s" ::msgcat::mcset es "%s whiteboard" "Pizarra: %s" ::msgcat::mcset es "Cancel" "Cancelar" ::msgcat::mcset es "Circle" "Círculo" ::msgcat::mcset es "Clear" "Limpiar" ::msgcat::mcset es "Enter text" "Introduce texto" ::msgcat::mcset es "Fill color" "Color de relleno" ::msgcat::mcset es "Fill" "Rellenar" ::msgcat::mcset es "FreeHand" "Mano alzada" ::msgcat::mcset es "Line color" "Color de línea" ::msgcat::mcset es "Line width: " "Ancho de línea: " ::msgcat::mcset es "Move" "Mover" ::msgcat::mcset es "OK" "Sí" ::msgcat::mcset es "PolyLine" "Polilínea" ::msgcat::mcset es "Polygon" "Polígono" ::msgcat::mcset es "Remove" "Borrar" ::msgcat::mcset es "Save..." "Guardar..." ::msgcat::mcset es "Show balloons" "Mostrar globos" ::msgcat::mcset es "Text color" "Color del texto" ::msgcat::mcset es "Text font" "Fuente del texto" ::msgcat::mcset es "Text" "Texto" ::msgcat::mcset es "Whiteboard" "Pizarra" tkabber-plugins-0.11.1/whiteboard/msgs/ro.msg0000644000175000017500000000051707626634725020456 0ustar sergeisergei::msgcat::mcset ro "Whiteboard" "Tablă" ::msgcat::mcset ro "%s whiteboard" "Table %s" ::msgcat::mcset ro "PolyLine" "Linie poligonală" ::msgcat::mcset ro "FreeHand" "Mână liberă" ::msgcat::mcset ro "Move" "Mută" #::msgcat::mcset ro "Remove" "Şterge" ::msgcat::mcset ro "Clear" "Şterge tot" ::msgcat::mcset ro "Color" "Culoare" tkabber-plugins-0.11.1/whiteboard/msgs/de.msg0000644000175000017500000000327111055051410020375 0ustar sergeisergei # German messages file # Roger Sondermann 26.08.2008 ::msgcat::mcset de "%s created: %s" "%s erstellt von %s" ::msgcat::mcset de "%s moved: %s" "%s verschoben von %s" ::msgcat::mcset de "%s transformed: %s" "%s transformiert: %s" ::msgcat::mcset de "%s whiteboard" "%s" ::msgcat::mcset de "Cancel" "Abbrechen" ::msgcat::mcset de "Circle" "Kreis" ::msgcat::mcset de "Clear" "Leeren" ::msgcat::mcset de "Enter text" "Text eingeben" ::msgcat::mcset de "Fill color" "Fll-Farbe" ::msgcat::mcset de "Fill" "Fllen" ::msgcat::mcset de "Flip horizontally" "Spiegeln horizontal" ::msgcat::mcset de "Flip vertically" "Spiegeln vertikal" ::msgcat::mcset de "FreeHand" "Frei-Hand" ::msgcat::mcset de "Line color" "Linien-Farbe" ::msgcat::mcset de "Line width: " "Linien-Breite" ::msgcat::mcset de "OK" "OK" ::msgcat::mcset de "PolyLine" "Linie" ::msgcat::mcset de "Polygon" "Polygon" ::msgcat::mcset de "Rectangle" "Rechteck" ::msgcat::mcset de "Remove" "Entfernen" ::msgcat::mcset de "Rotate 135\u00b0" "Drehen 135\u00b0" ::msgcat::mcset de "Rotate 180\u00b0" "Drehen 180\u00b0" ::msgcat::mcset de "Rotate 45\u00b0" "Drehen 45\u00b0" ::msgcat::mcset de "Rotate 90\u00b0" "Drehen 90\u00b0" ::msgcat::mcset de "Save..." "Speichern..." ::msgcat::mcset de "Show balloons" "Tooltips" ::msgcat::mcset de "Text color" "Text-Farbe" ::msgcat::mcset de "Text font" "Schriftart" ::msgcat::mcset de "Text" "Text" ::msgcat::mcset de "Move/Transform" "Bewegen" ::msgcat::mcset de "Whiteboard" "Whiteboard" tkabber-plugins-0.11.1/whiteboard/msgs/ru.msg0000644000175000017500000000362411054753075020454 0ustar sergeisergei# $Id: ru.msg 1490 2008-08-26 10:09:01Z sergei $ ::msgcat::mcset ru "Cancel" "Отменить" ::msgcat::mcset ru "Circle" "Окружность" ::msgcat::mcset ru "Clear" "Очистить" ::msgcat::mcset ru "Enter text" "Введите текст" ::msgcat::mcset ru "Fill color" "Цвет заливки" ::msgcat::mcset ru "Fill" "Заливать" ::msgcat::mcset ru "Flip horizontally" "Отразить горизонтально" ::msgcat::mcset ru "Flip vertically" "Отразить вертикально" ::msgcat::mcset ru "FreeHand" "Кривая" ::msgcat::mcset ru "Line color" "Цвет линии" ::msgcat::mcset ru "Line width: " "Ширина линии: " ::msgcat::mcset ru "Move/Transform" "Перемест./Трансформ." ::msgcat::mcset ru "OK" "Продолжить" ::msgcat::mcset ru "Polygon" "Многоугольник" ::msgcat::mcset ru "PolyLine" "Ломаная" ::msgcat::mcset ru "Rectangle" "Прямоугольник" ::msgcat::mcset ru "Remove" "Удалить" ::msgcat::mcset ru "Rotate 135\u00b0" "Повернуть на 135\u00b0" ::msgcat::mcset ru "Rotate 180\u00b0" "Повернуть на 180\u00b0" ::msgcat::mcset ru "Rotate 45\u00b0" "Повернуть на 45\u00b0" ::msgcat::mcset ru "Rotate 90\u00b0" "Повернуть на 90\u00b0" ::msgcat::mcset ru "Save..." "Сохранить..." ::msgcat::mcset ru "Show balloons" "Показывать подск." ::msgcat::mcset ru "%s created: %s" "%s создано: %s" ::msgcat::mcset ru "%s moved: %s" "%s перемещено: %s" ::msgcat::mcset ru "%s transformed: %s" "%s трансформировано: %s" ::msgcat::mcset ru "%s whiteboard" "%s доска" ::msgcat::mcset ru "Text color" "Цвет текста" ::msgcat::mcset ru "Text font" "Шрифт текста" ::msgcat::mcset ru "Text" "Текст" ::msgcat::mcset ru "Whiteboard" "Грифельная доска" # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/whiteboard/msgs/uk.msg0000644000175000017500000000144010512234573020432 0ustar sergeisergei# ukrainian messages file # writed by levsha@jabber.net.ua. Last chnage 3.10.2006 ::msgcat::mcset uk "Whiteboard" "Грифельна дошка" ::msgcat::mcset uk "%s whiteboard" "%s дошка" ::msgcat::mcset uk "PolyLine" "Ламана" ::msgcat::mcset uk "FreeHand" "Крива" ::msgcat::mcset uk "Move" "Перемістити" ::msgcat::mcset uk "Remove" "Видалити" ::msgcat::mcset uk "Clear" "Очистити" ::msgcat::mcset uk "Line color" "Колір лінії" ::msgcat::mcset uk "Text" "Текст" ::msgcat::mcset uk "Text color" "Колір тексту" ::msgcat::mcset uk "Text font" "Шрифт тексту" ::msgcat::mcset uk "Line width: " "Товщина лінії: " ::msgcat::mcset uk "OK" "Продовжити" ::msgcat::mcset uk "Cancel" "Відмінити" tkabber-plugins-0.11.1/whiteboard/msgs/nl.msg0000644000175000017500000000112010277726732020432 0ustar sergeisergei# Dutch messages file # Author: Sander Devrieze s.devrieze@pandora.be # Please notify me of errors or incoherencies. ::msgcat::mcset nl "Whiteboard" "Whiteboard" ::msgcat::mcset nl "%s whiteboard" "Whiteboard %s" ::msgcat::mcset nl "PolyLine" "Veelhoek" ::msgcat::mcset nl "FreeHand" "Potlood" ::msgcat::mcset nl "Move" "Verplaatsen" ::msgcat::mcset nl "Clear" "Wissen" ::msgcat::mcset nl "Color" "Kleur" ::msgcat::mcset nl "Text" "Tekst" ::msgcat::mcset nl "Text Color" "Tekstkleur" ::msgcat::mcset nl "Font" "Lettertype" ::msgcat::mcset nl "OK" "OK" ::msgcat::mcset nl "Cancel" "Annuleren"tkabber-plugins-0.11.1/whiteboard/whiteboard.tcl0000644000175000017500000010303611054755662021203 0ustar sergeisergei# $Id: whiteboard.tcl 1493 2008-08-26 10:32:18Z sergei $ uplevel #0 [list source [file join [file dirname [info script]] svgrender.tcl]] package require msgcat ::msgcat::mcload [file join [file dirname [info script]] msgs] namespace eval wb { set id_base [pid] ;# used in proc create_id } proc wb::add_whiteboard_menu_item {m connid jid} { $m add command -label [::msgcat::mc "Whiteboard"] \ -command [list [namespace current]::open_wb $connid $jid -raise 1] } hook::add chat_create_user_menu_hook \ [namespace current]::wb::add_whiteboard_menu_item 47 hook::add chat_create_conference_menu_hook \ [namespace current]::wb::add_whiteboard_menu_item 47 hook::add roster_jid_popup_menu_hook \ [namespace current]::wb::add_whiteboard_menu_item 47 proc wb::open_wb {connid jid args} { global dofill set raise 0 foreach {key val} $args { switch -- $key { -raise { set raise $val } } } set chatid [chat::chatid $connid $jid] set w [win_id whiteboard $chatid] if {[winfo exists $w]} { if {$raise} { raise_win $w } return } set jid [chat::get_jid $chatid] set title [format [::msgcat::mc "%s whiteboard"] $jid] add_win $w -title $title \ -tabtitle $title \ -class Whiteboard \ -raise $raise set sw [ScrolledWindow $w.sw] pack $sw -side right -fill both -expand yes set c [canvas $w.c -background white] $sw setwidget $c #pack $c -side right -fill both -expand yes bindscroll $c set tb [frame $w.tb] pack $tb -side left -fill y set tbfreehand [radiobutton $w.tb.freehand -text [::msgcat::mc "FreeHand"] \ -variable [namespace current]::tool($chatid) \ -value freehand \ -anchor w \ -command [list [namespace current]::freehand_bind \ $c $chatid]] set tbpolyline [radiobutton $w.tb.line -text [::msgcat::mc "PolyLine"] \ -variable [namespace current]::tool($chatid) \ -value polyline \ -anchor w \ -command [list [namespace current]::line_bind $c $chatid]] set tbrectangle [radiobutton $w.tb.rectangle -text [::msgcat::mc "Rectangle"] \ -variable [namespace current]::tool($chatid) \ -value rectangle \ -anchor w \ -command [list [namespace current]::rectangle_bind \ $c $chatid]] set tbpolygon [radiobutton $w.tb.polygon -text [::msgcat::mc "Polygon"] \ -variable [namespace current]::tool($chatid) \ -value polygon \ -anchor w \ -command [list [namespace current]::polygon_bind \ $c $chatid]] set tbcircle [radiobutton $w.tb.circle -text [::msgcat::mc "Circle"] \ -variable [namespace current]::tool($chatid) \ -value circle \ -anchor w \ -command [list [namespace current]::circle_bind \ $c $chatid]] set tbtext [radiobutton $w.tb.text -text [::msgcat::mc "Text"] \ -variable [namespace current]::tool($chatid) \ -value text \ -anchor w \ -command [list [namespace current]::text_bind \ $c $chatid]] set tbmove [radiobutton $w.tb.move -text [::msgcat::mc "Move/Transform"] \ -variable [namespace current]::tool($chatid) \ -value move \ -anchor w \ -command [list [namespace current]::move_bind \ $c $chatid]] pack $tbfreehand $tbpolyline $tbrectangle $tbpolygon $tbcircle $tbtext \ $tbmove -anchor w -fill x button $w.tb.clear -text [::msgcat::mc "Clear"] \ -command [list [namespace current]::send_clear $chatid] pack $w.tb.clear -side bottom -anchor w -fill x button $w.tb.save -text [::msgcat::mc "Save..."] \ -command [list [namespace current]::save_wb $chatid] pack $w.tb.save -side bottom -anchor w -fill x #frame $w.tb.spacer1 -relief sunken -bd 1 -height 2 -highlightthickness 0 #pack $w.tb.spacer1 -side bottom -anchor w -fill x -pady 1m set [namespace current]::text_set_fr($chatid) $w.tb label $w.tb.example_char -text A pack $w.tb.example_char -side bottom -fill x button $w.tb.seltextcol -text [::msgcat::mc "Text color"] \ -command [list [namespace current]::select_text_color \ $w.tb.seltextcol $w.tb.example_char] pack $w.tb.seltextcol -side bottom -anchor w -fill x button $w.tb.selfont -text [::msgcat::mc "Text font"] \ -command [list [namespace current]::select_font \ $w.tb.selfont $w.tb.example_char] pack $w.tb.selfont -side bottom -anchor w -fill x #frame $w.tb.spacer2 -relief sunken -bd 1 -height 2 -highlightthickness 0 #pack $w.tb.spacer2 -side bottom -anchor w -fill x -pady 1m frame $w.tb.fill checkbutton $w.tb.dofill -text [::msgcat::mc "Fill"] -variable dofill pack $w.tb.dofill -side left -in $w.tb.fill canvas $w.tb.fillcolor -background \#FFFFFF -height 5m -width 5m pack $w.tb.fillcolor -side left -padx 3m -in $w.tb.fill pack $w.tb.fill -side bottom -anchor w -fill x button $w.tb.selfillcol -text [::msgcat::mc "Fill color"] \ -command [list [namespace current]::select_color \ $w.tb.selfillcol $w.tb.fillcolor] pack $w.tb.selfillcol -side bottom -anchor w -fill x #frame $w.tb.spacer3 -relief sunken -bd 1 -height 2 -highlightthickness 0 #pack $w.tb.spacer3 -side bottom -anchor w -fill x -pady 1m canvas $w.tb.color -background \#000000 -height 0.5c -width 1 pack $w.tb.color -side bottom frame $w.tb.linewidth label $w.tb.lwidth -text [::msgcat::mc "Line width: "] pack $w.tb.lwidth -side left -in $w.tb.linewidth SpinBox $w.tb.width -width 4 -range {1 100} \ -textvariable [namespace current]::width($chatid) pack $w.tb.width -side left -in $w.tb.linewidth pack $w.tb.linewidth -side bottom -anchor w -fill x button $w.tb.selcol -text [::msgcat::mc "Line color"] \ -command [list [namespace current]::select_color \ $w.tb.selcol $w.tb.color] pack $w.tb.selcol -side bottom -anchor w -fill x variable balloon set balloon($chatid) 1 checkbutton $w.tb.balloon -text [::msgcat::mc "Show balloons"] \ -variable [namespace current]::balloon($chatid) pack $w.tb.balloon -side bottom -anchor w -fill x $c bind all \ [list [namespace current]::balloon $chatid $c enter %X %Y] $c bind all \ [list [namespace current]::balloon $chatid $c motion %X %Y] $c bind all \ [list [namespace current]::balloon $chatid $c leave %X %Y] trace variable [namespace current]::width($chatid) w \ [list [namespace current]::change_width \ $w.tb.color [namespace current]::width($chatid)] variable tool set tool($chatid) move move_bind $c $chatid } proc wb::balloon {chatid c action X Y} { variable balloon if {!$balloon($chatid)} return set id [$c find withtag current] set tags {} foreach t [$c gettags $id] { if {[lindex $t 0] == "time"} { lappend tags $t } } set msgs {} foreach t [lsort -index 1 -integer $tags] { lappend msgs [lindex $t 2] } balloon::default_balloon $c:$id $action $X $Y -text [join $msgs "\n"] } proc wb::select_color {but col} { set color [SelectColor::menu $col.color [list below $but] \ -color [$col cget -background]] if {[string length $color]} { $col configure -background $color } } proc wb::select_font {chatid col} { variable app_font set font_desc [SelectFont .s -type dialog] if {[string length $font_desc] == 0} return if {![info exists app_font($font_desc)]} { set app_font($font_desc) \ [eval font create [list $font_desc] [font actual $font_desc]] } $col configure -font $app_font($font_desc) } proc wb::select_text_color {but col} { set color [SelectColor::menu $col.color [list below $but] \ -color [$col cget -foreground]] if {[string length $color]} { $col configure -foreground $color } } proc wb::get_text_color {chatid} { [set [namespace current]::text_set_fr($chatid)].example_char cget -foreground } proc wb::get_text_font {chatid} { [set [namespace current]::text_set_fr($chatid)].example_char cget -font } proc wb::get_fill_color {chatid} { set w [win_id whiteboard $chatid] $w.tb.fillcolor cget -background } proc wb::get_color {chatid} { set w [win_id whiteboard $chatid] $w.tb.color cget -background } proc wb::change_width {col widthvar args} { set width [set $widthvar] $col configure -width $width } proc wb::get_width {chatid} { set w [win_id whiteboard $chatid] $w.tb.color cget -width } proc wb::save_wb {chatid} { set w [win_id whiteboard $chatid] set filepath [tk_getSaveFile -defaultextension .eps \ -filetypes {{{Encapsulated PostScript files} *.eps} {{All files} *}}] if {$filepath == ""} return $w.c postscript -file $filepath } ############################################################################### proc wb::create_id {} { # Unseeded random number is not good enough, because remote clients # are likely to produce the same numbers. return [rand 10000][clock seconds][set [namespace current]::id_base] } proc wb::send_svg {chatid tag} { if {[chat::is_groupchat $chatid]} { set type groupchat } else { set type chat } set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] jlib::send_msg $jid \ -connection $connid \ -type $type \ -xlist [list [jlib::wrapper:createtag x \ -vars {xmlns tkabber:whiteboard} \ -subtags [list [jlib::wrapper:createtag svg \ -subtags [list $tag]]]]] } proc wb::send_clear {chatid} { if {[chat::is_groupchat $chatid]} { set type groupchat } else { set type chat [win_id whiteboard $chatid].c delete all } set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] jlib::send_msg $jid -type $type \ -connection $connid \ -xlist [list [jlib::wrapper:createtag x \ -vars {xmlns tkabber:whiteboard} \ -subtags [list [jlib::wrapper:createtag clear]]]] } proc wb::handle_wb {chatid from type body x} { set seconds [jlib::x_delay $x] foreach xelem $x { jlib::wrapper:splitxml $xelem tag vars isempty chdata children if {[string equal [jlib::wrapper:getattr $vars xmlns] \ tkabber:whiteboard]} { open_wb [chat::get_connid $chatid] [chat::get_jid $chatid] set w [win_id whiteboard $chatid] foreach child $children { parse_item $chatid $from $seconds $child } tab_set_updated $w 1 message $w.c configure -scrollregion [$w.c bbox all] } } } hook::add draw_message_hook [namespace current]::wb::handle_wb 1 proc wb::parse_item {chatid from seconds item} { set w [win_id whiteboard $chatid] jlib::wrapper:splitxml $item tag vars isempty chdata children switch -- $tag { svg { foreach child $children { set id [svg::parseSVGItem $w.c {} {} $child] if {$id != ""} { $w.c addtag [list tag $child] withtag $id $w.c addtag [time_tag created $from $seconds] withtag $id } } } transform { set id [jlib::wrapper:getattr $vars id] set transform [jlib::wrapper:getattr $vars transform] set transform1 $transform set tags [$w.c gettags [list id $id]] set child {} foreach t $tags { if {[lindex $t 0] == "tag"} { set child [lindex $t 1] break } } foreach t $tags { if {[lindex $t 0] == "transform"} { set transform "$transform [lindex $t 1]" break } } if {$child != {}} { $w.c delete [list id $id] set id1 [svg::parseSVGItem $w.c [svg::ParseTransform $transform] {} $child] if {$id1 != ""} { foreach t $tags { $w.c addtag $t withtag $id1 } add_transform_tag $w.c $id $transform1 $w.c addtag [time_tag transformed $from $seconds] withtag $id1 } } } move { set id [jlib::wrapper:getattr $vars id] set dx [jlib::wrapper:getattr $vars dx] set dy [jlib::wrapper:getattr $vars dy] if {![string is double $dx] || $dx == ""} {set dx 0} if {![string is double $dy] || $dy == ""} {set dy 0} add_transform_tag $w.c $id translate($dx,$dy) $w.c addtag [time_tag moved $from $seconds] withtag [list id $id] $w.c move [list id $id] $dx $dy } remove { $w.c delete [list id [jlib::wrapper:getattr $vars id]] } clear { $w.c delete all } } } ############################################################################### proc wb::add_transform_tag {c id transform} { set tags [$c gettags [list id $id]] foreach t $tags { if {[lindex $t 0] == "transform"} { set transform "$transform [lindex $t 1]" $c dtag [list id $id] $t break } } $c addtag [list transform $transform] withtag [list id $id] } proc wb::time_tag {type jid {seconds ""}} { set seconds_now [clock seconds] set format $::plugins::options(timestamp_format) set seconds_day_before [clock scan "-23 hours 59 minutes" -base $seconds_now] if {$seconds == ""} { set seconds $seconds_now } if {$seconds <= $seconds_day_before} { set format $::plugins::options(delayed_timestamp_format) } set time [clock format $seconds -format $format] switch -- $type { created { return [list time $seconds [::msgcat::mc "%s created: %s" $time $jid]] } moved { return [list time $seconds [::msgcat::mc "%s moved: %s" $time $jid]] } transformed { return [list time $seconds [::msgcat::mc "%s transformed: %s" $time $jid]] } default { return "" } } } ############################################################################### proc wb::popup_menu {c chatid x y} { set m .whiteboard_popup_menu if {[winfo exists $m]} { destroy $m } set tags [$c gettags current] set id "" foreach t $tags { if {[lindex $t 0] == "id"} { set id [lindex $t 1] break } } menu $m -tearoff 0 if {![string equal $id ""]} { set state normal } else { set state disabled } $m add command -label [::msgcat::mc "Flip horizontally"] \ -command [list [namespace current]::flip_h $c $chatid $id] \ -state $state $m add command -label [::msgcat::mc "Flip vertically"] \ -command [list [namespace current]::flip_v $c $chatid $id] \ -state $state $m add command -label [::msgcat::mc "Rotate 45\u00b0"] \ -command [list [namespace current]::rotate $c $chatid $id -45] \ -state $state $m add command -label [::msgcat::mc "Rotate 90\u00b0"] \ -command [list [namespace current]::rotate $c $chatid $id -90] \ -state $state $m add command -label [::msgcat::mc "Rotate 135\u00b0"] \ -command [list [namespace current]::rotate $c $chatid $id -135] \ -state $state $m add command -label [::msgcat::mc "Rotate 180\u00b0"] \ -command [list [namespace current]::rotate $c $chatid $id -180] \ -state $state $m add separator $m add command -label [::msgcat::mc "Remove"] \ -command [list [namespace current]::remove_b1p $c $chatid $id] \ -state $state tk_popup $m $x $y } ############################################################################### proc wb::flip_h {c chatid id} { lassign [$c bbox [list id $id]] x1 y1 x2 y2 set x02 [expr {$x1+$x2}] transform $c $chatid $id "translate($x02,0) scale(-1,1)" } proc wb::flip_v {c chatid id} { lassign [$c bbox [list id $id]] x1 y1 x2 y2 set y02 [expr {$y1+$y2}] transform $c $chatid $id "translate(0,$y02) scale(1,-1)" } proc wb::rotate {c chatid id angle} { lassign [$c bbox [list id $id]] x1 y1 x2 y2 set x0 [expr {($x1+$x2)/2}] set y0 [expr {($y1+$y2)/2}] transform $c $chatid $id "rotate($angle,$x0,$y0)" } proc wb::transform {c chatid id transform} { if {[chat::is_groupchat $chatid]} { set type groupchat } else { set type chat set jid [jlib::connection_jid [chat::get_connid $chatid]] add_transform_tag $c $id $transform $c addtag [time_tag transformed $jid] withtag [list id $id] } set vars [list id $id transform $transform] set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] jlib::send_msg $jid \ -connection $connid \ -type $type \ -xlist [list [jlib::wrapper:createtag x \ -vars {xmlns tkabber:whiteboard} \ -subtags [list [jlib::wrapper:createtag transform \ -vars $vars]]]] } ############################################################################### ############################################################################### # Line proc wb::line_bind {c chatid} { bind $c \ [list [namespace current]::line_b1 [double% $c] [double% $chatid] %x %y] bind $c {} bind $c [list [namespace current]::line_b1m [double% $c] %x %y] bind $c {} bind $c [list [namespace current]::line_b3 \ [double% $c] [double% $chatid]] $c configure -cursor crosshair } proc wb::line_b1 {c chatid x y} { variable line set x [$c canvasx $x] set y [$c canvasy $y] if {[info exists line(drawed)]} { lappend line(coords) $x $y catch {$c delete $line(temp)} set tag [line_tag ""] set line(temp) [svg::parseSVGItem $c {} {} $tag] } else { set line(drawed) 1 set line(coords) [list $x $y] set line(options) [list stroke-linejoin miter stroke [get_color $chatid]] if {[set width [get_width $chatid]] != 1} { lappend line(options) stroke-width $width } } } proc wb::line_b1m {c x y} { variable line set x [$c canvasx $x] set y [$c canvasy $y] if {[info exists line(drawed)]} { set coords $line(coords) lappend line(coords) $x $y catch {$c delete $line(temp)} set tag [line_tag ""] set line(temp) [svg::parseSVGItem $c {} {} $tag] set line(coords) $coords } } proc wb::line_b3 {c chatid} { variable line catch { unset line(drawed) set id [create_id] catch {$c delete $line(temp)} set tag [line_tag $id] set line(temp) [svg::parseSVGItem $c {} {} $tag] if {[chat::is_groupchat $chatid]} { $c delete $line(temp) } else { set jid [jlib::connection_jid [chat::get_connid $chatid]] $c addtag [list tag $tag] withtag $line(temp) $c addtag [time_tag created $jid] withtag $line(temp) } send_svg $chatid $tag set line(coords) {} set line(temp) {} } } proc wb::line_tag {id} { variable line set vars $line(options) lappend vars points $line(coords) if {$id != ""} { lappend vars id $id } return [jlib::wrapper:createtag polyline -vars $vars] } ############################################################################### ############################################################################### # Polygon proc wb::polygon_bind {c chatid} { bind $c \ [list [namespace current]::polygon_b1 [double% $c] [double% $chatid] %x %y] bind $c {} bind $c [list [namespace current]::polygon_m [double% $c] %x %y] bind $c {} bind $c [list [namespace current]::polygon_b3 \ [double% $c] [double% $chatid]] $c configure -cursor crosshair } proc wb::polygon_b1 {c chatid x y} { variable polygon variable line1 variable line2 global dofill set x [$c canvasx $x] set y [$c canvasy $y] if {[info exists polygon(drawed)]} { lappend polygon(coords) $x $y catch {$c delete $line1(temp)} catch {$c delete $line2(temp)} catch {$c delete $polygon(temp)} set tag [polygon_tag ""] set polygon(temp) [svg::parseSVGItem $c {} {} $tag] } else { set polygon(drawed) 1 set polygon(coords) [list $x $y] set polygon(line_options) [list -fill [get_color $chatid] \ -width [get_width $chatid] \ -joinstyle miter] set polygon(options) [list stroke-linejoin miter stroke [get_color $chatid]] if {[set width [get_width $chatid]] != 1} { lappend polygon(options) stroke-width $width } if {$dofill == 1} { lappend polygon(options) fill [get_fill_color $chatid] } } } proc wb::polygon_m {c x y} { variable polygon variable line1 variable line2 set x [$c canvasx $x] set y [$c canvasy $y] if {[info exists polygon(drawed)]} { set x1 [lindex $polygon(coords) 0] set y1 [lindex $polygon(coords) 1] set xn [lindex $polygon(coords) end-1] set yn [lindex $polygon(coords) end] catch {$c delete $line1(temp)} catch {$c delete $line2(temp)} set line1(temp) [eval $c create line $x1 $y1 $x $y $polygon(line_options)] set line2(temp) [eval $c create line $xn $yn $x $y $polygon(line_options)] } } proc wb::polygon_b3 {c chatid} { variable polygon variable line1 variable line2 global dofill catch { unset polygon(drawed) set id [create_id] catch {$c delete $line1(temp)} catch {$c delete $line2(temp)} catch {$c delete $polygon(temp)} set tag [polygon_tag $id] if {[llength $polygon(coords)] > 4} { set polygon(temp) [svg::parseSVGItem $c {} {} $tag] if {[chat::is_groupchat $chatid]} { $c delete $polygon(temp) } else { set jid [jlib::connection_jid [chat::get_connid $chatid]] $c addtag [list tag $tag] withtag $polygon(temp) $c addtag [time_tag created $jid] withtag $polygon(temp) } send_svg $chatid $tag } set polygon(coords) {} set polygon(temp) {} } } proc wb::polygon_tag {id} { variable polygon set vars $polygon(options) lappend vars points $polygon(coords) if {$id != ""} { lappend vars id $id } return [jlib::wrapper:createtag polygon -vars $vars] } ############################################################################### ############################################################################### # Rectangle proc wb::rectangle_bind {c chatid} { bind $c \ [list [namespace current]::rectangle_b1 [double% $c] [double% $chatid] %x %y] bind $c \ [list [namespace current]::rectangle_b1m [double% $c] %x %y] bind $c {} bind $c \ [list [namespace current]::rectangle_b1r [double% $c] [double% $chatid] %x %y] bind $c {} $c configure -cursor crosshair } proc wb::rectangle_b1 {c chatid x y} { variable rectangle global dofill set x [$c canvasx $x] set y [$c canvasy $y] set rectangle(drawed) 1 set rectangle(x1) $x set rectangle(y1) $y set rectangle(options) [list stroke [get_color $chatid]] if {$dofill == 1} { lappend rectangle(options) fill [get_fill_color $chatid] } if {[set width [get_width $chatid]] != 1} { lappend rectangle(options) stroke-width $width } } proc wb::rectangle_b1r {c chatid x y} { variable rectangle if {[info exists rectangle(drawed)]} { unset rectangle(drawed) set rectangle(x2) [$c canvasx $x] set rectangle(y2) [$c canvasy $y] set id [create_id] set tag [rectangle_tag $id] catch {$c delete $rectangle(temp)} set rectangle(temp) [svg::parseSVGItem $c {} {} $tag] if {[chat::is_groupchat $chatid]} { $c delete $rectangle(temp) } else { set jid [jlib::connection_jid [chat::get_connid $chatid]] $c addtag [list tag $tag] withtag $rectangle(temp) $c addtag [time_tag created $jid] withtag $rectangle(temp) } send_svg $chatid $tag unset rectangle(x1) unset rectangle(x2) unset rectangle(y1) unset rectangle(y2) set rectangle(temp) {} } } proc wb::rectangle_b1m {c x y} { variable rectangle if {[info exists rectangle(drawed)]} { set rectangle(x2) [$c canvasx $x] set rectangle(y2) [$c canvasy $y] set tag [rectangle_tag ""] catch {$c delete $rectangle(temp)} set rectangle(temp) [svg::parseSVGItem $c {} {} $tag] } } proc wb::rectangle_tag {id} { variable rectangle set vars $rectangle(options) if {$rectangle(x2) > $rectangle(x1)} { lappend vars x $rectangle(x1) \ width [expr {$rectangle(x2) - $rectangle(x1)}] } else { lappend vars x $rectangle(x2) \ width [expr {$rectangle(x1) - $rectangle(x2)}] } if {$rectangle(y2) > $rectangle(y1)} { lappend vars y $rectangle(y1) \ height [expr {$rectangle(y2) - $rectangle(y1)}] } else { lappend vars y $rectangle(y2) \ height [expr {$rectangle(y1) - $rectangle(y2)}] } if {$id != ""} { lappend vars id $id } return [jlib::wrapper:createtag rect -vars $vars] } ############################################################################### ############################################################################### # Circle proc wb::circle_bind {c chatid} { bind $c \ [list [namespace current]::circle_b1 [double% $c] [double% $chatid] %x %y] bind $c \ [list [namespace current]::circle_b1m [double% $c] %x %y] bind $c {} bind $c \ [list [namespace current]::circle_b1r [double% $c] [double% $chatid] %x %y] bind $c {} $c configure -cursor crosshair } proc wb::circle_b1 {c chatid x y} { variable circle global dofill set cx [$c canvasx $x] set cy [$c canvasy $y] set circle(drawed) 1 set circle(cx) $cx set circle(cy) $cy set circle(options) [list cx $cx cy $cy stroke [get_color $chatid]] if {$dofill == 1} { lappend circle(options) fill [get_fill_color $chatid] } if {[set width [get_width $chatid]] != 1} { lappend circle(options) stroke-width $width } } proc wb::circle_b1r {c chatid x y} { variable circle if {[info exists circle(drawed)]} { unset circle(drawed) set cx $circle(cx) set cy $circle(cy) set x [$c canvasx $x] set y [$c canvasy $y] set r [expr {hypot($cx - $x, $cy - $y)}] set id [create_id] set tag [circle_tag $id $r] catch {$c delete $circle(temp)} set circle(temp) [svg::parseSVGItem $c {} {} $tag] if {[chat::is_groupchat $chatid]} { $c delete $circle(temp) } else { set jid [jlib::connection_jid [chat::get_connid $chatid]] $c addtag [list tag $tag] withtag $circle(temp) $c addtag [time_tag created $jid] withtag $circle(temp) } send_svg $chatid $tag unset circle(cx) unset circle(cy) set circle(temp) {} } } proc wb::circle_b1m {c x y} { variable circle if {[info exists circle(drawed)]} { set cx $circle(cx) set cy $circle(cy) set x [$c canvasx $x] set y [$c canvasy $y] set r [expr hypot($cx - $x, $cy - $y)] set tag [circle_tag "" $r] catch {$c delete $circle(temp)} set circle(temp) [svg::parseSVGItem $c {} {} $tag] } } proc wb::circle_tag {id r} { variable circle set vars $circle(options) lappend vars r $r if {$id != ""} { lappend vars id $id } return [jlib::wrapper:createtag circle -vars $vars] } ############################################################################### ############################################################################### # Freehand proc wb::freehand_bind {c chatid} { bind $c \ [list [namespace current]::freehand_b1p \ [double% $c] [double% $chatid] %x %y] bind $c [list [namespace current]::freehand_b1m \ [double% $c] %x %y] bind $c \ [list [namespace current]::freehand_b1r [double% $c] [double% $chatid]] bind $c {} $c configure -cursor crosshair } proc wb::freehand_b1p {c chatid x y} { variable line set x [$c canvasx $x] set y [$c canvasy $y] set line(drawed) 1 set line(coords) [list $x $y] set line(options) [list stroke-linejoin round stroke [get_color $chatid]] if {[set width [get_width $chatid]] != 1} { lappend line(options) stroke-width $width } } proc wb::freehand_b1m {c x y} { variable line set x [$c canvasx $x] set y [$c canvasy $y] if {[info exists line(drawed)]} { lappend line(coords) $x $y catch {$c delete $line(temp)} set tag [freehand_tag ""] set line(temp) [svg::parseSVGItem $c {} {} $tag] } } proc wb::freehand_b1r {c chatid} { variable line catch { unset line(drawed) set id [create_id] set tag [freehand_tag $id] catch {$c delete $line(temp)} set line(temp) [svg::parseSVGItem $c {} {} $tag] if {[chat::is_groupchat $chatid]} { $c delete $line(temp) } else { set jid [jlib::connection_jid [chat::get_connid $chatid]] $c addtag [list tag $tag] withtag $line(temp) $c addtag [time_tag created $jid] withtag $line(temp) } send_svg $chatid $tag set line(coords) {} set line(temp) {} } } proc wb::freehand_tag {id} { variable line set vars $line(options) lappend vars points $line(coords) if {$id != ""} { lappend vars id $id } return [jlib::wrapper:createtag polyline -vars $vars] } ############################################################################### ############################################################################### # Remove proc wb::remove_b1p {c chatid id} { set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] if {[chat::is_groupchat $chatid]} { set type groupchat } else { set type chat $c delete [list id $id] } if {$id != ""} { jlib::send_msg $jid \ -connection $connid \ -type $type \ -xlist [list [jlib::wrapper:createtag x \ -vars {xmlns tkabber:whiteboard} \ -subtags [list [jlib::wrapper:createtag remove \ -vars [list id $id]]]]] } } ############################################################################### ############################################################################### # Move proc wb::move_bind {c chatid} { bind $c \ [list [namespace current]::move_b1p [double% $c] [double% $chatid] %x %y] bind $c \ [list [namespace current]::move_b1m [double% $c] %x %y] bind $c \ [list [namespace current]::move_b1r [double% $c] [double% $chatid]] bind $c \ [list [namespace current]::popup_menu [double% $c] [double% $chatid] %X %Y] bind $c {} $c configure -cursor "" } proc wb::move_b1p {c chatid x y} { variable move set tags [$c gettags current] set id "" foreach t $tags { if {[lindex $t 0] == "id"} { set id [lindex $t 1] break } } if {$id != ""} { set x [$c canvasx $x] set y [$c canvasy $y] set move(startx) $x set move(starty) $y set move(lastx) $x set move(lasty) $y set move(id) $id $c configure -cursor hand2 } else { catch {unset move(id)} } } proc wb::move_b1m {c x y} { variable move if {[info exists move(id)]} { set id $move(id) set x [$c canvasx $x] set y [$c canvasy $y] $c move [list id $id] [expr {$x - $move(lastx)}] [expr {$y - $move(lasty)}] set move(lastx) $x set move(lasty) $y } } proc wb::move_b1r {c chatid} { variable move if {[info exists move(id)]} { set id $move(id) set x $move(lastx) set y $move(lasty) set dx [expr {$x - $move(startx)}] set dy [expr {$y - $move(starty)}] if {$dx == 0 && $dy == 0} { $c configure -cursor "" return } if {[chat::is_groupchat $chatid]} { set type groupchat $c move [list id $id] [expr {-$dx}] [expr {-$dy}] } else { set type chat set jid [jlib::connection_jid [chat::get_connid $chatid]] $c addtag [time_tag moved $jid] withtag [list id $id] } set vars [list id $id dx $dx dy $dy] set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] jlib::send_msg $jid \ -connection $connid \ -type $type \ -xlist [list [jlib::wrapper:createtag x \ -vars {xmlns tkabber:whiteboard} \ -subtags [list [jlib::wrapper:createtag move \ -vars $vars]]]] $c configure -cursor "" } } ############################################################################### # Text proc wb::text_bind {c chatid} { bind $c {} bind $c {} bind $c \ [list [namespace current]::text_b1 [double% $c] [double% $chatid] %x %y] bind $c {} $c configure -cursor crosshair } proc wb::text_b1 {c chatid x y} { variable text_info set text_info(x) [$c canvasx $x] set text_info(y) [$c canvasy $y] set w [win_id whiteboard $chatid] set wt $w.text_dialog if {[winfo exists $wt]} { wm deiconify $wt } else { Dialog $wt -anchor e \ -separator yes \ -title [::msgcat::mc "Enter text"] \ -side bottom \ -modal none \ -default 0 \ -cancel 1 $wt add -text [::msgcat::mc "OK"] \ -command [list [namespace current]::text_ok $wt $c $chatid] $wt add -text [::msgcat::mc "Cancel"] \ -command [list [namespace current]::text_cancel $wt $c $chatid] set en [entry $wt.text -width 80 \ -textvariable [namespace current]::text_entered($chatid)] pack $en -side top -in [$wt getframe] $wt draw $en } } proc wb::text_ok {wt c chatid} { variable app_font variable text_info set id [create_id] set text [set [namespace current]::text_entered($chatid)] set vars [list id $id x $text_info(x) y $text_info(y) \ fill [get_text_color $chatid]] set font [get_text_font $chatid] if {[info exists app_font($font)]} { array set font_opt [font configure $font] lappend vars font-size $font_opt(-size) \ font-family $font_opt(-family) if {$font_opt(-underline) || $font_opt(-overstrike)} { set dec {} if {$font_opt(-underline)} { lappend dec underline } if {$font_opt(-overstrike)} { lappend dec line-through } lappend vars text-decoration $dec } if {[string equal $font_opt(-slant) italic]} { lappend vars font-style italic } if {[string equal $font_opt(-weight) bold]} { lappend vars font-weight bold } unset font_opt } set tag [jlib::wrapper:createtag text -vars $vars -chdata $text] if {![chat::is_groupchat $chatid]} { set textid [svg::parseSVGItem $c {} {} $tag] set jid [jlib::connection_jid [chat::get_connid $chatid]] $c addtag [list tag $tag] withtag $textid $c addtag [time_tag created $jid] withtag $textid } send_svg $chatid $tag wm withdraw $wt } proc wb::text_cancel {wt c chatid} { wm withdraw $wt } ############################################################################### tkabber-plugins-0.11.1/whiteboard/ChangeLog0000644000175000017500000000257310436136540020114 0ustar sergeisergei2006-05-27 Alexey Shchepin * whiteboard.tcl: Updated interface, bugfix (thanks to Sergei Golovan) * msgs/ru.msg: Updated (thanks to Sergei Golovan) 2006-04-27 Alexey Shchepin * msgs/ru.msg: Updated (thanks to Sergei Golovan) 2006-01-20 Alexey Shchepin * whiteboard.tcl: Updated (thanks to Sergei Golovan) 2005-08-14 Alexey Shchepin * msgs/nl.msg: Updated (thanks to Sander Devrieze) 2004-07-17 Alexey Shchepin * msgs/nl.msg: Dutch translation (thanks to Sander Devrieze) 2004-03-22 Alexey Shchepin * svgrender.tcl: Extended the parsing of point-lists to match SVG spec, extended proc parse_text to use new proc text_opts (thanks to Jeff Silver) * whiteboard.tcl: Enhanced uniqueness of object ID, added "Text" tool with color and font configuration, bugfix in wb::send_clear, removed the code that put commas in x,y pairs in lists of points, changed line join style in freehand from 'miter' to 'round' (thanks to Jeff Silver) 2004-01-05 Alexey Shchepin * whiteboard.tcl (wb::add_roster_menu_item): Updated to latest tkabber cvs version 2003-09-01 Alexey Shchepin * whiteboard.tcl: Bugfixes 2003-05-29 Alexey Shchepin * whiteboard.tcl: Support for private whiteboard tkabber-plugins-0.11.1/whiteboard/svgrender.tcl0000644000175000017500000004103011034732754021040 0ustar sergeisergei# $Id: svgrender.tcl 1471 2008-07-08 18:46:04Z sergei $ namespace eval svg { # Smoothed lines and polygons are available in Tk starting from 8.5 if {[package vsatisfies [package provide Tk] 8.5]} { variable Smooth 1 } else { variable Smooth 0 } variable Debug 0 } proc svg::loadFile {c filename} { set f [open $filename] set file [read $f] close $f set parser [jlib::wrapper:new "#" "#" \ [list [namespace current]::parseSVG $c]] jlib::wrapper:elementstart $parser stream:stream {} {} jlib::wrapper:parser $parser parse $file jlib::wrapper:parser $parser configure -final 0 } proc svg::parseSVG {c xmldata} { Debug 2 $xmldata jlib::wrapper:splitxml $xmldata tag vars isempty chdata children if {$tag != "svg"} { return -code error "Not a SVG file" } parseSVGItem $c {} {} $xmldata } proc svg::parseSVGItem {c transform curAttrs item} { jlib::wrapper:splitxml $item tag vars isempty chdata children switch -- $tag { svg { ParseSVG $c $transform $curAttrs $item } rect { ParseRect $c $transform $curAttrs $item } line { ParseLine $c $transform $curAttrs $item } polyline { ParsePolyline $c $transform $curAttrs $item } polygon { ParsePolygon $c $transform $curAttrs $item } circle { ParseCircle $c $transform $curAttrs $item } ellipse { ParseEllipse $c $transform $curAttrs $item } text { ParseText $c $transform $curAttrs $item } g { ParseG $c $transform $curAttrs $vars $children } default { Debug 1 Unknown SVG tag '$tag' return "" } } } proc svg::ParseSVG {c transform curAttrs item} { jlib::wrapper:splitxml $item tag vars isempty chdata children # TODO foreach child $children { parseSVGItem $c $transform $curAttrs $child } return "" } proc svg::ParseG {c transform curAttrs vars items} { eval lappend transform \ [ParseTransform [jlib::wrapper:getattr $vars transform]] array set attrs $curAttrs array set attrs $vars set curAttrs [array get attrs] foreach item $items { parseSVGItem $c $transform $curAttrs $item } return "" } proc svg::ParsePolygon {c transform curAttrs item} { jlib::wrapper:splitxml $item tag vars isempty chdata children eval lappend transform \ [ParseTransform [jlib::wrapper:getattr $vars transform]] set p [TransformPoints $transform [jlib::wrapper:getattr $vars points]] array set attrs $curAttrs array set attrs $vars set styles [split [jlib::wrapper:getattr $vars style] \;] set drawitem line foreach s $styles { foreach {attr val} [split $s :] break set attr [string trim $attr] set val [string trim $val] switch -- $attr { "" {} fill - stroke - stroke-width - stroke-linejoin { set attrs($attr) $val } default { Debug 1 Unknown style attr '$attr' } } } if {[info exists attrs(fill)]} { set opts [PolygonOpts] set drawitem polygon } else { set opts [LineOpts] set drawitem line lappend p [lindex $p 0] [lindex $p 1] } Debug 2 $drawitem $p $opts eval [list $c create $drawitem] $p $opts } proc svg::ParseCircle {c transform curAttrs item} { variable Smooth variable Unitcircle jlib::wrapper:splitxml $item tag vars isempty chdata children eval lappend transform \ [ParseTransform [jlib::wrapper:getattr $vars transform]] array set attrs $curAttrs array set attrs {cx 0 cy 0 r 0} array set attrs $vars set styles [split [jlib::wrapper:getattr $vars style] \;] set drawitem circle foreach s $styles { foreach {attr val} [split $s :] break set attr [string trim $attr] set val [string trim $val] switch -- $attr { "" {} cx - cy - r - fill - stroke - stroke-width { set attrs($attr) $val } default { Debug 1 Unknown style attr '$attr' } } } set opts [CircleOpts] if {$Smooth} { set points {} for {set i 0} {$i < 30} {incr i} { set a [expr {3.1415926 * $i / 15}] lappend points [expr {$attrs(cx) + $attrs(r)*cos($a)}] \ [expr {$attrs(cy) + $attrs(r)*sin($a)}] } } else { set points {} for {set i 0} {$i < 180} {incr i} { set a [expr {3.1415926 * $i / 90}] lappend points [expr {$attrs(cx) + $attrs(r)*cos($a)}] \ [expr {$attrs(cy) + $attrs(r)*sin($a)}] } } set points [TransformPoints $transform $points] Debug 2 polygon $points $opts eval [list $c create polygon $points] $opts } proc svg::ParseEllipse {c transform curAttrs item} { variable Smooth variable Unitcircle jlib::wrapper:splitxml $item tag vars isempty chdata children eval lappend transform \ [ParseTransform [jlib::wrapper:getattr $vars transform]] array set attrs $curAttrs array set attrs {cx 0 cy 0 rx 0 ry 0} array set attrs $vars set styles [split [jlib::wrapper:getattr $vars style] \;] set drawitem circle foreach s $styles { foreach {attr val} [split $s :] break set attr [string trim $attr] set val [string trim $val] switch -- $attr { "" {} cx - cy - rx - ry - fill - stroke - stroke-width { set attrs($attr) $val } default { Debug 1 Unknown style attr '$attr' } } } set opts [CircleOpts] if {$Smooth} { set points {} for {set i 0} {$i < 30} {incr i} { set a [expr {3.1415926 * $i / 15}] lappend points [expr {$attrs(cx) + $attrs(rx)*cos($a)}] \ [expr {$attrs(cy) + $attrs(ry)*sin($a)}] } } else { set points {} for {set i 0} {$i < 180} {incr i} { set a [expr {3.1415926 * $i / 90}] lappend points [expr {$attrs(cx) + $attrs(rx)*cos($a)}] \ [expr {$attrs(cy) + $attrs(ry)*sin($a)}] } } set points [TransformPoints $transform $points] Debug 2 polygon $points $opts eval [list $c create polygon $points] $opts } proc svg::ParseLine {c transform curAttrs item} { jlib::wrapper:splitxml $item tag vars isempty chdata children eval lappend transform \ [ParseTransform [jlib::wrapper:getattr $vars transform]] set x1 [jlib::wrapper:getattr $vars x1] set y1 [jlib::wrapper:getattr $vars y1] set x2 [jlib::wrapper:getattr $vars x2] set y2 [jlib::wrapper:getattr $vars y2] foreach {x1 y1} [TransformCoord $transform $x1 $y1] break foreach {x2 y2} [TransformCoord $transform $x2 $y2] break array set attrs $curAttrs array set attrs $vars set styles [split [jlib::wrapper:getattr $vars style] \;] set drawitem line foreach s $styles { foreach {attr val} [split $s :] break set attr [string trim $attr] set val [string trim $val] switch -- $attr { "" {} stroke - stroke-width - stroke-linecap - stroke-linejoin { set attrs($attr) $val } default { Debug 1 Unknown style attr '$attr' } } } set opts [LineOpts] Debug 2 line $x1 $y1 $x2 $y2 $opts eval [list $c create line $x1 $y1 $x2 $y2] $opts } proc svg::ParseRect {c transform curAttrs item} { jlib::wrapper:splitxml $item tag vars isempty chdata children eval lappend transform \ [ParseTransform [jlib::wrapper:getattr $vars transform]] set x [jlib::wrapper:getattr $vars x] set y [jlib::wrapper:getattr $vars y] set width [jlib::wrapper:getattr $vars width] set height [jlib::wrapper:getattr $vars height] set rx [jlib::wrapper:getattr $vars rx] set ry [jlib::wrapper:getattr $vars ry] if {$rx != ""} { Debug 1 Round corners are ignored } set x2 [expr {$x + $width}] set y2 [expr {$y + $height}] foreach {xx yy} [TransformCoord $transform $x $y] break foreach {xx1 yy1} [TransformCoord $transform $x2 $y] break foreach {xx2 yy2} [TransformCoord $transform $x2 $y2] break foreach {xx3 yy3} [TransformCoord $transform $x $y2] break array set attrs $curAttrs array set attrs $vars set styles [split [jlib::wrapper:getattr $vars style] \;] set drawitem line foreach s $styles { foreach {attr val} [split $s :] break set attr [string trim $attr] set val [string trim $val] switch -- $attr { "" {} stroke - stroke-width - stroke-linejoin { set attrs($attr) $val } default { Debug 1 Unknown style attr '$attr' } } } set opts [PolygonOpts] Debug 2 polygon $xx $yy $xx1 $yy1 $xx2 $yy2 $xx3 $yy3] $opts eval [list $c create polygon $xx $yy $xx1 $yy1 $xx2 $yy2 $xx3 $yy3] $opts } proc svg::ParsePolyline {c transform curAttrs item} { jlib::wrapper:splitxml $item tag vars isempty chdata children set p [TransformPoints $transform [jlib::wrapper:getattr $vars points]] array set attrs $curAttrs array set attrs $vars set styles [split [jlib::wrapper:getattr $vars style] \;] set drawitem line foreach s $styles { foreach {attr val} [split $s :] break set attr [string trim $attr] set val [string trim $val] switch -- $attr { "" {} fill - stroke - stroke-width - stroke-linecap - stroke-linejoin { set attrs($attr) $val } default { Debug 1 Unknown style attr '$attr' } } } set opts [LineOpts] Debug 2 line $p $opts eval [list $c create line] $p $opts } proc svg::ParseText {c transform curAttrs item} { jlib::wrapper:splitxml $item tag vars isempty chdata children eval lappend transform \ [ParseTransform [jlib::wrapper:getattr $vars transform]] set x [jlib::wrapper:getattr $vars x] set y [jlib::wrapper:getattr $vars y] if {$x == ""} {set x 0} if {$y == ""} {set y 0} foreach {x y} [TransformCoord $transform $x $y] break array set attrs $curAttrs array set attrs $vars set styles [split [jlib::wrapper:getattr $vars style] \;] foreach s $styles { foreach {attr val} [split $s :] break set attr [string trim $attr] set val [string trim $val] set attrs($attr) $val } set allopts [TextOpts] set opts [lindex $allopts 0] set fontopts [lindex $allopts 1] if {$fontopts != ""} { variable app_font set fontname [list font $fontopts] if {![info exists app_font($fontname)]} { # create a font to match the settings set app_font($fontname) [eval [list font create $fontname] $fontopts] } lappend opts -font $app_font($fontname) } Debug 2 text $x $y -text $chdata $opts eval [list $c create text $x $y -text $chdata] $opts } proc svg::LineOpts {} { upvar attrs attrs upvar c c set opts {-joinstyle miter -capstyle butt} foreach {attr val} [array get attrs] { switch -- $attr { "" {} stroke {lappend opts -fill [color $c $val]} stroke-width {lappend opts -width $val} stroke-linecap { switch -- $val { round {lappend opts -capstyle round} square {lappend opts -capstyle projecting} } } stroke-linejoin { switch -- $val { round {lappend opts -joinstyle round} bevel {lappend opts -joinstyle bevel} } } id {lappend opts -tags [list [list id $val]]} } } return $opts } proc svg::PolygonOpts {} { upvar attrs attrs upvar c c set opts {-joinstyle miter -fill "" -outline ""} foreach {attr val} [array get attrs] { switch -- $attr { "" {} fill { if {$val != "" && $val != "none"} { lappend opts -fill [color $c $val] } } stroke { if {$val != "" && $val != "none"} { lappend opts -outline [color $c $val] } } stroke-width {lappend opts -width $val} stroke-linejoin { switch -- $val { round {lappend opts -joinstyle round} bevel {lappend opts -joinstyle bevel} } } id {lappend opts -tags [list [list id $val]]} } } return $opts } proc svg::CircleOpts {} { variable Smooth upvar attrs attrs upvar c c set opts {-joinstyle round -fill "" -outline ""} if {$Smooth} { lappend opts -smooth bezier } foreach {attr val} [array get attrs] { switch -- $attr { "" {} fill { if {$val != "" && $val != "none"} { lappend opts -fill [color $c $val] } } stroke { if {$val != "" && $val != "none"} { lappend opts -outline [color $c $val] } } stroke-width {lappend opts -width $val} id {lappend opts -tags [list [list id $val]]} } } return $opts } proc svg::TextOpts {} { upvar attrs attrs upvar c c set opts {-anchor w} set fontopts {} foreach {attr val} [array get attrs] { switch -- $attr { "" {} fill {lappend opts -fill [color $c $val]} font-family {lappend fontopts -family $val} font-size {lappend fontopts -size $val} font-size-adjust { # How to do this in Tk? } font-stretch { # How to do this in Tk? } font-style { if {[string equal $val italic] || [string equal $val oblique]} { lappend fontopts -slant italic } } font-variant { # How to do this in Tk? } font-weight { if {[string match bold* $val]} { lappend fontopts -weight bold } } text-decoration { foreach subval $val { switch -- $subval { underline { lappend fontopts -underline on } line-through { lappend fontopts -overstrike on } } } } dx { # How to do this in Tk? } dy { # How to do this in Tk? } id {lappend opts -tags [list [list id $val]]} } } return [list $opts $fontopts] } proc svg::TransformPoints {transform raw_points} { # SVG spec says coordinate points can be separated by comma or # white space or comma-with-white-space # string map... convert , to space # regsub... condense multiple whitespaces to single space regsub -all {\s\s*} [string map {, { }} [string trim $raw_points]] { } points_str set p {} foreach {x y} [split $points_str] { eval lappend p [TransformCoord $transform $x $y] } return $p } proc svg::ParseTransform {s} { Debug 2 $s set t {} while {[regexp {(\w+)\s*\(([^\)]*)\)(.*)} $s temp transform param s]} { lappend t [list $transform [split $param ", "]] } Debug 1 $s $t return $t } proc svg::TransformCoord {transform x y} { Debug 2 $transform $x $y set matrix [list 1 0 0 1 0 0] foreach t $transform { foreach {op param} $t break switch -- $op/[llength $param] { matrix/6 { set matrix [Tcompose $matrix $param] } translate/1 { foreach tx $param break set matrix [Tcompose $matrix [list 1 0 0 1 $tx 0]] } translate/2 { foreach {tx ty} $param break set matrix [Tcompose $matrix [list 1 0 0 1 $tx $ty]] } scale/1 { foreach sx $param break set matrix [Tcompose $matrix [list $sx 0 0 $sx 0 0]] } scale/2 { foreach {sx sy} $param break set matrix [Tcompose $matrix [list $sx 0 0 $sy 0 0]] } rotate/1 { foreach a $param break set a [expr {3.1415926 * $a / 180}] set matrix [Tcompose $matrix \ [list [expr {cos($a)}] [expr {sin($a)}] \ [expr {-sin($a)}] [expr {cos($a)}] 0 0]] } rotate/3 { foreach {a cx cy} $param break set a [expr {3.1415926 * $a / 180}] set matrix [Tcompose $matrix [list 1 0 0 1 $cx $cy]] set matrix [Tcompose $matrix \ [list [expr {cos($a)}] [expr {sin($a)}] \ [expr {-sin($a)}] [expr {cos($a)}] 0 0]] set matrix [Tcompose $matrix [list 1 0 0 1 [expr {-$cx}] [expr {-$cy}]]] } skewX/1 { foreach a $param break set a [expr {3.1415926 * $a / 180}] set matrix [Tcompose $matrix [list 1 0 [expr {tan($a)}] 1 0 0]] } skewY/1 { foreach a $param break set a [expr {3.1415926 * $a / 180}] set matrix [Tcompose $matrix [list 1 [expr {tan($a)}] 0 1 0 0]] } } } return [Tapply $matrix $x $y] } proc svg::Tcompose {matrix1 matrix2} { Debug 2 [list $matrix1] [list $matrix2] foreach {a1 b1 c1 d1 e1 f1} $matrix1 break foreach {a2 b2 c2 d2 e2 f2} $matrix2 break set a [expr {$a1*$a2 + $c1*$b2}] set b [expr {$b1*$a2 + $d1*$b2}] set c [expr {$a1*$c2 + $c1*$d2}] set d [expr {$b1*$c2 + $d1*$d2}] set e [expr {$a1*$e2 + $c1*$f2 + $e1}] set f [expr {$b1*$e2 + $d1*$f2 + $f1}] return [list $a $b $c $d $e $f] } proc svg::Tapply {matrix x y} { Debug 2 [list $matrix] $x $y foreach {a b c d e f} $matrix break set x1 [expr {$a*$x + $c*$y + $e}] set y1 [expr {$b*$x + $d*$y + $f}] Debug 1 $x1 $y1 return [list $x1 $y1] } proc svg::color {c color} { Debug 2 $color if {[catch {$c create line 0 0 0 0 -fill $color -width 0} id]} { return black } else { $c delete $id return $color } } proc svg::Debug {level args} { variable Debug if {$Debug >= $level} { puts "[lindex [info level -1] 0]: [join $args]" } } tkabber-plugins-0.11.1/latex/0000755000175000017500000000000011076120366015320 5ustar sergeisergeitkabber-plugins-0.11.1/latex/latex.tcl0000644000175000017500000001116010732302307017133 0ustar sergeisergei# $Id: latex.tcl 1330 2007-12-19 20:53:27Z sergei $ # Shows LaTeX formulas as pictures (*NIX and Windows only) # Requires working latex, dvips, imagemagick # and their binaries should be in the directory listed in PATH package require msgcat namespace eval latex { variable scriptdir [file dirname [info script]] ::msgcat::mcload [file join $scriptdir msgs] variable tmpdir [pwd] variable null "" switch -- $tcl_platform(platform) { windows { catch { set tmpdir $::env(TMP) } catch { set tmpdir $::env(TEMP) } set null "2>NUL" } unix { set tmpdir "/tmp" catch { set tmpdir $::env(TMPDIR) } set null "2>/dev/null" } macintosh { # In case when someone would like to implement it set tmpdir $::env(TRASH_FOLDER) return } } custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup LaTeX [::msgcat::mc "LaTeX formulas plugin options."] -group Plugins custom::defvar options(resolution) 100 \ [::msgcat::mc "Resolution of the LaTeX generated images in pixels per inch."] \ -group LaTeX -type integer # Blacklist is taken from KopeTeX. Not all of them are dengerous though variable blacklist {\def \let \futurelet \newcommand \renewcommand \else \fi \write \input \include \chardef \catcode \makeatletter \noexpand \toksdef \every \errhelp \errorstopmode \scrollmode \nonstopmode \batchmode \read \csname \newhelp \relax \afterground \afterassignment \expandafter \noexpand \special \command \loop \repeat \toks \output \line \mathcode \name \item \section \DeclareRobustCommand} } proc latex::find_formulas {chatid from type body x} { variable blacklist init_colors $chatid foreach {str formula} [regexp -all -inline {\$\$([^$]+)\$\$} $body] { if {[lsearch -exact [image names] latex/$str] >= 0} continue set bl 0 foreach csname $blacklist { if {[string first $csname $formula] >= 0} { set bl 1 break } } if {$bl} continue if {[catch {convert_formula latex/$str $formula} msg]} { debugmsg plugins "latex error: $msg" continue } plugins::emoticons::add $str latex/$str } } hook::add draw_message_hook [namespace current]::latex::find_formulas 10 proc latex::convert_formula {imgname formula} { variable tmpdir variable options variable bg variable fg variable null set res $options(resolution) set i 0 while {1} { set dirname [file join $tmpdir latex$i] if {![file exists $dirname]} break incr i } file mkdir $dirname set fname [file join $dirname out.tex] set fd [open $fname w] fconfigure $fd -encoding utf-8 puts $fd "\\documentclass\[12pt,letterpaper\]{article} \\usepackage{amsmath} \\usepackage{amssymb} \\usepackage{color} \\pagestyle{empty} \\pagecolor\[rgb\]{$bg} \\begin{document} \\color\[rgb\]{$fg} \\begin{gather*}$formula\\end{gather*} \\end{document}" close $fd set wd [pwd] if {[catch { cd $dirname exec latex -interaction=batchmode out.tex $null exec dvips -o [file join $dirname out.eps] \ -E \ [file join $dirname out.dvi] $null exec convert +adjoin \ -antialias \ -density ${res}x${res} \ [file join $dirname out.eps] \ [file join $dirname out.gif] $null } msg]} { cd $wd file delete -force $dirname return -code error $msg } image create photo $imgname -file [file join $dirname out.gif] cd $wd file delete -force $dirname # If the page is empty, dvips doesn't crop it, so we # check image height and width. Letter paper dimensions are 8.5in x 11in if {abs([image width $imgname] - [expr $res * 8.5]) < 1 && \ abs([image height $imgname] - [expr $res * 11]) < 1} { # It's better to delete image and run latex every time when the same # formula appears. Otherwise large images will be stored # and waste space image delete $imgname return -code error "Image is empty" } return $imgname } proc latex::init_colors {chatid} { variable fg variable bg if {[info exists fg] && [info exists bg]} return set chatw [chat::chat_win $chatid] set bgopt [option get $chatw background Chat] if {$bgopt == ""} { set bgopt white } set bg [get_rgb_color $chatw $bgopt] set fgopt [option get $chatw foreground Chat] if {$fgopt == ""} { set fgopt black } set fg [get_rgb_color $chatw $fgopt] } proc latex::get_rgb_color {w color} { lassign [winfo rgb $w $color] r g b set r [expr {($r % 256)/256.}] set g [expr {($g % 256)/256.}] set b [expr {($b % 256)/256.}] return $r,$g,$b } tkabber-plugins-0.11.1/latex/msgs/0000755000175000017500000000000011076120366016271 5ustar sergeisergeitkabber-plugins-0.11.1/latex/msgs/es.msg0000644000175000017500000000047410512234573017415 0ustar sergeisergei::msgcat::mcset es "LaTeX formulas plugin options." "Opciones del plugin de fórmulas LaTeX." ::msgcat::mcset es "Plugins options." "Opciones de los plugins." ::msgcat::mcset es "Resolution of the LaTeX generated images in pixels per inch." "Resolución en pixeles por pulgada de las imágenes generadas por LaTeX." tkabber-plugins-0.11.1/latex/msgs/de.msg0000644000175000017500000000055510573320542017375 0ustar sergeisergei # German messages file # Roger Sondermann 06.03.2007 ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "LaTeX formulas plugin options." "Optionen fr das LaTeX-Formeln-Plugin." ::msgcat::mcset de "Resolution of the LaTeX generated images in pixels per inch." "Auflsung der von LaTeX erstellten Bilder in Pixel/Inch." tkabber-plugins-0.11.1/latex/msgs/ru.msg0000644000175000017500000000061710447053366017441 0ustar sergeisergei::msgcat::mcset ru "Plugins options." "Настройки расширений." ::msgcat::mcset ru "LaTeX formulas plugin options." "Настройки расширения формул LaTeX." ::msgcat::mcset ru "Resolution of the LaTeX generated images in pixels per inch." \ "Разрешение изображений, генерируемых LaTeX'ом, в точках на дюйм." tkabber-plugins-0.11.1/latex/msgs/uk.msg0000644000175000017500000000064410543570072017425 0ustar sergeisergei::msgcat::mcset uk "Plugins options." "Параметри плагінів." ::msgcat::mcset uk "LaTeX formulas plugin options." "Параметри плагіна формул LaTeX." ::msgcat::mcset uk "Resolution of the LaTeX generated images in pixels per inch." \ "Роздільна здатність зображень, що будуть генеруватися LaTeX'ом, у точках на дюйм." tkabber-plugins-0.11.1/ejabberd/0000755000175000017500000000000011076120366015741 5ustar sergeisergeitkabber-plugins-0.11.1/ejabberd/msgs/0000755000175000017500000000000011076120366016712 5ustar sergeisergeitkabber-plugins-0.11.1/ejabberd/msgs/pl.msg0000644000175000017500000000344310667535014020046 0ustar sergeisergei# Polish messages file for ejabberd plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "List of ejabberd servers." "Lista serwerów ejabberd." ::msgcat::mcset pl "Administrate ejabberd" "Zarządzanie serwerem ejabberd" ::msgcat::mcset pl "Administrate ejabberd..." "Zarządzanie serwerem ejabberd..." ::msgcat::mcset pl "Number of users that used this service N days ago:" "Liczba osób korzystających z usługi N dni temu:" ::msgcat::mcset pl "ejabberd server" "Serwer ejabberd" ::msgcat::mcset pl "Administrate" "Zarządzaj" ::msgcat::mcset pl "%s administration" "Zarządzanie serwerem %s" ::msgcat::mcset pl "Reload" "Przeładuj" ::msgcat::mcset pl "Integral" "Razem" ::msgcat::mcset pl "Main" "Główny" ::msgcat::mcset pl "Nodes" "Węzły" ::msgcat::mcset pl "Registration" "Rejestracja" ::msgcat::mcset pl "Access" "Dostęp" ::msgcat::mcset pl "Last Activity" "Ostatnia aktywność" ::msgcat::mcset pl "Registered users:" "Użytkownicy zarejestrowani:" ::msgcat::mcset pl "Online users:" "Użytkownicy połączeni:" ::msgcat::mcset pl "Running nodes:" "Działające węzły:" ::msgcat::mcset pl "Stopped nodes:" "Zatrzymane węzły:" ::msgcat::mcset pl "Outgoing S2S:" "Wychodzący ruch S2S:" ::msgcat::mcset pl "Welcome message subject:" "Temat wiadomości powitalnej:" ::msgcat::mcset pl "Welcome message body:" "Treść wiadomości powitalnej:" ::msgcat::mcset pl "Registration watchers:" "Obserwatorzy rejestracji:" ::msgcat::mcset pl "ACLs:" "ACL-e:" ::msgcat::mcset pl "Access rules:" "Reguły dostępu:" ::msgcat::mcset pl "JID:" "JID:" ::msgcat::mcset pl "Set" "Ustaw" ::msgcat::mcset pl "Cancel" "Anuluj" ::msgcat::mcset pl "Connection:" "Połączenie:" ::msgcat::mcset pl "Server JID:" "JID serwera:" tkabber-plugins-0.11.1/ejabberd/msgs/es.msg0000644000175000017500000000307410712161173020032 0ustar sergeisergei::msgcat::mcset es "%s administration" "administración de %s" ::msgcat::mcset es "ACLs:" "ACLs:" ::msgcat::mcset es "Access rules:" "Reglas de acceso:" ::msgcat::mcset es "Access" "Accesi" ::msgcat::mcset es "Administrate ejabberd" "Administrar ejabberd" ::msgcat::mcset es "Administrate ejabberd..." "Administrar ejabberd..." ::msgcat::mcset es "Administrate" "Administrar" ::msgcat::mcset es "Cancel" "Cancelar" ::msgcat::mcset es "Connection:" "Conexión:" ::msgcat::mcset es "Integral" "Integral" ::msgcat::mcset es "Last Activity" "Última Actividad" ::msgcat::mcset es "List of ejabberd servers." "Lista de servidores ejabberd." ::msgcat::mcset es "Main" "Principal" ::msgcat::mcset es "Nodes" "Nodos" ::msgcat::mcset es "Number of users that used this service N days ago:" "Número de usuarios que usaron este servidor hace N días:" ::msgcat::mcset es "Online users:" "Usuarios conectados:" ::msgcat::mcset es "Outgoing S2S:" "Conexiones S2S salientes:" ::msgcat::mcset es "Registered users:" "Usuarios registrados:" ::msgcat::mcset es "Registration watchers:" "Visores de registros:" ::msgcat::mcset es "Registration" "Regitro" ::msgcat::mcset es "Reload" "Recargar" ::msgcat::mcset es "Running nodes:" "Nodos funcionando:" ::msgcat::mcset es "Server JID:" "JID del servidor:" ::msgcat::mcset es "Set" "Poner" ::msgcat::mcset es "Stopped nodes:" "Nodos detenidos:" ::msgcat::mcset es "Welcome message body:" "Contenido del mensaje de bienvenida:" ::msgcat::mcset es "Welcome message subject:" "Asunto del mensaje de bienvenida:" ::msgcat::mcset es "ejabberd server" "servidor ejabberd" tkabber-plugins-0.11.1/ejabberd/msgs/de.msg0000644000175000017500000000406410735772434020030 0ustar sergeisergei # German messages file # Roger Sondermann 30.12.2007 ::msgcat::mcset de "%s administration" "%s Administrierung" ::msgcat::mcset de "Access rules:" "Zugriffs-Regeln:" ::msgcat::mcset de "Access" "Zugriff" #::msgcat::mcset de "ACLs:" "ACLs:" ::msgcat::mcset de "ACLs:" "Zugriffs-Kontrolllisten:" ::msgcat::mcset de "Administrate ejabberd" "ejabberd administrieren" ::msgcat::mcset de "Administrate ejabberd..." "ejabberd administrieren..." ::msgcat::mcset de "Administrate" "Administrieren" ::msgcat::mcset de "Cancel" "Abbrechen" ::msgcat::mcset de "Connection:" "Verbindung:" ::msgcat::mcset de "ejabberd server" "ejabberd-Server" ::msgcat::mcset de "Integral" "Integriert" ::msgcat::mcset de "Server JID:" "Server-JID:" ::msgcat::mcset de "Last Activity" "Letzte Aktivitt" ::msgcat::mcset de "List of ejabberd servers." "Liste von ejabberd-Servern." ::msgcat::mcset de "Main" "Allgemein" ::msgcat::mcset de "Nodes" "Knoten" ::msgcat::mcset de "Number of users that used this service N days ago:" "Anzahl der Benutzer, die diesen Service innerhalb der letzten N Tage genutzt haben:" ::msgcat::mcset de "Online users:" "'Online'-Benutzer:" ::msgcat::mcset de "Outgoing S2S:" "Ausgehende S2S:" ::msgcat::mcset de "Registered users:" "Registrierte Benutzer:" ::msgcat::mcset de "Registration watchers:" "Registrierungs-Beobachter:" ::msgcat::mcset de "Registration" "Registrierung" ::msgcat::mcset de "Reload" "Neu laden" ::msgcat::mcset de "Running nodes:" "Laufende Knoten:" ::msgcat::mcset de "Set" "Setzen" ::msgcat::mcset de "Stopped nodes:" "Angehaltene Knoten:" ::msgcat::mcset de "Welcome message body:" "Text der 'Willkommen'-Nachricht:" ::msgcat::mcset de "Welcome message subject:" "Subjekt der 'Willkommen'-Nachricht:" tkabber-plugins-0.11.1/ejabberd/msgs/ru.msg0000644000175000017500000000411510633037331020046 0ustar sergeisergei::msgcat::mcset ru "%s administration" "Администрирование %s" ::msgcat::mcset ru "Access rules:" "Правила доступа:" ::msgcat::mcset ru "Access" "Доступ" ::msgcat::mcset ru "ACLs:" "Списки управления доступом:" ::msgcat::mcset ru "Administrate ejabberd" "Администрировать ejabberd" ::msgcat::mcset ru "Administrate ejabberd..." "Администрировать ejabberd..." ::msgcat::mcset ru "Administrate" "Администрировать" ::msgcat::mcset ru "Cancel" "Отменить" ::msgcat::mcset ru "Connection:" "Соединение:" ::msgcat::mcset ru "ejabberd server" "Сервер ejabberd" ::msgcat::mcset ru "Integral" "Интегральный" ::msgcat::mcset ru "Server JID:" "JID сервера:" ::msgcat::mcset ru "Last Activity" "Последнее подключение" ::msgcat::mcset ru "List of ejabberd servers." "Список серверов ejabberd." ::msgcat::mcset ru "Main" "Главная" ::msgcat::mcset ru "Nodes" "Узлы" ::msgcat::mcset ru "Number of users that used this service N days ago:" "Число пользователей, которые подключались к серверу N дней назад:" ::msgcat::mcset ru "Online users:" "Подключённые пользователи:" ::msgcat::mcset ru "Outgoing S2S:" "Исходящие S2S-соединения:" ::msgcat::mcset ru "Registered users:" "Зарегистрированные пользователи:" ::msgcat::mcset ru "Registration watchers:" "Наблюдатели за регистрацией:" ::msgcat::mcset ru "Registration" "Регистрация" ::msgcat::mcset ru "Reload" "Обновить" ::msgcat::mcset ru "Running nodes:" "Запущенные узлы:" ::msgcat::mcset ru "Set" "Установить" ::msgcat::mcset ru "Stopped nodes:" "Остановленные узлы:" ::msgcat::mcset ru "Welcome message body:" "Тело приветственного сообщения:" ::msgcat::mcset ru "Welcome message subject:" "Тема приветственного сообщения:" tkabber-plugins-0.11.1/ejabberd/msgs/uk.msg0000644000175000017500000000365410633037331020046 0ustar sergeisergei ::msgcat::mcset uk "%s administration" "адміністрування %s" ::msgcat::mcset uk "Access rules:" "Правила доступу:" ::msgcat::mcset uk "Access" "Доступ" ::msgcat::mcset uk "ACLs:" "ACLs:" ::msgcat::mcset uk "Administrate ejabberd" "Адмініструвати ejabberd" ::msgcat::mcset uk "Administrate ejabberd..." "Адмініструвати ejabberd..." ::msgcat::mcset uk "Administrate" "Адмініструвати" ::msgcat::mcset uk "Cancel" "Відміна" ::msgcat::mcset uk "Connection:" "З'єднання:" ::msgcat::mcset uk "ejabberd server" "сервер ejabberd" ::msgcat::mcset uk "Integral" "Integral" ::msgcat::mcset uk "Server JID:" "JID сервера:" ::msgcat::mcset uk "Last Activity" "Остання активність" ::msgcat::mcset uk "List of ejabberd servers." "Список ejabberd серверів." ::msgcat::mcset uk "Main" "Головна" ::msgcat::mcset uk "Nodes" "Node" ::msgcat::mcset uk "Number of users that used this service N days ago:" "Кількість користувачів, які використовували цей сервіс N днів тому:" ::msgcat::mcset uk "Online users:" "Користувачі он-лайн:" ::msgcat::mcset uk "Outgoing S2S:" "Вихідні S2S з’єднання:" ::msgcat::mcset uk "Registered users:" "Зареєстровані користувачі:" ::msgcat::mcset uk "Registration watchers:" "Наглядачі реєстрацій:" ::msgcat::mcset uk "Registration" "Реєстрація" ::msgcat::mcset uk "Reload" "Оновити" ::msgcat::mcset uk "Running nodes:" "Запущені nodes:" ::msgcat::mcset uk "Set" "Встановити" ::msgcat::mcset uk "Stopped nodes:" "Зупинені nodes:" ::msgcat::mcset uk "Welcome message body:" "Повідомлення з привітанням:" ::msgcat::mcset uk "Welcome message subject:" "Тема повідомлення з привітанням:" tkabber-plugins-0.11.1/ejabberd/ejabberd.tcl0000644000175000017500000003346710747411465020227 0ustar sergeisergei# $Id: ejabberd.tcl 1354 2008-01-28 17:39:01Z sergei $ package require msgcat ::msgcat::mcload [file join [file dirname [info script]] msgs] namespace eval ejabberd { custom::defvar ejabberd_server_list {} \ [::msgcat::mc "List of ejabberd servers."] \ -group Hidden } set ::NS_ECONFIGURE "http://ejabberd.jabberstudio.org/protocol/configure" proc ejabberd::setup_menu {} { catch { set m [.mainframe getmenu admin] $m add command -label [::msgcat::mc "Administrate ejabberd..."] \ -command [namespace current]::ask_server_dialog } } hook::add finload_hook [namespace current]::ejabberd::setup_menu disco::browser::register_feature_handler $::NS_ECONFIGURE \ [namespace current]::ejabberd::open_win \ -desc [list * [::msgcat::mc "Administrate ejabberd"]] proc ejabberd::ask_server_dialog {} { global ejabberd_server global ejabberd_connid variable ejabberd_server_list set gw .ejabberdserver catch { destroy $gw } if {[llength [jlib::connections]] == 0} return set ejabberd_connid [jlib::connection_jid [lindex [jlib::connections] 0]] Dialog $gw -title [::msgcat::mc "ejabberd server"] -separator 1 -anchor e \ -default 0 -cancel 1 set gf [$gw getframe] grid columnconfigure $gf 1 -weight 1 if {[llength $ejabberd_server_list]} { set ejabberd_server [lindex $ejabberd_server_list 0] } label $gf.ljid -text [::msgcat::mc "Server JID:"] ComboBox $gf.jid \ -textvariable ejabberd_server \ -values $ejabberd_server_list \ -width 35 grid $gf.ljid -row 0 -column 0 -sticky e grid $gf.jid -row 0 -column 1 -sticky ew if {[llength [jlib::connections]] > 1} { foreach c [jlib::connections] { lappend connections [jlib::connection_jid $c] } set ejabberd_connid [lindex $connections 0] label $gf.lconnid -text [::msgcat::mc "Connection:"] ComboBox $gf.connid \ -textvariable ejabberd_connid \ -values $connections \ -editable 0 grid $gf.lconnid -row 1 -column 0 -sticky e grid $gf.connid -row 1 -column 1 -sticky ew } $gw add -text [::msgcat::mc "Administrate"] -command "[namespace current]::administrate $gw" $gw add -text [::msgcat::mc "Cancel"] -command "destroy $gw" $gw draw $gf.jid } proc ejabberd::administrate {gw} { global ejabberd_server global ejabberd_connid variable ejabberd_server_list destroy $gw set ejabberd_server_list \ [update_combo_list $ejabberd_server_list $ejabberd_server 10] foreach c [jlib::connections] { if {[jlib::connection_jid $c] == $ejabberd_connid} { set connid $c } } if {![info exists connid]} return open_win $ejabberd_server -connection $connid } proc ejabberd::open_win {jid args} { foreach {key val} $args { switch -- $key { -connection { set connid $val } } } if {![info exists connid]} { return -code error "ejabberd::open_win: -connection is mandatory" } set w [win_id ejabberd $connid:$jid] if {[winfo exists $w]} { raise_win $w return } set title [format [::msgcat::mc "%s administration"] $jid] add_win $w -title $title \ -tabtitle $jid \ -class Ejabberd \ -raise 1 set nb [NoteBook $w.nb] pack $nb -fill both -expand yes # Binding $nb, not $w to avoid multiple calls if $w is a toplevel bind $nb [list [namespace current]::cleanup $connid $jid] foreach {page title} \ [list main [::msgcat::mc "Main"] \ nodes [::msgcat::mc "Nodes"] \ reg [::msgcat::mc "Registration"] \ access [::msgcat::mc "Access"] \ last [::msgcat::mc "Last Activity"]] { set f [$nb insert end $page -text $title] fill_page_$page $f $connid $jid } $nb raise main } proc ejabberd::cleanup {connid jid} { variable data catch {unset data($connid,$jid,total_users)} catch {unset data($connid,$jid,online_users)} catch {unset data($connid,$jid,running_nodes)} catch {unset data($connid,$jid,stopped_nodes)} catch {unset data($connid,$jid,outgoing_s2s)} catch {unset data($connid,$jid,welcome_subj)} catch {unset data($connid,$jid,welcome_body)} catch {unset data($connid,$jid,reg_watchers)} catch {unset data($connid,$jid,acls)} catch {unset data($connid,$jid,access_rules)} catch {unset data($connid,$jid,last)} catch {unset data($connid,$jid,last_int)} } proc ejabberd::add_grid_record {connid jid info name desc row} { label $info.l$name -text $desc label $info.v$name -textvariable [namespace current]::data($connid,$jid,$name) grid $info.l$name -row $row -column 0 -sticky e grid $info.v$name -row $row -column 1 -sticky w } proc ejabberd::add_grid_edit {connid jid info name desc row} { label $info.l$name -text $desc entry $info.v$name -textvariable [namespace current]::data($connid,$jid,$name) grid $info.l$name -row $row -column 0 -sticky e grid $info.v$name -row $row -column 1 -sticky we } proc ejabberd::add_grid_text {connid jid info name desc row} { label $info.l$name -text $desc set sw [ScrolledWindow $info.s$name -scrollbar vertical] text $info.v$name -height 6 -wrap word $sw setwidget $info.v$name grid $info.l$name -row $row -column 0 -sticky e grid $info.s$name -row $row -column 1 -sticky we } proc ejabberd::fill_page_main {f connid jid} { variable data set info [frame $f.info] pack $info -side top -anchor w -fill both grid columnconfigure $info 1 -weight 2 add_grid_record $connid $jid $info total_users [::msgcat::mc "Registered users:"] 0 add_grid_record $connid $jid $info online_users [::msgcat::mc "Online users:"] 1 add_grid_record $connid $jid $info running_nodes [::msgcat::mc "Running nodes:"] 2 add_grid_record $connid $jid $info stopped_nodes [::msgcat::mc "Stopped nodes:"] 3 add_grid_record $connid $jid $info outgoing_s2s [::msgcat::mc "Outgoing S2S:"] 4 set reload \ [button $f.reload -text [::msgcat::mc "Reload"] \ -command [list [namespace current]::reload_page_main $f $connid $jid]] pack $reload -side bottom -anchor e reload_page_main $f $connid $jid } proc ejabberd::reload_page_main {f connid jid} { jlib::send_iq get \ [jlib::wrapper:createtag info \ -vars [list xmlns $::NS_ECONFIGURE]] \ -to $jid \ -connection $connid \ -command [list [namespace current]::parse_main_info $f $connid $jid] } proc ejabberd::parse_main_info {f connid jid res child} { variable data if {![cequal $res OK]} { return } jlib::wrapper:splitxml $child tag vars isempty chdata children set data($connid,$jid,total_users) [jlib::wrapper:getattr $vars registered-users] set data($connid,$jid,online_users) [jlib::wrapper:getattr $vars online-users] set data($connid,$jid,running_nodes) [jlib::wrapper:getattr $vars running-nodes] set data($connid,$jid,stopped_nodes) [jlib::wrapper:getattr $vars stopped-nodes] set data($connid,$jid,outgoing_s2s) [jlib::wrapper:getattr $vars outgoing-s2s-servers] } proc ejabberd::fill_page_nodes {f connid jid} { } proc ejabberd::fill_page_reg {f connid jid} { variable data set info [frame $f.info] pack $info -side top -anchor w -fill both grid columnconfigure $info 1 -weight 2 add_grid_edit $connid $jid $info welcome_subj [::msgcat::mc "Welcome message subject:"] 0 add_grid_text $connid $jid $info welcome_body [::msgcat::mc "Welcome message body:"] 1 add_grid_text $connid $jid $info reg_watchers [::msgcat::mc "Registration watchers:"] 2 #set set_b [button $f.set -text [::msgcat::mc "Set"]] #pack $set_b -side right -anchor se set reload \ [button $f.reload -text [::msgcat::mc "Reload"] \ -command [list [namespace current]::reload_page_reg $f $connid $jid]] pack $reload -side right -anchor se reload_page_reg $f $connid $jid } proc ejabberd::reload_page_reg {f connid jid} { jlib::send_iq get \ [jlib::wrapper:createtag welcome-message \ -vars [list xmlns $::NS_ECONFIGURE]] \ -to $jid \ -connection $connid \ -command [list [namespace current]::parse_welcome_message $f $connid $jid] jlib::send_iq get \ [jlib::wrapper:createtag registration-watchers \ -vars [list xmlns $::NS_ECONFIGURE]] \ -to $jid \ -connection $connid \ -command [list [namespace current]::parse_registration_watchers $f $connid $jid] } proc ejabberd::parse_welcome_message {f connid jid res child} { variable data set wsubj $f.info.vwelcome_subj set wbody $f.info.vwelcome_body if {![winfo exists $wsubj]} { return } if {![cequal $res OK]} { return } jlib::wrapper:splitxml $child tag vars isempty chdata children set subj "" set body "" foreach ch $children { jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1 switch -- $tag1 { subject {set subj $chdata1} body {set body $chdata1} } } set data($connid,$jid,welcome_subj) $subj set data($connid,$jid,welcome_body) $body $wbody delete 0.0 end $wbody insert 0.0 $body } proc ejabberd::parse_registration_watchers {f connid jid res child} { variable data set wwatchers $f.info.vreg_watchers if {![winfo exists $wwatchers]} { return } if {![cequal $res OK]} { return } jlib::wrapper:splitxml $child tag vars isempty chdata children set jids {} foreach ch $children { jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1 switch -- $tag1 { jid {lappend jids $chdata1} } } set data($connid,$jid,reg_watchers) $jids $wwatchers delete 0.0 end $wwatchers insert 0.0 [join $jids \n] } proc ejabberd::fill_page_access {f connid jid} { variable data set info [frame $f.info] pack $info -side top -anchor w -fill both grid columnconfigure $info 1 -weight 2 add_grid_text $connid $jid $info acls [::msgcat::mc "ACLs:"] 0 add_grid_text $connid $jid $info access_rules [::msgcat::mc "Access rules:"] 1 #set set_b [button $f.set -text [::msgcat::mc "Set"]] #pack $set_b -side right -anchor se set reload \ [button $f.reload -text [::msgcat::mc "Reload"] \ -command [list [namespace current]::reload_page_access $f $connid $jid]] pack $reload -side right -anchor se reload_page_access $f $connid $jid } proc ejabberd::reload_page_access {f connid jid} { jlib::send_iq get \ [jlib::wrapper:createtag acls \ -vars [list xmlns $::NS_ECONFIGURE]] \ -to $jid \ -connection $connid \ -command [list [namespace current]::parse_access acls $f $connid $jid] jlib::send_iq get \ [jlib::wrapper:createtag access \ -vars [list xmlns $::NS_ECONFIGURE]] \ -to $jid \ -connection $connid \ -command [list [namespace current]::parse_access access_rules $f $connid $jid] } proc ejabberd::parse_access {var f connid jid res child} { variable data set w $f.info.v$var if {![winfo exists $w]} { return } if {![cequal $res OK]} { return } jlib::wrapper:splitxml $child tag vars isempty chdata children set data($connid,$jid,$var) $chdata $w delete 0.0 end $w insert 0.0 $chdata } proc ejabberd::fill_page_last {f connid jid} { variable data set info [frame $f.info] pack $info -side top -anchor w -fill both -expand yes #grid columnconfigure $info 1 -weight 2 #add_grid_text $connid $jid $info acls [::msgcat::mc "ACLs:"] 0 #add_grid_text $connid $jid $info access_rules [::msgcat::mc "Access rules:"] 1 label $info.lplot \ -text [::msgcat::mc \ "Number of users that used this service N days ago:"] pack $info.lplot -side top -anchor w set sw [ScrolledWindow $info.sw] pack $sw -side top -fill both -expand yes set plot [canvas $info.plot -background white] $sw setwidget $plot set data($connid,$jid,last) {} set data($connid,$jid,last_int) 0 set integral \ [checkbutton $f.integral -text [::msgcat::mc "Integral"] \ -variable [namespace current]::data($connid,$jid,last_int) \ -command [list [namespace current]::redraw_last $f $connid $jid]] pack $integral -side left -anchor se set reload \ [button $f.reload -text [::msgcat::mc "Reload"] \ -command [list [namespace current]::reload_page_last $f $connid $jid]] pack $reload -side right -anchor se } proc ejabberd::reload_page_last {f connid jid} { jlib::send_iq get \ [jlib::wrapper:createtag last \ -vars [list xmlns $::NS_ECONFIGURE]] \ -to $jid \ -connection $connid \ -command [list [namespace current]::parse_last $f $connid $jid] } proc ejabberd::parse_last {f connid jid res child} { variable data set plot $f.info.plot if {![winfo exists $plot]} { return } if {![cequal $res OK]} { return } jlib::wrapper:splitxml $child tag vars isempty chdata children set data($connid,$jid,last) $chdata redraw_last $f $connid $jid } proc ejabberd::redraw_last {f connid jid} { variable data set plot $f.info.plot set maxdays 0 foreach t $data($connid,$jid,last) { set days [expr {$t / (60*60*24)}] if {$days > $maxdays} {set maxdays $days} if {![info exists last($days)]} { set last($days) 0 } incr last($days) } set xscale 20 set yscale 200 $plot delete all set val 0 for {set i 0} {$i <= $maxdays} {incr i} { if {[info exists last($i)]} { set v $last($i) } else { set v 0 } if {$data($connid,$jid,last_int)} { incr val $v } else { set val $v } set x1 [expr {$xscale * $i}] set x2 [expr {$xscale * ($i+1)}] set x [expr {($x1 + $x2)/2}] set y [expr {-$yscale * $val}] $plot create rectangle $x1 0 $x2 $y -fill red $plot create text $x 0 -text $i -anchor n $plot create text $x $y -text $val -anchor s } set bbox [$plot bbox all] set y1 [lindex $bbox 1] set y2 [lindex $bbox 3] set height [winfo height $plot] $plot scale all 0 0 1 [expr {0.9 * $height / (0.0 + $y2 - $y1)}] $plot configure -scrollregion [$plot bbox all] } tkabber-plugins-0.11.1/reversi/0000755000175000017500000000000011076120366015662 5ustar sergeisergeitkabber-plugins-0.11.1/reversi/msgs/0000755000175000017500000000000011076120366016633 5ustar sergeisergeitkabber-plugins-0.11.1/reversi/msgs/pl.msg0000644000175000017500000000720710667535014017771 0ustar sergeisergei# Polish messages file for reversi plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Reversi plugin options." "Ustawienia wtyczki do gry w Reversi." ::msgcat::mcset pl "Reversi figures theme." "Motyw graficzny figur." ::msgcat::mcset pl "Flip board view when playing white by default." "Odwróć widok planszy podczas gry białymi." ::msgcat::mcset pl "Reversi Invitation" "Zaproszenie do gry w Reversi" ::msgcat::mcset pl "Sending reversi game invitation to %s (%s)" "Wysyłanie zaproszenia do gry w Reversi do %s (%s)" ::msgcat::mcset pl "%s (%s) has refused reversi invitation: %s" "%s (%s) odrzuca zaproszenie do gry w Reversi: %s" ::msgcat::mcset pl "Reversi Invitation from %s" "Zaproszenie do gry w Reversi od %s" ::msgcat::mcset pl "Reversi game invitation from %s (%s) is received." "Otrzymano zaproszenie do gry w Reversi od %s (%s)." ::msgcat::mcset pl "Reversi with %s" "Reversi: %s" ::msgcat::mcset pl "Draw" "Remis" ::msgcat::mcset pl "Reversi..." "Reversi..." ::msgcat::mcset pl "White" "Białe" ::msgcat::mcset pl "Move: " "Ruch: " ::msgcat::mcset pl "History" "Historia" ::msgcat::mcset pl "Black" "Czarne" ::msgcat::mcset pl "Show last move by default." "Pokazuj ostatni ruch." ::msgcat::mcset pl "Show tooltips with short instructions." "Pokazuj dymki podpowiedzi z krótkimi instrukcjami." ::msgcat::mcset pl "Allow illegal moves (useful for debugging)." "Pozwalaj na nieprawidłowe ruchy (użyteczne przy debugowaniu)." ::msgcat::mcset pl "Accept opponent illegal moves (useful for debugging)." "Pozwalaj na nieprawidłowe ruchy przeciwnika (użyteczne przy debugowaniu)." ::msgcat::mcset pl "I want play white" "Chcę grać białymi" ::msgcat::mcset pl "I want play black" "Chcę grać czarnymi" ::msgcat::mcset pl "Cancel invitation" "Anuluj zaproszenie" ::msgcat::mcset pl "Agree to play" "Przyjmij zaproszenie" ::msgcat::mcset pl "Refuse to play" "Odrzuć zaproszenie" ::msgcat::mcset pl " (You)" " (Ty)" ::msgcat::mcset pl " (Opponent)" " (Przeciwnik)" ::msgcat::mcset pl "You win (Opponent resigned)" "Wygałeś (przeciwnik zrezygnował)" ::msgcat::mcset pl "Draw (Opponent accepted)" "Remis (za zgodą przeciwnika)" ::msgcat::mcset pl "Show last move" "Pokaż ostatni ruch" ::msgcat::mcset pl "Flip view" "Odwróć widok" ::msgcat::mcset pl "Propose a draw" "Zaproponuj remis" ::msgcat::mcset pl "Accept the draw proposal" "Zaakceptuj remis" ::msgcat::mcset pl "Resign the game" "Zrezygnuj z gry" ::msgcat::mcset pl "Press button and make move if you want propose draw" "Naciśnij przycisk i wykonaj ruch jeżeli chcesz zaproponować remis" ::msgcat::mcset pl "Press button if you want accept the draw proposal" "Naciśnij przycisk jeżeli chcesz zaakceptować propozycję remisu" ::msgcat::mcset pl "Press button if you want resign" "Naciśnij przycisk jeżeli chcesz zrezygnować z gry" ::msgcat::mcset pl "\n\n Opponent proposes a draw\n\n" "\n\n Przeciwnik proponuje remis\n\n" ::msgcat::mcset pl "Draw (You accepted)" "Remis (Za moją zgodą)" ::msgcat::mcset pl "Opponent wins (You resigned)" "Wygrał przeciwnik (Zrezygnowałeś z gry)" ::msgcat::mcset pl "Games" "Gry planszowe" ::msgcat::mcset pl "Sound to play after opponent's turn" "Odtwórz dźwięk po ruchu przeciwnika" ::msgcat::mcset pl "%s wants play white." "%s chce grać białymi." ::msgcat::mcset pl "%s wants play black." "%s chce grać czarnymi." ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "\n\n Opponent rejected move:\n %s\n\n" "\n\n Przeciwnik odrzucił ruch:\n %s\n\n" ::msgcat::mcset pl "You win" "Wygrałeś" ::msgcat::mcset pl "Opponent wins" "Wygrał przeciwnik" tkabber-plugins-0.11.1/reversi/msgs/es.msg0000644000175000017500000000701210545463157017762 0ustar sergeisergei ::msgcat::mcset es " (Opponent)" " (Oponente)" ::msgcat::mcset es " (You)" " (Tu)" ::msgcat::mcset es "%s (%s) has refused reversi invitation: %s" "%s (%s) ha rechazado la invitación de jugar al reversi: %s" ::msgcat::mcset es "%s wants play black." "%s quiere jugar con las negras." ::msgcat::mcset es "%s wants play white." "%s quiere jugar con las blancas." ::msgcat::mcset es "Accept opponent illegal moves (useful for debugging)." "Aceptar movimientos ilegales del oponente (útil para depuración)." ::msgcat::mcset es "Accept the draw proposal" "Aceptar la propuesta de empate" ::msgcat::mcset es "Agree to play" "Aceptar la invitación" ::msgcat::mcset es "Allow illegal moves (useful for debugging)." "Permitir movimientos ilegales (útil para depuración)." ::msgcat::mcset es "Black" "Negra" ::msgcat::mcset es "Cancel invitation" "Cancelar la invitación" ::msgcat::mcset es "Draw (Opponent accepted)" "Empate (el oponente aceptó)" ::msgcat::mcset es "Draw (You accepted)" "Empate (aceptaste)" ::msgcat::mcset es "Draw" "Empate" ::msgcat::mcset es "Flip board view when playing white by default." "Rotar tablero por defecto cuando juegas con las blancas." ::msgcat::mcset es "Flip view" "Rotar tablero" ::msgcat::mcset es "Games" "Juegos" ::msgcat::mcset es "History" "Historia" ::msgcat::mcset es "I want play black" "Quiero jugar con las negras" ::msgcat::mcset es "I want play white" "Quiero jugar con las blancas" ::msgcat::mcset es "Move: " "Movimiento: " ::msgcat::mcset es "Opponent wins (You resigned)" "El oponente gana (te rendiste)" ::msgcat::mcset es "Opponent wins" "El oponente gana" ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Press button and make move if you want propose draw" "Pulsa el botón y haz un movimiento si quieres proponer un empate" ::msgcat::mcset es "Press button if you want accept the draw proposal" "Pulsa el botón si quieres aceptar la propuesta de empate" ::msgcat::mcset es "Press button if you want resign" "Pulsa el botón si quieres rendirte" ::msgcat::mcset es "Propose a draw" "Proponer un empate" ::msgcat::mcset es "Refuse to play" "Rechazar la invitación" ::msgcat::mcset es "Resign the game" "Rendirte" ::msgcat::mcset es "Reversi Invitation from %s" "Invitación al Reversi de %s" ::msgcat::mcset es "Reversi Invitation" "Invitación al Reversi" ::msgcat::mcset es "Reversi figures theme." "Tipo de fichas en Reversi." ::msgcat::mcset es "Reversi game invitation from %s (%s) is received." "Se ha recibido una invitación para jugar al reversi de %s (%s)." ::msgcat::mcset es "Reversi plugin options." "Opciones del plugin Reversi." ::msgcat::mcset es "Reversi with %s" "Reversi: %s" ::msgcat::mcset es "Reversi..." "Reversi..." ::msgcat::mcset es "Sending reversi game invitation to %s (%s)" "Enviando invitación para jugar al reversi a %s (%s)" ::msgcat::mcset es "Show last move by default." "Mostrar el último movimiento por defecto." ::msgcat::mcset es "Show last move" "Mostrar el último movimiento" ::msgcat::mcset es "Show tooltips with short instructions." "Mostrar pequeñas instrucciones de ayuda." ::msgcat::mcset es "Sound to play after opponent's turn" "Sonido a reproducir cuando el oponente haya movido" ::msgcat::mcset es "White" "Blanca" ::msgcat::mcset es "You win (Opponent resigned)" "Tu ganas (el oponente se rindió)" ::msgcat::mcset es "You win" "Tu ganas" ::msgcat::mcset es "\n\n Opponent proposes a draw\n\n" "\n\n El oponente propone un empate \n\n" ::msgcat::mcset es "\n\n Opponent rejected move:\n %s\n\n" "\n\n El oponente rechazó el movimiento:\n %s\n\n" tkabber-plugins-0.11.1/reversi/msgs/ru.msg0000644000175000017500000001061210512234573017771 0ustar sergeisergei ::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Flip board view when playing white by default." "Разворачивать по умолчанию доску при игре белыми." ::msgcat::mcset ru "Show last move by default." "По умолчанию показывать последний ход." ::msgcat::mcset ru " (You)" " (Вы)" ::msgcat::mcset ru " (Opponent)" " (Оппонент)" ::msgcat::mcset ru "Flip view" "Развернуть доску" ::msgcat::mcset ru "Reversi plugin options." "Параметры расширения Реверси." ::msgcat::mcset ru "Reversi figures theme." "Тема фишек реверси." ::msgcat::mcset ru "Show tooltips with short instructions." "Показывать всплывающие подсказки к элементам интерфейса." ::msgcat::mcset ru "Allow illegal moves (useful for debugging)." "Разрешать неправильные ходы (используется при отладке)." ::msgcat::mcset ru "Accept opponent illegal moves (useful for debugging)." "Принимать неправильные ходы от оппонента (используется при отладке)." ::msgcat::mcset ru "Reversi Invitation" "Приглашение сыграть в реверси" ::msgcat::mcset ru "Sending reversi game invitation to %s (%s)" "Посылаем приглашение сыграть в реверси с %s (%s)" ::msgcat::mcset ru "I want play white" "Хочу играть белыми" ::msgcat::mcset ru "I want play black" "Хочу играть чёрными" ::msgcat::mcset ru "Cancel invitation" "Отменить приглашение" ::msgcat::mcset ru "%s (%s) has refused reversi invitation: %s" "%s (%s) отказался играть в реверси: %s" ::msgcat::mcset ru "Reversi Invitation from %s" "Приглашение сыграть в реверси с %s" ::msgcat::mcset ru "Reversi game invitation from %s (%s) is received." "Получено приглашение сыграть в реверси с %s (%s)" ::msgcat::mcset ru "%s wants play white." "%s хочет играть белыми" ::msgcat::mcset ru "%s wants play black." "%s хочет играть чёрными" ::msgcat::mcset ru "Agree to play" "Согласиться играть" ::msgcat::mcset ru "Refuse to play" "Отказаться играть" ::msgcat::mcset ru "Reversi with %s" "Реверси с %s" ::msgcat::mcset ru "Show last move" "Показывать последний ход" ::msgcat::mcset ru "Move: " "Ход: " ::msgcat::mcset ru "Propose a draw" "Предложить ничью" ::msgcat::mcset ru "Accept the draw proposal" "Принять предложенную ничью" ::msgcat::mcset ru "Resign the game" "Сдать партию" ::msgcat::mcset ru "History" "Запись партии" ::msgcat::mcset ru "Reversi..." "Реверси..." ::msgcat::mcset ru "White" "Белые" ::msgcat::mcset ru "Black" "Чёрные" ::msgcat::mcset ru "Opponent wins" "Оппонент выиграл" ::msgcat::mcset ru "You win" "Вы выиграли" ::msgcat::mcset ru "Opponent wins (You resigned)" "Оппонент выиграл (Вы сдались)" ::msgcat::mcset ru "You win (Opponent resigned)" "Вы выиграли (Оппонент сдался)" ::msgcat::mcset ru "Draw" "Ничья" ::msgcat::mcset ru "Draw (You accepted)" "Ничья (Вы приняли)" ::msgcat::mcset ru "Draw (Opponent accepted)" "Ничья (Оппонент принял)" ::msgcat::mcset ru "Press button and make move if you want propose draw" "Нажмите кнопку и сделайте ход, если хотите предложить ничью" ::msgcat::mcset ru "Press button if you want accept the draw proposal" "Нажмите кнопку, если хотите принять предложенную ничью" ::msgcat::mcset ru "Press button if you want resign" "Нажмите кнопку, если хотите сдаться" ::msgcat::mcset ru "\n\n Opponent proposes a draw\n\n" "\n\n Оппонент предлагает ничью\n\n" ::msgcat::mcset ru "\n\n Opponent rejected move:\n %s\n\n" "\n\n Оппонент отверг ход:\n %s\n\n" ::msgcat::mcset ru "Games" "Игры" ::msgcat::mcset ru "Sound to play after opponent's turn" "Звук, который проигрывается после хода оппонента" tkabber-plugins-0.11.1/reversi/msgs/uk.msg0000644000175000017500000001074310543571750017774 0ustar sergeisergei ::msgcat::mcset uk "Plugins options." "Параметри плагінів." ::msgcat::mcset uk "Flip board view when playing black by default." "Розвертати дошку при грі чорними за замовчуванням." ::msgcat::mcset uk "Show last move by default." "Показувати останній хід за замовчуванням." ::msgcat::mcset uk " (You)" " (Ви)" ::msgcat::mcset uk " (Opponent)" " (Опонент)" ::msgcat::mcset uk "Flip view" "Розгорнути дошку" ::msgcat::mcset uk "Reversi plugin options." "Параметри плагіна Реверсі." ::msgcat::mcset uk "Reversi figures theme." "Тема фішок реверсі." ::msgcat::mcset uk "Show tooltips with short instructions." "Показувати спливаючі підказки до елементів інтерфейсу." ::msgcat::mcset uk "Allow illegal moves (useful for debugging)." "Дозволяти неправильні ходи (використовується при налагодженні)." ::msgcat::mcset uk "Accept opponent illegal moves (useful for debugging)." "Приймати неправильні ходи від опонента (використовується при налагодженні)." ::msgcat::mcset uk "Reversi Invitation" "Запрошення зіграти в реверсі" ::msgcat::mcset uk "Sending reversi game invitation to %s (%s)" "Відправлення запрошення зіграти в реверсі з %s (%s)" ::msgcat::mcset uk "I want play white" "Хочу грати білими" ::msgcat::mcset uk "I want play black" "Хочу грати чорними" ::msgcat::mcset uk "Cancel invitation" "Скасувати запрошення" ::msgcat::mcset uk "%s (%s) has refused reversi invitation: %s" "%s (%s) відмовився грати в реверсі: %s" ::msgcat::mcset uk "Reversi Invitation from %s" "Запрошення зіграти в реверсі з %s" ::msgcat::mcset uk "Reversi game invitation from %s (%s) is received." "Отримане запрошення зіграти в реверсі з %s (%s)" ::msgcat::mcset uk "%s wants play white." " %s хоче грати білими" ::msgcat::mcset uk "%s wants play black." " %s хоче грати чорними" ::msgcat::mcset uk "Agree to play" "Погодитися грати" ::msgcat::mcset uk "Refuse to play" "Відмовитися грати" ::msgcat::mcset uk "Reversi with %s" "Реверсі з %s" ::msgcat::mcset uk "Show last move" "Показувати останній хід" ::msgcat::mcset uk "Move: " "Хід: " ::msgcat::mcset uk "Propose a draw" "Запропонувати нічию" ::msgcat::mcset uk "Accept the draw proposal" "Прийняти запропоновану нічию" ::msgcat::mcset uk "Resign the game" "Здати партію" ::msgcat::mcset uk "History" "Запис партії" ::msgcat::mcset uk "Pawn promotion" "Перетворення пішака" ::msgcat::mcset uk "Reversi..." "Реверсі..." ::msgcat::mcset uk "White" "Білі" ::msgcat::mcset uk "Black" "Чорні" ::msgcat::mcset uk "Opponent wins" "Опонент виграв" ::msgcat::mcset uk "You win" "Ви виграли" ::msgcat::mcset uk "Opponent wins (You resigned)" "Опонент виграв (Ви здалися)" ::msgcat::mcset uk "You win (Opponent resigned)" "Ви виграли (Опонент здався)" ::msgcat::mcset uk "Draw" "Нічия" ::msgcat::mcset uk "Draw (You accepted)" "Нічия (Ви прийняли)" ::msgcat::mcset uk "Draw (Opponent accepted)" "Нічия (Опонент прийняв)" ::msgcat::mcset uk "Press button and make move if you want propose draw" "Натисніть кнопку й зробіть хід, якщо хочете запропонувати нічию" ::msgcat::mcset uk "Press button if you want accept the draw proposal" "Натисніть кнопку, якщо хочете прийняти запропоновану нічию" ::msgcat::mcset uk "Press button if you want resign" "Натисніть кнопку, якщо хочете здатися" ::msgcat::mcset uk "\n\n Opponent proposes a draw\n\n" "\n\n Опонент пропонує нічию\n\n" ::msgcat::mcset uk "\n\n Opponent rejected move:\n %s\n\n" "\n\n Опонент відкинув хід:\n %s\n\n" ::msgcat::mcset uk "Games" "Ігри" ::msgcat::mcset uk "Sound to play after opponent's turn" "Звук, який буде програватися після ходу опонента" tkabber-plugins-0.11.1/reversi/msgs/nl.msg0000644000175000017500000000714310277726732017774 0ustar sergeisergei# Dutch messages file # Author: Sander Devrieze s.devrieze@pandora.be # Please notify me of errors or incoherencies. ::msgcat::mcset nl "Plugins options." "Pluginopties." ::msgcat::mcset nl "Reversi plugin options." "Pluginopties voor Reversi." ::msgcat::mcset nl "Reversi figures theme." "Thema voor afbeeldingen van stenen." ::msgcat::mcset nl "Flip board view when playing white by default." "Het speelbord standaard omkeren bij het spelen met wit." ::msgcat::mcset nl "Show last move by default." "Laatste zet standaard laten zien." ::msgcat::mcset nl "Show tooltips with short instructions." "Tekstballonnen met korte instructies laten zien." ::msgcat::mcset nl "Allow illegal moves (useful for debugging)." "Niet-toegelaten zetten toestaan (bruikbaar voor debuggen)." ::msgcat::mcset nl "Accept opponent illegal moves (useful for debugging)." "Niet-toegelaten zetten van tegenstander accepteren (bruikbaar voor debuggen)." ::msgcat::mcset nl "Reversi Invitation" "Uitnodiging voor een spelletje Reversi" ::msgcat::mcset nl "Sending reversi game invitation to %s (%s)" "Bezig met verzenden van uitnodiging voor een spelletje Reversi naar %s (%s)" ::msgcat::mcset nl "I want play black" "Ik wil met zwart spelen" ::msgcat::mcset nl "I want play white" "Ik wil met wit spelen" ::msgcat::mcset nl "Cancel invitation" "Uitnodiging annuleren" ::msgcat::mcset nl "%s (%s) has refused reversi invitation: %s" "%s (%s) ging niet in op de uitnodiging om met hem Reversi te spelen: %s" ::msgcat::mcset nl "Reversi Invitation from %s" "Uitnodiging voor een spelletje Reversi met %s" ::msgcat::mcset nl "Reversi game invitation from %s (%s) is received." "Uitnodiging voor een spelletje Reversi met %s (%s) werd ontvangen." ::msgcat::mcset nl "%s wants play %s." "%s wil spelen met %s." ::msgcat::mcset nl "Agree to play" "Spelen" ::msgcat::mcset nl "Refuse to play" "Niet spelen" ::msgcat::mcset nl "White" "Wit" ::msgcat::mcset nl "Black" "Zwart" ::msgcat::mcset nl " (You)" "(Jij)" ::msgcat::mcset nl " (Opponent)" "(Tegenstander)" ::msgcat::mcset nl "You win (Opponent resigned)" "Jij hebt gewonnen (de tegenstander gaf het op)" ::msgcat::mcset nl "Draw (Opponent accepted)" "Gelijkspel (de tegenstander accepteerde de uitslag)" ::msgcat::mcset nl "Reversi with %s" "Reversi met %s" ::msgcat::mcset nl "Show last move" "Laatste zet laten zien" ::msgcat::mcset nl "Flip view" "Beeld omkeren" ::msgcat::mcset nl "Move: " "Zet: " ::msgcat::mcset nl "Propose a draw" "Gelijkspel voorstellen" ::msgcat::mcset nl "Accept the draw proposal" "Het voorstel voor gelijkspel accepteren" ::msgcat::mcset nl "Resign the game" "Geef het op" ::msgcat::mcset nl "History" "Geschiedenis" ::msgcat::mcset nl "Press button and make move if you want propose draw" "Druk op de knop en doe een zet als je gelijkspel wilt voorstellen" ::msgcat::mcset nl "Press button if you want accept the draw proposal" "Druk op de knop als je het voorstel voor gelijkspel wilt accepteren" ::msgcat::mcset nl "Press button if you want resign" "Druk op de knop als je wilt opgeven" ::msgcat::mcset nl "\n\n Opponent proposes a draw\n\n" "\n\n De tegenstander stelt een gelijkspel voor\n\n" ::msgcat::mcset nl "Draw" "Gelijkspel" ::msgcat::mcset nl "You win" "Jij hebt gewonnen" ::msgcat::mcset nl "Opponent wins" "De tegenstander heeft gewonnen" ::msgcat::mcset nl "Draw (You accepted)" "Gelijkspel (jij accepteerde de uitslag)" ::msgcat::mcset nl "Opponent wins (You resigned)" "De tegenstander heeft gewonnen (jij gaf het op)" ::msgcat::mcset nl "\n\n Opponent rejected move:\n %s\n\n" "\n\n De tegenstander weigerde de zet:\n %s\n\n" ::msgcat::mcset nl "Games" "Spelletjes" ::msgcat::mcset nl "Reversi..." "Reversi..." tkabber-plugins-0.11.1/reversi/proto0000644000175000017500000000312110214663710016743 0ustar sergeisergeiRequest: 600 -- for all players 10 -- if on black side played Kasparov Positive response: or simply ? Turn: 'pos' attribute contains coordinates of piece. Coordinate is a comma-separated list of integers >= 0. Proposing draw: Accepting draw proposal: Resigning: Also we need and tags for games where we must put or remove pieces. can have 'type' and 'color' attributes. move, put & destroy tags can have some game-specific subtags Response: if move accepted, or error 'Not Acceptable' if other side think that this move illegal. tkabber-plugins-0.11.1/reversi/reversi.tcl0000644000175000017500000007427711047022175020063 0ustar sergeisergei# $Id: reversi.tcl 1481 2008-08-08 10:48:29Z sergei $ package require msgcat namespace eval reversi { variable scriptdir [file dirname [info script]] ::msgcat::mcload [file join $scriptdir msgs] variable square_size 48 variable line_width 1 variable themes set dirs [glob -nocomplain -directory [file join $scriptdir pixmaps] *] foreach dir $dirs { pixmaps::load_theme_name [namespace current]::themes $dir } set values {} foreach theme [lsort [array names themes]] { lappend values $theme $theme } custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup Reversi [::msgcat::mc "Reversi plugin options."] -group Plugins custom::defvar options(theme) Checkers \ [::msgcat::mc "Reversi figures theme."] -group Reversi \ -type options -values $values \ -command [namespace current]::load_stored_theme custom::defvar options(flip_white_view) 0 \ [::msgcat::mc "Flip board view when playing white by default."] \ -type boolean -group Reversi custom::defvar options(show_last_move) 0 \ [::msgcat::mc "Show last move by default."] \ -type boolean -group Reversi custom::defvar options(show_tooltips) 1 \ [::msgcat::mc "Show tooltips with short instructions."] \ -type boolean -group Reversi \ -command [list [namespace current]::set_tooltips] custom::defvar options(sound) "" \ [::msgcat::mc "Sound to play after opponent's turn"] \ -type file -group Reversi custom::defvar options(allow_illegal) 0 \ [::msgcat::mc "Allow illegal moves (useful for debugging)."] \ -type boolean -group Reversi custom::defvar options(accept_illegal) 0 \ [::msgcat::mc "Accept opponent illegal moves (useful for debugging)."] \ -type boolean -group Reversi } proc reversi::load_stored_theme {args} { variable options variable themes pixmaps::load_dir $themes($options(theme)) } hook::add postload_hook [namespace current]::reversi::load_stored_theme 70 proc reversi::get_nick {connid jid type} { if {[catch {chat::get_nick $connid $jid $type} nick]} { return [chat::get_nick $jid $type] } else { return $nick } } proc reversi::invite_dialog {connid jid} { set w .reversi_invite if {[winfo exists $w]} { destroy $w } Dialog $w -title [::msgcat::mc "Reversi Invitation"] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] message $wf.message -aspect 50000 \ -text [format [::msgcat::mc "Sending reversi game invitation to %s (%s)"] \ [get_nick $connid $jid chat] \ $jid] pack $wf.message -pady 2m $w add -text [::msgcat::mc "I want play black"] \ -command [list [namespace current]::invite $connid $jid black] $w add -text [::msgcat::mc "I want play white"] \ -command [list [namespace current]::invite $connid $jid white] $w add -text [::msgcat::mc "Cancel invitation"] \ -command [list destroy $w] $w draw } proc reversi::invite {connid jid color} { destroy .reversi_invite set id reversi[rand 1000000000] # FIX #set rjid [get_jid_of_user $jid] jlib::send_iq set \ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type reversi id $id color $color]] \ -to $jid \ -command [list [namespace current]::invite_res $connid $jid $id $color] \ -connection $connid } proc reversi::invite_res {connid jid id color res child} { if {![cequal $res OK]} { after idle [list NonmodalMessageDlg .reversi_invite_error -aspect 50000 -icon error \ -message [format [::msgcat::mc "%s (%s) has refused reversi invitation: %s"] \ [get_nick $connid $jid chat] \ $jid [error_to_string $child]]] return "" } start_play $connid $jid $id $color } proc reversi::invited_dialog {connid jid id color} { variable invited_result set w .reversi_invited if {[winfo exists $w]} { destroy $w } Dialog $w -title [format [::msgcat::mc "Reversi Invitation from %s"] $jid] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] bind $wf [list [namespace current]::set_invited_res ""] set nick [get_nick $connid $jid chat] set message1 [format [::msgcat::mc "Reversi game invitation from %s (%s) is received."] \ $nick $jid] switch -- $color { white { set message2 [format [::msgcat::mc "%s wants play white."] $nick] } black { set message2 [format [::msgcat::mc "%s wants play black."] $nick] } default { return [list error modify bad-request] } } message $wf.message1 -aspect 50000 -text $message1 message $wf.message2 -aspect 50000 -text $message2 pack $wf.message1 -pady 1m pack $wf.message2 -pady 1m $w add -text [::msgcat::mc "Agree to play"] \ -command [list [namespace current]::set_invited_res 0] $w add -text [::msgcat::mc "Refuse to play"] \ -command [list [namespace current]::set_invited_res 1] $w draw vwait [namespace current]::invited_result catch { bind $wf {} destroy $w } if {$invited_result == 0} { switch -- $color { white { start_play $connid $jid $id black } black { start_play $connid $jid $id white } default { return [list error modify bad-request] } } return [list result\ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type reversi id $id]]] } else { return [list error modify not-acceptable] } } proc reversi::set_invited_res {res} { variable invited_result set invited_result $res } proc reversi::start_play {connid jid id color} { set gid [make_gid $jid $id] variable $gid upvar 0 $gid flags set flags(window) [win_id reversi $gid] set flags(connid) $connid set flags(opponent) $jid set flags(id) $id set flags(flip) 0 set flags(our_color) $color trace variable [namespace current]::${gid}(position,turn) w \ [list [namespace current]::set_label_move $gid] make_default_position $gid open $gid } proc reversi::set_label_move {gid args} { variable $gid upvar 0 $gid flags switch -- $flags(position,turn) { white { set flags(move_label) [::msgcat::mc "White"] set move 1 } black { set flags(move_label) [::msgcat::mc "Black"] set move 1 } default { set move 0 } } if {$move && [is_my_move $gid]} { append flags(move_label) [::msgcat::mc " (You)"] } else { append flags(move_label) [::msgcat::mc " (Opponent)"] } } proc reversi::make_default_position {gid} { variable $gid upvar 0 $gid flags for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set flags(position,$c,$r) "" } } set flags(position,3,3) w set flags(position,4,4) w set flags(position,3,4) b set flags(position,4,3) b set flags(position,turn) black catch {unset flags(position,last_move)} set flags(position,draw) 0 set flags(position,halfmove) 0 set flags(position,history) {} } proc reversi::save_position {gid} { variable $gid upvar 0 $gid flags set flags(saved_position) [array get flags position,*] } proc reversi::restore_position {gid} { variable $gid upvar 0 $gid flags array set flags $flags(saved_position) draw_position $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc reversi::make_gid {jid id} { jid_to_tag [concat $jid $id] } proc reversi::turn_recv {gid children} { variable options variable $gid upvar 0 $gid flags set move 0 set draw 0 foreach child $children { jlib::wrapper:splitxml $child tag vars isempty chdata children1 switch -- $tag { put { set pos [jlib::wrapper:getattr $vars pos] set poss [split $pos ","] if {[llength $poss] == 2} { set ct [lindex $poss 0] set rt [lindex $poss 1] set move 1 if {$options(sound) != "" && ![::sound::is_mute]} { ::sound::play $options(sound) } } } resign { end_game $gid 1 [::msgcat::mc "You win (Opponent resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type reversi \ id $flags(id)]]] } accept { if {$flags(position,draw)} { end_game $gid 0.5 [::msgcat::mc "Draw (Opponent accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type reversi \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } draw { set draw 1 } } } if {$move && [do_move $gid $ct $rt $draw]} { update_controls $gid $draw draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type reversi \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } ############################################################################### proc reversi::calc_moves {} { variable moves for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { for {set moves(d1,$c,$r) {}; set x [expr {$c+1}]; set y [expr {$r+1}]} \ {($x < 8) && ($y < 8)} {incr x; incr y} { lappend moves(d1,$c,$r) $x $y } for {set moves(d2,$c,$r) {}; set x [expr {$c-1}]; set y [expr {$r+1}]} \ {($x >= 0) && ($y < 8)} {incr x -1; incr y} { lappend moves(d2,$c,$r) $x $y } for {set moves(d3,$c,$r) {}; set x [expr {$c-1}]; set y [expr {$r-1}]} \ {($x >= 0) && ($y >= 0)} {incr x -1; incr y -1} { lappend moves(d3,$c,$r) $x $y } for {set moves(d4,$c,$r) {}; set x [expr {$c+1}]; set y [expr {$r-1}]} \ {($x < 8) && ($y >= 0)} {incr x; incr y -1} { lappend moves(d4,$c,$r) $x $y } for {set moves(h1,$c,$r) {}; set x [expr {$c+1}]} {$x < 8} {incr x} { lappend moves(h1,$c,$r) $x $r } for {set moves(h2,$c,$r) {}; set x [expr {$c-1}]} {$x >= 0} {incr x -1} { lappend moves(h2,$c,$r) $x $r } for {set moves(v1,$c,$r) {}; set y [expr {$r+1}]} {$y < 8} {incr y} { lappend moves(v1,$c,$r) $c $y } for {set moves(v2,$c,$r) {}; set y [expr {$r-1}]} {$y >= 0} {incr y -1} { lappend moves(v2,$c,$r) $c $y } } } } hook::add finload_hook [namespace current]::reversi::calc_moves 100 proc reversi::center {c r} { variable square_size variable line_width set r [expr {7 - $r}] list [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $c)}] \ [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $r)}] } proc reversi::close {gid} { variable $gid upvar 0 $gid flags array unset flags } proc reversi::exists {gid} { variable $gid info exists $gid } proc reversi::open {gid} { variable options variable square_size variable line_width variable $gid upvar 0 $gid flags set jid $flags(opponent) set w $flags(window) if {[winfo exists $w]} { raise_win $w return } set title [format [::msgcat::mc "Reversi with %s"] [get_nick $flags(connid) $jid chat]] add_win $w -title $title \ -tabtitle $title \ -class Reversi \ -raise 1 set board [canvas $w.board \ -width [expr {($square_size + $line_width) * 8}] \ -height [expr {($square_size + $line_width) * 8}]] pack $board -side left -anchor w -padx 10 set flags(board) $board set flags(show_last_move) $options(show_last_move) set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] set slm [Button $w.show_last_move -text [::msgcat::mc "Show last move"] \ -relief $relief \ -command [list [namespace current]::toggle_show_last_move $gid]] pack $slm -side top -anchor w -fill x set flags(show_last_move_button) $slm set flags(flip) 0 set slm [Button $w.flip -text [::msgcat::mc "Flip view"] \ -relief raised \ -command [list [namespace current]::toggle_flip_view $gid]] pack $slm -side top -anchor w -fill x set flags(flip_button) $slm frame $w.move pack $w.move -side top -anchor w label $w.move.title -text [::msgcat::mc "Move: "] pack $w.move.title -side left label $w.move.on_move -anchor w \ -textvariable [namespace current]::${gid}(move_label) pack $w.move.on_move -side left -anchor w set bbox [ButtonBox $w.bbox -orient vertical -spacing 0] $bbox add -text [::msgcat::mc "Propose a draw"] \ -command [list [namespace current]::toggle_draw $gid] $bbox add -text [::msgcat::mc "Accept the draw proposal"] \ -state disabled \ -command [list [namespace current]::accept_draw $gid] $bbox add -text [::msgcat::mc "Resign the game"] \ -command [list [namespace current]::send_resign $gid] grid columnconfigure $bbox 0 -weight 1 pack $bbox -side bottom -anchor w -fill x set flags(bbox) $bbox set_tooltips #label $w.history -text [::msgcat::mc "History"] #pack $w.history -side top -anchor w set hsw [ScrolledWindow $w.hsw] pack $hsw -side top -fill x -expand yes set ht [text $w.text -wrap word -height 60 -state disabled] set font [$ht cget -font] set tabstop1 [font measure $font "99.."] set tabstop2 [font measure $font "99..Qa8-a8+= "] $ht configure -tabs "$tabstop1 $tabstop2" $ht tag configure attention -foreground [option get $ht errorForeground Text] $hsw setwidget $ht set flags(hw) $ht set dsq_color #77a26d set lsq_color #c8c365 for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set x1 [expr {$line_width + (($square_size + $line_width) * $c)}] set x2 [expr {($square_size + $line_width) * ($c + 1)}] set y1 [expr {$line_width + (($square_size + $line_width) * $r)}] set y2 [expr {($square_size + $line_width) * ($r + 1)}] set color [expr {($c+$r) % 2 ? $dsq_color : $lsq_color}] set img [expr {($c+$r) % 2 ? "bf" : "wf"}] $board create image $x1 $y1 -image reversi/$img -anchor nw \ -tags [list background [list cr $c [expr {7-$r}]]] $board create rectangle $x1 $y1 $x2 $y2 \ -outline {} \ -tags [list last [list cr $c [expr {7-$r}]]] $board create rectangle $x1 $y1 $x2 $y2 \ -outline {} \ -tags [list square [list cr $c [expr {7-$r}]]] } } bind $board \ [list [namespace current]::motion $gid %x %y] bind $board \ [list [namespace current]::motion $gid %x %y] bind $board \ [list [namespace current]::leave $gid %x %y] bind $board \ [list [namespace current]::release $gid %x %y] bind $w [list [namespace current]::close $gid] make_default_position $gid if {[is_white $flags(our_color)] && $options(flip_white_view)} { toggle_flip_view $gid } draw_position $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc reversi::toggle_flip_view {gid} { variable $gid upvar 0 $gid flags set flags(flip) [expr {!$flags(flip)}] set board $flags(board) for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { $board addtag [list temp [expr {7-$c}] [expr {7-$r}]] \ withtag [list cr $c $r] $board dtag [list cr $c $r] } } for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { $board addtag [list cr $c $r] withtag [list temp $c $r] $board dtag [list temp $c $r] } } set relief [expr {$flags(flip) ? "sunken" : "raised"}] $flags(flip_button) configure -relief $relief draw_position $gid highlight_legal_moves $gid highlight_last_move $gid } proc reversi::set_tooltips {args} { variable options if {$options(show_tooltips)} { set tooltip0 [::msgcat::mc "Press button and make move if you want propose draw"] set tooltip1 [::msgcat::mc "Press button if you want accept the draw proposal"] set tooltip2 [::msgcat::mc "Press button if you want resign"] } else { set tooltip0 "" set tooltip1 "" set tooltip2 "" } foreach var [info vars [namespace current]::*] { upvar 0 $var flags if {[info exists flags(bbox)]} { catch { $flags(bbox) itemconfigure 0 -helptext $tooltip0 $flags(bbox) itemconfigure 1 -helptext $tooltip1 $flags(bbox) itemconfigure 2 -helptext $tooltip2 } } } } proc reversi::toggle_show_last_move {gid} { variable $gid upvar 0 $gid flags set flags(show_last_move) [expr {!$flags(show_last_move)}] set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] $flags(show_last_move_button) configure -relief $relief highlight_last_move $gid } proc reversi::toggle_draw {gid} { variable $gid upvar 0 $gid flags set flags(position,draw) [expr {!$flags(position,draw)}] if {$flags(position,draw)} { $flags(bbox) itemconfigure 0 -relief sunken } else { $flags(bbox) itemconfigure 0 -relief raised } } proc reversi::update_controls {gid {draw_proposed 0}} { variable $gid upvar 0 $gid flags $flags(bbox) itemconfigure 0 -relief raised if {[is_my_move $gid]} { $flags(board) config -cursor "" set flags(position,draw) 0 if {$draw_proposed} { $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state normal $flags(bbox) itemconfigure 2 -state disabled } else { $flags(bbox) itemconfigure 0 -state normal $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state normal } } elseif {![is_white $flags(position,turn)] && \ ![is_black $flags(position,turn)]} { $flags(board) config -cursor "" $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled } else { $flags(board) config -cursor watch $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled } } proc reversi::end_game {gid my_score message} { variable $gid upvar 0 $gid flags set opponent_score [expr {1 - $my_score}] if {[is_black $flags(our_color)]} { set score "$my_score : $opponent_score" } else { set score "$opponent_score : $my_score" } set flags(position,turn) none set flags(move_label) $message set hw $flags(hw) $hw configure -state normal catch {$hw delete attention.first attention.last} $hw delete {end -1 char} end $hw insert end "\n\t\t$score\n" $hw see end $hw configure -state disabled } proc reversi::draw_position {gid} { variable $gid upvar 0 $gid flags $flags(board) delete figure for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { if {$flags(position,$c,$r) != ""} { if {$flags(flip)} { set c1 [expr {7 - $c}] set r1 [expr {7 - $r}] } else { set c1 $c set r1 $r } $flags(board) create image [center $c1 $r1] \ -image reversi/$flags(position,$c,$r) \ -tags [list figure $flags(position,$c,$r) [list cr $c $r]] } } } } proc reversi::motion {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq $board addtag dst_sq overlapping $x $y $x $y set tags [$board gettags dst_sq&&background] lassign [lindex $tags [lsearch $tags cr*]] cr c r $board addtag dst_sq withtag [list cr $c $r]&&square if {[info exists flags(position,$c,$r)] && $flags(position,$c,$r) == ""} { $board itemconfigure dst_sq&&square -outline red $board itemconfigure dst_sq&&legal&&square -outline blue } } proc reversi::leave {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq highlight_last_move $gid } proc reversi::release {gid x y} { variable options variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq $board addtag dst_sq overlapping $x $y $x $y set tags [$board gettags dst_sq&&background] lassign [lindex $tags [lsearch $tags cr*]] cr c r $board dtag dst_sq if {$options(allow_illegal) || [is_my_move $gid]} { if {[do_move $gid $c $r $flags(position,draw)]} { $board itemconfigure [list cr $c $r]&&square -outline "" } } update_controls $gid draw_position $gid highlight_last_move $gid } proc reversi::highlight_last_move {gid} { variable $gid upvar 0 $gid flags $flags(board) itemconfigure last -outline "" if {[catch {lassign $flags(position,last_move) ct rt}]} { return } if {$flags(show_last_move)} { set color white } else { set color {} } $flags(board) itemconfigure [list cr $ct $rt]&&last -outline $color } proc reversi::do_move {gid ct rt draw} { variable options variable moves variable $gid upvar 0 $gid flags if {$ct == "" || $rt == ""} { return 0 } set my_move [is_my_move $gid] if {![is_move_legal $gid $ct $rt]} { if {$my_move && !$options(allow_illegal)} { return 0 } if {!$my_move && !$options(accept_illegal)} { return 0 } } save_position $gid if {[is_white $flags(position,turn)]} { set mover w set opp b } else { set mover b set opp w } set flags(position,$ct,$rt) $mover foreach dir {d1 d2 d3 d4 h1 h2 v1 v2} { set state opp foreach {x y} $moves($dir,$ct,$rt) { set pos $flags(position,$x,$y) switch -- $state { opp { if {$pos != $opp} { break } else { set state both } } both { if {$pos == ""} { break } elseif {$pos == $mover} { foreach {x y} $moves($dir,$ct,$rt) { set pos $flags(position,$x,$y) if {$pos == $mover} { break } else { set flags(position,$x,$y) $mover } } break } } } } } set flags(position,last_move) [list $ct $rt] add_move_to_history $gid $ct $rt if {$draw && !$my_move} { attention_message $gid \ [::msgcat::mc "\n\n Opponent proposes a draw\n\n"] } if {$my_move} { send_move $gid $ct $rt } if {[is_white $flags(position,turn)]} { find_legal_moves $gid black } else { find_legal_moves $gid white } set skip [lempty $flags(legal_moves)] if {!$skip} { if {[is_white $flags(position,turn)]} { set flags(position,turn) black } else { set flags(position,turn) white } } find_legal_moves $gid $flags(position,turn) set endgame 0 if {$skip && [lempty $flags(legal_moves)]} { set endgame 1 lassign [count_pieces $gid] bp wp } elseif {$skip} { add_move_to_history $gid } if {$endgame} { if {$bp == $wp} { # Draw end_game $gid 0.5 [::msgcat::mc "Draw"] } elseif {(($bp > $wp) && [is_black $flags(our_color)]) || \ (($bp < $wp) && [is_white $flags(our_color)])} { # I win end_game $gid 1 [::msgcat::mc "You win"] } else { # Opponent wins end_game $gid 0 [::msgcat::mc "Opponent wins"] } } tab_set_updated [winfo parent $flags(board)] 1 mesg_to_user return 1 } proc reversi::accept_draw {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type reversi \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag accept]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0.5 [::msgcat::mc "Draw (You accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc reversi::send_resign {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type reversi \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag resign]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0 [::msgcat::mc "Opponent wins (You resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc reversi::send_move {gid ct rt} { variable $gid upvar 0 $gid flags set put_tags [list [jlib::wrapper:createtag put -vars [list pos "$ct,$rt"]]] if {$flags(position,draw)} { lappend put_tags [jlib::wrapper:createtag draw] } jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type reversi \ id $flags(id)] \ -subtags $put_tags] \ -to $flags(opponent) \ -connection $flags(connid) \ -command [list [namespace current]::send_result $gid] } proc reversi::send_result {gid res child} { if {$res == "ERR"} { attention_message $gid \ [format [::msgcat::mc "\n\n Opponent rejected move:\n %s\n\n"] \ [error_to_string $child]] restore_position $gid } } proc reversi::count_pieces {gid} { variable $gid upvar 0 $gid flags set b 0 set w 0 for {set ct 0} {$ct < 8} {incr ct} { for {set rt 0} {$rt < 8} {incr rt} { switch -- $flags(position,$ct,$rt) { b { incr b } w { incr w } } } } return [list $b $w] } proc reversi::add_move_to_history {gid {ct ""} {rt ""}} { variable $gid upvar 0 $gid flags incr flags(position,halfmove) if {$ct != "" && $rt != ""} { lappend flags(position,history) [list $ct $rt] } else { lappend flags(position,history) skip } set hw $flags(hw) $hw configure -state normal $hw delete 0.0 end $hw insert end "\t[::msgcat::mc Black]\t[::msgcat::mc White]\n" set i 1 foreach {b w} $flags(position,history) { $hw insert end "${i}.\t" if {$b == "skip"} { $hw insert end "--\t" } elseif {$b != {}} { lassign $b ct rt incr rt set lt [format %c [expr {$ct+97}]] $hw insert end "$lt$rt\t" } if {$w == "skip"} { $hw insert end "--\n" } elseif {$w != {}} { lassign $w ct rt incr rt set lt [format %c [expr {$ct+97}]] $hw insert end "$lt$rt\n" } else { $hw insert end "\n" } incr i } lassign [count_pieces $gid] bp wp $hw insert end "\n\t$bp\t$wp\n" $hw see end $hw configure -state disabled } proc reversi::find_legal_moves {gid color} { variable $gid upvar 0 $gid flags set flags(legal_moves) {} for {set ct 0} {$ct < 8} {incr ct} { for {set rt 0} {$rt < 8} {incr rt} { if {$flags(position,$ct,$rt) == "" && \ [check_legal $gid $ct $rt $color]} { lappend flags(legal_moves) [list $ct $rt] } } } highlight_legal_moves $gid } proc reversi::check_legal {gid ct rt color} { variable moves variable $gid upvar 0 $gid flags set me [expr {[is_black $color] ? "b" : "w"}] set opp [expr {[is_black $color] ? "w" : "b"}] foreach dir {d1 d2 d3 d4 h1 h2 v1 v2} { set state opp foreach {x y} $moves($dir,$ct,$rt) { set pos $flags(position,$x,$y) switch -- $state { opp { if {$pos != $opp} { break } else { set state both } } both { if {$pos == ""} { break } elseif {$pos == $me} { return 1 } } } } } return 0 } proc reversi::is_move_legal {gid ct rt} { variable $gid upvar 0 $gid flags expr {[lmatch -regexp $flags(legal_moves) ^[list $ct $rt]] != {}} } proc reversi::highlight_legal_moves {gid} { variable $gid upvar 0 $gid flags set board $flags(board) $board dtag legal foreach move $flags(legal_moves) { lassign $move ct rt $board addtag legal withtag [list cr $ct $rt]&&square } } proc reversi::attention_message {gid message} { variable $gid upvar 0 $gid flags set hw $flags(hw) $hw configure -state normal $hw delete {end -1 char} end $hw insert end $message attention $hw see end $hw configure -state disabled } proc reversi::is_my_move {gid} { variable $gid upvar 0 $gid flags is_same_color $flags(position,turn) $flags(our_color) } proc reversi::is_white {f} { string equal -length 1 $f w } proc reversi::is_black {f} { string equal -length 1 $f b } proc reversi::is_same_color {f1 f2} { string equal -length 1 $f1 $f2 } proc reversi::add_groupchat_user_menu_item {m connid jid} { set mm $m.gamesmenu if {![winfo exists $mm]} { menu $mm -tearoff 0 $m add cascade -label [::msgcat::mc "Games"] -menu $mm } $mm add command -label [::msgcat::mc "Reversi..."] \ -command [list [namespace current]::invite_dialog $connid $jid] } hook::add roster_create_groupchat_user_menu_hook \ [namespace current]::reversi::add_groupchat_user_menu_item 51 hook::add chat_create_user_menu_hook \ [namespace current]::reversi::add_groupchat_user_menu_item 51 hook::add roster_jid_popup_menu_hook \ [namespace current]::reversi::add_groupchat_user_menu_item 51 proc reversi::iq_create {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children if {[jlib::wrapper:getattr $vars type] == "reversi"} { if {[jlib::wrapper:isattr $vars color]} { set color [jlib::wrapper:getattr $vars color] switch -- $color { white - black { } default { set var [list error modify bad-request] } } } else { set color white } set var [[namespace current]::invited_dialog \ $connid $from \ [jlib::wrapper:getattr $vars id] \ $color] } return } hook::add games_board_create_hook [namespace current]::reversi::iq_create proc reversi::iq_turn {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children if {[jlib::wrapper:getattr $vars type] == "reversi"} { set gid [make_gid $from [jlib::wrapper:getattr $vars id]] if {[exists $gid]} { set var [[namespace current]::turn_recv $gid $children] } else { set var [list error cancel item-not-found] } } return } hook::add games_board_turn_hook [namespace current]::reversi::iq_turn # Common games:board part proc iq_games_board_create {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_create_hook res $connid $from $child return $res } iq::register_handler set create games:board \ [namespace current]::iq_games_board_create proc iq_games_board_turn {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_turn_hook res $connid $from $child return $res } iq::register_handler set turn games:board \ [namespace current]::iq_games_board_turn tkabber-plugins-0.11.1/reversi/pixmaps/0000755000175000017500000000000011076120366017343 5ustar sergeisergeitkabber-plugins-0.11.1/reversi/pixmaps/xboard/0000755000175000017500000000000011076120366020622 5ustar sergeisergeitkabber-plugins-0.11.1/reversi/pixmaps/xboard/w.gif0000644000175000017500000000035210471327266021565 0ustar sergeisergeiGIF89a11!,11ڋ{IHؠ$›q0wwm |P( rcRW5nʋfuyִ uoF82Xx~_җ"@XȤrhX7IYyfHV&Y6f' 6iDVWa1{#v3:҂Fw,=M]m}Q;tkabber-plugins-0.11.1/reversi/pixmaps/xboard/b.gif0000644000175000017500000000034410471327266021541 0ustar sergeisergeiGIF89a11!,11ڋ{IHؠ$›10wwm |P rcRW5nʋfuyִ uoF82Xx~_җ"@XȤrhX7IYyfHV&Y6f' 6iDVWa1{#v3:҂Fw,=M]m}Q;tkabber-plugins-0.11.1/reversi/pixmaps/xboard/bf.gif0000644000175000017500000000013310471327266021703 0ustar sergeisergeiGIF89a11wm!,112ڋ޼H扦ʶ L Ģ;tkabber-plugins-0.11.1/reversi/pixmaps/xboard/wf.gif0000644000175000017500000000013310471327266021730 0ustar sergeisergeiGIF89a11e!,112ڋ޼H扦ʶ L Ģ;tkabber-plugins-0.11.1/reversi/pixmaps/xboard/icondef.xml0000644000175000017500000000122010366754433022757 0ustar sergeisergei Xboard 1.0 Reversi Xboard Theme. 2006-01-23 reversi/bf bf.gif reversi/b b.gif reversi/wf wf.gif reversi/w w.gif tkabber-plugins-0.11.1/reversi/pixmaps/checkers/0000755000175000017500000000000011076120366021132 5ustar sergeisergeitkabber-plugins-0.11.1/reversi/pixmaps/checkers/w.gif0000644000175000017500000000166010501561725022072 0ustar sergeisergeiGIF89a11 ! ,11@pH,Ȥrl:ШtJZlgTlK >!=$ vm| V| U| t S|c^ ʻ Q{cedk^ Posuu^ a} p식rf>bgԱ0ae :AHuI1 bѦ!C8uzA S1y#*brS 0`l0oY*ZRLho)` = ՅD:3T `ʉ@4.("t. G4 4ξ VL! 4XRԒY "K)-gI-@9Y!qtBJ*|C A Y?ږ@)J6xx@ rOthHb D_GXBIxLPψTTV87Ȅyy4Q<`u'9|8PCLv[xU#ha@D  v@i jiL#ʨ֤+k$M!wI(+[czUln'&6[D;tkabber-plugins-0.11.1/reversi/pixmaps/checkers/bf.gif0000644000175000017500000000156510501561725022217 0ustar sergeisergeiGIF89a11 sQ1sY1{U1{Y1kUBsYJ{YBYBaBaJiB! ,11А" mAQ!Hn x&HLՕqdj~ˠ CiCbtB. 3=BN 7B+A'(7ay@\V76!~2 (HR99 / jͺbi8*ä8n$/b8,0{ډ#ɟT{VXkA Bl:iΖ"P.@-"C$P "h6Ŋ Wܩ垁pTγ5;$f &q pS?s|4:RMPX( 8XLy@ٖf <2] jBN@Ήi8-(EAВ%X?Bjg : ;t4BȞ "@duع:,m KndSFpULW67ŏ5j8*;I0܉vwK=Ig isr(4I!pi'ci*%IhD q R=9(.Df!} f&4JJ ow]&_bYo1qz f(EGdk+oQy4 :-3_adl^hXmm4KuXqh : b|:vBД a> f¬ J|R'deת,PH'ݎpc!eBO @: G)9db`!( y:]{&bƬA} 8ϐ4Fx nP Nh !1Q`Z5ճIRJ7b*OP5@\'2*,5AKŜCĠhGmX"D%eR@lP\7I]O)3FqEzH@]̆=KegOU .QRMa DvNʱm_oBaȽ{c6euo`\jI.)3:P{9%G'}mp_bV cX/`.N!xN%TA{d`/!wxBIdBC!`3j ?搉̩cBG:4;ődvY*29dT"NVMS#x(epDiֳ`/ZVd%Ic@e%|lݶeAI2@;tkabber-plugins-0.11.1/reversi/pixmaps/checkers/icondef.xml0000644000175000017500000000122410366754433023273 0ustar sergeisergei Checkers 1.0 Reversi Checkers Theme. 2006-01-23 reversi/bf bf.gif reversi/b b.gif reversi/wf wf.gif reversi/w w.gif tkabber-plugins-0.11.1/custom-urls/0000755000175000017500000000000011076120366016500 5ustar sergeisergeitkabber-plugins-0.11.1/custom-urls/custom-urls.tcl0000644000175000017500000000757710633516775021534 0ustar sergeisergei# $Id: custom-urls.tcl 1145 2007-06-12 13:22:05Z sergei $ # Custom URL Processing -- converts some strings into clickable URLS. # # Predefined examples include: # 1) XEP links: # xep-0013 or jep-0013 or jep-13 or xep-13 or jep13 or xep13 -> # http://www.xmpp.org/extensions/xep-0013.html # 2) RFC links: # rfc-1111 -> http://rfc.net/rfc1111.html # 3) Debian BTS links: # bug-345678 or #345678 -> # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=345678 # # Matching is case insensitive. # # To define your own custom numbered URL add its definition (similar to URLs # below) to postload section of Tkabber config file. Note that the number must # match the second regexp match variable, and the whole link must match the # first match variable, so look closely at (?:) modifiers in the examples. # Also, note that the plugin uses extended regexp syntax. # # Example for config.tcl: # #proc postload {} { # set re {\y(bug(?:-|\s+)?\#?(\d+))\y} # set ::plugins::custom-urls::url(tclbug) \ # [list [string map {bug tclbug} $re] \ # "http://sourceforge.net/search/?type_of_search=artifact&group_id=10894&words=%d"] # set ::plugins::custom-urls::url(tkbug) \ # [list [string map {bug tkbug} $re] \ # "http://sourceforge.net/search/?type_of_search=artifact&group_id=12997&words=%d"] #} # namespace eval custom-urls { variable url set url(xep) [list {\y((?:jep|xep)(?:-|\s+)?(\d+))\y} \ "http://www.xmpp.org/extensions/xep-%04d.html"] set url(rfc) [list {\y(rfc(?:-|\s+)?(\d+))\y} \ "http://rfc.net/rfc%04d.html"] set url(debbug) [list {(?:^|\s)((?:(?:bug(?:-|\s+)?\#?)|\#)(\d+))\y} \ "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%d"] } ############################################################################### # This proc actually uses "url" rich text entity and relies on its # ability to render "titled" URLs. proc custom-urls::process_urls {atLevel accName} { upvar #$atLevel $accName chunks set out {} foreach {s type tags} $chunks { if {$type != "text"} { # pass through lappend out $s $type $tags continue } set ix 0; set xs 0; set xe 0; set num {} while {[spot_url $s $ix xs xe t num]} { if {$xs - $ix > 0} { # dump chunk before URL lappend out [string range $s $ix [expr {$xs - 1}]] $type $tags } set text [string range $s $xs $xe] set url [make_url $text $t $num] lappend out $url url $tags ::richtext::property_update url:title,$url $text set ix [expr {$xe + 1}] } if {[string length $s] - $ix > 0} { # dump chunk after URL lappend out [string range $s $ix end] $type $tags } } set chunks $out } ############################################################################### proc custom-urls::spot_url {what at startVar endVar typeVar numVar} { variable url upvar 1 $startVar xs $endVar xe $typeVar type $numVar num set res 0 foreach idx [array names url] { if {[regexp -expanded -nocase -indices -start $at -- \ [lindex $url($idx) 0] $what -> all digits]} { set type $idx set res 1 break } } if {!$res} { return false } lassign $all xs xe lassign $digits ds de set num [::force_integer [string range $what $ds $de]] return true } ############################################################################### proc custom-urls::make_url {text type num} { variable url if {[catch {set curl [format [lindex $url($type) 1] $num]}]} { return "" } else { return $curl } } ############################################################################### namespace eval custom-urls { ::richtext::register_entity custom-url \ -parser [namespace current]::process_urls \ -parser-priority 55 ::richtext::entity_state custom-url 1 } ############################################################################### # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/unixkeys/0000755000175000017500000000000011076120366016062 5ustar sergeisergeitkabber-plugins-0.11.1/unixkeys/unixkeys.tcl0000644000175000017500000000413011022754505020442 0ustar sergeisergei# $Id: unixkeys.tcl 1450 2008-06-08 13:06:13Z sergei $ # "Unixkeys" -- plugin for Tkabber. # Provides keybindings in Tk Text widgets which are familiar # to Unix users: they resemble "canonical" bindings found in # readline and Emacs. # Written by Konstantin Khomoutov # See INSTALL for installation procedure. # See README for usage guidelines. # See license.terms for details on usage and distribution. namespace eval unixkeys { proc BindEntry {event script} { bind Entry $event $script bind BwEntry $event $script } foreach mod {Alt Meta} { bind Text <$mod-Key-a> [bind Text ] bind Text <$mod-Key-e> [bind Text ] BindEntry <$mod-Key-a> [bind Entry ] BindEntry <$mod-Key-e> [bind Entry ] } foreach mod {Alt Meta} { bind Text <$mod-Key-b> [bind Text ] bind Text <$mod-Key-f> [bind Text ] } BindEntry [bind Entry ] BindEntry [bind Entry ] bind Text { %W delete {insert linestart} insert} BindEntry { %W delete 0 insert } foreach {mod key} {Alt BackSpace Control w} { bind Text <$mod-Key-$key> { %W delete [tk::TextPrevPos %W insert tcl_startOfPreviousWord] insert } BindEntry <$mod-Key-$key> { %W delete [tk::EntryPreviousWord %W insert] insert } } foreach key {d Delete} { foreach mod {Alt Meta} { bind Text <$mod-Key-$key> { %W delete insert [::tk::TextNextPos %W insert tcl_endOfWord] } BindEntry <$mod-Key-$key> { %W delete insert [::tk::EntryNextWord %W insert] } } } if {[string equal $::tcl_platform(os) windows]} { event add <> } event add <> bind Text { %W tag add sel 1.0 end } bind Text { %W tag remove sel 1.0 end } bind Text { %W tag add sel 1.0 end } BindEntry [bind Entry ] } namespace delete unixkeys # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/unixkeys/README0000644000175000017500000000747211022754505016753 0ustar sergeisergei$Id: README 1450 2008-06-08 13:06:13Z sergei $ "Unixkeys" -- plugin for Tkabber. I. The idea This plugins adds some Unix-style keybindings to various widgets used to enter text in Tkabber (namely, entry widgets, chat input windows, comboboxes etc). The text "Unix-style" is vague, so more precisely it stands for something like "resembles default keybindings of Emacs text editor and Readline library". That is, these keybindings should be familiar to those using bash and Emacs. See the next section for complete listing of keybindings. II. Usage After this plugin is loaded by Tkabber, the keybindings it provides are available in all controls used to input text in Tkabber. The keybindings added are: * M-a -- move cursor to the start of text. * M-e -- move cursor to the end of text (but see below). * M-f -- move cursor one word forward. * M-b -- move cursor one word backward. * C-u -- delete text from the cursor to the beginning of the current line. * M-BackSpace, C-w -- delete text from the cursor to the start of the current word. * M-BackSpace, M-d -- delete text from the cursor to the end of the current word. * C-x C-u -- Undo the last change (in multiline entry widgets). * C-x h -- Select all text. Also, on Windows, another keybinding is added to multiline entry widgets: * C-_ (Ctrl-Underscore) -- Undo the last change. And, finally, two convenience bindings are added to multiline entry widgets (they're borrowed from single-line entry and listbox Tk widgets): * C-/ (Ctrl-slash) -- Select all text. * C-\ (Ctrl-backslash) -- Clear selection. Since text-oriented Tk widgets already provide some Unix-style bindings, we can summarise the complete "Unix-style editing capabilities" which those widgets provide in concert with this plugin: * C-f, C-b -- move cursor one character forward/backward. * M-f, M-b -- move cursor one word forward/backward. * C-a, C-e -- move cursor to the start/end of the current line (in multiline entry widgets) or to the start/end of text (in single-line entry widgets). * M-a, M-e -- move cursor to the start/end of text. * C-h, C-d -- delete one character to the left/right from the cursor. * C-w, M-BackSpace -- delete text to the start of the current word. * M-d, M-Delete -- delete text to the end of the current word. * C-u, C-k -- delete text from the cursor to the start/end of the current line. * C-x C-u, C-_, C-z -- Undo the last change (only in multiline entry widgets). * C-/, C-x h -- Select all text. * C-\ -- Clear selection. III. Configuration. No configuration is needed except for one issue explained below. The built-in Tkabber plugin providing support for emoticons binds its action "show menu with available emoticons" to M-e ( and ) in chat input windows thus effectively cancelling the effect of pressing M-e which this plugin adds. If you prefer M-e to be used for cursor motion as provided by this plugin, add something like construct in the postload section of your config.tcl: foreach b [event info <>] { event delete <> $b } This will unbind *all* bindings from the Tk virtual event that shows the emoticons palette, effectivly disabling its usage. If you want to access this palette via some other gesture, add it like this, for instance: event add <> This will made the emoticons palette to pop up when you press on your keyboard. IV. Limitations. The bindings do not match *exactly* the behaviours of software they borrow from. For example, M-e in Emacs stands for "end of sentence", not "end of text in the buffer" as this plugin does for multiline entry widgets. The plugin requires special tweaking to get M-e working, as described above. # vim:tw=64:noet tkabber-plugins-0.11.1/unixkeys/TODO0000644000175000017500000000016511022754505016553 0ustar sergeisergei$Id: TODO 1450 2008-06-08 13:06:13Z sergei $ * M-a, M-e in text widgets should move by sentences. # vim:tw=64:noet tkabber-plugins-0.11.1/unixkeys/license.terms0000644000175000017500000000211211021551246020547 0ustar sergeisergeiCopyright (c) 2007 Konstantin Khomoutov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/unixkeys/INSTALL0000644000175000017500000000047311021551246017112 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/unixkeys/ ~/.tkabber/plugins/unixkeys/unixkeys.tcl Restart Tkabber, to get the plugin loaded. Consult the README file for the details about using this plugin. tkabber-plugins-0.11.1/unixkeys/AUTHORS0000644000175000017500000000006611021551246017127 0ustar sergeisergeiKonstantin Khomoutov tkabber-plugins-0.11.1/floatinglog/0000755000175000017500000000000011076120366016510 5ustar sergeisergeitkabber-plugins-0.11.1/floatinglog/msgs/0000755000175000017500000000000011076120366017461 5ustar sergeisergeitkabber-plugins-0.11.1/floatinglog/msgs/pl.msg0000644000175000017500000000437110714530322020604 0ustar sergeisergei# Polish messages file for floatinglog plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Delay before message hide (in seconds)." "Odstęp czasu, po którym widomość zostanie ukryta (w sekundach)" ::msgcat::mcset pl "Floating Log plugin options." "Ustawienia wtyczki FloatingLog." ::msgcat::mcset pl "Floating Log window properties." "Właściowości okna FloatingLog." ::msgcat::mcset pl "From: " "Od: " ::msgcat::mcset pl "Idle for %s" "Bezczynny przez %s" ::msgcat::mcset pl "Incoming message" "Wiadomość przychodząca" ::msgcat::mcset pl "Message types to show." "Typy pokazywanych wiadomości." ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "Show chat messages." "Pokaż wiadomości z rozmów." ::msgcat::mcset pl "Show floating log." "Pokaż okno FloatingLog." ::msgcat::mcset pl "Show groupchat messages." "Pokaż wiadomości z konferencji." ::msgcat::mcset pl "Show in \"Away\" status." "Pokaż przy statusie \"Zaraz wracam\"." ::msgcat::mcset pl "Show in \"Do not disturb\" status." "Pokaż przy statusie \"Nie przeszkadzać\"." ::msgcat::mcset pl "Show in \"Extended away\" status." "Pokaż przy statusie \"Nieobecny\"." ::msgcat::mcset pl "Show incoming message body." "Pokaż treść przychodzącej wiadomości." ::msgcat::mcset pl "Show other messages." "Pokaż inne wiadomości." ::msgcat::mcset pl "Show when Tkabber is active." "Pokaż gdy aktywne jest główne okno Tkabbera." ::msgcat::mcset pl "Use simple view scheme." "Używaj prostego schematu widoku." ::msgcat::mcset pl "Window opacity (in percent)." "Przeźroczystość okna (w procentach)." ::msgcat::mcset pl "Window position." "Pozycja okna." ::msgcat::mcset pl "Window width." "Szerokość okna." ::msgcat::mcset pl "Show notifications (presence state changes, chat state events, IQ queries etc)." "Pokaż powiadomienia (zmiany statusów, zdarzenia wiadomości, zapytania IQ itp.)." ::msgcat::mcset pl "Show only personal messages and MUC highlights." "Pokaż tylko wiadomości do mnie i podkreślone wiadomości MUC." ::msgcat::mcset pl "Maximum window height." "Maksymalna szerokość okna." ::msgcat::mcset pl "%s request from %s" "Zapytanie %s od %s"tkabber-plugins-0.11.1/floatinglog/msgs/es.msg0000644000175000017500000000410710712161173020577 0ustar sergeisergei::msgcat::mcset es "%s request from %s" "Petición %s de %s" ::msgcat::mcset es "Delay before message hide (in seconds)." "Retraso antes de ocultar el mensaje (en segundos)." ::msgcat::mcset es "Floating Log plugin options." "Opciones del plugin Floating Log." ::msgcat::mcset es "Floating Log window properties." "Propiedades de la ventana Floating Log." ::msgcat::mcset es "From: " "De: " ::msgcat::mcset es "Idle for %s" "Inactivo para %s" ::msgcat::mcset es "Incoming message" "Mensaje entrante" ::msgcat::mcset es "Maximum window height." "Altura máxima de ventana." ::msgcat::mcset es "Message types to show." "Tipos de mensajes a mostrar." ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Show chat messages." "Mostrar mensajes de charla." ::msgcat::mcset es "Show floating log." "Mostrar log (histórico) flotante." ::msgcat::mcset es "Show groupchat messages." "Mostrar mensajes de grupos de charla." ::msgcat::mcset es "Show in \"Away\" status." "Mostrar en el estado \"Ausente\"." ::msgcat::mcset es "Show in \"Do not disturb\" status." "Mostrar en el estado \"No molestar\"." ::msgcat::mcset es "Show in \"Extended away\" status." "Mostrar en el estado \"Muy Ausente\"." ::msgcat::mcset es "Show incoming message body." "Mostrar cuerpo del mensaje de entrada." ::msgcat::mcset es "Show notifications (presence state changes, chat state events, IQ queries etc)." "Mostrar notificaciones (cambios en el estado de la presencia, eventos del estado de la charla, peticiones IQ, etc)." ::msgcat::mcset es "Show only personal messages and MUC highlights." "Mostrar solo mensajes personales y resaltados de las salas de charla." ::msgcat::mcset es "Show other messages." "Mostrar otros mensajes." ::msgcat::mcset es "Show when Tkabber is active." "Mostrar cuando Tkabber está activo." ::msgcat::mcset es "Use simple view scheme." "Usar esquema de visionado simple." ::msgcat::mcset es "Window opacity (in percent)." "Opacidad de la ventana (en porcentaje)." ::msgcat::mcset es "Window position." "Posición de la ventana." ::msgcat::mcset es "Window width." "Ancho de la ventana." tkabber-plugins-0.11.1/floatinglog/msgs/de.msg0000644000175000017500000000511210710656517020566 0ustar sergeisergei # German messages file # Roger Sondermann 27.10.2007 ::msgcat::mcset de "%s request from %s" "%s-Anfrage von %s" ::msgcat::mcset de "Delay before message hide (in seconds)." "Verzgerung bevor das FloatingLog-Fenster verborgen wird (in Sekunden)." ::msgcat::mcset de "Floating Log plugin options." "Optionen fr das FloatingLog-Plugin." ::msgcat::mcset de "Floating Log window properties." "Eigenschaften des FloatingLog-Fensters." ::msgcat::mcset de "From: " "Von: " ::msgcat::mcset de "Idle for %s" "Leerlauf seit %s" ::msgcat::mcset de "Incoming message" "Eingehende Nachricht" ::msgcat::mcset de "Maximum window height." "Maximale Hhe des Fensters." ::msgcat::mcset de "Message types to show." "Anzuzeigende Nachrichten-Typen." ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "Show chat messages." "Chat-Nachrichten anzeigen." ::msgcat::mcset de "Show floating log." "FloatingLog-Fenster anzeigen." ::msgcat::mcset de "Show groupchat messages." "Konferenz-Nachrichten anzeigen." ::msgcat::mcset de "Show in \"Away\" status." "Bei Status 'Abwesend' anzeigen." ::msgcat::mcset de "Show in \"Do not disturb\" status." "Bei Status 'Bitte nicht stren' anzeigen." ::msgcat::mcset de "Show in \"Extended away\" status." "Bei Status 'Lnger abwesend' anzeigen." ::msgcat::mcset de "Show incoming message body." "Eingehenden Nachrichten-Text anzeigen." ::msgcat::mcset de "Show notifications (presence state changes, chat state events, IQ queries etc)." "Benachrichtigungen (Prsenz-Status-nderungen, Chat-Status-Ereignisse, IQ-Anfragen, etc.) anzeigen." ::msgcat::mcset de "Show only personal messages and MUC highlights." "Nur persnliche Nachrichten und markierte MUC-Nachrichten anzeigen." ::msgcat::mcset de "Show other messages." "Andere Nachrichten anzeigen." ::msgcat::mcset de "Show when Tkabber is active." "Bei aktivem Tkabber-Fenster anzeigen." ::msgcat::mcset de "Use simple view scheme." "Einfache Art der Anzeige benutzen." ::msgcat::mcset de "Window opacity (in percent)." "Transparenz des Fensters (in Prozent)." ::msgcat::mcset de "Window position." "Position des Fensters." ::msgcat::mcset de "Window width." "Breite des Fensters." tkabber-plugins-0.11.1/floatinglog/msgs/ru.msg0000644000175000017500000000550711015364576020634 0ustar sergeisergei# $Id: ru.msg 1444 2008-05-22 21:45:34Z sergei $ ::msgcat::mcset ru "%s request from %s" "Запрос %s от %s" ::msgcat::mcset ru "Delay before message hide (in seconds)." "Задержка перед тем, как сообщение исчезнет (в секундах)." ::msgcat::mcset ru "From: " "От: " ::msgcat::mcset ru "Floating Log plugin options." "Настройки расширения Плавающий журнал." ::msgcat::mcset ru "Floating Log window properties." "Свойства окна плавающего журнала." ::msgcat::mcset ru "Idle for %s" "Время бездействия: %s" ::msgcat::mcset ru "Incoming message" "Входящее сообщение" ::msgcat::mcset ru "Maximum window height." "Максимальная высота окна." ::msgcat::mcset ru "Message types to show." "Типы сообщений, которые следует показывать." ::msgcat::mcset ru "Plugins options." "Настройки расширений." ::msgcat::mcset ru "Show chat messages." "Показывать сообщения разговора." ::msgcat::mcset ru "Show floating log." "Показывать плавающий журнал." ::msgcat::mcset ru "Show groupchat messages." "Показывать групповые сообщения." ::msgcat::mcset ru "Show in \"Away\" status." "Показывать в состоянии \"Отошёл\"." ::msgcat::mcset ru "Show in \"Do not disturb\" status." "Показывать в состоянии \"Не беспокоить\"." ::msgcat::mcset ru "Show in \"Extended away\" status." "Показывать в состоянии \"Отошёл давно\"." ::msgcat::mcset ru "Show incoming message body." "Показывать текст входящих сообщений." ::msgcat::mcset ru "Show notifications (presence state changes, chat state events, IQ queries etc)." \ "Показывать уведомления (изменение присутствия, события в окне разговора, запросы и т.п.)" ::msgcat::mcset ru "Show only personal messages and MUC highlights." \ "Показывать только персональные сообщения и выделенные сообщения в конференциях." ::msgcat::mcset ru "Show other messages." "Показывать другие сообщения." ::msgcat::mcset ru "Show when Tkabber is active." "Показывать, когда окно Tkabber'а активно." ::msgcat::mcset ru "Use simple view scheme." "Использовать упрощенный вывод сообщений." ::msgcat::mcset ru "Window position." "Положение окна." ::msgcat::mcset ru "Window opacity (in percent)." "Непрозрачность окна (в процентах)." ::msgcat::mcset ru "Window width." "Ширина окна." tkabber-plugins-0.11.1/floatinglog/TODO0000644000175000017500000000032510702074341017174 0ustar sergeisergeiDo not show messages from set_status hook but get all of them from other hooks Open chat window on left click on message Log grows up or down depends on position Do not show messages for selected groups in roster tkabber-plugins-0.11.1/floatinglog/floatinglog.tcl0000644000175000017500000002606210743470503021530 0ustar sergeisergei# $Id: floatinglog.tcl 1348 2008-01-16 21:04:03Z sergei $ package require msgcat namespace eval floatinglog { ::msgcat::mcload [file join [file dirname [info script]] msgs] variable id 0 variable winname .floatinglog variable idlepat [string map {%s *} [::msgcat::mc "Idle for %s"]] set request_from [string map {%s *} [::msgcat::mc "%s request from %s"]] variable iqibbpat [string replace $request_from \ [string first * $request_from] \ [string first * $request_from] iqibb] variable ibbpat [string replace $request_from \ [string first * $request_from] \ [string first * $request_from] ibb] # # Options section # custom::defgroup Plugins [::msgcat::mc "Plugins options."] \ -group Tkabber custom::defgroup {Floating Log} \ [::msgcat::mc "Floating Log plugin options."] \ -group Plugins custom::defgroup {Floating Log Window} \ [::msgcat::mc "Floating Log window properties."] \ -group {Floating Log} custom::defgroup {Floating Log Control} \ [::msgcat::mc "Message types to show."] \ -group {Floating Log} custom::defvar options(show_log) 0 \ [::msgcat::mc "Show floating log."] \ -type boolean -group {Floating Log} custom::defvar options(show_chat) 1 \ [::msgcat::mc "Show chat messages."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_groupchat) 1 \ [::msgcat::mc "Show groupchat messages."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_other_messages) 1 \ [::msgcat::mc "Show other messages."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_only_personal) 0 \ [::msgcat::mc "Show only personal messages and MUC highlights."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_notifications) 1 \ [::msgcat::mc "Show notifications (presence state changes,\ chat state events, IQ queries etc)."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_when_tkabber_is_active) 0 \ [::msgcat::mc "Show when Tkabber is active."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_on_away_status) 1 \ [::msgcat::mc "Show in \"Away\" status."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_on_xa_status) 1 \ [::msgcat::mc "Show in \"Extended away\" status."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_on_dnd_status) 0 \ [::msgcat::mc "Show in \"Do not disturb\" status."] \ -type boolean -group {Floating Log Control} custom::defvar options(show_message_body) 1 \ [::msgcat::mc "Show incoming message body."] \ -type boolean -group {Floating Log Control} custom::defvar options(simple_show_scheme) 0 \ [::msgcat::mc "Use simple view scheme."] \ -type boolean -group {Floating Log Window} custom::defvar options(alpha) 80 \ [::msgcat::mc "Window opacity (in percent)."] \ -command [list [namespace current]::set_window] \ -type integer -group {Floating Log Window} custom::defvar options(position) "-0-60" \ [::msgcat::mc "Window position."] \ -command [list [namespace current]::set_window] \ -type string -group {Floating Log Window} custom::defvar options(max_height) 700 \ [::msgcat::mc "Maximum window height."] \ -command [list [namespace current]::set_window] \ -type integer -group {Floating Log Window} custom::defvar options(width) 300 \ [::msgcat::mc "Window width."] \ -command [list [namespace current]::set_window] \ -type integer -group {Floating Log Window} custom::defvar options(livetime) 5 \ [::msgcat::mc "Delay before message hide (in seconds)."] \ -type integer -group {Floating Log} } # # Floating window initialization # proc floatinglog::window_initialization {} { variable options variable winname toplevel $winname -bd 0 -class Balloon if {$::tcl_platform(platform) == "macintosh"} { catch {unsupported1 style $winname floating sideTitlebar} } elseif {$::aquaP} { ::tk::unsupported::MacWindowStyle style $winname help none } else { wm transient $winname . wm overrideredirect $winname 1 } catch { if {[lsearch -exact [wm attributes $winname] -topmost] >= 0} { wm attributes $winname -topmost 1 } } set_window bind $winname [list wm withdraw $winname] bind $winname [namespace current]::left_double_click hook::add set_status_hook [namespace current]::process_status hook::add process_message_hook [namespace current]::process_message wm withdraw $winname } proc floatinglog::left_double_click {} { ::ifacetk::systray::restore if {[focus] == ""} { focus -force . } } proc floatinglog::left_double_click_message {connid jid type} { switch -- $type { groupchat { } chat { chat::open_to_user $connid $jid } message { #message::send_dialog -to $jid } } } proc floatinglog::add_text {text {from ""} {connid ""} {type ""} \ {is_subject ""} {subject ""}} { variable options variable id variable winname variable logfileId if {!($options(show_log))} {return} set active_window "" set active_window [focus] if {$active_window != "" && !$options(show_when_tkabber_is_active)} return if {!$options(show_on_away_status) && $::curuserstatus == "away"} return if {!$options(show_on_xa_status) && $::curuserstatus == "xa"} return if {!$options(show_on_dnd_status) && $::curuserstatus == "dnd"} return incr id if {$options(simple_show_scheme)} { add_text_scheme_simple $text $from $connid $type $is_subject $subject } else { add_text_scheme_01 $text $from $connid $type $is_subject $subject } wm deiconify $winname raise $winname set_window } proc floatinglog::add_text_scheme_simple {body from connid type is_subject subject} { variable options variable id variable winname variable logfileId if { $from != "" } { if {[catch {::chat::get_nick $connid $from $type} nick]} { set nick [chat::get_nick $from $type] } if {!$options(show_message_body)} { set body [::msgcat::mc "Incoming message"] } set text [::msgcat::mc "From: "] set formattext [append text $nick " (" $from ")\n" "\n" $body] } else { set text $body } if {$text != ""} { set message_name $winname.msg$id message $message_name \ -text $text \ -width [expr $options(width) - 10] \ -justify left \ -relief solid -bd 1 -padx 3 -pady 3 set first_message [lindex [pack slaves $winname] 0] if {$first_message == ""} { pack $message_name -side bottom -fill x -padx 2 -pady 2 } else { pack $message_name -before $first_message \ -side bottom -fill x -padx 2 -pady 2 } if {($connid != "") && ($from != "") && ($type != "")} { bind $message_name \ +[list [namespace current]::left_double_click_message \ $connid [double% $from] [double% $type]] } after [expr {$options(livetime) * 1000}] \ [namespace current]::del_text "$message_name" } } proc floatinglog::add_text_scheme_01 {text from connid type is_subject subject} { variable options variable id variable winname variable logfileId if {$text != ""} { if { ! $options(show_message_body) && $from != "" } { set text [::msgcat::mc "Incoming message"] } set message_name $winname.msg$id message $message_name \ -text $text \ -width [expr $options(width) - 10] \ -justify left \ -relief solid -bd 1 -padx 3 -pady 3 } if {$from != ""} { if {[catch {::chat::get_nick $connid $from $type} nick]} { set nick [chat::get_nick $from $type] } if {$nick != "" } { append nick " (" $from ")" } else { set nick $from } set message_name_head $winname.msg${id}head message $message_name_head \ -text $nick \ -width [expr $options(width) - 10] \ -justify left \ -relief flat -bd 1 -padx 0 -pady 0 } set first_message [lindex [pack slaves $winname] 0] if {$first_message == ""} { if {$text != ""} { pack $message_name -side bottom -fill x -padx 2 -pady 2 } if {$from != ""} { pack $message_name_head -side bottom -fill x -padx 2 -pady 0 } } else { if {$text != ""} { pack $message_name -before $first_message \ -side bottom -fill x -padx 2 -pady 2 } if {$from != ""} { pack $message_name_head -before $first_message \ -side bottom -fill x -padx 2 -pady 0 } } if {($connid != "") && ($from != "") && ($type != "")} { if {$from != ""} { bind $message_name_head \ +[list [namespace current]::left_double_click_message \ $connid [double% $from] [double% $type]] } if {$text != "" } { bind $message_name \ +[list [namespace current]::left_double_click_message \ $connid [double% $from] [double% $type]] } } if {$text != ""} { after [expr {$options(livetime) * 1000}] \ [namespace current]::del_text "$message_name" } } proc floatinglog::process_status {text} { variable idlepat variable iqibbpat variable ibbpat variable options if {!$options(show_notifications)} return if {[string match $idlepat $text]} return if {[string match $iqibbpat $text]} return if {[string match $ibbpat $text]} return add_text $text } proc floatinglog::del_text {{msg ""}} { variable winname if {[winfo exists $msg]} { pack forget $msg destroy $msg } append msg head if {[winfo exists $msg]} { pack forget $msg destroy $msg } if {[winfo children $winname] == ""} { wm withdraw $winname } } proc floatinglog::process_message {connid from id type is_subject \ subject body err thread priority x} { variable options if {$body != ""} { switch -exact -- $type { chat { if {!$options(show_chat)} return } groupchat { if {!$options(show_groupchat)} return if {[is_delayed $x]} return if {![catch { ::plugins::mucignore::is_ignored $connid $from $type } ignore] && $ignore != ""} return if {$options(show_only_personal)} { set chatid [chat::chatid $connid \ [node_and_server_from_jid $from]] set myjid [chat::our_jid $chatid] set mynick [chat::get_nick $connid $myjid $type] if {![check_message $mynick $body]} return } } default { if {!$options(show_other_messages)} return } } catch { add_text $body $from $connid $type $is_subject $subject } } } proc floatinglog::is_delayed {xml} { foreach xelem $xml { ::jlib::wrapper:splitxml $xelem tag vars isempty chdata children switch -- [::jlib::wrapper:getattr $vars xmlns] { urn:xmpp:delay - jabber:x:delay { return 1 } } } return 0 } proc floatinglog::set_window {args} { variable options variable winname catch { if {[lsearch -exact [wm attributes $winname] -alpha] >= 0} { wm attributes $winname -alpha [expr $options(alpha) / 100.0] } } wm minsize $winname $options(width) 10 wm maxsize $winname $options(width) $options(max_height) wm geometry $winname $options(position) } hook::add finload_hook \ [namespace current]::floatinglog::window_initialization 200 # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/floatinglog/license.terms0000644000175000017500000000207210701671531021206 0ustar sergeisergeiCopyright (c) 2007 Rakhmanin Ruslan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/floatinglog/INSTALL0000644000175000017500000000050210701671531017535 0ustar sergeisergeiCopy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/floatinglog/ ~/.tkabber/plugins/floatinglog/floatinglog.tcl Restart Tkabber, to get the plugin loaded. Set option Tkabber -> Plugins -> FloatingLog -> show_log to enable plugin. tkabber-plugins-0.11.1/floatinglog/AUTHORS0000644000175000017500000000013610701671531017557 0ustar sergeisergeiRakhmanin Ruslan Thanks to Konstantin Khomoutov for is_delayed function. tkabber-plugins-0.11.1/floatinglog/VERSION0000644000175000017500000000004210701671531017553 0ustar sergeisergeiVersion: 0.4 Date: 2007-August-26 tkabber-plugins-0.11.1/floatinglog/ChangeLog0000644000175000017500000000235410701671531020265 0ustar sergeisergeiVersion 0.4 2007-08-26 Rakhmanin Ruslan * Double click on FloatingLog opens Tkabber window * You can off incoming message body show (it will show "Incoming message" string). Option "show_message_body". Default is on. * New default scheme of incoming message view. You can use old (simple) scheme by checking "simple_show_scheme" option. * Some bags fixed Version 0.3.1 2007-06-28 Rakhmanin Ruslan * You can off FloatingLog in away, xa, dnd status * You can choose if FloatingLog will show messages on active Tkabber window Version 0.3 2007-06-28 Rakhmanin Ruslan * Hide FloatingLog window on rigth button mouse click * Do not show messages on active Tkabber window * Use default colors from Tkabber for FloatingLog window Version 0.2 2007-06-06 Rakhmanin Ruslan * Do not show history messages from groupchat (on connecting to groupchat). * Do not show idle messages. * Options for on/off messages from chat, groupchat, other messages. Version 0.1 2007-06-03 Rakhmanin Ruslan * Initial version (0.1). For test only. * Show incoming messages and status messages in popup window tkabber-plugins-0.11.1/checkers/0000755000175000017500000000000011076120366015772 5ustar sergeisergeitkabber-plugins-0.11.1/checkers/README0000644000175000017500000000072010563364101016646 0ustar sergeisergeiCheckers Plugin for Tkabber Installation: Just put all checkers directory to $HOME/.tkabber/plugins (on UNIX), to %APPDATA%\Tkabber\plugins (on Windows), or to $HOME/Library/Application Support/Tkabber (on MacOS X) directory. Then after Tkabber restart new submenu "Games" with "Checkers" option will appear in roster user context menu. Checkers rules included in distribution are taken from http://ourworld.compuserve.com/homepages/Arthur_H_Olsen/checkers.htm tkabber-plugins-0.11.1/checkers/msgs/0000755000175000017500000000000011076120366016743 5ustar sergeisergeitkabber-plugins-0.11.1/checkers/msgs/pl.msg0000644000175000017500000001104710667535014020076 0ustar sergeisergei# Polish messages file for checkers plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Straight checkers (English draughts)" "Warcaby angielskie" ::msgcat::mcset pl "Brazilian checkers" "Warcaby brazylijskie" ::msgcat::mcset pl "Russian checkers" "Warcaby rosyjskie" ::msgcat::mcset pl "Pool checkers" "Warcaby tradycyjne" ::msgcat::mcset pl "Spanish checkers" "Warcaby hiszpańskie" ::msgcat::mcset pl "Italian checkers" "Warcaby włoskie" ::msgcat::mcset pl "Straight checkers" "Warcaby klasyczne" ::msgcat::mcset pl "Checkers plugin options." "Ustawienia wtyczki do gry w warcaby." ::msgcat::mcset pl "Checkers figures theme." "Motyw graficzny bierek." ::msgcat::mcset pl "Default game variant." "Domyślny wariant gry." ::msgcat::mcset pl "Flip board view when playing black (Russian, Spanish, Italian) or white (Straight, Pool, Brazilian) by default." "Odwróć widok warcabnicy podczas gry czarnymi (warcaby rosyjskie, hiszpańskie, włoskie) lub białymi (tradycyjne, klasyczne, brazylijskie)." ::msgcat::mcset pl "Checkers Invitation" "Zaproszenie do gry w warcaby" ::msgcat::mcset pl "Sending checkers game invitation to %s (%s)" "Wysyłanie zaproszenia do gry w warcaby do %s (%s)" ::msgcat::mcset pl "%s (%s) has refused checkers invitation: %s" "%s (%s) odrzuca zaproszenie do gry w warcaby: %s" ::msgcat::mcset pl "Checkers Invitation from %s" "Zaproszenie do gry w warcaby od %s" ::msgcat::mcset pl "Checkers game invitation from %s (%s) is received." "Otrzymano zaproszenie do gry w warcaby od %s (%s)." ::msgcat::mcset pl "%s wants play %s." "%s wybrał %s." ::msgcat::mcset pl "%s wants play white." "%s chce grać białymi." ::msgcat::mcset pl "%s wants play black." "%s chce grać czarnymi." ::msgcat::mcset pl "%s with %s" "%s: %s" ::msgcat::mcset pl "You win" "Twoja wygrana" ::msgcat::mcset pl "Opponent wins" "Wygrana przeciwnika" ::msgcat::mcset pl "\n\n Opponent rejected move:\n %s\n\n" "\n\n Przeciwnik odrzucił ruch:\n %s\n\n" ::msgcat::mcset pl "Checkers..." "Warcaby..." ::msgcat::mcset pl "White" "Białe" ::msgcat::mcset pl "Move: " "Ruch: " ::msgcat::mcset pl "History" "Historia" ::msgcat::mcset pl "Black" "Czarne" ::msgcat::mcset pl "Show last move by default." "Pokazuj ostatni ruch." ::msgcat::mcset pl "Show tooltips with short instructions." "Pokazuj dymki podpowiedzi z krótkimi instrukcjami." ::msgcat::mcset pl "Allow illegal moves (useful for debugging)." "Pozwalaj na nieprawidłowe ruchy (użyteczne przy debugowaniu)." ::msgcat::mcset pl "Accept opponent illegal moves (useful for debugging)." "Pozwalaj na nieprawidłowe ruchy przeciwnika (użyteczne przy debugowaniu)." ::msgcat::mcset pl "I want play white" "Chcę grać białymi" ::msgcat::mcset pl "I want play black" "Chcę grać czarnymi" ::msgcat::mcset pl "Cancel invitation" "Anuluj zaproszenie" ::msgcat::mcset pl "Agree to play" "Przyjmij zaproszenie" ::msgcat::mcset pl "Refuse to play" "Odrzuć zaproszenie" ::msgcat::mcset pl " (You)" " (Ty)" ::msgcat::mcset pl " (Opponent)" " (Przeciwnik)" ::msgcat::mcset pl "You win (Opponent resigned)" "Wygałeś (przeciwnik zrezygnował)" ::msgcat::mcset pl "Draw (Opponent accepted)" "Remis (za zgodą przeciwnika)" ::msgcat::mcset pl "Show last move" "Pokaż ostatni ruch" ::msgcat::mcset pl "Flip view" "Odwróć widok" ::msgcat::mcset pl "Propose a draw" "Zaproponuj remis" ::msgcat::mcset pl "Accept the draw proposal" "Zaakceptuj remis" ::msgcat::mcset pl "Resign the game" "Zrezygnuj z gry" ::msgcat::mcset pl "Press button and make move if you want propose draw" "Naciśnij przycisk i wykonaj ruch jeżeli chcesz zaproponować remis" ::msgcat::mcset pl "Press button if you want accept the draw proposal" "Naciśnij przycisk jeżeli chcesz zaakceptować propozycję remisu" ::msgcat::mcset pl "Press button if you want resign" "Naciśnij przycisk jeżeli chcesz zrezygnować z gry" ::msgcat::mcset pl "\n\n Opponent proposes a draw\n\n" "\n\n Przeciwnik proponuje remis\n\n" ::msgcat::mcset pl "Draw (You accepted)" "Remis (Za moją zgodą)" ::msgcat::mcset pl "Opponent wins (You resigned)" "Wygrał przeciwnik (Zrezygnowałeś z gry)" ::msgcat::mcset pl "Games" "Gry planszowe" ::msgcat::mcset pl "Sound to play after opponent's turn" "Odtwórz dźwięk po ruchu przeciwnika" ::msgcat::mcset pl "%s wants play white." "%s chce grać białymi." ::msgcat::mcset pl "%s wants play black." "%s chce grać czarnymi." ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "\n\n Opponent rejected move:\n %s\n\n" "\n\n Przeciwnik odrzucił ruch:\n %s\n\n" tkabber-plugins-0.11.1/checkers/msgs/es.msg0000644000175000017500000001020310545463157020066 0ustar sergeisergei::msgcat::mcset es " (Opponent)" " (Oponente)" ::msgcat::mcset es " (You)" " (Tu)" ::msgcat::mcset es "%s (%s) has refused checkers invitation: %s" "%s (%s) ha rechazado la invitación: %s" ::msgcat::mcset es "%s wants play %s." "%s quiere jugar %s." ::msgcat::mcset es "%s wants play black." "%s quiere jugar con las negras." ::msgcat::mcset es "%s wants play white." "%s quiere jugar con las blancas." ::msgcat::mcset es "%s with %s" "%s con %s" ::msgcat::mcset es "Accept opponent illegal moves (useful for debugging)." "Aceptar movimientos ilegales del oponente (útil para depuración)." ::msgcat::mcset es "Accept the draw proposal" "Aceptar la propuesta de empate" ::msgcat::mcset es "Agree to play" "Aceptar la invitación" ::msgcat::mcset es "Allow illegal moves (useful for debugging)." "Permitir movimientos ilegales (útil para depuración)." ::msgcat::mcset es "Black" "Negra" ::msgcat::mcset es "Brazilian checkers" "Damas brasileñas" ::msgcat::mcset es "Cancel invitation" "Cancelar la invitación" ::msgcat::mcset es "Checkers Invitation from %s" "Invitación a las Damas de %s" ::msgcat::mcset es "Checkers Invitation" "Invitación a las Damas" ::msgcat::mcset es "Checkers figures theme." "Tipo de figuras." ::msgcat::mcset es "Checkers game invitation from %s (%s) is received." "Se ha recibido una invitación de %s (%s) para jugar a las damas." ::msgcat::mcset es "Checkers plugin options." "Opciones del plugin de las Damas." ::msgcat::mcset es "Checkers..." "Damas..." ::msgcat::mcset es "Default game variant." "Variante del juego por defecto." ::msgcat::mcset es "Draw (Opponent accepted)" "Empate (el oponente aceptó)" ::msgcat::mcset es "Draw (You accepted)" "Empate (aceptaste)" ::msgcat::mcset es "Flip board view when playing black (Russian, Spanish, Italian) or white (Straight, Pool, Brazilian) by default." "Rotar por defecto el tablero si juegas con las negras (rusas, españolas, italianas) o las blancas (Straight, Pool, brasileñas)." ::msgcat::mcset es "Flip view" "Rotar tablero" ::msgcat::mcset es "Games" "Juegos" ::msgcat::mcset es "History" "Historia" ::msgcat::mcset es "I want play black" "Quiero jugar con las negras" ::msgcat::mcset es "I want play white" "Quiero jugar con las blancas" ::msgcat::mcset es "Italian checkers" "Damas italianas" ::msgcat::mcset es "Move: " "Movimiento: " ::msgcat::mcset es "Opponent wins (You resigned)" "El oponente gana (te rendiste)" ::msgcat::mcset es "Opponent wins" "El oponente gana" ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Pool checkers" "Damas Pool" ::msgcat::mcset es "Press button and make move if you want propose draw" "Pulsa el botón y haz un movimiento si quieres proponer un empate" ::msgcat::mcset es "Press button if you want accept the draw proposal" "Pulsa el botón si quieres aceptar la propuesta de empate" ::msgcat::mcset es "Press button if you want resign" "Pulsa el botón si quieres rendirte" ::msgcat::mcset es "Propose a draw" "Proponer un empate" ::msgcat::mcset es "Refuse to play" "Rechazar la invitación" ::msgcat::mcset es "Resign the game" "Rendirte" ::msgcat::mcset es "Russian checkers" "Damas rusas" ::msgcat::mcset es "Sending checkers game invitation to %s (%s)" "Enviando invitación para jugar a las damas a %s (%s)" ::msgcat::mcset es "Show last move by default." "Mostrar el último movimiento por defecto." ::msgcat::mcset es "Show last move" "Mostrar el último movimiento" ::msgcat::mcset es "Show tooltips with short instructions." "Mostrar pequeñas instrucciones de ayuda." ::msgcat::mcset es "Sound to play after opponent's turn" "Sonido a reproducir cuando el oponente haya movido" ::msgcat::mcset es "Spanish checkers" "Damas españolas" ::msgcat::mcset es "Straight checkers (English draughts)" "Damas Straight (inglesas)" ::msgcat::mcset es "Straight checkers" "Damas Straight" ::msgcat::mcset es "White" "Blanca" ::msgcat::mcset es "You win (Opponent resigned)" "Tu ganas (el oponente se rindió)" ::msgcat::mcset es "You win" "Tu ganas" ::msgcat::mcset es "\n\n Opponent proposes a draw\n\n" "\n\n El oponente propone un empate \n\n" ::msgcat::mcset es "\n\n Opponent rejected move:\n %s\n\n" "\n\n El oponente rechazó el movimiento:\n %s\n\n" tkabber-plugins-0.11.1/checkers/msgs/ru.msg0000644000175000017500000001232110512234573020100 0ustar sergeisergei ::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Show last move by default." "По умолчанию показывать последний ход." ::msgcat::mcset ru " (You)" " (Вы)" ::msgcat::mcset ru " (Opponent)" " (Оппонент)" ::msgcat::mcset ru "Flip view" "Развернуть доску" ::msgcat::mcset ru "Checkers plugin options." "Параметры расширения Шашки." ::msgcat::mcset ru "Checkers figures theme." "Внешний вид шашек." ::msgcat::mcset ru "Show tooltips with short instructions." "Показывать всплывающие подсказки к элементам интерфейса." ::msgcat::mcset ru "Allow illegal moves (useful for debugging)." "Разрешать неправильные ходы (используется при отладке)." ::msgcat::mcset ru "Accept opponent illegal moves (useful for debugging)." "Принимать неправильные ходы от оппонента (используется при отладке)." ::msgcat::mcset ru "Checkers Invitation" "Приглашение сыграть в шашки" ::msgcat::mcset ru "Sending checkers game invitation to %s (%s)" "Посылаем приглашение сыграть в шашки с %s (%s)" ::msgcat::mcset ru "I want play white" "Хочу играть белыми" ::msgcat::mcset ru "I want play black" "Хочу играть чёрными" ::msgcat::mcset ru "Cancel invitation" "Отменить приглашение" ::msgcat::mcset ru "%s (%s) has refused checkers invitation: %s" "%s (%s) отказался играть в шашки: %s" ::msgcat::mcset ru "Checkers Invitation from %s" "Приглашение сыграть в шашки с %s" ::msgcat::mcset ru "Checkers game invitation from %s (%s) is received." "Получено приглашение сыграть в шашки с %s (%s)" ::msgcat::mcset ru "%s wants play white." "%s хочет играть белыми" ::msgcat::mcset ru "%s wants play black." "%s хочет играть чёрными" ::msgcat::mcset ru "Agree to play" "Согласиться играть" ::msgcat::mcset ru "Refuse to play" "Отказаться играть" ::msgcat::mcset ru "Show last move" "Показывать последний ход" ::msgcat::mcset ru "Move: " "Ход: " ::msgcat::mcset ru "Propose a draw" "Предложить ничью" ::msgcat::mcset ru "Accept the draw proposal" "Принять предложенную ничью" ::msgcat::mcset ru "Resign the game" "Сдать партию" ::msgcat::mcset ru "History" "Запись партии" ::msgcat::mcset ru "Checkers..." "Шашки..." ::msgcat::mcset ru "White" "Белые" ::msgcat::mcset ru "Black" "Чёрные" ::msgcat::mcset ru "Opponent wins" "Оппонент выиграл" ::msgcat::mcset ru "You win" "Вы выиграли" ::msgcat::mcset ru "Opponent wins (You resigned)" "Оппонент выиграл (Вы сдались)" ::msgcat::mcset ru "You win (Opponent resigned)" "Вы выиграли (Оппонент сдался)" ::msgcat::mcset ru "Draw (You accepted)" "Ничья (Вы приняли)" ::msgcat::mcset ru "Draw (Opponent accepted)" "Ничья (Оппонент принял)" ::msgcat::mcset ru "Press button and make move if you want propose draw" "Нажмите кнопку и сделайте ход, если хотите предложить ничью" ::msgcat::mcset ru "Press button if you want accept the draw proposal" "Нажмите кнопку, если хотите принять предложенную ничью" ::msgcat::mcset ru "Press button if you want resign" "Нажмите кнопку, если хотите сдаться" ::msgcat::mcset ru "\n\n Opponent proposes a draw\n\n" "\n\n Оппонент предлагает ничью\n\n" ::msgcat::mcset ru "\n\n Opponent rejected move:\n %s\n\n" "\n\n Оппонент отверг ход:\n %s\n\n" ::msgcat::mcset ru "Games" "Игры" ::msgcat::mcset ru "Straight checkers (English draughts)" "Чекерс (английские шашки)" ::msgcat::mcset ru "Russian checkers" "Русские шашки" ::msgcat::mcset ru "Pool checkers" "Пул-чекерс" ::msgcat::mcset ru "Spanish checkers" "Испанские шашки" ::msgcat::mcset ru "Italian checkers" "Итальянские шашки" ::msgcat::mcset ru "Straight checkers" "Чекерс" ::msgcat::mcset ru "Brazilian checkers" "Бразильские шашки" ::msgcat::mcset ru "Default game variant." "Вариант игры в шашки по умолчанию." ::msgcat::mcset ru "Flip board view when playing black (Russian, Spanish, Italian) or white (Straight, Pool, Brazilian) by default." "Разворачивать доску по умолчанию при игре чёрными (русские, испанские, итальянские шашки) или белыми (чекерс, пул-чекерс, бразильские шашки)." ::msgcat::mcset ru "%s wants play %s." "%s хочет играть в %s" ::msgcat::mcset ru "%s with %s" "%s с %s" ::msgcat::mcset ru "Sound to play after opponent's turn" "Звук, который проигрывается после хода оппонента" tkabber-plugins-0.11.1/checkers/msgs/uk.msg0000644000175000017500000001234510543571750020104 0ustar sergeisergei ::msgcat::mcset uk "Plugins options." "Параметри плагінів." ::msgcat::mcset uk "Show last move by default." "Показувати останній хід за замовчуванням." ::msgcat::mcset uk " (You)" " (Ви)" ::msgcat::mcset uk " (Opponent)" " (Опонент)" ::msgcat::mcset uk "Flip view" "Розгорнути дошку" ::msgcat::mcset uk "Checkers plugin options." "Параметри плагіна Шашки." ::msgcat::mcset uk "Checkers figures theme." "Зовнішній вигляд шашок." ::msgcat::mcset uk "Show tooltips with short instructions." "Показувати спливаючі підказки до елементів інтерфейсу." ::msgcat::mcset uk "Allow illegal moves (useful for debugging)." "Дозволяти неправильні ходи (використовується при налагодженні)." ::msgcat::mcset uk "Accept opponent illegal moves (useful for debugging)." "Приймати неправильні ходи від опонента (використовується при налагодженні)." ::msgcat::mcset uk "Checkers Invitation" "Запрошення зіграти в шашки" ::msgcat::mcset uk "Sending checkers game invitation to %s (%s)" "Відсилається запрошення зіграти в шашки з %s (%s)" ::msgcat::mcset uk "I want play white" "Хочу грати білими" ::msgcat::mcset uk "I want play black" "Хочу грати чорними" ::msgcat::mcset uk "Cancel invitation" "Скасувати запрошення" ::msgcat::mcset uk "%s (%s) has refused checkers invitation: %s" "%s (%s) відмовився грати в шашки: %s" ::msgcat::mcset uk "Checkers Invitation from %s" "Запрошення зіграти в шашки з %s" ::msgcat::mcset uk "Checkers game invitation from %s (%s) is received." "Отримано запрошення зіграти в шашки з %s (%s)" ::msgcat::mcset uk "%s wants play white." " %s хоче грати білими" ::msgcat::mcset uk "%s wants play black." " %s хоче грати чорними" ::msgcat::mcset uk "Agree to play" "Погодитися грати" ::msgcat::mcset uk "Refuse to play" "Відмовитися грати" ::msgcat::mcset uk "Show last move" "Показувати останній хід" ::msgcat::mcset uk "Move: " "Хід: " ::msgcat::mcset uk "Propose a draw" "Запропонувати нічию" ::msgcat::mcset uk "Accept the draw proposal" "Прийняти запропоновану нічию" ::msgcat::mcset uk "Resign the game" "Здати партію" ::msgcat::mcset uk "History" "Запис партії" ::msgcat::mcset uk "Checkers..." "Шашки..." ::msgcat::mcset uk "White" "Білі" ::msgcat::mcset uk "Black" "Чорні" ::msgcat::mcset uk "Opponent wins" "Опонент виграв" ::msgcat::mcset uk "You win" "Ви виграли" ::msgcat::mcset uk "Opponent wins (You resigned)" "Опонент виграв (Ви здалися)" ::msgcat::mcset uk "You win (Opponent resigned)" "Ви виграли (Опонент здався)" ::msgcat::mcset uk "Draw" "Нічия" ::msgcat::mcset uk "Draw (You accepted)" "Нічия (Ви прийняли)" ::msgcat::mcset uk "Draw (Opponent accepted)" "Нічия (Опонент прийняв)" ::msgcat::mcset uk "Press button and make move if you want propose draw" "Натисніть кнопку й зробіть хід, якщо хочете запропонувати нічию" ::msgcat::mcset uk "Press button if you want accept the draw proposal" "Натисніть кнопку, якщо хочете прийняти запропоновану нічию" ::msgcat::mcset uk "Press button if you want resign" "Натисніть кнопку, якщо хочете здатися" ::msgcat::mcset uk "\n\n Opponent proposes a draw\n\n" "\n\n Опонент пропонує нічию\n\n" ::msgcat::mcset uk "\n\n Opponent rejected move:\n %s\n\n" "\n\n Опонент відкинув хід:\n %s\n\n" ::msgcat::mcset uk "Games" "Ігри" ::msgcat::mcset uk "Straight checkers (English draughts)" "Чекерс (англійські шашки)" ::msgcat::mcset uk "Russian checkers" "Російські шашки" ::msgcat::mcset uk "Pool checkers" "Пул-чекерс" ::msgcat::mcset uk "Brazilian checkers" "Бразильські шашки" ::msgcat::mcset uk "Spanish checkers" "Іспанські шашки" ::msgcat::mcset uk "Italian checkers" "Італійські шашки" ::msgcat::mcset uk "Straight checkers" "Чекерс" ::msgcat::mcset uk "Default game variant." "Варіант гри в шашки за замовчуванням." ::msgcat::mcset uk "Flip board view when playing black (Russian, Spanish, Italian) or white (Straight, Pool) by default." "Розвертати дошку за замовчуванням при грі чорними (російські, іспанські, італійські шашки) або білими (чекерс, пул-чекерс)." ::msgcat::mcset uk "%s wants play %s." " %s хоче грати в %s" ::msgcat::mcset uk "%s with %s" "%s з %s" ::msgcat::mcset uk "Sound to play after opponent's turn" "Звук, який буде програватися після ходу опонента" tkabber-plugins-0.11.1/checkers/msgs/nl.msg0000644000175000017500000001023410277726732020077 0ustar sergeisergei# Dutch messages file # Author: Sander Devrieze s.devrieze@pandora.be # Please notify me of errors or incoherencies. ::msgcat::mcset nl "Straight checkers (English draughts)" "Engels dammen" ::msgcat::mcset nl "Russian checkers" "Russisch dammen" ::msgcat::mcset nl "Pool checkers" "Pools dammen" ::msgcat::mcset nl "Brazilian checkers" "Braziliaans dammen" ::msgcat::mcset nl "Spanish checkers" "Spaans dammen" ::msgcat::mcset nl "Italian checkers" "Italiaans dammen" ::msgcat::mcset nl "Straight checkers" "Engels dammen" ::msgcat::mcset nl "Plugins options." "Pluginopties." ::msgcat::mcset nl "Checkers plugin options." "Pluginopties voor dammen." ::msgcat::mcset nl "Checkers figures theme." "Thema voor afbeeldingen van stenen." ::msgcat::mcset nl "Default game variant." "Standaard spel." ::msgcat::mcset nl "Flip board view when playing black (Russian, Spanish, Italian) or white (Straight, Pool, Brazilian) by default." "Het speelbord standaard omkeren bij het spelen met zwart (Russisch, Spaans, Italiaans) of wit (Engels, Pools, Braziliaans)." ::msgcat::mcset nl "Show last move by default." "Laatste zet standaard laten zien." ::msgcat::mcset nl "Show tooltips with short instructions." "Tekstballonnen met korte instructies laten zien." ::msgcat::mcset nl "Allow illegal moves (useful for debugging)." "Niet-toegelaten zetten toestaan (bruikbaar voor debuggen)." ::msgcat::mcset nl "Accept opponent illegal moves (useful for debugging)." "Niet-toegelaten zetten van tegenstander accepteren (bruikbaar voor debuggen)." ::msgcat::mcset nl "Checkers Invitation" "Uitnodiging voor een damspel" ::msgcat::mcset nl "Sending checkers game invitation to %s (%s)" "Bezig met verzenden van uitnodiging voor een damspel naar %s (%s)" ::msgcat::mcset nl "I want play white" "Ik wil met wit spelen" ::msgcat::mcset nl "I want play black" "Ik wil met zwart spelen" ::msgcat::mcset nl "Cancel invitation" "Uitnodiging annuleren" ::msgcat::mcset nl "%s (%s) has refused checkers invitation: %s" "%s (%s) ging niet in op de uitnodiging om met hem te dammen: %s" ::msgcat::mcset nl "Checkers Invitation from %s" "Uitnodiging voor een damspel met %s" ::msgcat::mcset nl "Checkers game invitation from %s (%s) is received." "Uitnodiging voor een damspel met %s (%s) werd ontvangen." ::msgcat::mcset nl "%s wants play %s." "%s wil %s spelen." ::msgcat::mcset nl "%s wants play %s." "%s wil spelen met %s." ::msgcat::mcset nl "Agree to play" "Spelen" ::msgcat::mcset nl "Refuse to play" "Niet spelen" ::msgcat::mcset nl "White" "Wit" ::msgcat::mcset nl "Black" "Zwart" ::msgcat::mcset nl " (You)" "(Jij)" ::msgcat::mcset nl " (Opponent)" "(Tegenstander)" ::msgcat::mcset nl "You win (Opponent resigned)" "Jij hebt gewonnen (de tegenstander gaf het op)" ::msgcat::mcset nl "Draw (Opponent accepted)" "Gelijkspel (de tegenstander accepteerde de uitslag)" ::msgcat::mcset nl "%s with %s" "%s met %s" ::msgcat::mcset nl "Show last move" "Laatste zet laten zien" ::msgcat::mcset nl "Flip view" "Beeld omkeren" ::msgcat::mcset nl "Move: " "Zet: " ::msgcat::mcset nl "Propose a draw" "Gelijkspel voorstellen" ::msgcat::mcset nl "Accept the draw proposal" "Het voorstel voor gelijkspel accepteren" ::msgcat::mcset nl "Resign the game" "Geef het op" ::msgcat::mcset nl "History" "Geschiedenis" ::msgcat::mcset nl "Press button and make move if you want propose draw" "Druk op de knop en doe een zet als je gelijkspel wilt voorstellen" ::msgcat::mcset nl "Press button if you want accept the draw proposal" "Druk op de knop als je het voorstel voor gelijkspel wilt accepteren" ::msgcat::mcset nl "Press button if you want resign" "Druk op de knop als je wilt opgeven" ::msgcat::mcset nl "\n\n Opponent proposes a draw\n\n" "\n\n De tegenstander stelt een gelijkspel voor\n\n" ::msgcat::mcset nl "You win" "Jij hebt gewonnen" ::msgcat::mcset nl "Opponent wins" "De tegenstander heeft gewonnen" ::msgcat::mcset nl "Draw (You accepted)" "Gelijkspel (jij accepteerde de uitslag)" ::msgcat::mcset nl "Opponent wins (You resigned)" "De tegenstander heeft gewonnen (jij gaf het op)" ::msgcat::mcset nl "\n\n Opponent rejected move:\n %s\n\n" "\n\n De tegenstander weigerde de zet:\n %s\n\n" ::msgcat::mcset nl "Games" "Spelletjes" ::msgcat::mcset nl "Checkers..." "Dammen..." tkabber-plugins-0.11.1/checkers/checkers.tcl0000644000175000017500000013236611047022175020275 0ustar sergeisergei# $Id: checkers.tcl 1481 2008-08-08 10:48:29Z sergei $ package require msgcat namespace eval checkers { variable scriptdir [file dirname [info script]] ::msgcat::mcload [file join $scriptdir msgs] variable square_size 48 variable line_width 1 variable themes set dirs [glob -nocomplain -directory [file join $scriptdir pixmaps] *] foreach dir $dirs { pixmaps::load_theme_name [namespace current]::themes $dir } set values {} foreach theme [lsort [array names themes]] { lappend values $theme $theme } set game_names_list \ [list \ straight [::msgcat::mc "Straight checkers (English draughts)"] \ russian [::msgcat::mc "Russian checkers"] \ pool [::msgcat::mc "Pool checkers"] \ brazilian [::msgcat::mc "Brazilian checkers"] \ spanish [::msgcat::mc "Spanish checkers"] \ italian [::msgcat::mc "Italian checkers"] \ ] array set game_names $game_names_list array set short_game_names $game_names_list set short_game_names(straight) [::msgcat::mc "Straight checkers"] custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup Checkers [::msgcat::mc "Checkers plugin options."] -group Plugins custom::defvar options(theme) Checkers \ [::msgcat::mc "Checkers figures theme."] -group Checkers \ -type options -values $values \ -command [namespace current]::load_stored_theme custom::defvar options(game) russian \ [::msgcat::mc "Default game variant."] -group Checkers \ -type options \ -values $game_names_list custom::defvar options(flip_black_view) 1 \ [::msgcat::mc "Flip board view when playing black (Russian, Spanish, Italian) or white (Straight, Pool, Brazilian) by default."] \ -type boolean -group Checkers custom::defvar options(show_last_move) 0 \ [::msgcat::mc "Show last move by default."] \ -type boolean -group Checkers custom::defvar options(show_tooltips) 1 \ [::msgcat::mc "Show tooltips with short instructions."] \ -type boolean -group Checkers \ -command [list [namespace current]::set_tooltips] custom::defvar options(sound) "" \ [::msgcat::mc "Sound to play after opponent's turn"] \ -type file -group Checkers custom::defvar options(allow_illegal) 0 \ [::msgcat::mc "Allow illegal moves (useful for debugging)."] \ -type boolean -group Checkers custom::defvar options(accept_illegal) 0 \ [::msgcat::mc "Accept opponent illegal moves (useful for debugging)."] \ -type boolean -group Checkers } proc checkers::load_stored_theme {args} { variable options variable themes pixmaps::load_dir $themes(Checkers) pixmaps::load_dir $themes($options(theme)) } hook::add postload_hook [namespace current]::checkers::load_stored_theme 70 proc checkers::get_nick {connid jid type} { if {[catch {chat::get_nick $connid $jid $type} nick]} { return [chat::get_nick $jid $type] } else { return $nick } } proc checkers::invite_dialog {connid jid} { variable options set w .checkers_invite if {[winfo exists $w]} { destroy $w } Dialog $w -title [::msgcat::mc "Checkers Invitation"] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] message $wf.message -aspect 50000 \ -text [format [::msgcat::mc "Sending checkers game invitation to %s (%s)"] \ [get_nick $connid $jid chat] \ $jid] pack $wf.message -pady 2m variable game $options(game) radiobutton $wf.straight -text [::msgcat::mc "Straight checkers (English draughts)"] \ -value straight -variable [namespace current]::game pack $wf.straight -padx 15m -anchor w radiobutton $wf.russian -text [::msgcat::mc "Russian checkers"] \ -value russian -variable [namespace current]::game pack $wf.russian -padx 15m -anchor w radiobutton $wf.pool -text [::msgcat::mc "Pool checkers"] \ -value pool -variable [namespace current]::game pack $wf.pool -padx 15m -anchor w radiobutton $wf.brazilian -text [::msgcat::mc "Brazilian checkers"] \ -value brazilian -variable [namespace current]::game pack $wf.brazilian -padx 15m -anchor w radiobutton $wf.spanish -text [::msgcat::mc "Spanish checkers"] \ -value spanish -variable [namespace current]::game pack $wf.spanish -padx 15m -anchor w radiobutton $wf.italian -text [::msgcat::mc "Italian checkers"] \ -value italian -variable [namespace current]::game pack $wf.italian -padx 15m -anchor w $w add -text [::msgcat::mc "I want play white"] \ -command [list [namespace current]::invite $connid $jid white] $w add -text [::msgcat::mc "I want play black"] \ -command [list [namespace current]::invite $connid $jid black] $w add -text [::msgcat::mc "Cancel invitation"] \ -command [list destroy $w] $w draw } proc checkers::invite {connid jid color} { variable game destroy .checkers_invite set id checkers[rand 1000000000] # FIX #set rjid [get_jid_of_user $jid] jlib::send_iq set \ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type checkers:$game id $id color $color]] \ -to $jid \ -command [list [namespace current]::invite_res $game $connid $jid $id $color] \ -connection $connid } proc checkers::invite_res {game connid jid id color res child} { if {![cequal $res OK]} { after idle [list NonmodalMessageDlg .checkers_invite_error -aspect 50000 -icon error \ -message [format [::msgcat::mc "%s (%s) has refused checkers invitation: %s"] \ [get_nick $connid $jid chat] \ $jid [error_to_string $child]]] return "" } start_play $game $connid $jid $id $color } proc checkers::invited_dialog {game connid jid id color} { variable invited_result variable game_names set w .checkers_invited if {[winfo exists $w]} { destroy $w } Dialog $w -title [format [::msgcat::mc "Checkers Invitation from %s"] $jid] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] bind $wf [list [namespace current]::set_invited_res ""] set nick [get_nick $connid $jid chat] set message1 [format [::msgcat::mc "Checkers game invitation from %s (%s) is received."] \ $nick $jid] set message2 [format [::msgcat::mc "%s wants play %s."] $nick $game_names($game)] switch -- $color { white { set message3 [format [::msgcat::mc "%s wants play white."] $nick] } black { set message3 [format [::msgcat::mc "%s wants play black."] $nick] } default { return [list error modify bad-request] } } message $wf.message1 -aspect 50000 -text $message1 message $wf.message2 -aspect 50000 -text $message2 message $wf.message3 -aspect 50000 -text $message3 pack $wf.message1 -pady 1m pack $wf.message2 -pady 1m pack $wf.message3 -pady 1m $w add -text [::msgcat::mc "Agree to play"] \ -command [list [namespace current]::set_invited_res 0] $w add -text [::msgcat::mc "Refuse to play"] \ -command [list [namespace current]::set_invited_res 1] $w draw vwait [namespace current]::invited_result catch { bind $wf {} destroy $w } if {$invited_result == 0} { switch -- $color { white { start_play $game $connid $jid $id black } black { start_play $game $connid $jid $id white } default { return [list error modify bad-request] } } return [list result\ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type checkers:$game id $id]]] } else { return [list error modify not-acceptable] } } proc checkers::set_invited_res {res} { variable invited_result set invited_result $res } proc checkers::start_play {game connid jid id color} { set gid [make_gid $jid $id] variable $gid variable options upvar 0 $gid flags set flags(window) [win_id checkers $gid] set flags(connid) $connid set flags(opponent) $jid set flags(id) $id set flags(flip) 0 set flags(game) $game set flags(our_color) $color switch -- $game { straight { set flags(board_type) 0 set flags(start) black } russian { set flags(board_type) 0 set flags(start) white } pool { set flags(board_type) 0 set flags(start) black } brazilian { set flags(board_type) 0 set flags(start) black } spanish { set flags(board_type) 1 set flags(start) white } italian { set flags(board_type) 1 set flags(start) white } } trace variable [namespace current]::${gid}(position,turn) w \ [list [namespace current]::set_label_move $gid] make_default_position $gid open $gid } proc checkers::set_label_move {gid args} { variable $gid upvar 0 $gid flags switch -- $flags(position,turn) { white { set flags(move_label) [::msgcat::mc "White"] set move 1 } black { set flags(move_label) [::msgcat::mc "Black"] set move 1 } default { set move 0 } } if {$move && [is_my_move $gid]} { append flags(move_label) [::msgcat::mc " (You)"] } else { append flags(move_label) [::msgcat::mc " (Opponent)"] } } proc checkers::make_default_position {gid} { variable $gid upvar 0 $gid flags switch -- $flags(start) { white { set p1 wp set p2 bp } black { set p1 bp set p2 wp } } for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set cr [list $c $r] set flags(position,$cr) "" if {($c + $r) % 2 == $flags(board_type)} { if {$r < 3} { set flags(position,$cr) $p1 } elseif {$r > 4} { set flags(position,$cr) $p2 } } } } set flags(position,turn) $flags(start) catch {unset flags(position,last_move)} set flags(position,draw) 0 set flags(position,halfmove) 0 set flags(position,history) {} } proc checkers::save_position {gid} { variable $gid upvar 0 $gid flags set flags(saved_position) [array get flags position,*] } proc checkers::restore_position {gid} { variable $gid upvar 0 $gid flags array set flags $flags(saved_position) draw_position $gid unhighlight_legal_moves $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc checkers::make_gid {jid id} { jid_to_tag [concat $jid $id] } proc checkers::turn_recv {gid childs} { variable options variable prom_rev variable $gid upvar 0 $gid flags set move {} set draw 0 foreach child $childs { jlib::wrapper:splitxml $child tag vars isempty chdata children switch -- $tag { move { set pos [jlib::wrapper:getattr $vars pos] set poss [split $pos ";"] if {[llength $poss] >= 2} { foreach pos1 $poss { set pos2 [split $pos1 ","] if {[llength $pos2] == 2} { lappend move $pos2 } else { return [list error modify not-acceptable] } } } else { return [list error modify not-acceptable] } if {$options(sound) != "" && ![::sound::is_mute]} { ::sound::play $options(sound) } } resign { end_game $gid 1 [::msgcat::mc "You win (Opponent resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type checkers:$flags(game) \ id $flags(id)]]] } accept { if {$flags(position,draw)} { end_game $gid 0.5 [::msgcat::mc "Draw (Opponent accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type checkers:$flags(game) \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } draw { set draw 1 } } } if {![lempty $move] && [do_move $gid $move $draw]} { update_controls $gid $draw draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type checkers:$flags(game) \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } ############################################################################### proc checkers::calc_moves {} { variable moves variable jumps for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set cr [list $c $r] set moves(up,$cr) {} if {$r <= 6} { if {$c <= 6} { lappend moves(up,$cr) [list [expr {$c + 1}] [expr {$r + 1}]] } if {$c >= 1} { lappend moves(up,$cr) [list [expr {$c - 1}] [expr {$r + 1}]] } } set moves(dn,$cr) {} if {$r >= 1} { if {$c <= 6} { lappend moves(dn,$cr) [list [expr {$c + 1}] [expr {$r - 1}]] } if {$c >= 1} { lappend moves(dn,$cr) [list [expr {$c - 1}] [expr {$r - 1}]] } } set jumps(up,$cr) {} if {$r <= 5} { if {$c <= 5} { lappend jumps(up,$cr) [list [expr {$c + 1}] [expr {$r + 1}]] \ [list [expr {$c + 2}] [expr {$r + 2}]] } if {$c >= 2} { lappend jumps(up,$cr) [list [expr {$c - 1}] [expr {$r + 1}]] \ [list [expr {$c - 2}] [expr {$r + 2}]] } } set jumps(dn,$cr) {} if {$r >= 2} { if {$c <= 5} { lappend jumps(dn,$cr) [list [expr {$c + 1}] [expr {$r - 1}]] \ [list [expr {$c + 2}] [expr {$r - 2}]] } if {$c >= 2} { lappend jumps(dn,$cr) [list [expr {$c - 1}] [expr {$r - 1}]] \ [list [expr {$c - 2}] [expr {$r - 2}]] } } for {set moves(d1,$cr) {}; set x [expr {$c+1}]; set y [expr {$r+1}]} \ {($x < 8) && ($y < 8)} {incr x; incr y} { lappend moves(d1,$cr) [list $x $y] } for {set moves(d2,$cr) {}; set x [expr {$c-1}]; set y [expr {$r+1}]} \ {($x >= 0) && ($y < 8)} {incr x -1; incr y} { lappend moves(d2,$cr) [list $x $y] } for {set moves(d3,$cr) {}; set x [expr {$c-1}]; set y [expr {$r-1}]} \ {($x >= 0) && ($y >= 0)} {incr x -1; incr y -1} { lappend moves(d3,$cr) [list $x $y] } for {set moves(d4,$cr) {}; set x [expr {$c+1}]; set y [expr {$r-1}]} \ {($x < 8) && ($y >= 0)} {incr x; incr y -1} { lappend moves(d4,$cr) [list $x $y] } } } } hook::add finload_hook [namespace current]::checkers::calc_moves 100 proc checkers::center {c r} { variable square_size variable line_width set r [expr {7 - $r}] list [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $c)}] \ [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $r)}] } proc checkers::close {gid} { variable $gid upvar 0 $gid flags array unset flags } proc checkers::exists {gid} { variable $gid info exists $gid } proc checkers::open {gid} { variable options variable square_size variable line_width variable short_game_names variable $gid upvar 0 $gid flags set jid $flags(opponent) set w $flags(window) if {[winfo exists $w]} { raise_win $w return } set title [format [::msgcat::mc "%s with %s"] \ $short_game_names($flags(game)) [get_nick $flags(connid) $jid chat]] add_win $w -title $title \ -tabtitle $title \ -class Checkers \ -raise 1 set board [canvas $w.board \ -width [expr {($square_size + $line_width) * 8}] \ -height [expr {($square_size + $line_width) * 8}]] pack $board -side left -anchor w -padx 10 set flags(board) $board set flags(show_last_move) $options(show_last_move) set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] set slm [Button $w.show_last_move -text [::msgcat::mc "Show last move"] \ -relief $relief \ -command [list [namespace current]::toggle_show_last_move $gid]] pack $slm -side top -anchor w -fill x set flags(show_last_move_button) $slm set flags(flip) 0 set slm [Button $w.flip -text [::msgcat::mc "Flip view"] \ -relief raised \ -command [list [namespace current]::toggle_flip_view $gid]] pack $slm -side top -anchor w -fill x set flags(flip_button) $slm frame $w.move pack $w.move -side top -anchor w label $w.move.title -text [::msgcat::mc "Move: "] pack $w.move.title -side left label $w.move.on_move -anchor w \ -textvariable [namespace current]::${gid}(move_label) pack $w.move.on_move -side left -anchor w set bbox [ButtonBox $w.bbox -orient vertical -spacing 0] $bbox add -text [::msgcat::mc "Propose a draw"] \ -command [list [namespace current]::toggle_draw $gid] $bbox add -text [::msgcat::mc "Accept the draw proposal"] \ -state disabled \ -command [list [namespace current]::accept_draw $gid] $bbox add -text [::msgcat::mc "Resign the game"] \ -command [list [namespace current]::send_resign $gid] grid columnconfigure $bbox 0 -weight 1 pack $bbox -side bottom -anchor w -fill x set flags(bbox) $bbox set_tooltips #label $w.history -text [::msgcat::mc "History"] #pack $w.history -side top -anchor w set hsw [ScrolledWindow $w.hsw] pack $hsw -side top -fill x -expand yes set ht [text $w.text -wrap word -height 60 -state disabled] set font [$ht cget -font] set tabstop1 [font measure $font "99.."] set tabstop2 [font measure $font "99..Qa8-a8+= "] $ht configure -tabs "$tabstop1 $tabstop2" $ht tag configure attention -foreground [option get $ht errorForeground Text] $hsw setwidget $ht set flags(hw) $ht set dsq_color #77a26d set lsq_color #c8c365 for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set x1 [expr {$line_width + (($square_size + $line_width) * $c)}] set x2 [expr {($square_size + $line_width) * ($c + 1)}] set y1 [expr {$line_width + (($square_size + $line_width) * $r)}] set y2 [expr {($square_size + $line_width) * ($r + 1)}] set color [expr {($c+$r) % 2 ? $dsq_color : $lsq_color}] switch -- $flags(board_type) { 0 { set img [expr {($c+$r) % 2 ? "bf" : "wf"}] } 1 { set img [expr {($c+$r) % 2 ? "wf" : "bf"}] } } $board create image $x1 $y1 -image checkers/$img -anchor nw \ -tags [list background [list cr [list $c [expr {7-$r}]]]] $board create rectangle $x1 $y1 $x2 $y2 \ -outline {} \ -tags [list square [list cr [list $c [expr {7-$r}]]]] } } $board bind figure <1> \ [list [namespace current]::start_drag_figure $gid %x %y] $board bind figure \ [list [namespace current]::drag_figure $gid %x %y] $board bind figure \ [list [namespace current]::drag_end $gid %x %y] bind $w [list [namespace current]::close $gid] if {![is_same_color $flags(our_color) $flags(start)] && $options(flip_black_view)} { toggle_flip_view $gid } draw_position $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc checkers::toggle_flip_view {gid} { variable $gid upvar 0 $gid flags set flags(flip) [expr {!$flags(flip)}] set board $flags(board) for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { $board addtag [list temp [expr {7-$c}] [expr {7-$r}]] \ withtag [list cr [list $c $r]] $board dtag [list cr [list $c $r]] } } for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { $board addtag [list cr [list $c $r]] withtag [list temp $c $r] $board dtag [list temp $c $r] } } set relief [expr {$flags(flip) ? "sunken" : "raised"}] $flags(flip_button) configure -relief $relief draw_position $gid highlight_last_move $gid } proc checkers::set_tooltips {args} { variable options if {$options(show_tooltips)} { set tooltip0 [::msgcat::mc "Press button and make move if you want propose draw"] set tooltip1 [::msgcat::mc "Press button if you want accept the draw proposal"] set tooltip2 [::msgcat::mc "Press button if you want resign"] } else { set tooltip0 "" set tooltip1 "" set tooltip2 "" } foreach var [info vars [namespace current]::*] { upvar 0 $var flags if {[info exists flags(bbox)]} { catch { $flags(bbox) itemconfigure 0 -helptext $tooltip0 $flags(bbox) itemconfigure 1 -helptext $tooltip1 $flags(bbox) itemconfigure 2 -helptext $tooltip2 } } } } proc checkers::toggle_show_last_move {gid} { variable $gid upvar 0 $gid flags set flags(show_last_move) [expr {!$flags(show_last_move)}] set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] $flags(show_last_move_button) configure -relief $relief highlight_last_move $gid } proc checkers::toggle_draw {gid} { variable $gid upvar 0 $gid flags set flags(position,draw) [expr {!$flags(position,draw)}] if {$flags(position,draw)} { $flags(bbox) itemconfigure 0 -relief sunken } else { $flags(bbox) itemconfigure 0 -relief raised } } proc checkers::update_controls {gid {draw_proposed 0}} { variable $gid upvar 0 $gid flags $flags(bbox) itemconfigure 0 -relief raised if {[is_my_move $gid]} { $flags(board) config -cursor "" set flags(position,draw) 0 if {$draw_proposed} { $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state normal $flags(bbox) itemconfigure 2 -state disabled } else { $flags(bbox) itemconfigure 0 -state normal $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state normal } } elseif {![is_white $flags(position,turn)] && \ ![is_black $flags(position,turn)]} { $flags(board) config -cursor "" $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled } else { $flags(board) config -cursor watch $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled } } proc checkers::end_game {gid my_score message} { variable $gid upvar 0 $gid flags set opponent_score [expr {1 - $my_score}] if {[is_same_color $flags(our_color) $flags(start)]} { set score "$my_score : $opponent_score" } else { set score "$opponent_score : $my_score" } set flags(position,turn) none set flags(move_label) $message set hw $flags(hw) $hw configure -state normal catch {$hw delete attention.first attention.last} $hw delete {end -1 char} end $hw insert end "\n\t\t$score\n" $hw see end $hw configure -state disabled } proc checkers::draw_position {gid} { variable $gid upvar 0 $gid flags $flags(board) delete figure for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set cr [list $c $r] if {$flags(position,$cr) != ""} { if {$flags(flip)} { set c1 [expr {7 - $c}] set r1 [expr {7 - $r}] } else { set c1 $c set r1 $r } $flags(board) create image [center $c1 $r1] \ -image checkers/$flags(position,$cr) \ -tags [list figure $flags(position,$cr) [list cr $cr]] } } } } proc checkers::start_drag_figure {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) lassign [lindex [lmatch -regexp [$board gettags current] ^cr] 0] \ cr currentcr set flags(current_move) [list $currentcr] set flags(last_x) [$board canvasx $x] set flags(last_y) [$board canvasy $y] $board raise current $board config -cursor hand2 highlight_legal_moves $gid $flags(current_move) } proc checkers::drag_figure {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board move current \ [expr {$x - $flags(last_x)}] [expr {$y - $flags(last_y)}] set flags(last_x) $x set flags(last_y) $y $board itemconfigure dst_sq&&square -outline {} $board dtag dst_sq $board itemconfigure intermediate1&&square -outline yellow $board itemconfigure intermediate2&&square -outline green $board itemconfigure legal&&square -outline blue $board addtag dst_sq overlapping $x $y $x $y lassign [lindex [lmatch -regexp [$board gettags dst_sq&&background] ^cr] 0] \ -> cr $board addtag dst_sq withtag [list cr $cr]&&square $board itemconfigure dst_sq&&square -outline red $board itemconfigure dst_sq&&legal&&square -outline blue if {[lindex $flags(current_move) end] != $cr} { set current [concat $flags(current_move) [list $cr]] if {[is_move_prefix_legal $gid $current]} { set flags(current_move) $current highlight_legal_moves $gid $flags(current_move) } elseif {[is_move_legal $gid $current]} { $board itemconfigure dst_sq&&legal&&square -outline white } } $board itemconfigure dst_sq&&intermediate1&&square -outline yellow $board itemconfigure dst_sq&&intermediate2&&square -outline green } proc checkers::drag_end {gid x y} { variable options variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board itemconfigure dst_sq&&square -outline {} $board dtag dst_sq $board addtag dst_sq overlapping $x $y $x $y lassign [lindex [lmatch \ -regexp [$board gettags dst_sq&&background] \ ^cr] 0] -> cr $board dtag dst_sq lappend flags(current_move) $cr if {$options(allow_illegal) || [is_my_move $gid]} { do_move $gid $flags(current_move) $flags(position,draw) } update_controls $gid draw_position $gid unhighlight_legal_moves $gid highlight_last_move $gid } proc checkers::highlight_last_move {gid} { variable $gid upvar 0 $gid flags $flags(board) itemconfigure square -outline "" $flags(board) itemconfigure square -outline "" if {![info exists flags(position,last_move)]} { return } if {$flags(show_last_move)} { set color white set color2 yellow } else { set color {} set color2 {} } foreach pos [lrange $flags(position,last_move) 1 end-1] { $flags(board) itemconfigure [list cr $pos]&&square -outline $color } $flags(board) itemconfigure \ [list cr [lindex $flags(position,last_move) 0]]&&square -outline $color $flags(board) itemconfigure \ [list cr [lindex $flags(position,last_move) end]]&&square -outline $color } proc checkers::do_move {gid move draw} { variable options variable $gid upvar 0 $gid flags if {([llength $move] < 2) || ([lindex $move 0] == [lindex $move 1])} { return 0 } set endgame 0 set opt "-" set suffix "" set my_move [is_my_move $gid] if {![is_move_legal $gid $move]} { if {$my_move && !$options(allow_illegal)} { return 0 } if {!$my_move && !$options(accept_illegal)} { return 0 } } save_position $gid set figure $flags(position,[lindex $move 0]) if {![is_move_legal $gid $move]} { set flags(position,[lindex $move end]) $figure set flags(position,[lindex $move 0]) "" } else { set origin [lindex $move 0] foreach step [lrange $move 1 end] { lassign $origin originx originy lassign $step stepx stepy set dx [expr {$originx < $stepx ? 1 : -1}] set dy [expr {$originy < $stepy ? 1 : -1}] for {set x $originx; set y $originy} {($x != $stepx) && ($y != $stepy)} \ {incr x $dx; incr y $dy} { set xy [list $x $y] if {![is_same_color $flags(position,$xy) $figure]} { set opt ":" } set flags(position,$xy) "" } switch -- $flags(game) { straight { switch -- $figure,$stepy { bp,7 { set figure bk } wp,0 { set figure wk } } } pool - brazilian { switch -- $figure,$stepy { bp,7 { if {[lindex $move end] == $step} { set figure bk } } wp,0 { if {[lindex $move end] == $step} { set figure wk } } } } russian - spanish - italian { switch -- $figure,$stepy { wp,7 { set figure wk } bp,0 { set figure bk } } } } set flags(position,$step) $figure set origin $step } } set flags(position,last_move) $move if {[is_white $flags(position,turn)]} { set flags(position,turn) black } else { set flags(position,turn) white } find_legal_moves $gid $flags(position,turn) if {[lempty $flags(legal_moves)]} { set draw 0 set endgame 1 } if {$draw} { set suffix "=" } add_move_to_history $gid $move $opt $suffix if {$draw && !$my_move} { attention_message $gid \ [::msgcat::mc "\n\n Opponent proposes a draw\n\n"] } if {$my_move} { send_move $gid $move } if {$endgame} { if {$my_move} { # I win end_game $gid 1 [::msgcat::mc "You win"] } else { # Opponent wins end_game $gid 0 [::msgcat::mc "Opponent wins"] } } tab_set_updated [winfo parent $flags(board)] 1 mesg_to_user return 1 } proc checkers::accept_draw {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type checkers:$flags(game) \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag accept]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0.5 [::msgcat::mc "Draw (You accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc checkers::send_resign {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type checkers:$flags(game) \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag resign]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0 [::msgcat::mc "Opponent wins (You resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc checkers::send_move {gid move} { variable $gid upvar 0 $gid flags set move_tags [list [make_move_tag $gid $move]] if {$flags(position,draw)} { lappend move_tags [jlib::wrapper:createtag draw] } jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type checkers:$flags(game) \ id $flags(id)] \ -subtags $move_tags] \ -to $flags(opponent) \ -connection $flags(connid) \ -command [list [namespace current]::send_result $gid] } proc checkers::send_result {gid res child} { if {$res == "ERR"} { attention_message $gid \ [format [::msgcat::mc "\n\n Opponent rejected move:\n %s\n\n"] \ [error_to_string $child]] restore_position $gid } } proc checkers::make_move_tag {gid move} { set move1 {} foreach pos $move { lappend move1 [join $pos ","] } jlib::wrapper:createtag move -vars [list pos [join $move1 ";"]] } proc checkers::add_move_to_history {gid move opt suffix} { variable piece_name variable $gid upvar 0 $gid flags incr flags(position,halfmove) 1 lappend flags(position,history) [list $move $opt $suffix] set hw $flags(hw) $hw configure -state normal $hw delete 0.0 end if {[is_white $flags(start)]} { $hw insert end "\t[::msgcat::mc White]\t[::msgcat::mc Black]\n" } else { $hw insert end "\t[::msgcat::mc Black]\t[::msgcat::mc White]\n" } set i 1 foreach {w b} $flags(position,history) { $hw insert end "${i}.\t" if {$w != {}} { lassign $w move opt suffix set move1 {} foreach pos $move { lassign $pos c r incr r set l [format %c [expr {$c+97}]] lappend move1 "$l$r" } $hw insert end "[join $move1 $opt]$suffix\t" } if {$b != {}} { lassign $b move opt suffix set move1 {} foreach pos $move { lassign $pos c r incr r set l [format %c [expr {$c+97}]] lappend move1 "$l$r" } $hw insert end "[join $move1 $opt]$suffix\n" } incr i } $hw see end $hw configure -state disabled } proc checkers::find_legal_moves {gid color} { variable moves variable jumps variable $gid upvar 0 $gid flags set flags(legal_moves) {} find_legal_jumps $gid $color if {[lempty $flags(legal_moves)]} { find_legal_moves1 $gid $color } } proc checkers::find_legal_jumps {gid color} { variable moves variable $gid upvar 0 $gid flags for {set cf 0} {$cf < 8} {incr cf} { for {set rf 0} {$rf < 8} {incr rf} { set cr [list $cf $rf] if {![is_same_color $flags(position,$cr) $color]} { continue } set figure $flags(position,$cr) set flags(position,$cr) "" find_legal_jumps1 $gid $cr $figure [list $cr] {} set flags(position,$cr) $figure } } clean_jumps $gid } proc checkers::clean_jumps {gid} { variable $gid upvar 0 $gid flags switch -- $flags(game) { brazilian - spanish { set jumps {} set l 0 foreach m $flags(legal_moves) { set l1 [llength $m] if {$l1 > $l} { set jumps [list $m] set l $l1 } elseif {$l1 == $l} { lappend jumps $m } } set flags(legal_moves) $jumps } italian { set jumps {} set l 0 set captor b set nkings 0 set pking 0 foreach m $flags(legal_moves) { set l1 [llength $m] set captor1 [string index $flags(position,[lindex $m 0]) end] lassign [count_kings $gid $m] nkings1 pking1 if {($l1 > $l) || (($l1 == $l) && ($captor1 == "k" && $captor == "b")) || (($l1 == $l) && ($captor1 == $captor) && ($nkings1 > $nkings)) || (($l1 == $l) && ($captor1 == $captor) && ($nkings1 == $nkings) && ($pking1 < $pking))} { set jumps [list $m] set l $l1 set captor $captor1 set nkings $nkings1 set pking $pking1 } elseif {($l1 == $l) && ($captor == $captor1) && ($nkings1 == $nkings) && ($pking1 == $pking)} { lappend jumps $m } } set flags(legal_moves) $jumps } } } proc checkers::count_kings {gid move} { variable $gid upvar 0 $gid flags set nkings 0 set pking 0 set crf [lindex $move 0] set i 1 foreach crt [lrange $move 1 end] { lassign $crf cf rf lassign $crt ct rt set crm [list [expr {($cf + $ct)/2}] [expr {($rf + $rt)/2}]] if {[string index $flags(position,$crm) end] == "k"} { incr nkings if {$pking == 0} { set pking $i } } incr i } return [list $nkings $pking] } proc checkers::find_legal_jumps1 {gid cr figure current forbidden {simulate 0}} { variable moves variable jumps variable $gid upvar 0 $gid flags set jump 0 switch -- $figure { "" { continue } bp { switch -- $flags(game) { straight { foreach {crdel crt} $jumps(up,$cr) { if {![lcontain $forbidden $crdel] && \ [is_white $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } spanish { foreach {crdel crt} $jumps(dn,$cr) { if {![lcontain $forbidden $crdel] && \ [is_white $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } italian { foreach {crdel crt} $jumps(dn,$cr) { if {![lcontain $forbidden $crdel] && \ $flags(position,$crdel) == "wp" && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } russian { foreach {crdel crt} [concat $jumps(up,$cr) $jumps(dn,$cr)] { if {![lcontain $forbidden $crdel] && \ [is_white $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt \ [expr {[lindex $crt 1] == 0 ? "bk" : "bp"}] \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } pool - brazilian { foreach {crdel crt} [concat $jumps(up,$cr) $jumps(dn,$cr)] { if {![lcontain $forbidden $crdel] && \ [is_white $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } } } wp { switch -- $flags(game) { straight { foreach {crdel crt} $jumps(dn,$cr) { if {![lcontain $forbidden $crdel] && \ [is_black $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } spanish { foreach {crdel crt} $jumps(up,$cr) { if {![lcontain $forbidden $crdel] && \ [is_black $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } italian { foreach {crdel crt} $jumps(up,$cr) { if {![lcontain $forbidden $crdel] && \ $flags(position,$crdel) == "bp" && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } russian { foreach {crdel crt} [concat $jumps(dn,$cr) $jumps(up,$cr)] { if {![lcontain $forbidden $crdel] && \ [is_black $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt \ [expr {[lindex $crt 1] == 7 ? "wk" : "wp"}] \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } pool - brazilian { foreach {crdel crt} [concat $jumps(dn,$cr) $jumps(up,$cr)] { if {![lcontain $forbidden $crdel] && \ [is_black $flags(position,$crdel)] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } } } wk - bk { switch -- $flags(game) { straight - italian { foreach {crdel crt} [concat $jumps(dn,$cr) $jumps(up,$cr)] { if {![lcontain $forbidden $crdel] && \ ![is_same_color $flags(position,$crdel) $figure] && \ $flags(position,$crt) == ""} { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } russian - pool - brazilian - spanish { set canjump {} set cantjump {} foreach d {d1 d2 d3 d4} { set state empty foreach crt $moves($d,$cr) { switch -- $state { empty { if {($flags(position,$crt) != "")} { if {![lcontain $forbidden $crt] && \ ![is_same_color $flags(position,$crt) $figure]} { set crdel $crt set state jump } else { break } } } jump { if {($flags(position,$crt) == "")} { if {[find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] 1]} { lappend canjump $crdel $crt } else { lappend cantjump $crdel $crt } } else { break } } } } } if {![lempty $canjump]} { foreach {crdel crt} $canjump { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } else { foreach {crdel crt} $cantjump { find_legal_jumps1 $gid $crt $figure \ [concat $current [list $crt]] \ [concat $forbidden [list $crdel]] set jump 1 } } } } } } if {!$simulate && !$jump && [llength $current] >= 2} { lappend flags(legal_moves) $current } return $jump } proc checkers::find_legal_moves1 {gid color} { variable moves variable $gid upvar 0 $gid flags for {set cf 0} {$cf < 8} {incr cf} { for {set rf 0} {$rf < 8} {incr rf} { set cr [list $cf $rf] if {![is_same_color $flags(position,$cr) $color]} { continue } switch -- $flags(position,$cr) { "" { continue } bp { switch -- $flags(game) { straight - pool - brazilian { foreach crt $moves(up,$cr) { if {$flags(position,$crt) == ""} { lappend flags(legal_moves) [list $cr $crt] } } } russian - spanish - italian { foreach crt $moves(dn,$cr) { if {$flags(position,$crt) == ""} { lappend flags(legal_moves) [list $cr $crt] } } } } } wp { switch -- $flags(game) { straight - pool - brazilian { foreach crt $moves(dn,$cr) { if {$flags(position,$crt) == ""} { lappend flags(legal_moves) [list $cr $crt] } } } russian - spanish - italian { foreach crt $moves(up,$cr) { if {$flags(position,$crt) == ""} { lappend flags(legal_moves) [list $cr $crt] } } } } } wk - bk { switch -- $flags(game) { straight - italian { foreach crt [concat $moves(up,$cr) $moves(dn,$cr)] { if {$flags(position,$crt) == ""} { lappend flags(legal_moves) [list $cr $crt] } } } russian - pool - brazilian - spanish { foreach d {d1 d2 d3 d4} { foreach crt $moves($d,$cr) { if {$flags(position,$crt) == ""} { lappend flags(legal_moves) [list $cr $crt] } else { break } } } } } } } } } } proc checkers::is_move_legal {gid move} { variable $gid upvar 0 $gid flags expr {[lsearch -exact $flags(legal_moves) $move] >= 0} } proc checkers::is_move_prefix_legal {gid move} { variable $gid upvar 0 $gid flags expr {[lsearch -glob $flags(legal_moves) "$move *"] >= 0} } proc checkers::highlight_legal_moves {gid prefix} { variable $gid upvar 0 $gid flags unhighlight_legal_moves $gid set len [llength $prefix] set lenm1 [expr {$len - 1}] foreach move $flags(legal_moves) { if {[lrange $move 0 $lenm1] != $prefix} { continue } foreach pos [lrange $move 1 $lenm1] { $flags(board) addtag intermediate1 withtag [list cr $pos]&&square } foreach pos [lrange $move $len end-1] { $flags(board) addtag intermediate2 withtag [list cr $pos]&&square } $flags(board) addtag legal withtag [list cr [lindex $move end]]&&square } $flags(board) itemconfigure legal&&square -outline blue $flags(board) itemconfigure intermediate1&&square -outline yellow $flags(board) itemconfigure intermediate2&&square -outline green } proc checkers::unhighlight_legal_moves {gid} { variable $gid upvar 0 $gid flags $flags(board) itemconfigure square -outline {} $flags(board) dtag legal $flags(board) dtag intermediate1 $flags(board) dtag intermediate2 } proc checkers::attention_message {gid message} { variable $gid upvar 0 $gid flags set hw $flags(hw) $hw configure -state normal $hw delete {end -1 char} end $hw insert end $message attention $hw see end $hw configure -state disabled } proc checkers::is_my_move {gid} { variable $gid upvar 0 $gid flags is_same_color $flags(position,turn) $flags(our_color) } proc checkers::is_white {f} { string equal -length 1 $f w } proc checkers::is_black {f} { string equal -length 1 $f b } proc checkers::is_same_color {f1 f2} { string equal -length 1 $f1 $f2 } proc checkers::add_groupchat_user_menu_item {m connid jid} { set mm $m.gamesmenu if {![winfo exists $mm]} { menu $mm -tearoff 0 $m add cascade -label [::msgcat::mc "Games"] -menu $mm } $mm add command -label [::msgcat::mc "Checkers..."] \ -command [list [namespace current]::invite_dialog $connid $jid] } hook::add roster_create_groupchat_user_menu_hook \ [namespace current]::checkers::add_groupchat_user_menu_item 49 hook::add chat_create_user_menu_hook \ [namespace current]::checkers::add_groupchat_user_menu_item 49 hook::add roster_jid_popup_menu_hook \ [namespace current]::checkers::add_groupchat_user_menu_item 49 proc checkers::iq_create {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children lassign [split [jlib::wrapper:getattr $vars type] ":"] cathegory game if {$cathegory != "checkers"} { return } switch -- $game { straight - russian - pool - brazilian - spanish - italian { if {[jlib::wrapper:isattr $vars color]} { set color [jlib::wrapper:getattr $vars color] switch -- $color { white - black { } default { set var [list error modify bad-request] } } } else { set color white } set var [[namespace current]::invited_dialog \ $game $connid $from \ [jlib::wrapper:getattr $vars id] \ $color] } } return } hook::add games_board_create_hook [namespace current]::checkers::iq_create proc checkers::iq_turn {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children lassign [split [jlib::wrapper:getattr $vars type] ":"] cathegory game if {$cathegory != "checkers"} { return } switch -- $game { straight - russian - pool - brazilian - spanish - italian { set gid [make_gid $from [jlib::wrapper:getattr $vars id]] if {[exists $gid]} { set var [[namespace current]::turn_recv $gid $children] } else { set var [list error cancel item-not-found] } } } return } hook::add games_board_turn_hook [namespace current]::checkers::iq_turn # Common games:board part proc iq_games_board_create {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_create_hook res $connid $from $child return $res } iq::register_handler set create games:board \ [namespace current]::iq_games_board_create proc iq_games_board_turn {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_turn_hook res $connid $from $child return $res } iq::register_handler set turn games:board \ [namespace current]::iq_games_board_turn tkabber-plugins-0.11.1/checkers/proto0000644000175000017500000000357310214157222017062 0ustar sergeisergeiRequest: 600 -- for all players 10 -- if on black side played Kasparov Known types: checkers:russian, checkers:pool, checkers:spanish, checkers:straight, checkers:italian Positive response: or simply ? Move: 'pos' attribute contain column-separated list of coordinates of piece, that moved from first to last one. Coordinate is a comma-separated list of integers >= 0. Jump move: Proposing draw: Accepting draw proposal: Resigning: Response: if move accepted, or error 'Not Acceptable' if other side think that this move illegal (to avoid evil hackers that write clients that can do few moves instead of one or can move King like Queen) tkabber-plugins-0.11.1/checkers/rules/0000755000175000017500000000000011076120366017124 5ustar sergeisergeitkabber-plugins-0.11.1/checkers/rules/pool.txt0000644000175000017500000001261710214157222020637 0ustar sergeisergeiPool Checkers Rules of Play 1. Pool checkers, also known as Spanish pool checkers, is played on the dark squares only of a standard checkerboard of 64 alternating dark and light squares, (eight rows, eight files) by two opponents having 12 checkers each of contrasting colors, nominally referred to as black and white. 2. The board is positioned squarely between the players and turned so that a dark square is at each player's near left side. Each player places his checkers on the dark squares of the three rows nearest him. The player with the darker checkers makes the first move of the game, and the players take turns thereafter, making one move at a time. 3. The object of the game is to prevent the opponent from being able to move when it is his turn to do so. This is accomplished either by capturing all of the opponent's checkers, or by blocking those that remain so that none of them can be moved. If neither player can accomplish this, the game is a draw. 4. Single checkers, known as men, move forward only, one square at a time in a diagonal direction, to an unoccupied square. Men capture by jumping over an opposing man on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Men may jump forward or backward, and may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Men may never jump over checkers of the same color. 5. A man which reaches the far side of the board becomes a king. However, if it reaches the far side by means of a jump, and is able to jump backward away from the far side over another man or king, it must do so, and does not become a king. A man reaching the far side by jumping becomes a king only if its jump, or series of jumps, terminates there. When a man becomes a king the turn to move passes to the other player, who must crown the new king by placing a checker of the same color atop it. A player is not permitted to make his own move until he crowns his opponent's king. 6. Kings move forward or backward any number of squares on a diagonal line to an unoccupied square. Kings capture from any distance along a diagonal line by jumping, forward or backward, over an opposing man or king with at least one unoccupied square immediately beyond it. The capturing king then lands on any one of these unoccupied squares (except as noted in rule 7) and continues jumping, if possible, either on the same line, or by making a right angle turn onto another diagonal line. Kings may never jump over checkers of the same color. 7. Whenever a player is able to make a capture he must do so. When there is more than one way to jump, a player may choose any way he wishes, not necessarily the one which results in the capture of the greatest number of opposing units. When a king jumps over an opposing man or king with more than one unoccupied square immediately beyond it, it must land on a square from which it is possible to continue jumping, if there is such a square. If there is more than one such square, any may be chosen. However, once a player chooses a sequence of captures, he must make all the captures possible in that sequence. He may not leave one or more checkers uncaptured that he could capture simply by continuing to jump. A "huff" of a checker for failure to jump properly is not permitted as it was in the past. The incorrect move must be retracted, and a correct move must be made. If possible, the correct move must be made with the man or king originally moved incorrectly. 8. A man or king may not jump over the same opposing man or king more than once. 9. Captured checkers are not removed from the board until all jumps made on the move are completed, and the hand is removed from the capturing man or king. (It is only in rare instances that rules 8 or 9 affect the play of a game. They can have the effect of reducing the number of captures possible on a move. In most of these cases a king is the capturing piece. On very rare occasions these rules, either separately or in combination, will result in a king being forced to terminate a series of jumps on a square from which it will then be captured by an opposing man or king which itself would have been captured were it not for these rules.) 10. Whenever a situation arises in which one player has three kings and the other one king, no other checkers remaining on the board, a count is begun of the moves made by the lone king. If the lone king is able to make 13 moves the game is a draw, even if the next move by the opponent would be the capture of the lone king. (In general, a win is possible only if the side with three kings has possession of the diagonal line running from the lower left corner to the upper right corner.) 11. Time limits for play may be based on a fixed amount of time for each move, with less time allowed for situations in which there is one, and only one, capturing move possible, or on a fixed amount of time for a given number of moves, without regard to how much of this time is used on any one move. When the latter method is used, and the given number of moves has been made by each player, with neither having used up the allotted time, an additional allotment of time and moves is given to each. This continues until the conclusion of the game. Unused time is retained when a new allotment is given. A player loses a game if his time expires before he has completed the required number of moves. tkabber-plugins-0.11.1/checkers/rules/spanish.txt0000644000175000017500000000661310214157222021332 0ustar sergeisergeiSpanish Checkers Rules of Play 1. Spanish checkers is played on the dark squares only of a standard checkerboard of 64 alternating dark and light squares, (eight rows, eight files) by two opponents having 12 checkers each of contrasting colors, nominally referred to as black and white. 2. The board is positioned squarely between the players and turned so that a dark square is at each player's near right side. Each player places his checkers on the dark squares of the three rows nearest him. The player with the lighter checkers makes the first move of the game, and the players take turns thereafter, making one move at a time. 3. The object of the game is to prevent the opponent from being able to move when it is his turn to do so. This is accomplished either by capturing all of the opponent's checkers, or by blocking those that remain so that none of them can be moved. If neither player can accomplish this, the game is a draw. 4. Single checkers, known as men, move forward only, one square at a time in a diagonal direction, to an unoccupied square. Men capture by jumping over an opposing man on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Men may jump forward only, and may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Men may never jump over checkers of the same color. 5. A man which reaches the far side of the board, whether by means of a jump or a simple move, becomes a king, and the move terminates. The opponent must then crown the new king by placing a checker of the same color atop it. A player is not permitted to make his own move until he crowns his opponent's king. 6. Kings move forward or backward any number of squares on a diagonal line to an unoccupied square. Kings capture from any distance along a diagonal line by jumping, forward or backward, over an opposing man or king with at least one unoccupied square immediately beyond it. The capturing king then lands on any one of these unoccupied squares (except as noted in rule 7) and continues jumping, if possible, either on the same line, or by making a right angle turn ontoanother diagonal line. Kings may never jump over checkers of the same color. 7. Whenever a player is able to make a capture he must do so. When there is more than one way to jump, a player must choose a sequence of jumps which results in the capture of the greatest possible number of opposing units, men and kings each counting as one unit. A "huff" of a checker for failure to jump properly is not permitted. The incorrect move must be retracted, and a correct move must be made. If possible, the correct move must be made with the man or king originally moved incorrectly. 8. A king may not jump over the same opposing man or king more than once. 9. Captured checkers are not removed from the board until all jumps made on the move are completed, and the hand is removed from the capturing man or king. (It is only in rare instances that rules 8 or 9 affect the play of a game. They can have the effect of reducing the number of captures a king can make. On very rare occasions these rules, either separately or in combination, will result in a king being forced to terminate a series of jumps on a square from which it will then be captured by an opposing man or king which itself would have been captured were it not for these rules.) tkabber-plugins-0.11.1/checkers/rules/brasilian.txt0000644000175000017500000000735110241713051021627 0ustar sergeisergeiBrazilian Checkers Rules of Play 1. Brazilian checkers is played on the dark squares only of a standard checkerboard of 64 alternating dark and light squares, (eight rows, eight files) by two opponents having 12 checkers each of contrasting colors, nominally referred to as black and white. 2. The board is positioned squarely between the players and turned so that a dark square is at each player's near left side. Each player places his checkers on the dark squares of the three rows nearest him. The player with the darker checkers makes the first move of the game, and the players take turns thereafter, making one move at a time. 3. The object of the game is to prevent the opponent from being able to move when it is his turn to do so. This is accomplished either by capturing all of the opponent's checkers, or by blocking those that remain so that none of them can be moved. If neither player can accomplish this, the game is a draw. 4. Single checkers, known as men, move forward only, one square at a time in a diagonal direction, to an unoccupied square. Men capture by jumping over an opposing man on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Men may jump forward or backward, and may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Men may never jump over checkers of the same color. 5. A man which reaches the far side of the board becomes a king. However, if it reaches the far side by means of a jump, and is able to jump backward away from the far side over another man or king, it must do so, and does not become a king. A man reaching the far side by jumping becomes a king only if its jump, or series of jumps, terminates there. When a man becomes a king the turn to move passes to the other player, who must crown the new king by placing a checker of the same color atop it. A player is not permitted to make his own move until he crowns his opponent's king. 6. Kings move forward or backward any number of squares on a diagonal line to an unoccupied square. Kings capture from any distance along a diagonal line by jumping, forward or backward, over an opposing man or king with at least one unoccupied square immediately beyond it. The capturing king then lands on any one of these unoccupied squares (except as noted in rule 7) and continues jumping, if possible, either on the same line, or by making a right angle turn onto another diagonal line. Kings may never jump over checkers of the same color. 7. Whenever a player is able to make a capture he must do so. When there is more than one way to jump, a player must choose a sequence of jumps which results in the capture of the greatest possible number of opposing units, men and kings each counting as one unit. A "huff" of a checker for failure to jump properly is not permitted. The incorrect move must be retracted, and a correct move must be made. If possible, the correct move must be made with the man or king originally moved incorrectly. 8. A man or king may not jump over the same opposing man or king more than once. 9. Captured checkers are not removed from the board until all jumps made on the move are completed, and the hand is removed from the capturing man or king. (It is only in rare instances that rules 8 or 9 affect the play of a game. They can have the effect of reducing the number of captures possible on a move. In most of these cases a king is the capturing piece. On very rare occasions these rules, either separately or in combination, will result in a king being forced to terminate a series of jumps on a square from which it will then be captured by an opposing man or king which itself would have been captured were it not for these rules.) tkabber-plugins-0.11.1/checkers/rules/italian.txt0000644000175000017500000000640210214157222021302 0ustar sergeisergeiItalian Checkers Rules of Play 1. Italian checkers is played on the dark squares only of a standard checkerboard of 64 alternating dark and light squares, (eight rows, eight files) by two opponents having 12 checkers each of contrasting colors, nominally referred to as black and white. 2. The board is positioned squarely between the players and turned so that a dark square is at each player's near right side. Each player places his checkers on the dark squares of the three rows nearest him. The player with the lighter checkers makes the first move of the game, and the players take turns thereafter, making one move at a time. 3. The object of the game is to prevent the opponent from being able to move when it is his turn to do so. This is accomplished either by capturing all of the opponent's checkers, or by blocking those that remain so that none of them can be moved. If neither player can accomplish this, the game is a draw. 4. Single checkers, known as men, move forward only, one square at a time in a diagonal direction, to an unoccupied square. Men capture by jumping over an opposing man on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Men may jump forward only, and may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Men may never jump over checkers of the same color. Men may never jump over kings. 5. A man which reaches the far side of the board, whether by means of a jump or a simple move, becomes a king, and the move terminates. The opponent must then crown the new king by placing a checker of the same color atop it. A player is not permitted to make his own move until he crowns his opponent's king. 6. Kings move forward or backward, one square at a time in a diagonal direction to an unoccupied square. Kings capture by jumping, forward or backward, over an opposing man or king on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Kings may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Kings may never jump over checkers of the same color. They may never jump over the same opposing man or king more than once. 7. Whenever a player is able to make a capture he must do so. a) If there is more than one way to jump, a player must choose a sequence of jumps which results in the capture of the greatest possible number of opposing units, men and kings each counting as one unit. b) If there is more than one way to capture the greatest possible number of opposing units, the capture must be made with a king, if possible, rather than with a single man. c) If there is more than one way for the greatest possible number of units to be captured by a king, the most kings must be captured. d) If there is more than one way for the greatest and most powerful forces to be captured, a capture which results in a king being captured earliest in the sequence of jumps must be chosen. A "huff" of a checker for failure to jump properly is not permitted. The incorrect move must be retracted, and a correct move must be made. If possible, the correct move must be made with the man or king originally moved incorrectly. tkabber-plugins-0.11.1/checkers/rules/russian.txt0000644000175000017500000001202010214157222021336 0ustar sergeisergeiRussian Checkers Rules of Play 1. Russian checkers is played on the dark squares only of a standard checkerboard of 64 alternating dark and light squares, (eight rows, eight files) by two opponents having 12 checkers each of contrasting colors, nominally referred to as black and white. 2. The board is positioned squarely between the players and turned so that a dark square is at each player's near left side. Each player places his checkers on the dark squares of the three rows nearest him. The player with the lighter checkers makes the first move of the game, and the players take turns thereafter, making one move at a time. 3. The object of the game is to prevent the opponent from being able to move when it is his turn to do so. This is accomplished either by capturing all of the opponent's checkers, or by blocking those that remain so that none of them can be moved. If neither player can accomplish this, the game is a draw. 4. Single checkers, known as men, move forward only, one square at a time in a diagonal direction, to an unoccupied square. Men capture by jumping over an opposing man on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Men may jump forward or backward, and may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Men may never jump over checkers of the same color. 5. A man which reaches the far side of the board becomes a king. If it reaches the far side by means of a jump, it continues jumping as a king on the same move, if possible, and remains a king at the end of the jumping sequence. When a man becomes a king the turn to move passes to the other player, who must crown the new king by placing a checker of the same color atop it. A player is not permitted to make his own move until he crowns his opponent's king. 6. Kings move forward or backward any number of squares on a diagonal line to an unoccupied square. Kings capture from any distance along a diagonal line by jumping, forward or backward, over an opposing man or king with at least one unoccupied square immediately beyond it. The capturing king then lands on any one of these unoccupied squares (except as noted in rule 7) and continues jumping, if possible, either on the same line, or by making a right angle turn onto another diagonal line. Kings may never jump over checkers of the same color. 7. Whenever a player is able to make a capture he must do so. When there is more than one way to jump, a player may choose any way he wishes, not necessarily the one which results in the capture of the greatest number of opposing units. When a king jumps over an opposing man or king with more than one unoccupied square immediately beyond it, it must land on a square from which it is possible to continue jumping, if there is such a square. If there is more than one such square, any may be chosen. However, once a player chooses a sequence of captures, he must make all the captures possible in that sequence. He may not leave one or more checkers uncaptured that he could capture simply by continuing to jump. A "huff" of a checker for failure to jump properly is not permitted. The incorrect move must be retracted, and a correct move must be made. If possible, the correct move must be made with the man or king originally moved incorrectly. 8. A man or king may not jump over the same opposing man or king more than once. 9. Captured checkers are not removed from the board until all jumps made on the move are completed, and the hand is removed from the capturing man or king. (It is only in rare instances that rules 8 or 9 affect the play of a game. They can have the effect of reducing the number of captures possible on a move. In most of these cases a king is the capturing piece. On very rare occasions these rules, either separately or in combination, will result in a king being forced to terminate a series of jumps on a square from which it will then be captured by an opposing man or king which itself would have been captured were it not for these rules.) 10. Whenever a situation arises in which one player has three kings and the other one king, no other checkers remaining on the board, a count is begun of the moves made by the stronger side. If the lone king is not captured by the end of the fifteenth move by the stronger side, the game is a draw. (In general, a win is possible only if the side with three kings has possession of the diagonal line running from the lower left corner to the upper right corner.) 11. Time limits for play are based on a fixed amount of time for a given number of moves, without regard to how much of this time is used on any one move. When the given number of moves has been made by each player, with neither having used up the allotted time, an additional allotment of time and moves is given to each. This continues until the conclusion of the game. Unused time is retained when a new allotment is given. A player loses a game if his time expires before he has completed the required number of moves. tkabber-plugins-0.11.1/checkers/rules/straight.txt0000644000175000017500000001005110214157222021501 0ustar sergeisergeiStraight Checkers or English Draughts Rules of Play 1. Straight checkers, also known as English draughts, is played on the dark squares only of a standard checkerboard of 64 alternating dark and light squares, (eight rows, eight files) by two opponents having 12 checkers each of contrasting colors, nominally referred to as black andwhite. (Serious checker players generally use red and white checkers, and green and yellow checkerboards. These colors have been designated as official by the American Checker Federation. In any case, colors of the checkers and the board should be different in order to provide good contrast, and especially to avoid such combinations as black checkers on black squares.) 2. The board is positioned squarely between the players and turned so that a dark square is at each player's near left side. Each player places his checkers on the dark squares of the three rows nearest him. The player with the darker checkers makes the first move of the game, andthe players take turns thereafter, making one move at a time. 3. The object of the game is to prevent the opponent from being able to move when it is his turn to do so. This is accomplished either by capturing all of the opponent's checkers, or by blocking those that remain so that none of them can be moved. If neither player can accomplish this, the game is a draw. 4. Single checkers, known as men, move forward only, one square at a time in a diagonal direction, to an unoccupied square. Men capture by jumping over an opposing man on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Men may jump forward only, and may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Men may never jump over checkers of the same color. 5. A man which reaches the far side of the board, whether by means of a jump or a simple move, becomes a king, and the move terminates. The opponent must then crown the new king by placing a checker of the same color atop it. A player is not permitted to make his own move until he crowns his opponent's king. 6. Kings move forward or backward, one square at a time in a diagonal direction to an unoccupied square. Kings capture by jumping, forward or backward, over an opposing man or king on a diagonally adjacent square to the square immediately beyond, but may do so only if this square is unoccupied. Kings may continue jumping as long as they encounter opposing checkers with unoccupied squares immediately beyond them. Kings may never jump over checkers of the same color. They may never jump over the same opposing man or king more than once. 7. Whenever a player is able to make a capture he must do so. When there is more than one way to jump, a player may choose any way he wishes, not necessarily the one which results in the capture of the greatest number of opposing units. However, once a player chooses asequence of captures, he must make all the captures possible in that sequence. He may not leave one or more checkers uncaptured that he could capture simply by continuing to jump. A "huff" of a checker for failure to jump properly is not permitted as it was in the past. Theincorrect move must be retracted, and a correct move must be made. If possible, the correct move must be made with the man or king originally moved incorrectly. 8. Time limits for play may be based on a fixed amount of time for each move, with less time allowed for situations in which there is one, and only one, capturing move possible, or on a fixed amount of time for a given number of moves, without regard to how much of this time is used on any one move. When the latter method is used, and the given number of moves has been made by each player, with neither having used up the allotted time, an additional allotment of time and moves is given to each. This continues until the conclusion of the game. Unused time is retained when a new allotment is given. A player loses a game if his time expires before he has completed the required number of moves. tkabber-plugins-0.11.1/checkers/pixmaps/0000755000175000017500000000000011076120366017453 5ustar sergeisergeitkabber-plugins-0.11.1/checkers/pixmaps/xboard/0000755000175000017500000000000011076120366020732 5ustar sergeisergeitkabber-plugins-0.11.1/checkers/pixmaps/xboard/wp.gif0000644000175000017500000000035210471327266022055 0ustar sergeisergeiGIF89a11!,11ڋ{IHؠ$›q0wwm |P( rcRW5nʋfuyִ uoF82Xx~_җ"@XȤrhX7IYyfHV&Y6f' 6iDVWa1{#v3:҂Fw,=M]m}Q;tkabber-plugins-0.11.1/checkers/pixmaps/xboard/bp.gif0000644000175000017500000000034410471327266022031 0ustar sergeisergeiGIF89a11!,11ڋ{IHؠ$›10wwm |P rcRW5nʋfuyִ uoF82Xx~_җ"@XȤrhX7IYyfHV&Y6f' 6iDVWa1{#v3:҂Fw,=M]m}Q;tkabber-plugins-0.11.1/checkers/pixmaps/xboard/wk.gif0000644000175000017500000000042710501561725022045 0ustar sergeisergeiGIF89a11!,11蔏ڋ{IHؠ$›q0wwm |P( rcRW5nʋfuyִf:G4zR//W'7WW4ׇ(Dxx IyR8 zJiZGhyzZ$l{[F) ܬ -  m=amVmmy.6qusFBHo01;tkabber-plugins-0.11.1/checkers/pixmaps/xboard/bf.gif0000644000175000017500000000013310471327266022013 0ustar sergeisergeiGIF89a11wm!,112ڋ޼H扦ʶ L Ģ;tkabber-plugins-0.11.1/checkers/pixmaps/xboard/bk.gif0000644000175000017500000000043210501561725022014 0ustar sergeisergeiGIF89a11!,11딏ڋ{IHؠ$›10wwm |P( rcRW5nʋfuy_9BZKS $(Tp68(WSx阠I)hj0q gw{yKKhօٗ\-= M<|Xa-Ӫu3F򭞡F/ <;tkabber-plugins-0.11.1/checkers/pixmaps/xboard/wf.gif0000644000175000017500000000013310471327266022040 0ustar sergeisergeiGIF89a11e!,112ڋ޼H扦ʶ L Ģ;tkabber-plugins-0.11.1/checkers/pixmaps/xboard/icondef.xml0000644000175000017500000000156710366754433023105 0ustar sergeisergei Xboard 1.0 Checkers Xboard Theme. 2006-01-23 checkers/bf bf.gif checkers/bk bk.gif checkers/bp bp.gif checkers/wf wf.gif checkers/wk wk.gif checkers/wp wp.gif tkabber-plugins-0.11.1/checkers/pixmaps/checkers/0000755000175000017500000000000011076120366021242 5ustar sergeisergeitkabber-plugins-0.11.1/checkers/pixmaps/checkers/wp.gif0000644000175000017500000000166010501561725022362 0ustar sergeisergeiGIF89a11 ! ,11@pH,Ȥrl:ШtJZlgTlK >!=$ vm| V| U| t S|c^ ʻ Q{cedk^ Posuu^ a} p식rf>bgԱ0ae :AHuI1 bѦ!C8uzA S1y#*brS 0`l0oY*ZRLho)` = ՅD:3T `ʉ@4.("t. G4 4ξ VL! 4XRԒY "K)-gI-@9Y!qtBJ*|C A Y?ږ@)J6xx@ rOthHb D_GXBIxLPψTTV87Ȅyy4Q<`u'9|8PCLv[xU#ha@D  v@i jiL#ʨ֤+k$M!wI(+[czUln'&6[D;tkabber-plugins-0.11.1/checkers/pixmaps/checkers/wk.gif0000644000175000017500000000177110501561725022360 0ustar sergeisergeiGIF89a115&&&//0777@@?FFFPOPWWW`__gggopoopppooppouuu!5,11pH,Ȥrl:ШtJZlFNE+sm#fڻnL!< -),np4,*'&aV|4&S  ,[-&  Pp|\iu Q&| i^^- ՟P|r,( Od46Т/ %,x5HpsiY]('p@b$SYj9;>Dj(`H`p<Mhp2ri` QWM&:u"0z 8!n\M5'XkBl0W}#nX`{ī)k[D;tkabber-plugins-0.11.1/checkers/pixmaps/checkers/bf.gif0000644000175000017500000000156510501561725022327 0ustar sergeisergeiGIF89a11 sQ1sY1{U1{Y1kUBsYJ{YBYBaBaJiB! ,11А" mAQ!Hn x&HLՕqdj~ˠ CiCbtB. 3=BN 7B+A'(7ay@\V76!~2 (HR99 / jͺbi8*ä8n$/b8,0{ډ#ɟT{VXkA Bl:iΖ"P.@-"C$P "h6Ŋ Wܩ垁pTγ5;$f &q pS?s|4:RMPX( 8XLy@ٖf <2] jBN@Ήi8-(EAВ%X?Bjg : ;t4BȞ "@duع:,m KndSFpULW67ŏ5j8*;I0܉vwK=Ig is Pm%t(լ M7 ќX;%\7_~=rB\?IJ%}[{Ef%Y*A{xgV K%)!Pi 20qG%*PF[|1@^[L8 TОm5@Z&C $"A_X`BρA !蕎wat( J% x`f ,p 'E۔% BcB P-f.N QL.P ݹoTL1fe( hvjEiؚk2`(jZQp%`x*s,ywy"m7'Q6++kE;tkabber-plugins-0.11.1/checkers/pixmaps/checkers/wf.gif0000644000175000017500000000147210501561725022351 0ustar sergeisergeiGIF89a11 ֢{ޮ{s{s֦ޮ޲޶綄羌! ,1103Р#>r(4I!pi'ci*%IhD q R=9(.Df!} f&4JJ ow]&_bYo1qz f(EGdk+oQy4 :-3_adl^hXmm4KuXqh : b|:vBД a> f¬ J|R'deת,PH'ݎpc!eBO @: G)9db`!( y:]{&bƬA} 8ϐ4Fx nP Nh !1Q`Z5ճIRJ7b*OP5@\'2*,5AKŜCĠhGmX"D%eR@lP\7I]O)3FqEzH@]̆=KegOU .QRMa DvNʱm_oBaȽ{c6euo`\jI.)3:P{9%G'}mp_bV cX/`.N!xN%TA{d`/!wxBIdBC!`3j ?搉̩cBG:4;ődvY*29dT"NVMS#x(epDiֳ`/ZVd%Ic@e%|lݶeAI2@;tkabber-plugins-0.11.1/checkers/pixmaps/checkers/icondef.xml0000644000175000017500000000156210366754433023410 0ustar sergeisergei Checkers 1.0 Checkers Theme. 2006-01-23 checkers/bf bf.gif checkers/bk bk.gif checkers/bp bp.gif checkers/wf wf.gif checkers/wk wk.gif checkers/wp wp.gif tkabber-plugins-0.11.1/mute/0000755000175000017500000000000011076120366015155 5ustar sergeisergeitkabber-plugins-0.11.1/mute/msgs/0000755000175000017500000000000011076120366016126 5ustar sergeisergeitkabber-plugins-0.11.1/mute/msgs/ru.msg0000644000175000017500000000114110573755632017274 0ustar sergeisergei::msgcat::mcset ru "Commit current version" "Записать текущую версию" ::msgcat::mcset ru "Edit %s" "Редактировать %s" ::msgcat::mcset ru "Error getting list: %s" "Ошибка при получении списка: %s" ::msgcat::mcset ru "Error patching: %s" "Ошибка при внесении изменений: %s" ::msgcat::mcset ru "List of texts from %s" "Список текстов от %s" ::msgcat::mcset ru "MUTE" "МПТР" ::msgcat::mcset ru "Revert to master version" "Вернуться к основной версии" # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/mute/mute.tcl0000644000175000017500000003015610747411465016647 0ustar sergeisergei# $Id: mute.tcl 1354 2008-01-28 17:39:01Z sergei $ set ::NS(mute_ancestor) "http://jabber.org/protocol/mute#ancestor" set ::NS(mute_editor) "http://jabber.org/protocol/mute#editor" package require msgcat namespace eval mute {} namespace eval mute::editor { ::msgcat::mcload [file join [file dirname [info script]] msgs] } proc mute::editor::get_winid {connid jid id} { return [win_id mute [list $connid $jid]//@mute@//$id] } proc mute::editor::add_user_menu_item {m connid jid} { $m add command \ -label [::msgcat::mc "MUTE"] \ -command [list [namespace current]::list_request $connid $jid] } hook::add roster_create_groupchat_user_menu_hook \ [namespace current]::mute::editor::add_user_menu_item 49 hook::add chat_create_user_menu_hook \ [namespace current]::mute::editor::add_user_menu_item 49 hook::add roster_jid_popup_menu_hook \ [namespace current]::mute::editor::add_user_menu_item 49 proc mute::editor::list_request {connid jid} { jlib::send_iq get \ [jlib::wrapper:createtag list \ -vars [list xmlns $::NS(mute_ancestor)]] \ -to $jid \ -command [list [namespace current]::list_recv $connid $jid] \ -connection $connid } proc mute::editor::list_recv {connid jid res child} { variable txts if {$res != "OK"} { after idle [list MessageDlg .mute_list_error -icon error \ -message [::msgcat::mc "Error getting list: %s" \ [error_to_string $child]] \ -type ok] return "" } jlib::wrapper:splitxml $child tag vars isempty chdata children set ids {} foreach ch $children { jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1 set id [jlib::wrapper:getattr $vars1 id] lappend ids $id set desc($id) [jlib::wrapper:getattr $vars1 desc] } set w .mute_invite if {[winfo exists $w]} { destroy $w } Dialog $w -title [::msgcat::mc "List of texts from %s" $jid] \ -separator 1 -anchor e -default 0 foreach id $ids { $w add -text "$id: $desc($id)" \ -command [list [namespace current]::subscribe_request $connid $jid $id] } $w add -text Cancel -command [list destroy $w] $w draw } proc mute::editor::subscribe_request {connid jid id} { jlib::send_iq set \ [jlib::wrapper:createtag subscribe \ -vars [list xmlns $::NS(mute_ancestor)] \ -subtags [list [jlib::wrapper:createtag item \ -vars [list id $id]]]] \ -to $jid \ -command [list [namespace current]::subscribe_recv $connid $jid $id] \ -connection $connid } proc mute::editor::subscribe_recv {connid jid id res child} { variable txts if {$res != "OK"} { after idle [list MessageDlg .mute_list_error -icon error \ -message [::msgcat::mc "Error getting list: %s" \ [error_to_string $child]] \ -type ok] return "" } } proc mute::editor::open_win {connid jid id} { variable txts set w [get_winid $connid $jid $id] if {[winfo exists $w]} { return } add_win $w -title [::msgcat::mc "Edit %s" $id] \ -tabtitle [::msgcat::mc "Edit %s" $id] \ -class Mute set bbox [ButtonBox $w.bbox -spacing 10 -padx 10] pack $bbox -side bottom -anchor e $bbox add -text [::msgcat::mc "Commit current version"] \ -command [list [namespace current]::commit $connid $jid $id] $bbox add -text [::msgcat::mc "Revert to master version"] \ -command [list [namespace current]::revert $connid $jid $id] set sep [Separator::create $w.sep -orient horizontal] pack $sep -pady 2m -fill x -side bottom set sw [ScrolledWindow $w.sw] set text [text $w.text] pack $sw -side top -anchor w -expand yes -fill both $sw setwidget $text } proc mute::editor::get_textw {connid jid id} { return "[get_winid $connid $jid $id].text" } proc mute::editor::set_text {connid jid id text} { variable txts set txts(text,$connid,$jid,$id) $text set t [get_textw $connid $jid $id] $t delete 1.0 end $t insert 0.0 $text } proc mute::editor::revert {connid jid id} { variable txts set text $txts(text,$connid,$jid,$id) set tw [get_textw $connid $jid $id] lassign [split [$tw index insert] .] line pos $tw delete 1.0 end $tw insert 0.0 $text $tw mark set insert "$line.$pos" } proc mute::editor::commit {connid jid id} { variable txts set orig $txts(text,$connid,$jid,$id) set tw [get_textw $connid $jid $id] set edit [$tw get 1.0 "end -1 chars"] if {[cindex $edit end] != "\n"} { set edit "$edit\n" } # TODO: check temp files set fn "/tmp/mute[rand 1000000]" set fd [open $fn.orig w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $orig close $fd set fd [open $fn.edit w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $edit close $fd catch { exec diff -u $fn.orig $fn.edit > $fn.diff } set fd [open $fn.diff r] fconfigure $fd -encoding utf-8 gets $fd gets $fd set diff [read $fd] close $fd file delete $fn.orig $fn.edit $fn.diff if {$diff != ""} { jlib::send_iq set \ [jlib::wrapper:createtag patch \ -vars [list xmlns $::NS(mute_ancestor) id $id] \ -chdata $diff] \ -to $jid \ -command [list [namespace current]::patch_res $connid $jid $id] \ -connection $connid } } proc mute::editor::patch_res {connid jid id res child} { variable txts if {$res != "OK"} { after idle [list MessageDlg .mute_list_error -icon error \ -message [::msgcat::mc "Error patching: %s" \ [error_to_string $child]] \ -type ok] return "" } set text $txts(text,$connid,$jid,$id) set tw [get_textw $connid $jid $id] lassign [split [$tw index insert] .] line pos $tw delete 1.0 end $tw insert 0.0 $text $tw mark set insert "$line.$pos" } proc mute::editor::patch {connid jid id patch} { variable txts set tw [get_textw $connid $jid $id] if {![info exists txts(text,$connid,$jid,$id)] || ![winfo exists $tw]} { return [list error cancel not-allowed] } set text $txts(text,$connid,$jid,$id) set edit [$tw get 1.0 "end -1 chars"] lassign [split [$tw index insert] .] line pos # TODO: check temp files set fn "/tmp/mute[rand 1000000]" set fd [open $fn.old w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $text close $fd set fd [open $fn.orig w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $text close $fd set fd [open $fn.patch w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $patch close $fd set fd [open $fn.edit w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $edit close $fd if {[catch { exec patch $fn.orig $fn.patch }]} { puts "something wrong..." return } set fd [open $fn.orig r] fconfigure $fd -encoding utf-8 set new [read $fd] close $fd catch { exec merge $fn.edit $fn.old $fn.orig } set fd [open $fn.edit r] fconfigure $fd -encoding utf-8 set newedit [read $fd] close $fd file delete $fn.old $fn.orig $fn.patch $fn.edit set txts(text,$connid,$jid,$id) $new $tw delete 1.0 end $tw insert 0.0 $newedit set lineregexp {@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@} set shift 0 foreach l [split $patch \n] { if {[regexp $lineregexp $l temp ol os nl ns]} { if {$ol >= $line} break set shift [expr {$nl + $ns - $ol - $os}] } } set line [expr {$line + $shift}] $tw mark set insert "$line.$pos" return [list result ""] } proc mute::editor::recv_set_iq {connid from lang child} { jlib::wrapper:splitxml $child tag vars isempty chdata children switch -- $tag { text { set id [jlib::wrapper:getattr $vars id] open_win $connid $from $id set_text $connid $from $id $chdata } patch { set id [jlib::wrapper:getattr $vars id] set patch $chdata return [patch $connid $from $id $patch] } default { return [list error cancel feature-not-implemented] } } } iq::register_handler set {} $::NS(mute_editor) \ [namespace current]::mute::editor::recv_set_iq ############################################################################### namespace eval mute::ancestor { set txts(ids) {id1 id2} set txts(desc,id1) "Useful text" set txts(desc,id2) "Useless text" set txts(text,id1) "... 8. Admin Use Cases 8.1. Banning a User 8.2. Modifying the Ban List 8.3. Granting Membership 8.4. Revoking Membership 8.5. Modifying the Member List 8.6. Granting Moderator Privileges 8.7. Revoking Moderator Privileges 8.8. Modifying the Moderator List ... " set txts(text,id2) "" } proc mute::ancestor::send_text {connid jid id} { variable txts jlib::send_iq set \ [jlib::wrapper:createtag text \ -vars [list xmlns $::NS(mute_editor) id $id] \ -chdata $txts(text,$connid,$id)] \ -to $jid \ -connection $connid # -command [list [namespace current]::subscribe_recv $connid $jid $id] } proc mute::ancestor::patch {connid jid id patch} { variable txts set text $txts(text,$connid,$id) # TODO: check temp files set fn "/tmp/mute[rand 1000000]" set fd [open $fn.orig w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $text close $fd set fd [open $fn.patch w] fconfigure $fd -encoding utf-8 puts -nonewline $fd $patch close $fd if {[catch { exec patch $fn.orig $fn.patch }]} { return [list error cancel not-allowed] } set fd [open $fn.orig r] fconfigure $fd -encoding utf-8 set new [read $fd] close $fd file delete $fn.orig $fn.patch set txts(text,$connid,$id) $new after idle [list [namespace current]::distribute_patch $connid $id $patch] return [list result ""] } proc mute::ancestor::distribute_patch {connid id patch} { variable txts foreach subscriber $txts(subscribed,$connid,$id) { jlib::send_iq set \ [jlib::wrapper:createtag patch \ -vars [list xmlns $::NS(mute_editor) id $id] \ -chdata $patch] \ -to $subscriber \ -command [list [namespace current]::unsubscribe_on_error \ $connid $subscriber $id] \ -connection $connid } } proc mute::ancestor::unsubscribe_on_error {connid jid id res child} { variable txts if {$res != "OK"} { set idx [lsearch -exact $txts(subscribed,$connid,$id) $jid] set txts(subscribed,$connid,$id) [lreplace $txts(subscribed,$connid,$id) $idx $idx] puts "REMOVE $connid $jid" } } proc mute::ancestor::recv_get_iq {connid from lang child} { jlib::wrapper:splitxml $child tag vars isempty chdata children switch -- $tag { list { variable txts # TODO if {![info exists txts(ids,$connid)]} { set txts(ids,$connid) $txts(ids) foreach id $txts(ids) { set txts(desc,$connid,$id) $txts(desc,$id) set txts(text,$connid,$id) $txts(text,$id) } } set items {} foreach id $txts(ids,$connid) { lappend items [jlib::wrapper:createtag item \ -vars [list id $id desc $txts(desc,$connid,$id)]] } return [list result [jlib::wrapper:createtag list \ -vars [list xmlns $::NS(mute_ancestor)] \ -subtags $items]] } default { return [list error cancel feature-not-implemented] } } return "" } iq::register_handler get {} $::NS(mute_ancestor) \ [namespace current]::mute::ancestor::recv_get_iq proc mute::ancestor::recv_set_iq {connid from lang child} { jlib::wrapper:splitxml $child tag vars isempty chdata children switch -- $tag { subscribe { variable txts foreach ch $children { jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1 set id [jlib::wrapper:getattr $vars1 id] if {[lcontain $txts(ids,$connid) $id]} { lappend txts(subscribed,$connid,$id) $from set txts(subscribed,$connid,$id) [lrmdups $txts(subscribed,$connid,$id)] after idle [list [namespace current]::send_text $connid $from $id] return [list result ""] } else { return [list error modify bad-request] } } return [list error modify bad-request] } patch { set id [jlib::wrapper:getattr $vars id] set patch $chdata return [patch $connid $from $id $patch] } default { return [list error cancel feature-not-implemented] } } return "" } iq::register_handler set {} $::NS(mute_ancestor) \ [namespace current]::mute::ancestor::recv_set_iq tkabber-plugins-0.11.1/spy/0000755000175000017500000000000011076120366015016 5ustar sergeisergeitkabber-plugins-0.11.1/spy/msgs/0000755000175000017500000000000011076120366015767 5ustar sergeisergeitkabber-plugins-0.11.1/spy/msgs/pl.msg0000644000175000017500000000214010667535014017114 0ustar sergeisergei# Polish messages file for presence spy plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Presence Spy" "Śledzenie statusów" ::msgcat::mcset pl "Spy" "Śledzenie statusów" ::msgcat::mcset pl "Spy presence" "Śledzenie statusów" ::msgcat::mcset pl "Set watch" "Ustaw czujkę" ::msgcat::mcset pl "Spy Presence plugin options." "Ustawienia wtyczki śledzenia statusów." ::msgcat::mcset pl "File to log Spy Presence messages." "Nazwa pliku do którego zapisywane będą śledzone statusy." ::msgcat::mcset pl "Format of timestamp in Spy Presence window." "Format znacznika czasu w oknie śledzenia statusów." ::msgcat::mcset pl "Alert when available" "Alarmuj kiedy kontakt staje się dostępny" ::msgcat::mcset pl "Spy Alert: user %s (%s) is available!" "Alarm śledzenia statusów: użytkownik %s (%s) jest dostępny!" ::msgcat::mcset pl "Open chat" "Rozpocznij rozmowę" ::msgcat::mcset pl "Cancel" "Anuluj" ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "Remove" "Usuń" tkabber-plugins-0.11.1/spy/msgs/es.msg0000644000175000017500000000153510577062431017115 0ustar sergeisergei::msgcat::mcset es "Alert when available" "Alertar cuando disponible" ::msgcat::mcset es "Cancel" "Cancelar" ::msgcat::mcset es "File to log Spy Presence messages." "Fichero donde guardar mensajes de Espia Presencia." ::msgcat::mcset es "Format of timestamp in Spy Presence window." "Formato del tiempo en la ventana de Espia Presencia." ::msgcat::mcset es "Open chat" "Abrir charla" ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Presence Spy" "Espia Presencia" ::msgcat::mcset es "Remove" "Borrar" ::msgcat::mcset es "Set watch" "Guardar" ::msgcat::mcset es "Spy Alert: user %s (%s) is available!" "Alerta Espia: el usuario %s (%s) está conectado" ::msgcat::mcset es "Spy Presence plugin options." "Opciones del plugin Espia Presencias." ::msgcat::mcset es "Spy presence" "Espiar presencia" ::msgcat::mcset es "Spy" "Espia" tkabber-plugins-0.11.1/spy/msgs/de.msg0000644000175000017500000000237610714654517017107 0ustar sergeisergei # German messages file # Roger Sondermann 08.11.2007 ::msgcat::mcset de "Alert when available" "Benachrichtigen wenn verfgbar" ::msgcat::mcset de "Cancel" "Abbrechen" ::msgcat::mcset de "File to log Spy Presence messages." "Datei, in die Prsenz-Spion-Nachrichten geschrieben werden sollen." ::msgcat::mcset de "Format of timestamp in Spy Presence window." "Format des Zeitstempels im Prsenz-Spion-Fenster." ::msgcat::mcset de "Open chat" "Chat ffnen" ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "Presence Spy" "Prsenz-Spion" ::msgcat::mcset de "Remove" "Entfernen:" ::msgcat::mcset de "Set watch" "berwachen:" ::msgcat::mcset de "Spy Alert: user %s (%s) is available!" "Spion-Benachrichtigung: Benutzer %s (%s) ist verfgbar!" ::msgcat::mcset de "Spy Presence plugin options." "Optionen fr das Prsenz-Spion-Plugin." ::msgcat::mcset de "Spy presence" "Prsenz-Spion" ::msgcat::mcset de "Spy" "Prsenz-Spion" tkabber-plugins-0.11.1/spy/msgs/ru.msg0000644000175000017500000000223310424225136017122 0ustar sergeisergei::msgcat::mcset ru "Alert when available" "Предупреждать при появлении" #::msgcat::mcset ru "Cancel" "Отменить" ::msgcat::mcset ru "File to log Spy Presence messages." "Файл, в который сохраняется информация о присутствии." ::msgcat::mcset ru "Format of timestamp in Spy Presence window." "Формат вывода даты/времени в шпионском окне." #::msgcat::mcset ru "Open chat" "Открытие окна разговора" #::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Presence Spy" "Espia Presencia" #::msgcat::mcset ru "Remove" "Удалить" ::msgcat::mcset ru "Set watch" "Установить наблюдение" ::msgcat::mcset ru "Spy Alert: user %s (%s) is available!" "Тревога: пользователь %s (%s) доступен!" ::msgcat::mcset ru "Spy Presence plugin options." "Настройки расширения, шпионящего за присутствием." ::msgcat::mcset ru "Spy presence" "Шпионить за присутствием" ::msgcat::mcset ru "Spy" "Шпион" tkabber-plugins-0.11.1/spy/msgs/uk.msg0000644000175000017500000000207310543571750017125 0ustar sergeisergei ::msgcat::mcset uk "Alert when available" "Сповіщати коли доступний" ::msgcat::mcset uk "Cancel" "Відмінити" ::msgcat::mcset uk "File to log Spy Presence messages." "Файл протоколу для повідомлень шпигуна." ::msgcat::mcset uk "Format of timestamp in Spy Presence window." "Формат дати/часу у вікні шпигуна." ::msgcat::mcset uk "Open chat" "Відкрити розмову" ::msgcat::mcset uk "Plugins options." "Параметри плагінів." ::msgcat::mcset uk "Presence Spy" "Шпигун" ::msgcat::mcset uk "Remove" "Видалити" ::msgcat::mcset uk "Set watch" "Установити нагляд" ::msgcat::mcset uk "Spy Alert: user %s (%s) is available!" "Сповіщення від шпигуна: користувач %s (%s) доступний" ::msgcat::mcset uk "Spy Presence plugin options." "Параметри плагіна Spy Presence." ::msgcat::mcset uk "Spy presence" "Шпигувати за присутністю" ::msgcat::mcset uk "Spy" "Шпигун" tkabber-plugins-0.11.1/spy/spy.tcl0000644000175000017500000002624710747411465016357 0ustar sergeisergei# Tkabber presence spy module, version 1.0 # Copyright (C) 2003 Maciek Pasternacki # # Traces presence messages, logging them into tkabber window # and/or file. # option add *Spy.timestampforeground Black widgetDefault option add *Spy.nickforeground DarkBlue widgetDefault option add *Spy.jidforeground DarkBlue widgetDefault option add *Spy.presenceforeground DarkRed widgetDefault option add *Spy.reasonforeground DarkMagenta widgetDefault package require msgcat namespace eval spy { set the_file "" set watches {} variable options variable scriptdir [file dirname [info script]] ::msgcat::mcload [file join $scriptdir msgs] custom::defgroup Plugins [::msgcat::mc "Plugins options."] \ -group Tkabber custom::defgroup Spy [::msgcat::mc "Spy Presence plugin options."] \ -group Plugins custom::defvar options(log_file) "" \ [::msgcat::mc "File to log Spy Presence messages."] \ -type string -group Spy custom::defvar options(timestamp_format) {[%m/%d %R]} \ [::msgcat::mc "Format of timestamp in Spy Presence window."] \ -type string -group Spy } proc spy::open_window {} { variable watches set w .spy if {[winfo exists $w]} { raise_win $w return } add_win $w -title [::msgcat::mc "Presence Spy"] \ -tabtitle [::msgcat::mc "Spy"] \ -class Spy \ -raisecmd [list focus $w.log] \ -raise 1 frame $w.controls button $w.controls.add -text [::msgcat::mc "Set watch"] \ -command "[namespace current]::set_watch" set watch_entry [entry $w.controls.watch_regex] bind $watch_entry "[namespace current]::set_watch" pack $w.controls.add -side left -anchor e pack $watch_entry -side left -anchor w -fill x pack $w.controls -side bottom -fill x frame $w.watches foreach watch $watches { set watch_id [lindex $watch 0] set watch_regex [lindex $watch 1] add_watch_frame $watch_id $watch_regex } pack $w.watches -side bottom -fill x set sw [ScrolledWindow $w.isw -scrollbar vertical] pack $sw -side top -fill both -expand yes -in $w set log [text $w.log -wrap word] $sw setwidget $log $log configure -state disabled -takefocus 1 bind $log <1> [list focus $log] $log tag configure timestamp \ -foreground [option get $w timestampforeground Spy] $log tag configure nick \ -foreground [option get $w nickforeground Spy] $log tag configure jid \ -foreground [option get $w jidforeground Spy] $log tag configure presence \ -foreground [option get $w presenceforeground Spy] $log tag configure reason \ -foreground [option get $w reasonforeground Spy] search::setup_panel $w } proc spy::set_watch {} { variable watches set w .spy if {![winfo exists $w]} return set entr $w.controls.watch_regex set regex [$entr get] if { $regex == "" } return # Add new watch if there is no such already present set next_watch [expr [llength $watches] + 1] foreach watch $watches { set r [lindex $watch 1] set idx [lindex $watch 0] if {$r == $regex} { #set b [$w.watches.$idx cget -background] #$w.watches.$idx configure -background red #after 1500 [list $w.watches.$idx configure -background $b] return } } if {[catch { regexp $regex "" }]} { $entr configure -fg [option get $entr errorForeground Entry] return } else { $entr configure -fg [option get $entr foreground Entry] } lappend watches [list $next_watch $regex] add_watch_frame $next_watch $regex } proc spy::add_watch_frame {watch_id watch_regex} { variable spy_alerts set w .spy if {![winfo exists $w]} return frame $w.watches.$watch_id button $w.watches.$watch_id.remove -text [::msgcat::mc "Remove"] \ -command [list [namespace current]::remove_watch $watch_id $watch_regex] label $w.watches.$watch_id.regex -text $watch_regex \ -foreground [option get $w nickforeground Spy] label $w.watches.$watch_id.nick -text "" \ -foreground [option get $w nickforeground Spy] label $w.watches.$watch_id.jid -text "" \ -foreground [option get $w nickforeground Spy] label $w.watches.$watch_id.timestamp -text "" \ -foreground [option get $w timestampforeground Spy] label $w.watches.$watch_id.presence -text "" \ -foreground [option get $w presenceforeground Spy] label $w.watches.$watch_id.reason -text "" \ -foreground [option get $w reasonforeground Spy] checkbutton $w.watches.$watch_id.alert -text [::msgcat::mc "Alert when available"] \ -variable [namespace current]::spy_alerts($watch_id) set [namespace current]::spy_alerts($watch_id) 0 pack $w.watches.$watch_id.remove \ $w.watches.$watch_id.regex \ $w.watches.$watch_id.timestamp \ $w.watches.$watch_id.nick \ $w.watches.$watch_id.jid \ $w.watches.$watch_id.presence -side left pack $w.watches.$watch_id.alert -side right pack $w.watches.$watch_id.reason -side left -fill x pack $w.watches.$watch_id -side bottom -fill x } proc spy::remove_watch {watch_id watch_regex} { variable watches set w .spy.watches.$watch_id if {![winfo exists $w]} return set idx [lsearch -exact $watches [list $watch_id $watch_regex]] set watches [lreplace $watches $idx $idx] destroy $w } proc spy::update_watch {connid watch_id nick jid type reason} { variable options variable spy_alerts set w .spy.watches.$watch_id if {![winfo exists $w]} return $w.timestamp configure -text \ [clock format [clock seconds] -format $options(timestamp_format)] $w.nick configure -text $nick $w.jid configure -text $jid $w.presence configure -text $type $w.reason configure -text $reason if { $spy_alerts($watch_id) && $type=="available" } { alert_dialog $connid $watch_id $nick $jid } } proc spy::alert_dialog {connid watch_id nick jid} { set w .spy_alert_${watch_id} if {[winfo exists $w]} { destroy $w } set message [format [::msgcat::mc "Spy Alert: user %s (%s) is available!"] $nick $jid] Dialog $w -title $message -modal none -separator 1 -anchor e -default 0 -cancel 1 set frame [$w getframe] message $frame.msg -text $message -width 70c pack $frame.msg -side left -fill x $w add -text [::msgcat::mc "Open chat"] -command [list [namespace current]::open_chat $w $connid $jid ] $w add -text [::msgcat::mc "Cancel"] -command [list destroy $w] $w draw } proc spy::open_chat {w connid jid} { destroy $w chat::open_to_user $connid $jid } proc spy::display {connid jid nick type reason} { variable options variable watches set w .spy if {![winfo exists $w]} return set log $w.log $log configure -state normal $log insert end \ [clock format [clock seconds] -format $options(timestamp_format)] timestamp $log insert end " " if { "$nick"!="" } { $log insert end "$nick" nick $log insert end " (" $log insert end "$jid" jid $log insert end ") " } else { $log insert end "$jid" jid $log insert end " " } $log insert end "$type" presence if { "$reason"!="" } { $log insert end " (" $log insert end "$reason" reason $log insert end ")" } $log insert end "\n" $log see end $log configure -state disabled foreach watch $watches { set watch_id [lindex $watch 0] set watch_regex [lindex $watch 1] if {[regexp "$watch_regex" $nick temp] || [regexp "$watch_regex" $jid temp]} { update_watch $connid $watch_id $nick $jid $type $reason } } } proc spy::client_presence_handler {connid from type x args} { variable options variable the_file if {[catch { chat::get_nick $connid $from chat } nick]} { if {[catch { chat::get_nick $from chat } nick]} { set nick $from } } if { "$nick"=="$from" } { set nick "" } set reason "" set show "" foreach {attr val} $args { switch -- $attr { -status {set reason $val} -show {set show $val} } } if { "$type"=="" } { set type "available" } if { "$show"!="" } { set type "$type/$show" } display "$connid" "$from" "$nick" "$type" "$reason" if {$options(log_file) != "" && $the_file == ""} { init_spy } if {$options(log_file) == "" && $the_file != ""} { deinit_spy } if {$the_file != ""} { puts -nonewline $the_file "[clock format [clock seconds]] " if {$nick != ""} { puts -nonewline $the_file "$nick ($from) " } else { puts -nonewline $the_file "$from " } puts -nonewline $the_file "$type" if {$reason != ""} { puts -nonewline $the_file " ($reason)" } puts $the_file {} flush $the_file } } proc spy::init_spy {} { variable the_file variable options if {$options(log_file) != ""} { if {$the_file != ""} { catch { close $the_file } set the_file "" } set the_file [open $options(log_file) a] puts $the_file "[clock format [clock seconds]] Started spying." } } proc spy::deinit_spy {} { variable the_file if {$the_file != ""} { puts $the_file "[clock format [clock seconds]] Spy goes away." catch { close $the_file } set the_file "" } } proc spy::setup_menu {} { catch { set m [.mainframe getmenu plugins] $m add command -label [::msgcat::mc "Spy presence"] \ -command [namespace current]::open_window } } hook::add postload_hook [namespace current]::spy::init_spy 100 hook::add client_presence_hook [namespace current]::spy::client_presence_handler 100 hook::add quit_hook [namespace current]::spy::deinit_spy 100 hook::add finload_hook [namespace current]::spy::setup_menu namespace eval spy::search {} proc spy::search::open_panel {w sf} { pack $sf -side bottom -anchor w -fill x -before $w.isw update idletasks $w.log see end } proc spy::search::close_panel {w sf} { $w.log tag remove search_highlight 0.0 end pack forget $sf focus $w.log } proc spy::search::setup_panel {w} { set log $w.log $log mark set sel_start end $log mark set sel_end 0.0 set sf [plugins::search::spanel [winfo parent $log].search \ -searchcommand [list ::plugins::search::do_text_search $log] \ -closecommand [list [namespace current]::close_panel $w]] bind $w.log <> \ [double% [list [namespace current]::open_panel $w $sf]] } ############################################################################## proc spy::restore_window {args} { open_window } proc spy::save_session {vsession} { upvar 2 $vsession session global usetabbar # We don't need JID at all, so make it empty (special case) set user "" set server "" set resource "" # TODO if {!$usetabbar} return set prio 0 foreach page [.nb pages] { set path [ifacetk::nbpath $page] if {[string equal $path .spy]} { lappend session [list $prio $user $server $resource \ [list [namespace current]::restore_window] \ ] } incr prio } } hook::add save_session_hook [namespace current]::spy::save_session tkabber-plugins-0.11.1/attline/0000755000175000017500000000000011076120366015643 5ustar sergeisergeitkabber-plugins-0.11.1/attline/README0000644000175000017500000001237210716640747016542 0ustar sergeisergei$Id: README 1313 2007-11-14 18:43:51Z sergei $ "Attention line" -- chat plugin for Tkabber. I. The idea This plugin helps to track discussion flow in high-volume chats by remembering the last message you have read in each chat window when you're leaving it and drawing a horizontal line just below that message when you return back to that chat window. This line is called the "attention line" since its task is to draw your attention to the point at which you stopped to attend the chat when you're back. "Leaving of the chat window" described above applies not only to the physical top-level chat windows in windowed mode but also to switching between chat tabs in tabbed mode. In tabbed mode leaving the main window is also considered as leaving the currently active chat tab, if any. So everywhere in this document, when you see "chat window" you can safely interpret it as "chat tab" if you're using tabbed mode in Tkabber. II. Usage The behaviour of the attention line is governed by its "expiration timeout". When you switch to a chat window and the chat log in that window contains unread messages, expiration line is placed just below the last read message. At that time the attention line expiration timer starts to tick. If you leave the chat window again until the timeout expires, the attention line is left intact as if you haven't switched to that window at all. Otherwise, if the timeout expires while you're in this chat window its attention line is considered "expired" and the chat log is considered as read. Normally the attention line doesn't do anything when it expires but you can make it disappear, if you so like (see the "Configuration" section below). When you leave the chat window with expired attention line and then switch back to it later the attention line will be placed just above the first message arrived while you haven't attending that chat window and the expiration timer starts again. The expiration timeout is configurable and can be disabled. If it's still not quite clear, you can consider this "expiration timeout" as "time to read", i.e. the time which must tick before the chat window you're currently attending is considered "read" (by you). When the chat window is active and its attention line is expired any new messages arriving in this chat are considered "read" immediately and doesn't affect the attention line. Chat input window is given one special Tk virtual event [1] named <> which is unbound by default but can be bound [2] to any Tk event (usually, a keyboard shortcut) and then used to move the chat log viewport to the place where the attention line is currently located. III. Configuration. You can configure the behavior of the attention line via Tkabber's Customize mechanism and its visual appearance via Tk option database [3]. Configuration parameters are available in the "Chat" -> "Attention Line" group of Customize settings (which are accessible via the "Tkabber" -> "Customize" main menu entry. There are two options to configure: * ::plugins::attline::options(expires_after) -- sets the attention line expiration timeout (in milliseconds). If set to 0 or a negative value attention line is considered expired right after you switch to a chat window it's placed in. The default value is 1000. * ::plugins::attline::options(remove_expired) -- when set, makes the attention line disappear when it's expired. (Note that when attention line is removed the text in the chat window is shifted to fill the gap which may be visually disturbing.) This flag is off by default. There's almost no sense to use removal of expired attention line along with its immediate expiration. Visual appearance is controlled by a set of Tk option database parameters: * Chat.attentionLineHeight -- controls the thickness (in pixels) of the attention line. (Note that some amount of white space is added above and below the attention line by the text widget which draws the attention line.) The default value is 1. * Chat.attentionLineColor -- color of the attention line. Can be specified in any form described in [4]. The default value is "red". * Chat.attentionLinePadX -- amount of extra white space to pad the attention line from left and right. The default value is 5. * Chat.attentionLinePadY -- amount of extra white space to pad the attention line above and below. The default value is 0. Example: # Expire attention line after 5 seconds of attending # the chat window: set ::plugins::attline::options(expires_after) 5000 # Make attention line green-coloured: option add *Chat.attentionLineColor green IV. Limitations. The attention line mechanism doesn't take into account the actual number of unread messages that exist in the chat window when you switch into it: after the expiration timeout is over the chat window is considered read no matter whether you have actually seen any unread messages. You can use the "chat bookmarks" builtin facility to attach a bookmark to any message in a chat window (this action can be accessed from the context menu of the widget that renders chat messages). V. Links 1. http://www.tcl.tk/man/tcl8.4/TkCmd/event.htm 2. http://www.tcl.tk/man/tcl8.4/TkCmd/bind.htm 3. http://www.tcl.tk/man/tcl8.4/TkCmd/option.htm 4. http://www.tcl.tk/man/tcl8.4/TkLib/GetColor.htm # vim:tw=64:noet tkabber-plugins-0.11.1/attline/msgs/0000755000175000017500000000000011076120366016614 5ustar sergeisergeitkabber-plugins-0.11.1/attline/msgs/pl.msg0000644000175000017500000000201010667535014017735 0ustar sergeisergei# Polish messages file for attline plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Attention Line chat plugin options. This plugin draws horizontal line separating read and unread messages in chat windows." "Ustawienia wtyczki separatora aktywności. Wtyczka ta wstawia wstawia poziomą linię oddzielającą przeczytane i nieprzeczytane wiadomości w rozmowie." ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "Remove the attention line after it was expired from its chat window." "Usuń separator nieaktywności po tym jak stracił ważność w oknie rozmowy." ::msgcat::mcset pl "Time (in milliseconds) after which unread messages in the currently active chat window are considered read and the attention line is considered expired." "Czas (w milisekundach), po którym nieprzeczytane wiadomości w aktywnym oknie rozmowy zostaną uznane za przeczytane i separator starci ważność." tkabber-plugins-0.11.1/attline/msgs/es.msg0000644000175000017500000000160110712161173017726 0ustar sergeisergei::msgcat::mcset es "Attention Line chat plugin options. This plugin draws horizontal line separating read and unread messages in chat windows." "Opciones del plugin de charla Attention Line. Este plugin dibuja una línea horizontal que separa los mensajes viejos leídos de los nuevos mensajes aún no leídos en la ventana de charla." ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Remove the attention line after it was expired from its chat window." "Borra la línea de atención de la ventana de charla cuando expire." ::msgcat::mcset es "Time (in milliseconds) after which unread messages in the currently active chat window are considered read and the attention line is considered expired." "Tiempo (en milisegundos) desde que un mensaje no leído en la ventana de charla activa se considera leído y se borra la línea de atención se considera expirada." tkabber-plugins-0.11.1/attline/msgs/de.msg0000644000175000017500000000165210771407202017716 0ustar sergeisergei # German messages file # Roger Sondermann 09.03.2008 ::msgcat::mcset de "Attention Line chat plugin options. This plugin draws horizontal line separating read and unread messages in chat windows." "Optionen fr das Augenmerk-Linie-Plugin.\nDieses zeichnet in Chat-Fenstern eine horizontale Linie zur Trennung gelesener und ungelesener Nachrichten." ::msgcat::mcset de "Plugins options." "Optionen fr Plugins." ::msgcat::mcset de "Remove the attention line after it was expired from its chat window." "Augenmerk-Linie entfernen, nachdem sie verfallen ist." ::msgcat::mcset de "Time (in milliseconds) after which unread messages in the currently active chat window are considered read and the attention line is considered expired." "Zeitraum nach dem ungelesene Nachrichten im aktiven Chat-Fenster als gelesen und die Augenmerk-Linie als verfallen betrachtet wird (in Millisekunden)." tkabber-plugins-0.11.1/attline/msgs/ru.msg0000644000175000017500000000230110704427230017743 0ustar sergeisergei::msgcat::mcset ru \ "Attention Line chat plugin options. This plugin draws horizontal\ line separating read and unread messages in chat windows." \ "Настройки расширения Attention Line. Это расширение отделяет непрочитанные\ сообщения в окнах разговора от прочитанных горизонтальной линией." ::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Remove the attention line after it was expired from its chat window." \ "Удалять линию, разделяющую сообщения по истечении времени её действия." ::msgcat::mcset ru \ "Time (in milliseconds) after which unread messages in the currently\ active chat window are considered read and the attention line is considered expired." \ "Время (в миллисекундах) по истечении которого сообщения в активном окне разговора\ считаются прочитанными, и разделительная линия считается недействующей." tkabber-plugins-0.11.1/attline/TODO0000644000175000017500000000045710716640747016353 0ustar sergeisergei$Id: TODO 1313 2007-11-14 18:43:51Z sergei $ * Remove att. line when a buffer marked as read loses focus instead of moving it to the bottom may be? * Calculation of line width isn't quite correct: left padding seems to be more than right. * Check whether the att. line can be made even thinner. tkabber-plugins-0.11.1/attline/license.terms0000644000175000017500000000211210661352400020330 0ustar sergeisergeiCopyright (c) 2007 Konstantin Khomoutov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tkabber-plugins-0.11.1/attline/INSTALL0000644000175000017500000000062510716640747016711 0ustar sergeisergeiAs usually, copy this directory under the ~/.tkabber/plugins directory so that you get a hierarchy like this: ~/.tkabber/plugins ~/.tkabber/plugins/attline/ ~/.tkabber/plugins/attline/attline.tcl Restart Tkabber, to get the plugin loaded. Visit the Tkabber->Customize->Chat->Attention Line block of settings, customize as you wish. Consult the README file for the details about using this plugin. tkabber-plugins-0.11.1/attline/AUTHORS0000644000175000017500000000006610661352400016710 0ustar sergeisergeiKonstantin Khomoutov tkabber-plugins-0.11.1/attline/attline.tcl0000644000175000017500000001745310744722670020030 0ustar sergeisergei# $Id: attline.tcl 1349 2008-01-20 19:49:12Z sergei $ # "Attention line" -- chat plugin for Tkabber. # Draws horizontal line in chat windows separating read and unread messages. # Written by Konstantin Khomoutov # See license.terms for the terms of distribution. package require msgcat option add *Chat.attentionLineHeight 1 widgetDefault option add *Chat.attentionLineColor black widgetDefault option add *Chat.attentionLinePadX 5 widgetDefault option add *Chat.attentionLinePadY 0 widgetDefault namespace eval attline { variable state variable options proc my what { return [uplevel 1 namespace current]::$what } proc mycmd args { lset args 0 [uplevel 1 namespace current]::[lindex $args 0] } ::msgcat::mcload [file join [file dirname [info script]] msgs] custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup {Attention Line} \ [::msgcat::mc "Attention Line chat plugin options.\ This plugin draws horizontal line separating\ read and unread messages in chat windows."] \ -group Plugins \ -group Chat custom::defvar options(expires_after) 1000 \ [::msgcat::mc "Time (in milliseconds) after which unread messages\ in the currently active chat window are considered read\ and the attention line is considered expired."] \ -group {Attention Line} \ -type integer custom::defvar options(remove_expired) false \ [::msgcat::mc "Remove the attention line after it was expired\ from its chat window."] \ -group {Attention Line} \ -type boolean hook::add open_chat_post_hook [mycmd setup_chat_win] # must perform after the hook from 'log on open' plugin: hook::add open_chat_post_hook [mycmd draw_chat_history_separator] 101 hook::add close_chat_post_hook [mycmd cleanup] # must perform earlier than drawing of timestamp: hook::add draw_message_hook [mycmd on_draw_message] 5.5 hook::add got_focus_hook [mycmd on_focused] hook::add lost_focus_hook [mycmd on_lost_focus] } proc attline::attline {cw} { return $cw.attention_line } proc attline::unread {cw {val ""}} { variable state if {$val == ""} { return $state($cw,unread) } else { set state($cw,unread) $val } } proc attline::atbottom {cw {val ""}} { variable state if {$val == ""} { return $state($cw,atbottom) } else { set state($cw,atbottom) $val } } proc attline::isvisible {text index} { expr {[llength [$text bbox $index]] > 0} } proc attline::setup_chat_win {chatid type} { variable state set cw [chat::chat_win $chatid] set iw [chat::input_win $chatid] set state($cw,mainwindow) [chat::winid $chatid] #unread $cw [expr {![has_focus $chatid]}] unread $cw false atbottom $cw false bind $iw <> +[mycmd see_attention_line $cw] return } proc attline::cleanup {chatid} { variable state set cw [chat::chat_win $chatid] cancel_attline_expiration $cw unset state($cw,mainwindow) unset state($cw,unread) unset state($cw,atbottom) } proc attline::getopt {cw opt} { variable state chat::query_optiondb $state($cw,mainwindow) $opt } proc attline::on_draw_message {chatid from type body x} { if {[is_delayed $x]} return set cw [chat::chat_win $chatid] if {![has_focus $chatid] && ![unread $cw]} { unread $cw true if {[drawn $cw]} { redraw_attention_line $cw } else { draw_attention_line $cw } } atbottom $cw false return } proc attline::is_delayed {xml} { foreach xelem $xml { ::jlib::wrapper:splitxml $xelem tag vars isempty chdata children switch -- [::jlib::wrapper:getattr $vars xmlns] { urn:xmpp:delay - jabber:x:delay { return 1 } } } return 0 } proc attline::drawn {cw} { winfo exists [attline $cw] } proc attline::draw_chat_history_separator {chatid type} { if {[string equal $type chat]} { set cw [chat::chat_win $chatid] # Draw only if text widget isn't empty (has some history lines): if {[$cw compare 1.0 < end-1c]} { draw_attention_line $cw } } return } proc attline::draw_attention_line {cw} { set al [attline $cw] frame $al bind $cw +[mycmd reconfigure_attention_line $cw $al] # Prevent destructed attention line from killing its parent # in windowed mode when there's no explicit handler and the # event is forwarded upstream: bind $al +break $cw window create end -window $al reconfigure_attention_line $cw $al debugmsg attline "drawn" } proc attline::delete_attention_line {cw} { set state [$cw cget -state] $cw configure -state normal $cw delete [attline $cw] $cw configure -state $state debugmsg attline "deleted" } proc attline::redraw_attention_line {cw} { set al [attline $cw] set ix [$cw index $al] if {[atbottom $cw]} { debugmsg attline "at bottom, won't redraw" return } set state [$cw cget -state] $cw configure -state normal $cw window configure $ix -window {} $cw delete $ix $cw window create end -window $al reconfigure_attention_line $cw $al $cw configure -state $state debugmsg attline "redrawn" } proc attline::see_attention_line {cw} { set al [attline $cw] if {[winfo exists $al] && ![isvisible $cw $al]} { $cw see $al } } proc attline::internal_width {cw} { # We assume $cw is mapped... expr { [winfo width $cw] - 2 * [$cw cget -borderwidth] - 2 * [$cw cget -padx] - 2 * [$cw cget -highlightthickness] } } proc attline::reconfigure_attention_line {cw al} { if {![winfo exists $al]} return set padx [getopt $cw attentionLinePadX] $al configure \ -background [getopt $cw attentionLineColor] \ -height [getopt $cw attentionLineHeight] \ -width [expr {[internal_width $cw] - 2 * $padx }] $cw window configure $al \ -padx $padx \ -pady [getopt $cw attentionLinePadY] \ } proc attline::has_focus {chatid} { global usetabbar if {$usetabbar} { expr {![string equal [focus -displayof .] ""] && \ [string equal [chat::winid $chatid] [ifacetk::nbpath [.nb raise]]]} } else { set fw [focus -displayof .] expr {![string equal $fw ""] && \ [string equal [winfo toplevel $fw] [chat::winid $chatid]]} } } proc attline::on_focused {w} { set chatid [chat::winid_to_chatid $w] if {$chatid == ""} return set cw [chat::chat_win $chatid] debugmsg attline "focused; unread? [unread $cw]" if {[unread $cw]} { see_attention_line $cw schedule_attline_expiration $cw } } proc attline::on_lost_focus {w} { set chatid [chat::winid_to_chatid $w] if {$chatid == ""} return set cw [chat::chat_win $chatid] debugmsg attline "lost focus; unread? [unread $cw]" if {[unread $cw]} { cancel_attline_expiration $cw } elseif {[drawn $cw]} { redraw_attention_line $cw atbottom $cw true } } proc attline::schedule_attline_expiration {cw} { variable state variable options set exptime $options(expires_after) if {$exptime <= 0} { # Immediate expiration: unread $cw false debugmsg attline "expired immediately" return } set state($cw,expiring) [after $exptime [mycmd expire_attention_line $cw]] debugmsg attline "expiration scheduled for after $exptime" } proc attline::cancel_attline_expiration {cw} { variable state if {[info exists state($cw,expiring)]} { after cancel $state($cw,expiring) unset state($cw,expiring) debugmsg attline "expiration cancelled" } } proc attline::expire_attention_line {cw} { variable state variable options if {[info exists state($cw,expiring)]} { unread $cw false unset state($cw,expiring) if {$options(remove_expired)} { delete_attention_line $cw } debugmsg attline "expired" } } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/socials/0000755000175000017500000000000011076120366015640 5ustar sergeisergeitkabber-plugins-0.11.1/socials/README0000644000175000017500000000043010563364101016512 0ustar sergeisergeiSocials Tkabber plugin -- add many "social" commands like "/dance" that used in Rom and Aladon MUDs. To install, copy socials/ directory to $HOME/.tkabber/plugins (on UNIX), to %APPDATA%\Tkabber\plugins (on Windows), or to $HOME/Library/Application Support/Tkabber (on MacOS X). tkabber-plugins-0.11.1/socials/socials.ru0000644000175000017500000017313707545364327017676 0ustar sergeisergei#SOCIALS kiss ? $ $N4. $n $N4. $n . H p. :( # bounce 0 0 BOIINNNNNNGG! $n , . $E3 . $n $N3 . $n . . . $n . smile 1 0 . $n . $N3. $n $N3. $n . ... . $n . dance 1 8 , ? $n ! $E2 . $n $N5. $n . , ? . $n . tango 0 8 , ? $n ... . $E5. $n $N5. $n . . . , ? $n . cackle 0 0 . $n ! $E5. $n $N5. $n . $E2. , . . - . $n . $e . laugh 0 0 . $n . $N5. $n $N5. $n . . . . . $n . ! giggle 0 0 . $n . $N2. $n $N2. $n . , . , . , , ... $n . $e . shake 0 5 . $n . $E2 . $n $N2. $n . , , . . $n . puke 0 0 ... !!! -- ! $n . $E2. $n $N2. $n2 $e ! ? . $n . growl 0 0 ... $n . .... , $N!!! $n $N2. . $n . ! . . , . $n . ... scream 0 0 -----!!!!! $n ! ------!!!!! - $E3!!! $n $N4. , $n !!! $n ! , ** ! . , . $n ! ? comfort 0 5 ? $ $E4. $n $N4. $n . ? . $n . sigh 0 0 . $n . , $E6. $n $N6. $n , . , ? , . . . $n . . sulk 1 0 . $n . # hug 1 5 ? $ $E4. $n $N4. $n . , , . . $n . snuggle 1 5 ? $ $E3. $n $N3. $n . . , . $n , . cuddle 1 5 ? $ $E4 . $n $N4 . $n . . :) $n . . nuzzle 1 5 ? $ $E2 . $n $N2. $n . ... ... , , . # cry 0 5 --..--.. $n . $E2 . $n $N2. $n . ? . $n . poke 0 0 ?? $ $E4 . $n $N4 . $n . , . , . $n . accuse 0 5 ?? $n . $E4. $n $N4. $n . -, ? . $n . grin 0 0 . $n . $N3. $n $N3. $n . . . , . . , . $n . , $e . bow 0 5 . $n .. $E3. $n $N3. $n . ? . $n . applaud 0 0 , , . $n . $E3. $n $N3. $n . ! . . , ! $n . , ! blush 0 0 . $n . $E5. $n , $N4. $n , . ! , , . . $n . burp 0 0 . $n . $E . $n $N2. $n . . . $n . . chuckle 0 0 . $n . $E2 . $n $N2. $n . p, . , . $n . clap 0 0 . $n p, . $E2 . $n $N2. $n . . . $n . cough 0 0 , pp p! $n p . # curtsey 0 0 . $n p . $E5. $n $N5. $n . . . $n , p $e4 . fart 0 0 ? $n ... $e4 ! $N4. , ! $n $N2. , $e ! $n . . ! ! $n . , $e3, . flip 0 0 . $n . $E4 . $n $N4 . $n . . . . $n . fondle 0 5 ? $ $E4. $n $N4. $n . , . , , ? $n - ! frown 0 0 . $n . $E4. $n $N4. $n . . . ... $n . ... gasp 0 0 . $n . , , $E . $n , $e , $N. $n , $e , . You need to panic. ! $n ! glare 0 5 p. $n . $E4. $n $N4. $n , . -, . . $n . $e5 ? groan 0 0 . $n . , $E4. $n , $N4. $n , . . , . $n , , $e . grope 0 5 ? $ , ? $n $N4. $n . , . - . $n - . hiccup 0 0 ** $n . # lick 0 0 . $n . $S . $n $N. $n . . . $n . love 0 0 . $n . $E3 . $n $N3. $n . , . , , . $n , ? moan 0 0 . $n . $E3 . $n $N3 . $n , . . . . $n . nibble 0 0 ? $ $N2. $n $N2. $n . , . ??????????????????? $n (, $e ?!!). pout 0 0 , . $n . # ruffle 0 0 - . $ $E2 . $n $N2. $n . . , , , , . $n - ! shiver 0 0 . $n . $E5. $n $N5. $n . . ? $n . shrug 0 0 . $n . $E2 . $n $N2. $n . . . $n . . sing 0 0 (?) . ! ! - $n . $E3 . $n $N3 . $n ! ! . . $n . slap 0 0 . $ *!* $E3 . *!* $n $N3 ! $n . ? , ! $n , ... smirk 0 0 . $n . $E2 . $n $N2. $n . ? . -..... $n ''. snap 0 0 ! . $n . , $E2 . $n $N5. $n ! . . $n . sneeze 0 0 ! $n . # snicker 0 0 . $n . $E5 . $n $N5 . $n . ? , . $n , . sniff 0 0 . ** $n . $E2 . $n $N2. $n . . , . $n . $e - . snore 0 0 . . Zzzzzzzzzzzzzzzzz. $n . # squeeze 0 0 , , ??? $ $E4 . $n $N4 . $n . , , ??? - ! $n . stare 0 5 . $n . $N4, $E2 .. $n $N4. $n , . , . - . $n - ! strut 0 0 . $n . $E5. $n $N5, $E2 . $n , . . . $n . thank 0 5 . $ $N4. $n $N4. $n . . , ! $n , $e . twiddle 0 0 . $n . $E2 . $n $N2. $n . . . $n . wave 0 0 . $n . $E3 . $n $N3 . $n . . . ?? ?? $n . whistle 0 0 . $n . , $E4. $n , $N4. $n , . ... , . $n , . wiggle 0 0 . $n . $N2. $n $N2. $n . , $z. . $n . wink 0 5 - ? $n . $N3. $n $N3. $n . . ?? - ? $n - - $e ... yawn 0 0 . $n . # snowball 0 0 ? $ $E2 . $n $N4. $n . . . $n . french 0 0 ? $ $E4. $n $N4. $n . , . .... $n . comb 0 0 - . $n - ! $E2 - ! $n $N2. $n . . , . $n . massage 0 0 ? ? $ $E2 . $n $N2. $n - ... . . $n , . tickle 0 0 ? $ $N4. $n $N4. $n - --! ? , ! $n . pat 0 0 ? $ $N4 $E2 . $n $N4 $E2 . $n . , , ? , . $n . curse 0 0 . $n : #@*"*&^*#%@*&! !!!!! $E4. $n $N4. $n ! ? , . . $n . ? pray 0 0 ... . $n . $N5. $n $N5. $n . , . , ... $n . beg 0 0 . $n2 . $E2. $n $N4 $e3 - ! $n . ! . ? . # cringe 1 0 . $n ! $E2. $n $N2. $n . . ? ? # daydream 1 0 . $n , $e2 . # fume 1 5 ! , . $n p p. , p p $E4. $n p p $N4, p. $n p p , p. ... . p - ! $n , . grovel 1 0 . $n . $E5. $n p $N5. $n p p . Who? That seems a little silly to me. # hop 0 0 . $n . # nudge 0 0 ? $ $E4 . $n $N4 . $n . -? . $n . ponder 0 0 . $n . # punch 0 0 ? $ $E4 . $n $N4 . $n . ! . . . $n . ? snarl 0 0 . $n . $E4. $n $N4. $n , ? ! . $n . spank 0 0 ? $ $E4. $n $N4. $n . ! ! ....... $n ....-... hand 0 0 ? $ $E2 . $n $N2. ! $n . ! . . ? $n . yodel 1 0 . $n . $N , . $n $N2. $n ... . ! , - ! $n $z . -. faint 1 0 . $n . $E2 . $n $N2. $n . -- . # pinch 1 0 , ' .' $n , ' .' $E4 . $n $N4 . $n . You'd like to, wouldn't you? , , . $n , , $e ! stroke 1 0 . $n . $E2 . $N . $N . $n . . . You are about to do something you'd rather not be caught doing. # apologize 1 0 . $n . $E5 . $n $N5 . $n . ? # caress 1 0 ? $ $E4. $n $N4. $n . $z ! # stagger 1 8 . $n . p $N6, p. $n $N6. $n p . ? # snort 1 0 . $n . $N4. $n $N4. $n . ? $z . $n $z . slobber 1 0 . $n $z . $E4. $n $N4. ** $n . ? # blink 1 0 . $n . , $N4. $n , $N4. $n , . ? # tease 1 0 p ! $n p p - p. p $N4 p . $n $N3 . $n ! Tease whom? p . H-H-H. $n p . knee 1 8 , ... $n . $E4 . $N , $n $E4 ! $n ! . ? !?!??!?!?!?! # flirt 1 0 . $n . $N5, $E2 . $n $N5. , $e ? $n . , . :( $z -- !?!?!? $n $z - $e ? tip 1 0 . $n . $E5. $n $N5. $n . ? # lust 1 0 . $n --- ! $M. $n $N. $n . ? , ! ... $n - $e $a... flutter 1 0 . $n . $N , . $n $N, . $n . , . # bark 1 0 - !!! - ! $n . - !!! -! ! $N, $E4 -- !! $n $N, $E4. $n , !! ? . $n . howl 1 0 . $n . $E4. $n $N4. $n . Who? What? Where? # babble 1 0 . $n , $e - ? $N . $n $N - $N ? $n . , , $e . ? $a . ! -, !! $n $a . ramble 1 0 . $n - . $N . $n $N - . $n . ? # hush 1 0 ... $n . ... $N . $n $N . $n . ? , . $n , . threaten 1 8 . $n. , $N. $n $N. $n ... , *laugh* ? # roll 1 0 . $n . $N4 . $n $N4 . $n , . ? . # swoon 1 0 . $n . $N4 . $n $N4 . $n . ? # bird 1 0 You flick a bird...How obscene! $n flicks a bird at no one in particular. You shoot a bird at $N. $n gives $N the bird. $n gives you the bird...What an ass! Don't you hate to waste a good obscene gesture like that? # eyebrow 1 0 . $n . $N2. $n $N2. $n . . . # serenade 1 0 . $n . $N2. $n $N2. $n , $e2 . , $z , , . . ?! $n . ! grimace 1 0 . $n . $N3. $n $N3. $n . ? . . $n . boggle 1 0 You boggle at the concept. $n boggles at the concept. You boggle at $N. $n boggles at $N. $n boggles at you. Boggle away. They've left. You boggle at yourself. Hmmm...intriguing. $n boggles quietly to $mself. beckon 1 0 . $n . $N . $n $N ... , ? $n . , . . $n . wonder 1 0 , . $n , . $N4 , . $n $N4 ... $n . , , . , . $n. $e ? worry 1 0 , . $n2. ? $N4 . $n $N4 . $n . - ! , . $n. ? drool 1 0 You drool down the front of your shirt. $n drools all over $mself -- making a TERRIBLE mess! You drool messily on $N. $n drools upon $N. $n looks at you lustily and drools. Oh fine, make a pool of slobber -- they aren't even here! You drool down the front of your shirt. $n drools all over $mself -- making a TERRIBLE mess! nod 1 0 . $n . $N3. $n $N3. $n . - . , . $n . purr 1 0 !!! $n . $N3 . $n $N3 . $n . ! . . $n . point 1 0 . $n -! $N4. $n $N4! $n . ! . . $n . rub 1 0 . $n . $N4. $n $N4. $n , . . ... ... .. $n ... ! bleed 1 0 You bleed profusely -- making a horrible mess! $n weakly bleeds all over the floor. You bleed on $N -- ewww! $n bleeds on $N. Watch out, YOU might be next! $n bleeds on you -- ewww! Get away!! Bleed on whom? You bleed all over yourself. $n bleeds profusely all over $mself. highfive 1 0 You jump in the air and give a BIG high five to...umm...absolutely nothing. $n wildly high fives the air, looking very foolish -- very foolish indeed. You jump in the air and give a BIG high five to $N! $n enthusiastically high-five's $N! $n gives you a BIG high five! Way to go!! Sorry, they have already left. You try to give yourself a high five. What ARE you thinking? $n tries to high five $mself, but ends up looking foolish instead. propose 1 0 You propose to everyone in the room. $n proposes to everyone in the room. Very odd. You kneel and romantically propose to $N. $n gets on one knee and proposes to $N. $n gets down on one knee and romantically proposes to you. You must be lonely. They aren't here. You are SO full of yourself! $n proposes to $mself -- how narcissistic! peer 1 0 . $n . $N4. $n $N4. $n . . , . $n . worship 1 0 ! $n ! $E4. $n $N4. $n . , . . $n . bearhug 1 0 Whom do you wish to bearhug? $ You overwhelm $N with a great, big, hulking bearhug. $n encompasses $N in an ENORMOUS bearhug! $n clutches you tightly in an overwhelming bearhug! Perhaps you should shower your affections on someone who is here? You vainly clutch yourself in a bearhug for consolation. $n hugs $mself as tightly as possible. Looks like $e could use a hand. spam 1 0 You mutter, 'spam' quietly to yourself again and again. $n rests in a corner and mutters 'spam' quietly to $mself. You SPAM $N mercilessly! $n spams $N! You've been SPAMMED by $n! Spam away -- they've left. # innocent 1 0 . $n . $N4 -- ! $n $N4 . $n . - . # collapse 1 0 . $n . $N2. $n $N2. $n . , . # stretch 1 0 . $n . $e4, ? # boast 1 0 . $n . $N3 . $n $N3. $n ! . . . $n $a - ! squirm 1 0 You squirm uncontrollably in your consternation. $n squirms uncontrollably, suddenly looking very uncomfortable. You look at $N and squirm with delight. $n looks at $N and squirms with delight. $n looks at you and squirms with delight. # moo You chew your cud and moo plaintively. Muh-OOOOO! $n turns cowlike eyes on you, chews $s cud, and moos plaintively. You focus all your bovine Zen on $N, and speak your thoughts. Muh-OOOOO! , , $n $N, -! $n . ? You'd better find someone else to moo at. You settle down into the center of your bovine Zen; the foolish world thinks you're just mooing. $n is mooing at $mself again... You look for an exit... moon 1 0 You drop your drawers and moon everyone in the room! $n drops $s pants and gives you the vertical smile! You bend over and moon $N. $n drops $s pants and rudely moons $N! $n bends over and gives you the vertical smile! You stand, with your pants around your ankles, looking VERY silly! You try to moon yourself, but you can't see your A** that well. $n nearly goes into convulsions while trying to moon $mself. goose 1 0 Who would you like to goose? $ You tenderly goose $N on the tush. $n reaches around $N's backside and gooses $M tenderly. $n gooses you tenderly! You should go hunting for another victim, they left. You pinch yourself on the rear, you must be desperate. $n pinches $mself on the rear. wince 1 0 . $n . $N4 $E2 . $n $N2. $n . # type 1 0 , ! $n , ! # brb 1 0 ! $n ! # mutter 1 0 -. $n - . - $N3. $n $N4 - . $n - . - ! . $n - . rofl 1 0 , . $n , . , $N. $n , $N! $n , ! # sob 1 0 . $n . , $N $A . $n , $N $A $e ! , $a $N4 . # pant 1 0 . $n . $S. $n $N . $n ... # whine 1 0 , . $n , $e4 . , $e4. $n , $N4. $n , . . , . $n . , $e . flex 1 0 You flex your muscles proudly! $n flexes $s muscles...what a stud!?! You show off to $N, flexing your muscles proudly. $n flexes $s muscles, in a vain attempt to impress $N. $n flexes $s muscles in a vain attempt to show off to you. # embrace 1 0 ? $ $N4 . $n $N4 . $n . - . , . $n , . duck 1 0 DUCK!!!! $ , $N. $n , $N. $n , , $s! # bonk 1 0 ***BONK!!!*** $ You bonk $N on the head for being such a moron. $n bonks $N on the head for being such an UTTER moron. $n bonks you on the head for being so foolish. ***BONK*** they left... You bonk yourself, fool that you are. $n bonks $mself and grimaces in pain. squeal 1 0 ! $n ! $N4 ! $n , $N4. $n ! # tackle 1 0 You're going to tackle everyone in the room?! $ You tackle $N playfully. $n playfully tackles $N. $n brings you down in a playful tackle! # spit 1 0 . $n ! $N4... ! $n $N4. $n - ! . - , ? $n ... ! life 0 0 You try to get a life, and fail. $n tries to get a life, and fails. $N needs to get a life! $N needs to get a life! You need to get a life! Who needs a life? But you have none to give! $n attempts to give $mself a life, but has none to spare. mosh 8 0 You mosh insanely around the room! $n moshes insanely around the room! You mosh sadistically against $N ... you WILL be punished. $n bounces off of $N in a vain attempt to mosh... what a LOSER. $n slams into you, moshing painfully against you. That REALLY hurts! Hmmm... your victim found a new dance partner. Masochist! $n throws $mself on the floor, grinding $mself into a bloody pulp flinch 0 0 --... . $n ... $e $a ? , ? $n $N . $n . , . , $a... $n , . air 0 0 , . $n ... !!! , $E . $n $N. $n $s . ... ! . # tweak 0 0 ? $ $e2 ... $E , ? $n $N4 ... , ? $n . ... ... . . # peck 5 0 ? $ , $N . $n $N . $n , ! , ... . # explode 0 0 , ! $n . , ... $n $N6 ! $n ... !!! ... . , . $n $a!!! , $e $a. raspberry 4 0 You stick your tongue out at ... well, no one. $n sticks $s tongue out, catching a few flies in the process. You give $N the raspberry... and spit all over yourself. $n gives $N the raspberry... PHBT! What a mess... Spit EVERYWHERE! You are splattered with saliva as $n gives you the raspberry... HOW RUDE! Hang your tongue out if you like, $e isn't here. You try to stick your tongue out at yourself... somehow, it isn't the same. # flash 0 0 You grin and strut as you open your coat and show what you've got! $n rips $s clothes off and parades naked around the room! Swiftly you jerk open your jacket, trying to get $M to notice you. Cover your eyes, $n is exposing $mself to $n! EWWWW! You gasp! $n has just revealed $s "equipment" to you! Exhibitionist, that person isn't here! That's sick. PERVERT PRESENT! $n is trying to flash $mself strip 0 0 ... $n ... $N4... ... $n $N2 ... $n ... ... ! # undress 0 0 , , . $n ... ... *Pant* $N4... . - $n $N4... , $n ... ... ... # tongue 0 0 You slowly give your tongue a nice workout. $ Mmmm... you give $N a good working over with your tongue... $n slides $s tongue over $N's body... $n wraps $s tongue around you, moving it across your young, nubile flesh... Never around when required... You slowly tongue yourself. $n slowly tongues $mself... ICK. view 0 0 , . $n . # grumble 0 0 . $n . ... $N4, $e2 . $n -... $e $a $N4 . $n ... $A? . ? # cheer 0 0 ! $n ! $N3 ! *!* , $N!!! $n $e4. $n ! $e4. ? ? ? , . , . $n $a ... . plead 0 0 . $n $s... $s . # charge 0 0 ! $n ! . $N ! $n $N ! ! $n ! . . . ! # criticize 0 0 , ? $ $N4 . , $n $N2. $n , . , ... $a . $n , . run 0 0 ! $n ! $N! $n $N ! $n , ! - . $a? $n , ! judge 0 0 , ? $ $e4 1 10. 1 10, $n $N4 !!! $n 1 10 , ... !!! . . # insane 0 0 , ... , $n ... # cover 0 0 . $n . $N4 . $n $N4 . $n - ... ! . ... . # flare 0 0 . $n . , $N... ! $n , $N, . $n , ... $A??? , , . *Sniff* ! # head 0 0 . $n . , $N. $n , $N... $n , ... :( . ? # pie 0 0 . $n . $N! $n $N! $n ... ! ... ... !!! :) $n , . cower 0 0 . $n . , $N $S . $n , $N. $a $n! $e , . . ! $n , . noogie 5 0 You can't noogie the AIR! It has no head. $ You grab $N, get $M in a head lock and NOOGIE $M! $n grabs $N in a head lock and NOOGIES $M... ARGH!!! Oh NO, $n grabs you, throws you in a head lock and NOOGIES you! That person has gone off to other lands... You rub your head and create a static charge... $n rubs $s OWN head and creates a static charge... *ZAP* yeehaw 5 0 You mount your pony(?) and shout YEEEEEEEHAAAAAAAW! $n bounces up and down screaming *YEEEEEEHAAAAAAW!* # pissed 5 0 You are PISSED! $n is PISSED so watch out! You turn a stoney gaze toward $N... you are SOOO pissed at $N! $n glares at $n.... $n is SOOO PISSED at $m! $n is pissed at you now... What do you think $e'll DO? That person is not here... You are PISSED at yourself! $n is so pissed at $mself. How could $e be so stupid??? passout 5 0 You belch and pass out. $n is OBVIOUSLY intoxicated... $e burps loudly and passes out! # adjust 5 0 , , "". $n , , "" ... # scratch 5 0 . $n ... $e . # meditate 0 0 . $n ... $e - . # bkiss 0 0 . $n . $N , $E . $n $N ... ! $n , . , , . ... , ? $n , . beer 0 0 6 . $n 6 . $N3. $n $N3 ... , $E ! $n ... , $e - ... . . $n . bcatch 0 0 , . $n , $e3 . # claw 0 0 . $n , ... $E2 ... ! $n $N2... , , ! $n $A ! . ! $n ! rose 0 0 $a ? $ $N3 . $n $N3 . $n ---'---,--{{@ . ... $n $a , $s? laces 0 0 ? $ , $E2 . $n $N3 $E2 . ! $n $a ! ? , . $n , . tag Tag whom? $n casts about for someone to tag. >From nowhere, you pounce on $N and TAG $M remorselessly! BWAHAHA!!! $n dives from the shadows and TAGS $N. $N IS IT! $n pounces on you and >>> TAGS <<< you! You're IT! Who were you going to tag, then? Unable to catch anyone else, you do the intelligent thing and tag yourself. You're still IT! Unable to catch anyone else, $n tags $mself. Are you impressed? tank You boldly offer to tank for your everyone else. Are you sure you know what you're getting into? $n offers to tank! () $N5. $n () $N5. $n () ! ? No one will tank for you, eh?!? WELL, YOU'LL SHOW THEM! (right?) In dazzling chivalry, $n offers to tank-- for $mself! starve , . $n - $e ! $N3, . $n $N2 . $e , ... $n ! ? , -- . # aargh --------!!! $n ! ! $n $N2, $E! $n , ! , , ! ! $n ! homework , - ... $n . $e $a - ? # puff . $n , " , $a C?" # yae . $n . , $s. $n , $N - ! $n , $s. , , , . ! $n ! lightbulb *!* ! $n! # voodoo Bad juju like this has to be directed at a person. $n looks hostile for a moment. You stare daggers at $N, jabbing pins into $S effigy. $n glares balefully at $N while stabbing a pin into a voodoo doll. Your heart lurches in your chest, and fiery pain stabs through your skull! Your hatred finds no such target. You stab a pin into your own voodoo doll! Agony! $n jabs a pin into $s own voodoo doll, and twitches in agony! ogg Ogg who? $ Engage! $n oggs $N's head with photon torpedos! $N reels. $n oggs your head with photon torpedos! You are reeling. You can't find your target. If you do that, the universe will explode. $n almost oggs $mself, but wisely reconsiders. confused . $n ... , $E2 . $n . $N $A $S ... $n . $A ? , . # beam You beam delightedly at nothing in particular. $n beams broadly at nothing in particular. You dazzle $N with your smile. $n must like $N a great deal to beam at $M so broadly! $n must like you a great deal to beam at you so broadly! You look pretty silly beaming at imaginary friends... Well, aren't you special? $n beams at $mself, obviously pleased. bite You glare around, muttering "Bite me..." under your breath. $n glares around, muttering "Bite me..." under $s breath. You bite $N on the neck. $n bites $N on the neck! $n bites you on the neck. Hungry? No such luck. You bite your knuckle in anguish. $n bites $s knuckle in anguish...the tragedy! discodance Groovy! $n discos wildly! You grab $N and disco wildly! Groovy! $n grabs $N and does $m best Travolta! $n grabs you and does $m best Travolta! It's okay, you can disco solo too. # scuff You scuff your foot sheepishly. $n scuffs $s foot in the dirt, looking very sheepish. You scuff your foot, avoiding $N's gaze. $n scuffs $s foot and shyly avoids $N's gaze. $n scuffs $s foot and shyly avoids your gaze. They aren't here. # whap Whap who? $ You whap $N upside the head! With a resounding WHAP!, $n reprimands $N. HEY! $n whaps you upside the head! Whiff... Ow! You give yourself a resounding whap upside the head. Biff! $n whaps $mself upside the head! lag Yes, yes. $n is m o v i n g v e ry sl o w l y ... # chortle Heh. $n chortles mischievously. You chortle mischievously at $N. $n chortles mischievously at $N. $n chortles mischievously at you. Took you a while to get that....they aren't here. You chortle at your own joke. $n chortles at $s own joke. Don't bother. zerbert Gotta zerbert SOMEBODY. $ You lift $N's shirt and blow loudly into $S navel! $n lifts $N's shirt and blows loudly into $S navel! Yeek! $n lifts your shirt and blows loudly into your navel! You missed. Careful, people are staring... $n looks around furtively, and then bends over and blows loudly into $s own navel! twitch 0 0 . $n . $N. $N $n... $n . ? . # leer 0 0 You peer around the room, leering like the pervert you are! $n peers about, leering like a filthy pervert! You leer at $N like the pervert you are. $n eyes $N up and down, leering like a filthy pervert! $n eyes you up and down, leering like a filthy pervert! You'll have to settle for memories -- that person isn't here. Desperation has reached new heights, hasn't it? $n leers at $mself shamelessly. polite 0 0 . $n . $S . $n $N. $n . . , . $n , . mischievous 0 0 . $n . $N, - . $n $N. $e $a - . $n . . . . $n . accept 0 0 You accept the proferred apology graciously. $n graciously accepts the proferred apology. # anticipate 0 0 You murmur 'Sssssoonnn, my presssssciousssss...' $n murmurs 'Ssssssooonnnn, my pressssscioussss...' # powertrip 0 0 You scream 'The PPppppPOOOOoooWWWwwwErrRRR!' and writhe. $n writhes, screaming 'The PPppppPOOOOoooWWWwwwErrRRR!' # shudder 0 0 , . $n , . # sage 0 0 . $n . # contemplate 0 0 . $n . # agree 0 0 . $n . $N5. $n $N5. $n . , . $a . $n $a . toast 0 0 , . $n , . $e. $n $N4. $n . . . $n . conspire 0 0 , . $n , . $N. $n $N. , ? $n . $a . $n . # support 0 0 . $n . $S . $n $N . $n . , , . . $n . ? pound 0 0 . $n . $N, $S . $n $N, $S . $n , . , , . # wrist 0 0 , . $n , . $S . $n $N . $n . , , . . $n . romeo 0 0 'Romeo & Julietta' . $n 'Romeo & Julietta' . # camel 0 0 You pretend you are a camel. $n pretends to be a camel. You light a Camel cigarette for $M. $n lights a Camel cigarette for $N. $n lights a Camel cigarette for you. You don't see that personhere. You light a Camel cigarette and inhale sharply. $n lights a Camel cigarette and inhales sharply. whip 0 0 You crack your bullwhip menacingly. $n cracks a bullwhip menacingly. You flick your whip across $M bare back. $n flicks $s whip across $N's bare back. $n flicks a whip across your back... the pain.. the pleasure.. Sorry, friend, I can't see that person here. You whip yourself into a frenzy. $n whips $mself into a frenzy. cramp 0 0 You gasp and clutch your abdomen, wheezing with the pain. $n gasps and clutches $m abdomen in agony. You hammerlock $M, screaming, "AAAAARRRRRGH!! I HAVE A CRAMP!!!" $n hammerlocks $N, screaming, "AAAAARRRRRGH!! I HAVE A CRAMP!!!". $n hammerlocks you, screaming "AAAAARRRRRGH!! I HAVE A CRAMP!!!" Suffering as you are, you didn't see that person slip out. # make 0 0 You breathe heavily and wetly. $n breathes heavily and wetly. You steam up the windows with $M. $n and $N start steaming up the windows. $n starts steaming up the windows with you. Sorry, friend, I can't see that person here. # sweep 0 0 . $n . $N $S . $n $N $S . $n . , $a , . # buff 0 0 . $n . # liver 0 0 , . $n , . $S . $n $N . $n . . # wrestle 0 0 $ $ $N . $n $N . $n . , , . . $n . tie 0 0 . $n . $N $S . $n $N $S . $n . , , . # tight 0 0 $ $ $E . $n $N . $n . , , . # fatality 0 0 $ $ , '$N $A. .' $n , '$N $A. .' $n , '$N $A. .' # yowl 0 0 . $n ! # silly 0 0 . $n . $e . # dig 0 0 . $n . # finger 0 0 . $n . # #0 #$ tkabber-plugins-0.11.1/socials/socials.en0000644000175000017500000017272007545364327017647 0ustar sergeisergei#SOCIALS gack Gaaack! $n gacks with dismay! Appalled, you gack at $N. $n gacks expressively, shooting $N a dismayed look. $n gacks, and looks your way, dismayed. That person isn't here. *GACK!* Appalled, $n gacks at $mself! kiss 0 0 Isn't there someone you want to kiss? $ You kiss $M. $n kisses $N. $n kisses you. Never around when required. All the lonely people :( # bounce 0 0 BOIINNNNNNGG! $n bounces around with a happy smile. You bounce onto $S lap and wiggle about. $n bounces onto $N's lap and wiggles about. $n bounces onto your lap and wiggles about. You don't see your plaything. You bounce your head like a basketball. $n plays basketball with $s head. smile 1 0 You smile happily. $n smiles happily. You smile at $M. $n beams a smile at $N. $n smiles at you. There's no one by that name around. You smile at yourself. $n smiles at $mself. dance 1 8 Feels silly, doesn't it? $n dances wildly before you! You lead $M to the dancefloor. $n sends $N across the dancefloor. $n sends you across the dancefloor. Eh, WHO? You skip and dance around by yourself. $n skips a light Fandango. cackle 0 0 You cackle gleefully. $n throws back $s head and cackles with insane glee! You cackle gleefully at $N $n cackles gleefully at $N. $n cackles gleefully at you. Better keep your distance from $m. You can't find a friend to cackle with. You cackle at yourself. Now, THAT'S strange! $n is really crazy now! $e cackles at $mself. laugh 0 0 You fall down laughing. $n falls down laughing. You laugh at $N mercilessly. $n laughs at $N mercilessly. $n laughs at you mercilessly. Hmmmmph. You can't find the butt of your joke. You laugh at yourself. I would, too. $n laughs at $mself. Let's all join in!!! giggle 0 0 You giggle. $n giggles. You giggle in $S presence. $n giggles at $N's actions. $n giggles at you. Hope it's not contagious! You giggle by yourself, since you can't find a partner to giggle with. You giggle at yourself, which makes you giggle at yourself, which makes you ... $n giggles at $mself. $e must be nervous or something. shake 0 5 You shake your head. $n shakes $s head. You shake $S hand. $n shakes $N's hand. $n shakes your hand. Sorry good buddy, but that person doesn't seem to be here. You are shaken by yourself. $n shakes and quivers like a bowl full of jelly. puke 0 0 You puke...chunks everywhere!!! YUK! $n pukes. You puke on $M. $n pukes on $N. $n spews vomit and pukes all over your clothing! Once again? You puke on yourself. $n pukes on $s clothes. growl 0 0 Grrrrrrrrrr... $n growls. Grrrrrrrrrr....take that, $N!!! $n growls at $N. Better leave the room before the fighting starts. $n growls at you. Hey, two can play it that way! No one can see you growl that far. You growl at yourself. Boy, do you feel bitter! $n growls at $mself. This could get interesting... scream 0 0 ARRRRRRRRRRGH!!!!! $n screams loudly! ARRRRRRRRRRGH!!!!! Yes, it MUST have been $S fault!!! $n screams loudly at $N. Better leave before $n blames you, too!!! $n screams at you! That's not nice! *sniff* Your lungs can't reach that far! You scream at yourself. Yes, that's ONE way of relieving tension! $n screams loudly at $mself! Is there a full moon up? comfort 0 5 Do you feel uncomfortable? $ You comfort $M. $n comforts $N. $n comforts you. Comfort who? You make a vain attempt to comfort yourself. $n has no one to comfort $m but $mself sigh 0 0 You sigh. $n sighs. You sigh as you think of $M. $n sighs at the sight of $N. $n sighs as $e thinks of you. Touching, huh? You really sigh, since you don't see your friend. You sigh at yourself. You MUST be lonely. $n sighs at $mself. What a sorry sight. sulk 1 0 You sulk. $n sulks in the corner. # hug 1 5 Hug who? $ You hug $M. $n hugs $N. $n hugs you. Sorry, friend, I can't see that person here. You hug yourself. $n hugs $mself in a vain attempt to get friendship. snuggle 1 5 Who? $ You snuggle $M. $n snuggles up to $N. $n snuggles up to you. They aren't here. You snuggle up, getting ready to sleep. $n snuggles up, getting ready to sleep. cuddle 1 5 Who do you feel like cuddling today? $ You cuddle $M. $n cuddles $N. $n cuddles you. They aren't here. You must feel very cuddly indeed ... :) $n cuddles up to $s shadow. What a sorry sight. nuzzle 1 5 Nuzzle who?? $ You nuzzle $S neck softly. $n softly nuzzles $N's neck. $n softly nuzzles your neck. No.. they aren't here.. I'm sorry, friend, but that's impossible. # cry 0 5 Waaaaah.. $n bursts into tears. You cry on $S shoulder. $n cries on $N's shoulder. $n cries on your shoulder. Who's that? You cry to yourself. $n sobs quietly to $mself. poke 0 0 Poke who?? $ You poke $M in the ribs. $n pokes $N in the ribs. $n pokes you in the ribs. You can't poke someone who's not here!. You poke yourself in the ribs, feeling very silly. $n pokes $mself in the ribs, looking very sheepish. accuse 0 5 Accuse who?? $n is in an accusing mood. You look accusingly at $M. $n looks accusingly at $N. $n looks accusingly at you. Accuse somebody who's not even there ?? You accuse yourself. $n seems to have a bad conscience. grin 0 0 You grin evilly. $n grins evilly. You grin evilly at $M. $n grins evilly at $N. $n grins evilly at you. Hmmm. Better keep your distance. You must be delirious. You grin at youself. You must be getting very bad thoughts. $n grins at $mself. You must wonder what's in $s mind. bow 0 5 You bow deeply. $n bows deeply. You bow before $M. $n bows before $N. $n bows before you. Who's that? You kiss your toes. $n folds up like a jacknife and kisses $s own toes. applaud 0 0 Clap, clap, clap. $n gives a round of applause. You clap at $N's actions. $n claps at $N's actions. $n gives you a round of applause. You MUST'VE done something good! You give your imaginary round of applause to your imaginary friend. You applaud at yourself. Boy, are we conceited! $n applauds at $mself. Boy, are we conceited! blush 0 0 Your cheeks are burning. $n blushes. You get all flustered up seeing $M. $n blushes as $e sees $N here. $n blushes as $e sees you here. Such an effect on people! You blush as you notice that person isn't here. You blush at your own folly. $n blushes as $e notices $s boo-boo. burp 0 0 You burp loudly. $n burps loudly. You burp loudly to $M in response. $n burps loudly in response to $N's remark. $n burps loudly in response to your remark. You can't find your victim. You burp at yourself. $n burps at $mself. What a sick sight. chuckle 0 0 You chuckle politely. $n chuckles politely. You chuckle at $S joke. $n chuckles at $N's joke. $n chuckles at your joke. You can't find a friend to chuckle with. You chuckle at your own joke, since no one else would. $n chuckles at $s own joke, since none of you would. clap 0 0 You clap your hands together. $n shows $s approval by clapping $s hands together. You clap at $S performance. $n claps at $N's performance. $n claps at your performance. You clap for nothing. You clap at your own performance. $n claps at $s own performance. cough 0 0 Yuck, try to cover your mouth next time! $n coughs loudly. # curtsey 0 0 You curtsey to your audience. $n curtseys gracefully. You curtsey to $M. $n curtseys gracefully to $N. $n curtseys gracefully for you. You curtsey to no one in particular. You curtsey to your audience (yourself). $n curtseys to $mself, since no one is paying attention to $m. fart 0 0 Where are your manners ? $n lets off a real rip-roarer ... a greenish cloud envelops $n! You fart at $M. Boy, you are sick. $n farts in the direction of $N. Better flee before $e turns to you! $n farts in your direction. You gasp for air. You can't hold it that long! You fart at yourself. You deserve it. $n farts at $mself. Better $m than you. flip 0 0 You flip head over heels. $n flips head over heels. You flip $M over your shoulder. $n flips $N over $s shoulder. $n flips you over $s shoulder. Hmmmm. You can't find the person. You tumble all over the room. $n does some nice tumbling and gymnastics. fondle 0 5 Who needs to be fondled ? $ You fondly fondle $M. $n fondly fondles $N. $n fondly fondles you. You fondly try to fondle someone not in the room, but who cares. You fondly fondle yourself, feels funny doesn't it? $n fondly fondles $mself - this is going too far!! frown 0 0 You frown disapprovingly. $n frowns. You frown at what $E did. $n frowns at what $N did. $n frowns at what you did. You don't see any reason to frown. You frown at yourself. Poor baby. $n frowns at $mself. What a sad puppy.... gasp 0 0 You gasp in astonishment. $n gasps in astonishment. You gasp as you realize what $E did. $n gasps as $e realizes what $N did. $n gasps as $e realizes what you did. You need to panic. You look at yourself and gasp! $n takes one look at $mself and gasps in astonisment! glare 0 5 You glare at nothing in particular. $n glares around $m. You glare icily at $M. $n glares at $N. $n glares icily at you, you feel cold to your bones. You try to glare at somebody who is not present. You glare icily at your feet, they are suddenly very cold. $n glares at $s feet, what is bothering $m? groan 0 0 You groan loudly. $n groans loudly. You groan at the sight of $M. $n groans at the sight of $N. $n groans at the sight of you. You see no reason to groan. You groan as you realize what you have done. $n groans as $e realizes what $e has done. grope 0 5 Whom do you wish to grope ?? $ Well, what sort of noise do you expect here? $n gropes $N. $n gropes you. Try someone who's here. You grope yourself - YUCK. $n gropes $mself - YUCK. hiccup 0 0 *HIC* $n hiccups. # lick 0 0 You lick your mouth and smile. $n licks $s mouth and smiles. You lick $N's jawline delicately. $n licks $N's jawline delicately. $n licks your jawline delicately. Lick away, nobody's here with that name. You lick your own eyebrows. $n licks $s own eyebrows. love 0 0 You love the whole world. $n loves everybody in the world. You tell your true feelings to $N. $n whispers softly to $N. $n whispers to you sweet words of love. Alas, your love is not present... Well, we already know you love yourself (lucky someone does !) $n loves $mself, can you believe it ? moan 0 0 You start to moan. $n starts moaning. You moan for the loss of $M. $n moans for the loss of $N. $n moans at the sight of you. Hmmmm. You see no cause to moan. You moan at yourself. $n makes $mself moan. nibble 0 0 Nibble on who ? $ You nibble on $N's ear. $n nibbles on $N's ear. $n nibbles on your ear. Sorry, not present. You nibble on your OWN ear ??????????????????? $n nibbles on $s OWN ear (I wonder how it is done !!). pout 0 0 Ah, don't take it so hard. $n pouts. # ruffle 0 0 You've got to ruffle SOMEONE. $ You ruffle $N's hair playfully. $n ruffles $N's hair playfully. $n ruffles your hair playfully. Might be a bit difficult. You ruffle your hair, wondering how far you can go before the rest think you're crazy. $n ruffles $s hair - weirdo! shiver 0 0 Brrrrrrrrr. $n shivers uncomfortably. You shiver at the thought of fighting $M. $n shivers at the thought of fighting $N. $n shivers at the suicidal thought of fighting you. You don't see any reason to shiver. You shiver to yourself? $n scares $mself to shivers. shrug 0 0 You shrug. $n shrugs helplessly. You shrug in response to $S question. $n shrugs in response to $N's question. $n shrugs in response to your question. You shrug to no one in particular. You shrug to yourself. $n shrugs to $mself. What a strange person. sing 0 0 You raise your clear (?) voice towards the sky. HEY CLERICS! I COULD USE A HEAL! $n has begun to sing. You sing a ballad to $M. $n sings a ballad to $N. $n sings a ballad to you! How sweet! You see no one to sing to. You sing a little ditty to yourself. $n sings a little ditty to $mself. slap 0 0 What is the sound of one hand slapping? $ *thwock!* You slap $N ringingly. *thwock!* $n slaps $N! $n slaps you stingingly. How about slapping someone in the same room as you ?? You slap yourself, silly you. $n slaps $mself, really strange ... smirk 0 0 You smirk. $n smirks. You smirk at $S saying. $n smirks at $N's saying. $n smirks at your saying. You want to smirk to whom? You smirk at yourself. Okay..... $n smirks at $s own 'wisdom'. snap 0 0 Eureka! You snap your fingers. $n snaps $s fingers. You snap back at $M. $n snaps back at $N. $n snaps back at you! You must be very agitated. You snap yourself to attention. $n snaps $mself to attention. sneeze 0 0 Gesundheit ! $n sneezes. # snicker 0 0 You snicker softly. $n snickers softly. You snicker with $M about your shared secret. $n snickers with $N about their shared secret. $n snickers with you about your shared secret. Huh? You snicker at your own evil thoughts. $n snickers at $s own evil thoughts. sniff 0 0 You sniff sadly. *SNIFF* $n sniffs sadly. You sniff sadly at the way $E is treating you. $n sniffs sadly at the way $N is treating $m. $n sniffs sadly at the way you are treating $m. You see no reason to sniff. You sniff sadly at your lost opportunities. $n sniffs sadly at $mself. Something MUST be bothering $m. snore 0 0 Zzzzzzzzzzzzzzzzz. $n snores loudly. # squeeze 0 0 Where, what, how, WHO ??? $ You squeeze $M fondly. $n squeezes $N fondly. $n squeezes you fondly. Where, what, how, WHO ??? You squeeze yourself - try to relax a little! $n squeezes $mself. stare 0 5 You stare at the sky. $n stares at the sky. You stare dreamily at $N, completely lost in $S eyes.. $n stares dreamily at $N. $n stares dreamily at you, completely lost in your eyes. You stare and stare but can't see that person anywhere... You stare dreamily at yourself - enough narcissism for now. $n stares dreamily at $mself - NARCISSIST! strut 0 0 Strut your stuff. $n struts proudly. You strut to get $S attention. $n struts, hoping to get $N's attention. $n struts, hoping to get your attention. You don't see an audience. You strut to yourself, lost in your own world. $n struts to $mself, lost in $s own world. thank 0 5 Thank you too. $ You thank $N heartily. $n thanks $N heartily. $n thanks you heartily. No one answers to that name here. You thank yourself since nobody else wants to ! $n thanks $mself since you won't. twiddle 0 0 You patiently twiddle your thumbs. $n patiently twiddles $s thumbs. You twiddle $S ears. $n twiddles $N's ears. $n twiddles your ears. You don't see the person here. You twiddle your ears like Dumbo. $n twiddles $s own ears like Dumbo. wave 0 0 You wave. $n waves happily. You wave goodbye to $N. $n waves goodbye to $N. $n waves goodbye to you. Have a good journey. They didn't wait for you to wave goodbye. Are you going on adventures as well?? $n waves goodbye to $mself. whistle 0 0 You whistle appreciatively. $n whistles appreciatively. You whistle at the sight of $M. $n whistles at the sight of $N. $n whistles at the sight of you. You don't see nothing special to whistle at. You whistle a little tune to yourself. $n whistles a little tune to $mself. wiggle 0 0 Your wiggle your bottom. $n wiggles $s bottom. You wiggle your bottom toward $M. $n wiggles $s bottom toward $N. $n wiggles $s bottom toward you. You must be alone. You wiggle about like a fish. $n wiggles about like a fish. wink 0 5 Have you got something in your eye? $n winks suggestively. You wink suggestively at $N. $n winks at $N. $n winks suggestively at you. No one with that name is present. You wink at yourself ?? - what are you up to? $n winks at $mself - something strange is going on... yawn 0 0 You must be tired. $n yawns. # snowball 0 0 Who do you want to throw a snowball at? $ You throw a snowball in $N's face. $n conjures a snowball from the thin air and throws it at $N. $n conjures a snowball from the thin air and throws it at you. You stand with the snowball in your hand because your victim is not here. You conjure a snowball from the thin air and throw it at yourself. $n conjures a snowball out of the thin air and throws it at $mself. french 0 0 Kiss whom? $ You give $N a long and passionate kiss, it seems to last forever... $n kisses $N passionately. $n gives you a long and passionate kiss, it seems to last forever... Your heart is filled with despair as that person is not here. You gather yourself in your arms and try to kiss yourself. $n makes an attempt at kissing $mself. comb 0 0 You comb your hair - perfect. $n combs $s hair, what a dashing specimen ! You patiently untangle $N's hair - what a mess ! $n tries patiently to untangle $N's hair. $n pulls your hair in an attempt to comb it. That person is not here. You pull your hair, but it will not be combed. $n tries to comb $s tangled hair. massage 0 0 Massage what? Thin air? $ You gently massage $N's shoulders. $n massages $N's shoulders. $n gently massages your shoulders - Ahhhhhhhhhh... You can only massage someone in the same room as you. You practice yoga as you try to massage yourself. $n gives a show on yoga-positions, trying to massage $mself. tickle 0 0 Whom do you want to tickle? $ You tickle $N. $n tickles $N. $n tickles you - ho ho ho. Who is that?? You tickle yourself, how funny! $n tickles $mself. pat 0 0 Pat who? $ You pat $N on $S head. $n pats $N on $S head. $n pats you on your head. Who, where, what? You pat yourself on your head, very reassuring. $n pats $mself on the head. curse 0 0 You swear loudly for a long time. $n swears : #@*"*&^*#%@*&! !!!!! You swear at $M. $n swears at $N. $n swears at you! Where are the manners? You can't find the victim of your frustrations. You swear at your own mistakes. $n starts swearing at $mself. Why don't you help? pray 0 0 You feel righteous, and maybe a little foolish. $n begs and grovels to the powers that be. You crawl in the dust before $M. $n falls down and grovels in the dirt before $N. $n kisses the dirt at your feet. No such person around; your prayers vanish into the endless voids. Talk about narcissism... $n performs some strange yoga-exercises and mumbles a prayer to $mself. beg 0 0 You beg the gods for mercy. The gods fall down laughing at $n's request for mercy. You desperately try to squeeze a few coins from $M. $n begs you for money. You graciously let $m peep at your fortune. $n begs $N for a dime or two - or twenty ! Your money-lender seems to be out for the moment. Begging yourself for money doesn't help. # cringe 1 0 You cringe in terror. $n cringes in terror! You cringe away from $M. $n cringes away from $N in mortal terror. $n cringes away from you. I don't see anyone by that name here.. what are you afraid of? I beg your pardon? # daydream 1 0 You dream of better times. $n looks absent-minded, his eyes staring into space. # fume 1 5 Take it easy now! count to ten, very slowly. $n grits $s teeth and fumes with rage. You stare at $M, fuming. $n stares at $N, fuming with rage. $n stares at you, fuming with rage! Fume away... they ain't here. That's right - hate yourself! $n clenches $s fists and stomps his feet, fuming with anger. grovel 1 0 You grovel in the dirt. $n grovels in the dirt. You grovel before $M $n grovels in the dirt before $N. $n grovels in the dirt before you. Who? That seems a little silly to me. # hop 0 0 You hop around like a little kid. $n hops around like a little kid. # nudge 0 0 Nudge whom? $ You nudge $M. $n nudges $N. $n nudges you. Who? You nudge yourself, for some strange reason. $n nudges $mself, to keep $mself awake. ponder 0 0 You ponder the question. $n sits down and thinks deeply. # punch 0 0 Punch whom? $ You punch $M playfully. $n punches $N playfully. $n punches you playfully. OUCH! You can't find your boxing partner. You punch yourself. You deserve it. $n punches $mself. Why don't you join in? snarl 0 0 You grizzle your teeth and look mean. $n snarls angrily. You snarl at $M. $n snarls at $N. $n snarls at you, for some reason. No need to snarl! You snarl at yourself. $n snarls at $mself. spank 0 0 Spank whom? $ You spank $M playfully. $n spanks $N playfully. $n spanks you playfully. OUCH! Your hand can't find your victim! You spank yourself....HMMMMMMM... $n spanks $mself....HMMMMMMM... hand 0 0 Kiss whose hand? $ You kiss $S hand. $n kisses $N's hand. How continental! $n kisses your hand. How continental! You can't find a lady in THIS group. You kiss your own hand. $n kisses $s own hand. yodel 1 0 You think of Julie Andrews and start to yodel. $n begins to yodel: HEY!! CLERICS!! I COULD USE A HEAL!!! $N covers $S ears as you begin to yodel. $n yodels to $N. $n yodels to you...you cringe and turn away. That person just escaped! Well, it's up to you if you want to damage your hearing. $n yodels to $mself. What a sado-masochist. faint 1 0 You faint. $n faints. You faint into $S arms. $n faints into $N's open arms. $n just fainted into YOUR arms. You fall on the floor and look stupid--really suave. # pinch 1 0 You say, 'A pinch of this, and a dab of that.' $n says, 'A pinch of this and a dab of that.' You squeeze $S bottom and grin. $n pinches $N's bottom and grins. $n pinches your bottom and grins. You'd like to, wouldn't you? You pinch yourself to see if you are dreaming! $n pinches $mself to see if $e is dreaming! stroke 1 0 You stroke the air vaguely. $n makes vague stroking motions. You gently stroke $S inner thigh. $N inhales sharply. $N exhales sharply and suddenly. $n gently strokes your inner thigh. You inhale sharply. Maybe you should practice on yourself first. You are about to do something you'd rather not be caught doing. # apologize 1 0 You apologize until you are blue in the face. $n apologizes profusely. You might as well apologize because $E sure as hell won't. $n apologizes to $N with a very sincere look on $s face. $n apologizes to you and begs for forgiveness. Who's that? # caress 1 0 Who do you wish to caress? $n looks for someone to caress. You tenderly caress $M. $n tenderly caresses $N. $n tenderly caresses your body. You're S.O.L., buddy. # stagger 1 8 You stagger blindly around the room. $n staggers blindly around the room. You stagger toward $N as the room begins to spin. $n staggers into $N. $n staggers blindly into you. Stagger into whom!?!? # snort 1 0 You snort derisively. $n snorts derisively. You snort derisively at $N. $n snorts derisively at $N. $n snorts at you. Snort at whom? You snort derisively at yourself. $n snorts derisively at $sself. slobber 1 0 You slobber down your front. $n slobbers all over $mself. You slobber on $N. $n slobbers on $N **Yuck** $n slobbers disgustingly on you. Slobber on WHOM? # blink 1 0 You bat your eyelashes. $n blinks innocently. You blink innocently at $N. $n blinks innocently at $N. $n blinks innocently at you. Feign innocence for whom? You try to convince yourself of your innocence. # tease 1 0 What a tease. SHEESH. $n looks around for someone to tease. You tease $N in a playful way. $n sticks $s tongue out at $N. $n sticks $s tongue out at you, what a DORK!! Tease whom? You tease yourself. NYAH NYAH NYAH. $n teases $mself. knee 1 8 You raise one knee, preparing to do justice... $n cocks one knee threateningly. You knee $M hard in the groin. $N doubles over in pain as $n knees $M in the groin! $n suddenly knees you in the groin! You fall to your knees in agony. Whom do you wish to render impotent? What ARE you thinking !?!??!?!?!?! # flirt 1 0 You flirt outrageously. $n is an outrageous flirt. You flirt with $N trying to get $S attention. $n flirts with $N, hmmm wonder what $e wants? *wink* $n flirts with you. Sorry no one here to flirt with. :( You flirt with yourself -- what ARE you trying to gain!?!?!? $n flirts with $mself, wonder what $e is trying to accomplish? tip 1 0 You tip your hat gallantly. $n gallantly tips $s hat. You tip your hat to $N. $n gallantly tips $s hat to $N. $n gallantly tips $s hat to you. But there is no one here to impress?!?! # lust 1 0 Your hormones begin to rage. $n has that look of lust in $s eyes --- Get away QUICK! You have lust after $N. $n looks lustily at $N. $n lusts after your delectable body. Whom are you trying to lust after? Oh, please! You aren't THAT great... $n lusts after $mself, lonely eh? flutter 1 0 You flutter your eyelashes seductively. $n flutters $s eyelashes seductively. You flutter your eyelashes at $N, trying to be seductive. $n flirts with $N, flutters $s eyelashes at $M. $n flutters $s eyelashes at you coyly. EH? Can't see them here. # bark 1 0 You bark loudly. $n barks like a dog. GO DAWGS SIC 'EM!!! WOOF! WOOF! WOOF! WOOF! You bark at $N scaring $M silly -- SHAME ON YOU!! $n barks at $N scaring $M senseless. $n barks loudly at you, you back away, because $e might bite too!! Bark at whom? You bark at yourself and jump back in fear. $n barks at $mself and cowers in fear. howl 1 0 You howl at the moon. $n howls at the moon. You howl soulfully at $N. $n howls at $N. $n howls soulfully at you. Who? What? Where? # babble 1 0 You babble endlessly. $n babbles endlessly, won't $e EVER shut up? You babble to $N for hours on end. $n babbles to $N for what seems an eternity, how can $N stand it? $n babbles at you. You nod mechanically, hoping $e will shut up soon. Whom do you wish to annoy with your babble? You babble on and on to yourself, FINALLY! someone who LISTENS!! $n babbles quietly to $mself. ramble 1 0 You ramble on and on. $n rambles on about a boring exploit. You ramble on to $N about your past adventures. $n blithers on and on to $N about something. $n tells you a rather boring tale, you feign interest. ??EH?? # hush 1 0 SHHHHHHHHHHHHHHHHHHHHHH $n requests everyone quiet down. Shhhhhhhhhhh... You nicely ask $N to be more quiet. $n nicely asks $N to be more quiet. $n kindly requests that you please quiet down. Who needs to be silenced? You realize you are loud and obnoxious and try to silence yourself. $n covers $s mouth in an attempt to silence $mself. threaten 1 8 You threaten everyone with your overwhelming presence. You feel threatened in the presence of the great $n. You stand tall as you threaten $N. $n threatens $N forcefully. $n threatens you...oooooooh scary *laugh* Whom do you wish to intimidate? # roll 1 0 You roll your eyes in disgust. $n rolls $s eyes, disgusted. You look at $N and roll your eyes in disgust. $n rolls $s eyes in disgust at $N. $n rolls $s eyes at you. You should be disgusted with yourself because you look so foolish. At whom do you wish to roll your eyes? # swoon 1 0 You swoon. $n swoons in absolute ecstasy. You look at $N and swoon in ecstasy. $n looks at $N and swoons in ecstasy. $n looks at you and swoons in ecstasy. Who? # bird 1 0 You flick a bird...How obscene! $n flicks a bird at no one in particular. You shoot a bird at $N. $n gives $N the bird. $n gives you the bird...What an ass! Don't you hate to waste a good obscene gesture like that? # eyebrow 1 0 You raise an eyebrow at the notion. $n raises an eyebrow. You raise your eyebrow at $N. $n raises an eyebrow at $N's weird actions. $n raises an eyebrow at you. Forget it. They aren't here. # serenade 1 0 You raise your voice in a loud serenade to your invisible love. $n raises $s voice to serenade the world. You raise your voice in a loving serenade to $N. $n raises $s voice in a loving serenade to $N. $n serenades you, you are swept away by $s voice. The one that you wish to serenade has left you to sing to yourself. You sing a loud serenade to yourself. What type of person are you?! $n serenades $mself. What an ego! grimace 1 0 You grimace painfully at the thought. $n grimaces painfully at the thought. You grimace at $N. $n grimaces at $n. $n grimaces at you. What could be wrong? You grimace at no one in particular. You grimace painfully at your thoughts. $n grimaces painfully to $mself. boggle 1 0 You boggle at the concept. $n boggles at the concept. You boggle at $N. $n boggles at $N. $n boggles at you. Boggle away. They've left. You boggle at yourself. Hmmm...intriguing. $n boggles quietly to $mself. beckon 1 0 You beckon for everyone to follow. $n beckons for everyone to follow. You beckon for $N to follow -- sure hope they do! $n beckons $N to follow...hmmm what's going on? $n beckons for you to follow. So sorry, that person has already left. You beckon to your shadow to follow. $n beckons to $s shadow to follow. wonder 1 0 You wonder about how things could have been. $n gets a blank stare on $s face. What could $e be wondering about? You look at $N and wonder what will happen. $n looks at $N and wonders.... $n looks at you quizzically. You wonder what would have happened had they been here. You wonder about yourself and your purpose here. A blank stare crosses $n's face. What could $e be wondering about? worry 1 0 You worry about what's going to happen. A troubled look suddenly crosses $n's face. Wonder what's wrong? You look at $N worriedly. $n looks at $N with a troubled gaze. $n looks at you worriedly. Well they obviously aren't worried -- they left! You worry about what's going to happen. A troubled look suddenly crosses $n's face. Wonder what's wrong? drool 1 0 You drool down the front of your shirt. $n drools all over $mself -- making a TERRIBLE mess! You drool messily on $N. $n drools upon $N. $n looks at you lustily and drools. Oh fine, make a pool of slobber -- they aren't even here! You drool down the front of your shirt. $n drools all over $mself -- making a TERRIBLE mess! nod 1 0 You nod. $n nods. You nod at $N. $n nods at $N. $n nods at you in agreement. Nod your head off -- they aren't here. You attempt to nod at yourself and get dizzy instead. $n nods quietly to $mself. What a wacko. purr 1 0 MMMMMMEEEEEEEEEOOOOOOOOOOOOOWWWWWWWWWWW!!!!!!!!!!! $n purrs contentedly. You rub up against $N and purr contentedly. $n rubs against $N and purrs contentedly. $n rubs up against you and purrs contentedly. You silly cat! They aren't here. You purr quietly to yourself. $n purrs contentedly to $mself. point 1 0 You point in every direction. $n points excitedly! You point at $N. $n points excitedly at $N! $n points at you. How rude! You point at no one in particular. You point at yourself, obviously very confused. $n points at $mself, obviously very confused. rub 1 0 You rub your hands together in greedy anticipation. $n rubs $s hands together in greedy anticipation. You give $N a nice, long, kinky rubdown. $n gives $N a nice long rubdown. $n gives you a rubdown, running $s hands over your tense shoulders...Mmmm... Shame to waste those talented hands, but they've already left. You rub yourself...lingering a little too long in some places. $n rubs $mself...what a creep! bleed 1 0 You bleed profusely -- making a horrible mess! $n weakly bleeds all over the floor. You bleed on $N -- ewww! $n bleeds on $N. Watch out, YOU might be next! $n bleeds on you -- ewww! Get away!! Bleed on whom? You bleed all over yourself. $n bleeds profusely all over $mself. highfive 1 0 You jump in the air and give a BIG high five to...umm...absolutely nothing. $n wildly high fives the air, looking very foolish -- very foolish indeed. You jump in the air and give a BIG high five to $N! $n enthusiastically high-five's $N! $n gives you a BIG high five! Way to go!! Sorry, they have already left. You try to give yourself a high five. What ARE you thinking? $n tries to high five $mself, but ends up looking foolish instead. propose 1 0 You propose to everyone in the room. $n proposes to everyone in the room. Very odd. You kneel and romantically propose to $N. $n gets on one knee and proposes to $N. $n gets down on one knee and romantically proposes to you. You must be lonely. They aren't here. You are SO full of yourself! $n proposes to $mself -- how narcissistic! peer 1 0 You peer around yourself intently. $n peers around $mself intently. You peer intently at $N. $n peers intently at $N. $n peers at you intently. They aren't here. You get a little cross-eyed with your attempts to stare yourself down. $n peers at $mself, crossing $s eyes in the process. worship 1 0 You prostrate yourself and worship the gods! $n prostrates $mself and worships the gods! You fall on your knees and worship $N. $n falls on $s knees and worships $N. $n falls to the ground and worships you. You can't worship someone who isn't here. You worship yourself. $n worships $mself. bearhug 1 0 Whom do you wish to bearhug? $ You overwhelm $N with a great, big, hulking bearhug. $n encompasses $N in an ENORMOUS bearhug! $n clutches you tightly in an overwhelming bearhug! Perhaps you should shower your affections on someone who is here? You vainly clutch yourself in a bearhug for consolation. $n hugs $mself as tightly as possible. Looks like $e could use a hand. innocent 1 0 You innocently whistle a tune. $n looks around and whistles innocently. You look at $N and bat your eyelashes -- the picture of innocence! $n bats $s eyelashes innocently at $N. $n looks at you and innocently bats $s eyelashes. Don't even TRY -- they've already left. # collapse 1 0 You collapse on the floor from exhaustion. $n dramatically collapses to the floor from exhaustion. You collapse right into $N's arms. $n collapses right into $N's arms. Suddenly, $n collapses into your arms from exhaustion. They've already left, just collapse on the floor. # stretch 1 0 You lean back and streeeeeettch your arms and legs. $n stretches luxuriously. Kinda makes you want to doesn't it? # spam 1 0 You mutter, 'spam' quietly to yourself again and again. $n rests in a corner and mutters 'spam' quietly to $mself. You SPAM $N mercilessly! $n spams $N! You've been SPAMMED by $n! Spam away -- they've left. # boast 1 0 You boast loudly of all your amazing accomplishments. $n boasts loudly in a pigheaded fashion. You boast to $N of all your great deeds. $n boasts to $N. Once again, $n boasts to you, what a bloated ego! Your ego takes a blow. They've already left. You boast to yourself of all your great feats! Your own biggest fan. $n boasts to $mself -- what an ego! squirm 1 0 You squirm uncontrollably in your consternation. $n squirms uncontrollably, suddenly looking very uncomfortable. You look at $N and squirm with delight. $n looks at $N and squirms with delight. $n looks at you and squirms with delight. # moo You chew your cud and moo plaintively. Muh-OOOOO! $n turns cowlike eyes on you, chews $s cud, and moos plaintively. You focus all your bovine Zen on $N, and speak your thoughts. Muh-OOOOO! Slowly, $n looks at $N, chews $s cud, and muh-OOOOs! $n moos at you. What could that possibly mean? You'd better find someone else to moo at. You settle down into the center of your bovine Zen; the foolish world thinks you're just mooing. $n is mooing at $mself again... You look for an exit... moon 1 0 You drop your drawers and moon everyone in the room! $n drops $s pants and gives you the vertical smile! You bend over and moon $N. $n drops $s pants and rudely moons $N! $n bends over and gives you the vertical smile! You stand, with your pants around your ankles, looking VERY silly! You try to moon yourself, but you can't see your A** that well. $n nearly goes into convulsions while trying to moon $mself. goose 1 0 Who would you like to goose? $ You tenderly goose $N on the tush. $n reaches around $N's backside and gooses $M tenderly. $n gooses you tenderly! You should go hunting for another victim, they left. You pinch yourself on the rear, you must be desperate. $n pinches $mself on the rear. wince 1 0 You wince in agony. $n winces in agony. You look at $N and wince at $S remark. $n winces at $N's remark. $n winces at your remark. # type 1 0 You can't type for crap tonight! You give up in frustration! $n throws $s hands up in disgust at $s lousy typing skills! # brb 1 0 Hope to see you soon! $n will be right back! # mutter 1 0 You mutter quietly to yourself. $n mutters something quietly to $mself. You mutter something to $N. $n looks at $N and mutters something nasty under $s breath. $n looks at you and mutters something nasty under $s breath. There's nothing left for you to say, they've left! You mutter quietly to yourself. $n mutters something quietly to $mself. rofl 1 0 You roll on the floor, laughing hysterically. $n falls to the ground and rolls around laughing hysterically. You fall to the floor laughing at $N's remark. $n rolls on the floor laughing at $N's antics! $n rolls on the floor laughing at your antics! # sob 1 0 You sob quietly to yourself. $n sobs in misery. You sob quietly to yourself because $N has hurt your feelings so badly. $n sobs quietly to $mself because $N was a jerk! You feel like a cad because you've made $n sob. # pant 1 0 You pant lustily. $n pants lustily. You pant lustily at $M. $n looks at $N and pants lustily. $n looks at you and pants lustily... # whine 1 0 You whine to anyone who will listen to you. $n whines pathetically to anyone who will listen. You whine to $M, hoping desperately that at least $E will give a damn. $n whines pathetically to $N. $n whines pathetically to you. What a loser! They really don't care. You whine to yourself, probably the only one who will listen. $n whines to $mself. At least $e isn't bitching to YOU. flex 1 0 You flex your muscles proudly! $n flexes $s muscles...what a stud!?! You show off to $N, flexing your muscles proudly. $n flexes $s muscles, in a vain attempt to impress $N. $n flexes $s muscles in a vain attempt to show off to you. # embrace 1 0 Who would you like to embrace? $ You wrap your arms around $N in a warm and loving embrace. $n wraps $s arms around $N in a warm and loving embrace. $n takes you in $s arms in a warm and loving embrace. Your heart breaks as you realize you are alone. You try to console yourself with a loving embrace. $n tries to console $mself by wrapping $s arms around $mself. duck 1 0 DUCK!!!! $n ducks defensively. You duck defensively, anticipating the oncoming swipe from $N. $n ducks, anticipating $N's reaction. $n ducks, please oh please don't hit $m! # bonk 1 0 ***BONK!!!*** $ You bonk $N on the head for being such a moron. $n bonks $N on the head for being such an UTTER moron. $n bonks you on the head for being so foolish. ***BONK*** they left... You bonk yourself, fool that you are. $n bonks $mself and grimaces in pain. squeal 1 0 You squeal with delight! $n lets out a sudden squeal of delight! You look at $N and squeal with delight! $n squeals with delight at $N. $n looks at you and squeals with delight! # tackle 1 0 You're going to tackle everyone in the room?! $ You tackle $N playfully. $n playfully tackles $N. $n brings you down in a playful tackle! # spit 1 0 You spit in utter disgust. $n spits in utter disgust! You spit on $N...you're gross! $n spits on $N. $n spits on you -- how gross! Your victim isn't here. You spit on yourself, pretty nasty eh? $n spits on $mself...what a sicko! life 0 0 You try to get a life, and fail. $n tries to get a life, and fails. $N needs to get a life! $N needs to get a life! You need to get a life! Who needs a life? But you have none to give! $n attempts to give $mself a life, but has none to spare. mosh 8 0 You mosh insanely around the room! $n moshes insanely around the room! You mosh sadistically against $N ... you WILL be punished. $n bounces off of $N in a vain attempt to mosh... what a LOSER. $n slams into you, moshing painfully against you. That REALLY hurts! Hmmm... your victim found a new dance partner. Masochist! $n throws $mself on the floor, grinding $mself into a bloody pulp flinch 0 0 EEEK... You flinch in obvious pain. $n flinches in obvious pain... you wonder what $e did THIS time. Don't you wish you could just crawl under a rock and die? $n sneaks a glance at $N and flinches. $n flinches in response to your cold rebuke. Relax, $E is gone. You can't belive what you've done... $n twitches violently, shocked at $s own behavior. air 0 0 You grab your air guitar and play for all you're worth. $n air-guitars like a mad man ... EXCELLENT!!! You hope $E appreciates your (total lack of) talent. $n is surrounded by air groupies. $n plays a most excellent tune for you on $s most excellent air guitar. Awww... you have no audience! You play softly to yourself. # tweak 0 0 Tweak who? $ You gently tweak $S cheek. Isn't $E so CUTE? $n tweaked $N's cheek... don't they look so adorable together? $n lovingly tweaks your cheek. It reminds you of Grandma... sniff... *Sniff* That cheek seems to be missing. You can't DO that. # peck 5 0 Wouldn't you like to do that to a person, or do you prefer air? $ Risking a slap to the face, you give $N a peck on the cheek. $n smiles and gives $N a chaste peck on the cheek. $n pecks you on the cheek, how sweet! I guess you scared them away... You must REALLY like yourself. $n tries in vain to wrap $s lips around $s cheeks. explode 0 0 You feel the blood boiling in your veins! $n turns a deep red, fighting to contain $s temper... You feel your rage explode deep in the pit of your stomach... $n burns holes through $N with his explosive anger! $n is ANGRY with you... I'd run if I were you!!! Temper Temper... they left. Your soul burns brightly then fades to nothing. $n implodes!!! Only a grease spot remains where $e once stood. raspberry 4 0 You stick your tongue out at ... well, no one. $n sticks $s tongue out, catching a few flies in the process. You give $N the raspberry... and spit all over yourself. $n gives $N the raspberry... PHBT! What a mess... Spit EVERYWHERE! You are splattered with saliva as $n gives you the raspberry... HOW RUDE! Hang your tongue out if you like, $e isn't here. You try to stick your tongue out at yourself... somehow, it isn't the same. # flash 0 0 You grin and strut as you open your coat and show what you've got! $n rips $s clothes off and parades naked around the room! Swiftly you jerk open your jacket, trying to get $M to notice you. Cover your eyes, $n is exposing $mself to $n! EWWWW! You gasp! $n has just revealed $s "equipment" to you! Exhibitionist, that person isn't here! That's sick. PERVERT PRESENT! $n is trying to flash $mself strip 0 0 You do a slow strip tease for the people... $n begins a slow, erotic strip-tease act... You start to undress $N ... one piece of clothing at a time... $n runs $s hands over $Ns body, slowly stripping away the clothing... $n has started to strip you... woah BABY! Your toy doesn't seem to be here... You can't DO that in public! # undress 0 0 You start to undress in the shadows, waiting for someone to notice. $n begins to undress... $e is VERY sexy... *Pant* You undress $M with your eyes... Kinky. You feel the temperature of the room rise as $n lusts on $N... Feeling exposed, you sense $n undressing you with $s eyes... They are not here... A mirror would work better... # tongue 0 0 You slowly give your tongue a nice workout. $ Mmmm... you give $N a good working over with your tongue... $n slides $s tongue over $N's body... $n wraps $s tongue around you, moving it across your young, nubile flesh... Never around when required... You slowly tongue yourself. $n slowly tongues $mself... ICK. view 0 0 You sit back and watch the world go by. $n kicks back and enjoys the view. # grumble 0 0 You grumble distractedly to yourself $n grumbles and growls. You wonder what's wrong... You grumble at $N, disgusted with their presence. $n seems to be a grumpy bear... $e is grumbling at poor $N. $n is grumbling at you... what'd you do? That person is presently AWOL. Why bother? # cheer 0 0 You cheer and dance as the joy within you bursts forth! $n cheers and sings... $e is just BURSTING with joy! You cheer $N on and wish $M good luck! *Yay!* Go $N!!! $n cheers $M on. You are cheered on by $n... you feel so loved! Who? Huh? Where? They're not here, that's for sure You cheer silently for yourself since nobody else will $n resorts to cheering for $mself... how sad. plead 0 0 You beg and plead to anyone who will listen. $n pleads $s case to anyone who will listen... You ALMOST feel sorry for $s. # charge 0 0 You charge into the fray! $n charges into the fray! All guts, no brains. With surprising dexterity, you head-butt $N! $n ducks down low, charges forward, and head-butts $N! OOF! $n rammed $s head into your stomach! That HURT. Nobody 'round with that name, Mister! You run your head into a brick wall. OUCH! # criticize 0 0 Yes, but who? $ You criticize $M with all the warmth of a snake. With a nasty grin, $n rips apart $Ns efforts. $n informs you that your attempts need some MAJOR adjustments. Where oh where has my victim gone, oh where oh where... You criticize yourself profusely. $n tears $mself apart, cursing $s own stupidity. run 0 0 You run away in terror and horror! $n runs away in utter terror! You run away from $N in complete terror! $n runs away from $N in utter terror and horror! $n runs from you, fearing for $s life! No reason to be afraid, they aren't here. Are you THAT ugly? $n looks in the mirror, sees $s face, and runs away terrified! judge 0 0 Yes, but who? $ You judge $m on a scale of 1 to 10. On a scale from 1 to 10, $n thinks $N is a complete ZERO!!! $n judges your actions on a scale of 1 to 10 and comes up with ZERO!!! They aren't here right now. You don't REALLY want to do that. # insane 0 0 You feel your sanity slipping away... Before your eyes, $n's sanity is slipping away... # cover 0 0 You cover your ears to protect them from the noise. $n covers $s ears to protect them from all the noise. You glare at $N and cover your ears. $n glares at $N and covers $s ears. $n covers $s ears because of you... you are TOO LOUD! They aren't here right now. No... I don't think so. # flare 0 0 You flare your nostrils disdainfully. $n flares $s nostrils disdainfully. You flare your nostrils disdainfully at $N... HOW RUDE! $n flares $s nostrils disdainfully at $N and turns up $s snobbish nose. $n flares $s nostrils disdainfully at you... what'd you DO??? Flare if you wish, but that person isn't here to see it. *Sniff* But you should LOVE yourself! # head 0 0 You toss your head haughtily. $n tosses $s head haughtily. You toss your head haughtily at $N. $n tosses her head haughtily at $N... what an ATTITUDE! $n tossed $s head haughtily at you... :( That person is AWOL. Why would you do that? # pie 0 0 You pick up a pie and toss it around for a bit. $n picks up a pie and tosses it around for a bit. You toss a pie at $N and hit $M right in the FACE! $n tosses a pie at $N and hits $m right in the FACE! $n tossed a pie in your face... and now you are all covered in GOO! That person isn't here... You bury your face in the pie... yummmmm!!! :) $n buries $s face in the pie, licking the pan clean. cower 0 0 You cower in a corner. $n cowers in a corner and whimpers softly. You cower away from $N and $S harsh words. $n cowers in a corner, terrified that $N will come after $m. You scared poor $n! Now $S is cowering in a corner, afraid for $s life. That person is AWOL at the moment. You are afraid of your own shadow! $n cowers in the corner afraid of $s own shadow noogie 5 0 You can't noogie the AIR! It has no head. $ You grab $N, get $M in a head lock and NOOGIE $M! $n grabs $N in a head lock and NOOGIES $M... ARGH!!! Oh NO, $n grabs you, throws you in a head lock and NOOGIES you! That person has gone off to other lands... You rub your head and create a static charge... $n rubs $s OWN head and creates a static charge... *ZAP* yeehaw 5 0 You mount your pony(?) and shout YEEEEEEEHAAAAAAAW! $n bounces up and down screaming *YEEEEEEHAAAAAAW!* # pissed 5 0 You are PISSED! $n is PISSED so watch out! You turn a stoney gaze toward $N... you are SOOO pissed at $N! $n glares at $n.... $n is SOOO PISSED at $m! $n is pissed at you now... What do you think $e'll DO? That person is not here... You are PISSED at yourself! $n is so pissed at $mself. How could $e be so stupid??? passout 5 0 You belch and pass out. $n is OBVIOUSLY intoxicated... $e burps loudly and passes out! # adjust 5 0 You look around, make sure nobody is watching, and you adjust your "Tool." $n looks around slyly, smiles, then reaches down and "adjusts" $mself... # scratch 5 0 You scratch yourself contentedly. $n reaches down and scratches $mself... Now $e looks VERY happy. # meditate 0 0 You assume a very comfortable position and begin to meditate. $n rests and begins to meditate... $e chants softly to $mself. # bkiss 0 0 You blow kisses to the air. $n blows kisses at no one in particular. You blow a kiss at $N and wonder if $E will catch it. $n blows a kiss at $N ... isn't $e so CUTE? $n blows a kiss at you and hopes you'll blow one back at $m. You kiss falls to the ground with no one to go to. You blow a kiss to yourself... isn't the world beautiful? $n blows a kiss to $mself, obviously very in love. beer 0 0 You pull out a six-pack. $n starts to juggle a six-pack of beer. You toss a bottle of beer at $N. $n tosses a bottle of beer at $N ... let's just hope $e'll catch it! $n tossed you a bottle of beer... I think $e wants something... The bottle crashes to the floor and shatters. You pop off the top and down a beer. $n pops the top off a bottle of beer and downs it in one gulp. bcatch 0 0 You reach out and rescue the bottle from its flight. $n reaches out and grabs the bottle of beer tossed to $m. # claw 0 0 You tighten your hands into a fist. $n clenches $s fists until blood drips from them... You claw $S eyes out... GROSS! $n buries $s nails in $N's eyes ... OH GOD, THE BLOOD! $n buries $s nails in your eyes and you are blinded by your own blood! They aren't here to claw. You claw yourself to shreds! $n rips $mself to shreds with $s fingernails! rose 0 0 Who would you like to give it to? $ You give $M a pretty rose. $n hands $N a beautiful rose. $n hands you a beautiful ---'---,--{@ They seem to have left. You give yourself a rose and feel a little sad... $n gives $mself a rose, dont you feel sorry for $m? laces Whose laces? $ With the greatest of stealth, you tie $S shoelaces together. $n sneaks up to $N and ties $S shoelaces together. You try to take a step, and you hit the world facedown! Someone must have tied your shoelaces together! Whose laces? You tie your own shoelaces together, try to walk, and promptly fall. $n cleverly ties $s own shoelaces together, tries to walk, and sprawls flat on the floor. tag Tag whom? $n casts about for someone to tag. >From nowhere, you pounce on $N and TAG $M remorselessly! BWAHAHA!!! $n dives from the shadows and TAGS $N. $N IS IT! $n pounces on you and >>> TAGS <<< you! You're IT! Who were you going to tag, then? Unable to catch anyone else, you do the intelligent thing and tag yourself. You're still IT! Unable to catch anyone else, $n tags $mself. Are you impressed? tank You boldly offer to tank for your everyone else. Are you sure you know what you're getting into? $n offers to tank! You offer to tank for $N. $n offers to tank for $N. $n offers to tank for you! Tank for whom? No one will tank for you, eh?!? WELL, YOU'LL SHOW THEM! (right?) In dazzling chivalry, $n offers to tank-- for $mself! starve You show your prominent ribs and hope that someone will take pity. $n is withering before your eyes! Starvation! You throw yourself upon $S mercy, begging for food. $n begs $N for food. One would think that magic would have cured hunger by now... $n is starving before your eyes! Could you spare some food, please? Sorry, but that person isn't around-- looks like you'll starve. # aargh AAAAAARRRRRRGGGGGGHHHHHH!!!!!! $n throws back $s head and howls in profound frustration! You scream your frustration and grab for $S throat with both hands! $n howls in frustration, and leaps for $N, trying to throttle $M! $n grabs for your throat with two hands, howling in frustration! You get even MORE frustrated when you can't find anyone to throttle! You scream in frustration at your own stupidity! $n screams in frustration at $s own stupidity! homework Your suddenly remember that you have to defend your thesis today... $n looks stricken. Could $e have blown off some important homework? # puff You mimic Puff at her most annoying. $n says, "Did you know that I'm written in C?" # yae You sigh, burdened with Yet Another Eeediot. $n sighs, burdened with Yet Another Eeediot. There's Yet Another Eeediot in the room, and you're looking right at $M. $n clearly believes that $N is an Eeediot! $n glares at you, obviously not impressed with your intelligence. There are plenty of Eeediots, but that one doesn't seem to be present. You bonk yourself for the Eeediot you are! $n bonks $mself, HARD, and curses $mself for the Eeediot $e is! lightbulb *Ding!* Inspiration! A light bulb appears above $n's head! # voodoo Bad juju like this has to be directed at a person. $n looks hostile for a moment. You stare daggers at $N, jabbing pins into $S effigy. $n glares balefully at $N while stabbing a pin into a voodoo doll. Your heart lurches in your chest, and fiery pain stabs through your skull! Your hatred finds no such target. You stab a pin into your own voodoo doll! Agony! $n jabs a pin into $s own voodoo doll, and twitches in agony! ogg Ogg who? $ Engage! $n oggs $N's head with photon torpedos! $N reels. $n oggs your head with photon torpedos! You are reeling. You can't find your target. If you do that, the universe will explode. $n almost oggs $mself, but wisely reconsiders. confused Your confusion is showing. $n blinks slowly... You blink slowly, trying to decipher $S comment. $n blinks slowly. Maybe $N left a word out of $S sentence... $n blinks slowly. Maybe you left a word out of your sentence? No wonder you're confused. # beam You beam delightedly at nothing in particular. $n beams broadly at nothing in particular. You dazzle $N with your smile. $n must like $N a great deal to beam at $M so broadly! $n must like you a great deal to beam at you so broadly! You look pretty silly beaming at imaginary friends... Well, aren't you special? $n beams at $mself, obviously pleased. bite You glare around, muttering "Bite me..." under your breath. $n glares around, muttering "Bite me..." under $s breath. You bite $N on the neck. $n bites $N on the neck! $n bites you on the neck. Hungry? No such luck. You bite your knuckle in anguish. $n bites $s knuckle in anguish...the tragedy! discodance Groovy! $n discos wildly! You grab $N and disco wildly! Groovy! $n grabs $N and does $m best Travolta! $n grabs you and does $m best Travolta! It's okay, you can disco solo too. # scuff You scuff your foot sheepishly. $n scuffs $s foot in the dirt, looking very sheepish. You scuff your foot, avoiding $N's gaze. $n scuffs $s foot and shyly avoids $N's gaze. $n scuffs $s foot and shyly avoids your gaze. They aren't here. # whap Whap who? $ You whap $N upside the head! With a resounding WHAP!, $n reprimands $N. HEY! $n whaps you upside the head! Whiff... Ow! You give yourself a resounding whap upside the head. Biff! $n whaps $mself upside the head! lag Yes, yes. $n is m o v i n g v e ry sl o w l y ... # chortle Heh. $n chortles mischievously. You chortle mischievously at $N. $n chortles mischievously at $N. $n chortles mischievously at you. Took you a while to get that....they aren't here. You chortle at your own joke. $n chortles at $s own joke. Don't bother. zerbert Gotta zerbert SOMEBODY. $ You lift $N's shirt and blow loudly into $S navel! $n lifts $N's shirt and blows loudly into $S navel! Yeek! $n lifts your shirt and blows loudly into your navel! You missed. Careful, people are staring... $n looks around furtively, and then bends over and blows loudly into $s own navel! twitch 0 0 You twitch nervously. $n twitches nervously. You twitch involuntarily at $N's presence. $N must really be getting to $n... $n notices you and twitches. Nervous? They aren't even here. # leer 0 0 You peer around the room, leering like the pervert you are! $n peers about, leering like a filthy pervert! You leer at $N like the pervert you are. $n eyes $N up and down, leering like a filthy pervert! $n eyes you up and down, leering like a filthy pervert! You'll have to settle for memories -- that person isn't here. Desperation has reached new heights, hasn't it? $n leers at $mself shamelessly. polite 0 0 You give a polite little chuckle. $n gives a polite little chuckle. You indicate your underappreciation of $S joke. $n gives a polite little chuckle to $N's joke. $n gives a politle but unappreciative chuckle to your joke. You can't find a friend to chuckle with. You chuckle at your own joke, since no one else would. $n chuckles at $s own joke, since none of you would. mischievous 0 0 You give a mischievous smile at the trouble you have in mind. $n grins mischievously at a nasty idea. You grin mischievously at $M, thinking an evil thought. $n grins mischievously at $N. $m must be thinking something evil. $n grins mischievously at you. You inch toward the door. You must be delirious. You grin mischievously to yourself. $n grins mischievously to $mself. accept 0 0 You accept the proferred apology graciously. $n graciously accepts the proferred apology. # anticipate 0 0 You murmur 'Sssssoonnn, my presssssciousssss...' $n murmurs 'Ssssssooonnnn, my pressssscioussss...' # shudder 0 0 You shudder at the horror and repress tears. $n shudders at the horror and represses tears. # powertrip 0 0 You scream 'The PPppppPOOOOoooWWWwwwErrRRR!' and writhe. $n writhes, screaming 'The PPppppPOOOOoooWWWwwwErrRRR!' # mull 0 0 You mull over the idea at hand, asking for patience. $n mulls over the idea at hand. Please be patient. # wait 0 0 You wait patiently. $n waits patiently. # bat 0 0 You bat your long, dark lashes and smile innocently. $n bats $s long, dark lashes and smiles innocently. # sage 0 0 You nod sagely. $n nods sagely. # contemplate 0 0 You bite your lip contemplatively. $n bites $s lip contemplatively. # agree 0 0 You agree absolutely. $n agrees absolutely. You nod in enthusiastic agreement with $N. $n nods in enthusiastic agreement with $N. $n nods in enthusiastic agreement with you. Sorry, your target is absent. You find yourself most agreeable. $n finds $mself the most agreeable being alive. toast 0 0 You raise a glass of champagne in a toast. $n raises $s glass of champagne in a toast. You raise your glass of champagne to $S. $n silently toasts $N. $n silently toasts you. Your object of praise is absent. You grin evilly and toast yourself. $n grins evilly and toasts $mself. conspire 0 0 You wink conspiratorily, waiting for the countersign. $n winks conspiratorily, waiting for the countersign. You induct $S into your private conspiracy with a wink. $n winks conspiratorily at $N. You wonder what this can mean. $n inducts you into $m private conspiracy with a wink. Even you conspire against yourself. $n is paranoid enough to distrust even $mself. # support 0 0 You fully support the plan. $n fully supports the plan. You hug $M supportively and smile. $n hugs $N supportively and smiles. $n hugs you supportively and smiles. Sorry, friend, I can't see that person here. You hug yourself sadly. $n hugs $mself sadly. Perhaps you could help? pound 0 0 You make vague pounding motions with your fist at the thought. $n makes vague pounding motions with $m fist at the thought. You pound $M into a bloody mass. $n pounds $N into a bloody mass. $n pounds you into a bloody mass. Sorry, friend, I can't see that person here. # wrist 0 0 You hold out out a wrist for a slap. $n holds out a wrist for a slap. You slaps $M wrist sharply. $n slaps $N's wrist sharply. $n slaps your wrist sharply. Sorry, friend, I can't see that person here. You slap your own wrist. $n slaps $m own wrist. romeo 0 0 You light up a Romeo y Julietta cigar and puff contentedly. $n lights up a Romeo y Julietta cigar and puffs contentedly. # camel 0 0 You pretend you are a camel. $n pretends to be a camel. You light a Camel cigarette for $M. $n lights a Camel cigarette for $N. $n lights a Camel cigarette for you. You don't see that personhere. You light a Camel cigarette and inhale sharply. $n lights a Camel cigarette and inhales sharply. whip 0 0 You crack your bullwhip menacingly. $n cracks a bullwhip menacingly. You flick your whip across $M bare back. $n flicks $s whip across $N's bare back. $n flicks a whip across your back... the pain.. the pleasure.. Sorry, friend, I can't see that person here. You whip yourself into a frenzy. $n whips $mself into a frenzy. cramp 0 0 You gasp and clutch your abdomen, wheezing with the pain. $n gasps and clutches $m abdomen in agony. You hammerlock $M, screaming, "AAAAARRRRRGH!! I HAVE A CRAMP!!!" $n hammerlocks $N, screaming, "AAAAARRRRRGH!! I HAVE A CRAMP!!!". $n hammerlocks you, screaming "AAAAARRRRRGH!! I HAVE A CRAMP!!!" Suffering as you are, you didn't see that person slip out. # make 0 0 You breathe heavily and wetly. $n breathes heavily and wetly. You steam up the windows with $M. $n and $N start steaming up the windows. $n starts steaming up the windows with you. Sorry, friend, I can't see that person here. # sweep 0 0 You look at your empty arms and sigh. $n looks at $s empty arms and sighs. You sweep $M into your arms and kiss $M long and deeply. $n sweeps $N into $s arms and kisses $M long and deeply. $n sweeps you into $s arms and kisses you long and deeply. The object of your kiss is absent. # buff 0 0 You buff your nails on your cloak. $n buffs $s nails on $s cloak. # liver 0 0 You look angrily for someone to disembowel. $n angrily for someone to disembowel. You rip out $S liver and eat it. $n rips out $N's liver and eats it. $n rips out your liver and eats it. The object of your wrath is absent. # wrestle 0 0 $ $ You wrestle $M to the floor and pin $M there. $n wrestles $N to the floor, pinning $M there. $n wrestles you to the floor and pins you. Sorry, friend, I can't see that person here. You wrestle with your conscience. $n wrestles with $m conscience. tie 0 0 You toy with a pair of handcuffs suggestively. $n toys suggestively with a pair of handcuffs. You grab $N and tie $M to the bedposts. $n grabs $N and ties $S to a four poster bed. $n grabs you and ties you securely to a four poster bed. Sorry, friend, I can't see that person here. # tight 0 0 $ $ You hold $M tightly in your arms. $n holds $N tightly in $m arms. $n holds you in $m arms. Sorry, friend, I can't see that person here. # fatality 0 0 $ $ You intone, '$N wins. Fatality.' $n intones, '$N wins. Fatality.' $n intones, '$N wins. Fatality.' # yowl 0 0 You yowl in frustration. $n yowls in frustration! # silly 0 0 You do the silly walk all around the room. $n does the silly walk all around the room. $e *is* silly. # #0 #$ tkabber-plugins-0.11.1/socials/socials.tcl0000644000175000017500000000662110216132554020003 0ustar sergeisergei# $Id: socials.tcl 615 2005-03-16 22:38:36Z aleksey $ namespace eval socials { set social_list {} } proc socials::load {filename {enc utf-8}} { variable social set f [file join [file dirname [info script]] $filename] set fd [open $f] fconfigure $fd -encoding $enc while {1} { set s [gets $fd] if {$s == "" && [eof $fd]} break set s [string trim $s] if {$s == "#SOCIALS" || $s == ""} continue if {$s == "#0"} break set names [split $s] set names [lmatch -regexp $names {[^\d]}] #puts $names add $names foreach kind {char_no_arg others_no_arg char_found others_found \ vict_found char_not_found char_auto others_auto} { set s [string trim [gets $fd]] if {$s == {$}} { continue } elseif {$s == "#"} { break } assign $names $kind $s } } close $fd } proc socials::add {names} { variable social variable social_list foreach name $names { lappend social_list $name } foreach kind {char_no_arg others_no_arg char_found others_found \ vict_found char_not_found char_auto others_auto} { assign $names $kind "" } } proc socials::assign {names kind val} { variable social foreach name $names { set social($kind,$name) $val } } socials::load socials.ru koi8-r #puts [array get socials::social] proc socials::substitute {s from to} { regsub -all {\$n\d?} $s /me s regsub -all {\$e\d?} $s /me s #regsub -all {\$e\d?} $s $from s regsub -all {\$N\d?} $s $to s regsub -all {\$E\d?} $s $to s return $s } proc socials::interp {soc from to} { variable social if {$to == ""} { return [substitute $social(others_no_arg,$soc) $from $to] } else { return [substitute $social(others_found,$soc) $from $to] } } #puts [socials::interp giggle asd ""] #puts [socials::interp asd qwe] proc socials::commands_comps {chatid compsvar wordstart line} { variable social_list upvar 0 $compsvar comps if {!$wordstart} { foreach soc $social_list { lappend comps "/$soc " } } #debugmsg completion "SOC: $comps" } hook::add generate_completions_hook \ [namespace current]::socials::commands_comps 51 #puts [llength $socials::social_list] proc socials::handle_commands {chatid user body type} { variable social_list variable social #if {$type != "groupchat"} return if {[string index $body 0] != "/"} return set we [string wordend $body 1] set command [string trim [crange $body 1 $we]] set to [string trim [crange $body $we end]] if {[lcontain $social_list $command]} { set our_jid [chat::our_jid $chatid] set connid [chat::get_connid $chatid] if {[catch {chat::get_nick $connid $our_jid groupchat} from]} { set from [chat::get_nick $our_jid groupchat] } if {$to == $from} { set s [substitute $social(others_auto,$command) $from $to] } elseif {$to == ""} { set s [substitute $social(others_no_arg,$command) $from $to] if {$s == ""} { set se [substitute $social(char_no_arg,$command) $from $to] chat::add_message $chatid $chatid error $se {} } } else { set s [substitute $social(others_found,$command) $from $to] } if {$s != ""} { #hook::run chat_send_message_hook $chatid $user $s $type ::plugins::send_message $chatid $user $s $type ::plugins::draw_message $chatid $user $s $type } return stop } } hook::add chat_send_message_hook \ [namespace current]::socials::handle_commands 50 tkabber-plugins-0.11.1/socials/ChangeLog0000644000175000017500000000042410216132554017407 0ustar sergeisergei2005-03-17 Alexey Shchepin * socials.tcl: Bugfix 2003-12-03 Alexey Shchepin * socials.tcl: Bugfix (thanks to Sergei Golovan) 2003-05-29 Alexey Shchepin * socials.tcl: Now socials work in private chats tkabber-plugins-0.11.1/Makefile0000644000175000017500000000230511075425335015646 0ustar sergeisergei# $Id: Makefile 1513 2008-10-15 17:39:41Z sergei $ PREFIX = /usr/local TKABBERPLUGINSDIR = $(PREFIX)/share/tkabber-plugins DOCDIR = $(PREFIX)/share/doc/tkabber-plugins SUBDIRS = aniemoticons \ attline \ bc \ browser \ checkers \ chess \ ctcomp \ custom-urls \ cyrillize \ debug \ ejabberd \ floatinglog \ georoster \ gmail \ iconsets \ jidlink \ latex \ mute \ openurl \ osd \ presencecmd \ quiz \ quotelastmsg \ receipts \ renju \ reversi \ singularity \ socials \ spy \ stripes \ tclchat \ tkabber-khim \ traffic \ unixkeys \ whiteboard install: install-bin install-doc install-bin: mkdir -p $(DESTDIR)/$(TKABBERPLUGINSDIR) cp -r $(SUBDIRS) $(DESTDIR)/$(TKABBERPLUGINSDIR) echo "" echo "" echo "" echo "To enable desired plugins copy or link their directories to ~/.tkabber/plugins/" echo "" echo "" echo "" install-doc: mkdir -p $(DESTDIR)/$(DOCDIR) cp COPYING ChangeLog README $(DESTDIR)/$(DOCDIR) .PHONY: install install-bin install-doc tkabber-plugins-0.11.1/bc/0000755000175000017500000000000011076120366014567 5ustar sergeisergeitkabber-plugins-0.11.1/bc/bc.tcl0000644000175000017500000001763710657346175015711 0ustar sergeisergei# $Id: bc.tcl 1183 2007-08-11 14:49:33Z sergei $ package require textutil namespace eval bc { set prefix {[B&C]: } } proc bc::load_file {filename {enc utf-8}} { variable words set fd [open $filename] fconfigure $fd -encoding $enc set words {} while {![eof $fd]} { lappend words [string trim [gets $fd]] } close $fd } namespace eval bc { # A hack (reload the script in koi8-r encoding) if {![info exists words]} { set file [file join [file dirname [info script]] ru.dic] load_file $file koi8-r set fd [open [info script]] fconfigure $fd -encoding koi8-r uplevel 1 [read $fd] close $fd return } } proc bc::get_question {} { variable words if {![info exists words] || ![llength $words]} return while {![info exists w]} { set w [lindex $words [rand [llength $words]]] if {[regexp {(.).*\1} $w]} { unset w } } return $w } proc bc::commands_comps {chatid compsvar wordstart line} { upvar 0 $compsvar comps if {!$wordstart} { lappend comps "/bcstart " "/bcstop " "/bcnext " "/bctop " } } hook::add generate_completions_hook \ [namespace current]::bc::commands_comps proc bc::handle_commands {chatid user body type} { variable game if {$type != "groupchat"} return if {[string index $body 0] != "/"} return set jid [chat::get_jid $chatid] lassign [textutil::splitx [string trim $body] {[\t \r\n]+}] command nick switch -- $command { /bcstart { start $chatid return stop } /bcstop { stop $chatid return stop } /bcnext { if {$nick != ""} { # , ... next $chatid "$jid/$nick" $type } return stop } /bctop { top $chatid return stop } } return } hook::add chat_send_message_hook \ [namespace current]::bc::handle_commands 50 proc bc::get_nick {chatid jid type} { if {[catch {chat::get_nick [chat::get_connid $chatid] $jid $type} nick]} { return [chat::get_nick $jid $type] } else { return $nick } } proc bc::handle_messages {chatid from type body x} { variable game variable words variable word variable attempts variable prefix set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] set s [string trim $body] switch -- $s { !bctop { top $chatid return } !bcrules { printrules $chatid $from return } !bcstart - !bsnext { next $chatid $from $type } } if {![info exists game($chatid)] || ![info exists word($chatid,$from)]} return switch -- $s { default { set nick [get_nick $chatid $from $type] set w [filter $body] if {[string length $w] != 5} { return } set ww [filter $word($chatid,$from)] if {$w == $ww} { incr attempts($chatid,$from) set at $attempts($chatid,$from) message::send_msg $jid -type groupchat \ -body "$nick: ${prefix}! \ \"$word($chatid,$from)\" $at\ [lindex {. } [numgrp $at]]." \ -connection $connid add_score $chatid $nick $ww $at unset word($chatid,$from) next $chatid $from $type return } if {[lsearch -exact $words $w] == -1} { message::send_msg $jid -type groupchat \ -body "$nick: ${prefix} \"$w\"." \ -connection $connid return } set l [string length $w] set matches 0 for {set i 0} {$i < $l} {incr i} { incr matches [expr {[string first [string index $w $i] $ww] != -1}] } if {[info exists attempts($chatid,$from)]} { incr attempts($chatid,$from) } else { set attempts($chatid,$from) 1 } message::send_msg $jid -type groupchat \ -body "$nick: ${prefix} $w: $matches" \ -connection $connid } } } hook::add draw_message_hook [namespace current]::bc::handle_messages 79 proc bc::start {chatid} { variable game variable prefix set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] if {![info exists game($chatid)]} { set game($chatid) "" message::send_msg $jid -type groupchat \ -body "${prefix} \" \"!\ , !bcrules." \ -connection $connid } else { chat::add_message $chatid $jid error " " {} } } proc bc::stop {chatid} { variable game variable word variable attempts variable prefix set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] if {[info exists game($chatid)]} { foreach n [array names word "$chatid,*"] { unset word($n) } foreach n [array names attempts "$chatid,*"] { unset attempts($n) } unset game($chatid) message::send_msg $jid -type groupchat \ -body "${prefix} ." \ -connection $connid top $chatid } else { chat::add_message $chatid $jid error " " {} } } proc bc::next {chatid jid type} { variable game variable word variable prefix set connid [chat::get_connid $chatid] set jid1 [chat::get_jid $chatid] if {[info exists game($chatid)]} { if {[info exists word($chatid,$jid)]} { set nick [get_nick $chatid $jid $type] message::send_msg $jid1 -type $type \ -body "$nick: ${prefix} : $word($chatid,$jid)." \ -connection $connid } catch {unset word($chatid.$jid)} after idle [list [namespace current]::ask $chatid $jid] } else { chat::add_message $chatid $jid1 error " " {} } } proc bc::ask {chatid jid} { variable game variable word variable attempts variable prefix set connid [chat::get_connid $chatid] set jid1 [chat::get_jid $chatid] after cancel [list [namespace current]::ask $chatid $jid] set word($chatid,$jid) [get_question] set attempts($chatid,$jid) 0 set nick [get_nick $chatid $jid groupchat] message::send_msg $jid1 -type groupchat \ -body "$nick: ${prefix} . ." \ -connection $connid } proc bc::filter {text} { regsub -all {[;:()\[\]!?.,/\\{}]} [string tolower $text] "" text return [string trim $text] } proc bc::numgrp {number} { switch -glob -- $number { *11 {return 3} *12 {return 3} *13 {return 3} *14 {return 3} *1 {return 1} *2 {return 2} *3 {return 2} *4 {return 2} default {return 3} } } proc bc::top {chatid} { variable top variable prefix set connid [chat::get_connid $chatid] set jid [chat::get_jid $chatid] if {[info exists top($chatid)]} { set t [lsort -integer -increasing -index 2 $top($chatid)] set ts "" foreach item $t { lassign $item nick word score append ts "$score\t$word\t$nick\n" } message::send_msg $jid -type groupchat \ -body "${prefix}Top scores:\n$ts" \ -connection $connid } else { chat::add_message $chatid $jid error " top scores" {} } } proc bc::add_score {chatid nick word attempts} { variable top if {![info exists top($chatid)]} { set top($chatid) {} } set t {} set b 1 foreach item $top($chatid) { lassign $item n w a if {$n == $nick} { if {$a > $attempts} { set a $attempts set w $word } set b 0 } lappend t [list $n $w $a] } if {$b} { lappend t [list $nick $word $attempts] } set top($chatid) $t } proc bc::printrules {chatid to} { variable game set connid [chat::get_connid $chatid] if {[info exists game($chatid)]} { message::send_msg $to -type chat \ -body " \" \"\n\ 1) () \ ( ) \ .\n\ 2) , \ ( , 5-)\ , \ .\n\ 3) , .\n\ \n\ , , !bcstart" \ -connection $connid } } tkabber-plugins-0.11.1/bc/ru.dic0000644000175000017500000002666407553070056015721 0ustar sergeisergei tkabber-plugins-0.11.1/ChangeLog0000644000175000017500000007613111075425335015770 0ustar sergeisergei2008-10-15 Sergei Golovan * quotelastmsg/*, singularity/*, stripes/*: Added three new plugins (thanks to Konstantin Khomoutov). 2008-08-26 Sergei Golovan * whiteboard/whiteboard.tcl: Converted draw actions back to radio buttons (it's too inefficient to use popup menu for them). Transform and remove actions are left in the popup menu. * whiteboard/msgs/ru.msg: Updated Russian translation. * README: Added description fo receipts and unixkeys plugins, cleared description for ctcomp plugins (thanks to Konstantin Khomoutov). * whiteboard/whiteboard.tcl: Fixed width of tools radiobuttons. * whiteboard/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2008-08-08 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, renju/renju.tcl, reversi/reversi.tcl: Don't warn user about not received move replies on disconnect. * chess/chess.tcl: Added draw by repetition. * chess/msgs/ru.msg: Updated Russian translation. * chess/chess.tcl: Fixed bug with forbidden castling in case when pieces has moved. * chess/chess.tcl: Added possibility of castling and capture en passant to position code when counting repetitions. 2008-07-12 Sergei Golovan * whiteboard/whiteboard.tcl: Fixed typo. 2008-07-09 Sergei Golovan * whiteboard/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2008-07-08 Sergei Golovan * whiteboard/svgrender.tcl: Fixed rotation transform. Changed id canvas tags from id$id to [list id $id] form. * whiteboard/whiteboard.tcl: Added several object transformations. 2008-07-07 Sergei Golovan * whiteboard/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2008-07-06 Sergei Golovan * whiteboard/svgrender.tcl: Reworked SVG rendering, made all existing shapes transformable (except text), implemented all transformations, added several new attributes (stroke-linecap, stroke-linejoin etc.). Broken compatibility (the default outline color is empty now and not black). * whiteboard/whiteboard.tcl: Use svgrender for all elements rendering. Added a new rectangular shape. Moved all actions to a popup menu instead of radiobuttons. Added very preliminary (without user interface yet) tranformation support. 2008-06-18 Sergei Golovan * cyrillize/cyrillize.tcl: Added cyrillize bindings to all text and entry widgets. 2008-06-08 Sergei Golovan * unixkeys/README, unixkeys/TODO, unixkeys/unixkeys.tcl: Added bindings to entry widgets also (thanks to Konstantin Khomoutov). * Makefile: Added receipts and unixkeys to plugins list. * *: 0.11.0 is released. 2008-06-04 Sergei Golovan * receipts/msgs/pl.msg: Updated Polish translation (thanks to Irek Chmielowiec). * tclchat/msgs/es.msg, browser/msgs/es.msg, renju/msgs/es.msg, jidlink/msgs/es.msg, receipts/msgs/es.msg: Added Spanish translation (thanks to Badlop). * unixkeys/*: Added a small plugin which provides alternative bindings in Text widget close to Emacs and readline bindings (thanks to Konstantin Khomoutov). 2008-05-22 Sergei Golovan * floatinglog/msgs/ru.msg, receipts/msgs/ru.msg: Updated Russian translation. 2008-05-20 Sergei Golovan * receipts/msgs/ru.msg: Added Russian translation (thanks to Konstantin Khomoutov). 2008-05-18 Sergei Golovan * receipts/receipts.tcl: Allowed to return message receipts to private chat partners in a conference room. Removed per-user receipts customization (thanks to Konstantin Khomoutov). * receipts/TODO, receipts/README: Clarified receipts requesting/responding behavior (thanks to Konstantin Khomoutov). * receipts/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2008-05-14 Sergei Golovan * receipts/receipts.tcl: Fixed a bug with cleanup for JIDs that contain %. 2008-05-13 Sergei Golovan * receipts/receipts.tcl: Allowed to disable receipt queries and answers. Don't send receipts to users which aren't subscribed to our presence (thanks to Konstantin Khomoutov). * receipts/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2008-05-12 Sergei Golovan * tkabber-khim/khim/es.msg: Added Spanish transpation (thanks to Badlop). * receipts/msgs/pl.msg: Added Polish translation (thanks to Irek Chmielowiec). 2008-05-11 Sergei Golovan * receipts/*: Added new plugin which implements XEP-0184 (Message Receipts). Thanks to Konstantin Khomoutov. * debug/debug.tcl: Do not crash if debug messages are coming when main window and mainnotebook aren't created yet. * receipts/receipts.tcl: Added message catalogs support. * receipts/msgs/de.msg: Added German translation (thanks to Roger Sondermann). 2008-05-05 Sergei Golovan * openurl/openurl.tcl, openurl/msgs/*.msg: Open URL in a separate tab in Opera, and moved menu items for different browsers to a submenu (thanks to Alex Smirnov, closes http://www.jabber.ru/bugzilla/show_bug.cgi?id=379). 2008-04-16 Sergei Golovan * renju/renju.tcl: Implemented Renju game (without openings). 2008-03-23 Sergei Golovan * attline/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). * traffic/traffic.tcl, osd/osd.tcl: Removed usage of global font variable. 2008-01-28 Sergei Golovan * browser/browser.tcl, checkers/checkers.tcl, chess/chess.tcl, ejabberd/ejabberd.tcl, georoster/georoster.tcl, gmail/gmail.tcl, mute/mute.tcl, renju/renju.tcl, reversi/reversi.tcl, spy/spy.tcl, tclchat/tclchat.tcl: Removed usage of global font variable. 2008-01-20 Sergei Golovan * attline/attline.tcl: Fixed bug with leaving chatlog window in normal state if an attention doesn't need to be redrawn (thanks to Konstantin Khomoutov). 2008-01-16 Sergei Golovan * attline/attline.tcl: Removed tags ATLINE, made the line more thin, optimized line redrawing, state clearing moved to chat_close_post_hook (thanks to Konstantin Khomoutov). * attline/attline.tcl: Changed default line color from red to black. * floatinglog/floatinglog.tcl: Fixed bug with displaying message with empty body (thanks to Ruslan Rakhmanin). 2007-12-31 Sergei Golovan * gmail/gmail.tcl: Removed opening notifications window at Tkabber start and added it to Tkabber state saving/restoring. * browser/browser.tcl, checkers/checkers.tcl, chess/chess.tcl, ejabberd/ejabberd.tcl, georoster/georoster.tcl, gmail/gmail.tcl, renju/renju.tcl, reversi/reversi.tcl, spy/spy.tcl, traffic/traffic.tcl, whiteboard/whiteboard.tcl: Do not raise new tabs (when raise_new_tab is off) only if it isn't created by a Tkabber user himself, but by some external event (incoming message etc.). 2007-12-30 Sergei Golovan * ejabberd/msgs/de.msg: Added German translation (thanks to Roger Sondermann). 2007-12-26 Sergei Golovan * attline/attline.tcl: Fixed bug with processing Configure events which come before attention line is placed to its chat window. 2007-12-19 Sergei Golovan * floatinglog/floatinglog.tcl, latex/latex.tcl, tkabber-khim/khim/khim.tcl: Added -- to all switch commands. 2007-12-15 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, renju/renju.tcl, reversi/reversi.tcl: Fixed invitation dialogs. 2007-12-06 Sergei Golovan * attline/attline.tcl: Fixed attention line width calculation (thanks to Konstantin Khomoutov). 2007-11-30 Sergei Golovan * attline/attline.tcl: Fixed attline state cleanup after closing chat window. 2007-11-29 Sergei Golovan * attline/attline.tcl: Fixed crash after closing chat tab/window before attline is expired if option 'remove expired attline' is turned on (thanks to Konstantin Khomoutov). 2007-11-25 Sergei Golovan * latex/latex.tcl: use [winfo rgb] to get RGB color instead of creating temporary image. * tclchat/tclchat.tcl: Fixed plugins::nickcolors::get_color call. * tclchat/tclchat_messages.tcl: Fixed processing Tkchat colors. 2007-11-14 Sergei Golovan * ctcomp/README: Added info about keybindings (thanks to Konstantin Khomoutov). * attline/BUGS: Removed since bugs mentioned in it are fixed (thanks to Konstantin Khomoutov). * attline/TODO: Removed already done tasks (thanks to Konstantin Khomoutov). * attline/README, attline/INSTALL: Added info about plugin and installation instructions (thanks to Konstantin Khomoutov). * ctcomp/README: A small fix (thanks to Konstantin Khomoutov). 2007-11-13 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, renju/renju.tcl, reversi/reversi.tcl: Turned invitation dialogs to non-modal ones. 2007-11-08 Sergei Golovan * floatinglog/msgs/pl.msg, gmail/msgs/pl.msg, openurl/msgs/pl.msg, presencecmd/msgs/pl.msg: Added Polish translation (thanks to Irek Chmielowiec). * gmail/msgs/de.msg: Added German translation (thanks to Roger Sondermann). * spy/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-10-31 Sergei Golovan * attline/msgs/es.msg, chess/msgs/es.msg, ejabberd/msgs/es.msg, floatinglog/msgs/es.msg, georoster/msgs/es.msg, gmail/msgs/es.msg, openurl/msgs/es.msg, presencecmd/msgs/es.msg, tkabber-khim/msgs/es.msg: Added and updated Spanish translation (thanks to Badlop). 2007-10-28 Sergei Golovan * *: Tagged 0.10.1-beta2 for release. 2007-10-27 Sergei Golovan * floatinglog/floatinglog.tcl: Added an option for the height of floating log window, and made it ignore IBB file transfer requests (thanks to Ruslan Rakhmanin). * floatinglog/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-10-26 Sergei Golovan * ctcomp/ctcomp.tcl: Fixed definition of word edges (thanks to Konstantin Khomoutov). 2007-10-23 Sergei Golovan * floatinglog/floatinglog.tcl: Raise floatinlog window. It helps to keep it on top (thanks to Denis Shaposhnikov). 2007-10-14 Sergei Golovan * attline/attline.tcl: Changed atline namespace to attline, the same for debug type. Switched to chat::winid_to_chatid. Bound cleanup procedure to Chat window class instead of specific windows (thanks to Konstantin Khomoutov). * attline/msgs/ru.msg: Fixed Russian translation (thanks to Konstantin Khomoutov). * debug/debug.tcl: Added attline and tclchat debug types. Reorganized debug types menu into two-level menu. 2007-10-10 Sergei Golovan * floatinglog/floatinglog.tcl: Added new options which allow to show only personal messages (or MUC highlights) and allow not to show status changes (thanks to Konstantin Khomoutov). * floatinglog/floatinglog.tcl, floatinglog/msgs/ru.msg: Fixed processing (ignoring) idle status messages (thanks to Konstantin Khomoutov) * floatinglog/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-10-07 Sergei Golovan * floatinglog/floatinglog.tcl: Fixed doubleclick bindings to JIDs which contain %. Removed unused variables and useless message options. * floatinglog/TODO: Removed tasks which are already done or will never be done. * ctcomp/*: Added new plugin which allow to complete words from chat log windows (thanks to Konstantin Khomoutov). * Makefile, README: Added ctcomp plugin. * *: Tagged 0.10.1-beta for release. * floatinglog/floatinglog.tcl: Added extra geometry settings to fix the behavior under control of some window managers (openbox, ion3). 2007-10-06 Sergei Golovan * browser/browser.tcl: Replaced ::jlib::route by the first connection in cinnection list. * floatinglog/*, README, Makefile: Added new plugin which reports about incoming messages in a floating log window (thanks to Ruslan Rakhmanin). * openurl/openurl.tcl, openurl/msgs/ru.msg: Added support for translations and Russian message file. * floatinglog/floatinglog.tcl: Cleaned up messages. Changed time units for hide delay from milliseconds to seconds. * floatinglog/msgs/ru.msg: Added Russian translation. * floatinglog/msgs/de.msg, openurl/msgs/de.msg: Added German translation (thanks to Roger Sondermann). * floatinglog/floatinglog.tcl: Removed explicit usage of background and foreground resources. 2007-10-05 Sergei Golovan * README: Added missing descriptions. * Makefile: Added custom-urls to a list of plugins to install. 2007-09-23 Sergei Golovan * aniemoticons/anigif.tcl: Fixed some GIF images processing (thanks to Ruslan Rakhmanin). 2007-09-21 Sergei Golovan * georoster/georoster.tcl: Use separated public XML storage interface. 2007-09-10 Sergei Golovan * presencecmd/msgs/de.msg: Added German translation (thanks to Roger Sondermann). 2007-09-08 Sergei Golovan * jidlink/msgs/de.msg: Added German translation (thanks to Roger Sondermann). 2007-09-05 Sergei Golovan * attline/msgs/pl.msg, browser/msgs/pl.msg, ejabberd/msgs/pl.msg, georoster/msgs/pl.msg, jidlink/msgs/pl.msg: Updated Polish translation (thanks to Irek Chmielowiec). * gmail/gmail.tcl, presencecmd/presencecmd.tcl: Made user messages translateable. * gmail/msgs/ru.msg, presencecmd/msgs/ru.msg: Added Russian translation. 2007-09-03 Sergei Golovan * gmail/gmail.tcl: Fixed bug with empty disabledForeground option. 2007-09-02 Sergei Golovan * tkabber-khim/tkabber-khim.tcl: Removed unnecessary namespace level. * gmail/gmail.tcl: Added new plugin which allows users of Google Talk service to get Gmail notifications. * openurl/openurl.tcl: Added new plugin which allows to open URLs in any installed browser found in PATH environment variable. 2007-09-01 Sergei Golovan * browser/msgs/de.msg, browser/msgs/ru.msg: Added SVN Id attribute. * jidlink/msgs/ru.msg: Fixed SVN Id attribute. 2007-08-31 Sergei Golovan * jidlink/*: New Jidlink support plugin. Jidlink support is removed from main Tkabebr distribution because it is obsolete and undocumented and superseeded by Stream Initiation. * Makefile: Added browser and jidlink plugins to a plugin list. 2007-08-30 Sergei Golovan * browser/*: New Jabber Browser (XEP-0011) support plugin. It was removed from main Tkabber distribution because it is deprecated. * browser/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-08-18 Sergei Golovan * attline/attline.tcl: Code cleanup. Do not expire attention line if it is already expired. * presencecmd/presencecmd.tcl: Code cleanup. * attline/attline.tcl: Added support for message catalogs. * attline/msgs/ru.msg: Added Russian translation. * attline/msgs/de.msg, debug/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-08-17 Sergei Golovan * attline/*: Added new plguin which draws an attention line in chat windows (thanks to Konstantin Khomoutov). * presencecmd/*: Added new plugin which introduces several chat commands changing user's presence information (thanks to Konstantin Khomoutov). * README: Added short descriptions of attline and presencecmd plugins. * Makefile: Added new plugins. * attline/*, presencecmd/*: Changed eol style to native. * attline/attline.tcl: Removed using control package to not force adding it to a strapacks, and unconditionally use real priority value in hook::add because it isn't necessary to use this plugin in earlier Tkabber versions. 2007-08-11 Sergei Golovan * bc/bc.tcl, checkers/checkers.tcl, chess/chess.tcl, mute/mute.tcl, quiz/quiz.tcl, renju/renju.tcl, reversi/reversi.tcl, whiteboard/whiteboard.tcl: Renamed [random] procedure to [rand] to prevent clash with one from Memchan package, which is loaded for JISP support. 2007-08-09 Sergei Golovan * quiz/quiz.tcl: Fixed hinting and added displaying the correct answer if nobody has found it (thanks to Alexander Kupcov). 2007-06-24 Sergei Golovan * tclchat/tclchat.tcl: Changed loginconf options according to changes in login.tcl. 2007-06-12 Sergei Golovan * georoster/georoster.tcl: Fixed typo. * custom-urls/custom-urls.tcl, README: Added new plugin, which allows to specify custom URLs based on regular expressions. * georoster/georoster.tcl: Fixed variable initialization. * custom-urls/custom-urls.tcl: Added an example of custom URLs. 2007-06-11 Sergei Golovan * georoster/georoster.tcl: Fixed drag'n'drop of JIDs over Georoster window. Store georoster contacts separately for each Tkabber connection (while showing them in one window). * georoster/msgs/ru.msg, georoster/msgs/uk.msg: Updated. * georoster/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-06-10 Sergei Golovan * ejabberd/ejabberd.tcl: Added connection choice to a dialog of selecting ejabberd server to administrate. Also, allowed opening several windows to the same JID from different connections. Also, clean up data variables on page close. * ejabberd/msgs/ru.msg, ejabberd/msgs/uk.msg: Updated. 2007-06-09 Sergei Golovan * tkabber-khim/khim/khim.tcl: Added khim package forgetting command to load really newest khim version. 2007-06-04 Sergei Golovan * whiteboard/svgrender.tcl: Ignore surrounding spaces in point lists. * ChangeLog: Fixed year in recent changelog entry dates. 2007-04-12 Sergei Golovan * *: 0.10.0 is released. * README: Added description for renju and tclchat plugins. 2007-04-08 Sergei Golovan * tclchat/tclchat.tcl: Fixed init routine priority. * renju/renju.tcl: Do not reply to game type 'renju' calls because this type is not implemented yet. 2007-04-02 Sergei Golovan * georoster/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-03-28 Sergei Golovan * traffic/traffic.tcl: Added scrolling by mousewheel (thanks to Artem Borodin). 2007-03-27 Sergei Golovan * mute/mute.tcl: Fixed bug with breaking messages into separate words in message dialogs. * tclchat/tclchat.tcl: Fixed restoring disabled state of Tclers' chat window. 2007-03-22 Sergei Golovan * traffic/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-03-17 Sergei Golovan * debug/msgs/es.msg, spy/msgs/es.msg: Updated Spanish translation (thanks to Badlop). 2007-03-14 Sergei Golovan * debug/msgs/pl.msg, spy/msgs/pl.msg: Updated Polish translation (thanks to Irek Chmielowiec). 2007-03-11 Sergei Golovan * debug/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-03-10 Sergei Golovan * georoster/georoster.tcl: Added -connection argument to jlib::send_iq call. * debug/debug.tcl: Made jlib module debug messages more clear. 2007-03-08 Sergei Golovan * tclchat/tclchat.tcl: Load translated messages. * tclchat/msgs/ru.msg, mute/msgs/ru.msg: Added Russian translation. * debug/msgs/ru.msg, renju/msgs/ru.msg: Updated Russian translation. 2007-03-06 Sergei Golovan * latex/msgs.de.msg, spy/msgs/de.msg, traffic/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-03-04 Sergei Golovan * aniemoticons/aniemoticons.tcl, aniemoticons/anigif.tcl: Bugfix. Fixed creating and destroying images. * debug/debug.tcl, spy/spy.tcl: Use new unified search panel interface. * aniemoticons/anigif.tcl: Code cleanup. Fixed bugs with image names, which contain semicolon. * Makefile: Added installing of aniemoticons plugin. * *: 0.10.0-beta2 is released. * spy/msgs/de.msg, traffic/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-03-03 Sergei Golovan * aniemoticons/*: Added new external plugin (moved from the main Tkabber tree). Also applied patch by Ruslan Rakhmanin, which fixes some animated GIFs processing and improves performance. * README: Added short description of aniemoticons plugin. 2007-02-26 Sergei Golovan * renju/pixmaps/black/*: Added high contrast Gomoku/Renju theme. * whiteboard/msgs/de.msg: Added German translation (thanks to Roger Sondermann). 2007-02-25 Sergei Golovan * debug/msgs/de.msg, georoster/msgs/de.msg, spy/msgs/de.msg, traffic/msgs/de.msg: Added German translation (thanks to Roger Sondermann). * georoster/msgs/de.msg: Updated German translation (thanks to Roger Sondermann). 2007-02-23 Sergei Golovan * Makefile: Added tclchat and renju plugins. * *: 0.10.0-beta is released. 2007-02-17 Sergei Golovan * renju/renju.tcl: Added tournament Gomoku variant (with 5x5 forbidden zone for black at the second turn). 2007-02-16 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, renju/renju.tcl, reversi/reversi.tcl: Fixed bug with sometimes undeleted cell border on mouse leave. * renju/renju.tcl: Added standard Gomoku variant (where overline is not a win). 2007-02-15 Sergei Golovan * renju/*: New game plugin Gomoku/Renju (unfinished yet, only free-style Gomoku is implemented). 2007-02-14 Sergei Golovan * tclchat/tclchat.tcl: Added customize group Tclchat. * tclchat/tclchat_messages.tcl: Made bridge nick and JID, and Tclers' chat room JID customizable. Added processing of nickname changes on the IRC side. * reversi/msgs/pl.msg, debug/msgs/pl.msg, whiteboard/msgs/pl.msg, spy/msgs/pl.msg: Updated Polish translation (thanks to Irek Chmielowiec). 2007-02-13 Sergei Golovan * debug/msgs/es.msg, spy/msgs/es.msg, whiteboard/msgs/es.msg: Updated Spanish translation (thanks to Badlop). * tclchat/tclchat.tcl, tclchat/tclchat_commands.tcl, tclchat/tclchat_messages.tcl: Added modified tclchat plugin by Pat Thoyts for more comfortable use of Tclers' chat (unfinished yet). * tclchat/tclchat.tcl: Moved adding color to more suitable hook. * tclchat/tclchat_messages.tcl: Added IRC users, connected to Tclers' chat, to the conference roster. 2007-02-11 Sergei Golovan * iconsets/icq/icondef.xml, iconsets/icq/tkabber/tkabber-logo.gif: Removed logo (it must be only one). * iconsets/icq/tkabber/new-msg.gif: Removed unused icon. * iconsets/kroc/tkabber/new-msg.gif, iconsets/kroc/tkabber/search_bk.gif, iconsets/kroc/tkabber/search_case.gif, iconsets/kroc/tkabber/search_exact.gif, iconsets/kroc/tkabber/search_fw.gif: Removed unused icons. * whiteboard/whiteboard.tcl: Made using jlib::x_delay for computing message time. * georoster/georoster.tcl, spy/spy.tcl, traffic/traffic.tcl: Save tabs on exit and restore on start. * bc/bc.tcl, quiz/quiz.tcl, osd/osd.tcl, mute/mute.tcl: Made working with current Tkabber version. * quiz/quizdata.txt: Added short quiz data sample. * COPYING, Makefile: Added license file and Makefile. 2007-02-10 Sergei Golovan * whiteboard/whiteboard.tcl, whiteboard/svgrender.tcl: Added balloons, which show when the whiteboard item was created, and who has drawn it. Also redone text input dialog. * whiteboard/msgs/ru.msg: Updated. * README, checkers/README, debug/debug.tcl, debug/msgs/pl.msg, debug/msgs/ru.msg, socials/README, spy/spy.tcl, tkabber-khim/INSTALL: Made more accurate references to Tkabber config directory. 2007-02-09 Sergei Golovan * iconsets/iconsets.tcl, iconsets/*: Moved borrowed iconsets to a separate plugin. * README: Updated. * whiteboard/whiteboard.tcl: Removed spacers from whiteboard toolbar to make it fit 800x600 window. 2007-01-29 Sergei Golovan * spy/spy.tcl: Fixed a typo (thanks to Pavel Borzenkov). 2007-01-27 Sergei Golovan * spy/spy.tcl: Added search in spy presence window. * debug/debug.tcl: Added search in debug window. * quiz/quiz.tcl: Added check for existence of file 3hauka.txt. 2007-01-26 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, debug/debug.tcl, ejabberd/ejabberd.tcl, georoster/georoster.tcl, reversi/reversi.tcl, whiteboard/whiteboard.tcl: Removed explicit tab updates on raise. * debug/debug.tcl: Added richtext and mucignore modules to debug modules. Fixed bug with unknown debug module. 2007-01-11 Sergei Golovan * cyrillize/cyrillize.tcl: Added backward conversion from russian to english (bound to ). Also, added bindings for cyrillic layout in Windows. 2007-01-06 Sergei Golovan * debug/debug.tcl, traffic/traffic.tcl: Changed config directory references to $::configdir. 2007-01-05 Sergei Golovan * debug/msgs/pl.msg, tkabber-khim/khim/pl.msg, whiteboard/msgs/pl.msg: Updated (thanks to Irek Chmielowiec). 2007-01-03 Sergei Golovan * debug/debug.tcl: Made plugin options customizeable via GUI. * debug/msgs/ru.msg: Updated. * debug/msgs/es.msg, debug/msgs/pl.msg, debug/msgs/uk.msg: Added VIM modeline. * tkabber-khim/tkabber-khim.tcl, tkabber-khim/khim/pl.msg, tkabber-khim/khim/ru.msg, tkabber-khim/msgs/pl.msg, tkabber-khim/msgs/ru.msg: Added newline to a message, which is printed to the terminal when KHIM cannot be loaded, to fit 80 symbol width. 2007-01-01 Sergei Golovan * tkabber-khim/msgs/ru.msg, whiteboard/msgs/ru.msg: Updated. 2006-12-30 Sergei Golovan * checkers/msgs/es.msg, chess/msgs/es.msg, reversi/msgs/es.msg, whiteboard/msgs/es.msg: Updated (thanks to Badlop). * traffic/traffic.tcl, traffic/msgs/pl.msg, traffic/msgs/ru.msg, traffic/msgs/uk.msg: Bugfix in translated string (thanks to Badlop). 2006-12-29 Sergei Golovan * tkabber-khim/khim/pl.msg, tkabber-khim/msgs/pl.msg: Added Polish translation (thanks to Irek Chmielowiec). * whiteboard/msgs/pl.msg: Updated (thanks to Irek Chmielowiec). * tkabber-khim/khim/uk.msg: Added Ukrainian translation (thanks to Artem Bondarenko). 2006-12-28 Sergei Golovan * whiteboard/whiteboard.tcl: Added whiteboard saving option. 2006-12-24 Sergei Golovan * reversi/msgs/uk.msg, debug/msgs/uk.msg, checkers/msgs/uk.msg, ejabberd/msgs/uk.msg, chess/msgs/uk.msg, georoster/msgs/uk.msg, spy/msgs/uk.msg, latex/msgs/uk.msg, traffic/msgs/uk.msg: Added Ukrainian translation (thanks to Artem Bondarenko). 2006-12-17 Sergei Golovan * tkabber-khim/khim/khim.tcl: Bumped khim version number to ensure its loading. 2006-12-15 Sergei Golovan * tkabber-khim/khim/khim.tcl: Changed Unicode charmap colors. 2006-12-13 Sergei Golovan * tkabber-khim/*: Added tkabber-khim plugin by Konstantin Khomoutov. It allows to input Unicode characters using KHIM package by Kevin Kenny. KHIM package is included, but it can be also obtained as part of tklib. 2006-12-05 Sergei Golovan * osd/osd.tcl: Don't notify on history messages read from the log files. 2006-12-03 Sergei Golovan * whiteboard/svgrender.tcl, whiteboard/whiteboard.tcl, whiteboard/msgs/ru.msg: Added circle and polygon whiteboard figures (thanks to Pavel Arajums). 2006-11-27 Sergei Golovan * debug/debug.tcl: Added loading translation messages. * reversi/msgs/pl.msg, debug/msgs/pl.msg, checkers/msgs/pl.msg whiteboard/msgs/pl.msg, ejabberd/msgs/pl.msg, chess/msgs/pl.msg, georoster/msgs/pl.msg, spy/msgs/pl.msg, traffic/msgs/pl.msg: Added Polish translation (thanks to Irek Chmielowiec). 2006-11-25 Sergei Golovan * georoster/georoster.tcl: Replaced erroneous user_from_jid by node_and_server_from_jid. 2006-11-24 Sergei Golovan * whiteboard/whiteboard.tcl: Use mousewheel to scroll whiteboard window. 2006-11-04 Sergei Golovan * latex/latex.tcl: Updated to match current emoticons engine. Changed LaTeX expression regexp to allow spaces in it. 2006-10-22 Sergei Golovan * whiteboard/svgrender.tcl: Check color existence before rendering whiteboard item using this color. 2006-10-08 Sergei Golovan * checkers/msgs/ru.msg, chess/msgs/ru.msg, reversi/msgs/ru.msg: Updated (thanks to Pavel Borzenkov). * README: Added new plugins description. Replaced JEP abbreviation by XEP. 2006-10-05 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, ejabberd/ejabberd.tcl, georoster/georoster.tcl, latex/latex.tcl, reversi/reversi.tcl, traffic/traffic.tcl, whiteboard/whiteboard.tcl: Removed changing of system encoding when loading translated messages because msgcat itself uses UTF-8. * osd/osd.tcl: Removed encoding configuring of osdcat pipe because it is a system encoding by default. * whiteboard/msgs/uk.msg: Added Ukrainian translation (thanks to Mykola Dzham). 2006-10-02 Sergei Golovan * reversi/reversi.tcl: Fixed typo (thanks to Irek Chmielowiec). 2006-09-30 Sergei Golovan * georoster/georoster.tcl: Use options menu with nonfixed border width. 2006-09-29 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, georoster/georoster.tcl, reversi/reversi.tcl: Replaced customizeable radio variables by options variables. 2006-09-27 Sergei Golovan * checkers/checkers.tcl, chess/chess.tcl, reversi/reversi.tcl: Added sound notification of opponent's move (thanks to Pavel Borzenkov). 2006-09-25 Sergei Golovan * debug/debug.tcl: Added several debug categories. * latex/msgs/es.msg, traffic/msgs/es.msg: Added Spanish translation (thanks to Badlop). * whiteboard/msgs/es.msg: Updated (thanks to Badlop). 2006-09-19 Sergei Golovan * traffic/traffic.tcl: Code cleanup. * checkers/checkers.tcl, chess/chess.tcl, mute/mute.tcl, reversi/reversi.tcl: Added lang parameter to procedures registered via iq:register. 2006-09-16 Sergei Golovan * chess/chess.tcl, checkers/checkers.tcl, reversi/reversi.tcl: Made games using hook::run with upvar instead of hook::foldl (it looks more "ticklish"). Improved packing of game history windows. * traffic/*: Added new traffic accounting plugin. It counts total length of unencrypted and/or uncompressed XML stanzas only (thanks to Artem Borodin). tkabber-plugins-0.11.1/chess/0000755000175000017500000000000011076120366015310 5ustar sergeisergeitkabber-plugins-0.11.1/chess/msgs/0000755000175000017500000000000011076120366016261 5ustar sergeisergeitkabber-plugins-0.11.1/chess/msgs/pl.msg0000644000175000017500000000771710667535014017425 0ustar sergeisergei# Polish messages file for chess plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "White" "Białe" ::msgcat::mcset pl "Chess with %s" "Szachy: %s" ::msgcat::mcset pl "Move: " "Ruch: " ::msgcat::mcset pl "History" "Historia" ::msgcat::mcset pl "Black" "Czarne" ::msgcat::mcset pl "Pawn promotion" "Promocja piona" ::msgcat::mcset pl "K" "K" ::msgcat::mcset pl "Q" "H" ::msgcat::mcset pl "R" "W" ::msgcat::mcset pl "B" "G" ::msgcat::mcset pl "N" "S" ::msgcat::mcset pl "Chess plugin options." "Ustawienia wtyczki do gry w szachy." ::msgcat::mcset pl "Chess figures theme." "Motyw graficzny szchownicy." ::msgcat::mcset pl "Flip board view when playing black by default." "Odwróć widok szachownicy podczas gry czarnymi." ::msgcat::mcset pl "Show last move by default." "Pokazuj ostatni ruch." ::msgcat::mcset pl "Promote pawns always as queens." "Promocja piona zawsze do hetmana." ::msgcat::mcset pl "Show tooltips with short instructions." "Pokazuj dymki podpowiedzi z krótkimi instrukcjami." ::msgcat::mcset pl "Allow illegal moves (useful for debugging)." "Pozwalaj na nieprawidłowe ruchy (użyteczne przy debugowaniu)." ::msgcat::mcset pl "Accept opponent illegal moves (useful for debugging)." "Pozwalaj na nieprawidłowe ruchy przeciwnika (użyteczne przy debugowaniu)." ::msgcat::mcset pl "Chess Invitation" "Zaproszenie do gry w szachy" ::msgcat::mcset pl "Sending chess game invitation to %s (%s)" "Wysyłanie zaproszenia do gry w szachy do %s (%s)" ::msgcat::mcset pl "I want play white" "Chcę grać białymi" ::msgcat::mcset pl "I want play black" "Chcę grać czarnymi" ::msgcat::mcset pl "Cancel invitation" "Anuluj zaproszenie" ::msgcat::mcset pl "%s (%s) has refused chess invitation: %s" "%s (%s) odrzuca zaproszenie do gry w szachy: %s" ::msgcat::mcset pl "Chess Invitation from %s" "Zaproszenie do gry w szachy od %s" ::msgcat::mcset pl "Chess game invitation from %s (%s) is received." "Otrzymano zaproszenie do gry w szachy od %s (%s)." ::msgcat::mcset pl "Agree to play" "Przyjmij zaproszenie" ::msgcat::mcset pl "Refuse to play" "Odrzuć zaproszenie" ::msgcat::mcset pl " (You)" " (Ty)" ::msgcat::mcset pl " (Opponent)" " (Przeciwnik)" ::msgcat::mcset pl "You win (Opponent resigned)" "Wygałeś (przeciwnik zrezygnował)" ::msgcat::mcset pl "Draw (Opponent accepted)" "Remis (za zgodą przeciwnika)" ::msgcat::mcset pl "Show last move" "Pokaż ostatni ruch" ::msgcat::mcset pl "Flip view" "Odwróć widok" ::msgcat::mcset pl "Propose a draw" "Zaproponuj remis" ::msgcat::mcset pl "Accept the draw proposal" "Zaakceptuj remis" ::msgcat::mcset pl "Resign the game" "Zrezygnuj z gry" ::msgcat::mcset pl "Press button and make move if you want propose draw" "Naciśnij przycisk i wykonaj ruch jeżeli chcesz zaproponować remis" ::msgcat::mcset pl "Press button if you want accept the draw proposal" "Naciśnij przycisk jeżeli chcesz zaakceptować propozycję remisu" ::msgcat::mcset pl "Press button if you want resign" "Naciśnij przycisk jeżeli chcesz zrezygnować z gry" ::msgcat::mcset pl "\n\n Opponent proposes a draw\n\n" "\n\n Przeciwnik proponuje remis\n\n" ::msgcat::mcset pl "Draw (Stalemate)" "Remis (Pat)" ::msgcat::mcset pl "You win (Checkmate)" "Wygrałeś (Szach i Mat)" ::msgcat::mcset pl "Opponent wins (Checkmate)" "Wygrał przeciwnik (Szach i Mat)" ::msgcat::mcset pl "Draw (You accepted)" "Remis (Za moją zgodą)" ::msgcat::mcset pl "Opponent wins (You resigned)" "Wygrał przeciwnik (Zrezygnowałeś z gry)" ::msgcat::mcset pl "Chess..." "Szachy..." ::msgcat::mcset pl "Games" "Gry planszowe" ::msgcat::mcset pl "Sound to play after opponent's turn" "Odtwórz dźwięk po ruchu przeciwnika" ::msgcat::mcset pl "%s wants play white." "%s chce grać białymi." ::msgcat::mcset pl "%s wants play black." "%s chce grać czarnymi." ::msgcat::mcset pl "Plugins options." "Ustawienia wtyczek." ::msgcat::mcset pl "\n\n Opponent rejected move:\n %s\n\n" "\n\n Przeciwnik odrzucił ruch:\n %s\n\n" tkabber-plugins-0.11.1/chess/msgs/es.msg0000644000175000017500000000750610712161173017405 0ustar sergeisergei::msgcat::mcset es " (Opponent)" " (Oponente)" ::msgcat::mcset es " (You)" " (Tu)" ::msgcat::mcset es "%s (%s) has refused chess invitation: %s" "%s (%s) Ha rechazado tu invitación de jugar al ajedrez: %s" ::msgcat::mcset es "%s wants play black." "%s quiere jugar con las negras." ::msgcat::mcset es "%s wants play white." "%s quiere jugar con las blancas." ::msgcat::mcset es "Accept opponent illegal moves (useful for debugging)." "Permitir movimientos ilegales del oponente (útil para depurar)." ::msgcat::mcset es "Accept the draw proposal" "Aceptar la propuesta de empate" ::msgcat::mcset es "Agree to play" "Aceptar la partida" ::msgcat::mcset es "Allow illegal moves (useful for debugging)." "Permitir movimientos ilegales (útil para depurar)." ::msgcat::mcset es "B" "B" ::msgcat::mcset es "Black" "Negras" ::msgcat::mcset es "Cancel invitation" "Cancelar invitación" ::msgcat::mcset es "Chess Invitation from %s" "Invitación de Ajedrez de %s" ::msgcat::mcset es "Chess Invitation" "Invitación de Ajedrez" ::msgcat::mcset es "Chess figures theme." "Tema de las figuras de ajedrez." ::msgcat::mcset es "Chess game invitation from %s (%s) is received." "Se ha recibido una invitación de %s (%s) para jugar al ajedrez." ::msgcat::mcset es "Chess plugin options." "Opciones del ajedrez." ::msgcat::mcset es "Chess with %s" "Ajedrez con %s" ::msgcat::mcset es "Chess..." "Ajedrez..." ::msgcat::mcset es "Draw (Opponent accepted)" "Empate (el oponente aceptó)" ::msgcat::mcset es "Draw (Stalemate)" "Empate (Tablas)" ::msgcat::mcset es "Draw (You accepted)" "Empate (Aceptaste)" ::msgcat::mcset es "Flip board view when playing black by default." "Voltear el tablero cuando se juega con negras." ::msgcat::mcset es "Flip view" "Voltear el tablero" ::msgcat::mcset es "Games" "Juegos" ::msgcat::mcset es "History" "Historial" ::msgcat::mcset es "I want play black" "Quiero jugar con las negras" ::msgcat::mcset es "I want play white" "Quiero jugar con las blancas" ::msgcat::mcset es "K" "K" ::msgcat::mcset es "Move: " "Movimiento: " ::msgcat::mcset es "N" "N" ::msgcat::mcset es "Opponent wins (Checkmate)" "El oponente gana (por jaque mate)" ::msgcat::mcset es "Opponent wins (You resigned)" "El oponente gana (te rendiste)" ::msgcat::mcset es "Pawn promotion" "Promoción del peón" ::msgcat::mcset es "Plugins options." "Opciones de plugins." ::msgcat::mcset es "Press button and make move if you want propose draw" "Pulsa el botón y haz un movimiento si quieres proponer un empate" ::msgcat::mcset es "Press button if you want accept the draw proposal" "Pulsa el botón si quieres aceptar la propuesta de empate" ::msgcat::mcset es "Press button if you want resign" "Pulsa el botón si quieres rendirte" ::msgcat::mcset es "Promote pawns always as queens." "Promover peones a reinas siempre." ::msgcat::mcset es "Propose a draw" "Proponer empate" ::msgcat::mcset es "Q" "Q" ::msgcat::mcset es "R" "R" ::msgcat::mcset es "Refuse to play" "Rechazar la partida" ::msgcat::mcset es "Resign the game" "Rendirte" ::msgcat::mcset es "Sending chess game invitation to %s (%s)" "Enviando invitación de ajedrez a %s (%s)" ::msgcat::mcset es "Show last move by default." "Mostrar el último movimiento por defecto." ::msgcat::mcset es "Show last move" "Mostrar el último movimiento" ::msgcat::mcset es "Show tooltips with short instructions." "Mostrar tooltips con pequeñas instrucciones." ::msgcat::mcset es "Sound to play after opponent's turn" "Sonido a reproducir cuando el oponente haya movido" ::msgcat::mcset es "White" "Blancas" ::msgcat::mcset es "You win (Checkmate)" "Tu ganas (por jaque mate)" ::msgcat::mcset es "You win (Opponent resigned)" "Tu ganas (el oponente se ha rendido)" ::msgcat::mcset es "\n\n Opponent proposes a draw\n\n" "\n\n El oponente propone un empate\n\n" ::msgcat::mcset es "\n\n Opponent rejected move:\n %s\n\n" "\n\n El oponente rechazó el movimiento:\n %s\n\n" tkabber-plugins-0.11.1/chess/msgs/ro.msg0000644000175000017500000000130507626634725017427 0ustar sergeisergei ::msgcat::mcset ro "Let's play chess, %s!" "Hai să jucăm şah, %s!" #::msgcat::mcset ru "Invite" "Invită" #::msgcat::mcset ru "Cancel" "Anulare!" ::msgcat::mcset ro "Opponent %s refuse our request: %s" "Oponentul %s a refuzat cererea noastră: %s" ::msgcat::mcset ro "%s want to play chess!" "%s vrea să joace şah!" ::msgcat::mcset ro "Play" "Joacă" ::msgcat::mcset ro "Chess with %s" "Şah cu %s" ::msgcat::mcset ro "Allow illegal moves" "Permite mutări ilegale" ::msgcat::mcset ro "Move: " "Mutare: " ::msgcat::mcset ro "History" "Istoric" ::msgcat::mcset ro "Pawn promotion" "Transformare pion" ::msgcat::mcset ro "Chess" "Şah" ::msgcat::mcset ro "White" "Alb" ::msgcat::mcset ro "Black" "Negru" tkabber-plugins-0.11.1/chess/msgs/ru.msg0000644000175000017500000001157011047022175017420 0ustar sergeisergei ::msgcat::mcset ru "Plugins options." "Параметры расширений." ::msgcat::mcset ru "Flip board view when playing black by default." "Разворачивать по умолчанию доску при игре чёрными." ::msgcat::mcset ru "Show last move by default." "По умолчанию показывать последний ход." ::msgcat::mcset ru " (You)" " (Вы)" ::msgcat::mcset ru " (Opponent)" " (Оппонент)" ::msgcat::mcset ru "Flip view" "Развернуть доску" ::msgcat::mcset ru "R" "Л" ::msgcat::mcset ru "N" "К" ::msgcat::mcset ru "B" "С" ::msgcat::mcset ru "Q" "Ф" ::msgcat::mcset ru "K" "Кр" ::msgcat::mcset ru "Chess plugin options." "Параметры расширения Шахматы." ::msgcat::mcset ru "Chess figures theme." "Тема шахматных фигур." ::msgcat::mcset ru "Promote pawns always as queens." "Всегда превращать проведённую пешку в ферзя." ::msgcat::mcset ru "Show tooltips with short instructions." "Показывать всплывающие подсказки к элементам интерфейса." ::msgcat::mcset ru "Allow illegal moves (useful for debugging)." "Разрешать неправильные ходы (используется при отладке)." ::msgcat::mcset ru "Accept opponent illegal moves (useful for debugging)." "Принимать неправильные ходы от оппонента (используется при отладке)." ::msgcat::mcset ru "Chess Invitation" "Приглашение сыграть в шахматы" ::msgcat::mcset ru "Sending chess game invitation to %s (%s)" "Посылаем приглашение сыграть в шахматы с %s (%s)" ::msgcat::mcset ru "I want play white" "Хочу играть белыми" ::msgcat::mcset ru "I want play black" "Хочу играть чёрными" ::msgcat::mcset ru "Cancel invitation" "Отменить приглашение" ::msgcat::mcset ru "%s (%s) has refused chess invitation: %s" "%s (%s) отказался играть в шахматы: %s" ::msgcat::mcset ru "Chess Invitation from %s" "Приглашение сыграть в шахматы с %s" ::msgcat::mcset ru "Chess game invitation from %s (%s) is received." "Получено приглашение сыграть в шахматы с %s (%s)" ::msgcat::mcset ru "%s wants play white." "%s хочет играть белыми" ::msgcat::mcset ru "%s wants play black." "%s хочет играть чёрными" ::msgcat::mcset ru "Agree to play" "Согласиться играть" ::msgcat::mcset ru "Refuse to play" "Отказаться играть" ::msgcat::mcset ru "Chess with %s" "Шахматы с %s" ::msgcat::mcset ru "Show last move" "Показывать последний ход" ::msgcat::mcset ru "Move: " "Ход: " ::msgcat::mcset ru "Propose a draw" "Предложить ничью" ::msgcat::mcset ru "Accept the draw proposal" "Принять предложенную ничью" ::msgcat::mcset ru "Resign the game" "Сдать партию" ::msgcat::mcset ru "History" "Запись партии" ::msgcat::mcset ru "Pawn promotion" "Превращение пешки" ::msgcat::mcset ru "Chess..." "Шахматы..." ::msgcat::mcset ru "White" "Белые" ::msgcat::mcset ru "Black" "Чёрные" ::msgcat::mcset ru "Opponent wins (Checkmate)" "Оппонент выиграл (Мат)" ::msgcat::mcset ru "You win (Checkmate)" "Вы выиграли (Мат)" ::msgcat::mcset ru "Opponent wins (You resigned)" "Оппонент выиграл (Вы сдались)" ::msgcat::mcset ru "You win (Opponent resigned)" "Вы выиграли (Оппонент сдался)" ::msgcat::mcset ru "Draw (Stalemate)" "Ничья (Пат)" ::msgcat::mcset ru "Draw (Repetition)" "Ничья (Повторение позиции)" ::msgcat::mcset ru "Draw (You accepted)" "Ничья (Вы приняли)" ::msgcat::mcset ru "Draw (Opponent accepted)" "Ничья (Оппонент принял)" ::msgcat::mcset ru "Press button and make move if you want propose draw" "Нажмите кнопку и сделайте ход, если хотите предложить ничью" ::msgcat::mcset ru "Press button if you want accept the draw proposal" "Нажмите кнопку, если хотите принять предложенную ничью" ::msgcat::mcset ru "Press button if you want resign" "Нажмите кнопку, если хотите сдаться" ::msgcat::mcset ru "\n\n Opponent proposes a draw\n\n" "\n\n Оппонент предлагает ничью\n\n" ::msgcat::mcset ru "\n\n Opponent rejected move:\n %s\n\n" "\n\n Оппонент отверг ход:\n %s\n\n" ::msgcat::mcset ru "Games" "Игры" ::msgcat::mcset ru "Sound to play after opponent's turn" "Звук, который проигрывается после хода оппонента" tkabber-plugins-0.11.1/chess/msgs/uk.msg0000644000175000017500000001137410543571750017423 0ustar sergeisergei ::msgcat::mcset uk "Plugins options." "Параметри плагінів." ::msgcat::mcset uk "Flip board view when playing black by default." "Розвертати дошку при грі чорними за замовчуванням." ::msgcat::mcset uk "Show last move by default." "Показувати останній хід за замовчуванням." ::msgcat::mcset uk " (You)" " (Ви)" ::msgcat::mcset uk " (Opponent)" " (Опонент)" ::msgcat::mcset uk "Flip view" "Розгорнути дошку" ::msgcat::mcset uk "R" "Т" ::msgcat::mcset uk "N" "К" ::msgcat::mcset uk "B" "С" ::msgcat::mcset uk "Q" "Ф" ::msgcat::mcset uk "K" "Кр" ::msgcat::mcset uk "Chess plugin options." "Параметри плагіна Шахи." ::msgcat::mcset uk "Chess figures theme." "Тема шахових фігур." ::msgcat::mcset uk "Promote pawns always as queens." "Завжди перетворювати проведений пішак у ферзя." ::msgcat::mcset uk "Show tooltips with short instructions." "Показувати спливаючі підказки до елементів інтерфейсу." ::msgcat::mcset uk "Allow illegal moves (useful for debugging)." "Дозволяти неправильні ходи (використовується при налагодженні)." ::msgcat::mcset uk "Accept opponent illegal moves (useful for debugging)." "Приймати неправильні ходи від опонента (використовується при налагодженні)." ::msgcat::mcset uk "Chess Invitation" "Запрошення зіграти в шахи" ::msgcat::mcset uk "Sending chess game invitation to %s (%s)" "Відсилається запрошення зіграти в шахи з %s (%s)" ::msgcat::mcset uk "I want play white" "Хочу грати білими" ::msgcat::mcset uk "I want play black" "Хочу грати чорними" ::msgcat::mcset uk "Cancel invitation" "Скасувати запрошення" ::msgcat::mcset uk "%s (%s) has refused chess invitation: %s" "%s (%s) відмовився грати в шахи: %s" ::msgcat::mcset uk "Chess Invitation from %s" "Запрошення зіграти в шахи з %s" ::msgcat::mcset uk "Chess game invitation from %s (%s) is received." "Отримано запрошення зіграти в шахи з %s (%s)" ::msgcat::mcset uk "%s wants play white." " %s хоче грати білими" ::msgcat::mcset uk "%s wants play black." " %s хоче грати чорними" ::msgcat::mcset uk "Agree to play" "Погодитися грати" ::msgcat::mcset uk "Refuse to play" "Відмовитися грати" ::msgcat::mcset uk "Chess with %s" "Шахи з %s" ::msgcat::mcset uk "Show last move" "Показувати останній хід" ::msgcat::mcset uk "Move: " "Хід: " ::msgcat::mcset uk "Propose a draw" "Запропонувати нічию" ::msgcat::mcset uk "Accept the draw proposal" "Прийняти запропоновану нічию" ::msgcat::mcset uk "Resign the game" "Здати партію" ::msgcat::mcset uk "History" "Запис партії" ::msgcat::mcset uk "Pawn promotion" "Перетворення пішака" ::msgcat::mcset uk "Chess..." "Шахи..." ::msgcat::mcset uk "White" "Білі" ::msgcat::mcset uk "Black" "Чорні" ::msgcat::mcset uk "Opponent wins (Checkmate)" "Опонент виграв (Мат)" ::msgcat::mcset uk "You win (Checkmate)" "Ви виграли (Мат)" ::msgcat::mcset uk "Opponent wins (You resigned)" "Опонент виграв (Ви здалися)" ::msgcat::mcset uk "You win (Opponent resigned)" "Ви виграли (Опонент здався)" ::msgcat::mcset uk "Draw (Stalemate)" "Нічия (Пат)" ::msgcat::mcset uk "Draw (You accepted)" "Нічия (Ви прийняли)" ::msgcat::mcset uk "Draw (Opponent accepted)" "Нічия (Опонент прийняв)" ::msgcat::mcset uk "Press button and make move if you want propose draw" "Натисніть кнопку й зробіть хід, якщо хочете запропонувати нічию" ::msgcat::mcset uk "Press button if you want accept the draw proposal" "Натисніть кнопку, якщо хочете прийняти запропоновану нічию" ::msgcat::mcset uk "Press button if you want resign" "Натисніть кнопку, якщо хочете здатися" ::msgcat::mcset uk "\n\n Opponent proposes a draw\n\n" "\n\n Опонент пропонує нічию\n\n" ::msgcat::mcset uk "\n\n Opponent rejected move:\n %s\n\n" "\n\n Опонент відкинув хід:\n %s\n\n" ::msgcat::mcset uk "Games" "Ігри" ::msgcat::mcset uk "Sound to play after opponent's turn" "Звук, який буде програватися після ходу опонента" tkabber-plugins-0.11.1/chess/msgs/nl.msg0000644000175000017500000000762510277726732017427 0ustar sergeisergei# Dutch messages file # Author: Sander Devrieze s.devrieze@pandora.be # Please notify me of errors or incoherencies. ::msgcat::mcset nl "Chess with %s" "Schaken met %s" ::msgcat::mcset nl "Move: " "Aan zet:" ::msgcat::mcset nl "History" "Geschiedenis" ::msgcat::mcset nl "Pawn promotion" "Promotie van pion" ::msgcat::mcset nl "White" "Wit" ::msgcat::mcset nl "Black" "Zwart" ::msgcat::mcset nl "K" "K" ::msgcat::mcset nl "Q" "Q" ::msgcat::mcset nl "R" "R" ::msgcat::mcset nl "B" "B" ::msgcat::mcset nl "N" "N" ::msgcat::mcset nl "Plugins options." "Pluginopties." ::msgcat::mcset nl "Chess plugin options." "Pluginopties voor schaken." ::msgcat::mcset nl "Chess figures theme." "Thema voor afbeeldingen van pionnen." ::msgcat::mcset nl "Flip board view when playing black by default." "Het speelbord standaard omkeren bij het spelen met zwart." ::msgcat::mcset nl "Show last move by default." "Laatste zet standaard laten zien." ::msgcat::mcset nl "Promote pawns always as queens." "Pionnen steeds promoveren tot koninginnen." ::msgcat::mcset nl "Show tooltips with short instructions." "Tekstballonnen met korte instructies laten zien." ::msgcat::mcset nl "Allow illegal moves (useful for debugging)." "Niet-toegelaten zetten toestaan (bruikbaar voor debuggen)." ::msgcat::mcset nl "Accept opponent illegal moves (useful for debugging)." "Niet-toegelaten zetten van tegenstander accepteren (bruikbaar voor debuggen)." ::msgcat::mcset nl "Chess Invitation" "Uitnodiging voor een schaakspel" ::msgcat::mcset nl "Sending chess game invitation to %s (%s)" "Bezig met verzenden van uitnodiging voor een schaakspel naar %s (%s)" ::msgcat::mcset nl "I want play white" "Ik wil met wit spelen" ::msgcat::mcset nl "I want play black" "Ik wil met zwart spelen" ::msgcat::mcset nl "Cancel invitation" "Uitnodiging annuleren" ::msgcat::mcset nl "%s (%s) has refused chess invitation: %s" "%s (%s) ging niet in op de uitnodiging om met hem te schaken: %s" ::msgcat::mcset nl "Chess Invitation from %s" "Uitnodiging voor een schaakspel met %s" ::msgcat::mcset nl "Chess game invitation from %s (%s) is received." "Uitnodiging voor een schaakspel met %s (%s) werd ontvangen." ::msgcat::mcset nl "%s wants play %s." "%s wil spelen met %s." ::msgcat::mcset nl "Agree to play" "Spelen" ::msgcat::mcset nl "Refuse to play" "Niet spelen" ::msgcat::mcset nl " (You)" "(Jij)" ::msgcat::mcset nl " (Opponent)" "(Tegenstander)" ::msgcat::mcset nl "You win (Opponent resigned)" "Jij hebt gewonnen (de tegenstander gaf het op)" ::msgcat::mcset nl "Draw (Opponent accepted)" "Gelijkspel (de tegenstander accepteerde de uitslag)" ::msgcat::mcset nl "Show last move" "Laatste zet laten zie" ::msgcat::mcset nl "Flip view" "Beeld omkeren" ::msgcat::mcset nl "Propose a draw" "Gelijkspel voorstellen" ::msgcat::mcset nl "Accept the draw proposal" "et voorstel voor gelijkspel accepteren" ::msgcat::mcset nl "Resign the game" "Geef het op" ::msgcat::mcset nl "Press button and make move if you want propose draw" "Druk op de knop en doe een zet als je gelijkspel wilt voorstellen" ::msgcat::mcset nl "Press button if you want accept the draw proposal" "Druk op de knop als je het voorstel voor gelijkspel wilt accepteren" ::msgcat::mcset nl "Press button if you want resign" "Druk op de knop als je wilt opgeven" ::msgcat::mcset nl "\n\n Opponent proposes a draw\n\n" "\n\n De tegenstander stelt een gelijkspel voor\n\n" ::msgcat::mcset nl "Draw (Stalemate)" "Gelijkspel (pat)" ::msgcat::mcset nl "You win (Checkmate)" "Jij hebt gewonnen (schaakmat)" ::msgcat::mcset nl "Opponent wins (Checkmate)" "De tegenstander heeft gewonnen (schaakmat)" ::msgcat::mcset nl "Draw (You accepted)" "Gelijkspel (jij accepteerde de uitslag)" ::msgcat::mcset nl "Opponent wins (You resigned)" "De tegenstander heeft gewonnen (jij gaf het op)" ::msgcat::mcset nl "\n\n Opponent rejected move:\n %s\n\n" "\n\n De tegenstander weigerde de zet:\n %s\n\n" ::msgcat::mcset nl "Games" "Spelletjes" ::msgcat::mcset nl "Chess..." "Schaken..." tkabber-plugins-0.11.1/chess/proto0000644000175000017500000000353610214663710016403 0ustar sergeisergeiRequest: 600 -- for all players 10 -- if on black side played Kasparov Positive response: or simply ? Move: queen 'pos' attribute contain column-separated list of coordinates of piece, that moved from first to last one. Coordinate is a comma-separated list of integers >= 0. Each turn can have few tags. Proposing draw: Accepting draw proposal: Resigning: Also we need and tags for games where we must put or remove pieces. can have 'type' and 'color' attributes. move, put & destroy tags can have some game-specific subtags Response: if move accepted, or error 'Not Allowed' if other side think that this move illegal (to avoid evil hackers that write clients that can do few moves instead of one or can move King like Queen) tkabber-plugins-0.11.1/chess/pixmaps/0000755000175000017500000000000011076120366016771 5ustar sergeisergeitkabber-plugins-0.11.1/chess/pixmaps/wooden/0000755000175000017500000000000011076120366020264 5ustar sergeisergeitkabber-plugins-0.11.1/chess/pixmaps/wooden/bn.gif0000644000175000017500000000135410501561725021355 0ustar sergeisergeiGIF89a11 @@ @ @` @@@@`@@ @ @@@@@ @@`@@ࠀ!,11$dihlp,tm@!P$ W t2HaBE@1tSbp@wTw59 l y ST  =3~ rzTuw ndv  slg2l  vzah09P{zw~{/T|{y}h. }lLB" uC `k 6FTW`32 F4dIFDSQ >}ܙv@-VhV>!PH@e:'ۚiL6k5`F@MX,Ɩ3p!Z4AQAkfNO+d*c2e:0f5U,+`3E=lPj1zDu`S;E(}  *V?U2A}^._Z3˗ƩP5S2{?e@k1WkH!0SeH ̧L|iԈ(! P^x{wp1} %.'Ǒ?ͱٓPFTViXf\;tkabber-plugins-0.11.1/chess/pixmaps/wooden/wp.gif0000644000175000017500000000066310501561725021406 0ustar sergeisergeiGIF89a11`@@``@`@@@!,11I8ͻ`(dihlp,W1=7B("(Q<찈z a˺8W Nt`Gw mnJ}~ BzdK}:Ebsg~X,2:3tNOx`78r(j_`r0gƒabtjmϧ o*[wՑ}8XLuň Rܡ&h\2[#?= ;DaY8'J&lfk-aIϟ1=b@@ɗ0;IW̬Vϟent82KU4:ސDXFŕTYAٳhRd¶۷pʝ!;tkabber-plugins-0.11.1/chess/pixmaps/wooden/wb.gif0000644000175000017500000000070210501561725021362 0ustar sergeisergeiGIF89a11 `@@@! ,11PI8ͻ`(di~@djʆ$hZ׎QrA@E̸P!M,P/0LU7 ]/wW{GrTrwdAg]j0T1{j]0J2IT0M*0Jd5}7qA,c3TT{QKmZpj}[9DopfdA.8XEGrp,(" cP%\5"^p2"[RG*(!Kg@lP&$d\eh&v $1DzP}ؑE"G!ngd~x!MF 9}1*蛇Y5mV*)/C-@dQVrx4D WZٜF iZ&;kU"9`LX(pǐ#KL;tkabber-plugins-0.11.1/chess/pixmaps/wooden/bp.gif0000644000175000017500000000077110471327266021367 0ustar sergeisergeiGIF89a11@ @ @` @@@@``@ @ @`@@@ @@@@@`@@ࠀ!,11`%dihlp,tmx|w 6ȅ$E@2d"@ d@& 9R] pdgvjD|nprtWiL nesgvwz{JVIZlJ[{AJiyM=P fUV:_ TI ɵƨC eWґb޸]"o]mdȾHcbq>pk2g }ɐPaoPWTl2 w,U[bZVzL.Y"Yaș)WnjS*]. aAV>pXiŦU&E,K 1@bIgpMqދVrͰ&LKu+^̸#B;tkabber-plugins-0.11.1/chess/pixmaps/wooden/wk.gif0000644000175000017500000000072610501561725021401 0ustar sergeisergeiGIF89a11@@@``@`@@@!,11I8ͻ`(diz@.,(I(<5͌Q3C$ dhXs"ZU`|gW8V; x  vx?@-)=8uw#n=t5)n +AeY9Km rR tRm hPɺP,* c۰j'Udj* Y. rGm dv:ԧ;z5_K{Ehc.m;xp&1H ạȒם{N@ ëEruҠR$*&;S4jypjLB'P& ץ2iKSÈ~Ƹǐ#Kf;tkabber-plugins-0.11.1/chess/pixmaps/wooden/bb.gif0000644000175000017500000000106410501561725021337 0ustar sergeisergeiGIF89a11@ @ @` @@@@``@ @ @`@@@ @@@@@`@@ࠀ!,11`%dihlp,tm@t,/h$ `-ߒ1@GM9 !.ɗD`COl L @vj oqPYJ?gwT b LQpp@ZA?ueBxYe"9A:@YZ:79 zPQCE`b¼:Zix  I;^@8@vbx -D geQG4 (y+ JY=l8viƱGCH 9GefuQ/Pc Lro U 1^r ySdO9pb :69VCöZ9 ~Z"~؁qX nXKWE9԰J/#0\fV8c7JM{4v׭ZHaGܚ,G Kq LlM)UigМ<+z3JvR&Jl*w)5HN:H 56#69XvIaƼ=KCĢ2YԀ,(jl9ӘJ>0D͖ [n9B: 7L;f>üs:$KN7B;tkabber-plugins-0.11.1/chess/pixmaps/wooden/bf.gif0000644000175000017500000000156510501561725021351 0ustar sergeisergeiGIF89a11 H=+E>4HA+MA,MB,OD6KC:TE7TI7ZK=YN8! ,113Ŕ]FAQ!n x&LՕqdj~ˠ CiCbtB. 3=BN 7B+A'(7ay@\V76!~2 (HR99 / jͺbi8*ä8n$/b8,0{ډ#ɟT{VXkA Bl:iΖ"P.@-"C$P "h6Ŋ Wܩ^pTγ5;$V &qpS?s|4:RPX( 8XLy@ٖf <2] jBN@Ήi8-(E$NAВ%X?Bjg : ;t4BȞ 2@duع:,m KndSfpULW67ŏ5j8*;I0܉vwK=Ig is=A-6-s…_sm%E^ C /ܘn+&!Г2Lc rH*UHS9/!`(5fX:Jmϳ46ҷ$iv医xFƷ߿ L";tkabber-plugins-0.11.1/chess/pixmaps/wooden/bk.gif0000644000175000017500000000110210501561725021341 0ustar sergeisergeiGIF89a11@ @ @` @@@@`@@``@ @ @@@`@@@ @@@@@`@@ࠀ!,11%dihlp,tm@߱3 ch"Eհ9Fq5V}[pa Gچ@P&c2 sw~LMHP09H  ;9k~N 4 z|E9Q‰WǞayؙ[ߌ<: vx50XO߻V}{ctD!qRR=9(.D!} f&4JJ ow]&_bYo1qz f(EGdk+oQy4 :-3_adl^hXmm4KuXqh : b|:vBД a> f¬ J|R'deת,PH'ݎpc!eBO @: G 9db`!( y:]{&bƬA} 8ϐ4Fx nP Nh !1Q`Z5ճIRJ7b*OP5.@\'2*,5AKŜCĠhGmX"D%eR@lP\7I]O)3FqEzH@]̆=KegOU .QRMa DvNʱm_oBaȽ{c6euo`\jI.)3:P{9%G'}mp_bV cX/`.N!xN%TA{d`/!wxBIdBC!`3j ?搉̩cBG:4;ődvY*29dT"NVMS#x(epDiֳ`/ZQVd%IcP@e%|lݶeAIr@;tkabber-plugins-0.11.1/chess/pixmaps/wooden/br.gif0000644000175000017500000000105410501561725021356 0ustar sergeisergeiGIF89a11 @@ @ @` @@@@`@@ @ @@@@@ @@`@@ࠀ!,11$dihlp,tmx:0 ƀ;.W``8qA~ kv{3za, V[\x_sOd]yzl6~  ePPj5]tRaX4~z3 eOE Q?S?; ]~ ̝OKvv><>~_Q"a/Z1xT>=xt (VDU(:7O<7GJ$JzA  c,I<\鼲c HM BTcҦB-feuee+R˶)VpcՕDN-=Q-UjGxIvd%@zs*V/YZ6'󑭤Ɓ\Y,+ FCb˞6۸sͻ;tkabber-plugins-0.11.1/chess/pixmaps/wooden/icondef.xml0000644000175000017500000000330210366754433022424 0ustar sergeisergei Wooden 1.0 Chess Wooden Theme. 2006-01-23 chess/bb bb.gif chess/bf bf.gif chess/bk bk.gif chess/bn bn.gif chess/bp bp.gif chess/bq bq.gif chess/br br.gif chess/wb wb.gif chess/wf wf.gif chess/wk wk.gif chess/wn wn.gif chess/wp wp.gif chess/wq wq.gif chess/wr wr.gif tkabber-plugins-0.11.1/chess/pixmaps/xboard/0000755000175000017500000000000011076120366020250 5ustar sergeisergeitkabber-plugins-0.11.1/chess/pixmaps/xboard/bn.gif0000644000175000017500000000034010471327266021341 0ustar sergeisergeiGIF89a11 !,11ڋޜ|G9Fi Mײhg>z@KGTѲldvfM*\:ܩڃ_NRDŽ58ƒ'"IYfe)WhsYWhs* R%;UdTk;+ [++\Q;tkabber-plugins-0.11.1/chess/pixmaps/xboard/wp.gif0000644000175000017500000000024510501561725021366 0ustar sergeisergeiGIF89a11!,11vڋޜuHZ /] tz!L6iTI=.-׀+ T'-}9cw_(X'Wq()9Q;tkabber-plugins-0.11.1/chess/pixmaps/xboard/wb.gif0000644000175000017500000000026610471327266021361 0ustar sergeisergeiGIF89a11!,11ڋo݅zU%J)7s[+#v/6Wɨ\~ #(WK<&:jZڭ(9ؖw9=]U3wW $H'#h Shƨ*:JP;tkabber-plugins-0.11.1/chess/pixmaps/xboard/wn.gif0000644000175000017500000000034010471327266021366 0ustar sergeisergeiGIF89a11!,11ڋޜ|G9Fi Mײhg>z@KGTѲldvfM*\:ܩڃ_NRDŽ58ƒ'"IYfe)WhsYWhs* R%;UdTk;+ [++\Q;tkabber-plugins-0.11.1/chess/pixmaps/xboard/wq.gif0000644000175000017500000000040210471327266021370 0ustar sergeisergeiGIF89a11!,11Ӕڋ[y|\u"()ªqis(KALlNR;tkabber-plugins-0.11.1/chess/pixmaps/xboard/bp.gif0000644000175000017500000000024510501561725021341 0ustar sergeisergeiGIF89a11 !,11vڋޜuHZ /] tz!L6iTI=.-׀+ T'-}9cw_(X'Wq()9Q;tkabber-plugins-0.11.1/chess/pixmaps/xboard/wk.gif0000644000175000017500000000036310501561725021362 0ustar sergeisergeiGIF89a11!,11Ĕڋa{}X@xfaj,r3q׋Y~:3AI|NR;tkabber-plugins-0.11.1/chess/pixmaps/xboard/bf.gif0000644000175000017500000000013310471327266021331 0ustar sergeisergeiGIF89a11wm!,112ڋ޼H扦ʶ L Ģ;tkabber-plugins-0.11.1/chess/pixmaps/xboard/wr.gif0000644000175000017500000000026210501561725021367 0ustar sergeisergeiGIF89a11!,11ڋI$F޹hj- _OӉ8*!9:[0DMٳjb-7}BbWc eխŪWݜ6 g$('Hq4hɒHɨ P;tkabber-plugins-0.11.1/chess/pixmaps/xboard/bk.gif0000644000175000017500000000036310501561725021335 0ustar sergeisergeiGIF89a11 !,11Ĕڋa{}X@xfaj,r3q׋Y~:3AI| Xboard 1.0 Chess Xboard Theme. 2006-01-23 chess/bb bb.gif chess/bf bf.gif chess/bk bk.gif chess/bn bn.gif chess/bp bp.gif chess/bq bq.gif chess/br br.gif chess/wb wb.gif chess/wf wf.gif chess/wk wk.gif chess/wn wn.gif chess/wp wp.gif chess/wq wq.gif chess/wr wr.gif tkabber-plugins-0.11.1/chess/pixmaps/classic/0000755000175000017500000000000011076120366020412 5ustar sergeisergeitkabber-plugins-0.11.1/chess/pixmaps/classic/bn.gif0000644000175000017500000000100610471327266021503 0ustar sergeisergeiGIF89a00$$D$D$DDD$D$DDDDDdDdDDddDdddd!,00 %dihlp,tm]Sޤˆáhl8"P.Wl)yF-S,:SG|(`t]-Kgxh*浥^!DxpO&G(Hn"L"0k/i^ a}#K̦˘3k&;tkabber-plugins-0.11.1/chess/pixmaps/classic/wp.gif0000644000175000017500000000073210501561725021531 0ustar sergeisergeiGIF89a00$$D$DDD$D$DDDDDdDddDdddĤĤ!,00`%dihlp,tmx|%pD #R$Q` 4"SH$[Z#$0>J#,H"hCxlRd=[ w {ax ;y ~:y?O vi` a  Q {ZQ֨Z[ ġӇ[ i MOs hkW9OWwk kш E 0J5F'cCԀƓVX8]tրA*_맦f͑d \"<*賜/KؒW_FX`eVc0sYkbǂ\VpʝKH;tkabber-plugins-0.11.1/chess/pixmaps/classic/wb.gif0000644000175000017500000000077110501561725021516 0ustar sergeisergeiGIF89a00$$DD$D$DDDDDdDdDDddDdddĤ!,00$dihlp,tm*I9-^[,CWqw&UHdH mwx<aq)"4 nZ=Ni;v z{@Ovo;sCvo;{~ q{ 7? R 5?2?­İDƛ /? ٙ ᮤF`1yƮ(h@WJ MD%(%L (*w <@AU(p[ 8' @]Kf̔a0 PJ#AATDXK}t "; lyp@WnrU["? !8p18Y̸4B;tkabber-plugins-0.11.1/chess/pixmaps/classic/wn.gif0000644000175000017500000000110610501561725021523 0ustar sergeisergeiGIF89a00$$D$DD$DDDDDdDddDddddĤ!,00%dihlp,tm]U^ˆAhlk(eZQrB<SwD.e㱀VA`'r wF=eC~[V=eqK;PC|jsd3Dd[t ɍöS.D Ĺ/=ӌtSNPrsi At PP@8P|4RJ!.PuPDIyXX@E"Ğ\+\ТCD  Ih@"l3t4Y):o(psNJ(djզFŁTTN (mA]bzSrUQ!k#L'I@gpTI kԻ dX Nx8HAXmyr;R]qh۸sf6.Nٴ)_|УKN}M;tkabber-plugins-0.11.1/chess/pixmaps/classic/wq.gif0000644000175000017500000000113010501561725021523 0ustar sergeisergeiGIF89a00$$D$D$DDD$DDDDdDddDddĤ!,00$dihlp,tmHK0дS~#Ij~QQtb,o SCP4q{8kcN5_ @x/VZ d:jO~Z `lIBfLoR PJ?#q w%zqQe{)_s?ӵY,eiRiQ~*T i}š IaAI/.~ Z/@~9O@Dv{ր4H2:C;*!X2. h9sMiH;5JD(I([~ñ+0F4i=&J@wMޠn*@x*JP "FF@e̺-H`Sf\VF 6[jR„=ӵc2l,Xns1uҹqËO~|;tkabber-plugins-0.11.1/chess/pixmaps/classic/bp.gif0000644000175000017500000000064110501561725021503 0ustar sergeisergeiGIF89a00$$D$DDD$D$DDDDDdDdDDddDddĤ!,00$dihlp,tmx|pD !ȤH 4ЀDgʍ Emk0 _1 'nC iW{;}m s|vPotxqv[v qLm q=ctV]XNlq8NReRȲQ pP3u،ڔ2e /bג y6NwЋ e2bY2IAN2ȋN4!&΍* }۵1Z%ynWM*ryb͛8s³ϟ@;tkabber-plugins-0.11.1/chess/pixmaps/classic/wk.gif0000644000175000017500000000111410501561725021517 0ustar sergeisergeiGIF89a00$$D$D$DDD$D$DDDDddDddĤ!,00`%dihlp,tmx˔@s"+(l:0bb%` ǁ}AdY'vsWggx3 cs Mjv1Ai B H0ii t_Un-hsn˃̺xo Qo}onl]oBA-t'`/σL5f$p HT 6„ʖ5LHmo%3< ܨbS9HXj6'URi@@LpUӜ_F %0rPP0 pd@䎽9cGu0Ijeap0)ÕgHȁιn^ofAt2:X1ꞹ,NgVQ]@*J^س;tkabber-plugins-0.11.1/chess/pixmaps/classic/bb.gif0000644000175000017500000000074710501561725021474 0ustar sergeisergeiGIF89a00$$D$D$DDD$D$DDDDDdDdDDddDddd!,00$dihlp,tm*I9H/ aK4:<)8@,fŪmQD`n&" Om>Ӂzsh=~TT{gR~[fTl6Zms@Vzo8ZMVfUF3t T|M G0@  [/Z VV aVF Х7~  9?V˶ Ųz  9(XP)3J!X N4 /E 2e(:kS APCU;rh@@uM3Rhdk.Z;) *%ڈ5NӚ؀%?wA'B˷߿=B;tkabber-plugins-0.11.1/chess/pixmaps/classic/bq.gif0000644000175000017500000000114710501561725021506 0ustar sergeisergeiGIF89a00$$D$D$DDD$D$DDDDDdDdDDddDdddd!,00`%dihlp,tmJL@J.¡i${6+Pzr+C5~ibLFo%A)]>& co#@MDIJij+9X# ȤKZyQDIT yR@! Ȥ-685hOJe$ 삓 xVjۇ@8kcغ>K`m><oa`_$[nͥ}#H9pQJд2 0n;Q#li6LlrpZ=A 3s+nA7@`y(ӣ̾+ ;tkabber-plugins-0.11.1/chess/pixmaps/classic/bf.gif0000644000175000017500000000156510501561725021477 0ustar sergeisergeiGIF89a11 sQ1sY1{U1{Y1kUBsYJ{YBYBaBaJiB! ,11А" mAQ!Hn x&HLՕqdj~ˠ CiCbtB. 3=BN 7B+A'(7ay@\V76!~2 (HR99 / jͺbi8*ä8n$/b8,0{ډ#ɟT{VXkA Bl:iΖ"P.@-"C$P "h6Ŋ Wܩ垁pTγ5;$f &q pS?s|4:RMPX( 8XLy@ٖf <2] jBN@Ήi8-(EAВ%X?Bjg : ;t4BȞ "@duع:,m KndSFpULW67ŏ5j8*;I0܉vwK=Ig ism|DZ<L ;畀pכH&׏\d 1gt|!J8(kj@BcYM3b >]\ZˉMh-PM H%ɢa$LKMY y) ɝ+ر]r[c:(5$a .X`1uP&7̹ϠCM;tkabber-plugins-0.11.1/chess/pixmaps/classic/bk.gif0000644000175000017500000000110610501561725021473 0ustar sergeisergeiGIF89a00$$D$D$DDD$D$DDDDDdDdDDddDdddd!,00 &dihlp,tmx׵˗@s"+(l:0 ) `؂Kq0+/Kϗn -<RpWRBX/L jBcB Rn/Bm_j  +c¼M M   )A  BF֫M- KQ9 Q (IwEw@ؾJܓXII25 z t2p![jX9j'lشB`~!BLt#qZdžh)KM^j"ՏRVY@A&bި7zm! /fIPA"+|{ k›H\59\ Jq~fp^a(׼l'D1 0@8Fs+ç93УKN]E;tkabber-plugins-0.11.1/chess/pixmaps/classic/wf.gif0000644000175000017500000000147210501561725021521 0ustar sergeisergeiGIF89a11 ֢{ޮ{s{s֦ޮ޲޶綄羌! ,1103Р#>r(4I!pi'ci*%IhD q R=9(.Df!} f&4JJ ow]&_bYo1qz f(EGdk+oQy4 :-3_adl^hXmm4KuXqh : b|:vBД a> f¬ J|R'deת,PH'ݎpc!eBO @: G)9db`!( y:]{&bƬA} 8ϐ4Fx nP Nh !1Q`Z5ճIRJ7b*OP5@\'2*,5AKŜCĠhGmX"D%eR@lP\7I]O)3FqEzH@]̆=KegOU .QRMa DvNʱm_oBaȽ{c6euo`\jI.)3:P{9%G'}mp_bV cX/`.N!xN%TA{d`/!wxBIdBC!`3j ?搉̩cBG:4;ődvY*29dT"NVMS#x(epDiֳ`/ZVd%Ic@e%|lݶeAI2@;tkabber-plugins-0.11.1/chess/pixmaps/classic/br.gif0000644000175000017500000000076310501561725021512 0ustar sergeisergeiGIF89a00$$D$D$DDD$D$DDDDDdDdDDddDdddd!,00 %dihlp,tmx|N p,NA$7QqBӪuy@Ń Dp@XPwEV`zn}sOvag\6^j5e_OP6q=uL~ b|>^ajv gcºΡx֘q˂ ՓɆP` ~7qaFrgXf fe H 8c$:xq8B8;ń'LT*gu 0$/r4P,^zϝM_A8'{8""bF h+e]FÈ+~;tkabber-plugins-0.11.1/chess/pixmaps/classic/icondef.xml0000644000175000017500000000330410366754433022554 0ustar sergeisergei Classic 1.0 Chess Classic Theme. 2006-01-23 chess/bb bb.gif chess/bf bf.gif chess/bk bk.gif chess/bn bn.gif chess/bp bp.gif chess/bq bq.gif chess/br br.gif chess/wb wb.gif chess/wf wf.gif chess/wk wk.gif chess/wn wn.gif chess/wp wp.gif chess/wq wq.gif chess/wr wr.gif tkabber-plugins-0.11.1/chess/chess.tcl0000644000175000017500000013463711047072350017134 0ustar sergeisergei# $Id: chess.tcl 1486 2008-08-08 16:31:36Z sergei $ package require msgcat namespace eval chess { set scriptdir [file dirname [info script]] ::msgcat::mcload [file join $scriptdir msgs] variable square_size 48 variable line_width 1 array set piece_name [list \ wk [::msgcat::mc "K"] \ wq [::msgcat::mc "Q"] \ wr [::msgcat::mc "R"] \ wb [::msgcat::mc "B"] \ wn [::msgcat::mc "N"] \ wp {} \ bk [::msgcat::mc "K"] \ bq [::msgcat::mc "Q"] \ br [::msgcat::mc "R"] \ bb [::msgcat::mc "B"] \ bn [::msgcat::mc "N"] \ bp {}] array set prom_name [list q queen r rook b bishop n knight] array set prom_rev [list queen q rook r bishop b knight n] variable themes set dirs [glob -nocomplain -directory [file join $scriptdir pixmaps] *] foreach dir $dirs { pixmaps::load_theme_name [namespace current]::themes $dir } set values {} foreach theme [lsort [array names themes]] { lappend values $theme $theme } custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber custom::defgroup Chess [::msgcat::mc "Chess plugin options."] -group Plugins custom::defvar options(theme) Classic \ [::msgcat::mc "Chess figures theme."] -group Chess \ -type options -values $values \ -command [namespace current]::load_stored_theme custom::defvar options(flip_black_view) 1 \ [::msgcat::mc "Flip board view when playing black by default."] \ -type boolean -group Chess custom::defvar options(show_last_move) 0 \ [::msgcat::mc "Show last move by default."] \ -type boolean -group Chess custom::defvar options(always_queen) 0 \ [::msgcat::mc "Promote pawns always as queens."] \ -type boolean -group Chess custom::defvar options(show_tooltips) 1 \ [::msgcat::mc "Show tooltips with short instructions."] \ -type boolean -group Chess \ -command [list [namespace current]::set_tooltips] custom::defvar options(sound) "" \ [::msgcat::mc "Sound to play after opponent's turn"] \ -type file -group Chess custom::defvar options(allow_illegal) 0 \ [::msgcat::mc "Allow illegal moves (useful for debugging)."] \ -type boolean -group Chess custom::defvar options(accept_illegal) 0 \ [::msgcat::mc "Accept opponent illegal moves (useful for debugging)."] \ -type boolean -group Chess } proc chess::load_stored_theme {args} { variable options variable themes pixmaps::load_dir $themes($options(theme)) } hook::add postload_hook [namespace current]::chess::load_stored_theme 70 proc chess::get_nick {connid jid type} { if {[catch {chat::get_nick $connid $jid $type} nick]} { return [chat::get_nick $jid $type] } else { return $nick } } proc chess::invite_dialog {connid jid} { set w .chess_invite if {[winfo exists $w]} { destroy $w } Dialog $w -title [::msgcat::mc "Chess Invitation"] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] message $wf.message -aspect 50000 \ -text [format [::msgcat::mc "Sending chess game invitation to %s (%s)"] \ [get_nick $connid $jid chat] \ $jid] pack $wf.message -pady 2m $w add -text [::msgcat::mc "I want play white"] \ -command [list [namespace current]::invite $connid $jid white] $w add -text [::msgcat::mc "I want play black"] \ -command [list [namespace current]::invite $connid $jid black] $w add -text [::msgcat::mc "Cancel invitation"] \ -command [list destroy $w] $w draw } proc chess::invite {connid jid color} { destroy .chess_invite set id chess[rand 1000000000] # FIX #set rjid [get_jid_of_user $jid] jlib::send_iq set \ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type chess id $id color $color]] \ -to $jid \ -command [list [namespace current]::invite_res $connid $jid $id $color] \ -connection $connid } proc chess::invite_res {connid jid id color res child} { if {![cequal $res OK]} { after idle [list NonmodalMessageDlg .chess_invite_error -aspect 50000 -icon error \ -message [format [::msgcat::mc "%s (%s) has refused chess invitation: %s"] \ [get_nick $connid $jid chat] \ $jid [error_to_string $child]]] return "" } start_play $connid $jid $id $color } proc chess::invited_dialog {connid jid id color} { variable invited_result set w .chess_invited if {[winfo exists $w]} { destroy $w } Dialog $w -title [format [::msgcat::mc "Chess Invitation from %s"] $jid] \ -modal none -separator 1 -anchor e -default 0 set wf [$w getframe] bind $wf [list [namespace current]::set_invited_res ""] set nick [get_nick $connid $jid chat] set message1 [format [::msgcat::mc "Chess game invitation from %s (%s) is received."] \ $nick $jid] switch -- $color { white { set message2 [format [::msgcat::mc "%s wants play white."] $nick] } black { set message2 [format [::msgcat::mc "%s wants play black."] $nick] } default { return [list error modify bad-request] } } message $wf.message1 -aspect 50000 -text $message1 message $wf.message2 -aspect 50000 -text $message2 pack $wf.message1 -pady 1m pack $wf.message2 -pady 1m $w add -text [::msgcat::mc "Agree to play"] \ -command [list [namespace current]::set_invited_res 0] $w add -text [::msgcat::mc "Refuse to play"] \ -command [list [namespace current]::set_invited_res 1] $w draw vwait [namespace current]::invited_result catch { bind $wf {} destroy $w } if {$invited_result == 0} { switch -- $color { white { start_play $connid $jid $id black } black { start_play $connid $jid $id white } default { return [list error modify bad-request] } } return [list result\ [jlib::wrapper:createtag create \ -vars [list xmlns games:board type chess id $id]]] } else { return [list error modify not-acceptable] } } proc chess::set_invited_res {res} { variable invited_result set invited_result $res } proc chess::start_play {connid jid id color} { set gid [make_gid $jid $id] variable $gid variable options upvar 0 $gid flags set flags(window) [win_id chess $gid] set flags(connid) $connid set flags(opponent) $jid set flags(id) $id set flags(flip) 0 set flags(our_color) $color trace variable [namespace current]::${gid}(position,turn) w \ [list [namespace current]::set_label_move $gid] make_default_position $gid open $gid } proc chess::set_label_move {gid args} { variable $gid upvar 0 $gid flags switch -- $flags(position,turn) { white { set flags(move_label) [::msgcat::mc "White"] set move 1 } black { set flags(move_label) [::msgcat::mc "Black"] set move 1 } default { set move 0 } } if {$move && [is_my_move $gid]} { append flags(move_label) [::msgcat::mc " (You)"] } else { append flags(move_label) [::msgcat::mc " (Opponent)"] } } proc chess::make_default_position {gid} { variable $gid upvar 0 $gid flags for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set flags(position,$c,$r) "" } } for {set c 0} {$c < 8} {incr c} { set flags(position,$c,1) wp set flags(position,$c,6) bp } set c 0 foreach f {r n b q k b n r} { set flags(position,$c,0) w$f set flags(position,$c,7) b$f incr c } set flags(position,wk,c) 4 set flags(position,wk,r) 0 set flags(position,bk,c) 4 set flags(position,bk,r) 7 set flags(position,wk,kcastling) 1 set flags(position,wk,qcastling) 1 set flags(position,bk,kcastling) 1 set flags(position,bk,qcastling) 1 set flags(position,enpassant) {} set flags(position,turn) white catch {unset flags(position,last_move)} set flags(position,draw) 0 set flags(position,halfmove) 0 set flags(position,history) {} set flags(position,repetitions) [list [code_position $gid] 1] } proc chess::save_position {gid} { variable $gid upvar 0 $gid flags set flags(saved_position) [array get flags position,*] } proc chess::restore_position {gid} { variable $gid upvar 0 $gid flags array set flags $flags(saved_position) draw_position $gid unhighlight_legal_moves $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc chess::code_position {gid} { variable $gid upvar 0 $gid flags set code "" for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { switch -- $flags(position,$c,$r) { wk {append code K} wq {append code Q} wr {append code R} wb {append code B} wn {append code N} wp {append code P} bk {append code k} bq {append code q} br {append code r} bb {append code b} bn {append code n} bp {append code p} default {append code .} } } } append code $flags(position,wk,kcastling) append code $flags(position,wk,qcastling) append code $flags(position,bk,kcastling) append code $flags(position,bk,qcastling) if {[llength $flags(position,enpassant)] > 0} { lassign $flags(position,enpassant) c r set cp1 [expr {$c + 1}] set cm1 [expr {$c - 1}] if {$r == 2} { if {($cp1 < 8 && $flags(position,$cp1,3) == "bp") || \ ($cm1 >= 0 && $flags(position,$cm1,3) == "bp")} { append code $c$r } } elseif {$r == 5} { if {($cp1 < 8 && $flags(position,$cp1,4) == "wp") || \ ($cm1 >= 0 && $flags(position,$cm1,4) == "wp")} { append code $c$r } } } return $code } proc chess::make_gid {jid id} { jid_to_tag [concat $jid $id] } proc chess::turn_recv {gid childs} { variable options variable prom_rev variable $gid upvar 0 $gid flags set move 0 set draw 0 foreach child $childs { jlib::wrapper:splitxml $child tag vars isempty chdata children switch -- $tag { move { set pos [jlib::wrapper:getattr $vars pos] set poss [split $pos ";"] if {[llength $poss] == 2} { set pos1 [split [lindex $poss 0] ,] set pos2 [split [lindex $poss 1] ,] if {[llength $pos1] == 2 && [llength $pos2] == 2} { set cf [lindex $pos1 0] set rf [lindex $pos1 1] set ct [lindex $pos2 0] set rt [lindex $pos2 1] set prom "" foreach child2 $children { jlib::wrapper:splitxml $child2 tag2 vars2 isempty2 chdata2 children2 if {$tag2 == "promotion"} { if {[info exists prom_rev($chdata2)]} { set prom $prom_rev($chdata2) } } } set move 1 if {$options(sound) != "" && ![::sound::is_mute]} { ::sound::play $options(sound) } } } } resign { end_game $gid 1 [::msgcat::mc "You win (Opponent resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type chess \ id $flags(id)]]] } accept { if {$flags(position,draw)} { end_game $gid 0.5 [::msgcat::mc "Draw (Opponent accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type chess \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } draw { set draw 1 } } } if {$move && [do_move $gid $cf $rf $ct $rt $prom $draw]} { update_controls $gid $draw draw_position $gid highlight_last_move $gid return [list result [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type chess \ id $flags(id)]]] } else { return [list error modify not-acceptable] } } ############################################################################### proc chess::calc_moves {} { variable moves for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { for {set moves(d1,$c,$r) {}; set x [expr {$c+1}]; set y [expr {$r+1}]} \ {($x < 8) && ($y < 8)} {incr x; incr y} { lappend moves(d1,$c,$r) $x $y } for {set moves(d2,$c,$r) {}; set x [expr {$c-1}]; set y [expr {$r+1}]} \ {($x >= 0) && ($y < 8)} {incr x -1; incr y} { lappend moves(d2,$c,$r) $x $y } for {set moves(d3,$c,$r) {}; set x [expr {$c-1}]; set y [expr {$r-1}]} \ {($x >= 0) && ($y >= 0)} {incr x -1; incr y -1} { lappend moves(d3,$c,$r) $x $y } for {set moves(d4,$c,$r) {}; set x [expr {$c+1}]; set y [expr {$r-1}]} \ {($x < 8) && ($y >= 0)} {incr x; incr y -1} { lappend moves(d4,$c,$r) $x $y } for {set moves(h1,$c,$r) {}; set x [expr {$c+1}]} {$x < 8} {incr x} { lappend moves(h1,$c,$r) $x $r } for {set moves(h2,$c,$r) {}; set x [expr {$c-1}]} {$x >= 0} {incr x -1} { lappend moves(h2,$c,$r) $x $r } for {set moves(v1,$c,$r) {}; set y [expr {$r+1}]} {$y < 8} {incr y} { lappend moves(v1,$c,$r) $c $y } for {set moves(v2,$c,$r) {}; set y [expr {$r-1}]} {$y >= 0} {incr y -1} { lappend moves(v2,$c,$r) $c $y } set moves(n,$c,$r) {} foreach {dx dy} {1 2 -1 2 -2 1 -2 -1 -1 -2 1 -2 2 -1 2 1} { set x [expr {$c + $dx}] set y [expr {$r + $dy}] if {($x >= 0) && ($x < 8) && ($y >= 0) && ($y < 8)} { lappend moves(n,$c,$r) $x $y } } set moves(wpt,$c,$r) {} if {$r <= 6} { if {$c <= 6} { lappend moves(wpt,$c,$r) [expr {$c + 1}] [expr {$r + 1}] } if {$c >= 1} { lappend moves(wpt,$c,$r) [expr {$c - 1}] [expr {$r + 1}] } } set moves(bpt,$c,$r) {} if {$r >= 1} { if {$c <= 6} { lappend moves(bpt,$c,$r) [expr {$c + 1}] [expr {$r - 1}] } if {$c >= 1} { lappend moves(bpt,$c,$r) [expr {$c - 1}] [expr {$r - 1}] } } set moves(k,$c,$r) {} foreach {dx dy} {0 1 -1 1 -1 0 -1 -1 0 -1 1 -1 1 0 1 1} { set x [expr {$c + $dx}] set y [expr {$r + $dy}] if {($x >= 0) && ($x < 8) && ($y >= 0) && ($y < 8)} { lappend moves(k,$c,$r) $x $y } } } } } hook::add finload_hook [namespace current]::chess::calc_moves 100 proc chess::center {c r} { variable square_size variable line_width set r [expr {7 - $r}] list [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $c)}] \ [expr {$line_width + ($square_size * 0.5) + \ (($square_size + $line_width) * $r)}] } proc chess::close {gid} { variable $gid upvar 0 $gid flags array unset flags } proc chess::exists {gid} { variable $gid info exists $gid } proc chess::open {gid} { variable options variable square_size variable line_width variable piece_name variable $gid upvar 0 $gid flags set jid $flags(opponent) set w $flags(window) if {[winfo exists $w]} { raise_win $w return } set title [format [::msgcat::mc "Chess with %s"] [get_nick $flags(connid) $jid chat]] add_win $w -title $title \ -tabtitle $title \ -class Chess \ -raise 1 set board [canvas $w.board \ -width [expr {($square_size + $line_width) * 8}] \ -height [expr {($square_size + $line_width) * 8}]] pack $board -side left -anchor w -padx 10 set flags(board) $board set flags(show_last_move) $options(show_last_move) set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] set slm [Button $w.show_last_move -text [::msgcat::mc "Show last move"] \ -relief $relief \ -command [list [namespace current]::toggle_show_last_move $gid]] pack $slm -side top -anchor w -fill x set flags(show_last_move_button) $slm set flags(flip) 0 set slm [Button $w.flip -text [::msgcat::mc "Flip view"] \ -relief raised \ -command [list [namespace current]::toggle_flip_view $gid]] pack $slm -side top -anchor w -fill x set flags(flip_button) $slm frame $w.move pack $w.move -side top -anchor w label $w.move.title -text [::msgcat::mc "Move: "] pack $w.move.title -side left label $w.move.on_move -anchor w \ -textvariable [namespace current]::${gid}(move_label) pack $w.move.on_move -side left -anchor w set bbox [ButtonBox $w.bbox -orient vertical -spacing 0] $bbox add -text [::msgcat::mc "Propose a draw"] \ -command [list [namespace current]::toggle_draw $gid] $bbox add -text [::msgcat::mc "Accept the draw proposal"] \ -state disabled \ -command [list [namespace current]::accept_draw $gid] $bbox add -text [::msgcat::mc "Resign the game"] \ -command [list [namespace current]::send_resign $gid] grid columnconfigure $bbox 0 -weight 1 pack $bbox -side bottom -anchor w -fill x set flags(bbox) $bbox set_tooltips #label $w.history -text [::msgcat::mc "History"] #pack $w.history -side top -anchor w set hsw [ScrolledWindow $w.hsw] pack $hsw -side top -fill x -expand yes set ht [text $w.text -wrap word -height 60 -state disabled] set font [$ht cget -font] set tabstop1 [font measure $font "99.."] set tabstop2 [font measure $font "99..Qa8-a8+= "] $ht configure -tabs "$tabstop1 $tabstop2" $ht tag configure attention -foreground [option get $ht errorForeground Text] $hsw setwidget $ht set flags(hw) $ht set dsq_color #77a26d set lsq_color #c8c365 for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { set x1 [expr {$line_width + (($square_size + $line_width) * $c)}] set x2 [expr {($square_size + $line_width) * ($c + 1)}] set y1 [expr {$line_width + (($square_size + $line_width) * $r)}] set y2 [expr {($square_size + $line_width) * ($r + 1)}] set color [expr {($c+$r) % 2 ? $dsq_color : $lsq_color}] set img [expr {($c+$r) % 2 ? "bf" : "wf"}] $board create image $x1 $y1 -image chess/$img -anchor nw \ -tags [list background [list cr $c [expr {7-$r}]]] $board create rectangle $x1 $y1 $x2 $y2 \ -outline {} \ -tags [list square [list cr $c [expr {7-$r}]]] } } $board bind figure <1> \ [list [namespace current]::start_drag_figure $gid %x %y] $board bind figure \ [list [namespace current]::drag_figure $gid %x %y] $board bind figure \ [list [namespace current]::drag_end $gid %x %y] bind $w [list [namespace current]::close $gid] if {[is_black $flags(our_color)] && $options(flip_black_view)} { toggle_flip_view $gid } draw_position $gid update_controls $gid find_legal_moves $gid $flags(position,turn) } proc chess::toggle_flip_view {gid} { variable $gid upvar 0 $gid flags set flags(flip) [expr {!$flags(flip)}] set board $flags(board) for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { $board addtag [list temp [expr {7-$c}] [expr {7-$r}]] \ withtag [list cr $c $r] $board dtag [list cr $c $r] } } for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { $board addtag [list cr $c $r] withtag [list temp $c $r] $board dtag [list temp $c $r] } } set relief [expr {$flags(flip) ? "sunken" : "raised"}] $flags(flip_button) configure -relief $relief draw_position $gid highlight_last_move $gid } proc chess::set_tooltips {args} { variable options if {$options(show_tooltips)} { set tooltip0 [::msgcat::mc "Press button and make move if you want propose draw"] set tooltip1 [::msgcat::mc "Press button if you want accept the draw proposal"] set tooltip2 [::msgcat::mc "Press button if you want resign"] } else { set tooltip0 "" set tooltip1 "" set tooltip2 "" } foreach var [info vars [namespace current]::*] { upvar 0 $var flags if {[info exists flags(bbox)]} { catch { $flags(bbox) itemconfigure 0 -helptext $tooltip0 $flags(bbox) itemconfigure 1 -helptext $tooltip1 $flags(bbox) itemconfigure 2 -helptext $tooltip2 } } } } proc chess::toggle_show_last_move {gid} { variable $gid upvar 0 $gid flags set flags(show_last_move) [expr {!$flags(show_last_move)}] set relief [expr {$flags(show_last_move) ? "sunken" : "raised"}] $flags(show_last_move_button) configure -relief $relief highlight_last_move $gid } proc chess::toggle_draw {gid} { variable $gid upvar 0 $gid flags set flags(position,draw) [expr {!$flags(position,draw)}] if {$flags(position,draw)} { $flags(bbox) itemconfigure 0 -relief sunken } else { $flags(bbox) itemconfigure 0 -relief raised } } proc chess::update_controls {gid {draw_proposed 0}} { variable $gid upvar 0 $gid flags $flags(bbox) itemconfigure 0 -relief raised if {[is_my_move $gid]} { $flags(board) config -cursor "" set flags(position,draw) 0 if {$draw_proposed} { $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state normal $flags(bbox) itemconfigure 2 -state disabled } else { $flags(bbox) itemconfigure 0 -state normal $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state normal } } elseif {![is_white $flags(position,turn)] && \ ![is_black $flags(position,turn)]} { $flags(board) config -cursor "" $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled } else { $flags(board) config -cursor watch $flags(bbox) itemconfigure 0 -state disabled $flags(bbox) itemconfigure 1 -state disabled $flags(bbox) itemconfigure 2 -state disabled } } proc chess::end_game {gid my_score message} { variable $gid upvar 0 $gid flags set opponent_score [expr {1 - $my_score}] if {[is_white $flags(our_color)]} { set score "$my_score : $opponent_score" } else { set score "$opponent_score : $my_score" } set flags(position,turn) none set flags(move_label) $message set hw $flags(hw) $hw configure -state normal catch {$hw delete attention.first attention.last} $hw delete {end -1 char} end $hw insert end "\n\t\t$score\n" $hw see end $hw configure -state disabled } proc chess::draw_position {gid} { variable $gid upvar 0 $gid flags $flags(board) delete figure for {set c 0} {$c < 8} {incr c} { for {set r 0} {$r < 8} {incr r} { if {$flags(position,$c,$r) != ""} { if {$flags(flip)} { set c1 [expr {7 - $c}] set r1 [expr {7 - $r}] } else { set c1 $c set r1 $r } $flags(board) create image [center $c1 $r1] \ -image chess/$flags(position,$c,$r) \ -tags [list figure $flags(position,$c,$r) [list cr $c $r]] } } } } proc chess::start_drag_figure {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) lassign [lindex [lmatch -regexp [$board gettags current] ^cr] 0] cr \ flags(currentc) flags(currentr) set flags(last_x) [$board canvasx $x] set flags(last_y) [$board canvasy $y] $board raise current $board config -cursor hand2 highlight_legal_moves $gid $flags(currentc) $flags(currentr) } proc chess::drag_figure {gid x y} { variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board move current \ [expr {$x - $flags(last_x)}] [expr {$y - $flags(last_y)}] set flags(last_x) $x set flags(last_y) $y $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq $board itemconfigure legal&&square -outline blue $board addtag dst_sq overlapping $x $y $x $y lassign [lindex [lmatch -regexp [$board gettags dst_sq&&background] ^cr] 0] \ cr c r $board addtag dst_sq withtag [list cr $c $r]&&square $board itemconfigure dst_sq&&square -outline red $board itemconfigure dst_sq&&legal&&square -outline white } proc chess::drag_end {gid x y} { variable options variable $gid upvar 0 $gid flags set board $flags(board) set x [$board canvasx $x] set y [$board canvasy $y] $board itemconfigure dst_sq&&square -outline "" $board dtag dst_sq $board addtag dst_sq overlapping $x $y $x $y lassign [lindex [lmatch \ -regexp [$board gettags dst_sq&&background] \ ^cr] 0] cr c r $board dtag dst_sq if {$options(allow_illegal) || [is_my_move $gid]} { do_move $gid $flags(currentc) $flags(currentr) \ $c $r "" $flags(position,draw) } update_controls $gid draw_position $gid unhighlight_legal_moves $gid highlight_last_move $gid } proc chess::highlight_last_move {gid} { variable $gid upvar 0 $gid flags $flags(board) itemconfigure square -outline "" $flags(board) itemconfigure square -outline "" if {[catch {lassign $flags(position,last_move) cf rf ct rt}]} { return } if {$flags(show_last_move)} { set color white } else { set color {} } $flags(board) itemconfigure [list cr $cf $rf]&&square -outline $color $flags(board) itemconfigure [list cr $ct $rt]&&square -outline $color } proc chess::do_move {gid cf rf ct rt prom draw} { variable options variable $gid upvar 0 $gid flags if {$cf == $ct && $rf == $rt || $ct == "" || $rt == ""} { return 0 } set opts "-" set prm "" set suffix "" set checkmate 0 set stalemate 0 set my_move [is_my_move $gid] if {![is_move_legal $gid $cf $rf $ct $rt]} { if {$my_move && !$options(allow_illegal)} { return 0 } if {!$my_move && !$options(accept_illegal)} { return 0 } } save_position $gid if {$flags(position,$ct,$rt) != ""} { set opts ":" } set f $flags(position,$cf,$rf) set flags(position,$ct,$rt) $flags(position,$cf,$rf) set flags(position,$cf,$rf) "" if {$flags(position,$ct,$rt) == "wk"} { set flags(position,wk,c) $ct set flags(position,wk,r) $rt } elseif {$flags(position,$ct,$rt) == "bk"} { set flags(position,bk,c) $ct set flags(position,bk,r) $rt } if {[is_white $flags(position,turn)]} { set p "w" set opp "b" set r 0 } else { set p "b" set opp "w" set r 7 } if {$rt == (7 - $r)} { if {$ct == 0} { set flags(position,${opp}k,qcastling) 0 } elseif {$ct == 7} { set flags(position,${opp}k,kcastling) 0 } } if {$flags(position,$ct,$rt) == "${p}k"} { set flags(position,${p}k,kcastling) 0 set flags(position,${p}k,qcastling) 0 if {($ct - $cf) == 2} { set opts {0-0} set flags(position,5,$r) "${p}r" set flags(position,7,$r) "" } elseif {($ct - $cf) == -2} { set opts {0-0-0} set flags(position,3,$r) "${p}r" set flags(position,0,$r) "" } } elseif {$flags(position,$ct,$rt) == "${p}r"} { if {($cf == 0) && ($rf == $r)} { set flags(position,${p}k,qcastling) 0 } elseif {($cf == 7) && ($rf == $r)} { set flags(position,${p}k,kcastling) 0 } } set enpassant 0 if {$flags(position,$ct,$rt) == "${p}p"} { if {(($p == "w") && ($rt == 7)) || \ (($p == "b") && ($rt == 0))} { if {$my_move} { set promote [promote_pawn $gid $p] if {$promote == -1} { set flags(position,$ct,$rt) "${p}q" } else { set flags(position,$ct,$rt) $promote } } else { if {$prom != ""} { set flags(position,$ct,$rt) "${p}$prom" } # If we are here, then it's an error... } set prm $flags(position,$ct,$rt) } elseif {$flags(position,enpassant) == [list $ct $rt]} { if {[is_white $flags(position,turn)]} { set flags(position,$ct,4) "" } else { set flags(position,$ct,3) "" } set opts ":" } else { if {($rt - $rf) == 2} { set flags(position,enpassant) [list $ct [expr {$rt - 1}]] set enpassant 1 } elseif {($rt - $rf) == -2} { set flags(position,enpassant) [list $ct [expr {$rt + 1}]] set enpassant 1 } } } if {!$enpassant} { set flags(position,enpassant) {} } set flags(position,last_move) [list $cf $rf $ct $rt] if {[is_white $flags(position,turn)]} { set flags(position,turn) black set check [test_check $gid $flags(position,bk,c) $flags(position,bk,r) \ $flags(position,bk,c) $flags(position,bk,r)] } else { set flags(position,turn) white set check [test_check $gid $flags(position,wk,c) $flags(position,wk,r) \ $flags(position,wk,c) $flags(position,wk,r)] } find_legal_moves $gid $flags(position,turn) if {$check} { if {[lempty $flags(legal_moves)]} { set suffix "#" set draw 0 set checkmate 1 } else { set suffix "+" } } else { if {[lempty $flags(legal_moves)]} { set stalemate 1 } } if {$draw} { append suffix "=" } lappend opts $prm $suffix add_move_to_history $gid $cf $rf $ct $rt $f $opts set repetitions [add_to_repetitions $gid] if {$draw && !$my_move} { attention_message $gid \ [::msgcat::mc "\n\n Opponent proposes a draw\n\n"] } if {$my_move} { send_move $gid $cf $rf $ct $rt $prm } if {$stalemate} { # Draw by stalemate end_game $gid 0.5 [::msgcat::mc "Draw (Stalemate)"] } elseif {$repetitions >= 3} { # Draw by repetition end_game $gid 0.5 [::msgcat::mc "Draw (Repetition)"] } elseif {$checkmate} { if {$my_move} { # I win end_game $gid 1 [::msgcat::mc "You win (Checkmate)"] } else { # Opponent wins end_game $gid 0 [::msgcat::mc "Opponent wins (Checkmate)"] } } tab_set_updated [winfo parent $flags(board)] 1 mesg_to_user return 1 } proc chess::promote_pawn {gid color} { variable options variable square_size variable line_width variable $gid upvar 0 $gid flags if {$options(always_queen)} { return -1 } set w .promote if {[winfo exists $w]} { destroy $w } Dialog .promote -title [::msgcat::mc "Pawn promotion"] \ -separator 0 -anchor e -default 0 set fr [frame $w.fr] set select [canvas $w.select \ -width [expr {($square_size + $line_width) * 4}] \ -height [expr {($square_size + $line_width)}]] pack $fr -padx 3m -pady 1m pack $select -padx 3m -pady 1m set c 0 foreach fig {q r b n} { set img [expr {$c % 2 ? "bf" : "wf"}] set x1 [expr {$line_width + (($square_size + $line_width) * $c)}] set x2 [expr {($square_size + $line_width) * ($c + 1)}] set y1 [expr {$line_width + (($square_size + $line_width) * 0)}] set y2 [expr {($square_size + $line_width) * (0 + 1)}] $select create image $x1 $y1 -image chess/$img -anchor nw \ -tags [list background fg$fig] $select create image $x1 $y1 -image chess/$color$fig -anchor nw \ -tags [list figure fg$fig] $select create rectangle $x1 $y1 $x2 $y2 \ -outline {} \ -tags [list square fg$fig] incr c } bind $select [list [namespace current]::promotion:motion %W %x %y] bind $select [list [namespace current]::promotion:motion %W %x %y] bind $select [list [namespace current]::promotion:leave %W %x %y] foreach fig {q r b n} { $select bind fg$fig \ [list Dialog::enddialog $w $color$fig] } $w draw } proc chess::promotion:motion {c x y} { set x [$c canvasx $x] set y [$c canvasy $y] $c itemconfigure dst_sq&&square -outline "" $c dtag dst_sq $c addtag dst_sq overlapping $x $y $x $y set tags [$c gettags dst_sq&&background] set tag [lindex $tags [lsearch $tags fg*]] if {$tag != ""} { $c addtag dst_sq withtag $tag&&square } $c itemconfigure dst_sq&&square -outline blue } proc chess::promotion:leave {c x y} { $c itemconfigure dst_sq&&square -outline "" $c dtag dst_sq } proc chess::accept_draw {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type chess \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag accept]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0.5 [::msgcat::mc "Draw (You accepted)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc chess::send_resign {gid} { variable $gid upvar 0 $gid flags jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type chess \ id $flags(id)] \ -subtags [list [jlib::wrapper:createtag resign]]] \ -to $flags(opponent) \ -connection $flags(connid) end_game $gid 0 [::msgcat::mc "Opponent wins (You resigned)"] update_controls $gid draw_position $gid highlight_last_move $gid } proc chess::send_move {gid cf rf ct rt prom} { variable $gid upvar 0 $gid flags set move_tags [list [make_move_tag $gid $cf $rf $ct $rt $prom]] if {$flags(position,draw)} { lappend move_tags [jlib::wrapper:createtag draw] } jlib::send_iq set \ [jlib::wrapper:createtag turn \ -vars [list xmlns games:board \ type chess \ id $flags(id)] \ -subtags $move_tags] \ -to $flags(opponent) \ -connection $flags(connid) \ -command [list [namespace current]::send_result $gid] } proc chess::send_result {gid res child} { if {$res == "ERR"} { attention_message $gid \ [format [::msgcat::mc "\n\n Opponent rejected move:\n %s\n\n"] \ [error_to_string $child]] restore_position $gid } } proc chess::make_move_tag {gid cf rf ct rt prom} { variable prom_name if {$prom == ""} { jlib::wrapper:createtag move -vars [list pos "$cf,$rf;$ct,$rt"] } else { set f [string index $prom 1] jlib::wrapper:createtag move -vars [list pos "$cf,$rf;$ct,$rt"] \ -subtags [list [jlib::wrapper:createtag promotion -chdata $prom_name($f)]] } } proc chess::add_to_repetitions {gid} { variable $gid upvar 0 $gid flags array set repetitions $flags(position,repetitions) set code [code_position $gid] if {[info exists repetitions($code)]} { incr repetitions($code) } else { set repetitions($code) 1 } set flags(position,repetitions) [array get repetitions] return $repetitions($code) } proc chess::add_move_to_history {gid cf rf ct rt f opts} { variable piece_name variable $gid upvar 0 $gid flags incr flags(position,halfmove) 1 lappend flags(position,history) [list $cf $rf $ct $rt $f $opts] set hw $flags(hw) $hw configure -state normal $hw delete 0.0 end $hw insert end "\t[::msgcat::mc White]\t[::msgcat::mc Black]\n" set i 1 foreach {w b} $flags(position,history) { $hw insert end "${i}.\t" if {$w != {}} { lassign $w cf rf ct rt f opts lassign $opts opt prom check if {$prom == ""} { set m "" } else { set m $piece_name($prom) } if {($opt == "0-0") || ($opt == "0-0-0")} { $hw insert end "$opt$check\t" } else { incr rf incr rt set lf [format %c [expr {$cf+97}]] set lt [format %c [expr {$ct+97}]] set n $piece_name($f) $hw insert end "$n${lf}$rf${opt}${lt}$rt$m$check\t" } } if {$b != {}} { lassign $b cf rf ct rt f opts lassign $opts opt prom check if {$prom == ""} { set m "" } else { set m $piece_name($prom) } if {($opt == "0-0") || ($opt == "0-0-0")} { $hw insert end "$opt$check\n" } else { incr rf incr rt set lf [format %c [expr {$cf+97}]] set lt [format %c [expr {$ct+97}]] set n $piece_name($f) $hw insert end "$n${lf}$rf${opt}${lt}$rt$m$check\n" } } incr i } $hw see end $hw configure -state disabled } proc chess::find_pseudo_legal_moves {gid color callback} { variable moves variable $gid upvar 0 $gid flags set c [string index $color 0] for {set cf 0} {$cf < 8} {incr cf} { for {set rf 0} {$rf < 8} {incr rf} { if {[string index $flags(position,$cf,$rf) 0] != $c} { continue } switch -- $flags(position,$cf,$rf) { "" { continue } wp { set rt [expr {$rf + 1}] if {$rf < 7 && $flags(position,$cf,$rt) == ""} { if {$rf == 6} { eval $callback $gid $cf $rf $cf $rt promotion } else { eval $callback $gid $cf $rf $cf $rt } } if {$rf == 1 && $flags(position,$cf,2) == "" && \ $flags(position,$cf,3) == ""} { eval $callback $gid $cf $rf $cf 3 } foreach {ct rt} $moves(wpt,$cf,$rf) { if {[is_black $flags(position,$ct,$rt)] || \ ($flags(position,enpassant) == [list $ct $rt])} { if {$rf == 6} { eval $callback $gid $cf $rf $ct $rt promotion } else { eval $callback $gid $cf $rf $ct $rt } } } } bp { set rt [expr {$rf - 1}] if {$rf > 0 && $flags(position,$cf,$rt) == ""} { if {$rf == 1} { eval $callback $gid $cf $rf $cf $rt promotion } else { eval $callback $gid $cf $rf $cf $rt } } if {$rf == 6 && $flags(position,$cf,5) == "" && \ $flags(position,$cf,4) == ""} { eval $callback $gid $cf $rf $cf 4 } foreach {ct rt} $moves(bpt,$cf,$rf) { if {[is_white $flags(position,$ct,$rt)] || \ $flags(position,enpassant) == [list $ct $rt]} { if {$rf == 1} { eval $callback $gid $cf $rf $ct $rt promotion } else { eval $callback $gid $cf $rf $ct $rt } } } } wn - bn { foreach {ct rt} $moves(n,$cf,$rf) { if {[is_same_color $flags(position,$cf,$rf) \ $flags(position,$ct,$rt)]} \ continue eval $callback $gid $cf $rf $ct $rt } } wb - bb { foreach d {d1 d2 d3 d4} { foreach {ct rt} $moves($d,$cf,$rf) { if {[is_same_color $flags(position,$cf,$rf) \ $flags(position,$ct,$rt)]} \ break eval $callback $gid $cf $rf $ct $rt if {$flags(position,$ct,$rt) != ""} \ break } } } wr - br { foreach d {h1 h2 v1 v2} { foreach {ct rt} $moves($d,$cf,$rf) { if {[is_same_color $flags(position,$cf,$rf) \ $flags(position,$ct,$rt)]} \ break eval $callback $gid $cf $rf $ct $rt if {$flags(position,$ct,$rt) != ""} \ break } } } wq - bq { foreach d {d1 d2 d3 d4 h1 h2 v1 v2} { foreach {ct rt} $moves($d,$cf,$rf) { if {[is_same_color $flags(position,$cf,$rf) \ $flags(position,$ct,$rt)]} \ break eval $callback $gid $cf $rf $ct $rt if {$flags(position,$ct,$rt) != ""} \ break } } } wk { foreach {ct rt} $moves(k,$cf,$rf) { if {[is_same_color $flags(position,$cf,$rf) \ $flags(position,$ct,$rt)]} \ continue eval $callback $gid $cf $rf $ct $rt } if {($cf == 4) && ($rf == 0)} { if {$flags(position,wk,kcastling) && \ $flags(position,5,0) == "" && \ $flags(position,6,0) == ""} { eval $callback $gid 4 0 6 0 kcastling } if {$flags(position,wk,qcastling) && \ $flags(position,3,0) == "" && \ $flags(position,2,0) == "" && \ $flags(position,1,0) == ""} { eval $callback $gid 4 0 2 0 qcastling } } } bk { foreach {ct rt} $moves(k,$cf,$rf) { if {[is_same_color $flags(position,$cf,$rf) \ $flags(position,$ct,$rt)]} \ continue eval $callback $gid $cf $rf $ct $rt } if {($cf == 4) && ($rf == 7)} { if {$flags(position,bk,kcastling) && \ $flags(position,5,7) == "" && \ $flags(position,6,7) == ""} { eval $callback $gid 4 7 6 7 kcastling } if {$flags(position,bk,qcastling) && \ $flags(position,3,7) == "" && \ $flags(position,2,7) == "" && \ $flags(position,1,7) == ""} { eval $callback $gid 4 7 2 7 qcastling } } } } } } } proc chess::find_legal_moves {gid color} { variable $gid upvar 0 $gid flags set flags(legal_moves) {} find_pseudo_legal_moves $gid $color check_legal_callback } proc chess::check_legal_callback {gid cf rf ct rt {opt ""}} { variable $gid upvar 0 $gid flags if {![test_check $gid $cf $rf $ct $rt $opt]} { lappend flags(legal_moves) [list $cf $rf $ct $rt $opt] } } proc chess::test_check {gid cf rf ct rt {opt ""}} { variable $gid upvar 0 $gid flags set enpassantback "" set enpassantx "" set enpassanty "" if {[is_white $flags(position,turn)]} { set color black set f wk set of bk if {($rf == 4) && \ ($flags(position,$cf,$rf) == "wp") && \ ($flags(position,enpassant) == [list $ct $rt])} { set enpassantback "bp" set enpassantx $ct set enpassanty [expr {$rt - 1}] set flags(position,$enpassantx,$enpassanty) "" } } else { set color white set f bk set of wk if {($rf == 3) && \ ($flags(position,$cf,$rf) == "bp") && \ ($flags(position,enpassant) == [list $ct $rt])} { set enpassantback "wp" set enpassantx $ct set enpassanty [expr {$rt + 1}] set flags(position,$enpassantx,$enpassanty) "" } } set checks 0 set back $flags(position,$ct,$rt) set flags(position,$ct,$rt) $flags(position,$cf,$rf) set flags(position,$cf,$rf) "" if {$flags(position,$ct,$rt) == "wk"} { set flags(position,wk,c) $ct set flags(position,wk,r) $rt } elseif {$flags(position,$ct,$rt) == "bk"} { set flags(position,bk,c) $ct set flags(position,bk,r) $rt } set kc $flags(position,$f,c) set kr $flags(position,$f,r) set okc $flags(position,$of,c) set okr $flags(position,$of,r) if {$opt == "kcastling"} { set kcs [list 4 5 6] } elseif {$opt == "qcastling"} { set kcs [list 4 3 2] } else { set kcs [list $kc] } foreach c $kcs { incr checks [test_figures $gid $color $c $kr] incr checks [test_pawns $gid $color $c $kr] if {[info exists okc]} { set dx [expr {abs($c-$okc)}] set dy [expr {abs($kr-$okr)}] if {($dx <= 1) && ($dy <= 1)} { incr checks } } } set flags(position,$cf,$rf) $flags(position,$ct,$rt) set flags(position,$ct,$rt) $back if {$flags(position,$cf,$rf) == "wk"} { set flags(position,wk,c) $cf set flags(position,wk,r) $rf } elseif {$flags(position,$cf,$rf) == "bk"} { set flags(position,bk,c) $cf set flags(position,bk,r) $rf } if {$enpassantback != ""} { set flags(position,$enpassantx,$enpassanty) $enpassantback } return $checks } proc chess::test_pawns {gid color c r} { variable moves variable $gid upvar 0 $gid flags if {[is_white $color]} { foreach {x y} $moves(bpt,$c,$r) { if {$flags(position,$x,$y) == "wp"} { return 1 } } } else { foreach {x y} $moves(wpt,$c,$r) { if {$flags(position,$x,$y) == "bp"} { return 1 } } } return 0 } proc chess::test_figures {gid color c r} { variable moves variable $gid upvar 0 $gid flags if {[is_white $color]} { foreach i {d1 d2 d3 d4} { foreach {x y} $moves($i,$c,$r) { switch -- $flags(position,$x,$y) { "" {continue} wq - wb {return 1} default {break} } } } foreach i {h1 h2 v1 v2} { foreach {x y} $moves($i,$c,$r) { switch -- $flags(position,$x,$y) { "" {continue} wq - wr {return 1} default {break} } } } foreach {x y} $moves(n,$c,$r) { switch -- $flags(position,$x,$y) { wn {return 1} default {continue} } } } else { foreach i {d1 d2 d3 d4} { foreach {x y} $moves($i,$c,$r) { switch -- $flags(position,$x,$y) { "" {continue} bq - bb {return 1} default {break} } } } foreach i {h1 h2 v1 v2} { foreach {x y} $moves($i,$c,$r) { switch -- $flags(position,$x,$y) { "" {continue} bq - br {return 1} default {break} } } } foreach {x y} $moves(n,$c,$r) { switch -- $flags(position,$x,$y) { bn {return 1} default {continue} } } } return 0 } proc chess::is_move_legal {gid cf rf ct rt} { variable $gid upvar 0 $gid flags expr {[lmatch -regexp $flags(legal_moves) ^[list $cf $rf $ct $rt]] != {}} } proc chess::highlight_legal_moves {gid cf rf} { variable $gid upvar 0 $gid flags foreach move [lmatch -regexp $flags(legal_moves) ^[list $cf $rf]] { lassign $move cft rft ct rt $flags(board) addtag legal withtag [list cr $ct $rt]&&square } $flags(board) itemconfigure legal&&square -outline blue } proc chess::unhighlight_legal_moves {gid} { variable $gid upvar 0 $gid flags foreach sq [$flags(board) find withtag legal&&square] { $flags(board) itemconfigure $sq \ -outline [$flags(board) itemcget $sq -fill] } $flags(board) dtag legal } proc chess::attention_message {gid message} { variable $gid upvar 0 $gid flags set hw $flags(hw) $hw configure -state normal $hw delete {end -1 char} end $hw insert end $message attention $hw see end $hw configure -state disabled } proc chess::is_my_move {gid} { variable $gid upvar 0 $gid flags is_same_color $flags(position,turn) $flags(our_color) } proc chess::is_white {f} { string equal -length 1 $f w } proc chess::is_black {f} { string equal -length 1 $f b } proc chess::is_same_color {f1 f2} { string equal -length 1 $f1 $f2 } proc chess::add_groupchat_user_menu_item {m connid jid} { set mm $m.gamesmenu if {![winfo exists $mm]} { menu $mm -tearoff 0 $m add cascade -label [::msgcat::mc "Games"] -menu $mm } $mm add command -label [::msgcat::mc "Chess..."] \ -command [list [namespace current]::invite_dialog $connid $jid] } hook::add roster_create_groupchat_user_menu_hook \ [namespace current]::chess::add_groupchat_user_menu_item 48 hook::add chat_create_user_menu_hook \ [namespace current]::chess::add_groupchat_user_menu_item 48 hook::add roster_jid_popup_menu_hook \ [namespace current]::chess::add_groupchat_user_menu_item 48 proc chess::iq_create {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children if {[jlib::wrapper:getattr $vars type] == "chess"} { if {[jlib::wrapper:isattr $vars color]} { set color [jlib::wrapper:getattr $vars color] switch -- $color { white - black { } default { set var [list error modify bad-request] } } } else { set color white } set var [[namespace current]::invited_dialog \ $connid $from \ [jlib::wrapper:getattr $vars id] \ $color] } return } hook::add games_board_create_hook [namespace current]::chess::iq_create proc chess::iq_turn {varname connid from child} { upvar 2 $varname var jlib::wrapper:splitxml $child tag vars isempty chdata children if {[jlib::wrapper:getattr $vars type] == "chess"} { set gid [make_gid $from [jlib::wrapper:getattr $vars id]] if {[exists $gid]} { set var [[namespace current]::turn_recv $gid $children] } else { set var [list error cancel item-not-found] } } return } hook::add games_board_turn_hook [namespace current]::chess::iq_turn # Common games:board part proc iq_games_board_create {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_create_hook res $connid $from $child return $res } iq::register_handler set create games:board \ [namespace current]::iq_games_board_create proc iq_games_board_turn {connid from lang child} { set res [list error cancel feature-not-implemented] hook::run games_board_turn_hook res $connid $from $child return $res } iq::register_handler set turn games:board \ [namespace current]::iq_games_board_turn tkabber-plugins-0.11.1/tkabber-khim/0000755000175000017500000000000011076120366016543 5ustar sergeisergeitkabber-plugins-0.11.1/tkabber-khim/khim/0000755000175000017500000000000011076120366017473 5ustar sergeisergeitkabber-plugins-0.11.1/tkabber-khim/khim/pl.msg0000644000175000017500000001003410547503600020612 0ustar sergeisergei# pl.msg -- # # Polish-language messages for KHIM # Contributed by Irek Chmielowiec # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # #---------------------------------------------------------------------- namespace eval ::khim { # If you edit HELPTEXT or {SELECT COMPOSE KEY}, also edit the corresponding # messages in ROOT.msg ::msgcat::mcset pl HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM pozwala na wprowadzanie znaków narodowych i symboli z klawiatury która tego nie obsługuje. Działa niezależnie od metody wprowadzania znaków jaką może oferować system operacyjny; jest przewidziany do sytuacji kiedy nie ma się kontroli nad odwzorowaniem klawiszy a istnieje potrzeba wprowadzania tekstu w różnych językach. Aby móc używać KHIM, uruchom okno Ustawień KHIM (sposób jego uruchomienia zależy od używanej aplikacji) i włącz KHIM zaznaczając opcję "Włącz KHIM". Należy także wybrać klawisz który jest rzadko używany i przypisać mu funkcję klawisza "sterującego" naciskając przycisk "Klawisz sterujący:", a następnie naciskając klawisz któremu chcemy tę funkcję przypisać. Mówiąc ogólnie, nie powinien to być klawisz ustawiony jako sterujący dla używanego układu klawiatury (np. Alt); klawisz ten będzie działał niezależnie od metody wprowadzania znaków oferowanej przez lokalny system operacyjny. Kiedy KHIM jest już uruchomiony, można wprowadzać znaki narodowe i symbole w każdym elemencie interfejsu użytkownika, który został ustawiony do korzystania z KHIM, naciskając klawisz sterujący razem z sekwencją dwóch znaków. Lista wyboru w ustawieniach KHIM pokazuje dostępne kombinacje. Dodatkowo, po dwukrotnym naciśnięciu klawisza sterującego pojawi się okno pozwalające na bezpośrednie wstawienie wybranego znaku z tablicy symboli Unicode. W oknie tablicy można nawigować pomiędzy znakami używając klawiszy kursorów lub za pomocą myszy a wybór znaku następuje przez dwukrotne kliknięcie, naciśnięcie spacji lub naciśnięcie klawisza Enter (Return). Aby zdefiniować nową sekwencję do użycia z klawiszem sterującym należy uruchomić ustawienia KHIM, wprowadzić dwa znaki w polu "Sekwencja znaków" i znak jaki chcemy uzyskać w polu "Wynik" oraz nacisnąć przycisk "Zmień". (Można także skopiować i wkleić znak z innej aplikacji lub użyć przycisku "Tablica Unicode..." (także przez dwukrotne naciśnięcie klawisza sterującego) do wyboru znaku z tablicy wszystkich dostępnych kodów Unicode.) Aby usunąć sekwencję znaków, należy wybrać ją z listy i nacisnąć "Usuń". } ::msgcat::mcset pl {SELECT COMPOSE KEY} [string map [list \n\t \n] { Proszę nacisnąć klawisz który ma być używany jako sterujący. }] ::msgcat::mcset pl {Apply} {Zastosuj} ::msgcat::mcset pl {Cancel} {Anuluj} ::msgcat::mcset pl {Change} {Zmień} ::msgcat::mcset pl {Character} {Wynik} ::msgcat::mcset pl {Compose Key} {Klawisz sterujący} ::msgcat::mcset pl {Compose key:} {Klawisz sterujący:} ::msgcat::mcset pl {Composed sequence must be two characters long} \ {Sekwecja znaków musi być dwuelementowa} ::msgcat::mcset pl {Delete} {Usuń} ::msgcat::mcset pl {KHIM Help} {Pomoc KHIM} ::msgcat::mcset pl {Help...} {Pomoc...} ::msgcat::mcset pl {Input key sequence} {Sekwencja znaków} ::msgcat::mcset pl {Insert Character} {Wstaw znak} ::msgcat::mcset pl {Invalid sequence} {Nieprawidłowa sekwencja} ::msgcat::mcset pl {Key sequences} {Sekwencje znaków} ::msgcat::mcset pl {KHIM Controls} {Ustawienia KHIM} ::msgcat::mcset pl {OK} {OK} ::msgcat::mcset pl {Select code page:} {Wybierz kodowanie:} ::msgcat::mcset pl {Unicode...} {Tablica Unicode...} ::msgcat::mcset pl {Use KHIM} {Włącz KHIM} } # vim:ft=tcl:ts=8:sw=4:sts=4:noet # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/khim/es.msg0000644000175000017500000001734011012353630020607 0ustar sergeisergei# es.msg -- # # Spanish-language messages for KHIM # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: es.msg 1420 2008-05-13 18:02:00Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/en.msg,v $ # #---------------------------------------------------------------------- namespace eval ::khim { # If you edit HELPTEXT or {SELECT COMPOSE KEY}, also edit the corresponding # messages in ROOT.msg ::msgcat::mcset es HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM te permite introducir caracteres internacionales usando un teclado que no los soporta. Funciona independientemente del método de entrada que use el sistema operativo; se usa cuando no tienes control sobre el mapa de teclado y aún así deseas introducir texto en otros idiomas. Para usar KHIM, abre los Controles KHIM (la forma de hacerlo depende de la aplicación) y activa KHIM pulsando en "Usar KHIM". También necesitas escoger una tecla de tu teclado que sea usada raramente, y designarla como la tecla de "Componer" pulsando el botón "Tecla de composición" y pulsando la tecla deseada. En general, esta tecla no debería ser designada como "Componer" en el teclado; esta tecla seguirá sirviendo para invocar cualquier método de entrada proporcionado por el sistema operativo. Once KHIM is enabled, you can enter international characters in any widget that is configured to use KHIM by pressing the Compose key followed by a two-character sequence. The listbox in the KHIM controls shows the available sequences. In addition, if you strike the Compose key twice, you get a dialog that allows you to input arbitrary symbols from a Unicode character map. In the map, you can navigate among the characters using either the cursor keys or the mouse, and you can select the current character for insertion by double-clicking it, pressing the space bar, or pressing the Enter (or Return) key. To define a new sequence for use with the Compose key, bring up the KHIM controls, enter the two characters in the "Input key sequence" entry and the desired character to insert into the "Character" entry, and press "Change". (You may copy and paste the character from another application, or use the "Unicode..." button (or press the Compose key twice) to select the character from a map of all available Unicode code points.) To remove a sequence, select it in the listbox and press "Delete". } ::msgcat::mcset es {SELECT COMPOSE KEY} [string map [list \n\t \n] { Por favor pulsa la tecla que quieres usar como la tecla de "Componer". }] ::msgcat::mcset es {Apply} {Aplicar} ::msgcat::mcset es {Cancel} {Cancelar} ::msgcat::mcset es {Change} {Cambiar} ::msgcat::mcset es {Character} {Carácter} ::msgcat::mcset es {Compose Key} {Tecla de Composición} ::msgcat::mcset es {Compose key:} {Tecla de composición:} ::msgcat::mcset es {Composed sequence must be two characters long} \ {La secuencia compuesta debe tener al menos dos carácteres de longitud} ::msgcat::mcset es {Delete} {Borrar} ::msgcat::mcset es {KHIM Help} {Ayuda de KHIM} ::msgcat::mcset es {Help...} {Ayuda...} ::msgcat::mcset es {Input key sequence} {Secuencia de introducción de teclas} ::msgcat::mcset es {Insert Character} {Insertar Carácter} ::msgcat::mcset es {Invalid sequence} {Secuencia inválida} ::msgcat::mcset es {Key sequences} {Secuencias de Teclas} ::msgcat::mcset es {KHIM Controls} {Controles de KHIM} ::msgcat::mcset es {OK} {Aceptar} ::msgcat::mcset es {Select code page:} {Seleccionar página de códigos:} ::msgcat::mcset es {Unicode...} {Unicode...} ::msgcat::mcset es {Use KHIM} {Usar KHIM} } # Local Variables: # mode: tcl # End: # es.msg -- # # Spanish-language messages for KHIM # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: es.msg 1420 2008-05-13 18:02:00Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/en.msg,v $ # #---------------------------------------------------------------------- namespace eval ::khim { # If you edit HELPTEXT or {SELECT COMPOSE KEY}, also edit the corresponding # messages in ROOT.msg ::msgcat::mcset es HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM te permite introducir caracteres internacionales usando un teclado que no los soporta. Funciona independientemente del método de entrada que use el sistema operativo; se usa cuando no tienes control sobre el mapa de teclado y aún así deseas introducir texto en otros idiomas. Para usar KHIM, abre los Controles KHIM (la forma de hacerlo depende de la aplicación) y activa KHIM pulsando en "Usar KHIM". También necesitas escoger una tecla de tu teclado que sea usada raramente, y designarla como la tecla de "Componer" pulsando el botón "Tecla de composición" y pulsando la tecla deseada. En general, esta tecla no debería ser designada como "Componer" en el teclado; esta tecla seguirá sirviendo para invocar cualquier método de entrada proporcionado por el sistema operativo. Once KHIM is enabled, you can enter international characters in any widget that is configured to use KHIM by pressing the Compose key followed by a two-character sequence. The listbox in the KHIM controls shows the available sequences. In addition, if you strike the Compose key twice, you get a dialog that allows you to input arbitrary symbols from a Unicode character map. In the map, you can navigate among the characters using either the cursor keys or the mouse, and you can select the current character for insertion by double-clicking it, pressing the space bar, or pressing the Enter (or Return) key. To define a new sequence for use with the Compose key, bring up the KHIM controls, enter the two characters in the "Input key sequence" entry and the desired character to insert into the "Character" entry, and press "Change". (You may copy and paste the character from another application, or use the "Unicode..." button (or press the Compose key twice) to select the character from a map of all available Unicode code points.) To remove a sequence, select it in the listbox and press "Delete". } ::msgcat::mcset es {SELECT COMPOSE KEY} [string map [list \n\t \n] { Por favor pulsa la tecla que quieres usar como la tecla de "Componer". }] ::msgcat::mcset es {Apply} {Aplicar} ::msgcat::mcset es {Cancel} {Cancelar} ::msgcat::mcset es {Change} {Cambiar} ::msgcat::mcset es {Character} {Carácter} ::msgcat::mcset es {Compose Key} {Tecla de Composición} ::msgcat::mcset es {Compose key:} {Tecla de composición:} ::msgcat::mcset es {Composed sequence must be two characters long} \ {La secuencia compuesta debe tener al menos dos carácteres de longitud} ::msgcat::mcset es {Delete} {Borrar} ::msgcat::mcset es {KHIM Help} {Ayuda de KHIM} ::msgcat::mcset es {Help...} {Ayuda...} ::msgcat::mcset es {Input key sequence} {Secuencia de introducción de teclas} ::msgcat::mcset es {Insert Character} {Insertar Carácter} ::msgcat::mcset es {Invalid sequence} {Secuencia inválida} ::msgcat::mcset es {Key sequences} {Secuencias de Teclas} ::msgcat::mcset es {KHIM Controls} {Controles de KHIM} ::msgcat::mcset es {OK} {Aceptar} ::msgcat::mcset es {Select code page:} {Seleccionar página de códigos:} ::msgcat::mcset es {Unicode...} {Unicode...} ::msgcat::mcset es {Use KHIM} {Usar KHIM} } # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/khim/ROOT.msg0000644000175000017500000000554010540047772020776 0ustar sergeisergei# ROOT.msg -- # # Default English-language messages for KHIM # # Copyright (c) 2006 by Kevin B. Kenny. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: ROOT.msg 826 2006-12-13 19:09:46Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/ROOT.msg,v $ # #---------------------------------------------------------------------- # Make sure that help text is available in the root locale. namespace eval ::khim { # If you edit this file, also edit the corresponding text in en.msg, # which is provided for 8.4 compatibility. ::msgcat::mcset {} HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM allows you to input international characters from a keyboard that doesn't support them. It works independently of any input method that the operating system may supply; it is intended for when you don't have control over your keyboard mapping and still need to input text in other languages. To use KHIM, bring up the KHIM Controls (the way this is done depends on your application) and enable KHIM by checking "Use KHIM". You also need to choose a key on your keyboard that is seldom used, and designate it as the "Compose" key by pressing the button labelled, "Compose key:" then striking the key you wish to designate. Generally speaking, this key should not be the key designated as "Compose" on the keyboard; that key will continue to invoke whatever input method the local operating system supplies. Once KHIM is enabled, you can enter international characters in any widget that is configured to use KHIM by pressing the Compose key followed by a two-character sequence. The listbox in the KHIM controls shows the available sequences. In addition, if you strike the Compose key twice, you get a dialog that allows you to input arbitrary symbols from a Unicode character map. In the map, you can navigate among the characters using either the cursor keys or the mouse, and you can select the current character for insertion by double-clicking it, pressing the space bar, or pressing the Enter (or Return) key. To define a new sequence for use with the Compose key, bring up the KHIM controls, enter the two characters in the "Input key sequence" entry and the desired character to insert into the "Character" entry, and press "Change". (You may copy and paste the character from another application, or use the "Unicode..." button (or press the Compose key twice) to select the character from a map of all available Unicode code points.) To remove a sequence, select it in the listbox and press "Delete". } ::msgcat::mcset {} {SELECT COMPOSE KEY} [string map [list \n\t \n] { Please press the key that you want to use as the "Compose" key. }] } tkabber-plugins-0.11.1/tkabber-khim/khim/cs.msg0000644000175000017500000000727210540047772020624 0ustar sergeisergei# cs.msg -- # # Czech-language messages for KHIM # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # Translation by Michal Mestan # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: cs.msg 826 2006-12-13 19:09:46Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/cs.msg,v $ # #---------------------------------------------------------------------- namespace eval ::khim { ::msgcat::mcset cs HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM vám umožňuje zadávat mezinárodní znaky včetně těch, které na vaší klávesnici nejspou. Pracuje nezávisle na požité vstupní metodě kterou váš operační systém může poskytovat. Je hlavně určen pro případy, kdy nemáte možnost měnit mapování klávesnice a přesto potřebujete zapsat cizojazyčný text. K nastavení KHIM slouží "Ovládací panel KHIM" (jeho vyvolání je závaislé na konkrétní aplikaci), zde povolte KHIM zaškrtnutím políčka "Používat KHIM". Mužete si zde též vybrat klávesu na vaší klávesnici, kterou bude KHIM používat jako "mrtvá" stisknutím talčítka "Mrtvá klávesa" a poté stisktnutím patřičné klávesy. Obecně lze říci, nemůže to být jakákoliv "mrtvá" klávasa vaší klávesové mapy, jelikož při stisknutí je volána vstupní metoda operačního systému. Když je KHIM povolen, můžete vkládat mezinárodní znaky v jakémkoliv přípravku, který je nastaven tak, aby používal KHIM stiknutním "mrtvé" klávesy následované posloupností dvou znaků. Seznam v "Ovládacím panelu KHIM" zobrazuje dostupné posloupnosti. Pokud stisknete "mrtvou" klávesu dvakrát, zobrazí se vám dialog, ve kterém můžete vybrat žádaný symbol z unokódové mapy. V mapě se můžete pohybovat kursorovými klávesami, dvojklikem myší, mezerníkem či klávesou enter vybraný znak vložíte do textu. Chcete-li další znaky vkládat pomocí mrtvé klávesy, otevřete "Ovládací panel KHIM" vložte dva znaky do pole "Posloupnost kláves" a požadovaný znak, který chcete vložit do pole "Vkládaný znak" a stisknětě talčítko "Změnit" (vkládaný znak můžete nakopírovat z jiné aplikace nebo poučít talčítko "Unikód..." (nebo stisknout dvakrát "mrtvou" klávesu) a vybrat znak z unikódové mapy). K odstranění klávesové posloupnosti slouží tlačítko "Smazat". } ::msgcat::mcset cs {SELECT COMPOSE KEY} [string map [list \n\t \n] { Stiskněte klávesu kterou chcete používat jako "mrtvou" klávesu. }] ::msgcat::mcset cs {Apply} "Použít" ::msgcat::mcset cs {Cancel} "Zrušit" ::msgcat::mcset cs {Change} "Změnit" ::msgcat::mcset cs {Character} "Znak" ::msgcat::mcset cs {Compose Key} "Mrtvá klávesa" ::msgcat::mcset cs {Compose key:} "Mrtvá klávesa:" ::msgcat::mcset cs {Composed sequence must be two characters long} \ "Vkládaný znak je vždy šložen z posloupnosti zdvou nzaků" ::msgcat::mcset cs {Delete} "Smazat" ::msgcat::mcset cs {Help...} "Nápověda..." ::msgcat::mcset cs {Input key sequence} "Zadajete posloupnost kláves" ::msgcat::mcset cs {Insert Character} "Vkládaný znak" ::msgcat::mcset cs {Invalid sequence} "Chybná posloupnost" ::msgcat::mcset cs {Key sequences} "Posloupnosti kláves" ::msgcat::mcset cs {KHIM Controls} "Ovládací panel KHIM" ::msgcat::mcset cs {OK} {OK} ::msgcat::mcset cs {Select code page:} "Výběr kódové stránky:" ::msgcat::mcset cs {Unicode...} "Unikód..." ::msgcat::mcset cs {Use KHIM} "Používat KHIM" } # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/khim/khim.tcl0000644000175000017500000015433710732302307021137 0ustar sergeisergei# khim.tcl -- # # Kevin's Hacky Input Method # # The 'khim' package defines a KHIM bindtag that can be applied to # entry or text widgets (after widget-specific bindings but before # Entry or Text bindings) to allow entry of international characters # from a US keyboard without any input method other than Tk. # # It works by defining a "Compose" key (default is ). When # the "Compose" key is pressed, followed by a two-character sequence, # those two characters are looked up in a user-configurable table and # replaced with a Unicode character, which is inserted into the widget. # # Copyright (c) 2006 by Kevin B. Kenny. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: khim.tcl 1330 2007-12-19 20:53:27Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/khim.tcl,v $ # #---------------------------------------------------------------------- package require Tcl 8.4 package require Tk 8.4 package require msgcat 1.2 #package require autoscroll 1.0 package provide khim 1.0.1 namespace eval khim [list variable KHIMDir [file dirname [info script]]] namespace eval khim { namespace import ::msgcat::mc namespace export getOptions getConfig setConfig showHelp variable composeKey; # Keysym of the key used for the # Compose function variable map; # Dictionary whose keys are two- # character sequences and whose # values are the characters to # insert when those sequences # are composed variable UniOK; # Table of code-point ranges that # conform to printable chars variable use; # 1 if KHIM is enabled, 0 if not. #---------------------------------------------------------------------- variable CMapFont; # Font to use to display Unicode # characters in the character map variable CMapBadCharFont; # Font in which to display the hex # values of bad code points #---------------------------------------------------------------------- variable CMapCodePage; # Array whose keys are the # path names of KHIM character map # dialogs and whose values are # the code pages on display in # those dialogs variable CMapFocus; # Array whose keys are the path names # of KHIM character map dialogs and # whose values are the focus windows # where characters selected in the # dialogs will be inserted. variable CMapInputCodePage; # Array whose keys are the path names # of KHIM character map dialogs and # whose values are variables used # to hold the value of the spinbox # that selects the code page. variable CMapSelectedCharacter; # Array whose keys are the path names # of KHIM character map dialogs and # whose values are the characters # currently selected in the dialogs variable CMapXL; # Array whose keys are the path names # of KHIM character map dialogs and # whose values are the # X co-ordinates of the columns in # the character map variable CMapYL; # Array whose keys are the path names # of KHIM character map dialogs and # whose values are the # Y co-ordinates of the rows in the # character map. } # Load up message catalogs for the locale namespace eval khim [list ::msgcat::mcload [file dirname [info script]]] # Compressed table of which Unicode code points in the BMP are printable # characters. The table is read, "0x0000-0x001f are not printable, # 0x0020-0x007e are printable, 0x007f-0x009f are not printable, # 0x00a0-0x00ac are printable, 0x00ad is not, 0x00ae-0x0241 are, etc." set khim::UniOK { 0x0000 0x0020 0x007f 0x00a0 0x00ad 0x00ae 0x0242 0x0250 0x0370 0x0374 0x0376 0x037a 0x037b 0x037e 0x037f 0x0384 0x038b 0x038c 0x038d 0x038e 0x03a2 0x03a3 0x03cf 0x03d0 0x0487 0x0488 0x04cf 0x04d0 0x04fa 0x0500 0x0510 0x0531 0x0557 0x0559 0x0560 0x0561 0x0588 0x0589 0x058b 0x0591 0x05ba 0x05bb 0x05c8 0x05d0 0x05eb 0x05f0 0x0600 0x060b 0x0616 0x061b 0x061c 0x061e 0x0620 0x0621 0x063b 0x0640 0x065f 0x0660 0x06dd 0x06de 0x070f 0x0710 0x074b 0x074d 0x076e 0x0780 0x07b2 0x0901 0x093a 0x093c 0x094e 0x0950 0x0955 0x0958 0x0971 0x097d 0x097e 0x0981 0x0984 0x0985 0x098d 0x098f 0x0991 0x0993 0x09a9 0x09aa 0x09b1 0x09b2 0x09b3 0x09b6 0x09ba 0x09bc 0x09c5 0x09c7 0x09c9 0x09cb 0x09cf 0x09d7 0x09d8 0x09dc 0x09de 0x09df 0x09e4 0x09e6 0x09fb 0x0a01 0x0a04 0x0a05 0x0a0b 0x0a0f 0x0a11 0x0a13 0x0a29 0x0a2a 0x0a31 0x0a32 0x0a34 0x0a35 0x0a37 0x0a38 0x0a3a 0x0a3c 0x0a3d 0x0a3e 0x0a43 0x0a47 0x0a49 0x0a4b 0x0a4e 0x0a59 0x0a5d 0x0a5e 0x0a5f 0x0a66 0x0a75 0x0a81 0x0a84 0x0a85 0x0a8e 0x0a8f 0x0a92 0x0a93 0x0aa9 0x0aaa 0x0ab1 0x0ab2 0x0ab4 0x0ab5 0x0aba 0x0abc 0x0ac6 0x0ac7 0x0aca 0x0acb 0x0ace 0x0ad0 0x0ad1 0x0ae0 0x0ae4 0x0ae6 0x0af0 0x0af1 0x0af2 0x0b01 0x0b04 0x0b05 0x0b0d 0x0b0f 0x0b11 0x0b13 0x0b29 0x0b2a 0x0b31 0x0b32 0x0b34 0x0b35 0x0b3a 0x0b3c 0x0b44 0x0b47 0x0b49 0x0b4b 0x0b4e 0x0b56 0x0b58 0x0b5c 0x0b5e 0x0b5f 0x0b62 0x0b66 0x0b72 0x0b82 0x0b84 0x0b85 0x0b8b 0x0b8e 0x0b91 0x0b92 0x0b96 0x0b99 0x0b9b 0x0b9c 0x0b9d 0x0b9e 0x0ba0 0x0ba3 0x0ba5 0x0ba8 0x0bab 0x0bae 0x0bba 0x0bbe 0x0bc3 0x0bc6 0x0bc9 0x0bca 0x0bce 0x0bd7 0x0bd8 0x0be6 0x0bfb 0x0c01 0x0c04 0x0c05 0x0c0d 0x0c0e 0x0c11 0x0c12 0x0c29 0x0c2a 0x0c34 0x0c35 0x0c3a 0x0c3e 0x0c45 0x0c46 0x0c49 0x0c4a 0x0c4e 0x0c55 0x0c57 0x0c60 0x0c62 0x0c66 0x0c70 0x0c82 0x0c84 0x0c85 0x0c8d 0x0c8e 0x0c91 0x0c92 0x0ca9 0x0caa 0x0cb4 0x0cb5 0x0cba 0x0cbc 0x0cc5 0x0cc6 0x0cc9 0x0cca 0x0cce 0x0cd5 0x0cd7 0x0cde 0x0cdf 0x0ce0 0x0ce2 0x0ce6 0x0cf0 0x0d02 0x0d04 0x0d05 0x0d0d 0x0d0e 0x0d11 0x0d12 0x0d29 0x0d2a 0x0d3a 0x0d3e 0x0d44 0x0d46 0x0d49 0x0d4a 0x0d4e 0x0d57 0x0d58 0x0d60 0x0d62 0x0d66 0x0d70 0x0d82 0x0d84 0x0d85 0x0d97 0x0d9a 0x0db2 0x0db3 0x0dbc 0x0dbd 0x0dbe 0x0dc0 0x0dc7 0x0dca 0x0dcb 0x0dcf 0x0dd5 0x0dd6 0x0dd7 0x0dd8 0x0de0 0x0df2 0x0df5 0x0e01 0x0e3b 0x0e3f 0x0e5c 0x0e81 0x0e83 0x0e84 0x0e85 0x0e87 0x0e89 0x0e8a 0x0e8b 0x0e8d 0x0e8e 0x0e94 0x0e98 0x0e99 0x0ea0 0x0ea1 0x0ea4 0x0ea5 0x0ea6 0x0ea7 0x0ea8 0x0eaa 0x0eac 0x0ead 0x0eba 0x0ebb 0x0ebe 0x0ec0 0x0ec5 0x0ec6 0x0ec7 0x0ec8 0x0ece 0x0ed0 0x0eda 0x0edc 0x0ede 0x0f00 0x0f48 0x0f49 0x0f6b 0x0f71 0x0f8c 0x0f90 0x0f98 0x0f99 0x0fbd 0x0fbe 0x0fcd 0x0fcf 0x0fd2 0x1000 0x1022 0x1023 0x1028 0x1029 0x102b 0x102c 0x1033 0x1036 0x103a 0x1040 0x105a 0x10a0 0x10c6 0x10d0 0x10fd 0x1100 0x115a 0x115f 0x11a3 0x11a8 0x11fa 0x1200 0x1249 0x124a 0x124e 0x1250 0x1257 0x1258 0x1259 0x125a 0x125e 0x1260 0x1289 0x128a 0x128e 0x1290 0x12b1 0x12b2 0x12b6 0x12b8 0x12bf 0x12c0 0x12c1 0x12c2 0x12c6 0x12c8 0x12d7 0x12d8 0x1311 0x1312 0x1316 0x1318 0x135b 0x135f 0x137d 0x1380 0x139a 0x13a0 0x13f5 0x1401 0x1677 0x1680 0x169d 0x16a0 0x16f1 0x1700 0x170d 0x170e 0x1715 0x1720 0x1737 0x1740 0x1754 0x1760 0x176d 0x176e 0x1771 0x1772 0x1774 0x1780 0x17b4 0x17b6 0x17de 0x17e0 0x17ea 0x17f0 0x17fa 0x1800 0x180f 0x1810 0x181a 0x1820 0x1878 0x1880 0x18aa 0x1900 0x191d 0x1920 0x192c 0x1930 0x193c 0x1940 0x1941 0x1944 0x196e 0x1970 0x1975 0x1980 0x19aa 0x19b0 0x19ca 0x19d0 0x19da 0x19de 0x1a1c 0x1a1e 0x1a20 0x1d00 0x1dc4 0x1e00 0x1e9c 0x1ea0 0x1efa 0x1f00 0x1f16 0x1f18 0x1f1e 0x1f20 0x1f46 0x1f48 0x1f4e 0x1f50 0x1f58 0x1f59 0x1f5a 0x1f5b 0x1f5c 0x1f5d 0x1f5e 0x1f5f 0x1f7e 0x1f80 0x1fb5 0x1fb6 0x1fc5 0x1fc6 0x1fd4 0x1fd6 0x1fdc 0x1fdd 0x1ff0 0x1ff2 0x1ff5 0x1ff6 0x1fff 0x2000 0x200b 0x2010 0x202a 0x202f 0x2060 0x2070 0x2072 0x2074 0x208f 0x2090 0x2095 0x20a0 0x20b6 0x20d0 0x20ec 0x2100 0x214d 0x2153 0x2184 0x2190 0x23dc 0x2400 0x2427 0x2440 0x244b 0x2460 0x269d 0x26a0 0x26b2 0x2701 0x2705 0x2706 0x270a 0x270c 0x2728 0x2729 0x274c 0x274d 0x274e 0x274f 0x2753 0x2756 0x2757 0x2758 0x275f 0x2761 0x2795 0x2798 0x27b0 0x27b1 0x27bf 0x27c0 0x27c7 0x27d0 0x27ec 0x27f0 0x2b14 0x2c00 0x2c2f 0x2c30 0x2c5f 0x2c80 0x2ceb 0x2cf9 0x2d26 0x2d30 0x2d66 0x2d6f 0x2d70 0x2d80 0x2d97 0x2da0 0x2da7 0x2da8 0x2daf 0x2db0 0x2db7 0x2db8 0x2dbf 0x2dc0 0x2dc7 0x2dc8 0x2dcf 0x2dd0 0x2dd7 0x2dd8 0x2ddf 0x2e00 0x2e18 0x2e1c 0x2e1e 0x2e80 0x2e9a 0x2e9b 0x2ef4 0x2f00 0x2fd6 0x2ff0 0x2ffc 0x3000 0x3040 0x3041 0x3097 0x3099 0x3100 0x3105 0x312d 0x3131 0x318f 0x3190 0x31b8 0x31c0 0x31d0 0x31f0 0x321f 0x3220 0x3244 0x3250 0x32ff 0x3300 0x4db6 0x4dc0 0x9fbc 0xa000 0xa48d 0xa490 0xa4c7 0xa700 0xa717 0xa800 0xa82c 0xac00 0xd7a4 0xe000 0xfa2e 0xfa30 0xfa6b 0xfa70 0xfada 0xfb00 0xfb07 0xfb13 0xfb18 0xfb1d 0xfb37 0xfb38 0xfb3d 0xfb3e 0xfb3f 0xfb40 0xfb42 0xfb43 0xfb45 0xfb46 0xfbb2 0xfbd3 0xfd40 0xfd50 0xfd90 0xfd92 0xfdc8 0xfdf0 0xfdfe 0xfe00 0xfe1a 0xfe20 0xfe24 0xfe30 0xfe53 0xfe54 0xfe67 0xfe68 0xfe6c 0xfe70 0xfe75 0xfe76 0xfeff 0xff01 0xffbf 0xffc2 0xffc8 0xffca 0xffd0 0xffd2 0xffd8 0xffda 0xffdd 0xffe0 0xffe7 0xffe8 0xfff9 0xfffc 0xfffe } #---------------------------------------------------------------------- # # BSearch -- # # Service procedure that does binary search in several places. # # Parameters: # list - List of lists, sorted in ascending order by the # first elements # key - Value to search for # # Results: # Returns the index of the greatest element in $list that is less # than or equal to $key. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::khim::BSearch { list key } { if { $key < [lindex $list 0 0] } { return -1 } set l 0 set u [expr { [llength $list] - 1 }] while { $l < $u } { # At this point, we know that # $k >= [lindex $list $l 0] # Either $u == [llength $list] or else $k < [lindex $list $u+1 0] # We find the midpoint of the interval {l,u} rounded UP, compare # against it, and set l or u to maintain the invariant. Note # that the interval shrinks at each step, guaranteeing convergence. set m [expr { ( $l + $u + 1 ) / 2 }] if { $key >= [lindex $list $m 0] } { set l $m } else { set u [expr { $m - 1 }] } } return $l } #---------------------------------------------------------------------- # # khim::ValidChar -- # # Test whether a number is the index of a valid character. # # Parameters: # c - Number of the character. # # Results: # Returns 1 if the character is a printable Unicode characte # in the BMP, and 0 otherwise. # #---------------------------------------------------------------------- proc ::khim::ValidChar { c } { variable UniOK return [expr {( [BSearch $UniOK $c] & 1 )}] } #---------------------------------------------------------------------- # # khim::getOptions -- # # Displays a dialog that allows the user to enable/disable KHIM, # change key mappings, and change the Compose key. # # Parameters: # w -- Window path name of the dialog box. # # Results: # None. # # Side effects: # Changes options to whatever the user selects. # #---------------------------------------------------------------------- proc khim::getOptions {w} { variable use variable composeKey variable map variable inputUse variable inputComposeKey variable inputMap # Set temporary options for the use of the dialog set inputUse $use set inputComposeKey $composeKey array set inputMap $map # Create a modal dialog toplevel $w -class dialog wm withdraw $w set p [winfo toplevel [winfo parent $w]] set g [wm transient $p] if { ![string compare {} $g] } { set g $p } wm transient $w $g catch {wm attributes $w -toolwindow 1} wm title $w [mc "KHIM Controls"] bind $w [list ::khim::HandleDestroy $w %W] # Create GUI and manage geometry checkbutton $w.v -variable ::khim::inputUse -text [mc "Use KHIM"] label $w.l1 -text [mc "Compose key:"] button $w.b1 -textvariable khim::inputComposeKey \ -command [list ::khim::GetComposeKey $w.b1] labelframe $w.lf1 -text [mc "Key sequences"] -padx 5 -pady 5 -width 400 listbox $w.lf1.lb -height 20 -yscroll [list $w.lf1.y set] \ -font {Courier 12} -width 8 -height 10 \ -exportselection 0 bind $w.lf1.lb <> [list ::khim::Select %W] scrollbar $w.lf1.y -orient vertical -command [list $w.lf1.lb yview] frame $w.lf1.f1 label $w.lf1.f1.l1 -text [mc "Input key sequence"] entry $w.lf1.f1.e1 -textvariable ::khim::inputSequence -width 2 \ -font {Courier 12} bind $w.lf1.f1.e1 { %W selection from 0 %W selection to end } grid $w.lf1.f1.l1 $w.lf1.f1.e1 grid columnconfigure $w.lf1.f1 2 -weight 1 frame $w.lf1.f2 label $w.lf1.f2.l1 -text [mc "Character"] entry $w.lf1.f2.e1 -textvariable ::khim::inputCharacter -width 2 \ -font {Courier 12} bind $w.lf1.f2.e1 { %W selection from 0 %W selection to end } button $w.lf1.f2.b1 -text [mc "Unicode..."] \ -command [list ::khim::FocusAndInsertSymbol $w.lf1.f2.e1] grid $w.lf1.f2.l1 $w.lf1.f2.e1 grid $w.lf1.f2.b1 -row 0 -column 2 -sticky w -padx {20 0} grid columnconfigure $w.lf1.f2 3 -weight 1 grid $w.lf1.lb -row 0 -column 0 -sticky nsew -rowspan 5 grid $w.lf1.y -row 0 -column 1 -sticky ns -rowspan 5 frame $w.lf1.f3 button $w.lf1.f3.b1 -text [mc Change] \ -command [list ::khim::ChangeSequence $w] button $w.lf1.f3.b2 -text [mc Delete] \ -command [list ::khim::DeleteSequence $w] grid $w.lf1.f1 -row 0 -column 2 -sticky e -padx {20 0} grid $w.lf1.f2 -row 1 -column 2 -sticky e -padx {20 0} grid $w.lf1.f3.b1 $w.lf1.f3.b2 -padx 5 -sticky ew grid columnconfigure $w.lf1.f3 {0 1} -weight 1 -uniform A grid $w.lf1.f3 -row 3 -column 2 -sticky e -padx 20 grid rowconfigure $w.lf1 2 -weight 1 grid columnconfigure $w.lf1 3 -weight 1 #::autoscroll::autoscroll $w.lf1.y frame $w.bf button $w.bf.ok -text [mc OK] -command [list ::khim::OK $w] button $w.bf.apply -text [mc Apply] -command [list ::khim::Apply $w] button $w.bf.cancel -text [mc Cancel] -command [list destroy $w] button $w.bf.help -text [mc Help...] \ -command [list ::khim::showHelp $w.help] grid $w.bf.ok -row 0 -column 0 -padx 5 -sticky ew grid $w.bf.apply -row 0 -column 1 -padx 5 -sticky ew grid $w.bf.cancel -row 0 -column 2 -padx 5 -sticky ew grid $w.bf.help -row 0 -column 4 -padx 5 grid columnconfigure $w.bf 3 -weight 1 grid columnconfigure $w.bf {0 1 2 4} -uniform A grid $w.v -columnspan 2 -sticky w grid $w.l1 $w.b1 -sticky w grid $w.lf1 -columnspan 2 -sticky nsew -padx 5 -pady 5 grid $w.bf -pady 5 -sticky ew -columnspan 2 grid columnconfigure $w 1 -weight 1 # Initialize the listbox content ShowSequences $w # Pop up the dialog wm deiconify $w tkwait window $w return } #---------------------------------------------------------------------- # # khim::FocusAndInsertSymbol -- # # Shift focus to a given window and call the character map # interactor on it. # # Parameters: # w - Window to focus # # Results: # None. # # Side effects: # Whatever the user requests from the character map. # #---------------------------------------------------------------------- proc khim::FocusAndInsertSymbol {w} { focus $w CMapInteractor $w return } #---------------------------------------------------------------------- # # khim::showHelp -- # # Display a help dialog for KHIM # # Parameters: # w -- Path name of the dialog # # Results: # None. # # Side effects: # Pops up the dialog. # # The help text is in the HELPTEXT entry in the message catalog of the # current locale. # #---------------------------------------------------------------------- proc khim::showHelp {w} { variable KHIMDir # Create dialog to display help catch {destroy $w} toplevel $w wm withdraw $w set p [winfo toplevel [winfo parent $w]] set g [wm transient $p] if { ![string compare {} $g] } { set g $p } wm transient $w $g wm title $w [mc {KHIM Help}] catch {wm attributes $w -toolwindow 1} # Create and manage GUI components text $w.t -width 60 -yscrollcommand [list $w.y set] -wrap word set text [string trim [mc HELPTEXT]] if {$text eq "HELPTEXT"} { # This must be a version of Tcl that doesn't support the root # locale. Do The Right Thing anyway set locale [::msgcat::mclocale] ::msgcat::mclocale en set text [string trim [mc HELPTEXT]] if {$text eq "HELPTEXT"} { ::msgcat::mcload $KHIMDir set text [string trim [mc HELPTEXT]] } ::msgcat::mclocale $locale } regsub -all -line {^[ \t]+} $text {} text regsub -all -line {[ \t]+$} $text {} text regsub -all {\n\n} $text

text regsub -all {\n} $text { } text regsub -all

$text \n\n text $w.t insert insert $text $w.t see 1.0 $w.t configure -state disabled scrollbar $w.y -command [list $w.t yview] -orient vertical button $w.ok -text [mc OK] -command [list destroy $w] grid $w.t -row 0 -column 0 -sticky nsew grid $w.y -row 0 -column 1 -sticky ns grid $w.ok -pady 5 -row 1 -column 0 -columnspan 2 grid rowconfigure $w 0 -weight 1 grid columnconfigure $w 0 -weight 1 # Determine whether we have a grab in effect set gr [grab current $w] if {$gr ne {}} { bind $w "focus $w.ok; grab set $w" } else { bind $w [list focus $w.ok] } # Pop up the dialog wm deiconify $w # Restore the grab if there was one if {$gr ne {}} { tkwait window $w grab set $gr } return } #---------------------------------------------------------------------- # # khim::GetComposeKey -- # # Prompt the user for what key to use for the "Compose" function. # # Parameters: # parent -- Path name of the parent widget of the dialog # # Side effects: # Stores the user's selection in 'inputComposeKey' # #---------------------------------------------------------------------- proc khim::GetComposeKey {parent} { variable KHIMDir variable inputComposeKey set w [winfo parent $parent].composeKey toplevel $w -class dialog wm withdraw $w wm geometry $w +[winfo rootx $parent]+[winfo rooty $parent] set p [winfo toplevel [winfo parent $w]] set g [wm transient $p] if { ![string compare {} $g] } { set g $p } wm transient $w $g catch {wm attributes $w -toolwindow 1} wm title $w [mc "Compose Key"] set text [mc "SELECT COMPOSE KEY"] if {$text eq "SELECT COMPOSE KEY"} { # This must be a version of Tcl that doesn't support the root # locale. Do The Right Thing anyway set locale [::msgcat::mclocale] ::msgcat::mclocale en set text [string trim [mc "SELECT COMPOSE KEY"]] if {$text eq "SELECT COMPOSE KEY"} { ::msgcat::mcload $KHIMDir set text [string trim [mc "SELECT COMPOSE KEY"]] } ::msgcat::mclocale $locale } grid [label $w.l -text $text] bind $w.l [list set ::khim::inputComposeKey %K] bind $w.l [list focus %W] wm resizable $w 0 0 bind $w [list grab $w] wm deiconify $w bind $w {set ::khim::inputComposeKey DESTROYED} set holdInputComposeKey $inputComposeKey while {1} { vwait ::khim::inputComposeKey if { $inputComposeKey eq {DESTROYED} } { set inputComposeKey $holdInputComposeKey break } elseif {$inputComposeKey ne {}} { bind $w {} after idle [list destroy $w] break } } return } #---------------------------------------------------------------------- # # khim::Select -- # # Handles selection in the listbox containing KHIM input # character sequences. # # Parameters: # lb -- Path name of the listbox. # # Results: # None. # # Side effects: # Stores the currently selected sequence, and its mapping, # in "inputSequence" and "inputCharacter." # #---------------------------------------------------------------------- proc khim::Select {lb} { variable inputSequence variable inputCharacter foreach item [$lb curselection] { if { [regexp "^(..) \u2192 (.)" [$lb get $item] \ -> inputSequence inputCharacter] } { break } } return } #---------------------------------------------------------------------- # # khim::DeleteSequence -- # # Deletes the currently selected input sequence from the set. # # Parameters: # w - Path name of the active dialog box. # # Results: # None. # # Side effects: # Removes the currently selected sequence from 'inputMap' # and redisplays the sequences in the listbox # #---------------------------------------------------------------------- proc khim::DeleteSequence {w} { khim::SetSequence $w {} return } #---------------------------------------------------------------------- # # khim::ChangeSequence -- # # Changes the currently selected input sequence from the set. # # Parameters: # w - Path name of the active dialog box. # # Results: # None. # # Side effects: # Changes the currently selected sequence from 'inputMap' # to request the character stored in 'inputCharacter' # and redisplays the sequences in the listbox # #---------------------------------------------------------------------- proc khim::ChangeSequence {w} { variable inputCharacter khim::SetSequence $w $inputCharacter return } #---------------------------------------------------------------------- # # khim::SetSequence -- # # Deletes or changes a character sequence in the input map # # Parameters: # w - Path name of the active dialog box # inputCharacter - Character that the active sequence should # map to. An empty string deletes the sequence. # # Results: # None. # # Side effects: # Changes the currently selected sequence from 'inputMap' # to request the character stored in 'inputCharacter' # and redisplays the sequences in the listbox # #---------------------------------------------------------------------- proc khim::SetSequence {w inputCharacter} { variable inputSequence variable inputMap if { [string length $inputSequence] != 2 } { tk_messageBox \ -message [mc {Composed sequence must be two characters long}] \ -type ok \ -icon error \ -parent $w \ -title [mc {Invalid sequence}] } elseif { [string length $inputCharacter] == 0 } { catch { unset inputMap($inputSequence) } ShowSequences $w } else { set inputMap($inputSequence) $inputCharacter ShowSequences $w $inputSequence } return } #---------------------------------------------------------------------- # # khim::ShowSequences -- # # Updates the listbox in the KHIM configuration dialog with # the currently defined input sequences. # # Parameters: # w -- Path name of the active dialog # inputSequence -- Input sequence that has been changed, if any. # # Results: # None. # # Side effects: # Listbox is updated to reflect change, and the active sequence # is selected. # #---------------------------------------------------------------------- proc khim::ShowSequences {w {inputSequence {}}} { variable inputMap # Remember the scroll position foreach {top bottom} [$w.lf1.lb yview] break # Clear the listbox $w.lf1.lb delete 0 end # Put all the items back in the listbox, in order. # Remember the index of any item that matches the current sequence. foreach key [lsort -dictionary [array names inputMap]] { if { ![string compare $key $inputSequence] } { set idx [$w.lf1.lb index end] } $w.lf1.lb insert end "$key \u2192 $inputMap($key)" } # Select the just-changed item, if any. If there is nothing to select, # simply restore the scroll position. if { [info exists idx] } { $w.lf1.lb selection set $idx $w.lf1.lb see $idx } else { $w.lf1.lb yview moveto $top } return } #---------------------------------------------------------------------- # # khim::Apply -- # # Apply changes from the KHIM configuration dialog. # # Parameters: # w - Path name of the dialog # # Results: # None. # # Side effects: # Current configuration is stored, and bindings to the KHIM # bindtag are applied. # #---------------------------------------------------------------------- proc khim::Apply { w } { variable use variable composeKey variable map variable inputUse variable inputComposeKey variable inputMap set use $inputUse set composeKey $inputComposeKey set map [array get inputMap] RedoBindings return } #---------------------------------------------------------------------- # # khim::OK -- # # Apply changes and dismiss the KHIM configuration dialog. # # Parameters: # w - Path name of the dialog # # Results: # None. # # Side effects: # Current configuration is stored, and bindings to the KHIM # bindtag are applied. The dialog is dismissed. # #---------------------------------------------------------------------- proc khim::OK { w } { Apply $w destroy $w } #---------------------------------------------------------------------- # # khim::HandleDestroy -- # # Clean up from destruction of the KHIM input dialog. # # Parameters: # w - Path name of the destroyed window # t - Path name of the toplevel of the active dialog. # # Results: # None. # # Side effects: # Unsets variables that are used only when the dialog is active. # #---------------------------------------------------------------------- proc khim::HandleDestroy { w t } { if { [string compare $w $t] } return variable inputComposeKey variable inputMap variable inputUse unset inputUse unset inputComposeKey unset inputMap return } #---------------------------------------------------------------------- # # khim::RedoBindings -- # # Establish bindings on the KHIM bindtag according to the current # settings. # # Parameters: # None. # # Results: # None. # # Side effects: # Binds the Compose key to a {break}, the leading character # of each two-character sequence to a break as well, and # the second character of each two character sequence to # insert the mapped character. Arranges so that unrecognized # two-character sequences insert the two individual characters. # #---------------------------------------------------------------------- proc khim::RedoBindings {} { variable use variable composeKey variable map foreach b [bind KHIM] { bind KHIM $b {} } if { $use } { bind KHIM break bind KHIM { khim::CMapInteractor %W } foreach {seq char} $map { set c0 [string map {{ } < } [string index $seq 0]] set c1 [string map {{ } < } [string index $seq 1]] bind KHIM $c0 break bind KHIM $c0 \ [list khim::BadCompose %W [string index $seq 0] %A] bind KHIM $c0$c1 \ [list khim::Insert %W $char]\;break } } return } #---------------------------------------------------------------------- # # khim::BadCompose -- # # Handle an unrecognized key sequence # # Parameters: # w - Focus window # c0 - First character in the sequence # c1 - Second character in the sequence, or an empty string if # there is no second character # # Results: # None # # Side effects: # Inserts the two individual characters into the focus window. # #---------------------------------------------------------------------- proc khim::BadCompose {w c0 c1} { if {$c1 ne {}} { khim::Insert $w $c0 khim::Insert $w $c1 } return -code break } #---------------------------------------------------------------------- # # khim::Insert -- # # Inserts a character into a text or entry. # # Parameters: # w - Window in which to insert # c - Character to insert # # Results: # None. # # Side effects: # Character is inserted. # #---------------------------------------------------------------------- proc khim::Insert {w c} { $w insert insert $c switch -exact -- [winfo class $w] { Entry - TEntry { set c [$w index insert] if {($c < [$w index @0]) || ($c > [$w index @[winfo width $w]])} { $w xview $c } } Text { $w see insert } } } #---------------------------------------------------------------------- # # khim::getConfig -- # # Returns a script that will restore the current KHIM configuration. # # Results: # Returns the script. # #---------------------------------------------------------------------- proc khim::getConfig {} { variable use variable composeKey variable map array set x $map set retval [list khim::setConfig 1.0 $use $composeKey] append retval { } \{ foreach key [lsort -dictionary [array names x]] { append retval \n { } [list $key] { } [ReplaceU $x($key)] } append retval \n\} } #---------------------------------------------------------------------- # # khim::setConfig -- # # Restores the saved configuration from "khim::getConfig" # # Parameters: # version - Version of the configuration command # u - Flag for whether KHIM is enabled # c - Compose key selected # m - Map from compose sequences to characters. # # Results: # None # # Side effects: # Configuration is set. # #---------------------------------------------------------------------- proc khim::setConfig {v u c m args} { variable use variable composeKey variable map switch -exact -- $v { 1.0 { set use $u set composeKey $c set map $m } default { return -code error "Unknown KHIM version $v" } } RedoBindings return } #---------------------------------------------------------------------- # # khim::ReplaceU -- # # Replaces non-ASCII characters in a Unicode string with \u escapes. # # Parameters: # s - String to clean up # # Results: # Returns the cleaned string. # #---------------------------------------------------------------------- proc khim::ReplaceU {string} { set retval {} foreach char [split $string {}] { scan $char %c ccode if { $ccode >= 0x0020 && $ccode < 0x007f && $char ne "\{" && $char ne "\}" && $char ne "\[" && $char ne "\]" && $char ne "\\" && $char ne "\$" } { append retval $char } else { append retval \\u [format %04x $ccode] } } return $retval } #---------------------------------------------------------------------- # # khim::CMapUpdateSpinbox -- # # Variable trace callback that manages the state of the # code page selection spinbox when the code page changes. # # Parameters: # w - Window path name of the character map dialog # args - Extra args from the 'trace' mechanism are not used here. # # Results: # None. # # Side effects: # If the CMapInputCodePage variable contains an invalid code # page number, the background of the spinbox changes to red. # Otherwise, the background of the spinbox changes to white. # The values list of the spinbox is updated to be a list of # the decimal or hexadecimal code page numbers according to # whether the variable's string representation contains # '0x'. # #---------------------------------------------------------------------- proc khim::CMapUpdateSpinbox {w args} { variable CMapInputCodePage variable CMapCodePage set spin $w.spin # Test validity of the code page number if { ![string is integer -strict $CMapInputCodePage($w)] || $CMapInputCodePage($w) < 0 || $CMapInputCodePage($w) >= 0x100 } { #$spin configure -background \#ff6666 } else { # Valid code page - generate the values list. Make sure that # the current value is in the list, even if it's formatted # eccentrically (e.g., 0x000012). #$spin configure -background white if { [string match *0x* $CMapInputCodePage($w)] } { set format 0x%02X } else { set format %d } for { set i 0 } { $i < $CMapInputCodePage($w) } { incr i } { lappend values [format $format $i] } lappend values $CMapInputCodePage($w) for { incr i } { $i < 0x100 } { incr i } { lappend values [format $format $i] } # When we change the values list, the content of the spinbox # appears to be lost; deal with this by saving and restoring it. set cp $CMapInputCodePage($w) set i [$spin index insert] $spin configure -values $values $spin set $cp $spin icursor $i set CMapCodePage($w) $CMapInputCodePage($w) } return } #---------------------------------------------------------------------- # # khim::CMapDrawCanvas -- # # Puts a map of a single Unicode code page into a canvas. # # Parameters: # w -- Path name of the character map dialog # args -- Additional arguments resulting from a 'trace' callback # # Results: # None. # # Side effects: # The given canvas is redrawn with a 16x16 grid of characters. # #---------------------------------------------------------------------- proc khim::CMapDrawCanvas {w args} { variable CMapCodePage variable CMapInputCodePage variable CMapFont variable CMapBadCharFont variable CMapXL variable CMapYL variable CMapSelectedCharacter variable CMapAfter variable CMapForeground if {[info exists CMapAfter($w)]} { after cancel $CMapAfter($w) unset CMapAfter($w) } set c $w.c set pad 2 # Clear the canvas $c delete all set minsize [CMapCellSize $c] # Drop glyphs for all the characters onto the canvas, stacking them # all at (0,0). We'll be sliding them by rows and columns to make the # grid. set rem [expr { $CMapSelectedCharacter($w) % 0x0100 }] set srow [expr { $rem / 16 }] set scol [expr { $rem % 16 }] set tick [clock clicks -milliseconds] set ok 1 for { set row 0 } { $row < 16 } { incr row } { for { set col 0 } { $col < 16 } { incr col } { set point [expr { 256 * $CMapCodePage($w) + 16 * $row + $col }] if { ($ok || ($row == $srow && $col == $scol)) && [ValidChar $point] } { set t [format %c $point] set f $CMapFont } else { set t [format %02X\n%02X \ [expr { $point / 0x100 }] [expr { $point % 0x100 }]] set f $CMapBadCharFont } set tags [list text row$row col$col] $c create text 0 0 -text $t -font $f -fill $CMapForeground\ -anchor center -justify center -tags $tags set tock [clock clicks -milliseconds] if {$ok && $tock-$tick > 1500} { set CMapAfter($w) [after 500 [list khim::CMapDrawCanvas $w]] set ok 0 } } } # Spread out the columns and generate a list of the X co-ordinates # of the spacer lines set xmin [expr {$pad + 1}] set x $xmin set CMapXL($w) [list $x] for { set col 0 } { $col < 16 } { incr col } { foreach { x0 - x1 - } [$c bbox col$col] break set cw [expr { $x1 - $x0 + 5 }] if { $cw < $minsize } { set cw $minsize } set xt [expr { $x + $cw/2 }] set dx [expr { $xt - ( $x0 + $x1 ) / 2 }] $c move col$col $dx 0 incr x $cw lappend CMapXL($w) $x } set xmax $x # Now do the same with the rows set ymin [expr {$pad + 1}] set y $ymin set CMapYL($w) [list $y] for { set row 0 } { $row < 16 } { incr row } { foreach { - y0 - y1 } [$c bbox row$row] break set rh [expr { $y1 - $y0 + 5 }] if { $rh < $minsize } { set rh $minsize } set yt [expr { $y + $rh/2 }] set dy [expr { $yt - ( $y0 + $y1 ) / 2 }] $c move row$row 0 $dy incr y $rh lappend CMapYL($w) $y } set ymax $y # Now that the characters on the grid are properly positioned, draw # the separator lines and configure the canvas size foreach x $CMapXL($w) { $c create line $x $ymin $x $ymax -width 0 -fill $CMapForeground } foreach y $CMapYL($w) { $c create line $xmin $y $xmax $y -width 0 -fill $CMapForeground } $c configure -width [expr { $xmax + $pad }] \ -height [expr { $ymax + $pad }] \ -scrollregion [list 0 0 [expr {$xmax + $pad}] [expr {$ymax + $pad}]] # Change the codepage in the spinbox if { $CMapCodePage($w) != $CMapInputCodePage($w) } { set CMapInputCodePage($w) $CMapCodePage($w) } # Display a selection box ShowSelectedCell $w } #---------------------------------------------------------------------- # # khim::CMapCellSize -- # # Computes the size of one cell in the character map # # Parameters: # c - canvas in which the map will be drawn. # # Results: # Returns the size in pixels of one square cell in the canvas. # #---------------------------------------------------------------------- proc khim::CMapCellSize {c} { variable CMapFont variable CMapBadCharFont # Compute the minimum linear dimension of one box in the grid. # It is at least 5 pxl greater than # - the linespace of the display font # - 2-line space in the "bad character" font # - one em in the display font # - two digit widths in the "bad character" font set minsize \ [expr { [font metrics $CMapFont -displayof $c -linespace] + 5 }] set minsize2 [expr { 2 * [font metrics $CMapBadCharFont \ -displayof $c -linespace] + 5 }] if { $minsize2 > $minsize } { set minsize $minsize2 } set minsize2 [expr { [font measure $CMapFont -displayof $c M] + 5 }] if { $minsize2 > $minsize } { set minsize $minsize2 } set minsize2 [expr { [font measure $CMapBadCharFont -displayof $c 00] + 5 }] if { $minsize2 > $minsize } { set minsize $minsize2 } return $minsize } #---------------------------------------------------------------------- # # khim::ShowSelectedCell -- # # Paints a border around the cell in the KHIM character map # corresponding to the selected character # # Parameters: # w - Path name of the character map # # Results: # None. # #---------------------------------------------------------------------- proc khim::ShowSelectedCell {w} { variable CMapCodePage variable CMapSelectedCharacter variable CMapXL variable CMapYL variable CMapForeground variable CMapSelectBackground variable CMapSelectForeground if { $CMapSelectedCharacter($w) < $CMapCodePage($w) * 0x0100 || $CMapSelectedCharacter($w) >= ($CMapCodePage($w) + 1) * 0x100 } { set CMapSelectedCharacter($w) \ [expr { ($CMapSelectedCharacter($w) % 0x100) + (0x100 * $CMapCodePage($w)) }] } set c $w.c set rem [expr { $CMapSelectedCharacter($w) % 0x0100 }] set row [expr { $rem / 16 }] set col [expr { $rem % 16 }] $c itemconfigure text -fill $CMapForeground $c itemconfigure text&&row$row&&col$col -fill $CMapSelectForeground set xmin [lindex $CMapXL($w) $col] incr col set xmax [lindex $CMapXL($w) $col] set ymin [lindex $CMapYL($w) $row] incr row set ymax [lindex $CMapYL($w) $row] catch { $c delete selectrect } $c create rectangle $xmin $ymin $xmax $ymax \ -width 2 -fill $CMapSelectBackground \ -outline $CMapSelectBackground -tags selectrect $c lower selectrect return } #---------------------------------------------------------------------- # # khim::CMapSelectedCharacter -- # # Given X and Y co-ordinates in the character map, determines # what character is selected. # # Parameters: # c - The canvas displaying the map. # # Results: # Returns the character, or an empty string if the co-ordinates # do not designate a cell. # #---------------------------------------------------------------------- proc khim::CMapSelectedCharacter {w x y} { variable CMapCodePage variable CMapXL variable CMapYL set row [BSearch $CMapYL($w) $y] set col [BSearch $CMapXL($w) $x] if { $row >= 0 && $row <= 15 && $col >= 0 && $col <= 15 } { return [format %c [expr { 0x100 * $CMapCodePage($w) + 0x10 * $row + $col }]] } else { return {} } } #---------------------------------------------------------------------- # # khim::CMapSelect -- # # Handles mouse selection in the KHIM color map # # Parameters: # c - Path name of the canvas # x, y - Mouse coordinates relative to the canvas # # Results: # None # # Side effects: # Character in the cell containing the pointer is selected, and # the display of the selection is updated. # #---------------------------------------------------------------------- proc khim::CMapSelect {c x y} { variable CMapSelectedCharacter set w [khim::CMapCanvToDialog $c] set ch [khim::CMapSelectedCharacter $w $x $y] if { $ch ne {} } { scan $ch %c CMapSelectedCharacter($w) } ShowSelectedCell $w return } #---------------------------------------------------------------------- # # khim::CMapActivate -- # # Activates the KHIM character map after a mouse selection. # # Parameters: # c - Path name of the canvas # x, y - Mouse coordinates relative to the canvas # # Results: # None # # Side effects: # Directs focus to the canvas, and selects the character designated # by the pointer. # #---------------------------------------------------------------------- proc khim::CMapActivate {c x y} { focus $c khim::CMapSelect $c $x $y return } #---------------------------------------------------------------------- # # khim::CMapHomeEnd -- # # Handles the Home and End keys in the KHIM character map # # Parameters: # c - Path name of the canvas # unit - Unit being homed (word, page, file) # key - 1 for End, 0 for Home # # Results: # None. # # Side effects: # Moves the selection according to the key pressed. # #---------------------------------------------------------------------- proc khim::CMapHome {c unit key} { variable CMapSelectedCharacter set w [khim::CMapCanvToDialog $c] set sc [expr { $unit * ($CMapSelectedCharacter($w) / $unit) + $key * ($unit - 1) }] khim::CMapMoveTo $c $sc return } #---------------------------------------------------------------------- # # khim::CMapMove -- # # Handles several cursor keys (Left, Right, Up, Down, PgUp, # PgDn) in the KHIM character map. # # Parameters: # c - Path name of the canvas # delta - Number of code points to move # # Results: # None. # # Side effects; # Moves the selection by the designated number of codepoints. # #---------------------------------------------------------------------- proc khim::CMapMove {c delta} { variable CMapSelectedCharacter set w [khim::CMapCanvToDialog $c] set sc [expr { $CMapSelectedCharacter($w) + $delta }] if { $sc < 0 } { set sc 0 } elseif { $sc > 0xffff } { set sc 0xffff } khim::CMapMoveTo $c $sc return } #---------------------------------------------------------------------- # # khim:CMapMoveTo -- # # Changes the selection in the KHIM character map to a specified # codepoint. # # Parameters: # c - Path name of the canvas # sc - Code point to select, expressed as an integer # # Results: # None # # Side effects: # Moves the selection to the given character. # #---------------------------------------------------------------------- proc khim::CMapMoveTo { c sc } { variable CMapSelectedCharacter variable CMapCodePage set w [khim::CMapCanvToDialog $c] set cp [expr { $sc / 0x0100 }] set CMapSelectedCharacter($w) $sc if { $cp != $CMapCodePage($w) } { set CMapCodePage($w) $cp } else { ShowSelectedCell $w } return } #---------------------------------------------------------------------- # # CMapKey -- # # Handles non-cursor keypresses in the KHIM character map # # Parameters: # c - Path name of the canvas # char - Character sent by the key # # Results: # None. # # Side effects: # Selects the given character # #---------------------------------------------------------------------- proc khim::CMapKey {c char} { if {$char eq {}} return; # If the key doesn't generate a char, # ignore it. scan $char %c sc CMapMoveTo $c $sc return } #---------------------------------------------------------------------- # # khim::CMapWheel -- # # Handles the mousewheel in the KHIM character map # # Parameters: # c - Path name of the canvas # delta - Amount by which the canvas is to move. # # Return value: # None. # # Side effects: # Adjusts the selection by an appropriately scaled version of 'delta' # #---------------------------------------------------------------------- proc khim::CMapWheel { c delta shifted } { # the delta will vary for OS X and X11/Win32, but we only check # + or - and move accordingly if {$delta > 0} { khim::CMapMove $c [expr {$shifted ? -1 : -16}] } else { khim::CMapMove $c [expr {$shifted ? 1 : 16}] } return } #---------------------------------------------------------------------- # # khim::CMapCanvToDialog -- # # Locates the KHIM character map dialog given the widget path # name of the canvas. # # Parameters: # c - Path name of the canvas # # Results: # Returns the path name of the dialog. # #---------------------------------------------------------------------- proc khim::CMapCanvToDialog {c} { return [winfo parent $c] } #---------------------------------------------------------------------- # # khim::CMapInteractor -- # # Posts the KHIM character map for interacting with the user. # # Parameters: # w - Path name of the text or canvas widget to which the # interactor applies. # # Results: # None. # # Side effects: # Interactor is posted, and the event loop is entered recursively # to handle it. On return, any requested symbol insertion has # already been done. # #---------------------------------------------------------------------- proc khim::CMapInteractor {w} { variable CMapSelectedCharacter variable CMapInputCodePage variable CMapCodePage variable CMapFocus variable CMapBackground variable CMapForeground variable CMapSelectBackground variable CMapSelectForeground set t [winfo toplevel $w] if { $t eq "." } { set t {} } set map $t.khimcmap if {[winfo exists $map]} { wm deiconify $map return } toplevel $map wm withdraw $map wm title $map [mc {Insert Character}] if { ![info exists CMapInputCodePage($map)] } { set CMapInputCodePage($map) 0 set CMapCodePage($map) 0 } grid [label $map.l1 -text [mc {Select code page:}]] \ -row 0 -column 0 -sticky e grid [spinbox $map.spin -textvariable khim::CMapInputCodePage($map) \ -width 4] \ -row 0 -column 1 -sticky w # Get canvas background from spinbox background set CMapBackground [lindex [$map.spin configure -background] 4] # Get text foreground and grid lines color from spinbox text foreground set CMapForeground [lindex [$map.spin configure -foreground] 4] # Get rectangle outline from spinbox selectbackground set CMapSelectBackground [lindex [$map.spin configure -selectbackground] 4] set CMapSelectForeground [lindex [$map.spin configure -selectforeground] 4] set c $map.c grid [canvas $c -width 400 -height 400 -bg $CMapBackground -takefocus 1] \ -columnspan 2 -padx 3 -pady 3 grid [frame $map.f] -row 2 -column 0 -columnspan 2 -sticky ew -pady 3 button $map.f.b1 -text [mc OK] -command [list khim::CMapOK $map] button $map.f.b2 -text [mc Cancel] -command [list khim::CMapCancel $map] button $map.f.b3 -text [mc Help...] \ -command [list khim::showHelp $map.help] grid $map.f.b1 -row 0 -column 0 -sticky ew -padx 5 grid $map.f.b2 -row 0 -column 1 -sticky ew -padx 5 grid $map.f.b3 -row 0 -column 3 -sticky ew -padx 5 grid columnconfigure $map.f 2 -weight 1 grid columnconfigure $map.f {0 1 3} -uniform A grid columnconfigure $map 1 -weight 1 bindtags $c [list $c khim::cmap Canvas [winfo toplevel $c] all] trace add variable ::khim::CMapInputCodePage($map) write \ [list khim::CMapUpdateSpinbox $map] after idle [list khim::CMapUpdateSpinbox $map] trace add variable ::khim::CMapCodePage($map) write \ [list khim::CMapDrawCanvas $map] if { ![info exists CMapSelectedCharacter($map)] } { set CMapSelectedCharacter($map) 0x0000 } set CMapFocus($map) $w CMapDrawCanvas $map wm deiconify $map bind $map [list grab $map] bind $map.c [list focus %W] tkwait window $map catch { destroy $map } focus $w return } #---------------------------------------------------------------------- # # khim::CMapCopypastedismiss -- # # Handles double-click in the KHIM character map. # # Parameters: # c - Path name of the canvas # x,y - Mouse co-ordinates of the double click # # Results: # None. # # Side effects: # Copies the designated character into the text or entry # that KHIM is using, and dismisses the widget. # #---------------------------------------------------------------------- proc khim::CMapCopypastedismiss {c x y} { CMapSelect $c $x $y CMapOK $c return } #---------------------------------------------------------------------- # # khim::CMapOK # # Handles the 'OK' button in the KHIM character map. # # Parameters: # w - Path name of the dialog # # Results: # None. # # Side effects: # Copies the selected character into the text or entry # that KHIM is using, and dismisses the widget. # #---------------------------------------------------------------------- proc khim::CMapOK {w} { CMapCopy $w CMapPasteToFocus $w CMapCancel $w return } #---------------------------------------------------------------------- # # khim::CMapCopy -- # # Copies a character from the KHIM character map onto the # clipboard. # # Parameters: # w - Path name of the dialog. # # Results: # None. # # Side efffects: # Copies the selected character to the clipboard. # #---------------------------------------------------------------------- proc khim::CMapCopy {w} { variable CMapSelectedCharacter clipboard clear -displayof $w upvar 0 CMapSelectedCharacter([winfo toplevel $w]) ch if { [info exists ch] && $ch ne {} } { clipboard append -displayof $w -- [format %c $ch] } return } #---------------------------------------------------------------------- # # khim::CMapPasteToFocus -- # # Sends a <> event into the window on whose behalf # the KHIM character map was invoked, to copy a character selection # into it. # # Parameters: # w - Path name of the character map dialog. # # Results: # None. # # Side effects: # <> is generated. # #---------------------------------------------------------------------- proc khim::CMapPasteToFocus {w} { variable CMapFocus event generate $CMapFocus([winfo toplevel $w]) <> return } #---------------------------------------------------------------------- # # khim::CMapCancel -- # # Handles the 'Cancel' button in the KHIM character map. # # Parameters: # w - Path name of the character map dialog. # # Results: # None. # # Side effects: # Destroys the dialog without taking further action. # #---------------------------------------------------------------------- proc khim::CMapCancel {w} { destroy [winfo toplevel $w] } #---------------------------------------------------------------------- # # khim::CMapDestroy -- # # Handles the notification in the KHIM character map # # Parameters: # c - Path name of the character map canvas # # Results: # None. # # Side effects: # Cleans up memory for the destroyed widget. # #---------------------------------------------------------------------- proc khim::CMapDestroy {c} { variable CMapFocus variable CMapAfter variable CMapXL variable CMapYL set w [winfo toplevel $c] if {[info exists CMapAfter($w)]} { after cancel $CMapAfter($w) unset CMapAfter($w) } catch {unset CMapFocus($w)} catch {unset CMapXL($w)} catch {unset CMapYL($w)} return } # Bindings for the "khim::cmap" bindtag that is used in the character map # dialog bind khim::cmap <1> {khim::CMapSelect %W %x %y} bind khim::cmap {khim::CMapCopypastedismiss %W %x %y} bind khim::cmap {khim::CMapSelect %W %x %y} bind khim::cmap {khim::CMapActivate %W %x %y} bind khim::cmap {khim::CMapMove %W -16; break} bind khim::cmap {khim::CMapMove %W -1; break} bind khim::cmap {khim::CMapMove %W 1; break} bind khim::cmap {khim::CMapMove %W 16; break} bind khim::cmap {khim::CMapMove %W 0x100; break} bind khim::cmap {khim::CMapMove %W -0x100; break} bind khim::cmap {khim::CMapMoveTo %W 0x0000; break} bind khim::cmap {khim::CMapMoveTo %W 0xffff; break} bind khim::cmap {khim::CMapHome %W 0x0100 0; break} bind khim::cmap {khim::CMapHome %W 0x0100 1; break} bind khim::cmap {khim::CMapHome %W 0x010 0; break} bind khim::cmap {khim::CMapHome %W 0x010 1; break} bind khim::cmap {khim::CMapKey %W %A} bind khim::cmap <> {khim::CMapCopy %W} bind khim::cmap <> {khim::CMapCopy %W} bind khim::cmap {khim::CMapOK %W} bind khim::cmap {khim::CMapOK %W} bind khim::cmap {khim::CMapCancel %W} bind khim::cmap {khim::CMapWheel %W %D 0; break} bind khim::cmap {khim::CMapWheel %W %D 1; break} bind khim::cmap {tk::TabToWindow [tk_focusNext %W]; break} bind khim::cmap <> {tk::TabToWindow [tk_focusPrev %W]; break} if { [string equal "x11" [tk windowingsystem]] } { bind khim::cmap <4> {khim::CMapWheel %W 120 0; break} bind khim::cmap <5> {khim::CMapWheel %W -120 0; break} bind khim::cmap {khim::CMapWheel %W 120 1; break} bind khim::cmap {khim::CMapWheel %W -120 1; break} } bind khim::cmap {khim::CMapDestroy %W} # Set initial default configuration khim::setConfig 1.0 1 Pause { !! \u00a1 {"A} \u00c4 {"a} \u00e4 {"E} \u00cb {"e} \u00eb {"I} \u00cf {"i} \u00ef {"O} \u00d6 {"o} \u00f6 {"U} \u00dc {"u} \u00fc 'A \u00c1 'a \u00e1 'E \u00c9 'e \u00e9 'I \u00cd 'i \u00ed 'O \u00d3 'o \u00f3 'U \u00da 'u \u00fa 'Y \u00dd 'y \u00fd *A \u00c5 *a \u00e5 ,C \u00c7 ,c \u00e7 -> \u2192 -L \u0141 -l \u0142 /O \u00d8 /o \u00f8 12 \u00bd 13 \u2153 14 \u00bc 18 \u215b 23 \u2154 34 \u00be 38 \u215c 58 \u215d 78 \u215e :( \u2639 :) \u263a <- \u2190 << \u00ab >> \u00bb ?? \u00bf ^A \u00c2 ^a \u00e2 ^E \u00ca ^e \u00ea ^I \u00ce ^i \u00ee ^O \u00d4 ^o \u00f4 ^U \u00db ^u \u00fb `A \u00c0 `a \u00e0 `E \u00c8 `e \u00e8 `I \u00cc `i \u00ec `O \u00d2 `o \u00f2 `U \u00d9 `u \u00f9 AA \u00c5 aa \u00e5 AE \u00c6 ae \u00e6 bu \u2022 de \u00b0 eu \u20ac LP \u2615 mu \u00b5 OE \u0152 oe \u0153 OC \u00a9 OR \u00ae ss \u00df |c \u00a2 ~A \u00c3 ~a \u00e3 ~N \u00d1 ~n \u00f1 ~O \u00d5 ~o \u00f5 } # Set initial bindings on the KHIM bind tag. khim::RedoBindings set khim::CMapFont [font create -family helvetica -size 15] set khim::CMapBadCharFont [font create -family courier -size 8] # Test program if {[info exists ::argv0] && ![string compare $::argv0 [info script]]} { grid [entry .e -font {Courier 18}] -columnspan 5 -sticky ew .e insert end {Type here} bindtags .e {.e KHIM Entry . all} grid [button .test -text "Test" -command "khim::getOptions .khim"] \ [button .bload -text "Load config" -command "testLoadConfig"] \ [button .bsave -text "Save config" -command "testSaveConfig"] \ [button .bhelp -text "Help" -command "khim::showHelp .help"] \ [button .bquit -text "Quit" -command "exit"] \ -padx 5 -pady 5 proc testLoadConfig {} { source ~/.khimrc } proc testSaveConfig {} { set f [open ~/.khimrc w] puts $f [khim::getConfig] close $f } } tkabber-plugins-0.11.1/tkabber-khim/khim/pkgIndex.tcl0000644000175000017500000000102610541267402021746 0ustar sergeisergei# Tcl package index file, version 1.1 # This file is generated by the "pkg_mkIndex" command # and sourced either when an application starts up or # by a "package unknown" script. It invokes the # "package ifneeded" command to set up package-related # information so that packages will be loaded automatically # in response to "package require" commands. When this # script is sourced, the variable $dir must contain the # full path name of this file's directory. package ifneeded khim 1.0.1 [list source [file join $dir khim.tcl]] tkabber-plugins-0.11.1/tkabber-khim/khim/de.msg0000644000175000017500000001044010540047772020576 0ustar sergeisergei# de.msg -- # # German-language messages for KHIM # # Copyright (c) 2006 by Andreas Kupries. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: de.msg 826 2006-12-13 19:09:46Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/de.msg,v $ # #---------------------------------------------------------------------- namespace eval ::khim { ::msgcat::mcset de HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM ermöglicht die Eingabe von internationalen Zeichen mittels einer Tastatur, welches diese nicht direkt unterstützt. Es ist unabhängig von allen Eingabemethoden, welche vom Betriebssystem bereitgestellt werden (könnten), und für den Fall gedacht, wenn der Anwender keine Kontrolle über die Tastatur hat und dennoch Text in anderen Sprachen eingeben muß. Um KHIM zu benutzen, ist es notwendig, den KHIM Steuer-Dialog zu öffnen (dies ist abhängig von der Anwendung) und dann KHIM durch 'ticken' der 'Benutze KHIM'-Checkbox zu aktivieren. Es ist weiterhin notwendig, eine Taste als die Kombinier-Taste zu wählen. Die gewählte Taste sollte im Normalgebrauch selten genutzt werden. Die Auswahl selbst besteht aus zwei Schritten. Zuerst muß der Knopf "Kombinier-Taste:" gedrückt werden, dann die gewünschte Taste. Allgemein gesprochen, wenn die benutzte Tastatur eine Taste "Compose" besitzt, dann sollte diese _nicht_ als die Kombinier-Taste für KHIM gewählt werden. Dies stellt sicher, das diese Taste weiterhin vom Betriebssystem genutzt werden kann, um dessen eventuelle Eingabemethoden zu aktivieren. Sobald KHIM aktiviert wurde, können in jedem Widget, welches für die Benutzung von KHIM konfiguriert wurde, internationale Zeichen eingegeben werden. Dies geschieht durch Drücken der gewählten Kombinier-Taste, gefolgt von zwei weiteren Zeichen, welche das gewünschte Zeichen identifizieren. Der KHIM Steuer-Dialog stellt eine Liste der bekannten Zeichenfolgen zur Verfügung. Zusätzlich ist es möglich einen Dialog zu öffnen, welcher die Auswahl beliebiger Zeichen in einer Tabelle erlaubt. Dies geschieht durch zweimaliges Drücken der Kombinier-Taste. Navigation in der Tabelle geschieht mit der Maus oder den Kursor-Tasten. Das einzufügende Zeichen kann mit Doppel-Klick gewählt werden, durch Drücken der Leer-Taste, oder durch Drücken der Enter- (oder Return-)Taste. Es ist auch möglich, die Liste der direkt anwählbären Zeichen zu erweitern. Dies geschieht im KHIM Steuer-Dialog durch Eingabe der zwei Zeichen für den Kode im Eingabefeld "Eingabezeichenfolge", des gewünschten Zeichens im Feld "Zeichen", gefolgt vom Drücken des Knopfes "Ändern". (Bezüglich der Herkunft des gewünschten Zeichens: Es kann aus einer anderen Anwendung kopiert werden, oder man benutze den Knopf "Unicode..." (oder drücke die Kombinier-Taste zweimal), um es aus der Tabelle aller Zeichen auszuwählen.) Eine Zeichenfolge wird gelöscht durch Auswahl der Folge in der Liste aller Zeichenfolgen, gefolgt von der Lösch/Entferne-Taste. } ::msgcat::mcset de {SELECT COMPOSE KEY} [string map [list \n\t \n] { Bitte drücken Sie die Taste, welche Sie als Kombinier-Taste verwenden wollen. }] ::msgcat::mcset de {Apply} {Anwenden} ::msgcat::mcset de {Cancel} {Abbrechen} ::msgcat::mcset de {Change} {Ändern} ::msgcat::mcset de {Character} {Zeichen} ::msgcat::mcset de {Compose Key} {Kombinier-Taste} ::msgcat::mcset de {Compose key:} {Kombinier-Taste:} ::msgcat::mcset de {Composed sequence must be two characters long} \ {Die Eingabezeichenfolge muß aus zwei Zeichen bestehen} ::msgcat::mcset de {Delete} {Löschen} ::msgcat::mcset de {Help...} {Hilfe...} ::msgcat::mcset de {Input key sequence} {Eingabezeichenfolge} ::msgcat::mcset de {Insert Character} {Zeichen einfügen} ::msgcat::mcset de {Invalid sequence} {Ungültige Zeichenfolge} ::msgcat::mcset de {Key sequences} {Zeichenfolgen} ::msgcat::mcset de {KHIM Controls} {KHIM Steuerung} ::msgcat::mcset de {OK} {OK} ::msgcat::mcset de {Select code page:} {Wähle Code-Seite:} ::msgcat::mcset de {Unicode...} {Unicode...} ::msgcat::mcset de {Use KHIM} {Benutze KHIM} } # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/khim/ru.msg0000644000175000017500000001472010546743545020650 0ustar sergeisergei# ru.msg -- # # Russian-language messages for KHIM # # Contributed by Konstantin Khomoutov . # Proof-read and edited by Serge Yudin . # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: ru.msg 858 2007-01-03 15:10:29Z sergei $ # $Source$ # #---------------------------------------------------------------------- namespace eval ::khim { # If you edit HELPTEXT or {SELECT COMPOSE KEY}, also edit the corresponding # messages in ROOT.msg ::msgcat::mcset ru HELPTEXT { Kevin's Hacky Input Method (KHIM) -- Нетривиальный Метод Кевина для Ввода Символов KHIM делает возможным ввод символов национальных алфавитов с клавиатуры, которая не позволяют этого делать. Он работает независимо от любых способов ввода, которые поддерживает ОС; его задача -- позволить осуществлять ввод таких символов, которые невозможно ввести с текущими настройками ОС данного компьютера, а менять их нет возможности или желания. Для того, чтобы использовать KHIM, следует вызвать диалог "Настройки KHIM" (как это сделать, зависит от приложения, использующего KHIM) и разрешить работу KHIM, включив переключатель "Использовать KHIM". Также Вам понадобится выбрать редко используемую клавишу на Вашей клавиатуре и назначить её "клавишей композиции". Для этого нужно нажать кнопку, подписанную "Клавиша композиции:", в диалоге настроек KHIM и затем нажать выбранную клавишу на клавиатуре. Имейте в виду, что если на Вашей клавиатуре есть клавиша, называемая "Compose", то её не следует выбирать в качестве клавиши композиции для KHIM -- пусть она продолжает вызывать тот метод ввода, который назначен ей операционной системой. После того как KHIM активирован, Вы можете вставлять символы национальных алфавитов в любое поле ввода, настроенное на использование KHIM, таким образом: нажать и отпустить клавишу композиции, затем ввести два символа -- "входную последовательность". В диалоге настроек KHIM есть окно со списком доступных последовательностей. Кроме того, двойное нажатие клавиши композиции вызывает окно диалога, позволяющее выбрать произвольный символ Unicode. Выбор нужного символа в этом диалоге осуществляется мышью либо клавишами управления курсором, а вставка выбранного символа -- двойным щелчком левой кнопки мыши на нём, либо нажатием клавиши Пробел или Ввод. Чтобы создать новую входную последовательность для использования совместно с клавишей композиции окройте диалог настроек KHIM, введите два символа в поле "Входная последовательность" и соответствующий ей символ в поле "Символ", затем нажмите кнопку "Изменить". (Вы можете копировать и вставлять целевой символ из другого приложения. Также можно воспользоваться встроенным в KHIM диалогом выбора символов Unicode, нажав кнопку "Unicode..." или дважды нажав клавишу композиции.) Для удаления входной последовательности выберите её в списке и дажмите "Удалить". } ::msgcat::mcset ru {SELECT COMPOSE KEY} [string map [list \n\t \n] { Нажмите клавишу, которую вы хотите использовать в качестве "Клавиши композиции" }] ::msgcat::mcset ru {Apply} {Применить} ::msgcat::mcset ru {Cancel} {Отменить} ::msgcat::mcset ru {Change} {Изменить} ::msgcat::mcset ru {Character} {Символ} ::msgcat::mcset ru {Compose Key} {Клавиша композиции} ::msgcat::mcset ru {Compose key:} {Клавиша композиции:} ::msgcat::mcset ru {Composed sequence must be two characters long} \ {Входная последовательность должна состоять из двух символов} ::msgcat::mcset ru {Delete} {Удалить} ::msgcat::mcset ru {KHIM Help} {Справка по KHIM} ::msgcat::mcset ru {Help...} {Справка...} ::msgcat::mcset ru {Input key sequence} {Входная последовательность} ::msgcat::mcset ru {Insert Character} {Выберите символ} ::msgcat::mcset ru {Invalid sequence} {Неправильная комбинация} ::msgcat::mcset ru {Key sequences} {Комбинации клавиш} ::msgcat::mcset ru {KHIM Controls} {Настройки KHIM} ::msgcat::mcset ru {OK} {OK} ::msgcat::mcset ru {Select code page:} {Выберите страницу кодов:} ::msgcat::mcset ru {Unicode...} {Unicode...} ::msgcat::mcset ru {Use KHIM} {Использовать KHIM} } # vim:ft=tcl:ts=8:sw=4:sts=4:noet # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/khim/uk.msg0000644000175000017500000001433110545202730020620 0ustar sergeisergei# uk.msg -- # # Ukrainian-language messages for KHIM # # Contributed by Fixer jabber:, email:. # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # #---------------------------------------------------------------------- namespace eval ::khim { # If you edit HELPTEXT or {SELECT COMPOSE KEY}, also edit the corresponding # messages in ROOT.msg ::msgcat::mcset uk HELPTEXT { Kevin's Hacky Input Method (KHIM) -- Нетривіальний Метод Кевіна для Введення Символів KHIM дає можливість вводити символи національних алфавітів з клавіатури, яка не дозволяє цього робити. Він працює незалежно від інших способів вводу, котрі підтримує ОС; його завдання -- дати змогу здійснювати введення таких символів, котрі неможливо ввести з теперішніми налаштуваннями ОС даного компьютера, а поміняти їх немає ні можливості, ні бажання. Для того, щоб користуватися KHIM, треба відкрити діалог "Налаштування KHIM" (як це зробити, залежить від програми, яка використовує KHIM) і дозволити роботу KHIM, увімкнувши перемикач "Використовувати KHIM". Також Вам необхідно обрати рідко використовувану клавішу на Вашій клавіатурі і призначити її "клавішою композиції". Для цього потрібно натиснути кнопку, підписану як "Клавіша композиції:", у діалозі налаштувань KHIM, а потім натиснути обрану клавішу на клавіатурі. Майте на увазі, що якшо на Вашій клавіатурі є клавіша, що зветься "Compose", то її не треба обирати в якості клавіши композиції для KHIM -- хай вона продовжує викликати той метод вводу, котрий призначений їй операційною системою. Після того як KHIM активувався, Ви можете вставляти символи національних алфавітів в будь-яке поле для вводу, налаштоване на використання KHIM, таким чином: натиснути і відпустити клавішу композиції, а потім ввести два символи -- "вхідну послідовність". У діалозі налаштувань KHIM є вікно з переліком доступних послідовностей. Крім того, подвійне натискання клавіші композиції викликає вікно діалогу, що дозволяє обрати довільний символ Unicode. Вибір потрібного символу в цьому діалозі здійснюється мишою чи клавішами управління курсором, а вставляння обраного симолу -- подвійним клацанням лівої кнопки миші на ньому, або натисканням клавіши Пробіл чи Ввід. Щоб створити нову вхідну послідовність для використання сумісно з клавішою композиції відкрийте діалог налаштувань KHIM, введіть два символи в поле "Вхідна послідовність" і відповідний їй символ у полі "Символ", а потім натисніть клавішу "Змінити". (Ви можете копіювати і вставляти цільовий символ з іншої програми. Також можна скористатися вбудованим у KHIM діалогом вибору символів Unicode, натиснувши кнопку "Unicode...", або подвійно клацнувши клавішу композиції.) Для видалення вхідної послідовності оберіть її у переліку і натисніть "Видалити." } ::msgcat::mcset uk {SELECT COMPOSE KEY} [string map [list \n\t \n] { Натисніть клавішу, котру ви бажаєте використовувати в якості "Клавіші композиції" }] ::msgcat::mcset uk {Apply} {Прийняти} ::msgcat::mcset uk {Cancel} {Відмінити} ::msgcat::mcset uk {Change} {Змінити} ::msgcat::mcset uk {Character} {Символ} ::msgcat::mcset uk {Compose Key} {Клавіша композиції} ::msgcat::mcset uk {Compose key:} {Клавіша композиції:} ::msgcat::mcset uk {Composed sequence must be two characters long} \ {Вхідна послідовність повинна складатися з двох символів} ::msgcat::mcset uk {Delete} {Видалити} ::msgcat::mcset uk {KHIM Help} {Допомога по KHIM} ::msgcat::mcset uk {Help...} {Допомога...} ::msgcat::mcset uk {Input key sequence} {Вхідна послідовність} ::msgcat::mcset uk {Insert Character} {Оберіть символ} ::msgcat::mcset uk {Invalid sequence} {Неправильна комбінація} ::msgcat::mcset uk {Key sequences} {Комбінації клавіш} ::msgcat::mcset uk {KHIM Controls} {Налаштування KHIM} ::msgcat::mcset uk {OK} {OK} ::msgcat::mcset uk {Select code page:} {Оберіть кодову сторінку:} ::msgcat::mcset uk {Unicode...} {Unicode...} ::msgcat::mcset uk {Use KHIM} {Використовувати KHIM} } # vim:ft=tcl:ts=8:sw=4:sts=4:noet # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/khim/en.msg0000644000175000017500000000746510540047772020625 0ustar sergeisergei# en.msg -- # # English-language messages for KHIM # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: en.msg 826 2006-12-13 19:09:46Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/en.msg,v $ # #---------------------------------------------------------------------- namespace eval ::khim { # If you edit HELPTEXT or {SELECT COMPOSE KEY}, also edit the corresponding # messages in ROOT.msg ::msgcat::mcset en HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM allows you to input international characters from a keyboard that doesn't support them. It works independently of any input method that the operating system may supply; it is intended for when you don't have control over your keyboard mapping and still need to input text in other languages. To use KHIM, bring up the KHIM Controls (the way this is done depends on your application) and enable KHIM by checking "Use KHIM". You also need to choose a key on your keyboard that is seldom used, and designate it as the "Compose" key by pressing the button labelled, "Compose key:" then striking the key you wish to designate. Generally speaking, this key should not be the key designated as "Compose" on the keyboard; that key will continue to invoke whatever input method the local operating system supplies. Once KHIM is enabled, you can enter international characters in any widget that is configured to use KHIM by pressing the Compose key followed by a two-character sequence. The listbox in the KHIM controls shows the available sequences. In addition, if you strike the Compose key twice, you get a dialog that allows you to input arbitrary symbols from a Unicode character map. In the map, you can navigate among the characters using either the cursor keys or the mouse, and you can select the current character for insertion by double-clicking it, pressing the space bar, or pressing the Enter (or Return) key. To define a new sequence for use with the Compose key, bring up the KHIM controls, enter the two characters in the "Input key sequence" entry and the desired character to insert into the "Character" entry, and press "Change". (You may copy and paste the character from another application, or use the "Unicode..." button (or press the Compose key twice) to select the character from a map of all available Unicode code points.) To remove a sequence, select it in the listbox and press "Delete". } ::msgcat::mcset en {SELECT COMPOSE KEY} [string map [list \n\t \n] { Please press the key that you want to use as the "Compose" key. }] ::msgcat::mcset en {Apply} {Apply} ::msgcat::mcset en {Cancel} {Cancel} ::msgcat::mcset en {Change} {Change} ::msgcat::mcset en {Character} {Character} ::msgcat::mcset en {Compose Key} {Compose Key} ::msgcat::mcset en {Compose key:} {Compose key:} ::msgcat::mcset en {Composed sequence must be two characters long} \ {Composed sequence must be two characters long} ::msgcat::mcset en {Delete} {Delete} ::msgcat::mcset en {KHIM Help} {KHIM Help} ::msgcat::mcset en {Help...} {Help...} ::msgcat::mcset en {Input key sequence} {Input key sequence} ::msgcat::mcset en {Insert Character} {Insert Character} ::msgcat::mcset en {Invalid sequence} {Invalid sequence} ::msgcat::mcset en {Key sequences} {Key sequences} ::msgcat::mcset en {KHIM Controls} {KHIM Controls} ::msgcat::mcset en {OK} {OK} ::msgcat::mcset en {Select code page:} {Select code page:} ::msgcat::mcset en {Unicode...} {Unicode...} ::msgcat::mcset en {Use KHIM} {Use KHIM} } # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/khim/da.msg0000644000175000017500000000715510540047772020603 0ustar sergeisergei# da.msg -- # # Danish-language messages for KHIM # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # Translation by Torsten Berg # # Refer to the file "license.terms" for the terms and conditions of # use and redistribution of this file, and a DISCLAIMER OF ALL WARRANTEES. # # $Id: da.msg 826 2006-12-13 19:09:46Z sergei $ # $Source: /cvsroot/tcllib/tklib/modules/khim/da.msg,v $ # #---------------------------------------------------------------------- namespace eval ::khim { ::msgcat::mcset da {Apply} {Anvend} ::msgcat::mcset da {Cancel} {Annuller} ::msgcat::mcset da {Change} {ndre} ::msgcat::mcset da {Character} {Tegn} ::msgcat::mcset da {Compose Key} {Compose taste} ::msgcat::mcset da {Compose key:} {Compose taste:} ::msgcat::mcset da {Composed sequence must be two characters long} \ {Compose tegnflgen skal best af to tegn} ::msgcat::mcset da {Delete} {Slet} ::msgcat::mcset da {Help...} {Hjlp...} ::msgcat::mcset da HELPTEXT { Kevin's Hacky Input Method (KHIM) KHIM gr det muligt at indtaste internationale tegn med et tastatur som ikke understtter disse. Dette fungerer uafhngigt af en bestende indtast metode som styresystemet mtte understtte. Det er tnkt til at hjlpe, hvis du ikke har kontrol over tilordningen p dit tastatur og dog har brug for at indtaste tekst i andre sprog. For at benytte KHIM, vis kontrolpanelet (hvordan det gres, afhnger af dit program) og aktiver KHIM ved at afkrydse "Benyt KHIM". Du skal vlge en taste der kun sjldent benyttes p dit tastatur og fastlgge denne som "Compose" taste for at stte tegn sammen med. Tryk dertil p knappen markeret med "Compose taste:" og tryk derefter p den taste du nsker at fastlgge. Generellt skulle det ikke vre den taste som normalt benyttes til at konstruere tegn med; denne taste vil fortsat oprbe din lokale systems indtast metode. Nr KHIM er aktiveret kan du indtaste internationale tegn i enhver kontrol der er konfigureret til at bruge KHIM ved at trykke p den valgte "Compose" taste fulgt af to bestemte tegn. Rullelisten til venstre p KHIM kontrolpanelet viser de tegnflger der str til rdighed. Hvis du trykker "Compose" tasten to gange kommer der et vindue frem hvor du kan vlge vilkrlige symboler fra en unicode tabel. Du kan navigere rundt i selve tabellen ved enten at benytte markren eller markrtasterne. Du kan udvlge det markerede tegn ved at doppelt-klikke p symbolet eller ved at trykke p mellemrums-, enter- eller returtasten. Ny tegnflger kan defineres ved at indtaste en flge af to tegn i feltet markeret med "Indtast tegnflge" og det nskede symbol i feltet markeret med "Tegn" og derefter trykke p "ndre". Du kan ogs kopiere og indstte et symbol fra et andet program eller benytte "Unicode..." knappen (eller trykke "Compose" tasten to gange) for at hente et symbol fra tabellen med alle unicode koder. Tryk p "Slet" knappen for at fjerne en tegnflge. } ::msgcat::mcset da {Input key sequence} {Indtast tegnflge} ::msgcat::mcset da {Insert Character} {Indtast et tegn} ::msgcat::mcset da {Invalid sequence} {Ugyldig tegnflge} ::msgcat::mcset da {Key sequences} {Tegnflger} ::msgcat::mcset da {KHIM Controls} {KHIM kontrolpanel} ::msgcat::mcset da {OK} {O.k.} ::msgcat::mcset da {Select code page:} {Vlg kode side:} ::msgcat::mcset da {SELECT COMPOSE KEY} [string map [list \n\t \n] { Tryk p den taske du nsker at bruge som "Compose" taste. }] ::msgcat::mcset da {Unicode...} {Unicode...} ::msgcat::mcset da {Use KHIM} {Benyt KHIM} } # Local Variables: # mode: tcl # End: tkabber-plugins-0.11.1/tkabber-khim/msgs/0000755000175000017500000000000011076120366017514 5ustar sergeisergeitkabber-plugins-0.11.1/tkabber-khim/msgs/pl.msg0000644000175000017500000000110510546743545020647 0ustar sergeisergei# Polish messages file for khim plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "KHIM options" "Ustawienia wtyczki KHIM" ::msgcat::mcset pl "Problem loading KHIM. Tkabber-khim functionality will be disabled.\nRefer to the INSTALL file of the tkabber-khim plugin." \ "Wystąpił problem podczas ładowania wtyczki KHIM.\nFunkcje dostępne przez wtyczkę będą wyłączone.\nSprawdź instrukcje w pliku INSTALL w katalogu wtyczki." # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/tkabber-khim/msgs/es.msg0000644000175000017500000000124610712161173020633 0ustar sergeisergei::msgcat::mcset es "KHIM options" "Opciones de KHIM" ::msgcat::mcset pl "Problem loading KHIM. Tkabber-khim functionality will be disabled.\nRefer to the INSTALL file of the tkabber-khim plugin." "Hubo un problema cargando KHIM.\nLa funcionalidad se ha desactivado en Tkabber.\nConsulta el fichero INSTALL del directorio de tkabber-khim." ::msgcat::mcset es "KHIM options" "Opciones de KHIM" ::msgcat::mcset pl "Problem loading KHIM. Tkabber-khim functionality will be disabled.\nRefer to the INSTALL file of the tkabber-khim plugin." "Hubo un problema cargando KHIM.\nLa funcionalidad se ha desactivado en Tkabber.\nConsulta el fichero INSTALL del directorio de tkabber-khim." tkabber-plugins-0.11.1/tkabber-khim/msgs/ru.msg0000644000175000017500000000104010546743545020660 0ustar sergeisergei# $Id: ru.msg 858 2007-01-03 15:10:29Z sergei $ ::msgcat::mcset ru "KHIM options" "Настройки KHIM" ::msgcat::mcset ru "Problem loading KHIM. Tkabber-khim functionality will be\ disabled.\nRefer to the INSTALL file of the tkabber-khim plugin." \ "Не удалось загрузить KHIM. Расширение Tkabber-khim не будет\ активизирован.\nОбратитесь к файлу INSTALL в каталоге с расширением\ tkabber-khim." # vim:ft=tcl:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/tkabber-khim/INSTALL0000644000175000017500000000341210563364101017571 0ustar sergeisergei$Id: INSTALL 918 2007-02-10 15:44:01Z sergei $ As usually, copy this directory to $HOME/.tkabber/plugins (on UNIX), to %APPDATA%\Tkabber\plugins (on Windows), or to $HOME/Library/Application Support/Tkabber (on MacOS X) directory. Restart Tkabber, then navigate to the "Services" -> "Plugins" menu and activate the "KHIM Options..." menu entry -- the KHIM configuration dialog will appear. Hit the "Help..." button and read the help carefully. Normally, this plugin is bundled with the original "khim" and "autoscroll" Tcl packages, which are parts of the "tklib" library [1]. If these packages are missing, you most probably need to get tklib installed in your system. The khim package is not yet currently in the official "stable" flavor of the tklib [2], so you generally have two options: 1) Recent Active State's distros come with the "CVS HEAD state" tklib, so if you have such a distro, you most probably have khim, too. 2) Fetch and install tklib from CVS: * Log in as anonymous with the empty password (just hit Enter): cvs -d :pserver:anonymous@tcllib.cvs.sourceforge.net/cvsroot/tcllib/ login * Fetch the sources (the "tklib" directory under the current one will be created): cvs -z3 -d :pserver:anonymous@tcllib.cvs.sourceforge.net/cvsroot/tcllib/ co tklib * Log out: cvs -d :pserver:anonymous@tcllib.cvs.sourceforge.net/cvsroot/tcllib/ logout * Install: cd tklib ./configure --with-tcl=/usr/bin --prefix=/usr make test su make install (Leave out "su" if not on Unix. "make test" step is optional, of course). * Alternatively, you can just grab "khim" and "autoscroll" packages and place them into the root directory of this plugin. [1] http://tcllib.sourceforge.net/ [2] This is written on 09-Dec-2006. tkabber-plugins-0.11.1/tkabber-khim/tkabber-khim.tcl0000644000175000017500000000606710666503424021624 0ustar sergeisergei# $Id: tkabber-khim.tcl 1216 2007-09-02 09:49:08Z sergei $ # # Tkabber plugin adding KHIM functionality to Tkabber's Text and Entry widgets. # Written by Konstantin Khomoutov . # KHIM written by Kevin B Kenny . # Read more about KHIM: http://wiki.tcl.tk/16343 # # To use this plugin you either need KHIM and autoscroll packegs themselves, # or the fresh tklib, which KHIM is now a part of. # Refer to INSTALL file for details. # TODO eval'ing of KHIM settings looks unsafe. # TODO it would be better not to subvert ::entry and ::text commands. namespace eval khim { # If the directory named "khim" is available locally, use it. # This makes possible to distribute KHIM and autoscroll bundled # with this plugin (and lift the dependency on tklib). set scriptdir [file dirname [info script]] set local_khim [file join $scriptdir khim] if {[file isdirectory $local_khim]} { lappend ::auto_path $scriptdir package forget khim } # Load message catalog: package require msgcat ::msgcat::mcload [file join $scriptdir msgs] # Attempt to load KHIM. Warn and quit loading plugin if we can't: if {[catch { package require khim } err]} { # TODO why didn't tk_messageBox work here? puts stderr $err puts stderr [::msgcat::mc "Problem loading KHIM. Tkabber-khim\ functionality will be\ disabled.\nRefer to the INSTALL file\ of the tkabber-khim plugin."] # Clean up what's already here and bail out: namespace delete [namespace current] return } # Configuration section: variable settings custom::defvar settings {} \ "KHIM subsystem settings" \ -group Hidden \ -type list # Event handlers: # This handler should be called after Customize DB has been restored # which occurs in postload_hook at priority 60. ::hook::add postload_hook [namespace current]::restore_settings 70 ::hook::add finload_hook [namespace current]::on_init # The trickery (see http://wiki.tcl.tk/16343): rename ::entry ::khim::entry rename ::text ::khim::text proc ::entry {w args} { eval [linsert $args 0 ::khim::entry $w] bindtags $w [list $w KHIM Entry [winfo toplevel $w] all] return $w } proc ::text {w args} { eval [linsert $args 0 ::khim::text $w] bindtags $w [list $w KHIM Text [winfo toplevel $w] all] return $w } } # Passes the KHIM settings restored from the Customize DB # to the KHIM subsystem: proc khim::restore_settings {args} { variable settings catch {eval $settings} } # Invokes the KHIM's options dialog, # then saves current KHIM options. # Intended to be invoked via Tkabber menus, etc. proc khim::edit_options {} { variable settings ::khim::getOptions .tkabber_khim_options set settings [::khim::getConfig] } # Creates an entry for KHIM in the "Services->Plugins" Tkabber menu: proc khim::on_init {} { set menu [.mainframe getmenu plugins] $menu add command \ -label [::msgcat::mc "KHIM options"] \ -command [namespace current]::edit_options } # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/tkabber-khim/VERSION0000644000175000017500000000003710540047772017617 0ustar sergeisergeiVersion: 1.2 Date: 11-Dec-2006 tkabber-plugins-0.11.1/tkabber-khim/ChangeLog0000644000175000017500000000257210541264615020325 0ustar sergeisergei2006-12-17 Sergei Golovan * Bumped khim version number to ensure its loading. 2006-12-15 Sergei Golovan * Changed colors of Unicode charmap. This change looks like a hack, so it's not for proposing uopstream. 2006-12-13 Sergei Golovan * Removed autoscroll package and reference to it from KHIM to make plugin slightly lighter. 2006-12-11 Konstantin Khomoutov * Fixed KHIM bug with attempting to re-create the Unicode map window on simultaneous Compose keypresses. * Added translateable title to the KHIM help window. * Several typos fixed ru.msg of KHIM (thanks to Serge Yudin). * Added KHIM help window title string to en.msg and ru.msg. * In tkabber-khim.tcl: * Fixed comment; * Added removal of one transient variable; * Added cleanup of the plugin namespace on failed khim loading attempt. * Misc indenting fix in INSTALL. * Misc fix in khim/ru.msg. 2006-12-10 Konstantin Khomoutov * Fixed issues with mclocale. * Added loading of message catalogs. * Added Russian translation of the plugin interface. * Written INSTALL file, added ChangeLog file. * Added tklib_license.terms file (for khim and autoscroll packages). 2006-12-09 Konstantin Khomoutov * Initial (preview) release. tkabber-plugins-0.11.1/tkabber-khim/tklib_licence.terms0000644000175000017500000000415410540047772022416 0ustar sergeisergeiThis software is copyrighted by Ajuba Solutions and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tkabber-plugins-0.11.1/openurl/0000755000175000017500000000000011076120366015667 5ustar sergeisergeitkabber-plugins-0.11.1/openurl/msgs/0000755000175000017500000000000011076120366016640 5ustar sergeisergeitkabber-plugins-0.11.1/openurl/msgs/pl.msg0000644000175000017500000000035311007542441017760 0ustar sergeisergei# Polish messages file for openurl plugin # Author: Irek Chmielowiec # Contact: xmpp:irek@chrome.pl :: mailto:irek.ch@gmail.com # Please notify me of errors or incoherencies ::msgcat::mcset pl "Open URL with" "Otwórz URL za pomocą" tkabber-plugins-0.11.1/openurl/msgs/es.msg0000644000175000017500000000006311007542441017752 0ustar sergeisergei::msgcat::mcset es "Open URL with" "Abrir URL con" tkabber-plugins-0.11.1/openurl/msgs/de.msg0000644000175000017500000000015411007542441017734 0ustar sergeisergei # German messages file # Roger Sondermann 06.10.2007 ::msgcat::mcset de "Open URL with" "ffne URL mit" tkabber-plugins-0.11.1/openurl/msgs/ru.msg0000644000175000017500000000017411007542441017774 0ustar sergeisergei# $Id: ru.msg 1407 2008-05-05 08:28:17Z sergei $ ::msgcat::mcset ru "Open URL with" "Открыть URL с помощью" tkabber-plugins-0.11.1/openurl/openurl.tcl0000644000175000017500000000360711007542441020061 0ustar sergeisergei# $Id: openurl.tcl 1407 2008-05-05 08:28:17Z sergei $ package require msgcat namespace eval openurl { ::msgcat::mcload [file join [file dirname [info script]] msgs] set options(browsers) [list \ firefox "Firefox" \ galeon "Galeon" \ konqueror "Konqueror" \ mozilla-firefox "Mozilla Firefox" \ mozilla-firebird "Mozilla Firebird" \ mozilla "Mozilla" \ netscape "Netscape" \ iexplorer "Internet Explorer" \ opera "Opera" \ lynx "Lynx" \ links "Links" \ elinks "Elinks"] } proc openurl::open_url {brname brpath command} { set url [::plugins::urls::encode_url [eval $command]] switch -- $brname { firefox - mozilla-firefox - mozilla-firebird - mozilla - netscape { if {[catch {eval exec $brpath -remote \"openURL($url, new-tab)\"}]} { exec $brpath $url & } } galeon { exec $brpath --new-tab $url & } opera { exec $brpath -newpage $url & } links - elinks - lynx { exec xterm -e $brpath $url & } default { exec $brpath $url & } } } proc openurl::add_chat_win_popup_menu {m chatwin X Y x y} { variable options set tags [$chatwin tag names "@$x,$y"] set idx1 [lsearch $tags url] set idx2 [lsearch $tags xep] switch -glob -- [expr {$idx1 >= 0}]/[expr {$idx2 >= 0}] { 0/0 { return } 1/* { set command [list ::plugins::urls::get_url $chatwin $x $y] } default { set command [list ::plugins::xeps::get_xep $chatwin $x $y] } } set mb [menu $m.openurl -tearoff 0] foreach {brname brdesc} $options(browsers) { if {[llength [set e [auto_execok $brname]]] > 0} { $mb add command \ -label $brdesc \ -command [list [namespace current]::open_url \ $brname [lindex $e 0] $command] } } $m add cascade -label [::msgcat::mc "Open URL with"] -menu $mb } hook::add chat_win_popup_menu_hook \ [namespace current]::openurl::add_chat_win_popup_menu 5 # vim:ts=8:sw=4:sts=4:noet tkabber-plugins-0.11.1/cyrillize/0000755000175000017500000000000011076120366016211 5ustar sergeisergeitkabber-plugins-0.11.1/cyrillize/engrus.tbl0000644000175000017500000000037410551424751020225 0ustar sergeisergeiq w e r t y u i o p \[ \{ \] \} a s d f g h j k l ; : ' \" z x c v b n m , < . > ` ~ ? , / . tkabber-plugins-0.11.1/cyrillize/cyrillize.tcl0000644000175000017500000000574411026170605020731 0ustar sergeisergei# $Id: cyrillize.tcl 1463 2008-06-18 11:29:09Z sergei $ namespace eval cyrillize { } proc cyrillize::load_table {} { variable convert set f [file join [file dirname [info script]] engrus.tbl] set fd [open $f] fconfigure $fd -encoding koi8-r set convert_table [read $fd] close $fd foreach {f t} $convert_table { set convert(eng,rus,$f) $t set convert(rus,eng,$t) $f } } cyrillize::load_table #puts [array get cyrillize::engrus] proc cyrillize::do {s from to} { variable convert set res "" foreach c [split $s ""] { if {[info exists convert($from,$to,$c)]} { append res $convert($from,$to,$c) } elseif {[info exists convert($from,$to,[string tolower $c])]} { append res [string toupper $convert($from,$to,[string tolower $c])] } else { append res $c } } return $res } #puts [cyrillize::do Ghbdtn] proc cyrillize::wordInText {w from to} { if {[$w cget -state] != "normal"} return set ins [lindex [split [$w index insert] .] 1] set line [$w get "insert linestart" "insert lineend"] set wordstart [string wordstart $line [expr {$ins-1}]] set wordend [string length \ [string trimright \ [string range $line 0 [expr {$wordstart-1}]]]] set word [string range $line $wordstart [expr {$ins-1}]] set newword [do $word $from $to] $w delete "insert linestart +$wordstart chars" insert $w insert insert $newword $w mark set insert "insert linestart +$wordend chars" } proc cyrillize::wordInEntry {w from to} { if {[$w cget -state] != "normal"} return set ins [$w index insert] set line [$w get] set wordstart [string wordstart $line [expr {$ins-1}]] set wordend [string length \ [string trimright \ [string range $line 0 [expr {$wordstart-1}]]]] set word [string range $line $wordstart [expr {$ins-1}]] set newword [do $word $from $to] $w delete $wordstart insert $w insert insert $newword $w icursor $wordend } event add <> event add <> event add <> event add <> bind Text <> \ [list [namespace current]::cyrillize::wordInText %W eng rus] bind Text <> +break bind Text <> \ [list [namespace current]::cyrillize::wordInText %W rus eng] bind Text <> +break bind Entry <> \ [list [namespace current]::cyrillize::wordInEntry %W eng rus] bind Entry <> +break bind Entry <> \ [list [namespace current]::cyrillize::wordInEntry %W rus eng] bind Entry <> +break bind BwEntry <> \ [list [namespace current]::cyrillize::wordInEntry %W eng rus] bind BwEntry <> +break bind BwEntry <> \ [list [namespace current]::cyrillize::wordInEntry %W rus eng] bind BwEntry <> +break