17052
|
1 ;;; devan-util.el --- Support for Devanagari Script Composition
|
|
2
|
|
3 ;; Copyright (C) 1996 Free Software Foundation, Inc.
|
|
4
|
|
5 ;; Author: KAWABATA, Taichi <kawabata@is.s.u-tokyo.ac.jp>
|
|
6
|
|
7 ;; Keywords: multilingual, Indian, Devanagari
|
|
8
|
|
9 ;; This file is part of GNU Emacs.
|
|
10
|
|
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
12 ;; it under the terms of the GNU General Public License as published by
|
|
13 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
14 ;; any later version.
|
|
15
|
|
16 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19 ;; GNU General Public License for more details.
|
|
20
|
|
21 ;; You should have received a copy of the GNU General Public License
|
|
22 ;; along with GNU Emacs; see the file COPYING. If not, write to
|
|
23 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
24
|
|
25 ;;; Commentary:
|
|
26
|
|
27 ;; History:
|
|
28 ;; 1996.10.18 written by KAWABATA, Taichi <kawabata@is.s.u-tokyo.ac.jp>
|
|
29
|
|
30 ;; Devanagari script composition rules and related programs.
|
|
31
|
|
32 ;;; Code:
|
|
33
|
|
34 ;;;
|
|
35 ;;; Steps toward composition of Devanagari Characters.
|
|
36 ;;;
|
|
37
|
|
38 ;;; Basic functions.
|
|
39
|
|
40 ;;;###autoload
|
|
41 (defun indian-to-devanagari (ch)
|
|
42 "Convert IS 13194 characters to Devanagari basic characters."
|
|
43 (let ((charcodes (split-char ch)))
|
|
44 (if (eq (car charcodes) 'indian-is13194)
|
|
45 (make-char 'indian-2-column ?\x21 (nth 1 charcodes))
|
|
46 ch)))
|
|
47
|
|
48 ;;;###autoload
|
|
49 (defun devanagari-to-indian (ch)
|
|
50 "Convert Devanagari basic characters to IS 13194 characters."
|
|
51 (let* ((charcodes (split-char ch))
|
|
52 (charset (car charcodes))
|
|
53 (code-h (car (cdr charcodes))))
|
|
54 (if (and (eq (car charcodes) 'indian-2-column)
|
|
55 (= (nth 1 charcodes) ?\x21))
|
|
56 (make-char 'indian-is13194 (nth 2 charcodes))
|
|
57 ch)))
|
|
58
|
|
59 ;;;###autoload
|
|
60 (defun indian-to-devanagari-region (from to)
|
|
61 "Convert IS 13194 characters in region to Devanagari basic characters."
|
|
62 (interactive "r")
|
|
63 (save-restriction
|
|
64 (narrow-to-region from to)
|
|
65 (goto-char (point-min))
|
|
66 (while (re-search-forward "\\cd" nil t)
|
|
67 (let* ((devanagari-char (indian-to-devanagari (preceding-char))))
|
|
68 (delete-char -1)
|
|
69 (insert devanagari-char)))))
|
|
70
|
|
71 ;;;###autoload
|
|
72 (defun devanagari-to-indian-region (from to)
|
|
73 "Convert Devanagari basic characters in region to Indian characters."
|
|
74 (interactive "r")
|
|
75 (save-restriction
|
|
76 (narrow-to-region from to)
|
|
77 (goto-char (point-min))
|
|
78 (while (re-search-forward "\\cD" nil t) ; Devanagari Character Code.
|
|
79 (let* ((indian-char (devanagari-to-indian (preceding-char))))
|
|
80 (delete-char -1)
|
|
81 (insert indian-char)))))
|
|
82
|
|
83 ;;;###autoload
|
|
84 (defun indian-to-devanagari-string (str)
|
|
85 "Convert Indian String to Devanagari Basic Character String."
|
|
86 (let ((pos 0) (dst "") (src str) char)
|
|
87 (while (not (equal src ""))
|
|
88 (setq char (string-to-char src))
|
|
89 (setq src (substring src (char-bytes char)))
|
|
90 (setq dst (concat dst (char-to-string (indian-to-devanagari char)))))
|
|
91 dst))
|
|
92
|
|
93 ;; Phase 0 - Determine whether the characters can be composed.
|
|
94 ;;
|
|
95 ;;;
|
|
96 ;;; Regular expressions to split characters for composition.
|
|
97 ;;;
|
|
98 ;;
|
|
99 ;; Indian script word contains one or more syllables.
|
|
100 ;; In BNF, it can be expressed as follows:
|
|
101 ;;
|
|
102 ;; Word ::= {Syllable} [Cons-Syllable]
|
|
103 ;; Syllable ::= Cons-Vowel-Syllable | Vowel-Syllable
|
|
104 ;; Vowel-Syllable ::= V[D]
|
|
105 ;; Cons-Vowel-Syllable ::= [Cons-Syllable] Full-Cons [M] [D]
|
|
106 ;; Cons-Syllable ::= [Pure-Cons] [Pure-Cons] Pure-Cons
|
|
107 ;; Pure-Cons ::= Full-Cons H
|
|
108 ;; Full-Cons ::= C [N]
|
|
109 ;;
|
|
110 ;; {} repeat, [] optional
|
|
111 ;;
|
|
112 ;; C - Consonant ($(5!3!4!5!6!7!8!9!:!;!<!=!>!?!@!A!B!C!D!E(B
|
|
113 ;; $(5!F!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X(B)
|
|
114 ;; N - Nukta ($(5!i(B)
|
|
115 ;; H - Halant($(5!h(B)
|
|
116 ;; V - Vowel ($(5!$!%!&!'!(!)!*!+!,!-!.!/!0!1!2(B)
|
|
117 ;; D - Vowel Modifiers, i.e. Anuswar, Chandrabindu, Visarg ($(5!!!"(B)
|
|
118 ;; M - Matra ($(5!Z![!\!]!^!_!`!a!b!c!d!e!f!g(B)
|
|
119 ;;
|
|
120 ;; In Emacs, one syllable of Indian language is considered to be one
|
|
121 ;; composite glyph. If we expand the above expression, it would be:
|
|
122 ;;
|
|
123 ;; [[C [N] H] [C [N] H] C [N] H] C [N] [M] [D] | V [D]
|
|
124 ;;
|
|
125 ;; Therefore, in worst case, the consonant syllabe will consist of
|
|
126 ;; following characters.
|
|
127 ;;
|
|
128 ;; C N H C N H C N H C N M D
|
|
129 ;;
|
|
130 ;; On the other hand, incomplete consonant syllable before inputting
|
|
131 ;; base consonant must satisfy the following condition:
|
|
132 ;;
|
|
133 ;; [C [N] H] [C [N] H] C [N] H
|
|
134 ;;
|
|
135 ;; This is acceptable BEFORE proper consonant-syllable is input. The
|
|
136 ;; string which doesn't match with the above expression is invalid and
|
|
137 ;; thus must be fixed.
|
|
138 ;;
|
|
139 ;; Note:
|
|
140 ;; Third case can be considered, which is acceptable syllable and can
|
|
141 ;; not add any code more.
|
|
142 ;;
|
|
143 ;; [[C [N] H] [C [N] H] C [N] H] C [N] [M] D
|
|
144 ;;
|
|
145 ;; However, to make editing possible even in this condition, we will
|
|
146 ;; not consider about this case.
|
|
147
|
|
148 (defconst devanagari-cons-syllable-examine
|
|
149 "\\(\\([$(5!3(B-$(5!X(B]$(5!i(B?$(5!h(B\\)?\\([$(5!3(B-$(5!X(B]$(5!i(B?$(5!h(B\\)?[$(5!3(B-$(5!X(B]$(5!i(B?$(5!h(B\\)?[$(5!3(B-$(5!X(B]$(5!i(B?[$(5!Z(B-$(5!g(B]?[$(5!!!"(B]?"
|
|
150 "Regexp matching to one Devanagari consonant syllable.")
|
|
151
|
|
152 (defconst devanagari-cons-syllable-incomplete-examine
|
|
153 "\\([$(5!3(B-$(5!X(B]$(5!i(B?$(5!h(B\\)?\\([$(5!3(B-$(5!X(B]$(5!i(B?$(5!h(B\\)?[$(5!3(B-$(5!X(B]$(5!i(B?$(5!h(B$"
|
|
154 "Regexp matching to one Devanagari incomplete consonant syllable.")
|
|
155
|
|
156 (defconst devanagari-vowel-syllable-examine
|
|
157 "[$(5!$(B-$(5!2(B][$(5!!!"!#(B]?"
|
|
158 "Regexp matching to one Devanagari vowel syllable.")
|
|
159
|
|
160 ;;
|
|
161 ;; Also, digits and virams should be processed other than syllables.
|
|
162 ;;
|
|
163 ;; In IS 13194, Avagrah is obtained by Nukta after Viram, and
|
|
164 ;; OM is obtained by Nukta after Chandrabindu
|
|
165 ;;
|
|
166 (defconst devanagari-digit-viram-examine
|
|
167 "[$(5!q(B-$(5!z!j(B]")
|
|
168 (defconst devanagari-other-sign-examine
|
|
169 "[$(5!!!j(B]$(5!i(B")
|
|
170
|
|
171 (defconst devanagari-composite-glyph-unit-examine
|
|
172 (concat "\\(" devanagari-cons-syllable-incomplete-examine
|
|
173 "\\)\\|\\(" devanagari-vowel-syllable-examine
|
|
174 "\\)\\|\\(" devanagari-digit-viram-examine
|
|
175 "\\)\\|\\(" devanagari-cons-syllable-examine
|
|
176 "\\)\\|\\(" devanagari-other-sign-examine"\\)")
|
|
177 "Regexp matching to Devanagari string to be composed form one glyph.")
|
|
178
|
|
179 ;;(put-charset-property charset-devanagari-1-column
|
|
180 ;; 'char-to-glyph 'devanagari-compose-string)
|
|
181 ;;(put-charset-property charset-devanagari-2-column
|
|
182 ;; 'char-to-glyph 'devanagari-compose-string)
|
|
183
|
|
184 ;; Sample
|
|
185 ;;
|
|
186 ;;(string-match devanagari-cons-syllable-examine "$(5!X![(B") => 0
|
|
187 ;;(string-match devanagari-cons-syllable-examine "$(5!F!h!D!\(B") => 0
|
|
188 ;;(string-match devanagari-cons-syllable-examine "$(5!X![!F!h!D!\(B") => 0
|
|
189
|
|
190 ;;
|
|
191 ;; Steps toward the composition
|
|
192 ;; Converting Character Code to Composite Glyph.
|
|
193 ;;
|
|
194 ;; Example : $(5!X![(B/$(5!F!h!D!\(B
|
|
195 ;;
|
|
196 ;; First, convert Characters to appropriate glyphs.
|
|
197 ;;
|
|
198 ;; => $(5!X![(B/$(5"F!D!\(B
|
|
199 ;;
|
|
200 ;; Then, determine the base glyph, apply-orders and apply-rules.
|
|
201 ;;
|
|
202 ;; => $(5!X(B (ml.mr) $(5![(B / $(5!D(B (ml.mr) $(5"F(B (mr ml) $(5!\(B
|
|
203 ;;
|
|
204 ;; Finally, convert 2-column glyphs to 1-column glyph
|
|
205 ;; if such a glyph exist.
|
|
206 ;;
|
|
207 ;; => $(6![(B (ml.mr) $(6!X(B / $(6!D(B (ml.mr) $(6"F(B (mr ml) $(6!\(B
|
|
208 ;;
|
|
209 ;; Compose the glyph.
|
|
210 ;;
|
|
211 ;; => 2$(6!X@![1(B/2$(6!D@"FP!\1(B
|
|
212 ;; => 2$(6!X@![12!D@"FP!\1(B
|
|
213 ;;
|
|
214
|
|
215 ;;
|
|
216 ;; Phase 1: Converting Character Code to Glyph Code.
|
|
217 ;;
|
|
218 ;;
|
|
219 ;; IMPORTANT:
|
|
220 ;; There may be many rules which you many want to be suppressed.
|
|
221 ;; In that case, please comment out that rule.
|
|
222 ;;
|
|
223 ;; RULES WILL BE EVALUATED FROM FIRST TO LAST.
|
|
224 ;; PUT MORE SPECIFIC RULES FIRST.
|
|
225 ;;
|
|
226 ;; TO DO:
|
|
227 ;; Prepare multiple specific list of rules for each languages
|
|
228 ;; which adopts Devanagari script.
|
|
229 ;;
|
|
230
|
|
231
|
|
232 (defconst devanagari-char-to-glyph-rules
|
|
233 '(
|
|
234 ;; special form for "ru".
|
|
235 ("\\($(5!O!](B\\)" . "$(5",(B")
|
|
236 ("\\($(5!O!^(B\\)" . "$(5"-(B")
|
|
237 ("\\($(5!P!](B\\)" . "$(5".(B")
|
|
238 ("\\($(5!P!^(B\\)" . "$(5"/(B")
|
|
239
|
|
240 ;; `r' at the top of syllable and followed by other consonants.
|
|
241 ;; ("[^$(5!h(B]\\($(5!O!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"p(B")
|
|
242 ("^\\($(5!O!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"p(B")
|
|
243
|
|
244 ;; If "r" is preceded by the vowel-suppressed consonant
|
|
245 ;; (especially those with vertical line), it will be written as
|
|
246 ;; slanted line below the preceding consonant character. Some of
|
|
247 ;; them are pre-composed as one glyph.
|
|
248
|
|
249 ("\\($(5!:!i!h!O(B\\)" . "$(5"!(B")
|
|
250 ("\\($(5!I!i!h!O(B\\)" . "$(5""(B")
|
|
251 ("\\($(5!3!h!O(B\\)" . "$(5"#(B")
|
|
252 ("\\($(5!:!h!O(B\\)" . "$(5"$(B")
|
|
253 ("\\($(5!B!h!O(B\\)" . "$(5"%(B")
|
|
254 ("\\($(5!H!h!O(B\\)" . "$(5"&(B")
|
|
255 ("\\($(5!I!h!O(B\\)" . "$(5"'(B")
|
|
256 ("\\($(5!U!h!O(B\\)" . "$(5"((B")
|
|
257 ("\\($(5!W!h!O(B\\)" . "$(5")(B")
|
|
258
|
|
259 ;; Ligature Rules
|
|
260 ("\\($(5!3!h!B!h!O!h!M(B\\)" . "$(5$!(B")
|
|
261 ("\\($(5!3!h!B!h!T(B\\)" . "$(5$"(B")
|
|
262 ("\\($(5!3!h!B!h!M(B\\)" . "$(5$#(B")
|
|
263 ("\\($(5!3!h!F!h!M(B\\)" . "$(5$$(B")
|
|
264 ("\\($(5!3!h!O!h!M(B\\)" . "$(5$%(B")
|
|
265 ("\\($(5!3!h!T!h!M(B\\)" . "$(5$&(B")
|
|
266 ("\\($(5!3!h!3(B\\)" . "$(5$'(B")
|
|
267 ("\\($(5!3!h!B(B\\)" . "$(5$((B")
|
|
268 ("\\($(5!3!h!F(B\\)" . "$(5$)(B")
|
|
269 ("\\($(5!3!h!L(B\\)" . "$(5$*(B")
|
|
270 ("\\($(5!3!h!M(B\\)" . "$(5$+(B")
|
|
271 ("\\($(5!3!h!Q(B\\)" . "$(5$,(B")
|
|
272 ("\\($(5!3!h!T(B\\)" . "$(5$-(B")
|
|
273 ("\\($(5!3!h!V(B\\)" . "$(5$.(B")
|
|
274 ("\\($(5!6!h!F(B\\)" . "$(5$/(B")
|
|
275 ("\\($(5!7!h!3!h!B!h!M(B\\)" . "$(5$0(B")
|
|
276 ("\\($(5!7!h!3!h!V!h!T(B\\)" . "$(5$1(B")
|
|
277 ("\\($(5!7!h!3!h!B(B\\)" . "$(5$2(B")
|
|
278 ("\\($(5!7!h!3!h!V(B\\)" . "$(5$3(B")
|
|
279 ("\\($(5!7!h!6!h!O(B\\)" . "$(5$4(B")
|
|
280 ("\\($(5!7!h!3!h!M(B\\)" . "$(5$5(B")
|
|
281 ("\\($(5!7!h!4!h!M(B\\)" . "$(5$6(B")
|
|
282 ("\\($(5!7!h!5!h!M(B\\)" . "$(5$7(B")
|
|
283 ("\\($(5!7!h!6!h!M(B\\)" . "$(5$8(B")
|
|
284 ("\\($(5!7!h!3(B\\)" . "$(5$9(B")
|
|
285 ("\\($(5!7!h!4(B\\)" . "$(5$:(B")
|
|
286 ("\\($(5!7!h!5(B\\)" . "$(5$;(B")
|
|
287 ("\\($(5!7!h!6(B\\)" . "$(5$<(B")
|
|
288 ("\\($(5!7!h!7(B\\)" . "$(5$=(B")
|
|
289 ("\\($(5!7!h!F(B\\)" . "$(5$>(B")
|
|
290 ("\\($(5!7!h!L(B\\)" . "$(5$?(B")
|
|
291 ("\\($(5!7!h!M(B\\)" . "$(5$@(B")
|
|
292 ("\\($(5!8!h!8(B\\)" . "$(5$A(B")
|
|
293 ("\\($(5!8!h!<(B\\)" . "$(5$B(B")
|
|
294 ("\\($(5!9!h!M(B\\)" . "$(5$C(B")
|
|
295 ("\\($(5!:!h!O(B\\)" . "$(5$D(B")
|
|
296 ("\\($(5!:!h!h(B\\)" . "$(5$E(B")
|
|
297 ("\\($(5!<!h!8(B\\)" . "$(5$F(B")
|
|
298 ("\\($(5!<!h!:(B\\)" . "$(5$G(B")
|
|
299 ("\\($(5!=!h!3(B\\)" . "$(5$H(B")
|
|
300 ("\\($(5!=!h!=(B\\)" . "$(5$I(B")
|
|
301 ("\\($(5!=!h!>(B\\)" . "$(5$J(B")
|
|
302 ("\\($(5!=!h!M(B\\)" . "$(5$K(B")
|
|
303 ("\\($(5!>!h!M(B\\)" . "$(5$L(B")
|
|
304 ("\\($(5!?!h!5!h!M(B\\)" . "$(5$M(B")
|
|
305 ("\\($(5!?!h!6!h!O(B\\)" . "$(5$N(B")
|
|
306 ("\\($(5!?!h!O!h!M(B\\)" . "$(5$O(B")
|
|
307 ("\\($(5!?!h!5(B\\)" . "$(5$P(B")
|
|
308 ("\\($(5!?!h!6(B\\)" . "$(5$Q(B")
|
|
309 ("\\($(5!?!h!?(B\\)" . "$(5$R(B")
|
|
310 ("\\($(5!?!h!L(B\\)" . "$(5$S(B")
|
|
311 ("\\($(5!?!h!M(B\\)" . "$(5$T(B")
|
|
312 ("\\($(5!@!h!M(B\\)" . "$(5$`(B")
|
|
313 ("\\($(5!B!h!B(B\\)" . "$(5$a(B")
|
|
314 ("\\($(5!B!h!F(B\\)" . "$(5$b(B")
|
|
315 ("\\($(5!D!h!D!h!M(B\\)" . "$(5$c(B")
|
|
316 ("\\($(5!D!h!E!h!M(B\\)" . "$(5$d(B")
|
|
317 ("\\($(5!D!h!K!h!M(B\\)" . "$(5$e(B")
|
|
318 ("\\($(5!D!h!O!h!M(B\\)" . "$(5$f(B")
|
|
319 ("\\($(5!D!h!T!h!M(B\\)" . "$(5$g(B")
|
|
320 ("\\($(5!D!h!5!h!O(B\\)" . "$(5$h(B")
|
|
321 ("\\($(5!D!h!6!h!O(B\\)" . "$(5$i(B")
|
|
322 ("\\($(5!D!h!D!h!T(B\\)" . "$(5$j(B")
|
|
323 ("\\($(5!D!h!E!h!T(B\\)" . "$(5$k(B")
|
|
324 ("\\($(5!D!h!5(B\\)" . "$(5$l(B")
|
|
325 ("\\($(5!D!h!6(B\\)" . "$(5$m(B")
|
|
326 ("\\($(5!D!h!D(B\\)" . "$(5$n(B")
|
|
327 ("\\($(5!D!h!E(B\\)" . "$(5$o(B")
|
|
328 ("\\($(5!D!h!F(B\\)" . "$(5$p(B")
|
|
329 ("\\($(5!D!h!J(B\\)" . "$(5$q(B")
|
|
330 ("\\($(5!D!h!K(B\\)" . "$(5$r(B")
|
|
331 ("\\($(5!D!h!L(B\\)" . "$(5$s(B")
|
|
332 ("\\($(5!D!h!M(B\\)" . "$(5$t(B")
|
|
333 ("\\($(5!D!h!T(B\\)" . "$(5$u(B")
|
|
334 ("\\($(5!E!h!F(B\\)" . "$(5$v(B")
|
|
335 ("\\($(5!F!h!F(B\\)" . "$(5$w(B")
|
|
336 ("\\($(5!H!h!B(B\\)" . "$(5$x(B")
|
|
337 ("\\($(5!H!h!F(B\\)" . "$(5$y(B")
|
|
338 ("\\($(5!H!h!Q(B\\)" . "$(5$z(B")
|
|
339 ("\\($(5!J!h!F(B\\)" . "$(5${(B")
|
|
340 ("\\($(5!J!h!J(B\\)" . "$(5$|(B")
|
|
341 ("\\($(5!J!h!T(B\\)" . "$(5$}(B")
|
|
342 ("\\($(5!K!h!F(B\\)" . "$(5$~(B")
|
|
343 ("\\($(5!L!h!F(B\\)" . "$(5#P(B")
|
|
344 ("\\($(5!L!h!Q(B\\)" . "$(5#Q(B")
|
|
345 ("\\($(5!Q!h!Q(B\\)" . "$(5#`(B")
|
|
346 ("\\($(5!T!h!F(B\\)" . "$(5#a(B")
|
|
347 ("\\($(5!T!h!T(B\\)" . "$(5#b(B")
|
|
348 ("\\($(5!U!h!8(B\\)" . "$(5#c(B")
|
|
349 ("\\($(5!U!h!F(B\\)" . "$(5#d(B")
|
|
350 ("\\($(5!U!h!J(B\\)" . "$(5#e(B")
|
|
351 ("\\($(5!U!h!Q(B\\)" . "$(5#f(B")
|
|
352 ("\\($(5!U!h!T(B\\)" . "$(5#g(B")
|
|
353 ("\\($(5!V!h!=!h!O!h!M(B\\)" . "$(5#h(B")
|
|
354 ("\\($(5!V!h!=!h!M(B\\)" . "$(5#i(B")
|
|
355 ("\\($(5!V!h!=!h!T(B\\)" . "$(5#j(B")
|
|
356 ("\\($(5!V!h!=(B\\)" . "$(5#k(B")
|
|
357 ("\\($(5!V!h!>(B\\)" . "$(5#l(B")
|
|
358 ("\\($(5!W!h!F(B\\)" . "$(5#m(B")
|
|
359 ("\\($(5!W!h!O(B\\)" . "$(5#n(B")
|
|
360 ("\\($(5!X!h!A(B\\)" . "$(5#p(B")
|
|
361 ("\\($(5!X!h!F(B\\)" . "$(5#q(B")
|
|
362 ("\\($(5!X!h!L(B\\)" . "$(5#r(B")
|
|
363 ("\\($(5!X!h!M(B\\)" . "$(5#s(B")
|
|
364 ("\\($(5!X!h!O(B\\)" . "$(5#t(B")
|
|
365 ("\\($(5!X!h!Q(B\\)" . "$(5#u(B")
|
|
366 ("\\($(5!X!h!T(B\\)" . "$(5#v(B")
|
|
367 ;; Special Ligature Rules
|
|
368 ("\\($(5!X!_(B\\)" . "$(5#R(B")
|
|
369
|
|
370 ;; Half form with ligature. Special "r" case is included. "r"
|
|
371 ;; connection which is not listed here has not been examined yet.
|
|
372 ;; I don't know what to do with them.
|
|
373 ;;
|
|
374 ;; special forms
|
|
375 ("\\($(5!3!h!V!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"l(B")
|
|
376 ("\\($(5!:!h!<!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"m(B")
|
|
377 ;; ordinary forms
|
|
378 ("\\($(5!5!h!O!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"`(B")
|
|
379 ("\\($(5!6!h!F!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"a(B")
|
|
380 ;; ("\\($(5!<!h!8!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"c(B") ; Mistake, must check later.
|
|
381 ("\\($(5!B!h!B!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"c(B")
|
|
382 ("\\($(5!B!h!O!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"d(B")
|
|
383 ("\\($(5!E!h!F!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"e(B")
|
|
384 ("\\($(5!E!h!O!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"f(B")
|
|
385 ("\\($(5!H!h!B!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"g(B")
|
|
386 ("\\($(5!U!h!8!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"h(B")
|
|
387 ("\\($(5!U!h!O!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"i(B")
|
|
388 ("\\($(5!U!h!T!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"j(B")
|
|
389 ;; ("\\($(5!U!h!T!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"k(B") ; must check later.
|
|
390 ;; Conjunction form associated with Nukta sign.
|
|
391 ("\\($(5!3!i!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"s(B")
|
|
392 ("\\($(5!4!i!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"t(B")
|
|
393 ("\\($(5!5!i!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"u(B")
|
|
394 ("\\($(5!:!i!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"z(B")
|
|
395 ("\\($(5!I!i!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"y(B")
|
|
396
|
|
397 ;; For consonants other than listed above, glyph-composition will
|
|
398 ;; be applied. If the consonant which is preceding "$(5!O(B" does not
|
|
399 ;; have the vertical line (such as "$(5!?(B"), "$(5"r(B" is put beneath the
|
|
400 ;; consonant.
|
|
401 ;;
|
|
402 ;; ("cons-not-yet-listed-up\\($(5!h!O(B\\)" . "$(5"q(B")
|
|
403 ("[$(5!7!9!=!>!?!@!D!O!P!R!S!X(B]\\($(5!h!O(B\\)" . "$(5"r(B")
|
|
404 ("$(5!?!i(B\\($(5!h!O(B\\)" . "$(5"r(B")
|
|
405 ("$(5!@!i(B\\($(5!h!O(B\\)" . "$(5"r(B")
|
|
406
|
|
407 ;; Nukta
|
|
408 ("\\($(5!!!i(B\\)" . "$(5#!(B")
|
|
409 ("\\($(5!&!i(B\\)" . "$(5#&(B")
|
|
410 ("\\($(5!'!i(B\\)" . "$(5#'(B")
|
|
411 ("\\($(5!*!i(B\\)" . "$(5#*(B")
|
|
412 ("\\($(5!3!i(B\\)" . "$(5#3(B")
|
|
413 ("\\($(5!4!i(B\\)" . "$(5#4(B")
|
|
414 ("\\($(5!5!i(B\\)" . "$(5#5(B")
|
|
415 ("\\($(5!:!i(B\\)" . "$(5#:(B")
|
|
416 ("\\($(5!?!i(B\\)" . "$(5#?(B")
|
|
417 ("\\($(5!@!i(B\\)" . "$(5#@(B")
|
|
418 ("\\($(5!I!i(B\\)" . "$(5#I(B")
|
|
419 ("\\($(5!j!i(B\\)" . "$(5#J(B")
|
|
420
|
|
421 ;; Half forms.
|
|
422 ("\\($(5!3!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"3(B")
|
|
423 ("\\($(5!4!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"4(B")
|
|
424 ("\\($(5!5!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"5(B")
|
|
425 ("\\($(5!6!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"6(B")
|
|
426 ("\\($(5!8!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"8(B")
|
|
427 ("\\($(5!:!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5":(B")
|
|
428 ("\\($(5!;!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5";(B")
|
|
429 ("\\($(5!<!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"<(B")
|
|
430 ("\\($(5!A!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"A(B")
|
|
431 ("\\($(5!B!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"B(B")
|
|
432 ("\\($(5!C!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"C(B")
|
|
433 ("\\($(5!E!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"E(B")
|
|
434 ("\\($(5!F!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"F(B")
|
|
435 ("\\($(5!G!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"G(B")
|
|
436 ("\\($(5!H!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"H(B")
|
|
437 ("\\($(5!I!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"I(B")
|
|
438 ("\\($(5!J!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"J(B")
|
|
439 ("\\($(5!K!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"K(B")
|
|
440 ("\\($(5!L!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"L(B")
|
|
441 ("\\($(5!M!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"M(B")
|
|
442 ("\\($(5!N!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"N(B")
|
|
443 ("\\($(5!Q!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"Q(B")
|
|
444 ("\\($(5!R!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"R(B")
|
|
445 ("\\($(5!S!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"S(B")
|
|
446 ("\\($(5!T!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"T(B")
|
|
447 ("\\($(5!U!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"U(B")
|
|
448 ("\\($(5!V!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"V(B")
|
|
449 ("\\($(5!W!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"W(B")
|
|
450 )
|
|
451 "Alist of regexps of Devanagari character sequences vs composed characters.")
|
|
452
|
|
453 ;; Example:
|
|
454 ;;("\\($(5!F!h(B\\)[$(5!3(B-$(5!X(B]" . "$(5"F(B")
|
|
455 ;;(string-match "\\($(5!F!h(B\\)[$(5!3(B-$(5!X(B]" "$(5!X![!F!h!D!\(B") => 8
|
|
456 ;;(match-end 1) => 16
|
|
457
|
|
458 ;;
|
|
459 ;; Defining character properties : char-to-glyph, glyph-to-char
|
|
460 ;;
|
|
461 ;; * If char-to-glyph is non-nil, it would be one of the following forms.
|
|
462 ;;
|
|
463 ;; (("character-regexp" . "glyphs")
|
|
464 ;; .....) or
|
|
465 ;; (("character-regexp" . ?glyph)
|
|
466 ;; .....) or
|
|
467 ;; ("characters-regexp" . "glyphs")
|
|
468 ;; or
|
|
469 ;; ?glyph
|
|
470 ;;
|
|
471 ;; * If glyph-to-char is non-nil, it would be one of the following forms.
|
|
472 ;;
|
|
473 ;; (("glyph-regexp" . "characters") ;; This is the only case in Devanagari
|
|
474 ;; ....) or
|
|
475 ;; (("glyph-regexp" . ?character)
|
|
476 ;; ....) or
|
|
477 ;; ("glyph-regexp" . "characters")
|
|
478 ;; or
|
|
479 ;; "characters"
|
|
480 ;; or
|
|
481 ;; ?character
|
|
482 ;;
|
|
483
|
|
484 (let ((rules devanagari-char-to-glyph-rules))
|
|
485 (while rules
|
|
486 (let ((rule (car rules))
|
|
487 (chars) (char) (glyph))
|
|
488 (setq rules (cdr rules))
|
|
489 (string-match "\\\\(\\(.+\\)\\\\)" (car rule))
|
|
490 (setq chars (substring (car rule) (match-beginning 1) (match-end 1)))
|
|
491 (setq char (string-to-char chars))
|
|
492 (setq glyph (string-to-char (cdr rule))) ; assume one glyph in devan.
|
|
493 (put-char-code-property
|
|
494 char 'char-to-glyph
|
|
495 (append (get-char-code-property char 'char-to-glyph) (list rule)))
|
|
496 (put-char-code-property glyph 'glyph-to-char chars))))
|
|
497
|
|
498 ;;
|
|
499 ;; Convert Character Code to Glyph Code
|
|
500 ;;
|
|
501
|
|
502 ;;;###autoload
|
|
503 (defun char-to-glyph-devanagari (src-str)
|
|
504 "Convert Devanagari characters in the string to Devanagari glyphs.
|
|
505 Ligatures and special rules are processed."
|
|
506 (let ((pos 0)
|
|
507 (dst-str ""))
|
|
508 (while (< pos (length src-str))
|
|
509 (let ((found nil)
|
|
510 (rules (get-char-code-property
|
|
511 (string-to-char
|
|
512 ;; caution. other forms not supported for now.
|
|
513 (substring src-str pos)) 'char-to-glyph)))
|
|
514 (while rules
|
|
515 (let* ((rule (car rules))
|
|
516 (regexp (car rule)))
|
|
517 (if (string-match regexp src-str)
|
|
518 (if (= (match-beginning 1) pos)
|
|
519 (progn
|
|
520 (setq dst-str (concat dst-str (cdr rule)))
|
|
521 (setq rules nil) ; Get out of the loop.
|
|
522 (setq found t)
|
|
523 ;; proceed `pos' for replaced characters.
|
|
524 (setq pos (match-end 1)))
|
|
525 (setq rules (cdr rules)))
|
|
526 (setq rules (cdr rules)))))
|
|
527 ;; proceed to next position
|
|
528 (if (not found)
|
|
529 (let ((nextchar (string-to-char (substring src-str pos))))
|
|
530 (setq pos (+ pos
|
|
531 (char-bytes (string-to-char (substring src-str pos)))))
|
|
532 (setq dst-str (concat dst-str (char-to-string nextchar)))))))
|
|
533 dst-str))
|
|
534
|
|
535 ;; Example:
|
|
536 ;;(char-to-glyph-devanagari "$(5!X![!F!h!D!\(B") => "$(5!X!["F!D!\(B"
|
|
537 ;;(char-to-glyph-devanagari "$(5!O!Z!V!h!=!h!O![!M(B") => ???
|
|
538
|
|
539 ;;
|
|
540 ;; Phase 2: Compose Glyphs to form One Glyph.
|
|
541 ;;
|
|
542
|
|
543 ;; Each list consist of glyph, application-priority and application-direction.
|
|
544 ;;
|
|
545 ;; Glyphs will be ordered from low priority number to high priority number.
|
|
546 ;; If application-priority is omitted, it is assumed to be 0.
|
|
547 ;; If application-direction is omitted, it is asumbed to be '(mr . ml).
|
|
548
|
|
549 (defconst devanagari-composition-rules
|
|
550 '((?$(5!!(B 60 (tr . br))
|
|
551 (?$(5!"(B 60 (tr . br))
|
|
552 (?$(5!#(B 60)
|
|
553 (?$(5!$(B 0)
|
|
554 (?$(5!%(B 0)
|
|
555 (?$(5!&(B 0)
|
|
556 (?$(5!'(B 0)
|
|
557 (?$(5!((B 0)
|
|
558 (?$(5!)(B 0)
|
|
559 (?$(5!*(B 0)
|
|
560 (?$(5!+(B 0)
|
|
561 (?$(5!,(B 0)
|
|
562 (?$(5!-(B 0)
|
|
563 (?$(5!.(B 0)
|
|
564 (?$(5!/(B 0)
|
|
565 (?$(5!0(B 0)
|
|
566 (?$(5!1(B 0)
|
|
567 (?$(5!2(B 0)
|
|
568 (?$(5!3(B 0)
|
|
569 (?$(5!4(B 0)
|
|
570 (?$(5!5(B 0)
|
|
571 (?$(5!6(B 0)
|
|
572 (?$(5!7(B 0)
|
|
573 (?$(5!8(B 0)
|
|
574 (?$(5!9(B 0)
|
|
575 (?$(5!:(B 0)
|
|
576 (?$(5!;(B 0)
|
|
577 (?$(5!<(B 0)
|
|
578 (?$(5!=(B 0)
|
|
579 (?$(5!>(B 0)
|
|
580 (?$(5!?(B 0)
|
|
581 (?$(5!@(B 0)
|
|
582 (?$(5!A(B 0)
|
|
583 (?$(5!B(B 0)
|
|
584 (?$(5!C(B 0)
|
|
585 (?$(5!D(B 0)
|
|
586 (?$(5!E(B 0)
|
|
587 (?$(5!F(B 0)
|
|
588 (?$(5!G(B 0)
|
|
589 (?$(5!H(B 0)
|
|
590 (?$(5!I(B 0)
|
|
591 (?$(5!J(B 0)
|
|
592 (?$(5!K(B 0)
|
|
593 (?$(5!L(B 0)
|
|
594 (?$(5!M(B 0)
|
|
595 (?$(5!N(B 0)
|
|
596 (?$(5!O(B 0)
|
|
597 (?$(5!P(B 0)
|
|
598 (?$(5!Q(B 0)
|
|
599 (?$(5!R(B 0)
|
|
600 (?$(5!S(B 0)
|
|
601 (?$(5!T(B 0)
|
|
602 (?$(5!U(B 0)
|
|
603 (?$(5!V(B 0)
|
|
604 (?$(5!W(B 0)
|
|
605 (?$(5!X(B 0)
|
|
606 (?$(5!Y(B 0)
|
|
607 (?$(5!Z(B 40)
|
|
608 (?$(5![(B 40 (ml . mr))
|
|
609 (?$(5!\(B 40)
|
|
610 (?$(5!](B 40 (bc . tc))
|
|
611 (?$(5!^(B 40 (bc . tc))
|
|
612 (?$(5!_(B 40 (bc . tc))
|
|
613 (?$(5!`(B 40 (tc . bc))
|
|
614 (?$(5!a(B 40 (tc . bc))
|
|
615 (?$(5!b(B 40 (tc . bc))
|
|
616 (?$(5!c(B 40 (tc . bc))
|
|
617 (?$(5!d(B 40)
|
|
618 (?$(5!e(B 40)
|
|
619 (?$(5!f(B 40)
|
|
620 (?$(5!g(B 40)
|
|
621 (?$(5!h(B 0 (br . tr)) ; Halant's special treatment.
|
|
622 (?$(5!i(B 0 (br . tr)) ; Nukta's special treatment.
|
|
623 (?$(5!j(B 0)
|
|
624 (nil 0)
|
|
625 (nil 0)
|
|
626 (nil 0)
|
|
627 (nil 0)
|
|
628 (nil 0)
|
|
629 (nil 0)
|
|
630 (?$(5!q(B 0)
|
|
631 (?$(5!r(B 0)
|
|
632 (?$(5!s(B 0)
|
|
633 (?$(5!t(B 0)
|
|
634 (?$(5!u(B 0)
|
|
635 (?$(5!v(B 0)
|
|
636 (?$(5!w(B 0)
|
|
637 (?$(5!x(B 0)
|
|
638 (?$(5!y(B 0)
|
|
639 (?$(5!z(B 0)
|
|
640 (nil 0)
|
|
641 (nil 0)
|
|
642 (nil 0)
|
|
643 (nil 0)
|
|
644 (?$(5"!(B 0)
|
|
645 (?$(5""(B 0)
|
|
646 (?$(5"#(B 0)
|
|
647 (?$(5"$(B 0)
|
|
648 (?$(5"%(B 0)
|
|
649 (?$(5"&(B 0)
|
|
650 (?$(5"'(B 0)
|
|
651 (?$(5"((B 0)
|
|
652 (?$(5")(B 0)
|
|
653 (?$(5"*(B 0)
|
|
654 (?$(5"+(B 0)
|
|
655 (?$(5",(B 0)
|
|
656 (?$(5"-(B 0)
|
|
657 (?$(5".(B 0)
|
|
658 (?$(5"/(B 0)
|
|
659 (?$(5"0(B 0)
|
|
660 (?$(5"1(B 0)
|
|
661 (?$(5"2(B 0)
|
|
662 (?$(5"3(B 0)
|
|
663 (?$(5"4(B 0)
|
|
664 (?$(5"5(B 0)
|
|
665 (?$(5"6(B 0)
|
|
666 (?$(5"7(B 0)
|
|
667 (?$(5"8(B 0)
|
|
668 (?$(5"9(B 0)
|
|
669 (?$(5":(B 0)
|
|
670 (?$(5";(B 0)
|
|
671 (?$(5"<(B 0)
|
|
672 (?$(5"=(B 0)
|
|
673 (?$(5">(B 0)
|
|
674 (?$(5"?(B 0)
|
|
675 (?$(5"@(B 0)
|
|
676 (?$(5"A(B 0)
|
|
677 (?$(5"B(B 0)
|
|
678 (?$(5"C(B 0)
|
|
679 (?$(5"D(B 0)
|
|
680 (?$(5"E(B 0)
|
|
681 (?$(5"F(B 0)
|
|
682 (?$(5"G(B 0)
|
|
683 (?$(5"H(B 0)
|
|
684 (?$(5"I(B 0)
|
|
685 (?$(5"J(B 0)
|
|
686 (?$(5"K(B 0)
|
|
687 (?$(5"L(B 0)
|
|
688 (?$(5"M(B 0)
|
|
689 (?$(5"N(B 0)
|
|
690 (?$(5"O(B 0)
|
|
691 (?$(5"P(B 0)
|
|
692 (?$(5"Q(B 0)
|
|
693 (?$(5"R(B 0)
|
|
694 (?$(5"S(B 0)
|
|
695 (?$(5"T(B 0)
|
|
696 (?$(5"U(B 0)
|
|
697 (?$(5"V(B 0)
|
|
698 (?$(5"W(B 0)
|
|
699 (?$(5"X(B 0)
|
|
700 (?$(5"Y(B 0)
|
|
701 (?$(5"Z(B 0)
|
|
702 (?$(5"[(B 0)
|
|
703 (?$(5"\(B 0)
|
|
704 (?$(5"](B 0)
|
|
705 (?$(5"^(B 0)
|
|
706 (?$(5"_(B 0)
|
|
707 (?$(5"`(B 0)
|
|
708 (?$(5"a(B 0)
|
|
709 (?$(5"b(B 0)
|
|
710 (?$(5"c(B 0)
|
|
711 (?$(5"d(B 0)
|
|
712 (?$(5"e(B 0)
|
|
713 (?$(5"f(B 0)
|
|
714 (?$(5"g(B 0)
|
|
715 (?$(5"h(B 0)
|
|
716 (?$(5"i(B 0)
|
|
717 (?$(5"j(B 0)
|
|
718 (?$(5"k(B 0)
|
|
719 (?$(5"l(B 0)
|
|
720 (?$(5"m(B 0)
|
|
721 (?$(5"n(B 0)
|
|
722 (?$(5"o(B 0)
|
|
723 (?$(5"p(B 20 (tr . br))
|
|
724 (?$(5"q(B 20 (br . tr))
|
|
725 (?$(5"r(B 20 (br . tr))
|
|
726 (?$(5"s(B 0)
|
|
727 (?$(5"t(B 0)
|
|
728 (?$(5"u(B 0)
|
|
729 (?$(5"v(B 0)
|
|
730 (?$(5"w(B 0)
|
|
731 (?$(5"x(B 0)
|
|
732 (?$(5"y(B 0)
|
|
733 (?$(5"z(B 0)
|
|
734 (?$(5"{(B 0)
|
|
735 (?$(5"|(B 0)
|
|
736 (?$(5"}(B 0)
|
|
737 (?$(5"~(B 0)
|
|
738 (?$(5#!(B 0)
|
|
739 (?$(5#"(B 0)
|
|
740 (?$(5##(B 0)
|
|
741 (?$(5#$(B 0)
|
|
742 (?$(5#%(B 0)
|
|
743 (?$(5#&(B 0)
|
|
744 (?$(5#'(B 0)
|
|
745 (?$(5#((B 0)
|
|
746 (?$(5#)(B 0)
|
|
747 (?$(5#*(B 0)
|
|
748 (?$(5#+(B 0)
|
|
749 (?$(5#,(B 0)
|
|
750 (?$(5#-(B 0)
|
|
751 (?$(5#.(B 0)
|
|
752 (?$(5#/(B 0)
|
|
753 (?$(5#0(B 0)
|
|
754 (?$(5#1(B 0)
|
|
755 (?$(5#2(B 0)
|
|
756 (?$(5#3(B 0)
|
|
757 (?$(5#4(B 0)
|
|
758 (?$(5#5(B 0)
|
|
759 (?$(5#6(B 0)
|
|
760 (?$(5#7(B 0)
|
|
761 (?$(5#8(B 0)
|
|
762 (?$(5#9(B 0)
|
|
763 (?$(5#:(B 0)
|
|
764 (?$(5#;(B 0)
|
|
765 (?$(5#<(B 0)
|
|
766 (?$(5#=(B 0)
|
|
767 (?$(5#>(B 0)
|
|
768 (?$(5#?(B 0)
|
|
769 (?$(5#@(B 0)
|
|
770 (?$(5#A(B 0)
|
|
771 (?$(5#B(B 0)
|
|
772 (?$(5#C(B 0)
|
|
773 (?$(5#D(B 0)
|
|
774 (?$(5#E(B 0)
|
|
775 (?$(5#F(B 0)
|
|
776 (?$(5#G(B 0)
|
|
777 (?$(5#H(B 0)
|
|
778 (?$(5#I(B 0)
|
|
779 (?$(5#J(B 0)
|
|
780 (?$(5#K(B 0)
|
|
781 (?$(5#L(B 0)
|
|
782 (?$(5#M(B 0)
|
|
783 (?$(5#N(B 0)
|
|
784 (?$(5#O(B 0)
|
|
785 (?$(5#P(B 0)
|
|
786 (?$(5#Q(B 0)
|
|
787 (?$(5#R(B 0)
|
|
788 (?$(5#S(B 0)
|
|
789 (?$(5#T(B 0)
|
|
790 (?$(5#U(B 0)
|
|
791 (?$(5#V(B 0)
|
|
792 (?$(5#W(B 0)
|
|
793 (?$(5#X(B 0)
|
|
794 (?$(5#Y(B 0)
|
|
795 (?$(5#Z(B 0)
|
|
796 (?$(5#[(B 0)
|
|
797 (?$(5#\(B 0)
|
|
798 (?$(5#](B 0)
|
|
799 (?$(5#^(B 0)
|
|
800 (?$(5#_(B 0)
|
|
801 (?$(5#`(B 0)
|
|
802 (?$(5#a(B 0)
|
|
803 (?$(5#b(B 0)
|
|
804 (?$(5#c(B 0)
|
|
805 (?$(5#d(B 0)
|
|
806 (?$(5#e(B 0)
|
|
807 (?$(5#f(B 0)
|
|
808 (?$(5#g(B 0)
|
|
809 (?$(5#h(B 0)
|
|
810 (?$(5#i(B 0)
|
|
811 (?$(5#j(B 0)
|
|
812 (?$(5#k(B 0)
|
|
813 (?$(5#l(B 0)
|
|
814 (?$(5#m(B 0)
|
|
815 (?$(5#n(B 0)
|
|
816 (?$(5#o(B 0)
|
|
817 (?$(5#p(B 0)
|
|
818 (?$(5#q(B 0)
|
|
819 (?$(5#r(B 0)
|
|
820 (?$(5#s(B 0)
|
|
821 (?$(5#t(B 0)
|
|
822 (?$(5#u(B 0)
|
|
823 (?$(5#v(B 0)
|
|
824 (?$(5#w(B 0)
|
|
825 (?$(5#x(B 0)
|
|
826 (?$(5#y(B 0)
|
|
827 (?$(5#z(B 0)
|
|
828 (?$(5#{(B 0)
|
|
829 (?$(5#|(B 0)
|
|
830 (?$(5#}(B 0)
|
|
831 (?$(5#~(B 0)
|
|
832 (?$(5$!(B 0)
|
|
833 (?$(5$"(B 0)
|
|
834 (?$(5$#(B 0)
|
|
835 (?$(5$$(B 0)
|
|
836 (?$(5$%(B 0)
|
|
837 (?$(5$&(B 0)
|
|
838 (?$(5$'(B 0)
|
|
839 (?$(5$((B 0)
|
|
840 (?$(5$)(B 0)
|
|
841 (?$(5$*(B 0)
|
|
842 (?$(5$+(B 0)
|
|
843 (?$(5$,(B 0)
|
|
844 (?$(5$-(B 0)
|
|
845 (?$(5$.(B 0)
|
|
846 (?$(5$/(B 0)
|
|
847 (?$(5$0(B 0)
|
|
848 (?$(5$1(B 0)
|
|
849 (?$(5$2(B 0)
|
|
850 (?$(5$3(B 0)
|
|
851 (?$(5$4(B 0)
|
|
852 (?$(5$5(B 0)
|
|
853 (?$(5$6(B 0)
|
|
854 (?$(5$7(B 0)
|
|
855 (?$(5$8(B 0)
|
|
856 (?$(5$9(B 0)
|
|
857 (?$(5$:(B 0)
|
|
858 (?$(5$;(B 0)
|
|
859 (?$(5$<(B 0)
|
|
860 (?$(5$=(B 0)
|
|
861 (?$(5$>(B 0)
|
|
862 (?$(5$?(B 0)
|
|
863 (?$(5$@(B 0)
|
|
864 (?$(5$A(B 0)
|
|
865 (?$(5$B(B 0)
|
|
866 (?$(5$C(B 0)
|
|
867 (?$(5$D(B 0)
|
|
868 (?$(5$E(B 0)
|
|
869 (?$(5$F(B 0)
|
|
870 (?$(5$G(B 0)
|
|
871 (?$(5$H(B 0)
|
|
872 (?$(5$I(B 0)
|
|
873 (?$(5$J(B 0)
|
|
874 (?$(5$K(B 0)
|
|
875 (?$(5$L(B 0)
|
|
876 (?$(5$M(B 0)
|
|
877 (?$(5$N(B 0)
|
|
878 (?$(5$O(B 0)
|
|
879 (?$(5$P(B 0)
|
|
880 (?$(5$Q(B 0)
|
|
881 (?$(5$R(B 0)
|
|
882 (?$(5$S(B 0)
|
|
883 (?$(5$T(B 0)
|
|
884 (?$(5$U(B 0)
|
|
885 (?$(5$V(B 0)
|
|
886 (?$(5$W(B 0)
|
|
887 (?$(5$X(B 0)
|
|
888 (?$(5$Y(B 0)
|
|
889 (?$(5$Z(B 0)
|
|
890 (?$(5$[(B 0)
|
|
891 (?$(5$\(B 0)
|
|
892 (?$(5$](B 0)
|
|
893 (?$(5$^(B 0)
|
|
894 (?$(5$_(B 0)
|
|
895 (?$(5$`(B 0)
|
|
896 (?$(5$a(B 0)
|
|
897 (?$(5$b(B 0)
|
|
898 (?$(5$c(B 0)
|
|
899 (?$(5$d(B 0)
|
|
900 (?$(5$e(B 0)
|
|
901 (?$(5$f(B 0)
|
|
902 (?$(5$g(B 0)
|
|
903 (?$(5$h(B 0)
|
|
904 (?$(5$i(B 0)
|
|
905 (?$(5$j(B 0)
|
|
906 (?$(5$k(B 0)
|
|
907 (?$(5$l(B 0)
|
|
908 (?$(5$m(B 0)
|
|
909 (?$(5$n(B 0)
|
|
910 (?$(5$o(B 0)
|
|
911 (?$(5$p(B 0)
|
|
912 (?$(5$q(B 0)
|
|
913 (?$(5$r(B 0)
|
|
914 (?$(5$s(B 0)
|
|
915 (?$(5$t(B 0)
|
|
916 (?$(5$u(B 0)
|
|
917 (?$(5$v(B 0)
|
|
918 (?$(5$w(B 0)
|
|
919 (?$(5$x(B 0)
|
|
920 (?$(5$y(B 0)
|
|
921 (?$(5$z(B 0)
|
|
922 (?$(5${(B 0)
|
|
923 (?$(5$|(B 0)
|
|
924 (?$(5$}(B 0)
|
|
925 (?$(5$~(B 0)
|
|
926 ))
|
|
927
|
|
928 ;; Determine composition priority and rule of the array of Glyphs.
|
|
929 ;; Sort the glyphs with their priority.
|
|
930
|
|
931 ;; Example:
|
|
932 ;;(devanagari-reorder-glyph-for-composition '[?$(5"5(B ?$(5!X(B ?$(5![(B])
|
|
933 ;; => ((446680 0) (446773 0) (446683 50 (ml . mr)))
|
|
934
|
|
935 (defun devanagari-reorder-glyph-for-composition (glyph-alist)
|
|
936 (let* ((pos 0)
|
|
937 (ordered-glyphs '()))
|
|
938 (while (< pos (length glyph-alist))
|
|
939 (let* ((glyph (aref glyph-alist pos)))
|
|
940 (setq pos (1+ pos))
|
|
941 (setq ordered-glyphs
|
|
942 (append ordered-glyphs (list (assq glyph devanagari-composition-rules))))))
|
|
943 (sort ordered-glyphs '(lambda (x y) (< (car (cdr x)) (car (cdr y)))))))
|
|
944
|
|
945 ;;(devanagari-compose-to-one-glyph "$(5"5!X![(B") => "2$(6!XP"5@![1(B"
|
|
946
|
|
947 (defun devanagari-compose-to-one-glyph (devanagari-string)
|
|
948 (let* ((o-glyph-list (devanagari-reorder-glyph-for-composition
|
|
949 (string-to-vector devanagari-string)))
|
|
950 ;; List of glyphs to be composed.
|
|
951 (cmp-glyph-list (list (car (car o-glyph-list))))
|
|
952 (o-glyph-list (cdr o-glyph-list)))
|
|
953 (while o-glyph-list
|
|
954 (let* ((o-glyph (car o-glyph-list))
|
|
955 (glyph (if (< 2 (length o-glyph))
|
|
956 ;; default composition
|
|
957 (list (car (cdr (cdr o-glyph))) (car o-glyph))
|
|
958 ;; composition with a specified rule
|
|
959 (list '(mr . ml) (car o-glyph)))))
|
|
960 (setq o-glyph-list (cdr o-glyph-list))
|
|
961 (setq cmp-glyph-list (append cmp-glyph-list glyph))))
|
|
962 ;; Before applying compose-chars, convert glyphs to
|
|
963 ;; 1-column width if possible.
|
|
964 (setq cmp-glyph-list (devanagari-wide-to-narrow cmp-glyph-list))
|
|
965 (if (= (length cmp-glyph-list) 1) (char-to-string (car cmp-glyph-list))
|
|
966 (apply 'compose-chars cmp-glyph-list))))
|
|
967
|
|
968
|
|
969 ;;
|
|
970 ;; Phase 2.5 Convert Appropriate Character to 1-column shape.
|
|
971 ;;
|
|
972 ;; This is temporary and should be removed out when Emacs supports
|
|
973 ;; variable width characters.
|
|
974 ;;
|
|
975 ;; This will convert the composing glyphs (2 column glyphs)
|
|
976 ;; to narrow (1 column) glyphs if they exist.
|
|
977 ;;
|
|
978 ;; devanagari-wide-to-narrow-old converts glyphs simply.
|
|
979 ;; devanagari-wide-to-narrow takes care of upper/lower apply-glyphs
|
|
980 ;; with 2 column base-glyph.
|
|
981 ;;
|
|
982 ;; Execution Examples
|
|
983 ;;(devanagari-wide-to-narrow '(446680 446773 (ml . mr) 446683))
|
|
984 ;;(devanagari-wide-to-narrow '(?$(5!6(B (ml . ml) 446773 (tc . mr) 446683))
|
|
985
|
|
986 (defun devanagari-wide-to-narrow (src-list)
|
|
987 (if (null src-list) '()
|
|
988 (cons
|
|
989 (if (and (numberp (car src-list))
|
|
990 (cdr (assq (car src-list) devanagari-1-column-char)))
|
|
991 (cdr (assq (car src-list) devanagari-1-column-char))
|
|
992 (car src-list))
|
|
993 (devanagari-wide-to-narrow (cdr src-list)))))
|
|
994
|
|
995 ;; Make this function obsolete temporary Because now Emacs supports
|
|
996 ;; attaching 1 column character at the center 2 column char. However,
|
|
997 ;; there are still problems attempting to attach Halant or Nukta sign
|
|
998 ;; at the non-vowel consonant. This problem can not be solved until
|
|
999 ;; Emacs supports attaching the glyph at `temporary-preserved metric'.
|
|
1000
|
|
1001 (defun devanagari-wide-to-narrow-old (src-list)
|
|
1002 (if (null src-list) (progn (error "devanagari-wide-to-narrow error") nil)
|
|
1003 (let* ((base-glyph (cdr (assq (car src-list) devanagari-1-column-char)))
|
|
1004 (wide-base-glyph nil)
|
|
1005 (apply-glyph-list (cdr src-list)))
|
|
1006 (if (null base-glyph)
|
|
1007 (progn
|
|
1008 (setq wide-base-glyph t)
|
|
1009 (setq base-glyph (car src-list))))
|
|
1010 (cons base-glyph
|
|
1011 (devanagari-wide-to-narrow-iter apply-glyph-list wide-base-glyph))
|
|
1012 )))
|
|
1013
|
|
1014 ;; Convert apply-glyph-list from 2-column to 1-column.
|
|
1015 ;; wide-base-glyph is t when base-glyph is 2-column.
|
|
1016 ;; When apply-glyph is put at the top or bottom of 2-column base-glyph,
|
|
1017 ;; they must be 2-column glyph, too. Otherwise, they will be
|
|
1018 ;; converted to 1-column glyph if possible.
|
|
1019
|
|
1020 (defun devanagari-wide-to-narrow-iter (apply-glyph-list wide-base-glyph)
|
|
1021 (if (< (length apply-glyph-list) 2) '()
|
|
1022 (let* ((apply-dir (car apply-glyph-list))
|
|
1023 (apply-glyph (car (cdr apply-glyph-list)))
|
|
1024 (apply-rest (cdr (cdr apply-glyph-list)))
|
|
1025 (put-t-or-b (member (car apply-dir) '(tl tc tr bl bc br)))
|
|
1026 (narrow-glyph (cdr (assq apply-glyph devanagari-1-column-char))))
|
|
1027 (append
|
|
1028 (list apply-dir
|
|
1029 (if (or (and wide-base-glyph put-t-or-b)
|
|
1030 (null narrow-glyph))
|
|
1031 apply-glyph narrow-glyph))
|
|
1032 (devanagari-wide-to-narrow-iter apply-rest wide-base-glyph)))))
|
|
1033
|
|
1034 ;;
|
|
1035 ;; Summary
|
|
1036 ;;
|
|
1037
|
|
1038 ;;;###autoload
|
|
1039 (defun devanagari-compose-string (str)
|
|
1040 (let ((len (length str))
|
|
1041 (src str) (dst "") rest match-b match-e)
|
|
1042 (while (string-match devanagari-composite-glyph-unit-examine src)
|
|
1043 (setq match-b (match-beginning 0) match-e (match-end 0))
|
|
1044 (setq dst
|
|
1045 (concat dst
|
|
1046 (substring src 0 match-b)
|
|
1047 (devanagari-compose-to-one-glyph
|
|
1048 (char-to-glyph-devanagari
|
|
1049 (substring src match-b match-e)))))
|
|
1050 (setq src (substring src match-e)))
|
|
1051 (setq dst (concat dst src))
|
|
1052 dst))
|
|
1053
|
|
1054 ;;;###autoload
|
|
1055 (defun devanagari-compose-region (from to)
|
|
1056 (interactive "r")
|
|
1057 (save-restriction
|
|
1058 (narrow-to-region from to)
|
|
1059 (goto-char (point-min))
|
|
1060 (while (re-search-forward devanagari-composite-glyph-unit-examine nil t)
|
|
1061 (let* ((match-b (match-beginning 0)) (match-e (match-end 0))
|
|
1062 (cmps (devanagari-compose-to-one-glyph
|
|
1063 (char-to-glyph-devanagari
|
|
1064 (buffer-substring match-b match-e)))))
|
|
1065 (delete-region match-b match-e)
|
|
1066 (insert cmps)))))
|
|
1067
|
|
1068 ;;
|
|
1069 ;; Decomposition of composite font.
|
|
1070 ;;
|
|
1071
|
|
1072 (defun devanagari-normalize-narrow-glyph (charlist)
|
|
1073 (let ((wide-char (car (rassoc (car charlist) devanagari-1-column-char))))
|
|
1074 (if (null charlist) nil
|
|
1075 (cons (if (null wide-char) (car charlist) wide-char)
|
|
1076 (devanagari-normalize-narrow-glyph (cdr charlist))))))
|
|
1077
|
|
1078 (defvar devanagari-decomposition-rules
|
|
1079 '(
|
|
1080 (?$(5"p(B -20)
|
|
1081 )
|
|
1082 )
|
|
1083
|
|
1084 (defun devanagari-reorder-glyph-for-decomposition (glyphlist)
|
|
1085 "This function re-orders glyph list."
|
|
1086 (sort glyphlist
|
|
1087 '(lambda (x y)
|
|
1088 (let ((xx (assoc x devanagari-decomposition-rules))
|
|
1089 (yy (assoc y devanagari-decomposition-rules)))
|
|
1090 (if (null xx) (setq xx 0))
|
|
1091 (if (null yy) (setq yy 0))
|
|
1092 (< xx yy)))))
|
|
1093
|
|
1094 (defun devanagari-decompose-char (char)
|
|
1095 "This function decomposes one Devanagari composite character to
|
|
1096 basic Devanagari character."
|
|
1097 (let ((glyphlist (decompose-composite-char char)))
|
|
1098 (if (not (listp glyphlist))
|
|
1099 (setq glyphlist (list glyphlist)))
|
|
1100 (setq glyphlist (devanagari-normalize-narrow-glyph glyphlist))
|
|
1101 (mapconcat '(lambda (x) (let ((char (get-char-code-property
|
|
1102 x 'glyph-to-char)))
|
|
1103 (if (null char) (char-to-string x) char)))
|
|
1104 (devanagari-reorder-glyph-for-decomposition glyphlist)
|
|
1105 "")))
|
|
1106
|
|
1107 ;;;###autoload
|
|
1108 (defun devanagari-decompose-string (str)
|
|
1109 "This function Decomposes Devanagari glyph string to
|
|
1110 basic Devanagari character string."
|
|
1111 (let ((src str) (dst ""))
|
|
1112 (while (not (equal src ""))
|
|
1113 (let* ((char (string-to-char src))
|
|
1114 (clen (char-bytes char)))
|
|
1115 (setq src (substring src clen))
|
|
1116 (setq dst (concat dst
|
|
1117 (devanagari-decompose-char char)))))
|
|
1118 dst))
|
|
1119
|
|
1120 ;;;###autoload
|
|
1121 (defun devanagari-decompose-region (from to)
|
|
1122 (interactive "r")
|
|
1123 (save-restriction
|
|
1124 (narrow-to-region from to)
|
|
1125 (goto-char (point-min))
|
|
1126 (while (re-search-forward "." nil t)
|
|
1127 (let* ((match-b (match-beginning 0)) (match-e (match-end 0))
|
|
1128 (decmps (devanagari-decompose-string (buffer-substring match-b match-e))))
|
|
1129 (delete-char -1)
|
|
1130 (insert decmps)))))
|
|
1131
|
|
1132
|
|
1133
|
|
1134 ;; For pre-write and post-read conversion
|
|
1135
|
|
1136 ;;;###autoload
|
|
1137 (defun devanagari-compose-from-is13194-region (from to)
|
|
1138 "Compose IS 13194 characters in the region to Devanagari characters."
|
|
1139 (interactive "r")
|
|
1140 (save-restriction
|
|
1141 (narrow-to-region from to)
|
|
1142 (indian-to-devanagari-region (point-min) (point-max))
|
|
1143 (devanagari-compose-region (point-min) (point-max))))
|
|
1144
|
|
1145 ;;;###autoload
|
|
1146 (defun devanagari-decompose-to-is13194-region (from to)
|
|
1147 "Decompose Devanagari characters in the region to IS 13194 characters."
|
|
1148 (interactive "r")
|
|
1149 (save-restriction
|
|
1150 (narrow-to-region from to)
|
|
1151 (devanagari-decompose-region (point-min) (point-max))
|
|
1152 (devanagari-to-indian-region (point-min) (point-max))))
|
|
1153
|
|
1154 ;;
|
|
1155 (provide 'language/devan-util)
|
|
1156
|
|
1157 ;;; Local Variables:
|
|
1158 ;;; generated-autoload-file: "../loaddefs.el"
|
|
1159 ;;; End:
|
|
1160 ;;; devan-util.el ends here
|