Mercurial > emacs
comparison lisp/language/devan-util.el @ 17052:d0d7b244b1d0
Initial revision
author | Karl Heuer <kwzh@gnu.org> |
---|---|
date | Thu, 20 Feb 1997 07:02:49 +0000 |
parents | |
children | 70194012fb3a |
comparison
equal
deleted
inserted
replaced
17051:fd0b17a79b07 | 17052:d0d7b244b1d0 |
---|---|
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 |