Index: lang/elisp/twittering-mode/branches/tsuyoshi/twittering-mode.el
===================================================================
--- lang/elisp/twittering-mode/branches/tsuyoshi/twittering-mode.el (revision 31)
+++ lang/elisp/twittering-mode/branches/tsuyoshi/twittering-mode.el (revision 31)
@@ -0,0 +1,1003 @@
+;;; twittering-mode.el --- Major mode for Twitter
+
+;; Copyright (C) 2007 Yuto Hayamizu.
+;;               2008 Tsuyoshi CHO
+
+;; Author: Y. Hayamizu <y.hayamizu@gmail.com>
+;;         Tsuyoshi CHO <Tsuyoshi.CHO+develop@Gmail.com>
+;; Created: Sep 4, 2007
+;; Version: 0.3
+;; Keywords: twitter web
+;; URL: http://lambdarepos.svnrepository.com/share/trac.cgi/browser/lang/elisp/twittering-mode
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; twittering-mode.el is a major mode for Twitter.
+;; You can check friends timeline, and update your status on Emacs.
+
+;;; Feature Request:
+
+;; URL : http://twitter.com/d00dle/statuses/577876082
+;; URL : http://twitter.com/d00dle/statuses/577879732
+;; * Status Input from Popup buffer and C-cC-c to POST.
+;; * Mark fav(star)
+;; URL : http://code.nanigac.com/source/view/419
+;; * update status for region
+
+;;; Code:
+
+(require 'cl)
+(require 'xml)
+(require 'parse-time)
+
+(defconst twittering-mode-version "0.3")
+
+(defun twittering-mode-version ()
+  "Display a message for twittering-mode version."
+  (interactive)
+  (let ((version-string
+         (format "twittering-mode-v%s" twittering-mode-version)))
+    (if (interactive-p)
+        (message "%s" version-string)
+      version-string)))
+
+(defvar twittering-mode-map (make-sparse-keymap))
+
+(defvar twittering-timer nil "Timer object for timeline refreshing will be stored here. DO NOT SET VALUE MANUALLY.")
+
+(defvar twittering-idle-time 20)
+
+(defvar twittering-timer-interval 90)
+
+(defvar twittering-username nil)
+
+(defvar twittering-password nil)
+
+(defvar twittering-scroll-mode nil)
+
+(defvar twittering-jojo-mode nil)
+
+(defvar twittering-status-format nil)
+(setq twittering-status-format "%i %s,  %@:\n  %t // from %f%L")
+;; %s - screen_name
+;; %S - name
+;; %i - profile_image
+;; %d - description
+;; %l - location
+;; %L - " [location]"
+;; %u - url
+;; %j - user.id
+;; %p - protected?
+;; %c - created_at (raw UTC string)
+;; %C{time-format-str} - created_at (formatted with time-format-str)
+;; %@ - X seconds ago
+;; %t - text
+;; %' - truncated
+;; %f - source
+;; %# - id
+
+(defvar twittering-buffer "*twittering*")
+(defun twittering-buffer ()
+  (twittering-get-or-generate-buffer twittering-buffer))
+
+(defvar twittering-http-buffer "*twittering-http-buffer*")
+(defun twittering-http-buffer ()
+  (twittering-get-or-generate-buffer twittering-http-buffer))
+
+(defvar twittering-friends-timeline-data nil)
+
+(defvar twittering-username-face 'twittering-username-face)
+(defvar twittering-uri-face 'twittering-uri-face)
+
+(defun twittering-get-or-generate-buffer (buffer)
+  (if (bufferp buffer)
+      (if (buffer-live-p buffer)
+          buffer
+        (generate-new-buffer (buffer-name buffer)))
+    (if (stringp buffer)
+        (or (get-buffer buffer)
+            (generate-new-buffer buffer)))))
+
+(defun assocref (item alist)
+  (cdr (assoc item alist)))
+(defmacro list-push (value listvar)
+  `(setq ,listvar (cons ,value ,listvar)))
+
+;;; Proxy
+(defvar twittering-proxy-use nil)
+(defvar twittering-proxy-server nil)
+(defvar twittering-proxy-port 8080)
+(defvar twittering-proxy-user nil)
+(defvar twittering-proxy-password nil)
+
+(defun twittering-toggle-proxy () ""
+  (interactive)
+  (setq twittering-proxy-use
+        (not twittering-proxy-use))
+  (message "%s %s"
+           "Use Proxy:"
+           (if twittering-proxy-use
+               "on" "off")))
+
+(defun twittering-user-agent-default-function ()
+  "Twittering mode default User-Agent function."
+  (concat "Emacs/"
+          (int-to-string emacs-major-version) "." (int-to-string
+                                                   emacs-minor-version)
+          " "
+          "Twittering-mode/"
+          twittering-mode-version))
+
+(defvar twittering-user-agent-function 'twittering-user-agent-default-function)
+
+(defun twittering-user-agent ()
+  "Return User-Agent header string."
+  (funcall twittering-user-agent-function))
+
+;;; to show image files
+
+(defvar twittering-wget-buffer "*twittering-wget-buffer*")
+(defun twittering-wget-buffer ()
+  (twittering-get-or-generate-buffer twittering-wget-buffer))
+
+(defvar twittering-tmp-dir
+  (expand-file-name (concat "twmode-images-" (user-login-name))
+                    temporary-file-directory))
+
+(defvar twittering-icon-mode nil "You MUST NOT CHANGE this variable directory. You should change through function'twittering-icon-mode'")
+(defun twittering-icon-mode (&optional arg)
+  (interactive)
+  (setq twittering-icon-mode
+        (if twittering-icon-mode
+            (if (null arg)
+                nil
+              (> (prefix-numeric-value arg) 0))
+          (when (or (null arg)
+                    (and arg (> (prefix-numeric-value arg) 0)))
+            (when (file-writable-p twittering-tmp-dir)
+              (progn
+                (if (not (file-directory-p twittering-tmp-dir))
+                    (make-directory twittering-tmp-dir))
+                t)))))
+  (twittering-render-friends-timeline))
+
+(defun twittering-scroll-mode (&optional arg)
+  (interactive)
+  (setq twittering-scroll-mode
+        (if (null arg)
+            (not twittering-scroll-mode)
+          (> (prefix-numeric-value arg) 0))))
+
+(defun twittering-jojo-mode (&optional arg)
+  (interactive)
+  (setq twittering-jojo-mode
+        (if (null arg)
+            (not twittering-jojo-mode)
+          (> (prefix-numeric-value arg) 0))))
+
+(defvar twittering-image-stack nil)
+
+(defun twittering-image-type (file-name)
+  (cond
+   ((string-match "\\.jpe?g" file-name) 'jpeg)
+   ((string-match "\\.png" file-name) 'png)
+   ((string-match "\\.gif" file-name) 'gif)
+   (t nil)))
+
+(defun twittering-local-strftime (fmt string)
+  (format-time-string fmt ; like "%Y-%m-%d %H:%M:%S", shown in localtime
+                      (apply 'encode-time (parse-time-string string))))
+
+(defvar twittering-debug-mode nil)
+(defvar twittering-debug-buffer "*debug*")
+(defun twittering-debug-buffer ()
+  (twittering-get-or-generate-buffer twittering-debug-buffer))
+(defmacro debug-print (obj)
+  (let ((obsym (gensym)))
+    `(let ((,obsym ,obj))
+       (if twittering-debug-mode
+           (with-current-buffer (twittering-debug-buffer)
+             (insert (prin1-to-string ,obsym))
+             (newline)
+             ,obsym)
+         ,obsym))))
+
+(defun twittering-debug-mode ()
+  (interactive)
+  (setq twittering-debug-mode
+        (not twittering-debug-mode))
+  (message (if twittering-debug-mode "debug mode:on" "debug mode:off")))
+
+(if twittering-mode-map
+    (let ((km twittering-mode-map))
+      (define-key km "\C-c\C-f" 'twittering-friends-timeline)
+      (define-key km "\C-c\C-s" 'twittering-update-status-interactive)
+      (define-key km "\C-c\C-e" 'twittering-erase-old-statuses)
+      (define-key km "\C-m" 'twittering-enter)
+      (define-key km "\C-c\C-l" 'twittering-update-lambda)
+      (define-key km [mouse-1] 'twittering-click)
+      (define-key km "\C-c\C-v" 'twittering-view-user-page)
+      ;; (define-key km "j" 'next-line)
+      ;; (define-key km "k" 'previous-line)
+      (define-key km "j" 'twittering-goto-next-status)
+      (define-key km "k" 'twittering-goto-previous-status)
+      (define-key km "l" 'forward-char)
+      (define-key km "h" 'backward-char)
+      (define-key km "0" 'beginning-of-line)
+      (define-key km "^" 'beginning-of-line-text)
+      (define-key km "$" 'end-of-line)
+      (define-key km "n" 'twittering-goto-next-status-of-user)
+      (define-key km "p" 'twittering-goto-previous-status-of-user)
+      (define-key km [backspace] 'backward-char)
+      (define-key km "G" 'end-of-buffer)
+      (define-key km "H" 'beginning-of-buffer)
+      (define-key km "\C-c\C-p" 'twittering-toggle-proxy)
+      nil))
+
+(defvar twittering-mode-syntax-table nil "")
+
+(if twittering-mode-syntax-table
+    ()
+  (setq twittering-mode-syntax-table (make-syntax-table))
+  ;; (modify-syntax-entry ?  "" twittering-mode-syntax-table)
+  (modify-syntax-entry ?\" "w"  twittering-mode-syntax-table)
+  )
+
+(defun twittering-mode-init-variables ()
+  ;; (make-variable-buffer-local 'variable)
+  ;; (setq variable nil)
+  (font-lock-mode -1)
+  (defface twittering-username-face
+    `((t nil)) "" :group 'faces)
+  (copy-face 'font-lock-string-face 'twittering-username-face)
+  (set-face-attribute 'twittering-username-face nil :underline t)
+  (defface twittering-uri-face
+    `((t nil)) "" :group 'faces)
+  (set-face-attribute 'twittering-uri-face nil :underline t)
+  (add-to-list 'minor-mode-alist '(twittering-icon-mode " tw-icon"))
+  (add-to-list 'minor-mode-alist '(twittering-scroll-mode " tw-scroll"))
+  (add-to-list 'minor-mode-alist '(twittering-jojo-mode " tw-jojo"))
+  )
+
+(defmacro case-string (str &rest clauses)
+  `(cond
+    ,@(mapcar
+       (lambda (clause)
+         (let ((keylist (car clause))
+               (body (cdr clause)))
+           `(,(if (listp keylist)
+                  `(or ,@(mapcar (lambda (key) `(string-equal ,str ,key)) keylist))
+                't)
+             ,@body)))
+       clauses)))
+
+;; If you use Emacs21, decode-char 'ucs will fail unless Mule-UCS is loaded.
+;; TODO: Show error messages if Emacs 21 without Mule-UCS
+(defmacro twittering-ucs-to-char (num)
+  (if (functionp 'ucs-to-char)
+      `(ucs-to-char ,num)
+    `(decode-char 'ucs ,num)))
+
+(defvar twittering-mode-string "Twittering mode")
+
+(defun twittering-mode ()
+  "Major mode for Twitter"
+  (interactive)
+  (switch-to-buffer (twittering-buffer))
+  (kill-all-local-variables)
+  (twittering-mode-init-variables)
+  (use-local-map twittering-mode-map)
+  (setq major-mode 'twittering-mode)
+  (setq mode-name twittering-mode-string)
+  (set-syntax-table twittering-mode-syntax-table)
+  (run-hooks 'twittering-mode-hook)
+  (font-lock-mode -1)
+  (twittering-start)
+  )
+
+;;;
+;;; Basic HTTP functions
+;;;
+
+(defun twittering-http-get (method-class method &optional sentinel)
+  (if (null sentinel) (setq sentinel 'twittering-http-get-default-sentinel))
+
+  ;; clear the buffer
+  (save-excursion
+    (set-buffer (twittering-http-buffer))
+    (erase-buffer))
+
+  (let (proc server port
+             (proxy-user twittering-proxy-user)
+             (proxy-password twittering-proxy-password))
+    (condition-case nil
+        (progn
+          (if (and twittering-proxy-use twittering-proxy-server)
+              (setq server twittering-proxy-server
+                    port (if (integerp twittering-proxy-port)
+                             (int-to-string twittering-proxy-port)
+                           twittering-proxy-port))
+            (setq server "twitter.com"
+                  port "80"))
+          (setq proc
+                (open-network-stream
+                 "network-connection-process" (twittering-http-buffer)
+                 server (string-to-number port)))
+          (set-process-sentinel proc sentinel)
+          (process-send-string
+           proc
+           (let ((nl "\r\n")
+                 request)
+             (setq request
+                   (concat "GET http://twitter.com/" method-class "/" method ".xml HTTP/1.1" nl
+                           "Host: twitter.com" nl
+                           "User-Agent: " (twittering-user-agent) nl
+                           "Authorization: Basic "
+                           (base64-encode-string
+                            (concat twittering-username ":" (twittering-get-password)))
+                           nl
+                           "Accept: text/xml"
+                           ",application/xml"
+                           ",application/xhtml+xml"
+                           ",application/html;q=0.9"
+                           ",text/plain;q=0.8"
+                           ",image/png,*/*;q=0.5" nl
+                           "Accept-Charset: utf-8;q=0.7,*;q=0.7" nl
+                           (when twittering-proxy-use
+                             "Proxy-Connection: Keep-Alive" nl
+                             (when (and proxy-user proxy-password)
+                               (concat
+                                "Proxy-Authorization: Basic "
+                                (base64-encode-string
+                                 (concat proxy-user ":"
+                                         proxy-password))
+                                nl)))
+                           nl nl))
+             (debug-print (concat "GET Request\n" request))
+             request)))
+      (error
+       (message "Failure: HTTP GET") nil))))
+
+(defun twittering-http-get-default-sentinel (proc stat &optional suc-msg)
+  (let ((header (twittering-get-response-header))
+        (body (twittering-get-response-body))
+        (status nil)
+        )
+    (if (string-match "HTTP/1\.[01] \\([a-z0-9 ]+\\)\r?\n" header)
+        (progn
+          (setq status (match-string-no-properties 1 header))
+          (case-string
+           status
+           (("200 OK")
+            (mapcar
+             #'twittering-cache-status-datum
+             (reverse (twittering-xmltree-to-status
+                       body)))
+            (twittering-render-friends-timeline)
+            (message (if suc-msg suc-msg "Success: Get.")))
+           (t (message status))))
+      (message "Failure: Bad http response.")))
+  )
+
+(defun twittering-render-friends-timeline ()
+  (with-current-buffer (twittering-buffer)
+    (let ((point (point))
+          (end (point-max)))
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (insert
+       (mapconcat (lambda (status)
+                    (twittering-format-status status twittering-status-format))
+                  twittering-friends-timeline-data
+                  "\n"))
+      (if twittering-image-stack
+          (clear-image-cache))
+      (setq buffer-read-only t)
+      (debug-print (current-buffer))
+      (goto-char (+ point (if twittering-scroll-mode (- (point-max) end) 0))))
+    ))
+
+(defun twittering-format-status (status format-str)
+  (flet ((attr (key)
+               (assocref key status))
+         (profile-image
+          ()
+          (let ((profile-image-url (attr 'user-profile-image-url))
+                (icon-string "\n  "))
+            (if (string-match "/\\([^/?]+\\)\\(?:\\?\\|$\\)" profile-image-url)
+                (let ((filename (match-string-no-properties 1 profile-image-url)))
+                  ;; download icons if does not exist
+                  (if (file-exists-p (concat twittering-tmp-dir
+                                             "/" filename))
+                      t
+                    (add-to-list 'twittering-image-stack profile-image-url))
+
+                  (when (and icon-string twittering-icon-mode)
+                    (set-text-properties
+                     1 2 `(display
+                           (image :type ,(twittering-image-type filename)
+                                  :file ,(concat twittering-tmp-dir
+                                                 "/"
+                                                 filename)))
+                     icon-string)
+                    icon-string)
+                  )))))
+    (let ((cursor 0)
+          (result ())
+          c
+          found-at)
+      (setq cursor 0)
+      (setq result '())
+      (while (setq found-at (string-match "%\\(C{\\([^}]+\\)}\\|[A-Za-z#@']\\)" format-str cursor))
+        (setq c (string-to-char (match-string-no-properties 1 format-str)))
+        (if (> found-at cursor)
+            (list-push (substring format-str cursor found-at) result)
+          "|")
+        (setq cursor (match-end 1))
+
+        (case c
+          ((?s)                         ; %s - screen_name
+           (list-push (attr 'user-screen-name) result))
+          ((?S)                         ; %S - name
+           (list-push (attr 'user-name) result))
+          ((?i)                         ; %i - profile_image
+           (list-push (profile-image) result))
+          ((?d)                         ; %d - description
+           (list-push (attr 'user-description) result))
+          ((?l)                         ; %l - location
+           (list-push (attr 'user-location) result))
+          ((?L)                         ; %L - " [location]"
+           (let ((location (attr 'user-location)))
+             (unless (or (null location) (string= "" location))
+               (list-push (concat " [" location "]") result)) ))
+          ((?u)                         ; %u - url
+           (list-push (attr 'user-url) result))
+          ((?j)                         ; %j - user.id
+           (list-push (attr 'user-id) result))
+          ((?p)                         ; %p - protected?
+           (let ((protected (attr 'user-protected)))
+             (when (string= "true" protected)
+               (list-push "[x]" result))))
+          ((?c)                     ; %c - created_at (raw UTC string)
+           (list-push (attr 'created-at) result))
+          ((?C) ; %C{time-format-str} - created_at (formatted with time-format-str)
+           (list-push (twittering-local-strftime
+                       (or (match-string-no-properties 2 format-str) "%H:%M:%S")
+                       (attr 'created-at))
+                      result))
+          ((?@)                         ; %@ - X seconds ago
+           (let ((created-at
+                  (apply
+                   'encode-time
+                   (parse-time-string (attr 'created-at))))
+                 (now (current-time)))
+             (let ((secs (+ (* (- (car now) (car created-at)) 65536)
+                            (- (cadr now) (cadr created-at)))))
+               (list-push (cond ((< secs 5) "less than 5 seconds ago")
+                                ((< secs 10) "less than 10 seconds ago")
+                                ((< secs 20) "less than 20 seconds ago")
+                                ((< secs 30) "half a minute ago")
+                                ((< secs 60) "less than a minute ago")
+                                ((< secs 150) "1 minute ago")
+                                ((< secs 2400) (format "%d minutes ago"
+                                                       (/ (+ secs 30) 60)))
+                                ((< secs 5400) "about 1 hour ago")
+                                ((< secs 84600) (format "about %d hours ago"
+                                                        (/ (+ secs 1800) 3600)))
+                                (t (format-time-string "%I:%M %p %B %d, %Y" created-at)))
+                          result))))
+          ((?t)                         ; %t - text
+           (list-push                   ;(clickable-text)
+            (attr 'text)
+            result))
+          ((?')                         ; %' - truncated
+           (let ((truncated (attr 'truncated)))
+             (when (string= "true" truncated)
+               (list-push "..." result))))
+          ((?f)                         ; %f - source
+           (list-push (attr 'source) result))
+          ((?#)                         ; %# - id
+           (list-push (attr 'id) result))
+          (t
+           (list-push (char-to-string c) result)))
+        )
+      (list-push (substring format-str cursor) result)
+      (apply 'concat (nreverse result))
+      )))
+
+(defun twittering-http-post
+  (method-class method &optional parameters contents sentinel)
+  "Send HTTP POST request to twitter.com
+
+METHOD-CLASS must be one of Twitter API method classes(statuses, users or direct_messages).
+METHOD must be one of Twitter API method which belongs to METHOD-CLASS.
+PARAMETERS is alist of URI parameters. ex) ((\"mode\" . \"view\") (\"page\" . \"6\")) => <URI>?mode=view&page=6"
+  (if (null sentinel) (setq sentinel 'twittering-http-post-default-sentinel))
+
+  ;; clear the buffer
+  (save-excursion
+    (set-buffer (twittering-http-buffer))
+    (erase-buffer))
+
+  (let (proc server port
+             (proxy-user twittering-proxy-user)
+             (proxy-password twittering-proxy-password))
+    (progn
+      (if (and twittering-proxy-use twittering-proxy-server)
+          (setq server twittering-proxy-server
+                port (if (integerp twittering-proxy-port)
+                         (int-to-string twittering-proxy-port)
+                       twittering-proxy-port))
+        (setq server "twitter.com"
+              port "80"))
+      (setq proc
+            (open-network-stream
+             "network-connection-process" (twittering-http-buffer)
+             server (string-to-number port)))
+      (set-process-sentinel proc sentinel)
+      (process-send-string
+       proc
+       (let ((nl "\r\n")
+             request)
+         (setq  request
+                (concat "POST http://twitter.com/" method-class "/" method ".xml?"
+                        (if parameters
+                            (mapconcat
+                             (lambda (param-pair)
+                               (format "%s=%s"
+                                       (twittering-percent-encode (car param-pair))
+                                       (twittering-percent-encode (cdr param-pair))))
+                             parameters
+                             "&"))
+                        " HTTP/1.1" nl
+                        "Host: twitter.com" nl
+                        "User-Agent: " (twittering-user-agent) nl
+                        "Authorization: Basic "
+                        (base64-encode-string
+                         (concat twittering-username ":" (twittering-get-password)))
+                        nl
+                        "Content-Type: text/plain" nl
+                        "Content-Length: 0" nl
+                        (when twittering-proxy-use
+                          "Proxy-Connection: Keep-Alive" nl
+                          (when (and proxy-user proxy-password)
+                            (concat
+                             "Proxy-Authorization: Basic "
+                             (base64-encode-string
+                              (concat proxy-user ":"
+                                      proxy-password))
+                             nl)))
+                        nl nl))
+         (debug-print (concat "POST Request\n" request))
+         request)))))
+
+(defun twittering-http-post-default-sentinel (proc stat &optional suc-msg)
+
+  (condition-case err-signal
+      (let ((header (twittering-get-response-header))
+            ;; (body (twittering-get-response-body)) not used now.
+            (status nil))
+        (string-match "HTTP/1\.1 \\([a-z0-9 ]+\\)\r?\n" header)
+        (setq status (match-string-no-properties 1 header))
+        (case-string status
+                     (("200 OK")
+                      (message (if suc-msg suc-msg "Success: Post")))
+                     (t (message status)))
+        )
+    (error (message (prin1-to-string err-signal))))
+  )
+
+(defun twittering-get-response-header (&optional buffer)
+  "Exract HTTP response header from HTTP response.
+`buffer' may be a buffer or the name of an existing buffer.
+ If `buffer' is omitted, the value of `twittering-http-buffer' is used as `buffer'."
+  (if (stringp buffer) (setq buffer (get-buffer buffer)))
+  (if (null buffer) (setq buffer (twittering-http-buffer)))
+  (save-excursion
+    (set-buffer buffer)
+    (let ((content (buffer-string)))
+      (substring content 0 (string-match "\r?\n\r?\n" content)))))
+
+(defun twittering-get-response-body (&optional buffer)
+  "Exract HTTP response body from HTTP response, parse it as XML, and return a XML tree as list.
+`buffer' may be a buffer or the name of an existing buffer.
+ If `buffer' is omitted, the value of `twittering-http-buffer' is used as `buffer'."
+  (if (stringp buffer) (setq buffer (get-buffer buffer)))
+  (if (null buffer) (setq buffer (twittering-http-buffer)))
+  (save-excursion
+    (set-buffer buffer)
+    (let ((content (buffer-string)))
+      (let ((content (buffer-string)))
+        (xml-parse-region (+ (string-match "\r?\n\r?\n" content)
+                             (length (match-string 0 content)))
+                          (point-max)))
+      )))
+
+(defun twittering-cache-status-datum (status-datum &optional data-var)
+  "Cache status datum into data-var(default twittering-friends-timeline-data)
+If STATUS-DATUM is already in DATA-VAR, return nil. If not, return t."
+  (if (null data-var)
+      (setf data-var 'twittering-friends-timeline-data))
+  (let ((id (cdr (assq 'id status-datum))))
+    (if (or (null (symbol-value data-var))
+            (not (find-if
+                  (lambda (item)
+                    (eql id (cdr (assq 'id item))))
+                  (symbol-value data-var))))
+        (progn
+          (if twittering-jojo-mode
+              (twittering-update-jojo (cdr (assq 'user-screen-name status-datum))
+                                      (cdr (assq 'text status-datum))))
+          (set data-var (cons status-datum (symbol-value data-var)))
+          t)
+      nil)))
+
+(defun twittering-status-to-status-datum (status)
+  (flet ((assq-get (item seq)
+                   (car (cddr (assq item seq)))))
+    (let* ((status-data (cddr status))
+           id text source created-at truncated
+           (user-data (cddr (assq 'user status-data)))
+           user-id user-name
+           user-screen-name
+           user-location
+           user-description
+           user-profile-image-url
+           user-url
+           user-protected
+           regex-index)
+
+      (setq id (string-to-number (assq-get 'id status-data)))
+      (setq text (twittering-decode-html-entities
+                  (assq-get 'text status-data)))
+      (setq source (twittering-decode-html-entities
+                    (assq-get 'source status-data)))
+      (setq created-at (assq-get 'created_at status-data))
+      (setq truncated (assq-get 'truncated status-data))
+      (setq user-id (string-to-number (assq-get 'id user-data)))
+      (setq user-name (twittering-decode-html-entities
+                       (assq-get 'name user-data)))
+      (setq user-screen-name (twittering-decode-html-entities
+                              (assq-get 'screen_name user-data)))
+      (setq user-location (twittering-decode-html-entities
+                           (assq-get 'location user-data)))
+      (setq user-description (twittering-decode-html-entities
+                              (assq-get 'description user-data)))
+      (setq user-profile-image-url (assq-get 'profile_image_url user-data))
+      (setq user-url (assq-get 'url user-data))
+      (setq user-protected (assq-get 'protected user-data))
+
+      ;; make username clickable
+      (add-text-properties 0 (length user-screen-name)
+                           `(mouse-face highlight
+                                        uri ,(concat "http://twitter.com/" user-screen-name)
+                                        username ,user-screen-name
+                                        face twittering-username-face)
+                           user-screen-name)
+
+      ;; make URI clickable
+      (setq regex-index 0)
+      (while regex-index
+        (setq regex-index
+              (string-match "@\\([_a-zA-Z0-9]+\\)\\|\\(https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+\\)"
+                            text
+                            regex-index))
+        (when regex-index
+          (let* ((matched-string (match-string-no-properties 0 text))
+                 (screen-name (match-string-no-properties 1 text))
+                 (uri (match-string-no-properties 2 text)))
+            (add-text-properties
+             (if screen-name
+                 (+ 1 (match-beginning 0))
+               (match-beginning 0))
+             (match-end 0)
+             (if screen-name
+                 `(mouse-face
+                   highlight
+                   face twittering-uri-face
+                   username ,screen-name
+                   uri ,(concat "http://twitter.com/" screen-name))
+               `(mouse-face highlight
+                            face twittering-uri-face
+                            uri ,uri))
+             text))
+          (setq regex-index (match-end 0)) ))
+
+      ;; make screen-name clickable
+      (add-text-properties
+       0 (length user-screen-name)
+       `(mouse-face highlight
+                    face twittering-username-face
+                    uri ,(concat "http://twitter.com/" user-screen-name)
+                    username ,user-screen-name)
+       user-screen-name)
+
+      ;; make source pretty and clickable
+      (if (string-match "<a href=\"\\(.*\\)\">\\(.*\\)</a>" source)
+          (let ((uri (match-string-no-properties 1 source))
+                (caption (match-string-no-properties 2 source)))
+            (setq source caption)
+            (add-text-properties
+             0 (length source)
+             `(mouse-face highlight
+                          uri ,uri
+                          face twittering-uri-face
+                          source ,source)
+             source)
+            ))
+
+      (mapcar
+       (lambda (sym)
+         `(,sym . ,(symbol-value sym)))
+       '(id text source created-at truncated
+            user-id user-name user-screen-name user-location
+            user-description
+            user-profile-image-url
+            user-url
+            user-protected)))))
+
+(defun twittering-xmltree-to-status (xmltree)
+  (mapcar #'twittering-status-to-status-datum
+          ;; quirk to treat difference between xml.el in Emacs21 and Emacs22
+          ;; On Emacs22, there may be blank strings
+          (let ((ret nil) (statuses (reverse (cddr (car xmltree)))))
+            (while statuses
+              (if (consp (car statuses))
+                  (setq ret (cons (car statuses) ret)))
+              (setq statuses (cdr statuses)))
+            ret)))
+
+(defun twittering-percent-encode (str &optional coding-system)
+  (if (or (null coding-system)
+          (not (coding-system-p coding-system)))
+      (setq coding-system 'utf-8))
+  (mapconcat
+   (lambda (c)
+     (cond
+      ((twittering-url-reserved-p c)
+       (char-to-string c))
+      ((eq c ? ) "+")
+      (t (format "%%%x" c))))
+   (encode-coding-string str coding-system)
+   ""))
+
+(defun twittering-url-reserved-p (ch)
+  (or (and (<= ?A ch) (<= ch ?z))
+      (and (<= ?0 ch) (<= ch ?9))
+      (eq ?. ch)
+      (eq ?- ch)
+      (eq ?_ ch)
+      (eq ?~ ch)))
+
+(defun twittering-decode-html-entities (encoded-str)
+  (if encoded-str
+      (let ((cursor 0)
+            (found-at nil)
+            (result '()))
+        (while (setq found-at
+                     (string-match "&\\(#\\([0-9]+\\)\\|\\([A-Za-z]+\\)\\);"
+                                   encoded-str cursor))
+          (when (> found-at cursor)
+            (list-push (substring encoded-str cursor found-at) result))
+          (let ((number-entity (match-string-no-properties 2 encoded-str))
+                (letter-entity (match-string-no-properties 3 encoded-str)))
+            (cond (number-entity
+                   (list-push
+                    (char-to-string
+                     (twittering-ucs-to-char
+                      (string-to-number number-entity))) result))
+                  (letter-entity
+                   (cond ((string= "gt" letter-entity) (list-push ">" result))
+                         ((string= "lt" letter-entity) (list-push "<" result))
+                         (t (list-push "?" result))))
+                  (t (list-push "?" result)))
+            (setq cursor (match-end 0))))
+        (list-push (substring encoded-str cursor) result)
+        (apply 'concat (nreverse result)))
+    ""))
+
+(defun twittering-timer-action (func)
+  (let ((buf (get-buffer twittering-buffer)))
+    (if (null buf)
+        (twittering-stop)
+      (funcall func)
+      )))
+
+(defun twittering-update-status-if-not-blank (status)
+  (if (string-match "^\\s-*\\(?:@[-_a-z0-9]+\\)?\\s-*$" status)
+      nil
+    (twittering-http-post "statuses" "update"
+                          `(("status" . ,status)
+                            ("source" . "twmode")))
+    t))
+
+(defun twittering-update-status-from-minibuffer (&optional init-str)
+  (if (null init-str) (setq init-str ""))
+  (let ((status init-str) (not-posted-p t))
+    (while not-posted-p
+      (setq status (read-from-minibuffer "status: " status nil nil nil nil t))
+      (setq not-posted-p
+            (not (twittering-update-status-if-not-blank status))))))
+
+(defun twittering-update-lambda ()
+  (interactive)
+  (twittering-http-post
+   "statuses" "update"
+   `(("status" . "\xd34b\xd22b\xd26f\xd224\xd224\xd268\xd34b")
+     ("source" . "twmode"))))
+
+(defun twittering-update-jojo (usr msg)
+  (if (string-match "\xde21\xd24b\\(\xd22a\xe0b0\\|\xdaae\xe6cd\\)\xd24f\xd0d6\\([^\xd0d7]+\\)\xd0d7\xd248\xdc40\xd226"
+                    msg)
+      (twittering-http-post
+       "statuses" "update"
+       `(("status" . ,(concat
+                       "@" usr " "
+                       (match-string-no-properties 2 msg)
+                       "\xd0a1\xd24f\xd243!?"))
+         ("source" . "twmode")))))
+
+;;;
+;;; Commands
+;;;
+
+(defun twittering-start (&optional action)
+  (interactive)
+  (if (null action)
+      (setq action #'twittering-friends-timeline))
+  (if twittering-timer
+      nil
+    (setq twittering-timer
+          (run-at-time "0 sec"
+                       twittering-timer-interval
+                       #'twittering-timer-action action))))
+
+(defun twittering-stop ()
+  (interactive)
+  (cancel-timer twittering-timer)
+  (setq twittering-timer nil))
+
+(defun twittering-friends-timeline ()
+  (interactive)
+  (let ((buf (get-buffer twittering-buffer)))
+    (if (not buf)
+        (twittering-stop)
+      (twittering-http-get "statuses" "friends_timeline")
+      ))
+
+  (if twittering-icon-mode
+      (if twittering-image-stack
+          (let ((proc
+                 (apply
+                  #'start-process
+                  "wget-images"
+                  (twittering-wget-buffer)
+                  "wget"
+                  (format "--directory-prefix=%s" twittering-tmp-dir)
+                  "--no-clobber"
+                  "--quiet"
+                  twittering-image-stack)))
+            (set-process-sentinel
+             proc
+             (lambda (proc stat)
+               (clear-image-cache)
+               (save-excursion
+                 (set-buffer (twittering-wget-buffer))
+                 )))))))
+
+(defun twittering-update-status-interactive ()
+  (interactive)
+  (twittering-update-status-from-minibuffer))
+
+(defun twittering-erase-old-statuses ()
+  (interactive)
+  (setq twittering-friends-timeline-data nil)
+  (twittering-http-get "statuses" "friends_timeline"))
+
+(defun twittering-click ()
+  (interactive)
+  (let ((uri (get-text-property (point) 'uri)))
+    (if uri
+        (browse-url uri))))
+
+(defun twittering-enter ()
+  (interactive)
+  (let ((username (get-text-property (point) 'username))
+        (uri (get-text-property (point) 'uri)))
+    (if username
+        (twittering-update-status-from-minibuffer (concat "@" username " "))
+      (if uri
+          (browse-url uri)))))
+
+(defun twittering-view-user-page ()
+  (interactive)
+  (let ((uri (get-text-property (point) 'uri)))
+    (if uri
+        (browse-url uri))))
+
+(defun twittering-reply-to-user ()
+  (interactive)
+  (let ((username (get-text-property (point) 'username)))
+    (if username
+        (twittering-update-status-from-minibuffer (concat "@" username " ")))))
+
+(defun twittering-get-password ()
+  (or twittering-password
+      (setq twittering-password (read-passwd "twittering-mode: "))))
+
+(defun twittering-goto-next-status ()
+  "Go to next status."
+  (interactive)
+  (let ((pos))
+    (setq pos (twittering-get-next-username-face-pos (point)))
+    (when pos
+      (goto-char pos))))
+
+(defun twittering-get-next-username-face-pos (pos)
+  (interactive)
+  (let ((prop))
+    (while (not (eq prop twittering-username-face))
+      (setq pos (next-single-property-change pos 'face))
+      (setq prop (get-text-property pos 'face)))
+    pos))
+
+(defun twittering-goto-previous-status ()
+  "Go to previous status."
+  (interactive)
+  (let ((pos))
+    (setq pos (twittering-get-previous-username-face-pos (point)))
+    (when pos
+      (goto-char pos))))
+
+(defun twittering-get-previous-username-face-pos (pos)
+  (interactive)
+  (let ((prop))
+    (while (not (eq prop twittering-username-face))
+      (setq pos (previous-single-property-change pos 'face))
+      (setq prop (get-text-property pos 'face)))
+    pos))
+
+(defun twittering-goto-next-status-of-user ()
+  "Go to next status of user."
+  (interactive)
+  (let ((user-name (twittering-get-username-at-pos (point)))
+        (pos (twittering-get-next-username-face-pos (point))))
+    (while (not (equal (twittering-get-username-at-pos pos) user-name))
+      (setq pos (twittering-get-next-username-face-pos pos)))
+    (goto-char pos)))
+
+(defun twittering-goto-previous-status-of-user ()
+  "Go to previous status of user."
+  (interactive)
+  (let ((user-name (twittering-get-username-at-pos (point)))
+        (pos (twittering-get-previous-username-face-pos (point))))
+    (while (not (equal (twittering-get-username-at-pos pos) user-name))
+      (setq pos (twittering-get-previous-username-face-pos pos)))
+    (goto-char pos)))
+
+(defun twittering-get-username-at-pos (pos)
+  (let ((start-pos pos)
+        (end-pos))
+    (while (eq (get-text-property start-pos 'face) twittering-username-face)
+      (setq start-pos (1- start-pos)))
+    (setq start-pos (1+ start-pos))
+    (setq end-pos (next-single-property-change pos 'face))
+    (buffer-substring start-pos end-pos)))
+
+(provide 'twittering-mode)
+;;; twittering.el ends here
Index: lang/elisp/twittering-mode/branches/tsuyoshi/ChangeLog
===================================================================
--- lang/elisp/twittering-mode/branches/tsuyoshi/ChangeLog (revision 31)
+++ lang/elisp/twittering-mode/branches/tsuyoshi/ChangeLog (revision 31)
@@ -0,0 +1,172 @@
+2008-04-26  gan2  <gan2.ruby@gmail.com>
+
+	* twittering-mode.el: n, p でポイント上のユーザの次(前)の発言に移動する設定を追加
+	(twittering-goto-next-status): twittering-next-message の名前を変更
+	(twittering-get-next-username-face-pos): twittering-next-username-face-pos の名前を変更
+	(twittering-goto-previous-status): twittering-previous-message の名前を変更
+	(twittering-get-previous-username-face-pos): twittering-previous-username-face-pos の名前を変更
+	(twittering-goto-next-status-of-user): ポイント上のユーザの次の発言へ移動する関数を定義
+	(twittering-goto-previous-status-of-user): ポイント上のユーザの前の発言へ移動する関数を定義
+	(twittering-get-username-at-pos): ポイント上のユーザ名を返す関数を定義
+	(twittering-mode-map): n, p でポイント上のユーザの次(前)の発言に移動する設定を追加
+
+2008-04-25  gan2  <gan2.ruby@gmail.com>
+
+	* twittering-mode.el: next-line や previous-line は C-n や C-p でできるので j, k を隣接したメッセージの移動に変更
+	(twittering-next-message): 次のメッセージにジャンプする関数を定義
+	(twittering-next-username-face-pos): twittering-next-message が呼び出す関数を定義
+	(twittering-previous-message): 前のメッセージにジャンプする関数を定義
+	(twittering-previous-username-face-pos): twittering-previous-message が呼び出す関数を定義
+	(twittering-mode-map): j, k で次のメッセージと前のメッセージに移動するように変更
+
+2008-04-23  gan2  <gan2.ruby@gmail.com>
+
+	* twittering-mode.el : RB-0.3 を gan2 にコピー. ソフトタブに統一
+	(twittering-mode-version): バージョンを表示する関数を定義
+
+2008-03-15  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el : pushをfree variableと誤認識されるバグ(再現できていない)のため,clのpushをlist-pushで置きかえ.
+	(list-push): clのpushの代替として定義.
+
+2008-02-08  Tsuyoshi CHO  <Tsuyoshi.CHO+develop@Gmail.com>
+
+	* twittering-mode.el : 全体的に整形、Proxy、Safe Password、
+	User-Agent、Major mode stringを対応。Version 0.3
+	(twittering-mode-version): 暫定のバージョン定数を定義
+	(twittering-proxy-use): プロキシ関係設定を導入 from <http://d.hatena.ne.jp/lurdan/20080108/1199775387>
+	(twittering-proxy-server): 同上
+	(twittering-proxy-port, twittering-proxy-user): 同上
+	(twittering-proxy-password): 同上
+	(twittering-toggle-proxy): 同上
+	(twittering-user-agent-default-function): 同上
+	(twittering-user-agent-default-function): デフォルトUser-Agent生成関数
+	(twittering-user-agent-function): User-Agent生成関数指定変数を導入
+	(twittering-user-agent): 内部でのUser-Agent生成関数
+	(twittering-tmp-dir): ユーザー固有のImageTmpDirを生成 from <http://d.hatena.ne.jp/odz/20071021/1192957783>
+	(twittering-mode-map): プロキシの有効無効のキーバインド定義
+	(twittering-mode-string): メジャーモード文字列を変数定義
+	(twittering-mode): メジャーモード開始時に文字列を設定
+	(twittering-http-get): プロキシ、User-Agentによる処理を追加
+	(twittering-http-post): 同上
+	(twittering-get-password): パスワードを動的に確認する関数を定義
+
+2007-10-14  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el : Naoya T. <naoya.t@aqua.plala.or.jp>, masa_edw のパッチをとりこむ
+	(twittering-url-encode): 使わないので削除
+	(twittering-decode-html-entities): patched: 数値エンティティだけでなく,asciiエンティティにも対応.
+	(twittering-font-lock-keywords): font-lock-keywordsを削除.text propertyによって設定する.
+	(twittering-format-status): patched: statusとformat-strからstatusの表示用文字列を生成.
+	(twittering-scroll-mode): patched: 新しいtwitがあったときに,カーソルもスクロールするか固定するかを設定するマイナモード, masa_edwのパッチ
+	(twittering-status-format): twitの表示方法をきめるテンプレート文字列
+	(twittering-icon-mode): patched: ifをwhenにおかえた.nilを渡されたときはマイナモードのスイッチに振舞を変更
+	(twittering-local-strftime): patched: 時間をフォーマット文字列に従い文字列化
+	(twittering-mode-init-variables): font-lock-modeは,Emacs21系ではautoloadするために一度呼ぶ必要がある. icon-mode, scroll-modeをマイナモードに登録.
+	(twittering-inspect-object): 使わないので削除
+	(twittering-http-get-default-sentinel): エラーを追いやすくするため,condition-caseを廃止
+	(twittering-status-to-status-datum): 全てのデータを抽出するようコード追加.ユーザ名,URIリンク表示などの処理もここで.
+
+2007-10-13  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-font-lock-keywords): ユーザー名のフェイスを適用する規則を修正.アイコン画像を表示したときに,下線が画像にかからないようにした.
+	(twittering-render-friends-timeline): ポイントが特定のtwitに対して固定されるようにした(patch from masa_edw)
+
+2007-10-12  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-idle-time): つかわないので削除
+	(twittering-get-or-generate-buffer): バッファ取得のための関数.存在しないバッファだったら,新たに生成して返す.
+	(twittering-buffer): Variable:twittering-bufferを名前に持つバッファを返す関数.このバッファを使う場合は,(twittering-buffer)によって取得する.
+	(twittering-http-buffer): twittering-bufferと同じ
+	(twittering-wget-buffer): twittering-bufferと同じ
+	
+
+2007-10-11  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-icon-mode): アイコンを表示するか否かのフラグ
+	(twittering-wget-buffer): アイコン画像をwgetで取得するプロセスのバッファ
+	(twittering-icon-mode): アイコンの表示/非表示を切り換えるコマンド
+	(twittering-tmp-dir): アイコンの画像を保存するディレクトリ
+	(twittering-image-stack): ダウンロードすべきアイコン画像のリスト
+	(twittering-image-type): 画像の種類を判別する関数
+	(twittering-render-friends-timeline): friends timelineを表示する部分を切り出した
+
+2007-10-10  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el: バージョン番号をつけた 0.1.0
+
+2007-10-07  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-http-get-default-sentinel): http-bufferを毎回生成-削除するのをやめて,内容をeraseして使い回すようにした.
+	(twittering-http-get-default-sentinel):HTTPレスポンスのステータスコードが上手く拾えなかったときの処理を追加
+	(twittering-http-get-default-sentinel): カレントバッファか*twittering*のときは,friends-timelineを更新してもポイントの位置が変わらないように修正.
+
+2007-09-24  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-status-to-status-datum): URIをクリック可能にする処理を追加
+
+2007-09-23  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-uri-face): URI用のフェイス
+	(twittering-click): クリック時に実行されるコマンド
+	(twittering-enter): EnterかC-mが押されたときに実行されるコマンド
+
+2007-09-19  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-mode-syntax-table): "(double quote)を,文字列クオートと認識しないようにsytax-tableを変更.
+	(twittering-friends-timeline): friends timelineの取得したデータを保存しておく変数.twittering modeが起動している限り,この変数に取得したstatusを随時追加してゆく.
+	(cl): assocrefをinnner defunして,バイトコンパイル時にWarningが出ていた.clパッケージのfletを使うことでWarningが出ないように解決した.
+	(twittering-status-to-status-datum): twittering-status-to-lineから名前変更
+	(twittering-friends-timeline-data): twittering-friends-timelineから名前変更
+	(twittering-status-to-status-datum): idもstatus datumに含めるようにした.
+	(twittering-cache-status-datum): status datumをdata-var(デフォルトはtwittering-friends-timeline-data)にキャッシュする関数.すでにあるstatus datumを渡すとnil,新しいstatus datumを渡すとtを返してdata-varに追加する.
+	(twittering-http-get-default-sentinel):過去のstatus datumをキャッシュして,バッファに過去のstatusも表示されるようにした.
+	(twittering-erase-old-statuses): 21件目以降の古いstatusを消す関数.実際はキャッシュを全部消して,twittering-http-getを呼んでいるだけ.C-c C-eにバインド.
+	(twittering-username-face): ユーザ名用のface.(defface <name>)の後に(defvar <name>)で使用可能になった.なぜ？
+	(twittering-status-to-status-datum): ユーザ名のテキストにmouse-face属性と,uri属性(ユーザのページのURI)を付加するようにした.
+	(twittering-click-username): ユーザ名をクリックするか,C-mを押したときに起動するコマンド.
+	(twittering-mode-map): vimライクなキーバインドを追加
+	(twittering-mode): twittering-mode-hookでfont-lock-defaultsが設定された後に,font-lock-mode を2回呼んで変更を反映させるようにした.
+	(twittering-mode-init-variables): twittering-username-faceの定義をこの関数の中にうつした.
+	(twittering-browse-user-page): twittering-click-usernameから名前変更.
+	(twittering-update-status-interactive): twittering-update-statusから名前変更.
+	(twittering-reply-to-user): ユーザ名上でEnterを押すとこの関数が呼びだされるようにキーバインド変更.ミニバッファに @<ユーザ名> が自動挿入される.
+	(twittering-view-user-page): twittering-browse-user-pageから名前変更.C-c C-vにバインド.
+	(twittering-update-status-if-not-blank): 引数statusが,空白文字のみか, @<ユーザ名> のみの場合には nil を返し,他の文字も含む場合には POSTしてtを返す関数.
+	(twittering-update-status-from-minibuffer): ミニバッファからstatusを更新するための関数.無効な文字(twittering-update-status-if-not-blankで判定)が入力された場合は,有効な文字列が入力されるまでループする.
+
+2007-09-12  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-ucs-to-char): Emacs21系では,Mule-UCSがロードされていないと,(decode-char 'ucs HOGE)がnilになり,文字コードを取得できないことがある.そこで,ucs-to-charが使える環境ではucs-to-charを,使えない環境(Emacs22など)ではdecode-charを使うように自動で切り替えるマクロを書いた.
+
+2007-09-10  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el (twittering-refresh-buffer): 使わないので削除
+	(twittering-http-post-default-sentinel): condition-case でエラーハンドリングするようにした.
+	(twittering-http-get-default-sentinel): *twittering*バッファをread-onlyにした
+	(twittering-http-post-default-sentinel): condition-case でエラーハンドリングするコードを追加.
+	(twittering-start): 複数のタイマが走らないように,twittering-timerがnilでない=既存のタイマが走っている場合は一旦twittering-stopを呼び出してからタイマをスタートするようにした.
+
+2007-09-09  Y. Hayamizu  <haya@haya-laptop-ubuntu>
+
+	* twittering-mode.el: リリース
+	(case-string): CarbonEmacs (Emacs22)で,case-stringを呼びだすコードよりも前にdefmacroを持ってきたら,警告が出ないという報告.
+	(twittering-decode-html-entities): ucs-to-charの使用をやめ,(decode-char 'ucs ...)を使うことに. (reported by masa_edw)
+	(twittering-update-status): read-from-minibufferの7番目の引数にtを指定し,input methodをカレントバッファから継承するようにした.
+	(twittering-decode-html-entities): string-to-intはobsoleteなので,string-to-numberに変更 (reported by masa_edw)
+	(twittering-get-response-header): (setq (get-buffer ...)) となっていたので,(setq buffer (get-buffer ...))に修正. twittering-get-response-bodyも同様
+	(twittering-timer-action): twittering-refresh-triggerは既に使っていない変数だったので削除した
+	(debug-print): マクロが最初にコンパイルされる時点では,debug-modeが変数として宣言されていないので,debug-modeの判断まで含めたコードを吐くようにした.
+	(twittering-http-post-default-sentinel): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに伴い書き換えた
+	(twittering-get-response-body): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに伴い書き換えた
+	(twittering-xmltree-to-status): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに伴い書き換えた
+	(twittering-status-lines): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに伴い書き換えた
+	(twittering-status-to-line): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに伴い書き換えた
+	(twittering-get-timeline): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに削除
+	(twittering-status-lines): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに削除
+	(twittering-parse-xml): xml-parse.elのかわりに,xml.el(Emacs標準？)を使うように変更したことに削除
+	(twittering-timer-interval): twittering-refresh-intervalから名前変更
+	(twittering-inspect-object): 任意のLispオブジェクトを文字列で表現できるユーティリティ関数
+	(twittering-timer-action): xml.elにより処理が軽くなったので,一定時間間隔での更新に変更.
+	(twittering-xmltree-to-status): Emacs21とEmacs22のxml.elの差異を吸収するコードを追加.Emacs22では,ノードのリストに空の文字列が混入することがあるため,文字列を除去するようにした.
+
Index: lang/elisp/twittering-mode/branches/tsuyoshi/makefile
===================================================================
--- lang/elisp/twittering-mode/branches/tsuyoshi/makefile (revision 10)
+++ lang/elisp/twittering-mode/branches/tsuyoshi/makefile (revision 10)
@@ -0,0 +1,17 @@
+
+EMACS21 = /home/haya/usr/bin/emacs-21.4
+EMACS22 = /home/haya/usr/bin/emacs-22.1
+
+batchtest : twittering-mode.el
+	$(EMACS21) --no-init-file --batch -f batch-byte-compile twittering-mode.el
+	rm twittering-mode.elc
+	$(EMACS22) --no-init-file --batch -f batch-byte-compile twittering-mode.el
+	rm twittering-mode.elc
+
+test : twittering-mode.el
+	$(EMACS21) -q -l local.test-emacs21.el &
+	$(EMACS22) -q -l local.test-emacs22.el &
+
+clean : 
+	rm twittering-mode.elc
+
Index: lang/elisp/twittering-mode/branches/tsuyoshi/TAGS
===================================================================
--- lang/elisp/twittering-mode/branches/tsuyoshi/TAGS (revision 28)
+++ lang/elisp/twittering-mode/branches/tsuyoshi/TAGS (revision 28)
@@ -0,0 +1,82 @@
+
+C:\home\mshoji\site-lisp\twittering-mode\branches\gan2\twittering-mode.el,6271
+(defconst twittering-mode-version "0.3")twittering-mode-version48,1587
+(defun twittering-mode-version ()twittering-mode-version50,1629
+(defvar twittering-mode-map (make-sparse-keymap))twittering-mode-map59,1907
+(defvar twittering-timer nil "Timer object for timeline refreshing will be stored here. DO NOT SET VALUE MANUALLY.")twittering-timer61,1958
+(defvar twittering-idle-time 20)twittering-idle-time63,2076
+(defvar twittering-timer-interval 90)twittering-timer-interval65,2110
+(defvar twittering-username nil)twittering-username67,2149
+(defvar twittering-password nil)twittering-password69,2183
+(defvar twittering-scroll-mode nil)twittering-scroll-mode71,2217
+(defvar twittering-jojo-mode nil)twittering-jojo-mode73,2254
+(defvar twittering-status-format nil)twittering-status-format75,2289
+(defvar twittering-buffer "*twittering*")twittering-buffer94,2722
+(defun twittering-buffer ()twittering-buffer95,2764
+(defvar twittering-http-buffer "*twittering-http-buffer*")twittering-http-buffer98,2850
+(defun twittering-http-buffer ()twittering-http-buffer99,2909
+(defvar twittering-friends-timeline-data nil)twittering-friends-timeline-data102,3005
+(defvar twittering-username-face 'twittering-username-face)twittering-username-face104,3052
+(defvar twittering-uri-face 'twittering-uri-face)twittering-uri-face105,3112
+(defun twittering-get-or-generate-buffer (buffer)twittering-get-or-generate-buffer107,3163
+(defun assocref (item alist)assocref116,3413
+(defmacro list-push (value listvar)list-push118,3470
+(defvar twittering-proxy-use nil)twittering-proxy-use122,3560
+(defvar twittering-proxy-server nil)twittering-proxy-server123,3594
+(defvar twittering-proxy-port 8080)twittering-proxy-port124,3631
+(defvar twittering-proxy-user nil)twittering-proxy-user125,3667
+(defvar twittering-proxy-password nil)twittering-proxy-password126,3702
+(defun twittering-toggle-proxy () ""twittering-toggle-proxy128,3742
+(defun twittering-user-agent-default-function ()twittering-user-agent-default-function137,3941
+(defvar twittering-user-agent-function 'twittering-user-agent-default-function)twittering-user-agent-function146,4205
+(defun twittering-user-agent ()twittering-user-agent148,4286
+(defvar twittering-wget-buffer "*twittering-wget-buffer*")twittering-wget-buffer154,4425
+(defun twittering-wget-buffer ()twittering-wget-buffer155,4484
+(defvar twittering-tmp-dirtwittering-tmp-dir158,4580
+(defvar twittering-icon-mode nil "You MUST NOT CHANGE this variable directory. You should change through function'twittering-icon-mode'")twittering-icon-mode162,4705
+(defun twittering-icon-mode (&optional arg)twittering-icon-mode163,4843
+(defun twittering-scroll-mode (&optional arg)twittering-scroll-mode179,5304
+(defun twittering-jojo-mode (&optional arg)twittering-jojo-mode186,5487
+(defvar twittering-image-stack nil)twittering-image-stack193,5664
+(defun twittering-image-type (file-name)twittering-image-type195,5701
+(defun twittering-local-strftime (fmt string)twittering-local-strftime202,5899
+(defvar twittering-debug-mode nil)twittering-debug-mode206,6077
+(defvar twittering-debug-buffer "*debug*")twittering-debug-buffer207,6112
+(defun twittering-debug-buffer ()twittering-debug-buffer208,6155
+(defmacro debug-print (obj)debug-print210,6252
+(defun twittering-debug-mode ()twittering-debug-mode220,6500
+(defvar twittering-mode-syntax-table nil "")twittering-mode-syntax-table248,7656
+(defun twittering-mode-init-variables ()twittering-mode-init-variables257,7929
+(defmacro case-string (str &rest clauses)case-string273,8596
+(defmacro twittering-ucs-to-char (num)twittering-ucs-to-char287,9018
+(defvar twittering-mode-string "Twittering mode")twittering-mode-string292,9146
+(defun twittering-mode ()twittering-mode294,9197
+(defun twittering-http-get (method-class method &optional sentinel)twittering-http-get313,9656
+(defun twittering-http-get-default-sentinel (proc stat &optional suc-msg)twittering-http-get-default-sentinel372,11498
+(defun twittering-render-friends-timeline ()twittering-render-friends-timeline393,12139
+(defun twittering-format-status (status format-str)twittering-format-status411,12706
+(defun twittering-http-posttwittering-http-post519,16417
+(defun twittering-http-post-default-sentinel (proc stat &optional suc-msg)twittering-http-post-default-sentinel585,18605
+(defun twittering-get-response-header (&optional buffer)twittering-get-response-header601,19137
+(defun twittering-get-response-body (&optional buffer)twittering-get-response-body612,19655
+(defun twittering-cache-status-datum (status-datum &optional data-var)twittering-cache-status-datum627,20319
+(defun twittering-status-to-status-datum (status)twittering-status-to-status-datum646,21049
+(defun twittering-xmltree-to-status (xmltree)twittering-xmltree-to-status750,24508
+(defun twittering-percent-encode (str &optional coding-system)twittering-percent-encode761,24926
+(defun twittering-url-reserved-p (ch)twittering-url-reserved-p775,25305
+(defun twittering-decode-html-entities (encoded-str)twittering-decode-html-entities783,25482
+(defun twittering-timer-action (func)twittering-timer-action810,26439
+(defun twittering-update-status-if-not-blank (status)twittering-update-status-if-not-blank817,26593
+(defun twittering-update-status-from-minibuffer (&optional init-str)twittering-update-status-from-minibuffer825,26835
+(defun twittering-update-lambda ()twittering-update-lambda833,27181
+(defun twittering-update-jojo (usr msg)twittering-update-jojo840,27373
+(defun twittering-start (&optional action)twittering-start855,27779
+(defun twittering-stop ()twittering-stop866,28075
+(defun twittering-friends-timeline ()twittering-friends-timeline871,28183
+(defun twittering-update-status-interactive ()twittering-update-status-interactive899,28839
+(defun twittering-erase-old-statuses ()twittering-erase-old-statuses903,28949
+(defun twittering-click ()twittering-click908,29107
+(defun twittering-enter ()twittering-enter914,29232
+(defun twittering-view-user-page ()twittering-view-user-page923,29499
+(defun twittering-reply-to-user ()twittering-reply-to-user929,29633
+(defun twittering-get-password ()twittering-get-password935,29833
