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