| 1 | ;;; emms-i18n.el --- functions for handling coding systems -*- lexical-binding: t; -*- |
| 2 | |
| 3 | ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
| 4 | |
| 5 | ;; Author: Ye Wenbin <wenbinye@163.com> |
| 6 | |
| 7 | ;; This file is part of EMMS. |
| 8 | |
| 9 | ;; This program is free software; you can redistribute it and/or |
| 10 | ;; modify it under the terms of the GNU General Public License as |
| 11 | ;; published by the Free Software Foundation; either version 3, or (at |
| 12 | ;; your option) any later version. |
| 13 | |
| 14 | ;; This program is distributed in the hope that it will be useful, but |
| 15 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 | ;; General Public License for more details. |
| 18 | |
| 19 | ;; You should have received a copy of the GNU General Public License |
| 20 | ;; along with this program; if not, write to the Free Software |
| 21 | ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 22 | |
| 23 | ;;; Commentary: |
| 24 | |
| 25 | ;; When reading from process, first check the car part of |
| 26 | ;; `emms-i18n-default-coding-system'; if non-nil, use this for |
| 27 | ;; decoding, and never detect coding system; if nil, first call |
| 28 | ;; `emms-i18n-coding-detect-functions' to get coding system, if |
| 29 | ;; success, decode the result, otherwise, use |
| 30 | ;; `emms-i18n-detect-coding-function', the Emacs detect coding |
| 31 | ;; function, if the coding detected is not in |
| 32 | ;; `emms-i18n-never-used-coding-system', decode it, otherwise use |
| 33 | ;; locale-coding-system. |
| 34 | |
| 35 | ;; When writing/sending data to process, first check the cdr part of |
| 36 | ;; `emms-i18n-default-coding-system', if non-nil, use this to encode |
| 37 | ;; data, otherwise do nothing, that means use |
| 38 | ;; `default-process-coding-system' or `process-coding-system-alist' to |
| 39 | ;; encode data. |
| 40 | |
| 41 | ;; Put this file into your load-path and the following into your |
| 42 | ;; ~/.emacs: |
| 43 | |
| 44 | ;; (require 'emms-i18n) |
| 45 | |
| 46 | ;;; Code: |
| 47 | |
| 48 | (provide 'emms-i18n) |
| 49 | |
| 50 | ;; TODO: Use defcustom. |
| 51 | (defvar emms-i18n-never-used-coding-system |
| 52 | '(raw-text undecided) |
| 53 | "If the `emms-i18n-coding-detect-functions' return a coding |
| 54 | system in this list, use `emms-i18n-default-coding-system' |
| 55 | instead.") |
| 56 | |
| 57 | ;; TODO: Use defcustom. |
| 58 | (defvar emms-i18n-coding-system-for-read |
| 59 | 'utf-8 |
| 60 | "If coding detect fails, use this for decoding.") |
| 61 | |
| 62 | ;; TODO: Use defcustom. |
| 63 | (defvar emms-i18n-default-coding-system |
| 64 | '(no-conversion . no-conversion) |
| 65 | "If non-nil, use this for decoding and encoding.") |
| 66 | |
| 67 | ;; TODO: Use defcustom. |
| 68 | (defvar emms-i18n-coding-detect-functions |
| 69 | nil |
| 70 | "A list of functions to call to detect codings.") |
| 71 | |
| 72 | ;; TODO: Use defcustom. |
| 73 | (defvar emms-i18n-detect-max-size |
| 74 | 10000 |
| 75 | "Maximum amount of bytes to detect the coding system. nil |
| 76 | means to scan the whole buffer.") |
| 77 | |
| 78 | (defun emms-i18n-iconv (from to str) |
| 79 | "Convert string STR from FROM coding to TO coding." |
| 80 | (if (and from to) |
| 81 | (decode-coding-string |
| 82 | (encode-coding-string str to) |
| 83 | from) |
| 84 | str)) |
| 85 | |
| 86 | (defun emms-i18n-iconv-region (beg end from to) |
| 87 | (when (and from to) |
| 88 | (save-restriction |
| 89 | (narrow-to-region beg end) |
| 90 | (encode-coding-region (point-min) (point-max) to) |
| 91 | (decode-coding-region (point-min) (point-max) from)))) |
| 92 | |
| 93 | (defun emms-i18n-iconv-buffer (from to &optional buf) |
| 94 | "Convert buffer BUF from FROM coding to TO coding. BUF |
| 95 | defaults to the current buffer." |
| 96 | (save-excursion |
| 97 | (and buf (set-buffer buf)) |
| 98 | (emms-i18n-iconv-region (point-min) (point-max) from to))) |
| 99 | |
| 100 | (defun emms-i18n-set-default-coding-system (read-coding write-coding) |
| 101 | "Set `emms-i18n-default-coding-system'." |
| 102 | (interactive "zSet coding system for read: \nzSet coding system for write: ") |
| 103 | (setq emms-i18n-default-coding-system |
| 104 | (cons |
| 105 | (and (coding-system-p read-coding) read-coding) |
| 106 | (and (coding-system-p write-coding) write-coding))) |
| 107 | (message (concat |
| 108 | (if (car emms-i18n-default-coding-system) |
| 109 | (format "The coding system for reading is %S." (car emms-i18n-default-coding-system)) |
| 110 | "Good, you want me to detect the coding system!") |
| 111 | (format " The coding system for writing is %S." |
| 112 | (or (cdr emms-i18n-default-coding-system) |
| 113 | (cdr default-process-coding-system)))))) |
| 114 | |
| 115 | (defun emms-i18n-call-process-simple (&rest args) |
| 116 | "Run a program and return the program result. |
| 117 | If the car part of `emms-i18n-default-coding-system' is non-nil, |
| 118 | the program result will be decoded using the car part of |
| 119 | `emms-i18n-default-coding-system'. Otherwise, use |
| 120 | `emms-i18n-coding-detect-functions' to detect the coding system |
| 121 | of the result. If the `emms-i18n-coding-detect-functions' |
| 122 | failed, use `emms-i18n-detect-coding-function' to detect coding |
| 123 | system. If all the coding systems are nil or in |
| 124 | `emms-i18n-never-used-coding-system', decode the result using |
| 125 | `emms-i18n-coding-system-for-read'. |
| 126 | |
| 127 | ARGS are the same as in `call-process', except BUFFER should |
| 128 | always have the value t. Otherwise the coding detection will not |
| 129 | be performed." |
| 130 | (let ((default-process-coding-system (copy-tree default-process-coding-system)) |
| 131 | (process-coding-system-alist nil) exit pos) |
| 132 | (when (eq (nth 2 args) 't) |
| 133 | (setcar default-process-coding-system (car emms-i18n-default-coding-system)) |
| 134 | (setq pos (point))) |
| 135 | (setq exit (apply 'call-process args)) |
| 136 | (when (and (eq (nth 2 args) 't) |
| 137 | (eq (car emms-i18n-default-coding-system) 'no-conversion)) |
| 138 | (save-restriction |
| 139 | (narrow-to-region pos (point)) |
| 140 | (decode-coding-region (point-min) (point-max) (emms-i18n-detect-buffer-coding-system)))) |
| 141 | exit)) |
| 142 | |
| 143 | ;; TODO: Is this function useful? |
| 144 | (defun emms-i18n-call-process (&rest args) |
| 145 | "Run the program like `call-process'. If the cdr part of |
| 146 | `emms-i18n-default-coding-system' is non-nil, the string in ARGS |
| 147 | will be encoded by the cdr part of |
| 148 | `emms-i18n-default-coding-system'; otherwise, all parameters are |
| 149 | simply passed to `call-process'." |
| 150 | (with-temp-buffer |
| 151 | (if (cdr emms-i18n-default-coding-system) |
| 152 | (let ((default-process-coding-system emms-i18n-default-coding-system) |
| 153 | (process-coding-system-alist nil)) |
| 154 | (apply 'call-process args)) |
| 155 | (apply 'call-process args)))) |
| 156 | |
| 157 | (defun emms-i18n-detect-coding-function (size) |
| 158 | (detect-coding-region (point) |
| 159 | (+ (if (null emms-i18n-detect-max-size) |
| 160 | size |
| 161 | (min size emms-i18n-detect-max-size)) |
| 162 | (point)) t)) |
| 163 | |
| 164 | (defun emms-i18n-detect-buffer-coding-system (&optional buf) |
| 165 | "Before calling this function, make sure the buffer is literal." |
| 166 | (let ((size (- (point-max) (point-min))) |
| 167 | (_func (append emms-i18n-coding-detect-functions 'emms-i18n-detect-coding-function)) |
| 168 | coding) |
| 169 | (save-excursion |
| 170 | (and buf (set-buffer buf)) |
| 171 | (goto-char (point-min)) |
| 172 | (when (> size 0) |
| 173 | (setq coding (run-hook-with-args-until-success 'func size)) |
| 174 | (if (member (coding-system-base coding) emms-i18n-never-used-coding-system) |
| 175 | (setq coding (emms-i18n-detect-coding-function size)))) |
| 176 | (if (or (null coding) (member (coding-system-base coding) emms-i18n-never-used-coding-system)) |
| 177 | emms-i18n-coding-system-for-read |
| 178 | coding)))) |
| 179 | |
| 180 | ;;; emms-i18n.el ends here |