view lisp/gnus/rfc1843.el @ 111413:d53ee71e7e89

Unify mouse-highlight code for all GUI and TTY sessions. term.c: Remove static mouse_face_* variables. All users changed. (term_show_mouse_face, term_clear_mouse_face) (fast_find_position, term_mouse_highlight): Functions deleted. (tty_draw_row_with_mouse_face): New function. (term_mouse_movement): Call note_mouse_highlight instead of term_mouse_highlight. nsterm.m (ns_update_window_begin, ns_update_window_end) (ns_update_end, x_destroy_window, ns_frame_up_to_date) (ns_dumpglyphs_box_or_relief, ns_maybe_dumpglyphs_background) (ns_dumpglyphs_image, ns_dumpglyphs_stretch) (ns_initialize_display_info, keyDown, mouseMoved, mouseExited): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. xterm.c (x_update_window_begin, x_update_window_end) (x_update_end, XTframe_up_to_date, x_set_mouse_face_gc) (handle_one_xevent, x_free_frame_resources, x_term_init): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. w32term.c (x_update_window_begin, x_update_window_end) (x_update_end, w32_read_socket, x_free_frame_resources) (w32_initialize_display_info): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. xdisp.c (show_mouse_face, note_mode_line_or_margin_highlight) (note_mouse_highlight) [HAVE_WINDOW_SYSTEM]: Don't run GUI code unless the frame is on a window-system. (get_tool_bar_item, handle_tool_bar_click) (note_tool_bar_highlight, draw_glyphs, erase_phys_cursor) (show_mouse_face, clear_mouse_face, coords_in_mouse_face_p) (note_mode_line_or_margin_highlight, note_mouse_highlight) (x_clear_window_mouse_face, cancel_mouse_face, expose_frame): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. (coords_in_mouse_face_p): Move prototype out of the HAVE_WINDOW_SYSTEM conditional. (x_y_to_hpos_vpos, frame_to_window_pixel_xy): Move out of the HAVE_WINDOW_SYSTEM block. (try_window_id) [HAVE_GPM || MSDOS]: Call x_clear_window_mouse_face. (draw_row_with_mouse_face): Implementation for HAVE_WINDOW_SYSTEM systems. Call tty_draw_row_with_mouse_face for TTY systems. (show_mouse_face): Call draw_row_with_mouse_face, instead of calling draw_glyphs directly. (show_mouse_face, clear_mouse_face, coords_in_mouse_face_p) (cursor_in_mouse_face_p, rows_from_pos_range) (mouse_face_from_buffer_pos, mouse_face_from_string_pos) (note_mode_line_or_margin_highlight, note_mouse_highlight) (x_clear_window_mouse_face, cancel_mouse_face): Move out of the HAVE_WINDOW_SYSTEM block. Ifdef away window-system specific fragments. (note_mouse_highlight): Call popup_activated for MSDOS as well. Clear mouse highlight if pointer is over glyphs whose OBJECT is an integer. (mouse_face_from_buffer_pos): Add parentheses around && within ||. (x_consider_frame_title, tool_bar_lines_needed): Move prototypes to HAVE_WINDOW_SYSTEM-only part. (get_window_cursor_type): Move inside a HAVE_WINDOW_SYSTEM-only part. Remove "#ifdef HAVE_WINDOW_SYSTEM" from body of function. (null_glyph_slice): Move declaration into HAVE_WINDOW_SYSTEM-only part. dispnew.c (mirror_make_current): Set Y coordinate of the mode-line and header-line rows. (init_display): Setup initial frame's output_data for text terminal frames. xmenu.c (popup_activated): Don't define on MSDOS, which now has its own definition on msdos.c. msdos.c (show_mouse_face, clear_mouse_face) (fast_find_position, IT_note_mode_line_highlight) (IT_note_mouse_highlight): Functions deleted. (IT_frame_up_to_date, dos_rawgetc): Call note_mouse_highlight instead of IT_note_mouse_highlight. (draw_row_with_mouse_face, popup_activated): New functions. (dos_set_window_size, draw_row_with_mouse_face, IT_update_begin) (IT_update_end, IT_frame_up_to_date, internal_terminal_init) (dos_rawgetc): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. msdos.h (initialize_msdos_display): Add prototype. frame.h (MOUSE_HL_INFO): New macro. lisp.h (Mouse_HLInfo): New data type. xterm.h (struct x_display_info): w32term.h (struct w32_display_info): nsterm.h (struct ns_display_info): termchar.h (struct tty_display_info): Use it instead of mouse_face_* members. dispextern.h (show_mouse_face, clear_mouse_face): Update type of 1st argument. (frame_to_window_pixel_xy, note_mouse_highlight) (x_clear_window_mouse_face, cancel_mouse_face, clear_mouse_face) (show_mouse_face, cursor_in_mouse_face_p): Move prototypes out of HAVE_WINDOW_SYSTEM conditional. (draw_row_with_mouse_face): Declare prototype. (tty_draw_row_with_mouse_face): Declare prototype.
author Eli Zaretskii <eliz@gnu.org>
date Sat, 06 Nov 2010 10:28:31 +0200
parents 236342431786
children 417b1e4d63cd
line wrap: on
line source

;;; rfc1843.el --- HZ (rfc1843) decoding

;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;;   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.

;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: news HZ HZ+ mail i18n

;; This file is part of GNU Emacs.

;; GNU Emacs 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 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs 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.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; Usage:
;; (require 'rfc1843)
;; (rfc1843-gnus-setup)
;;
;; Test:
;; (rfc1843-decode-string  "~{<:Ky2;S{#,NpJ)l6HK!#~}")

;;; Code:

;; For Emacs <22.2 and XEmacs.
(eval-and-compile
  (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))

(eval-when-compile (require 'cl))
(require 'mm-util)

(defvar gnus-decode-encoded-word-function)
(defvar gnus-decode-header-function)
(defvar gnus-newsgroup-name)

(defvar rfc1843-word-regexp
  "~\\({\\([\041-\167][\041-\176]\\| \\)+\\)\\(~}\\|$\\)")

(defvar rfc1843-word-regexp-strictly
  "~\\({\\([\041-\167][\041-\176]\\)+\\)\\(~}\\|$\\)")

(defvar rfc1843-hzp-word-regexp
  "~\\({\\([\041-\167][\041-\176]\\| \\)+\\|\
\[<>]\\([\041-\175][\041-\176]\\| \\)+\\)\\(~}\\|$\\)")

(defvar rfc1843-hzp-word-regexp-strictly
  "~\\({\\([\041-\167][\041-\176]\\)+\\|\
\[<>]\\([\041-\175][\041-\176]\\)+\\)\\(~}\\|$\\)")

(defcustom rfc1843-decode-loosely nil
  "Loosely check HZ encoding if non-nil.
When it is set non-nil, only buffers or strings with strictly
HZ-encoded are decoded."
  :type 'boolean
  :group 'mime)

(defcustom rfc1843-decode-hzp t
  "HZ+ decoding support if non-nil.
HZ+ specification (also known as HZP) is to provide a standardized
7-bit representation of mixed Big5, GB, and ASCII text for convenient
e-mail transmission, news posting, etc.
The document of HZ+ 0.78 specification can be found at
ftp://ftp.math.psu.edu/pub/simpson/chinese/hzp/hzp.doc"
  :type 'boolean
  :group 'mime)

(defcustom rfc1843-newsgroups-regexp "chinese\\|hz"
  "Regexp of newsgroups in which might be HZ encoded."
  :type 'string
  :group 'mime)

(defun rfc1843-decode-region (from to)
  "Decode HZ in the region between FROM and TO."
  (interactive "r")
  (let (str firstc)
    (save-excursion
      (goto-char from)
      (if (or rfc1843-decode-loosely
	      (re-search-forward (if rfc1843-decode-hzp
				     rfc1843-hzp-word-regexp-strictly
				   rfc1843-word-regexp-strictly) to t))
	  (save-restriction
	    (narrow-to-region from to)
	    (goto-char (point-min))
	    (while (re-search-forward (if rfc1843-decode-hzp
					  rfc1843-hzp-word-regexp
					rfc1843-word-regexp) (point-max) t)
	      ;;; Text with extents may cause XEmacs crash
	      (setq str (buffer-substring-no-properties
			 (match-beginning 1)
			 (match-end 1)))
	      (setq firstc (aref str 0))
	      (insert (mm-decode-coding-string
		       (rfc1843-decode
			(prog1
			    (substring str 1)
			  (delete-region (match-beginning 0) (match-end 0)))
			firstc)
		       (if (eq firstc ?{) 'cn-gb-2312 'cn-big5))))
	    (goto-char (point-min))
	    (while (search-forward "~" (point-max) t)
	      (cond ((eq (char-after) ?\n)
		     (delete-char -1)
		     (delete-char 1))
		    ((eq (char-after) ?~)
		     (delete-char 1)))))))))

(defun rfc1843-decode-string (string)
  "Decode HZ STRING and return the results."
  (let ((m (mm-multibyte-p)))
    (with-temp-buffer
      (when m
	(mm-enable-multibyte))
      (insert string)
      (inline
	(rfc1843-decode-region (point-min) (point-max)))
      (buffer-string))))

(defun rfc1843-decode (word &optional firstc)
  "Decode HZ WORD and return it."
  (let ((i -1) (s (substring word 0)) v)
    (if (or (not firstc) (eq firstc ?{))
	(while (< (incf i) (length s))
	  (if (eq (setq v (aref s i)) ? ) nil
	    (aset s i (+ 128 v))))
      (while (< (incf i) (length s))
	(if (eq (setq v (aref s i)) ? ) nil
	  (setq v (+ (* 94 v) (aref s (1+ i)) -3135))
	  (aset s i (+ (/ v 157) (if (eq firstc ?<) 201 161)))
	  (setq v (% v 157))
	  (aset s (incf i) (+ v (if (< v 63) 64 98))))))
    s))

(autoload 'mail-header-parse-content-type "mail-parse")
(autoload 'message-narrow-to-head "message")
(declare-function message-fetch-field "message" (header &optional not-all))

(defun rfc1843-decode-article-body ()
  "Decode HZ encoded text in the article body."
  (if (string-match (concat "\\<\\(" rfc1843-newsgroups-regexp "\\)\\>")
		    (or gnus-newsgroup-name ""))
      (save-excursion
	(save-restriction
	  (message-narrow-to-head)
	  (let* ((inhibit-point-motion-hooks t)
		 (case-fold-search t)
		 (ct (message-fetch-field "Content-Type" t))
		 (ctl (and ct (mail-header-parse-content-type ct))))
	    (if (and ctl (not (string-match "/" (car ctl))))
		(setq ctl nil))
	    (goto-char (point-max))
	    (widen)
	    (forward-line 1)
	    (narrow-to-region (point) (point-max))
	    (when (or (not ctl)
		      (equal (car ctl) "text/plain"))
	      (rfc1843-decode-region (point) (point-max))))))))

(defvar gnus-decode-header-methods)
(defvar gnus-decode-encoded-word-methods)

(defun rfc1843-gnus-setup ()
  "Setup HZ decoding for Gnus."
  (require 'gnus-art)
  (require 'gnus-sum)
  (add-hook 'gnus-article-decode-hook 'rfc1843-decode-article-body t)
  (setq gnus-decode-encoded-word-function
	'gnus-multi-decode-encoded-word-string
	gnus-decode-header-function
	'gnus-multi-decode-header
	gnus-decode-encoded-word-methods
	(nconc gnus-decode-encoded-word-methods
	       (list
		(cons (concat "\\<\\(" rfc1843-newsgroups-regexp "\\)\\>")
		      'rfc1843-decode-string)))
	gnus-decode-header-methods
	(nconc gnus-decode-header-methods
	       (list
		(cons (concat "\\<\\(" rfc1843-newsgroups-regexp "\\)\\>")
		      'rfc1843-decode-region)))))

(provide 'rfc1843)

;;; rfc1843.el ends here