(defvar unicode-data-path
  (let ((default-load-path '("/pub/misc/character/tables/unicode/"
			     "/ftp@ftp.unicode.org:/Public/"))
	path)
    (setq path (get-latest-path "Update"))
    (if path
	(car (sort (directory-files
		    path t "UnicodeData" t)
		   (function file-newer-than-file-p))))))

(defun what-character (char)
  (interactive (list (char-after)))
  (let ((buf (get-buffer-create "*Character Description*"))
	(the-buf (current-buffer))
	(win-conf (current-window-configuration)))
    (pop-to-buffer buf)
    (make-local-variable 'what-character-original-window-configuration)
    (setq what-character-original-window-configuration win-conf)
    (setq buffer-read-only nil)
    (erase-buffer)
    (let (charset h l)
      (let ((sc (split-char char)))
	(setq charset (car sc)
	      h (nth 1 sc)
	      l (nth 2 sc)))
      (insert (format "%c\n    %s (%s): "
		      char charset (charset-description charset)))
      (insert (if l
		  (format "#x%02X%02X, %02d-%02d\n"
			  h l (- h 32) (- l 32))
		(format "#x%02X, %d/%d\n"
			h (lsh h -4) (logand h 15))))
      (let ((ucs (char-ucs char)))
	(when ucs
	  (insert (format "    UCS: %08X" ucs))
	  (if unicode-data-path
	      (let ((str
		     (with-current-buffer
			 (find-file-noselect unicode-data-path)
		       (goto-char (point-min))
		       (if (re-search-forward (format "^%04X;" ucs) nil t)
			   (buffer-substring (match-end 0)(point-at-eol))
			 ))))
		(if str
		    (let ((data (split-string str ";")))
		      (insert (format " (%s)\n" (nth 0 data)))
		      (insert
		       (format "    General Category: %s\n"
			       (cdr
				(assoc
				 (nth 1 data)
				 '(;; Normative
				   ("Mn" . "Mark, Non-Spacing")
				   ("Mc" . "Mark, Spacing Combining")
				   ("Me" . "Mark, Enclosing")
				   ("Nd" . "Number, Decimal Digit")
				   ("Nl" . "Number, Letter")
				   ("No" . "Number, Other")
				   ("Zs" . "Separator, Space")
				   ("Zl" . "Separator, Line")
				   ("Zp" . "Separator, Paragraph")
				   ("Cc" . "Other, Control")
				   ("Cf" . "Other, Format")
				   ("Cs" . "Other, Surrogate")
				   ("Co" . "Other, Private Use")
				   ("Cn" . "Other, Not Assigned")
				   ;; Informative
				   ("Lu" . "Letter, Uppercase")
				   ("Ll" . "Letter, Lowercase")
				   ("Lt" . "Letter, Titlecase")
				   ("Lm" . "Letter, Modifier")
				   ("Lo" . "Letter, Other")
				     
				   ("Pc" . "Punctuation, Connector")
				   ("Pd" . "Punctuation, Dash")
				   ("Ps" . "Punctuation, Open")
				   ("Pe" . "Punctuation, Close")
				   ("Pi" .
				    "Punctuation, Initial quote (may behave like Ps or Pe depending on usage)")
				   ("Pf" . "Punctuation, Final quote (may behave like Ps or Pe depending on usage)")
				   ("Po" . "Punctuation, Other")
				   
				   ("Sm" . "Symbol, Math")
				   ("Sc" . "Symbol, Currency")
				   ("Sk" . "Symbol, Modifier")
				   ("So" . "Symbol, Other")
				   )))))
		      (or (string= (nth 2 data) "")
			  (insert
			   (format "    Canonical Combining Classes: %s\n"
				   (nth 2 data))))
		      (or (string= (nth 3 data) "")
			  (insert (format "    Bidirectional Category: %s\n"
					  (nth 3 data))))
		      (or (string= (nth 4 data) "")
			  (insert (format "    Character Decomposition: %s\n"
					  (nth 4 data))))
		      (or (string= (nth 5 data) "")
			  (insert (format "    Decimal digit value: %s\n"
					  (nth 5 data))))
		      (or (string= (nth 6 data) "")
			  (insert (format "    Digit value: %s\n"
					  (nth 6 data))))
		      (or (string= (nth 7 data) "")
			  (insert (format "    Numeric value: %s\n"
					  (nth 7 data))))
		      (or (string= (nth 8 data) "")
			  (insert (format "    Mirror-able: %s\n"
					  (nth 8 data))))
		      (or (string= (nth 9 data) "")
			  (insert (format "    Unicode 1.0 Name: %s\n"
					  (nth 9 data))))
		      (or (string= (nth 10 data) "")
			  (insert (format "    10646 Comment: %s\n"
					  (nth 10 data))))
		      (or (string= (nth 11 data) "")
			  (insert (format "    Uppercase = %s\n"
					  (nth 11 data))))
		      (or (string= (nth 12 data) "")
			  (insert (format "    Lowercase = %s\n"
					  (nth 12 data))))
		      (or (string= (nth 13 data) "")
			  (insert (format "    Title-case = %s\n"
					  (nth 13 data))))
		      )
		  (insert "\n"))
		)))))
    (set-buffer-modified-p nil)
    (view-mode the-buf (lambda (buf)
			 (set-window-configuration
			  what-character-original-window-configuration)
			 ))
    (goto-char (point-min))))
