Commit | Line | Data |
---|---|---|
897755c4 | 1 | ;;; devan-util.el --- Support for composing Devanagari characters -*-coding: iso-2022-7bit;-*- |
4ed46869 | 2 | |
1bec6fdb | 3 | ;; Copyright (C) 2001 Free Software Foundation, Inc. |
4ed46869 | 4 | |
2fc227cb | 5 | ;; Maintainer: KAWABATA, Taichi <kawabata@m17n.org> |
1bec6fdb | 6 | ;; Keywords: multilingual, Devanagari |
4ed46869 KH |
7 | |
8 | ;; This file is part of GNU Emacs. | |
9 | ||
10 | ;; GNU Emacs is free software; you can redistribute it and/or modify | |
11 | ;; it under the terms of the GNU General Public License as published by | |
12 | ;; the Free Software Foundation; either version 2, or (at your option) | |
13 | ;; any later version. | |
14 | ||
15 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | ;; GNU General Public License for more details. | |
19 | ||
20 | ;; You should have received a copy of the GNU General Public License | |
e803d6bd KH |
21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the |
22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 | ;; Boston, MA 02111-1307, USA. | |
4ed46869 | 24 | |
1bec6fdb | 25 | ;; Created: Feb. 17. 2001 |
37cdc7ad | 26 | |
1bec6fdb | 27 | ;;; Commentary: |
4ed46869 | 28 | |
1bec6fdb RS |
29 | ;; This file provides character(Unicode) to glyph(CDAC) conversion and |
30 | ;; composition of Devanagari script characters. | |
4ed46869 KH |
31 | |
32 | ;;; Code: | |
33 | ||
1bec6fdb RS |
34 | ;; Devanagari Composable Pattern |
35 | ;; C .. Consonants | |
36 | ;; V .. Vowel | |
37 | ;; H .. Halant | |
38 | ;; M .. Matra | |
39 | ;; V .. Vowel | |
40 | ;; A .. Anuswar | |
41 | ;; D .. Chandrabindu | |
42 | ;; (N .. Zerowidth Non Joiner) | |
43 | ;; (J .. Zerowidth Joiner. ) | |
44 | ;; 1. vowel | |
45 | ;; V(A/D)? | |
46 | ;; 2. syllable : maximum of 5 consecutive consonants. (e.g. kartsnya) | |
9e35da28 | 47 | ;; ((CH)?(CH)?(CH)?CH)?C(H|M?(A|D)?)? |
1bec6fdb RS |
48 | |
49 | (defconst devanagari-consonant | |
50 | "[\e$,15U\e(B-\e$,15y68\e(B-\e$,16?\e(B]") | |
51 | ||
8f924df7 KH |
52 | ;;("\e$,16B\e(B" . nil) |
53 | ;;("\e$,16A\e(B" . nil) | |
54 | ;;("\e$,16C\e(B" . nil) | |
55 | ||
56 | ||
1bec6fdb | 57 | (defconst devanagari-composable-pattern |
a1506d29 | 58 | (concat |
8dcc539d | 59 | "\\([\e$,15E\e(B-\e$,15T6@6A\e(B][\e$,15A5B\e(B]?\\)\\|[\e$,15C6D\e(B]" |
1bec6fdb RS |
60 | "\\|\\(" |
61 | "\\(?:\\(?:[\e$,15U\e(B-\e$,15y68\e(B-\e$,16?\e(B]\e$,16-\e(B\\)?\\(?:[\e$,15U\e(B-\e$,15y68\e(B-\e$,16?\e(B]\e$,16-\e(B\\)?\\(?:[\e$,15U\e(B-\e$,15y68\e(B-\e$,16?\e(B]\e$,16-\e(B\\)?[\e$,15U\e(B-\e$,15y68\e(B-\e$,16?\e(B]\e$,16-\e(B\\)?" | |
62 | "[\e$,15U\e(B-\e$,15y68\e(B-\e$,16?\e(B]\\(?:\e$,16-\e(B\\|[\e$,15~\e(B-\e$,16-6B6C\e(B]?[\e$,15B5A\e(B]?\\)?" | |
63 | "\\)") | |
64 | "Regexp matching a composable sequence of Devanagari characters.") | |
65 | ||
2e82b5d5 KH |
66 | (dolist (range '((#x0903 . #x0903) |
67 | (#x0905 . #x0939) | |
68 | (#x0958 . #x0961))) | |
69 | (set-char-table-range indian-composable-pattern range | |
70 | devanagari-composable-pattern)) | |
71 | ||
8abb8f29 | 72 | ;;;###autoload |
1bec6fdb | 73 | (defun devanagari-compose-region (from to) |
4ed46869 | 74 | (interactive "r") |
31ce7719 | 75 | (save-excursion |
1bec6fdb RS |
76 | (save-restriction |
77 | (narrow-to-region from to) | |
78 | (goto-char (point-min)) | |
79 | (while (re-search-forward devanagari-composable-pattern nil t) | |
0b520940 DL |
80 | (devanagari-compose-syllable-region (match-beginning 0) |
81 | (match-end 0)))))) | |
1bec6fdb RS |
82 | (defun devanagari-compose-string (string) |
83 | (with-temp-buffer | |
84 | (insert (decompose-string string)) | |
85 | (devanagari-compose-region (point-min) (point-max)) | |
86 | (buffer-string))) | |
87 | ||
6b61353c | 88 | ;;;###autoload |
91c78c93 DL |
89 | (defun devanagari-post-read-conversion (len) |
90 | (save-excursion | |
91 | (save-restriction | |
92 | (let ((buffer-modified-p (buffer-modified-p))) | |
93 | (narrow-to-region (point) (+ (point) len)) | |
94 | (devanagari-compose-region (point-min) (point-max)) | |
95 | (set-buffer-modified-p buffer-modified-p) | |
96 | (- (point-max) (point-min)))))) | |
97 | ||
4f102de2 RS |
98 | (defun devanagari-regexp-of-hashtbl-keys (hashtbl) |
99 | "Return a regular expression that matches all keys in hashtable HASHTBL." | |
1bec6fdb RS |
100 | (let ((max-specpdl-size 1000)) |
101 | (regexp-opt | |
a1506d29 | 102 | (sort |
1bec6fdb RS |
103 | (let (dummy) |
104 | (maphash (function (lambda (key val) (setq dummy (cons key dummy)))) hashtbl) | |
105 | dummy) | |
106 | (function (lambda (x y) (> (length x) (length y)))))))) | |
107 | ||
2e82b5d5 KH |
108 | ;;;###autoload |
109 | (defun devanagari-composition-function (pos &optional string) | |
110 | "Compose Devanagari characters after the position POS. | |
111 | If STRING is not nil, it is a string, and POS is an index to the string. | |
112 | In this case, compose characters after POS of the string." | |
113 | (if string | |
114 | ;; Not yet implemented. | |
115 | nil | |
116 | (goto-char pos) | |
117 | (if (looking-at devanagari-composable-pattern) | |
118 | (prog1 (match-end 0) | |
119 | (devanagari-compose-syllable-region pos (match-end 0)))))) | |
1bec6fdb RS |
120 | |
121 | ;; Notes on conversion steps. | |
122 | ||
a1506d29 | 123 | ;; 1. chars to glyphs |
1bec6fdb RS |
124 | ;; |
125 | ;; Rules will not be applied to the halant appeared at the end of the | |
126 | ;; text. Also, the preceding/following "r" will be treated as special case. | |
127 | ||
128 | ;; 2. glyphs reordering. | |
129 | ;; | |
130 | ;; The glyphs are split by halant, and each glyph groups are | |
131 | ;; re-ordered in the following order. | |
132 | ;; | |
133 | ;; Note that `consonant-glyph' mentioned here does not contain the | |
134 | ;; vertical bar (right modifier) attached at the right of the | |
135 | ;; consonant. | |
a1506d29 JB |
136 | ;; |
137 | ;; If the glyph-group contains right modifier, | |
1bec6fdb RS |
138 | ;; (1) consonant-glyphs/vowels, with nukta sign |
139 | ;; (2) spacing | |
140 | ;; (3) right modifier (may be matra) | |
141 | ;; (4) top matra | |
142 | ;; (5) preceding "r" | |
143 | ;; (6) anuswar | |
144 | ;; (7) following "r" | |
145 | ;; (8) bottom matra or halant. | |
a1506d29 JB |
146 | ;; |
147 | ;; Otherwise, | |
1bec6fdb RS |
148 | ;; (1) consonant-glyph/vowels, with nukta sign |
149 | ;; (3) left matra | |
a1506d29 | 150 | ;; (4) top matra |
1bec6fdb RS |
151 | ;; (5) preceding "r" |
152 | ;; (6) anuswar | |
153 | ;; (7) following "r" | |
154 | ;; (8) bottom matra or halant. | |
155 | ;; (2) spacing | |
156 | ||
157 | ;; 3. glyph to glyph | |
158 | ;; | |
159 | ;; For better display, some glyph display would be tuned. | |
160 | ||
161 | ;; 4. Composition. | |
162 | ;; | |
163 | ;; left modifiers will be attached at the left. | |
164 | ;; others will be attached right. | |
165 | ||
166 | ;; Problem:: | |
167 | ;; Can we generalize this methods to other Indian scripts? | |
168 | ||
77539682 KH |
169 | (defvar dev-char-glyph |
170 | '(("\e$,15E\e(B" . "\e$,4 K\e(B") | |
1d475b5e KH |
171 | ("\e$,15F\e(B" . "\e$,4 K")\e(B") |
172 | ("\e$,15~\e(B" . "\e$,4")\e(B") | |
77539682 | 173 | ("\e$,15G\e(B" . "\e$,4 \\e(B") |
1d475b5e KH |
174 | ("\e$,15\7f\e(B" . "\e$,4"*\e(B") |
175 | ("\e$,15\7f5A\e(B" . "\e$,4"*\e(B\\e$,4"&\e(B") | |
77539682 | 176 | ("\e$,15H\e(B" . "\e$,4 \"'\e(B") |
1d475b5e KH |
177 | ("\e$,15H5A\e(B" . "\e$,4 \"'"&\e(B") |
178 | ("\e$,16 \e(B" . "\e$,4"2\e(B") | |
179 | ("\e$,16 5A\e(B" . "\e$,4"2"&\e(B") | |
77539682 | 180 | ("\e$,15I\e(B" . "\e$,4 ]\e(B") |
1d475b5e KH |
181 | ("\e$,16!\e(B" . "\e$,4"6\e(B") |
182 | ("\e$,15J\e(B" . "\e$,4 ^"P\e(B") | |
183 | ("\e$,16"\e(B" . "\e$,4":\e(B") | |
184 | ("\e$,15K\e(B" . "\e$,4 `"Q\e(B") | |
185 | ("\e$,16#\e(B" . "\e$,4">\e(B") | |
77539682 | 186 | ;;("\e$,15L\e(B" . nil) ; not implemented. |
1d475b5e KH |
187 | ("\e$,16$\e(B" . "\e$,4"?\e(B") |
188 | ("\e$,15M\e(B" . "\e$,4 b"L\e(B") | |
189 | ("\e$,15M5A\e(B" . "\e$,4 b"$\e(B") | |
190 | ("\e$,15M5B\e(B" . "\e$,4 b"$\e(B") | |
191 | ("\e$,16%\e(B" . "\\e$,4"L\e(B") | |
a1506d29 JB |
192 | ("\e$,15N\e(B" . "\e$,4 b"@\e(B") |
193 | ("\e$,15N5A\e(B" . "\e$,4 b"@"&\e(B") | |
1d475b5e KH |
194 | ("\e$,16&\e(B" . "\\e$,4"@\e(B") |
195 | ("\e$,16&5A\e(B" . "\\e$,4"@\e(B\\e$,4"&\e(B") | |
a1506d29 | 196 | ("\e$,15O\e(B" . "\e$,4 b\e(B") |
1d475b5e KH |
197 | ("\e$,16'\e(B" . "\\e$,4"D\e(B") |
198 | ("\e$,16'5A\e(B" . "\\e$,4"D\e(B\\e$,4"&\e(B") | |
a1506d29 JB |
199 | ("\e$,15P\e(B" . "\e$,4 b"D\e(B") |
200 | ("\e$,15P5A\e(B" . "\e$,4 b"D"&\e(B") | |
1d475b5e KH |
201 | ("\e$,16(\e(B" . "\\e$,4"H\e(B") |
202 | ("\e$,16(5A\e(B" . "\\e$,4"H\e(B\\e$,4"&\e(B") | |
203 | ("\e$,15Q\e(B" . "\e$,4 K")"L\e(B") ;; special rule for reodering. | |
204 | ("\e$,15Q5A\e(B" . "\e$,4 K")"$\e(B") | |
205 | ("\e$,15Q5B\e(B" . "\e$,4 K")"$\e(B") | |
206 | ("\e$,16)\e(B" . "\\e$,4")"L\e(B") | |
207 | ("\e$,16)5A\e(B" . "\\e$,4")"$\e(B") | |
208 | ("\e$,16)5B\e(B" . "\\e$,4")"$\e(B") | |
a1506d29 JB |
209 | ("\e$,15R\e(B" . "\e$,4 K")"@\e(B") |
210 | ("\e$,15R5A\e(B" . "\e$,4 K")"@"&\e(B") | |
1d475b5e KH |
211 | ("\e$,16*\e(B" . "\\e$,4")"@\e(B") |
212 | ("\e$,16*5A\e(B" . "\\e$,4")"@"&\e(B") | |
213 | ("\e$,15S\e(B" . "\e$,4 K")"D\e(B") | |
214 | ("\e$,15S5A\e(B" . "\e$,4 K")"D"&\e(B") | |
215 | ("\e$,16+\e(B" . "\\e$,4")"D\e(B") | |
216 | ("\e$,16+5A\e(B" . "\\e$,4")"D"&\e(B") | |
a1506d29 JB |
217 | ("\e$,15T\e(B" . "\e$,4 K")"H\e(B") |
218 | ("\e$,15T5A\e(B" . "\e$,4 K")"H"&\e(B") | |
1d475b5e KH |
219 | ("\e$,16,\e(B" . "\\e$,4")"H\e(B") |
220 | ("\e$,16,5A\e(B" . "\\e$,4")"H"&\e(B") | |
a1506d29 | 221 | ("\e$,16@\e(B" . "\e$,4 a"Q\e(B") |
77539682 | 222 | ;;("\e$,16B\e(B" . nil) |
a1506d29 | 223 | ;;("\e$,16A\e(B" . nil) |
77539682 KH |
224 | ;;("\e$,16C\e(B" . nil) |
225 | ||
226 | ;; GRUTTALS | |
1d475b5e | 227 | ("\e$,15U\e(B" . "\e$,4 e"R\e(B") |
77539682 | 228 | ("\e$,15U6-\e(B" . "\e$,4 c\e(B") |
1d475b5e KH |
229 | ("\e$,15U6-5p\e(B" . "\e$,4 g"R\e(B") |
230 | ("\e$,15U6-5d\e(B" . "\e$,4 h"R\e(B") | |
231 | ("\e$,15U6-5w\e(B" . "\e$,4 i")\e(B") | |
77539682 KH |
232 | ("\e$,15U6-5w6-\e(B" . "\e$,4 i\e(B") |
233 | ||
1d475b5e | 234 | ("\e$,15V\e(B" . "\e$,4 j")\e(B") |
77539682 | 235 | ("\e$,15V6-\e(B" . "\e$,4 j\e(B") |
1d475b5e | 236 | ("\e$,15V6-5p\e(B" . "\e$,4 l")\e(B") |
77539682 KH |
237 | ("\e$,15V6-5p6-\e(B" . "\e$,4 l\e(B") |
238 | ||
a1506d29 JB |
239 | ("\e$,15W\e(B" . "\e$,4 m")\e(B") |
240 | ("\e$,15W6-\e(B" . "\e$,4 m\e(B") | |
1d475b5e | 241 | ("\e$,15W6-5p\e(B" . "\e$,4 o")\e(B") |
77539682 KH |
242 | ("\e$,15W6-5p6-\e(B" . "\e$,4 o\e(B") |
243 | ||
a1506d29 JB |
244 | ("\e$,15X\e(B" . "\e$,4 p")\e(B") |
245 | ("\e$,15X6-\e(B" . "\e$,4 p\e(B") | |
246 | ("\e$,15X6-5p\e(B" . "\e$,4 q")\e(B") | |
247 | ("\e$,15X6-5p6-\e(B" . "\e$,4 q\e(B") | |
77539682 | 248 | |
1d475b5e | 249 | ("\e$,15Y\e(B" . "\e$,4 r"S\e(B") |
a1506d29 JB |
250 | ;; PALATALS |
251 | ("\e$,15Z\e(B" . "\e$,4 s")\e(B") | |
252 | ("\e$,15Z6-\e(B" . "\e$,4 s\e(B") | |
253 | ("\e$,15Z6-5p\e(B" . "\e$,4 t")\e(B") | |
77539682 KH |
254 | ("\e$,15Z6-5p6-\e(B" . "\e$,4 t\e(B") |
255 | ||
a1506d29 | 256 | ("\e$,15[\e(B" . "\e$,4 u"T\e(B") |
77539682 | 257 | |
a1506d29 JB |
258 | ("\e$,15\\e(B" . "\e$,4 v")\e(B") |
259 | ("\e$,15\6-\e(B" . "\e$,4 v\e(B") | |
260 | ("\e$,15\6-5p\e(B" . "\e$,4 x")\e(B") | |
261 | ("\e$,15\6-5p6-\e(B" . "\e$,4 x\e(B") | |
262 | ("\e$,15\6-5^\e(B" . "\e$,4 y")\e(B") | |
263 | ("\e$,15\6-5^6-\e(B" . "\e$,4 y\e(B") | |
77539682 | 264 | |
a1506d29 JB |
265 | ("\e$,15]\e(B" . "\e$,4 z")\e(B") |
266 | ("\e$,15]6-\e(B" . "\e$,4 z\e(B") | |
267 | ("\e$,15]6-5p\e(B" . "\e$,4 {")\e(B") | |
268 | ("\e$,15]6-5p6-\e(B" . "\e$,4 {\e(B") | |
77539682 | 269 | |
1d475b5e | 270 | ("\e$,15^\e(B" . "\e$,4 |")\e(B") |
77539682 | 271 | ("\e$,15^6-\e(B" . "\e$,4 |\e(B") |
a1506d29 | 272 | ;; CEREBRALS |
1d475b5e KH |
273 | ("\e$,15_\e(B" . "\e$,4 }"U\e(B") |
274 | ("\e$,15_6-5_\e(B" . "\e$,4 ~"U\e(B") | |
275 | ("\e$,15_6-5`\e(B" . "\e$,4 \7f"U\e(B") | |
77539682 | 276 | |
a1506d29 JB |
277 | ("\e$,15`\e(B" . "\e$,4! "V\e(B") |
278 | ("\e$,15`6-5`\e(B" . "\e$,4!!"V\e(B") | |
77539682 | 279 | |
a1506d29 JB |
280 | ("\e$,15a\e(B" . "\e$,4!""W\e(B") |
281 | ("\e$,15a6-5a\e(B" . "\e$,4!$"W\e(B") | |
282 | ("\e$,15a6-5b\e(B" . "\e$,4!%"W\e(B") | |
77539682 | 283 | |
a1506d29 | 284 | ("\e$,15b\e(B" . "\e$,4!&"X\e(B") |
77539682 | 285 | |
1d475b5e | 286 | ("\e$,15c\e(B" . "\e$,4!(")\e(B") |
77539682 | 287 | ("\e$,15c6-\e(B" . "\e$,4!(\e(B") |
a1506d29 JB |
288 | ;; DENTALS |
289 | ("\e$,15d\e(B" . "\e$,4!)")\e(B") | |
290 | ("\e$,15d6-\e(B" . "\e$,4!)\e(B") | |
291 | ("\e$,15d6-5p\e(B" . "\e$,4!*")\e(B") | |
292 | ("\e$,15d6-5p6-\e(B" . "\e$,4!*\e(B") | |
293 | ("\e$,15d6-5d\e(B" . "\e$,4!+")\e(B") | |
294 | ("\e$,15d6-5d6-\e(B" . "\e$,4!+\e(B") | |
295 | ||
296 | ("\e$,15e\e(B" . "\e$,4!,")\e(B") | |
297 | ("\e$,15e6-\e(B" . "\e$,4!,\e(B") | |
298 | ("\e$,15e6-5p\e(B" . "\e$,4!-")\e(B") | |
299 | ("\e$,15e6-5p6-\e(B" . "\e$,4!-\e(B") | |
300 | ||
301 | ("\e$,15f\e(B" . "\e$,4!."Y\e(B") | |
1d475b5e KH |
302 | ("\e$,15f6#\e(B" . "\e$,4!/"Y\e(B") |
303 | ("\e$,15f6-5p\e(B" . "\e$,4!0"Y\e(B") | |
304 | ("\e$,15f6-5f\e(B" . "\e$,4!1"Y\e(B") | |
305 | ("\e$,15f6-5g\e(B" . "\e$,4!2"Y\e(B") | |
77539682 KH |
306 | ("\e$,15f6-5n\e(B" . "\e$,4!3\e(B") |
307 | ("\e$,15f6-5o\e(B" . "\e$,4!4\e(B") | |
1d475b5e | 308 | ("\e$,15f6-5u\e(B" . "\e$,4!5"Y\e(B") |
77539682 | 309 | |
a1506d29 JB |
310 | ("\e$,15g\e(B" . "\e$,4!6")\e(B") |
311 | ("\e$,15g6-\e(B" . "\e$,4!6\e(B") | |
312 | ("\e$,15g6-5p\e(B" . "\e$,4!7")\e(B") | |
313 | ("\e$,15g6-5p6-\e(B" . "\e$,4!7\e(B") | |
77539682 | 314 | |
a1506d29 JB |
315 | ("\e$,15h\e(B" . "\e$,4!8")\e(B") |
316 | ("\e$,15h6-\e(B" . "\e$,4!8\e(B") | |
317 | ("\e$,15h6-5p\e(B" . "\e$,4!9")\e(B") | |
318 | ("\e$,15h6-5p6-\e(B" . "\e$,4!9")\e(B") | |
319 | ("\e$,15h6-5h\e(B" . "\e$,4!:")\e(B") | |
320 | ("\e$,15h6-5h6-\e(B" . "\e$,4!:\e(B") | |
77539682 | 321 | |
1d475b5e | 322 | ("\e$,15i\e(B" . "\e$,4!8"#")\e(B") |
a1506d29 JB |
323 | ;; LABIALS |
324 | ("\e$,15j\e(B" . "\e$,4!;")\e(B") | |
325 | ("\e$,15j6-\e(B" . "\e$,4!;\e(B") | |
326 | ("\e$,15j6-5p\e(B" . "\e$,4!<")\e(B") | |
327 | ("\e$,15j6-5p6-\e(B" . "\e$,4!<\e(B") | |
328 | ||
329 | ("\e$,15k\e(B" . "\e$,4!a"[\e(B") | |
330 | ("\e$,15k6-\e(B" . "\e$,4!=\e(B") | |
331 | ("\e$,15k6-5p\e(B" . "\e$,4!c"[\e(B") | |
332 | ||
333 | ("\e$,15l\e(B" . "\e$,4!d")\e(B") | |
334 | ("\e$,15l6-\e(B" . "\e$,4!d\e(B") | |
335 | ("\e$,15l6-5p\e(B" . "\e$,4!e")\e(B") | |
336 | ("\e$,15l6-5p6-\e(B" . "\e$,4!e\e(B") | |
337 | ||
338 | ("\e$,15m\e(B" . "\e$,4!f")\e(B") | |
339 | ("\e$,15m6-\e(B" . "\e$,4!f\e(B") | |
340 | ("\e$,15m6-5p\e(B" . "\e$,4!g")\e(B") | |
341 | ("\e$,15m6-5p6-\e(B" . "\e$,4!g\e(B") | |
77539682 | 342 | |
1d475b5e | 343 | ("\e$,15n\e(B" . "\e$,4!h")\e(B") |
77539682 | 344 | ("\e$,15n6-\e(B" . "\e$,4!h\e(B") |
1d475b5e | 345 | ("\e$,15n6-5p\e(B" . "\e$,4!i")\e(B") |
77539682 KH |
346 | ("\e$,15n6-5p6-\e(B" . "\e$,4!i\e(B") |
347 | ;; SEMIVOWELS | |
a1506d29 JB |
348 | ("\e$,15o\e(B" . "\e$,4!j")\e(B") |
349 | ("\e$,15o6-\e(B" . "\e$,4!j\e(B") | |
350 | ("\e$,15o6-5p\e(B" . "\e$,4!k")\e(B") | |
351 | ("\e$,15o6-5p6-\e(B" . "\e$,4!k\e(B") | |
77539682 KH |
352 | ("\e$,16-5o\e(B" . "\e$,4!l\e(B") ;; when every ohter lig. fails. |
353 | ||
a1506d29 | 354 | ("\e$,15p\e(B" . "\e$,4!n"W\e(B") |
77539682 | 355 | ;; ("\e$,15p6-\e(B" . "\\e$,4"'\e(B") ;; special case. only the topmost pos. |
a1506d29 | 356 | ("\e$,15q\e(B" . "\e$,4!n"#"W\e(B") |
77539682 | 357 | ("\e$,15q6-\e(B" . "\e$,4!m\e(B") ;; IS 13194 speical rule. |
a1506d29 JB |
358 | ("\e$,15p6!\e(B" . "\e$,4!o"[\e(B") |
359 | ("\e$,15p6"\e(B" . "\e$,4!p"\\e(B") | |
77539682 | 360 | |
a1506d29 JB |
361 | ("\e$,15r\e(B" . "\e$,4!q")\e(B") |
362 | ("\e$,15r6-\e(B" . "\e$,4!q\e(B") | |
363 | ("\e$,15s\e(B" . "\e$,4!s\e(B") | |
364 | ("\e$,15s6-\e(B" . "\e$,4!r\e(B") | |
1d475b5e KH |
365 | ("\e$,15t\e(B" . "\e$,4!s"#\e(B") |
366 | ("\e$,15t6-\e(B" . "\e$,4!r"#\e(B") | |
77539682 | 367 | |
1d475b5e | 368 | ("\e$,15u\e(B" . "\e$,4!t")\e(B") |
77539682 | 369 | ("\e$,15u6-\e(B" . "\e$,4!t\e(B") |
1d475b5e | 370 | ("\e$,15u6-5p\e(B" . "\e$,4!u")\e(B") |
77539682 | 371 | ("\e$,15u6-5p6-\e(B" . "\e$,4!u\e(B") |
a1506d29 JB |
372 | ;; SIBILANTS |
373 | ("\e$,15v\e(B" . "\e$,4!v")\e(B") | |
77539682 | 374 | ("\e$,15v6-\e(B" . "\e$,4!v\e(B") |
1d475b5e | 375 | ("\e$,15v6-5u\e(B" . "\e$,4!w")\e(B") |
77539682 | 376 | ("\e$,15v6-5u6-\e(B" . "\e$,4!w\e(B") |
1d475b5e | 377 | ("\e$,15v6-5p\e(B" . "\e$,4!x")\e(B") |
77539682 KH |
378 | ("\e$,15v6-5p6-\e(B" . "\e$,4!x\e(B") |
379 | ||
1d475b5e | 380 | ("\e$,15w\e(B" . "\e$,4!y")\e(B") |
77539682 | 381 | ("\e$,15w6-\e(B" . "\e$,4!y\e(B") |
1d475b5e | 382 | ("\e$,15x\e(B" . "\e$,4!z")\e(B") |
77539682 | 383 | ("\e$,15x6-\e(B" . "\e$,4!z\e(B") |
1d475b5e | 384 | ("\e$,15x6-5p\e(B" . "\e$,4!{")\e(B") |
77539682 KH |
385 | ("\e$,15x6-5p6-\e(B" . "\e$,4!{\e(B") |
386 | ||
387 | ("\e$,15y\e(B" . "\e$,4!}\e(B") | |
388 | ("\e$,15y6-\e(B" . "\e$,4!|\e(B") | |
389 | ("\e$,15y6#\e(B" . "\e$,4!~\e(B") | |
390 | ("\e$,15y6-5p\e(B" . "\e$,4!\7f\e(B") | |
1d475b5e KH |
391 | ("\e$,15y6-5n\e(B" . "\e$,4" \e(B") |
392 | ("\e$,15y6-5o\e(B" . "\e$,4"!\e(B") | |
a1506d29 | 393 | ;; NUKTAS |
1d475b5e | 394 | ("\e$,168\e(B" . "\e$,4 f"R"S\e(B") |
a1506d29 JB |
395 | ("\e$,1686-\e(B" . "\e$,4 d\e(B") |
396 | ("\e$,169\e(B" . "\e$,4 k")\e(B") | |
397 | ("\e$,1696-\e(B" . "\e$,4 k\e(B") | |
398 | ("\e$,16:\e(B" . "\e$,4 n")\e(B") | |
399 | ("\e$,16:6-\e(B" . "\e$,4 n\e(B") | |
400 | ("\e$,16;\e(B" . "\e$,4 w")\e(B") | |
401 | ("\e$,16;6-\e(B" . "\e$,4 w\e(B") | |
402 | ("\e$,16<\e(B" . "\e$,4!#"W\e(B") | |
403 | ("\e$,16=\e(B" . "\e$,4!'"X\e(B") | |
404 | ("\e$,16>\e(B" . "\e$,4!b"[\e(B") | |
405 | ("\e$,16>6-\e(B" . "\e$,4!>\e(B") | |
1d475b5e | 406 | ("\e$,16?\e(B" . "\e$,4!j"#")\e(B") |
77539682 | 407 | ;; misc modifiers. |
1d475b5e | 408 | ("\e$,15A\e(B" . "\\e$,4"$\e(B") |
a1506d29 | 409 | ("\e$,15B\e(B" . "\\e$,4"&\e(B") |
77539682 | 410 | ("\e$,15C\e(B" . "\e$,4 F\e(B") |
1d475b5e | 411 | ("\e$,15|\e(B" . "\e$,4"#\e(B") |
77539682 | 412 | ("\e$,15}\e(B" . "\e$,4 E\e(B") |
1d475b5e KH |
413 | ("\e$,16-\e(B" . "\e$,4""\e(B") |
414 | ("\e$,16-5p\e(B" . "\e$,4"%\e(B") ;; following "r" | |
a1506d29 | 415 | ;; ("\e$,160\e(B" . "\e$,4 D\e(B") |
8dcc539d | 416 | ("\e$,16D\e(B" . "\e$,4 J\e(B") |
a1506d29 JB |
417 | ;; ("\e$,16F\e(B" . "") |
418 | ;; ("\e$,16G\e(B" . "") | |
419 | ;; ("\e$,16H\e(B" . "") | |
420 | ;; ("\e$,16I\e(B" . "") | |
421 | ;; ("\e$,16J\e(B" . "") | |
422 | ;; ("\e$,16K\e(B" . "") | |
423 | ;; ("\e$,16L\e(B" . "") | |
424 | ;; ("\e$,16M\e(B" . "") | |
425 | ;; ("\e$,16N\e(B" . "") | |
77539682 KH |
426 | ;; ("\e$,16O\e(B" . "") |
427 | ) | |
a1506d29 | 428 | "Devanagari characters to glyphs conversion table. |
77539682 KH |
429 | Default value contains only the basic rules. You may add your own |
430 | preferred rule from the sanskrit fonts." ) | |
1bec6fdb RS |
431 | |
432 | (defvar dev-char-glyph-hash | |
aca05879 | 433 | (let* ((hash (make-hash-table :test 'equal))) |
1bec6fdb RS |
434 | (mapc (function (lambda (x) (puthash (car x) (cdr x) hash))) |
435 | dev-char-glyph) | |
436 | hash)) | |
437 | ||
438 | (defvar dev-char-glyph-regexp | |
4f102de2 | 439 | (devanagari-regexp-of-hashtbl-keys dev-char-glyph-hash)) |
1bec6fdb RS |
440 | |
441 | ;; glyph-to-glyph conversion table. | |
a1506d29 | 442 | ;; it is supposed that glyphs are ordered in |
1bec6fdb RS |
443 | ;; [consonant/nukta] - [matra/halant] - [preceding-r] - [anuswar]. |
444 | ||
77539682 | 445 | (defvar dev-glyph-glyph |
1d475b5e KH |
446 | '(("\\e$,4"'\e(B\\e$,4"&\e(B" . "\\e$,4"(\e(B") |
447 | ("\\e$,4"'\e(B\\e$,4"$\e(B" . "\\e$,4"(\e(B") | |
448 | ("\e$,4"*\e(B\\e$,4"&\e(B" . "\e$,4"+\e(B") | |
449 | ("\e$,4"*\e(B\\e$,4"'\e(B" . "\e$,4",\e(B") | |
450 | ("\e$,4"*\e(B\\e$,4"'\e(B\\e$,4"&\e(B" . "\e$,4"-\e(B") | |
451 | ("\e$,4"2\e(B\\e$,4"&\e(B" . "\e$,4"3\e(B") | |
452 | ("\e$,4"2\e(B\\e$,4"'\e(B" . "\e$,4"4\e(B") | |
453 | ("\e$,4"2\e(B\\e$,4"'\e(B\\e$,4"&\e(B" . "\e$,4"5\e(B") | |
454 | ("\e$,4"#\e(B\\e$,4"6\e(B" . "\e$,4"7\e(B") | |
455 | ("\e$,4"%\e(B\\e$,4"6\e(B" . "\e$,4"8\e(B") | |
456 | ;;("\e$,4"6\e(B" . "\e$,4"9\e(B") | |
457 | ("\e$,4"#\e(B\\e$,4":\e(B" . "\e$,4";\e(B") | |
458 | ("\e$,4"%\e(B\\e$,4":\e(B" . "\e$,4"<\e(B") | |
459 | ;;("\e$,4":\e(B" . "\e$,4"=\e(B") | |
460 | ("\\e$,4"@\e(B\\e$,4"&\e(B" . "\\e$,4"A\e(B") | |
461 | ("\\e$,4"@\e(B\\e$,4"'\e(B" . "\\e$,4"B\e(B") | |
462 | ("\\e$,4"@\e(B\\e$,4"'\e(B\\e$,4"&\e(B" . "\\e$,4"C\e(B") | |
463 | ("\\e$,4"D\e(B\\e$,4"&\e(B" . "\\e$,4"E\e(B") | |
464 | ("\\e$,4"D\e(B\\e$,4"'\e(B" . "\\e$,4"F\e(B") | |
465 | ("\\e$,4"D\e(B\\e$,4"'\e(B\\e$,4"&\e(B" . "\\e$,4"G\e(B") | |
466 | ("\\e$,4"H\e(B\\e$,4"&\e(B" . "\\e$,4"I\e(B") | |
467 | ("\\e$,4"H\e(B\\e$,4"'\e(B" . "\\e$,4"J\e(B") | |
468 | ("\\e$,4"H\e(B\\e$,4"'\e(B\\e$,4"&\e(B" . "\\e$,4"K\e(B") | |
469 | ("\\e$,4"L\e(B\\e$,4"&\e(B" . "\\e$,4"M\e(B") | |
470 | ("\\e$,4"L\e(B\\e$,4"'\e(B" . "\\e$,4"N\e(B") | |
471 | ("\\e$,4"L\e(B\\e$,4"'\e(B\\e$,4"&\e(B" . "\\e$,4"O\e(B") | |
77539682 | 472 | )) |
1bec6fdb | 473 | (defvar dev-glyph-glyph-hash |
aca05879 | 474 | (let* ((hash (make-hash-table :test 'equal))) |
1bec6fdb RS |
475 | (mapc (function (lambda (x) (puthash (car x) (cdr x) hash))) |
476 | dev-glyph-glyph) | |
477 | hash)) | |
478 | (defvar dev-glyph-glyph-regexp | |
4f102de2 | 479 | (devanagari-regexp-of-hashtbl-keys dev-glyph-glyph-hash)) |
1bec6fdb RS |
480 | |
481 | ||
482 | ;; yet another glyph-to-glyph conversions. | |
77539682 | 483 | (defvar dev-glyph-glyph-2 |
1d475b5e KH |
484 | '(("\e$,4"*\e(B" . "\e$,4".\e(B") |
485 | ("\e$,4"+\e(B" . "\e$,4"/\e(B") | |
486 | ("\e$,4",\e(B" . "\e$,4"0\e(B") | |
487 | ("\e$,4"-\e(B" . "\e$,4"1\e(B"))) | |
1bec6fdb | 488 | (defvar dev-glyph-glyph-2-hash |
aca05879 | 489 | (let* ((hash (make-hash-table :test 'equal))) |
1bec6fdb RS |
490 | (mapc (function (lambda (x) (puthash (car x) (cdr x) hash))) |
491 | dev-glyph-glyph-2) | |
492 | hash)) | |
493 | (defvar dev-glyph-glyph-2-regexp | |
4f102de2 | 494 | (devanagari-regexp-of-hashtbl-keys dev-glyph-glyph-2-hash)) |
1bec6fdb | 495 | |
1bec6fdb RS |
496 | (defun dev-charseq (from &optional to) |
497 | (if (null to) (setq to from)) | |
8f924df7 KH |
498 | (number-sequence (decode-char 'devanagari-cdac from) |
499 | (decode-char 'devanagari-cdac to))) | |
1bec6fdb RS |
500 | |
501 | (defvar dev-glyph-cvn | |
a1506d29 | 502 | (append |
1bec6fdb RS |
503 | (dev-charseq #x2b) |
504 | (dev-charseq #x3c #xc1) | |
505 | (dev-charseq #xc3)) | |
506 | "Devanagari Consonants/Vowels/Nukta Glyphs") | |
507 | ||
508 | (defvar dev-glyph-space | |
509 | (dev-charseq #xf0 #xfe) | |
510 | "Devanagari Spacing Glyphs") | |
511 | ||
512 | (defvar dev-glyph-right-modifier | |
a1506d29 | 513 | (append |
1bec6fdb RS |
514 | (dev-charseq #xc9) |
515 | (dev-charseq #xd2 #xd5)) | |
516 | "Devanagari Modifiers attached at the right side.") | |
517 | ||
518 | (defvar dev-glyph-right-modifier-regexp | |
519 | (concat "[" dev-glyph-right-modifier "]")) | |
520 | ||
521 | (defvar dev-glyph-left-matra | |
522 | (dev-charseq #xca #xd1) | |
523 | "Devanagari Matras attached at the left side.") | |
524 | ||
525 | (defvar dev-glyph-top-matra | |
526 | (dev-charseq #xe0 #xef) | |
527 | "Devanagari Matras attached at the top side.") | |
528 | ||
529 | (defvar dev-glyph-bottom-modifier | |
a1506d29 | 530 | (append |
1bec6fdb RS |
531 | (dev-charseq #xd6 #xdf) |
532 | (dev-charseq #xc2)) | |
533 | "Devanagari Modifiers attached at the bottom.") | |
534 | ||
535 | (defvar dev-glyph-order | |
536 | `((,dev-glyph-cvn . 1) | |
537 | (,dev-glyph-space . 2) | |
538 | (,dev-glyph-right-modifier . 3) | |
539 | (,dev-glyph-left-matra . 3) ;; processed by reference point. | |
540 | (,dev-glyph-top-matra . 4) | |
541 | (,(dev-charseq #xc7 #xc8) . 5) | |
760061fa | 542 | (,(dev-charseq #xc4) . 6) |
1bec6fdb RS |
543 | (,(dev-charseq #xc6) . 6) |
544 | (,(dev-charseq #xc5) . 7) | |
545 | (,dev-glyph-bottom-modifier . 8))) | |
546 | ||
a1506d29 | 547 | (mapc |
1bec6fdb | 548 | (function (lambda (x) |
a1506d29 | 549 | (mapc |
1bec6fdb RS |
550 | (function (lambda (y) |
551 | (put-char-code-property y 'composition-order (cdr x)))) | |
552 | (car x)))) | |
553 | dev-glyph-order) | |
554 | ||
555 | (mapc | |
556 | (function (lambda (x) | |
557 | (put-char-code-property x 'reference-point '(3 . 5)))) | |
558 | dev-glyph-left-matra) | |
559 | ||
560 | (defun devanagari-compose-syllable-string (string) | |
561 | (with-temp-buffer | |
562 | (insert (decompose-string string)) | |
563 | (devanagari-compose-syllable-region (point-min) (point-max)) | |
564 | (buffer-string))) | |
565 | ||
77539682 KH |
566 | (defun devanagari-compose-syllable-region (from to) |
567 | "Compose devanagari syllable in region FROM to TO." | |
568 | (let ((glyph-str nil) (cons-num 0) glyph-str-list | |
0b520940 DL |
569 | (last-halant nil) (preceding-r nil) (last-modifier nil) |
570 | (last-char (char-before to)) match-str | |
571 | glyph-block split-pos) | |
77539682 KH |
572 | (save-excursion |
573 | (save-restriction | |
0b520940 DL |
574 | ;;; *** char-to-glyph conversion *** |
575 | ;; Special rule 1. -- Last halant must be preserved. | |
576 | (if (eq last-char ?\e$,16-\e(B) | |
577 | (progn | |
578 | (setq last-halant t) | |
579 | (narrow-to-region from (1- to))) | |
580 | (narrow-to-region from to) | |
581 | ;; note if the last char is modifier. | |
582 | (if (or (eq last-char ?\e$,15A\e(B) (eq last-char ?\e$,15B\e(B)) | |
583 | (setq last-modifier t))) | |
584 | (goto-char (point-min)) | |
585 | ;; Special rule 2. -- preceding "r halant" must be modifier. | |
586 | (when (looking-at "\e$,15p6-\e(B.") | |
587 | (setq preceding-r t) | |
588 | (goto-char (+ 2 (point)))) | |
589 | ;; translate the rest characters into glyphs | |
6b61353c KH |
590 | (while (re-search-forward dev-char-glyph-regexp nil t) |
591 | (setq match-str (match-string 0)) | |
592 | (setq glyph-str | |
593 | (concat glyph-str | |
594 | (gethash match-str dev-char-glyph-hash))) | |
595 | ;; count the number of consonant-glyhs. | |
596 | (if (string-match devanagari-consonant match-str) | |
597 | (setq cons-num (1+ cons-num)))) | |
0b520940 DL |
598 | ;; preceding-r must be attached before the anuswar if exists. |
599 | (if preceding-r | |
600 | (if last-modifier | |
601 | (setq glyph-str (concat (substring glyph-str 0 -1) | |
602 | "\e$,4"'\e(B" (substring glyph-str -1))) | |
603 | (setq glyph-str (concat glyph-str "\e$,4"'\e(B")))) | |
604 | (if last-halant (setq glyph-str (concat glyph-str "\e$,4""\e(B"))) | |
605 | ;;; *** glyph-to-glyph conversion *** | |
606 | (when (string-match dev-glyph-glyph-regexp glyph-str) | |
607 | (setq glyph-str | |
608 | (replace-match (gethash (match-string 0 glyph-str) | |
609 | dev-glyph-glyph-hash) | |
610 | nil t glyph-str)) | |
611 | (if (and (> cons-num 1) | |
612 | (string-match dev-glyph-glyph-2-regexp glyph-str)) | |
613 | (setq glyph-str | |
614 | (replace-match (gethash (match-string 0 glyph-str) | |
615 | dev-glyph-glyph-2-hash) | |
616 | nil t glyph-str)))) | |
617 | ;;; *** glyph reordering *** | |
618 | (while (setq split-pos (string-match "\e$,4""\e(B\\|.$" glyph-str)) | |
619 | (setq glyph-block (substring glyph-str 0 (1+ split-pos))) | |
620 | (setq glyph-str (substring glyph-str (1+ split-pos))) | |
621 | (setq | |
622 | glyph-block | |
623 | (if (string-match dev-glyph-right-modifier-regexp glyph-block) | |
624 | (sort (string-to-list glyph-block) | |
625 | (function (lambda (x y) | |
626 | (< (get-char-code-property x 'composition-order) | |
627 | (get-char-code-property y 'composition-order))))) | |
628 | (sort (string-to-list glyph-block) | |
629 | (function (lambda (x y) | |
630 | (let ((xo (get-char-code-property x 'composition-order)) | |
631 | (yo (get-char-code-property y 'composition-order))) | |
632 | (if (= xo 2) nil (if (= yo 2) t (< xo yo))))))))) | |
633 | (setq glyph-str-list (nconc glyph-str-list glyph-block))) | |
634 | ;; concatenate and attach reference-points. | |
635 | (setq glyph-str | |
636 | (cdr | |
637 | (apply | |
638 | 'nconc | |
639 | (mapcar | |
640 | (function (lambda (x) | |
641 | (list | |
642 | (or (get-char-code-property x 'reference-point) | |
643 | '(5 . 3) ;; default reference point. | |
644 | ) | |
645 | x))) | |
646 | glyph-str-list)))))) | |
77539682 | 647 | (compose-region from to glyph-str))) |
4ed46869 | 648 | |
650e8505 | 649 | (provide 'devan-util) |
02ed5b47 | 650 | |
6b61353c | 651 | ;;; arch-tag: 9bc4d6e3-f2b9-4110-886e-ff9b66b7eebc |
02ed5b47 | 652 | ;;; devan-util.el ends here |