]> code.delx.au - gnu-emacs/blob - lisp/international/utf-8.el
(ccl-decode-mule-utf-8): Fix previous change.
[gnu-emacs] / lisp / international / utf-8.el
1 ;;; utf-8.el --- UTF-8 decoding/encoding support -*- coding: iso-2022-7bit -*-
2
3 ;; Copyright (C) 2001, 2004 Electrotechnical Laboratory, JAPAN.
4 ;; Licensed to the Free Software Foundation.
5 ;; Copyright (C) 2001, 2002 Free Software Foundation, Inc.
6
7 ;; Author: TAKAHASHI Naoto <ntakahas@m17n.org>
8 ;; Maintainer: FSF
9 ;; Keywords: multilingual, Unicode, UTF-8, i18n
10
11 ;; This file is part of GNU Emacs.
12
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING. If not, write to the
25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 ;; Boston, MA 02111-1307, USA.
27
28 ;;; Commentary:
29
30 ;; The coding-system `mule-utf-8' basically supports encoding/decoding
31 ;; of the following character sets to and from UTF-8:
32 ;;
33 ;; ascii
34 ;; eight-bit-control
35 ;; latin-iso8859-1
36 ;; mule-unicode-0100-24ff
37 ;; mule-unicode-2500-33ff
38 ;; mule-unicode-e000-ffff
39 ;;
40 ;; On decoding, Unicode characters that do not fit into the above
41 ;; character sets are handled as `eight-bit-control' or
42 ;; `eight-bit-graphic' characters to retain the information about the
43 ;; original byte sequence and text properties record the corresponding
44 ;; unicode.
45 ;;
46 ;; Fixme: note that reading and writing invalid utf-8 may not be
47 ;; idempotent -- to represent the bytes to fix that needs a new charset.
48 ;;
49 ;; Characters from other character sets can be encoded with mule-utf-8
50 ;; by populating the translation table
51 ;; `utf-translation-table-for-encode'. Hash tables
52 ;; `utf-subst-table-for-decode' and `utf-subst-table-for-encode' are
53 ;; used to support encoding and decoding of about a quarter of the CJK
54 ;; space between U+3400 and U+DFFF.
55
56 ;; UTF-8 is defined in RFC 3629. A sketch of the encoding is:
57
58 ;; scalar | utf-8
59 ;; value | 1st byte | 2nd byte | 3rd byte
60 ;; --------------------+-----------+-----------+----------
61 ;; 0000 0000 0xxx xxxx | 0xxx xxxx | |
62 ;; 0000 0yyy yyxx xxxx | 110y yyyy | 10xx xxxx |
63 ;; zzzz yyyy yyxx xxxx | 1110 zzzz | 10yy yyyy | 10xx xxxx
64
65 ;;; Code:
66
67 (defvar ucs-mule-to-mule-unicode (make-char-table 'translation-table nil)
68 "Char table mapping characters to latin-iso8859-1 or mule-unicode-*.
69
70 If `unify-8859-on-encoding-mode' is non-nil, this table populates the
71 translation-table named `utf-translation-table-for-encode'.")
72
73 (define-translation-table 'utf-translation-table-for-encode)
74
75
76 ;; Map Cyrillic and Greek to iso-8859 charsets, which take half the
77 ;; space of mule-unicode. For Latin scripts this isn't very
78 ;; important. Hebrew and Arabic might go here too when there's proper
79 ;; support for them.
80
81 (defvar utf-fragmentation-table (make-char-table 'translation-table nil)
82 "Char-table normally mapping non-Latin mule-unicode-* chars to iso-8859-*.
83
84 If `utf-fragment-on-decoding' is non-nil, this table populates the
85 translation-table named `utf-translation-table-for-decode'")
86
87 (defvar utf-defragmentation-table (make-char-table 'translation-table nil)
88 "Char-table for reverse mapping of `utf-fragmentation-table'.
89
90 If `utf-fragment-on-decoding' is non-nil and
91 `unify-8859-on-encoding-mode' is nil, this table populates the
92 translation-table named `utf-translation-table-for-encode'")
93
94 (define-translation-table 'utf-translation-table-for-decode)
95
96
97 (defvar ucs-mule-cjk-to-unicode (make-hash-table :test 'eq)
98 "Hash table mapping Emacs CJK character sets to Unicode code points.
99
100 If `utf-translate-cjk-mode' is non-nil, this table populates the
101 translation-hash-table named `utf-subst-table-for-encode'.")
102
103 (define-translation-hash-table 'utf-subst-table-for-encode
104 ucs-mule-cjk-to-unicode)
105
106 (defvar ucs-unicode-to-mule-cjk (make-hash-table :test 'eq)
107 "Hash table mapping Unicode code points to Emacs CJK character sets.
108
109 If `utf-translate-cjk-mode' is non-nil, this table populates the
110 translation-hash-table named `utf-subst-table-for-decode'.")
111
112 (define-translation-hash-table 'utf-subst-table-for-decode
113 ucs-unicode-to-mule-cjk)
114
115 (mapc
116 (lambda (pair)
117 (aset utf-fragmentation-table (car pair) (cdr pair))
118 (aset utf-defragmentation-table (cdr pair) (car pair)))
119 '((?\e$,1&d\e(B . ?\e,F4\e(B) (?\e$,1&e\e(B . ?\e,F5\e(B) (?\e$,1&f\e(B . ?\e,F6\e(B) (?\e$,1&h\e(B . ?\e,F8\e(B) (?\e$,1&i\e(B . ?\e,F9\e(B)
120 (?\e$,1&j\e(B . ?\e,F:\e(B) (?\e$,1&l\e(B . ?\e,F<\e(B) (?\e$,1&n\e(B . ?\e,F>\e(B) (?\e$,1&o\e(B . ?\e,F?\e(B) (?\e$,1&p\e(B . ?\e,F@\e(B)
121 (?\e$,1&q\e(B . ?\e,FA\e(B) (?\e$,1&r\e(B . ?\e,FB\e(B) (?\e$,1&s\e(B . ?\e,FC\e(B) (?\e$,1&t\e(B . ?\e,FD\e(B) (?\e$,1&u\e(B . ?\e,FE\e(B)
122 (?\e$,1&v\e(B . ?\e,FF\e(B) (?\e$,1&w\e(B . ?\e,FG\e(B) (?\e$,1&x\e(B . ?\e,FH\e(B) (?\e$,1&y\e(B . ?\e,FI\e(B) (?\e$,1&z\e(B . ?\e,FJ\e(B)
123 (?\e$,1&{\e(B . ?\e,FK\e(B) (?\e$,1&|\e(B . ?\e,FL\e(B) (?\e$,1&}\e(B . ?\e,FM\e(B) (?\e$,1&~\e(B . ?\e,FN\e(B) (?\e$,1&\7f\e(B . ?\e,FO\e(B)
124 (?\e$,1' \e(B . ?\e,FP\e(B) (?\e$,1'!\e(B . ?\e,FQ\e(B) (?\e$,1'#\e(B . ?\e,FS\e(B) (?\e$,1'$\e(B . ?\e,FT\e(B) (?\e$,1'%\e(B . ?\e,FU\e(B)
125 (?\e$,1'&\e(B . ?\e,FV\e(B) (?\e$,1''\e(B . ?\e,FW\e(B) (?\e$,1'(\e(B . ?\e,FX\e(B) (?\e$,1')\e(B . ?\e,FY\e(B) (?\e$,1'*\e(B . ?\e,FZ\e(B)
126 (?\e$,1'+\e(B . ?\e,F[\e(B) (?\e$,1',\e(B . ?\e,F\\e(B) (?\e$,1'-\e(B . ?\e,F]\e(B) (?\e$,1'.\e(B . ?\e,F^\e(B) (?\e$,1'/\e(B . ?\e,F_\e(B)
127 (?\e$,1'0\e(B . ?\e,F`\e(B) (?\e$,1'1\e(B . ?\e,Fa\e(B) (?\e$,1'2\e(B . ?\e,Fb\e(B) (?\e$,1'3\e(B . ?\e,Fc\e(B) (?\e$,1'4\e(B . ?\e,Fd\e(B)
128 (?\e$,1'5\e(B . ?\e,Fe\e(B) (?\e$,1'6\e(B . ?\e,Ff\e(B) (?\e$,1'7\e(B . ?\e,Fg\e(B) (?\e$,1'8\e(B . ?\e,Fh\e(B) (?\e$,1'9\e(B . ?\e,Fi\e(B)
129 (?\e$,1':\e(B . ?\e,Fj\e(B) (?\e$,1';\e(B . ?\e,Fk\e(B) (?\e$,1'<\e(B . ?\e,Fl\e(B) (?\e$,1'=\e(B . ?\e,Fm\e(B) (?\e$,1'>\e(B . ?\e,Fn\e(B)
130 (?\e$,1'?\e(B . ?\e,Fo\e(B) (?\e$,1'@\e(B . ?\e,Fp\e(B) (?\e$,1'A\e(B . ?\e,Fq\e(B) (?\e$,1'B\e(B . ?\e,Fr\e(B) (?\e$,1'C\e(B . ?\e,Fs\e(B)
131 (?\e$,1'D\e(B . ?\e,Ft\e(B) (?\e$,1'E\e(B . ?\e,Fu\e(B) (?\e$,1'F\e(B . ?\e,Fv\e(B) (?\e$,1'G\e(B . ?\e,Fw\e(B) (?\e$,1'H\e(B . ?\e,Fx\e(B)
132 (?\e$,1'I\e(B . ?\e,Fy\e(B) (?\e$,1'J\e(B . ?\e,Fz\e(B) (?\e$,1'K\e(B . ?\e,F{\e(B) (?\e$,1'L\e(B . ?\e,F|\e(B) (?\e$,1'M\e(B . ?\e,F}\e(B)
133 (?\e$,1'N\e(B . ?\e,F~\e(B)
134
135 (?\e$,1(!\e(B . ?\e,L!\e(B) (?\e$,1("\e(B . ?\e,L"\e(B) (?\e$,1(#\e(B . ?\e,L#\e(B) (?\e$,1($\e(B . ?\e,L$\e(B)
136 (?\e$,1(%\e(B . ?\e,L%\e(B) (?\e$,1(&\e(B . ?\e,L&\e(B) (?\e$,1('\e(B . ?\e,L'\e(B) (?\e$,1((\e(B . ?\e,L(\e(B) (?\e$,1()\e(B . ?\e,L)\e(B)
137 (?\e$,1(*\e(B . ?\e,L*\e(B) (?\e$,1(+\e(B . ?\e,L+\e(B) (?\e$,1(,\e(B . ?\e,L,\e(B) (?\e$,1(.\e(B . ?\e,L.\e(B) (?\e$,1(/\e(B . ?\e,L/\e(B)
138 (?\e$,1(0\e(B . ?\e,L0\e(B) (?\e$,1(1\e(B . ?\e,L1\e(B) (?\e$,1(2\e(B . ?\e,L2\e(B) (?\e$,1(3\e(B . ?\e,L3\e(B) (?\e$,1(4\e(B . ?\e,L4\e(B)
139 (?\e$,1(5\e(B . ?\e,L5\e(B) (?\e$,1(6\e(B . ?\e,L6\e(B) (?\e$,1(7\e(B . ?\e,L7\e(B) (?\e$,1(8\e(B . ?\e,L8\e(B) (?\e$,1(9\e(B . ?\e,L9\e(B)
140 (?\e$,1(:\e(B . ?\e,L:\e(B) (?\e$,1(;\e(B . ?\e,L;\e(B) (?\e$,1(<\e(B . ?\e,L<\e(B) (?\e$,1(=\e(B . ?\e,L=\e(B) (?\e$,1(>\e(B . ?\e,L>\e(B)
141 (?\e$,1(?\e(B . ?\e,L?\e(B) (?\e$,1(@\e(B . ?\e,L@\e(B) (?\e$,1(A\e(B . ?\e,LA\e(B) (?\e$,1(B\e(B . ?\e,LB\e(B) (?\e$,1(C\e(B . ?\e,LC\e(B)
142 (?\e$,1(D\e(B . ?\e,LD\e(B) (?\e$,1(E\e(B . ?\e,LE\e(B) (?\e$,1(F\e(B . ?\e,LF\e(B) (?\e$,1(G\e(B . ?\e,LG\e(B) (?\e$,1(H\e(B . ?\e,LH\e(B)
143 (?\e$,1(I\e(B . ?\e,LI\e(B) (?\e$,1(J\e(B . ?\e,LJ\e(B) (?\e$,1(K\e(B . ?\e,LK\e(B) (?\e$,1(L\e(B . ?\e,LL\e(B) (?\e$,1(M\e(B . ?\e,LM\e(B)
144 (?\e$,1(N\e(B . ?\e,LN\e(B) (?\e$,1(O\e(B . ?\e,LO\e(B) (?\e$,1(P\e(B . ?\e,LP\e(B) (?\e$,1(Q\e(B . ?\e,LQ\e(B) (?\e$,1(R\e(B . ?\e,LR\e(B)
145 (?\e$,1(S\e(B . ?\e,LS\e(B) (?\e$,1(T\e(B . ?\e,LT\e(B) (?\e$,1(U\e(B . ?\e,LU\e(B) (?\e$,1(V\e(B . ?\e,LV\e(B) (?\e$,1(W\e(B . ?\e,LW\e(B)
146 (?\e$,1(X\e(B . ?\e,LX\e(B) (?\e$,1(Y\e(B . ?\e,LY\e(B) (?\e$,1(Z\e(B . ?\e,LZ\e(B) (?\e$,1([\e(B . ?\e,L[\e(B) (?\e$,1(\\e(B . ?\e,L\\e(B)
147 (?\e$,1(]\e(B . ?\e,L]\e(B) (?\e$,1(^\e(B . ?\e,L^\e(B) (?\e$,1(_\e(B . ?\e,L_\e(B) (?\e$,1(`\e(B . ?\e,L`\e(B) (?\e$,1(a\e(B . ?\e,La\e(B)
148 (?\e$,1(b\e(B . ?\e,Lb\e(B) (?\e$,1(c\e(B . ?\e,Lc\e(B) (?\e$,1(d\e(B . ?\e,Ld\e(B) (?\e$,1(e\e(B . ?\e,Le\e(B) (?\e$,1(f\e(B . ?\e,Lf\e(B)
149 (?\e$,1(g\e(B . ?\e,Lg\e(B) (?\e$,1(h\e(B . ?\e,Lh\e(B) (?\e$,1(i\e(B . ?\e,Li\e(B) (?\e$,1(j\e(B . ?\e,Lj\e(B) (?\e$,1(k\e(B . ?\e,Lk\e(B)
150 (?\e$,1(l\e(B . ?\e,Ll\e(B) (?\e$,1(m\e(B . ?\e,Lm\e(B) (?\e$,1(n\e(B . ?\e,Ln\e(B) (?\e$,1(o\e(B . ?\e,Lo\e(B) (?\e$,1(q\e(B . ?\e,Lq\e(B)
151 (?\e$,1(r\e(B . ?\e,Lr\e(B) (?\e$,1(s\e(B . ?\e,Ls\e(B) (?\e$,1(t\e(B . ?\e,Lt\e(B) (?\e$,1(u\e(B . ?\e,Lu\e(B) (?\e$,1(v\e(B . ?\e,Lv\e(B)
152 (?\e$,1(w\e(B . ?\e,Lw\e(B) (?\e$,1(x\e(B . ?\e,Lx\e(B) (?\e$,1(y\e(B . ?\e,Ly\e(B) (?\e$,1(z\e(B . ?\e,Lz\e(B) (?\e$,1({\e(B . ?\e,L{\e(B)
153 (?\e$,1(|\e(B . ?\e,L|\e(B) (?\e$,1(~\e(B . ?\e,L~\e(B) (?\e$,1(\7f\e(B . ?\e,L\7f\e(B)))
154
155
156 (defcustom utf-fragment-on-decoding nil
157 "Whether or not to decode some chars in UTF-8/16 text into iso8859 charsets.
158 Setting this means that the relevant Cyrillic and Greek characters are
159 decoded into the iso8859 charsets rather than into
160 mule-unicode-0100-24ff. The iso8859 charsets take half as much space
161 in the buffer, but using them may affect how the buffer can be re-encoded
162 and may require a different input method to search for them, for instance.
163 See `unify-8859-on-decoding-mode' and `unify-8859-on-encoding-mode'
164 for mechanisms to make this largely transparent.
165
166 Setting this variable outside customize has no effect."
167 :set (lambda (s v)
168 (if v
169 (progn
170 (define-translation-table 'utf-translation-table-for-decode
171 utf-fragmentation-table)
172 ;; Even if unify-8859-on-encoding-mode is off, make
173 ;; mule-utf-* encode characters in
174 ;; utf-fragmentation-table.
175 (unless (eq (get 'utf-translation-table-for-encode
176 'translation-table)
177 ucs-mule-to-mule-unicode)
178 (define-translation-table 'utf-translation-table-for-encode
179 utf-defragmentation-table)))
180 (define-translation-table 'utf-translation-table-for-decode)
181 ;; When unify-8859-on-encoding-mode is off, be sure to make
182 ;; mule-utf-* disabled for characters in
183 ;; utf-fragmentation-table.
184 (unless (eq (get 'utf-translation-table-for-encode
185 'translation-table)
186 ucs-mule-to-mule-unicode)
187 (define-translation-table 'utf-translation-table-for-encode)))
188 (set-default s v))
189 :version "21.4"
190 :type 'boolean
191 :group 'mule)
192
193
194 (defconst utf-translate-cjk-charsets '(chinese-gb2312
195 chinese-big5-1 chinese-big5-2
196 japanese-jisx0208 japanese-jisx0212
197 korean-ksc5601)
198 "List of charsets supported by `utf-translate-cjk-mode'.")
199
200 (defconst utf-translate-cjk-unicode-range
201 '((#x2e80 . #xd7a3)
202 (#xff00 . #xffef))
203 "List of Unicode code ranges supported by `utf-translate-cjk-mode'.")
204
205 ;; Return non-nil if CODE-POINT is in `utf-translate-cjk-unicode-range'.
206 (defsubst utf-translate-cjk-substitutable-p (code-point)
207 (let ((tail utf-translate-cjk-unicode-range)
208 elt)
209 (while tail
210 (setq elt (car tail) tail (cdr tail))
211 (if (and (>= code-point (car elt)) (<= code-point (cdr elt)))
212 (setq tail nil)
213 (setq elt nil)))
214 elt))
215
216 (defvar utf-translate-cjk-lang-env nil
217 "Language environment in which tables for `utf-translate-cjk-mode' is loaded.
218 The value nil means that the tables are not yet loaded.")
219
220 (defun utf-translate-cjk-load-tables ()
221 "Load tables for `utf-translate-cjk-mode'."
222 ;; Fixme: Allow the use of the CJK charsets to be
223 ;; customized by reordering and possible omission.
224 (let ((redefined (< (hash-table-size ucs-mule-cjk-to-unicode) 43000)))
225 (if redefined
226 ;; Redefine them with realistic initial sizes and a
227 ;; smallish rehash size to avoid wasting significant
228 ;; space after they're built.
229 (setq ucs-mule-cjk-to-unicode
230 (make-hash-table :test 'eq :size 43000 :rehash-size 1000)
231 ucs-unicode-to-mule-cjk
232 (make-hash-table :test 'eq :size 21500 :rehash-size 1000)))
233
234 ;; Load the files explicitly, to avoid having to keep
235 ;; around the large tables they contain (as well as the
236 ;; ones which get built).
237 (cond ((string= "Korean" current-language-environment)
238 (load "subst-jis")
239 (load "subst-big5")
240 (load "subst-gb2312")
241 (load "subst-ksc"))
242 ((string= "Chinese-BIG5" current-language-environment)
243 (load "subst-jis")
244 (load "subst-ksc")
245 (load "subst-gb2312")
246 (load "subst-big5"))
247 ((string= "Chinese-GB" current-language-environment)
248 (load "subst-jis")
249 (load "subst-ksc")
250 (load "subst-big5")
251 (load "subst-gb2312"))
252 (t
253 (load "subst-ksc")
254 (load "subst-gb2312")
255 (load "subst-big5")
256 (load "subst-jis"))) ; jis covers as much as big5, gb2312
257
258 (when redefined
259 (define-translation-hash-table 'utf-subst-table-for-decode
260 ucs-unicode-to-mule-cjk)
261 (define-translation-hash-table 'utf-subst-table-for-encode
262 ucs-mule-cjk-to-unicode)
263 (set-char-table-extra-slot (get 'utf-translation-table-for-encode
264 'translation-table)
265 1 ucs-mule-cjk-to-unicode))
266
267 (setq utf-translate-cjk-lang-env current-language-environment)))
268
269 (defun utf-lookup-subst-table-for-decode (code-point)
270 (if (and utf-translate-cjk-mode
271 (not utf-translate-cjk-lang-env)
272 (utf-translate-cjk-substitutable-p code-point))
273 (utf-translate-cjk-load-tables))
274 (gethash code-point
275 (get 'utf-subst-table-for-decode 'translation-hash-table)))
276
277
278 (defun utf-lookup-subst-table-for-encode (char)
279 (if (and utf-translate-cjk-mode
280 (not utf-translate-cjk-lang-env)
281 (memq (char-charset char) utf-translate-cjk-charsets))
282 (utf-translate-cjk-load-tables))
283 (gethash char
284 (get 'utf-subst-table-for-encode 'translation-hash-table)))
285
286 (define-minor-mode utf-translate-cjk-mode
287 "Whether the UTF based coding systems should decode/encode CJK characters.
288 Enabling this allows the coding systems mule-utf-8,
289 mule-utf-16le and mule-utf-16be to encode characters in the charsets
290 `korean-ksc5601', `chinese-gb2312', `chinese-big5-1',
291 `chinese-big5-2', `japanese-jisx0208' and `japanese-jisx0212', and to
292 decode the corresponding unicodes into such characters.
293
294 Where the charsets overlap, the one preferred for decoding is chosen
295 according to the language environment in effect when this option is
296 turned on: ksc5601 for Korean, gb2312 for Chinese-GB, big5 for
297 Chinese-Big5 and jisx for other environments.
298
299 This option is on by default. If you are not interested in CJK
300 characters and want to avoid some overhead on encoding/decoding
301 by the above coding systems, you can customize this option to nil."
302 :init-value t
303 :version "21.4"
304 :type 'boolean
305 :group 'mule
306 :global t
307 (if utf-translate-cjk-mode
308 (progn
309 (define-translation-hash-table 'utf-subst-table-for-decode
310 ucs-unicode-to-mule-cjk)
311 (define-translation-hash-table 'utf-subst-table-for-encode
312 ucs-mule-cjk-to-unicode)
313 (set-char-table-extra-slot (get 'utf-translation-table-for-encode
314 'translation-table)
315 1 ucs-mule-cjk-to-unicode))
316 (define-translation-hash-table 'utf-subst-table-for-decode
317 (make-hash-table :test 'eq))
318 (define-translation-hash-table 'utf-subst-table-for-encode
319 (make-hash-table :test 'eq))
320 (set-char-table-extra-slot (get 'utf-translation-table-for-encode
321 'translation-table)
322 1 nil))
323
324 ;; Update safe-chars of mule-utf-* coding systems.
325 (dolist (elt (coding-system-list t))
326 (if (string-match "^mule-utf" (symbol-name elt))
327 (let ((safe-charsets (coding-system-get elt 'safe-charsets))
328 (safe-chars (coding-system-get elt 'safe-chars))
329 (need-update nil))
330 (dolist (charset utf-translate-cjk-charsets)
331 (unless (eq utf-translate-cjk-mode (memq charset safe-charsets))
332 (setq safe-charsets
333 (if utf-translate-cjk-mode
334 (cons charset safe-charsets)
335 (delq charset safe-charsets))
336 need-update t)
337 (aset safe-chars (make-char charset) utf-translate-cjk-mode)))
338 (when need-update
339 (coding-system-put elt 'safe-charsets safe-charsets)
340 (define-coding-system-internal elt))))))
341
342 (define-ccl-program ccl-mule-utf-untrans
343 ;; R0 is an untranslatable Unicode code-point (U+3500..U+DFFF or
344 ;; U+10000..U+10FFFF) or an invaid byte (#x00..#xFF). Write
345 ;; eight-bit-control/graphic sequence (2 to 4 chars) representing
346 ;; UTF-8 sequence of r0. Registers r4, r5, r6 are modified.
347 ;;
348 ;; This is a subrountine because we assume that this is called very
349 ;; rarely (so we don't have to worry about the overhead of the
350 ;; call).
351 `(0
352 ((r5 = ,(charset-id 'eight-bit-control))
353 (r6 = ,(charset-id 'eight-bit-graphic))
354 (if (r0 < #x100)
355 ((r4 = ((r0 >> 6) | #xC0))
356 (write-multibyte-character r6 r4))
357 ((if (r0 < #x10000)
358 ((r4 = ((r0 >> 12) | #xE0))
359 (write-multibyte-character r6 r4))
360 ((r4 = ((r0 >> 18) | #xF0))
361 (write-multibyte-character r6 r4)
362 (r4 = (((r0 >> 12) & #x3F) | #x80))
363 (if (r4 < #xA0)
364 (write-multibyte-character r5 r4)
365 (write-multibyte-character r6 r4))))
366 (r4 = (((r0 >> 6) & #x3F) | #x80))
367 (if (r4 < #xA0)
368 (write-multibyte-character r5 r4)
369 (write-multibyte-character r6 r4))))
370 (r4 = ((r0 & #x3F) | #x80))
371 (if (r4 < #xA0)
372 (write-multibyte-character r5 r4)
373 (write-multibyte-character r6 r4)))))
374
375 (define-ccl-program ccl-decode-mule-utf-8
376 ;;
377 ;; charset | bytes in utf-8 | bytes in emacs
378 ;; -----------------------+----------------+---------------
379 ;; ascii | 1 | 1
380 ;; -----------------------+----------------+---------------
381 ;; eight-bit-control | 2 | 2
382 ;; eight-bit-graphic | 2 | 1
383 ;; latin-iso8859-1 | 2 | 2
384 ;; -----------------------+----------------+---------------
385 ;; mule-unicode-0100-24ff | 2 | 4
386 ;; (< 0800) | |
387 ;; -----------------------+----------------+---------------
388 ;; mule-unicode-0100-24ff | 3 | 4
389 ;; (>= 8000) | |
390 ;; mule-unicode-2500-33ff | 3 | 4
391 ;; mule-unicode-e000-ffff | 3 | 4
392 ;; -----------------------+----------------+---------------
393 ;; invalid byte | 1 | 2
394 ;;
395 ;; Thus magnification factor is two.
396 ;;
397 `(2
398 ((r6 = ,(charset-id 'latin-iso8859-1))
399 (read r0)
400 (loop
401 (if (r0 < #x80)
402 ;; 1-byte encoding, i.e., ascii
403 (write-read-repeat r0))
404 (if (r0 < #xc2)
405 ;; continuation byte (invalid here) or 1st byte of overlong
406 ;; 2-byte sequence.
407 ((call ccl-mule-utf-untrans)
408 (r6 = ,(charset-id 'latin-iso8859-1))
409 (read r0)
410 (repeat)))
411
412 ;; Read the 2nd byte.
413 (read r1)
414 (if ((r1 & #b11000000) != #b10000000) ; Invalid 2nd byte
415 ((call ccl-mule-utf-untrans)
416 (r6 = ,(charset-id 'latin-iso8859-1))
417 ;; Handle it in the next loop.
418 (r0 = r1)
419 (repeat)))
420
421 (if (r0 < #xe0)
422 ;; 2-byte encoding 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
423 ((r1 &= #x3F)
424 (r1 |= ((r0 & #x1F) << 6))
425 ;; Now r2 holds scalar value. We don't have to check
426 ;; `overlong sequence' because r0 >= 0xC2.
427
428 (if (r1 >= 256)
429 ;; mule-unicode-0100-24ff (< 0800)
430 ((r0 = ,(charset-id 'mule-unicode-0100-24ff))
431 (r1 -= #x0100)
432 (r2 = (((r1 / 96) + 32) << 7))
433 (r1 %= 96)
434 (r1 += (r2 + 32))
435 (translate-character
436 utf-translation-table-for-decode r0 r1)
437 (write-multibyte-character r0 r1)
438 (read r0)
439 (repeat))
440 (if (r1 >= 160)
441 ;; latin-iso8859-1
442 ((r1 -= 128)
443 (write-multibyte-character r6 r1)
444 (read r0)
445 (repeat))
446 ;; eight-bit-control
447 ((r0 = ,(charset-id 'eight-bit-control))
448 (write-multibyte-character r0 r1)
449 (read r0)
450 (repeat))))))
451
452 ;; Read the 3rd bytes.
453 (read r2)
454 (if ((r2 & #b11000000) != #b10000000) ; Invalid 3rd byte
455 ((call ccl-mule-utf-untrans)
456 (r0 = r1)
457 (call ccl-mule-utf-untrans)
458 (r6 = ,(charset-id 'latin-iso8859-1))
459 ;; Handle it in the next loop.
460 (r0 = r2)
461 (repeat)))
462
463 (if (r0 < #xF0)
464 ;; 3byte encoding
465 ;; zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
466 ((r3 = ((r0 & #xF) << 12))
467 (r3 |= ((r1 & #x3F) << 6))
468 (r3 |= (r2 & #x3F))
469
470 (if (r3 < #x800) ; `overlong sequence'
471 ((call ccl-mule-utf-untrans)
472 (r0 = r1)
473 (call ccl-mule-utf-untrans)
474 (r0 = r2)
475 (call ccl-mule-utf-untrans)
476 (r6 = ,(charset-id 'latin-iso8859-1))
477 (read r0)
478 (repeat)))
479
480 (if (r3 < #x2500)
481 ;; mule-unicode-0100-24ff (>= 0800)
482 ((r0 = ,(charset-id 'mule-unicode-0100-24ff))
483 (r3 -= #x0100)
484 (r3 //= 96)
485 (r1 = (r7 + 32))
486 (r1 += ((r3 + 32) << 7))
487 (translate-character
488 utf-translation-table-for-decode r0 r1)
489 (write-multibyte-character r0 r1)
490 (read r0)
491 (repeat)))
492
493 (if (r3 < #x3400)
494 ;; mule-unicode-2500-33ff
495 ((r0 = r3) ; don't zap r3
496 (lookup-integer utf-subst-table-for-decode r0 r1)
497 (if (r7 == 0)
498 ((r0 = ,(charset-id 'mule-unicode-2500-33ff))
499 (r3 -= #x2500)
500 (r3 //= 96)
501 (r1 = (r7 + 32))
502 (r1 += ((r3 + 32) << 7))))
503 (write-multibyte-character r0 r1)
504 (read r0)
505 (repeat)))
506
507 (if (r3 < #xE000)
508 ;; Try to convert to CJK chars, else
509 ;; keep them as eight-bit-{control|graphic}.
510 ((r0 = r3)
511 (lookup-integer utf-subst-table-for-decode r3 r1)
512 (if r7
513 ;; got a translation
514 ((write-multibyte-character r3 r1)
515 (read r0)
516 (repeat))
517 ((call ccl-mule-utf-untrans)
518 (r6 = ,(charset-id 'latin-iso8859-1))
519 (read r0)
520 (repeat)))))
521
522 ;; mule-unicode-e000-ffff
523 ;; Fixme: fffe and ffff are invalid.
524 (r0 = r3) ; don't zap r3
525 (lookup-integer utf-subst-table-for-decode r0 r1)
526 (if (r7 == 0)
527 ((r0 = ,(charset-id 'mule-unicode-e000-ffff))
528 (r3 -= #xe000)
529 (r3 //= 96)
530 (r1 = (r7 + 32))
531 (r1 += ((r3 + 32) << 7))))
532 (write-multibyte-character r0 r1)
533 (read r0)
534 (repeat)))
535
536 ;; Read the 4th bytes.
537 (read r3)
538 (if ((r3 & #b11000000) != #b10000000) ; Invalid 4th byte
539 ((call ccl-mule-utf-untrans)
540 (r0 = r1)
541 (call ccl-mule-utf-untrans)
542 (r0 = r2)
543 (call ccl-mule-utf-untrans)
544 (r6 = ,(charset-id 'latin-iso8859-1))
545 ;; Handle it in the next loop.
546 (r0 = r3)
547 (repeat)))
548
549 (if (r0 < #xF8)
550 ;; 4-byte encoding:
551 ;; wwwzzzzzzyyyyyyxxxxxx = 11110www 10zzzzzz 10yyyyyy 10xxxxxx
552 ;; keep those bytes as eight-bit-{control|graphic}
553 ;; Fixme: allow lookup in utf-subst-table-for-decode.
554 ((r4 = ((r0 & #x7) << 18))
555 (r4 |= ((r1 & #x3F) << 12))
556 (r4 |= ((r2 & #x3F) << 6))
557 (r4 |= (r3 & #x3F))
558
559 (if (r4 < #x10000) ; `overlong sequence'
560 ((call ccl-mule-utf-untrans)
561 (r0 = r1)
562 (call ccl-mule-utf-untrans)
563 (r0 = r2)
564 (call ccl-mule-utf-untrans)
565 (r0 = r3)
566 (call ccl-mule-utf-untrans))
567 ((r0 = r4)
568 (call ccl-mule-utf-untrans))))
569
570 ;; Unsupported sequence.
571 ((call ccl-mule-utf-untrans)
572 (r0 = r1)
573 (call ccl-mule-utf-untrans)
574 (r0 = r2)
575 (call ccl-mule-utf-untrans)
576 (r0 = r3)
577 (call ccl-mule-utf-untrans)))
578 (r6 = ,(charset-id 'latin-iso8859-1))
579 (read r0)
580 (repeat)))
581
582
583 ;; At EOF...
584 (if (r0 >= 0)
585 ;; r0 >= #x80
586 ((call ccl-mule-utf-untrans)
587 (if (r1 >= 0)
588 ((r0 = r1)
589 (call ccl-mule-utf-untrans)
590 (if (r2 >= 0)
591 ((r0 = r2)
592 (call ccl-mule-utf-untrans)
593 (if (r3 >= 0)
594 ((r0 = r3)
595 (call ccl-mule-utf-untrans))))))))))
596
597 "CCL program to decode UTF-8.
598 Basic decoding is done into the charsets ascii, latin-iso8859-1 and
599 mule-unicode-*, but see also `utf-fragmentation-table' and
600 `ucs-mule-cjk-to-unicode'.
601 Encodings of un-representable Unicode characters are decoded asis into
602 eight-bit-control and eight-bit-graphic characters.")
603
604 (define-ccl-program ccl-mule-utf-8-encode-untrans
605 ;; UTF-8 decoder generates an UTF-8 sequence represented by a
606 ;; sequence eight-bit-control/graphic chars for an untranslatable
607 ;; character and an invalid byte.
608 ;;
609 ;; This CCL parses that sequence (the first byte is already in r1),
610 ;; writes out the original bytes of that sequence, and sets r5 to
611 ;; -1.
612 ;;
613 ;; If the eight-bit-control/graphic sequence is shorter than what r1
614 ;; suggests, it sets r5 and r6 to the last character read that
615 ;; should be handled by the next loop of a caller.
616 ;;
617 ;; Note: For UTF-8 validation, we only check if a character is
618 ;; eight-bit-control/graphic or not. It may result in incorrect
619 ;; handling of random binary data, but such a data can't be encoded
620 ;; by UTF-8 anyway. At least, UTF-8 decoders doesn't generate such
621 ;; a sequence even if a source contains invalid byte-sequence.
622 `(0
623 (;; Read the 2nd byte.
624 (read-multibyte-character r5 r6)
625 (r0 = (r5 != ,(charset-id 'eight-bit-control)))
626 (if ((r5 != ,(charset-id 'eight-bit-graphic)) & r0)
627 ((write r1) ; invalid UTF-8
628 (r1 = -1)
629 (end)))
630
631 (if (r1 <= #xC3)
632 ;; 2-byte sequence for an originally invalid byte.
633 ((r6 &= #x3F)
634 (r6 |= ((r1 & #x1F) << 6))
635 (write r6)
636 (r5 = -1)
637 (end)))
638
639 (write r1 r6)
640 (r2 = r1)
641 (r1 = -1)
642 ;; Read the 3rd byte.
643 (read-multibyte-character r5 r6)
644 (r0 = (r5 != ,(charset-id 'eight-bit-control)))
645 (if ((r5 != ,(charset-id 'eight-bit-graphic)) & r0)
646 (end)) ; invalid UTF-8
647 (write r6)
648 (if (r2 < #xF0)
649 ;; 3-byte sequence for an untranslated character.
650 ((r5 = -1)
651 (end)))
652 ;; Read the 4th byte.
653 (read-multibyte-character r5 r6)
654 (r0 = (r5 != ,(charset-id 'eight-bit-control)))
655 (if ((r5 != ,(charset-id 'eight-bit-graphic)) & r0)
656 (end)) ; invalid UTF-8
657 ;; 4-byte sequence for an untranslated character.
658 (write r6)
659 (r5 = -1)
660 (end))
661
662 ;; At EOF...
663 ((r5 = -1)
664 (if (r1 >= 0)
665 (write r1)))))
666
667 (define-ccl-program ccl-encode-mule-utf-8
668 `(1
669 ((r5 = -1)
670 (loop
671 (if (r5 < 0)
672 (read-multibyte-character r0 r1)
673 ;; Pre-read character is in r5 (charset-ID) and r6 (code-point).
674 ((r0 = r5)
675 (r1 = r6)
676 (r5 = -1)))
677 (translate-character utf-translation-table-for-encode r0 r1)
678
679 (if (r0 == ,(charset-id 'ascii))
680 (write-repeat r1))
681
682 (if (r0 == ,(charset-id 'latin-iso8859-1))
683 ;; r1 scalar utf-8
684 ;; 0000 0yyy yyxx xxxx 110y yyyy 10xx xxxx
685 ;; 20 0000 0000 1010 0000 1100 0010 1010 0000
686 ;; 7f 0000 0000 1111 1111 1100 0011 1011 1111
687 ((r0 = (((r1 & #x40) >> 6) | #xc2))
688 (r1 &= #x3f)
689 (r1 |= #x80)
690 (write r0)
691 (write-repeat r1)))
692
693 (if (r0 == ,(charset-id 'mule-unicode-0100-24ff))
694 ((r0 = ((((r1 & #x3f80) >> 7) - 32) * 96))
695 ;; #x3f80 == (0011 1111 1000 0000)b
696 (r1 &= #x7f)
697 (r1 += (r0 + 224)) ; 240 == -32 + #x0100
698 ;; now r1 holds scalar value
699 (if (r1 < #x0800)
700 ;; 2byte encoding
701 ((write ((r1 >> 6) | #xC0))
702 (r1 &= #x3F)
703 (r1 |= #x80)
704 (write-repeat r1))
705 ;; 3byte encoding
706 ((write ((r1 >> 12) | #xE0))
707 (write (((r1 & #x0FC0) >> 6) | #x80))
708 (r1 &= #x3F)
709 (r1 |= #x80)
710 (write-repeat r1)))))
711
712 (if (r0 == ,(charset-id 'mule-unicode-2500-33ff))
713 ((r0 = ((((r1 & #x3f80) >> 7) - 32) * 96))
714 (r1 &= #x7f)
715 (r1 += (r0 + 9440)) ; 9440 == -32 + #x2500
716 ;; now r1 holds scalar value
717 (write ((r1 >> 12) | #xE0))
718 (write (((r1 & #x0FC0) >> 6) | #x80))
719 (r1 &= #x3F)
720 (r1 |= #x80)
721 (write-repeat r1)))
722
723 (if (r0 == ,(charset-id 'mule-unicode-e000-ffff))
724 ((r0 = ((((r1 & #x3f80) >> 7) - 32) * 96))
725 (r1 &= #x7f)
726 (r1 += (r0 + 57312)) ; 57312 == -32 + #xe000
727 ;; now r1 holds scalar value
728 (write ((r1 >> 12) | #xE0))
729 (write (((r1 & #x0FC0) >> 6) | #x80))
730 (r1 &= #x3F)
731 (r1 |= #x80)
732 (write-repeat r1)))
733
734 (if (r0 == ,(charset-id 'eight-bit-control))
735 ;; r1 scalar utf-8
736 ;; 0000 0yyy yyxx xxxx 110y yyyy 10xx xxxx
737 ;; 80 0000 0000 1000 0000 1100 0010 1000 0000
738 ;; 9f 0000 0000 1001 1111 1100 0010 1001 1111
739 ((write #xC2)
740 (write-repeat r1)))
741
742 (if (r0 == ,(charset-id 'eight-bit-graphic))
743 ;; r1 scalar utf-8
744 ;; 0000 0yyy yyxx xxxx 110y yyyy 10xx xxxx
745 ;; a0 0000 0000 1010 0000 1100 0010 1010 0000
746 ;; ff 0000 0000 1111 1111 1101 1111 1011 1111
747 ((r0 = (r1 >= #xC0))
748 (r0 &= (r1 <= #xC3))
749 (r4 = (r1 >= #xE1))
750 (r4 &= (r1 <= #xF7))
751 (r0 |= r4)
752 (if r0
753 ((call ccl-mule-utf-8-encode-untrans)
754 (repeat))
755 (write-repeat r1))))
756
757 (lookup-character utf-subst-table-for-encode r0 r1)
758 (if r7 ; lookup succeeded
759 (if (r0 < #x800)
760 ;; 2byte encoding
761 ((write ((r0 >> 6) | #xC0))
762 (r1 &= #x3F)
763 (r1 |= #x80)
764 (write-repeat r1))
765 ;; 3byte encoding
766 ((write ((r0 >> 12) | #xE0))
767 (write (((r0 & #x0FC0) >> 6) | #x80))
768 (r1 &= #x3F)
769 (r1 |= #x80)
770 (write-repeat r1))))
771
772 ;; Unsupported character.
773 ;; Output U+FFFD, which is `ef bf bd' in UTF-8.
774 (write #xef)
775 (write #xbf)
776 (write-repeat #xbd))))
777 "CCL program to encode into UTF-8.")
778
779
780 (define-ccl-program ccl-untranslated-to-ucs
781 `(0
782 (if (r1 == 0)
783 nil
784 (if (r0 <= #xC3) ; 2-byte encoding
785 ((r0 = ((r0 & #x3) << 6))
786 (r0 |= (r1 & #x3F))
787 (r1 = 2))
788 (if (r2 == 0)
789 (r1 = 0)
790 (if (r0 < #xF0) ; 3-byte encoding, as above
791 ((r0 = ((r0 & #xF) << 12))
792 (r0 |= ((r1 & #x3F) << 6))
793 (r0 |= (r2 & #x3F))
794 (r1 = 3))
795 (if (r3 == 0)
796 (r1 = 0)
797 ((r0 = ((r0 & #x7) << 18))
798 (r0 |= ((r1 & #x3F) << 12))
799 (r0 |= ((r2 & #x3F) << 6))
800 (r0 |= (r3 & #x3F))
801 (r1 = 4))))))))
802 "Decode 2-, 3-, or 4-byte sequences in r0, r1, r2 [,r3] to unicodes in r0.
803 Set r1 to the byte length. r0 == 0 for invalid sequence.")
804
805 (defvar utf-8-ccl-regs (make-vector 8 0))
806
807 (defsubst utf-8-untranslated-to-ucs ()
808 "Return the UCS code for an untranslated sequence of raw bytes t point.
809 Only for 3- or 4-byte sequences."
810 (aset utf-8-ccl-regs 0 (or (char-after) 0))
811 (aset utf-8-ccl-regs 1 (or (char-after (1+ (point))) 0))
812 (aset utf-8-ccl-regs 2 (or (char-after (+ 2 (point))) 0))
813 (aset utf-8-ccl-regs 3 (or (char-after (+ 3 (point))) 0))
814 (ccl-execute 'ccl-untranslated-to-ucs utf-8-ccl-regs))
815
816 (defun utf-8-help-echo (window object position)
817 (format "Untranslated Unicode U+%04X"
818 (get-char-property position 'untranslated-utf-8 object)))
819
820 ;; We compose the untranslatable sequences into a single character,
821 ;; and move point to the next character.
822 ;; This is infelicitous for editing, because there's currently no
823 ;; mechanism for treating compositions as atomic, but is OK for
824 ;; display. They are composed to U+FFFD with help-echo which
825 ;; indicates the unicodes they represent. This function GCs too much.
826
827 ;; If utf-translate-cjk-mode is non-nil, this function is called with
828 ;; HASH-TABLE which translates CJK characters into some of CJK
829 ;; charsets.
830
831 (defsubst utf-8-compose (hash-table)
832 "Put a suitable composition on an untranslatable sequence at point.
833 If HASH-TABLE is non-nil, try to translate CJK characters by it at first.
834 Move point to the end of the sequence."
835 (utf-8-untranslated-to-ucs)
836 (let ((l (aref utf-8-ccl-regs 1))
837 ch)
838 (if (> l 0)
839 (if (and hash-table
840 (setq ch (gethash (aref utf-8-ccl-regs 0) hash-table)))
841 (progn
842 (insert ch)
843 (delete-region (point) (min (point-max) (+ l (point)))))
844 (setq ch (aref utf-8-ccl-regs 0))
845 (put-text-property (point) (min (point-max) (+ l (point)))
846 'untranslated-utf-8 ch)
847 (put-text-property (point) (min (point-max) (+ l (point)))
848 'help-echo 'utf-8-help-echo)
849 (if (= l 2)
850 (put-text-property (point) (min (point-max) (+ l (point)))
851 'display (format "\\%03o" ch))
852 (compose-region (point) (+ l (point)) ?\e$,3u=\e(B))
853 (forward-char l))
854 (forward-char 1))))
855
856 (defcustom utf-8-compose-scripts nil
857 "*Non-nil means compose various scripts on decoding utf-8 text."
858 :group 'mule
859 :version "21.4"
860 :type 'boolean)
861
862 (defun utf-8-post-read-conversion (length)
863 "Compose untranslated utf-8 sequences into single characters.
864 If `utf-translate-cjk-mode' is non-nil, tries to translate CJK characters.
865 Also compose particular scripts if `utf-8-compose-scripts' is non-nil."
866 (save-excursion
867 (save-restriction
868 (narrow-to-region (point) (+ (point) length))
869 ;; Can't do eval-when-compile to insert a multibyte constant
870 ;; version of the string in the loop, since it's always loaded as
871 ;; unibyte from a byte-compiled file.
872 (let ((range (string-as-multibyte "^\xc0-\xc3\xe1-\xf7"))
873 hash-table ch)
874 (when utf-translate-cjk-mode
875 (if (not utf-translate-cjk-lang-env)
876 ;; Check these characters:
877 ;; "U+2e80-U+33ff", "U+ff00-U+ffef"
878 ;; We may have to translate them to CJK charsets.
879 (let ((range2 "\e$,29@\e(B-\e$,2G\7f\e$,3r`\e(B-\e$,3u/\e(B"))
880 (skip-chars-forward (concat range range2))
881 (unless (eobp)
882 (utf-translate-cjk-load-tables)
883 (setq range (concat range range2)))
884 (setq hash-table (get 'utf-subst-table-for-decode
885 'translation-hash-table)))))
886 (while (and (skip-chars-forward range)
887 (not (eobp)))
888 (setq ch (following-char))
889 (if (< ch 256)
890 (utf-8-compose hash-table)
891 (if (and hash-table
892 (setq ch (gethash (encode-char ch 'ucs) hash-table)))
893 (progn
894 (insert ch)
895 (delete-char 1))
896 (forward-char 1)))))
897
898 (when (and utf-8-compose-scripts (> length 1))
899 ;; These currently have definitions which cover the relevant
900 ;; unicodes. We could avoid loading thai-util &c by checking
901 ;; whether the region contains any characters with the appropriate
902 ;; categories. There aren't yet Unicode-based rules for Tibetan.
903 (diacritic-compose-region (point-max) (point-min))
904 (thai-compose-region (point-max) (point-min))
905 (lao-compose-region (point-max) (point-min))
906 (devanagari-compose-region (point-max) (point-min))
907 (malayalam-compose-region (point-max) (point-min))
908 (tamil-compose-region (point-max) (point-min)))
909 (- (point-max) (point-min)))))
910
911 (defun utf-8-pre-write-conversion (beg end)
912 "Prepare for `utf-translate-cjk-mode' to encode text between BEG and END.
913 This is used as a post-read-conversion of utf-8 coding system."
914 (if (and utf-translate-cjk-mode
915 (not utf-translate-cjk-lang-env)
916 (save-excursion
917 (goto-char beg)
918 (re-search-forward "\\cc\\|\\cj\\|\\ch" end t)))
919 (utf-translate-cjk-load-tables))
920 nil)
921
922 (make-coding-system
923 'mule-utf-8 4 ?u
924 "UTF-8 encoding for Emacs-supported Unicode characters.
925 It supports Unicode characters of these ranges:
926 U+0000..U+33FF, U+E000..U+FFFF.
927 They correspond to these Emacs character sets:
928 ascii, latin-iso8859-1, mule-unicode-0100-24ff,
929 mule-unicode-2500-33ff, mule-unicode-e000-ffff
930
931 On decoding (e.g. reading a file), Unicode characters not in the above
932 ranges are decoded into sequences of eight-bit-control and
933 eight-bit-graphic characters to preserve their byte sequences. The
934 byte sequence is preserved on i/o for valid utf-8, but not necessarily
935 for invalid utf-8.
936
937 On encoding (e.g. writing a file), Emacs characters not belonging to
938 any of the character sets listed above are encoded into the UTF-8 byte
939 sequence representing U+FFFD (REPLACEMENT CHARACTER)."
940
941 '(ccl-decode-mule-utf-8 . ccl-encode-mule-utf-8)
942 `((safe-charsets
943 ascii
944 eight-bit-control
945 eight-bit-graphic
946 latin-iso8859-1
947 mule-unicode-0100-24ff
948 mule-unicode-2500-33ff
949 mule-unicode-e000-ffff
950 ,@(if utf-translate-cjk-mode
951 utf-translate-cjk-charsets))
952 (mime-charset . utf-8)
953 (coding-category . coding-category-utf-8)
954 (valid-codes (0 . 255))
955 (pre-write-conversion . utf-8-pre-write-conversion)
956 (post-read-conversion . utf-8-post-read-conversion)
957 (translation-table-for-encode . utf-translation-table-for-encode)
958 (dependency unify-8859-on-encoding-mode
959 unify-8859-on-decoding-mode
960 utf-fragment-on-decoding
961 utf-translate-cjk-mode)))
962
963 (define-coding-system-alias 'utf-8 'mule-utf-8)
964
965 ;; I think this needs special private charsets defined for the
966 ;; untranslated sequences, if it's going to work well.
967
968 ;;; (defun utf-8-compose-function (pos to pattern &optional string)
969 ;;; (let* ((prop (get-char-property pos 'composition string))
970 ;;; (l (and prop (- (cadr prop) (car prop)))))
971 ;;; (cond ((and l (> l (- to pos)))
972 ;;; (delete-region pos to))
973 ;;; ((and (> (char-after pos) 224)
974 ;;; (< (char-after pos) 256)
975 ;;; (save-restriction
976 ;;; (narrow-to-region pos to)
977 ;;; (utf-8-compose)))
978 ;;; t))))
979
980 ;;; (dotimes (i 96)
981 ;;; (aset composition-function-table
982 ;;; (+ 128 i)
983 ;;; `((,(string-as-multibyte "[\200-\237\240-\377]")
984 ;;; . utf-8-compose-function))))
985
986 ;;; arch-tag: b08735b7-753b-4ae6-b754-0f3efe4515c5
987 ;;; utf-8.el ends here