]> code.delx.au - gnu-emacs/blobdiff - lisp/language/devan-util.el
Adjusted for the change of make-coding-system. Register
[gnu-emacs] / lisp / language / devan-util.el
index 907fe75e3be283519f4984b520b9d9abad1bd0ca..c811e62fb64e51eaa0f00df5b253667ef3cae57e 100644 (file)
 
 ;; History:
 ;; 1996.10.18 written by KAWABATA, Taichi <kawabata@is.s.u-tokyo.ac.jp>
+;; 1997.1.20 fixed some bugs.
+;; 1997.3.24 fixed some bugs.
+
+;; Future work ::
+;; Decompose the input characters and process them on the character basis.
 
 ;; Devanagari script composition rules and related programs.
 
 ;;;   Steps toward composition of Devanagari Characters.
 ;;;
 
+;;; Intersection Function will be used.
+(require 'cl)
+
+;;;###autoload
+(defun setup-devanagari-environment ()
+  "Setup multilingual environment (MULE) for languages using Devanagari."
+  (interactive)
+  (setup-8-bit-environment "Devanagari" nil "devanagari-itrans"))
+
 ;;; Basic functions.
 
 ;;;###autoload
@@ -64,7 +78,8 @@
   (save-restriction 
     (narrow-to-region from to)
     (goto-char (point-min))
-    (while (re-search-forward "\\cd" nil t)
+;   (while (re-search-forward "\\cd" nil t)
+    (while (re-search-forward "." nil t)
       (let* ((devanagari-char (indian-to-devanagari (preceding-char))))
        (delete-char -1)
        (insert devanagari-char)))))
@@ -76,7 +91,8 @@
   (save-restriction
     (narrow-to-region from to)
     (goto-char (point-min))
-    (while (re-search-forward "\\cD" nil t) ; Devanagari Character Code.
+;   (while (re-search-forward "\\cD" nil t) ; Devanagari Character Code.
+    (while (re-search-forward "." nil t) 
       (let* ((indian-char (devanagari-to-indian (preceding-char))))
        (delete-char -1)
        (insert indian-char)))))
 ;; Syllable ::= Cons-Vowel-Syllable | Vowel-Syllable
 ;; Vowel-Syllable ::= V[D]
 ;; Cons-Vowel-Syllable ::= [Cons-Syllable] Full-Cons [M] [D]
-;; Cons-Syllable ::= [Pure-Cons] [Pure-Cons] Pure-Cons
+;; Cons-Syllable ::= [Pure-Cons] [Pure-Cons] [Pure-Cons] Pure-Cons
 ;; Pure-Cons ::= Full-Cons H
 ;; Full-Cons ::= C [N]
 ;;
 ;; C - Consonant (\e$(5!3!4!5!6!7!8!9!:!;!<!=!>!?!@!A!B!C!D!E\e(B
 ;;                \e$(5!F!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X\e(B)
 ;; N - Nukta (\e$(5!i\e(B)
-;; H - Halant(\e$(5!h\e(B)
-;; V - Vowel (\e$(5!$!%!&!'!(!)!*!+!,!-!.!/!0!1!2\e(B)
-;; D - Vowel Modifiers, i.e. Anuswar, Chandrabindu, Visarg  (\e$(5!!!"\e(B)
-;; M - Matra (\e$(5!Z![!\!]!^!_!`!a!b!c!d!e!f!g\e(B)
+;; H - Halant(\e$(5!h\e(B) or Virama
+;; V - Vowel (\e$(5!$!%!&!'!(!)!*!+!,!-!.!/!0!1!2#&#'#*\e(B)
+;;     ("\e$(5#&#'#*\e(B" can be obtained by IS13194 vowels with nukta.)
+;; D - Vowel Modifiers, i.e. Anuswar, Chandrabindu  (\e$(5!!!"\e(B) 
+;;     (Visaraga (\e$(5!#\e(B) is excluded.)
+;; M - Matra (\e$(5!Z![!\!]!^!_!`!a!b!c!d!e!f!g#K#L#M\e(B)
+;;     ("\e$(5#K#L#M\e(B" can be obtained by IS13194 matras with nukta.)
 ;;
-;; In Emacs, one syllable of Indian language is considered to be one 
-;; composite glyph.  If we expand the above expression, it would be:
+;; In Emacs, one syllable of Indian language is considered to be one
+;; composite glyph.  If we expand the above expression for
+;; cons-vowel-syllable, it would be:
 ;;
-;; [[C [N] H] [C [N] H] C [N] H] C [N] [M] [D] | V [D]
+;; [[C [N] H] [C [N] H] [C [N] H] C [N] H] C [N] [M] [D]
 ;; 
-;; Therefore, in worst case, the consonant syllabe will consist of
+;; Therefore, in worst case, the one syllable may contain
 ;; following characters.
 ;;
-;; C N H C N H C N H C N M D
+;; C N H C N H C N H C N H C N M D
+;;
+;; The example is a sanskrit word "kArtsnya", where five consecutive
+;; consonants appear.
 ;;
-;; On the other hand, incomplete consonant syllable before inputting
-;; base consonant must satisfy the following condition:
+;; On the other hand, consonant-syllable, which appears at the end of 
+;; the word, would have the following expression:
 ;;
-;; [C [N] H] [C [N] H] C [N] H
+;; [C [N] H] [C [N] H] [C [N] H] C [N] H
 ;;
 ;; This is acceptable BEFORE proper consonant-syllable is input.  The
 ;; string which doesn't match with the above expression is invalid and
 ;; Third case can be considered, which is acceptable syllable and can
 ;; not add any code more.
 ;;
-;; [[C [N] H] [C [N] H] C [N] H] C [N] [M] D
+;; [[C [N] H] [C [N] H] [C [N] H] C [N] H] C [N] [M] D
 ;;
 ;; However, to make editing possible even in this condition, we will
 ;; not consider about this case.
-
-(defconst devanagari-cons-syllable-examine
-  "\\(\\([\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B?\e$(5!h\e(B\\)?\\([\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B?\e$(5!h\e(B\\)?[\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B?\e$(5!h\e(B\\)?[\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B?[\e$(5!Z\e(B-\e$(5!g\e(B]?[\e$(5!!!"\e(B]?"
-  "Regexp matching to one Devanagari consonant syllable.")
-
-(defconst devanagari-cons-syllable-incomplete-examine
-  "\\([\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B?\e$(5!h\e(B\\)?\\([\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B?\e$(5!h\e(B\\)?[\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B?\e$(5!h\e(B$"
-  "Regexp matching to one Devanagari incomplete consonant syllable.")
-
-(defconst devanagari-vowel-syllable-examine
-  "[\e$(5!$\e(B-\e$(5!2\e(B][\e$(5!!!"!#\e(B]?"
-  "Regexp matching to one Devanagari vowel syllable.")
+;;
+;; Note:
+;; Currently, it seems that the only following consonants would have
+;; Nukta sign attatched.
+;; (\e$(5!3!4!5!:!?!@!I\e(B)
+;; Therefore, [\e$(5!3\e(B-\e$(5!X\e(B]\e$(5!i\e(B? can be re-written as 
+;; \\([\e$(5!3!4!5!:!?!@!I\e(B]\e$(5!i\e(B\\)\\|[\e$(5!3\e(B-\e$(5!X\e(B]
+
+(defconst devanagari-full-cons
+  "\\(\\([\e$(5!3!4!5!:!?!@!I\e(B]\e$(5!i\e(B\\)\\|[\e$(5!3\e(B-\e$(5!X$.$E"%\e(B]\\)"
+  "Devanagari full consonant")
+
+(defconst devanagari-pure-cons
+  (concat "\\(" devanagari-full-cons "\e$(5!h\e(B\\)")
+  "Devanagari pure consonant")
+
+(defconst devanagari-matra
+  "\\(\\([\e$(5!_![!\\e(B]\e$(5!i\e(B\\)\\|[\e$(5!Z\e(B-\e$(5!g#K#L#M\e(B]\\)"
+  "Devanagari Matra Signs.  '\e$(5#K#L#M\e(B' can also be created from the combination 
+of '\e$(5!_![!\\e(B' and nukta sign.")
+
+(defconst devanagari-vowel
+  "\\(\\([\e$(5!*!&!'\e(B]\e$(5!i\e(B\\)\\|[\e$(5!$\e(B-\e$(5!2#&#'#*\e(B]\\)"
+  "Devanagari Vowels.  '\e$(5#&#'#*\e(B' can also be created from the combination 
+of '\e$(5!*!&!'\e(B' and nukta sign.")
+  
+(defconst devanagari-vowel-syllable
+  (concat devanagari-vowel "[\e$(5!!!"\e(B]?")
+  "Devanagari vowel syllable.")
+
+(defconst devanagari-cons-syllable
+  (concat devanagari-pure-cons "?" devanagari-pure-cons "?" 
+         devanagari-pure-cons "?" devanagari-pure-cons "$")
+  "Devanagari consonant syllable")
+
+(defconst devanagari-cons-vowel-syllable
+  (concat "\\(" 
+         devanagari-pure-cons "?" devanagari-pure-cons "?" 
+         devanagari-pure-cons "?" devanagari-pure-cons "\\)?"
+         devanagari-full-cons devanagari-matra "?[\e$(5!!!"\e(B]?")
+  "Devanagari consonant vowel syllable.")
 
 ;;
 ;; Also, digits and virams should be processed other than syllables.
 ;; In IS 13194, Avagrah is obtained by Nukta after Viram, and
 ;; OM is obtained by Nukta after Chandrabindu
 ;;
-(defconst devanagari-digit-viram-examine 
-  "[\e$(5!q\e(B-\e$(5!z!j\e(B]")
-(defconst devanagari-other-sign-examine
-  "[\e$(5!!!j\e(B]\e$(5!i\e(B")
-
-(defconst devanagari-composite-glyph-unit-examine
-  (concat "\\(" devanagari-cons-syllable-incomplete-examine 
-         "\\)\\|\\(" devanagari-vowel-syllable-examine 
-         "\\)\\|\\(" devanagari-digit-viram-examine
-         "\\)\\|\\(" devanagari-cons-syllable-examine
-         "\\)\\|\\(" devanagari-other-sign-examine"\\)")
+
+(defconst devanagari-digit-viram-visarga
+  "[\e$(5!q\e(B-\e$(5!z!j!#\e(B]")
+(defconst devanagari-other-sign
+  "\\([\e$(5!!!j\e(B]\e$(5!i\e(B\\)\\|\\([\e$(5#!#J\e(B]\\)")
+
+(defconst devanagari-composite-glyph-unit
+  (concat "\\(" devanagari-cons-syllable
+         "\\)\\|\\(" devanagari-vowel-syllable
+         "\\)\\|\\(" devanagari-digit-viram-visarga
+         "\\)\\|\\(" devanagari-cons-vowel-syllable
+         "\\)\\|\\(" devanagari-other-sign "\\)")
   "Regexp matching to Devanagari string to be composed form one glyph.")
 
 ;;(put-charset-property charset-devanagari-1-column
 
 ;; Sample
 ;;
-;;(string-match devanagari-cons-syllable-examine "\e$(5!X![\e(B") => 0
-;;(string-match devanagari-cons-syllable-examine "\e$(5!F!h!D!\\e(B") => 0
-;;(string-match devanagari-cons-syllable-examine "\e$(5!X![!F!h!D!\\e(B") => 0
+;;(string-match devanagari-cons-vowel-syllable-examine "\e$(5!X![\e(B") => 0
+;;(string-match devanagari-cons-vowel-syllable-examine "\e$(5!F!h!D!\\e(B") => 0
+;;(string-match devanagari-cons-vowel-syllable-examine "\e$(5!X![!F!h!D!\\e(B") => 0
 
 ;;
 ;; Steps toward the composition
-;;  Converting Character Code to Composite Glyph.
+;;  Converting Character Codes to Composite Glyph.
 ;;
 ;; Example : \e$(5!X![\e(B/\e$(5!F!h!D!\\e(B
 ;; 
 
 (defconst devanagari-char-to-glyph-rules
   '(
-    ;; special form for "ru".
-    ("\\(\e$(5!O!]\e(B\\)" . "\e$(5",\e(B")
-    ("\\(\e$(5!O!^\e(B\\)" . "\e$(5"-\e(B")
-    ("\\(\e$(5!P!]\e(B\\)" . "\e$(5".\e(B")
-    ("\\(\e$(5!P!^\e(B\\)" . "\e$(5"/\e(B")
 
     ;; `r' at the top of syllable and followed by other consonants.
-    ;; ("[^\e$(5!h\e(B]\\(\e$(5!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"p\e(B")
-    ("^\\(\e$(5!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"p\e(B")
-
-    ;; If "r" is preceded by the vowel-suppressed consonant
-    ;; (especially those with vertical line), it will be written as
-    ;; slanted line below the preceding consonant character.  Some of
-    ;; them are pre-composed as one glyph.
-
-    ("\\(\e$(5!:!i!h!O\e(B\\)" . "\e$(5"!\e(B")
-    ("\\(\e$(5!I!i!h!O\e(B\\)" . "\e$(5""\e(B")
-    ("\\(\e$(5!3!h!O\e(B\\)" . "\e$(5"#\e(B")
-    ("\\(\e$(5!:!h!O\e(B\\)" . "\e$(5"$\e(B")
-    ("\\(\e$(5!B!h!O\e(B\\)" . "\e$(5"%\e(B")
-    ("\\(\e$(5!H!h!O\e(B\\)" . "\e$(5"&\e(B")
-    ("\\(\e$(5!I!h!O\e(B\\)" . "\e$(5"'\e(B")
-    ("\\(\e$(5!U!h!O\e(B\\)" . "\e$(5"(\e(B")
-    ("\\(\e$(5!W!h!O\e(B\\)" . "\e$(5")\e(B")
+    ;; ("[^\e$(5!h\e(B]\\(\e$(5!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" "\e$(5"p\e(B")
+    ("^\\(\e$(5!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" "\e$(5"p\e(B")
 
     ;; Ligature Rules 
-    ("\\(\e$(5!3!h!B!h!O!h!M\e(B\\)" . "\e$(5$!\e(B")
-    ("\\(\e$(5!3!h!B!h!T\e(B\\)" . "\e$(5$"\e(B")
-    ("\\(\e$(5!3!h!B!h!M\e(B\\)" . "\e$(5$#\e(B")
-    ("\\(\e$(5!3!h!F!h!M\e(B\\)" . "\e$(5$$\e(B")
-    ("\\(\e$(5!3!h!O!h!M\e(B\\)" . "\e$(5$%\e(B")
-    ("\\(\e$(5!3!h!T!h!M\e(B\\)" . "\e$(5$&\e(B")
-    ("\\(\e$(5!3!h!3\e(B\\)" . "\e$(5$'\e(B")
-    ("\\(\e$(5!3!h!B\e(B\\)" . "\e$(5$(\e(B")
-    ("\\(\e$(5!3!h!F\e(B\\)" . "\e$(5$)\e(B")
-    ("\\(\e$(5!3!h!L\e(B\\)" . "\e$(5$*\e(B")
-    ("\\(\e$(5!3!h!M\e(B\\)" . "\e$(5$+\e(B")
-    ("\\(\e$(5!3!h!Q\e(B\\)" . "\e$(5$,\e(B")
-    ("\\(\e$(5!3!h!T\e(B\\)" . "\e$(5$-\e(B")
-    ("\\(\e$(5!3!h!V\e(B\\)" . "\e$(5$.\e(B")
-    ("\\(\e$(5!6!h!F\e(B\\)" . "\e$(5$/\e(B")
-    ("\\(\e$(5!7!h!3!h!B!h!M\e(B\\)" . "\e$(5$0\e(B")
-    ("\\(\e$(5!7!h!3!h!V!h!T\e(B\\)" . "\e$(5$1\e(B")
-    ("\\(\e$(5!7!h!3!h!B\e(B\\)" . "\e$(5$2\e(B")
-    ("\\(\e$(5!7!h!3!h!V\e(B\\)" . "\e$(5$3\e(B")
-    ("\\(\e$(5!7!h!6!h!O\e(B\\)" . "\e$(5$4\e(B")
-    ("\\(\e$(5!7!h!3!h!M\e(B\\)" . "\e$(5$5\e(B")
-    ("\\(\e$(5!7!h!4!h!M\e(B\\)" . "\e$(5$6\e(B")
-    ("\\(\e$(5!7!h!5!h!M\e(B\\)" . "\e$(5$7\e(B")
-    ("\\(\e$(5!7!h!6!h!M\e(B\\)" . "\e$(5$8\e(B")
-    ("\\(\e$(5!7!h!3\e(B\\)" . "\e$(5$9\e(B")
-    ("\\(\e$(5!7!h!4\e(B\\)" . "\e$(5$:\e(B")
-    ("\\(\e$(5!7!h!5\e(B\\)" . "\e$(5$;\e(B")
-    ("\\(\e$(5!7!h!6\e(B\\)" . "\e$(5$<\e(B")
-    ("\\(\e$(5!7!h!7\e(B\\)" . "\e$(5$=\e(B")
-    ("\\(\e$(5!7!h!F\e(B\\)" . "\e$(5$>\e(B")
-    ("\\(\e$(5!7!h!L\e(B\\)" . "\e$(5$?\e(B")
-    ("\\(\e$(5!7!h!M\e(B\\)" . "\e$(5$@\e(B")
-    ("\\(\e$(5!8!h!8\e(B\\)" . "\e$(5$A\e(B")
-    ("\\(\e$(5!8!h!<\e(B\\)" . "\e$(5$B\e(B")
-    ("\\(\e$(5!9!h!M\e(B\\)" . "\e$(5$C\e(B")
-    ("\\(\e$(5!:!h!O\e(B\\)" . "\e$(5$D\e(B")
-    ("\\(\e$(5!:!h!h\e(B\\)" . "\e$(5$E\e(B")
-    ("\\(\e$(5!<!h!8\e(B\\)" . "\e$(5$F\e(B")
-    ("\\(\e$(5!<!h!:\e(B\\)" . "\e$(5$G\e(B")
-    ("\\(\e$(5!=!h!3\e(B\\)" . "\e$(5$H\e(B")
-    ("\\(\e$(5!=!h!=\e(B\\)" . "\e$(5$I\e(B")
-    ("\\(\e$(5!=!h!>\e(B\\)" . "\e$(5$J\e(B")
-    ("\\(\e$(5!=!h!M\e(B\\)" . "\e$(5$K\e(B")
-    ("\\(\e$(5!>!h!M\e(B\\)" . "\e$(5$L\e(B")
-    ("\\(\e$(5!?!h!5!h!M\e(B\\)" . "\e$(5$M\e(B")
-    ("\\(\e$(5!?!h!6!h!O\e(B\\)" . "\e$(5$N\e(B")
-    ("\\(\e$(5!?!h!O!h!M\e(B\\)" . "\e$(5$O\e(B")
-    ("\\(\e$(5!?!h!5\e(B\\)" . "\e$(5$P\e(B")
-    ("\\(\e$(5!?!h!6\e(B\\)" . "\e$(5$Q\e(B")
-    ("\\(\e$(5!?!h!?\e(B\\)" . "\e$(5$R\e(B")
-    ("\\(\e$(5!?!h!L\e(B\\)" . "\e$(5$S\e(B")
-    ("\\(\e$(5!?!h!M\e(B\\)" . "\e$(5$T\e(B")
-    ("\\(\e$(5!@!h!M\e(B\\)" . "\e$(5$`\e(B")
-    ("\\(\e$(5!B!h!B\e(B\\)" . "\e$(5$a\e(B")
-    ("\\(\e$(5!B!h!F\e(B\\)" . "\e$(5$b\e(B")
-    ("\\(\e$(5!D!h!D!h!M\e(B\\)" . "\e$(5$c\e(B")
-    ("\\(\e$(5!D!h!E!h!M\e(B\\)" . "\e$(5$d\e(B")
-    ("\\(\e$(5!D!h!K!h!M\e(B\\)" . "\e$(5$e\e(B")
-    ("\\(\e$(5!D!h!O!h!M\e(B\\)" . "\e$(5$f\e(B")
-    ("\\(\e$(5!D!h!T!h!M\e(B\\)" . "\e$(5$g\e(B")
-    ("\\(\e$(5!D!h!5!h!O\e(B\\)" . "\e$(5$h\e(B")
-    ("\\(\e$(5!D!h!6!h!O\e(B\\)" . "\e$(5$i\e(B")
-    ("\\(\e$(5!D!h!D!h!T\e(B\\)" . "\e$(5$j\e(B")
-    ("\\(\e$(5!D!h!E!h!T\e(B\\)" . "\e$(5$k\e(B")
-    ("\\(\e$(5!D!h!5\e(B\\)" . "\e$(5$l\e(B")
-    ("\\(\e$(5!D!h!6\e(B\\)" . "\e$(5$m\e(B")
-    ("\\(\e$(5!D!h!D\e(B\\)" . "\e$(5$n\e(B")
-    ("\\(\e$(5!D!h!E\e(B\\)" . "\e$(5$o\e(B")
-    ("\\(\e$(5!D!h!F\e(B\\)" . "\e$(5$p\e(B")
-    ("\\(\e$(5!D!h!J\e(B\\)" . "\e$(5$q\e(B")
-    ("\\(\e$(5!D!h!K\e(B\\)" . "\e$(5$r\e(B")
-    ("\\(\e$(5!D!h!L\e(B\\)" . "\e$(5$s\e(B")
-    ("\\(\e$(5!D!h!M\e(B\\)" . "\e$(5$t\e(B")
-    ("\\(\e$(5!D!h!T\e(B\\)" . "\e$(5$u\e(B")
-    ("\\(\e$(5!E!h!F\e(B\\)" . "\e$(5$v\e(B")
-    ("\\(\e$(5!F!h!F\e(B\\)" . "\e$(5$w\e(B")
-    ("\\(\e$(5!H!h!B\e(B\\)" . "\e$(5$x\e(B")
-    ("\\(\e$(5!H!h!F\e(B\\)" . "\e$(5$y\e(B")
-    ("\\(\e$(5!H!h!Q\e(B\\)" . "\e$(5$z\e(B")
-    ("\\(\e$(5!J!h!F\e(B\\)" . "\e$(5${\e(B")
-    ("\\(\e$(5!J!h!J\e(B\\)" . "\e$(5$|\e(B")
-    ("\\(\e$(5!J!h!T\e(B\\)" . "\e$(5$}\e(B")
-    ("\\(\e$(5!K!h!F\e(B\\)" . "\e$(5$~\e(B")
-    ("\\(\e$(5!L!h!F\e(B\\)" . "\e$(5#P\e(B")
-    ("\\(\e$(5!L!h!Q\e(B\\)" . "\e$(5#Q\e(B")
-    ("\\(\e$(5!Q!h!Q\e(B\\)" . "\e$(5#`\e(B")
-    ("\\(\e$(5!T!h!F\e(B\\)" . "\e$(5#a\e(B")
-    ("\\(\e$(5!T!h!T\e(B\\)" . "\e$(5#b\e(B")
-    ("\\(\e$(5!U!h!8\e(B\\)" . "\e$(5#c\e(B")
-    ("\\(\e$(5!U!h!F\e(B\\)" . "\e$(5#d\e(B")
-    ("\\(\e$(5!U!h!J\e(B\\)" . "\e$(5#e\e(B")
-    ("\\(\e$(5!U!h!Q\e(B\\)" . "\e$(5#f\e(B")
-    ("\\(\e$(5!U!h!T\e(B\\)" . "\e$(5#g\e(B")
-    ("\\(\e$(5!V!h!=!h!O!h!M\e(B\\)" . "\e$(5#h\e(B")
-    ("\\(\e$(5!V!h!=!h!M\e(B\\)" . "\e$(5#i\e(B")
-    ("\\(\e$(5!V!h!=!h!T\e(B\\)" . "\e$(5#j\e(B")
-    ("\\(\e$(5!V!h!=\e(B\\)" . "\e$(5#k\e(B")
-    ("\\(\e$(5!V!h!>\e(B\\)" . "\e$(5#l\e(B")
-    ("\\(\e$(5!W!h!F\e(B\\)" . "\e$(5#m\e(B")
-    ("\\(\e$(5!W!h!O\e(B\\)" . "\e$(5#n\e(B")
-    ("\\(\e$(5!X!h!A\e(B\\)" . "\e$(5#p\e(B")
-    ("\\(\e$(5!X!h!F\e(B\\)" . "\e$(5#q\e(B")
-    ("\\(\e$(5!X!h!L\e(B\\)" . "\e$(5#r\e(B")
-    ("\\(\e$(5!X!h!M\e(B\\)" . "\e$(5#s\e(B")
-    ("\\(\e$(5!X!h!O\e(B\\)" . "\e$(5#t\e(B")
-    ("\\(\e$(5!X!h!Q\e(B\\)" . "\e$(5#u\e(B")
-    ("\\(\e$(5!X!h!T\e(B\\)" . "\e$(5#v\e(B")
-    ;; Special Ligature Rules 
-    ("\\(\e$(5!X!_\e(B\\)" . "\e$(5#R\e(B")
-
-    ;; Half form with ligature.  Special "r" case is included.  "r"
-    ;; connection which is not listed here has not been examined yet.
-    ;; I don't know what to do with them.
+    ("\\(\e$(5!3!h!B!h!O!h!M\e(B\\)" "\e$(5$!\e(B" sanskrit)
+    ("\\(\e$(5!3!h!B!h!T\e(B\\)" "\e$(5$"\e(B" sanskrit)
+    ("\\(\e$(5!3!h!B!h!M\e(B\\)" "\e$(5$#\e(B" sanskrit)
+    ("\\(\e$(5!3!h!F!h!M\e(B\\)" "\e$(5$$\e(B") 
+    ("\\(\e$(5!3!h!O!h!M\e(B\\)" "\e$(5$%\e(B")
+    ("\\(\e$(5!3!h!O\e(B\\)" "\e$(5"#\e(B")                  ;                     Post "r"
+    ("\\(\e$(5!3!h!T!h!M\e(B\\)" "\e$(5$&\e(B" sanskrit)
+    ("\\(\e$(5!3!h\e(B\\)\e$(5!3!h\e(B[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"3\e(B")    ; Special Half Form
+    ("\\(\e$(5!3!h!3\e(B\\)" "\e$(5$'\e(B")
+    ("\\(\e$(5!3!h\e(B\\)\e$(5!B!h!O\e(B" "\e$(5"3\e(B")              ; Special Rules for "k-tr"
+    ("\\(\e$(5!3!h!B\e(B\\)" "\e$(5$(\e(B")
+    ("\\(\e$(5!3!h!F\e(B\\)" "\e$(5$)\e(B")
+    ("\\(\e$(5!3!h!L\e(B\\)" "\e$(5$*\e(B")
+    ("\\(\e$(5!3!h!M\e(B\\)" "\e$(5$+\e(B")
+    ("\\(\e$(5!3!h!Q\e(B\\)" "\e$(5$,\e(B")
+    ("\\(\e$(5!3!h!T\e(B\\)" "\e$(5$-\e(B")
+    ("\\(\e$(5!3!h!V!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"l\e(B")    ;         Half Form
+    ("\\(\e$(5$.!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"l\e(B")        ;         Half Form
+    ("\\(\e$(5!3!h!V\e(B\\)" "\e$(5$.\e(B")
+    ("\\(\e$(5!3!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"3\e(B")        ;         Half Form
+    ("\\(\e$(5!3!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"s\e(B")      ; Nukta   Half Form
+    ("\\(\e$(5!3!i\e(B\\)" "\e$(5#3\e(B")                    ; Nukta
+    ("\\(\e$(5!4!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"4\e(B")        ;         Half Form
+    ("\\(\e$(5!4!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"t\e(B")      ; Nukta   Half Form
+    ("\\(\e$(5!4!i\e(B\\)" "\e$(5#4\e(B")                    ; Nukta
+    ("\\(\e$(5!5!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"`\e(B")    ;         Half Form
+    ("\\(\e$(5!5!h!O\e(B\\)" "\e$(5"$\e(B")                  ;                     Post "r"
+    ("\\(\e$(5!5!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"5\e(B")        ;         Half Form
+    ("\\(\e$(5!5!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"u\e(B")      ; Nukta   Half Form
+    ("\\(\e$(5!5!i\e(B\\)" "\e$(5#5\e(B")                    ; Nukta
+    ("\\(\e$(5!6!h!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"a\e(B")    ;         Half Form
+    ("\\(\e$(5!6!h!F\e(B\\)" "\e$(5$/\e(B")
+    ; Slot
+    ("\\(\e$(5!6!h!O\e(B\\)" "\e$(5!6"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!6!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"6\e(B")        ;         Half Form
+    ("\\(\e$(5!7!h!3!h!B!h!M\e(B\\)" "\e$(5$0\e(B" sanskrit)
+    ("\\(\e$(5!7!h!3!h!V!h!T\e(B\\)" "\e$(5$1\e(B" sanskrit)
+    ("\\(\e$(5!7!h!3!h!B\e(B\\)" "\e$(5$2\e(B" sanskrit)
+    ("\\(\e$(5!7!h!3!h!V\e(B\\)" "\e$(5$3\e(B" sanskrit)
+    ("\\(\e$(5!7!h!3!h!O\e(B\\)" "\e$(5$9"q\e(B")            ; Special Rule. May be precomposed font needed.
+    ("\\(\e$(5!7!h!6!h!O\e(B\\)" "\e$(5$4\e(B" sanskrit)
+    ("\\(\e$(5!7!h!3!h!M\e(B\\)" "\e$(5$5\e(B" sanskrit)
+    ("\\(\e$(5!7!h!4!h!M\e(B\\)" "\e$(5$6\e(B" sanskrit)
+    ("\\(\e$(5!7!h!5!h!M\e(B\\)" "\e$(5$7\e(B" sanskrit)
+    ("\\(\e$(5!7!h!6!h!M\e(B\\)" "\e$(5$8\e(B" sanskrit)
+    ("\\(\e$(5!7!h!3\e(B\\)" "\e$(5$9\e(B")
+    ("\\(\e$(5!7!h!4\e(B\\)" "\e$(5$:\e(B")
+    ("\\(\e$(5!7!h!5!h!O\e(B\\)" "\e$(5$;"q\e(B")            ; Special Rule. May be precomposed font needed.
+    ("\\(\e$(5!7!h!5\e(B\\)" "\e$(5$;\e(B")
+    ("\\(\e$(5!7!h!6\e(B\\)" "\e$(5$<\e(B")
+    ("\\(\e$(5!7!h!7\e(B\\)" "\e$(5$=\e(B")
+    ("\\(\e$(5!7!h!F\e(B\\)" "\e$(5$>\e(B")
+    ("\\(\e$(5!7!h!L\e(B\\)" "\e$(5$?\e(B")
+    ("\\(\e$(5!7!h!M\e(B\\)" "\e$(5$@\e(B")
+    ("\\(\e$(5!8!h\e(B\\)[\e$(5!8!<\e(B]\e$(5!h\e(B" "\e$(5"8\e(B")            ;         Half Form
+    ("\\(\e$(5!8!h!8\e(B\\)" "\e$(5$A\e(B")
+    ("\\(\e$(5!8!h!<\e(B\\)" "\e$(5$B\e(B")
+    ("\\(\e$(5!8!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"8"q\e(B")  ;         Half Form   Post "r"
+    ("\\(\e$(5!8!h!O\e(B\\)" "\e$(5!8"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!8!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"8\e(B")        ;         Half Form
+    ("\\(\e$(5!9!h!M\e(B\\)" "\e$(5$C\e(B")
+    ("\\(\e$(5!:!h!O\e(B\\)" "\e$(5$D\e(B")
+    ("\\(\e$(5!:!h!<!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"m\e(B")    ;         Half Form
+    ("\\(\e$(5!:!h!<\e(B\\)" "\e$(5$E\e(B")
+    ("\\(\e$(5!:!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5":\e(B")        ;         Half Form
+    ("\\(\e$(5!:!i!h!O\e(B\\)" "\e$(5"!\e(B")                ; Nukta               Post "r"
+    ("\\(\e$(5!:!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"z\e(B")      ; Nukta   Half Form
+    ("\\(\e$(5!:!i\e(B\\)" "\e$(5#:\e(B")                    ; Nukta
+    ("\\(\e$(5!;!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5";\e(B")        ;         Half Form
+    ("\\(\e$(5!<!h\e(B\\)\e$(5!8!h\e(B[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"<\e(B")    ; Special Half Form
+    ("\\(\e$(5!<!h!8\e(B\\)" "\e$(5$F\e(B")
+    ("\\(\e$(5!<!h\e(B\\)\e$(5!:!h\e(B[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"<\e(B")    ; Special Half Form
+    ("\\(\e$(5!<!h!:\e(B\\)" "\e$(5$G\e(B")
+    ("\\(\e$(5!<!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"<\e(B")        ;         Half Form
+    ("\\(\e$(5!=!h!3\e(B\\)" "\e$(5$H\e(B")
+    ("\\(\e$(5!=!h!=\e(B\\)" "\e$(5$I\e(B")
+    ("\\(\e$(5!=!h!>\e(B\\)" "\e$(5$J\e(B")
+    ("\\(\e$(5!=!h!M\e(B\\)" "\e$(5$K\e(B")
+    ("\\(\e$(5!>!h!M\e(B\\)" "\e$(5$L\e(B")
+    ("\\(\e$(5!?!h!5!h!M\e(B\\)" "\e$(5$M\e(B" sanskrit)
+    ("\\(\e$(5!?!h!6!h!O\e(B\\)" "\e$(5$N\e(B" sanskrit)
+    ("\\(\e$(5!?!h!O!h!M\e(B\\)" "\e$(5$O\e(B")
+    ("\\(\e$(5!?!h!5\e(B\\)" "\e$(5$P\e(B")
+    ("\\(\e$(5!?!h!6\e(B\\)" "\e$(5$Q\e(B")
+    ("\\(\e$(5!?!h!?\e(B\\)" "\e$(5$R\e(B")
+    ("\\(\e$(5!?!h!L\e(B\\)" "\e$(5$S\e(B")
+    ("\\(\e$(5!?!h!M\e(B\\)" "\e$(5$T\e(B")
+    ("\\(\e$(5!?!i\e(B\\)" "\e$(5#?\e(B")                    ; Nukta
+    ("\\(\e$(5!@!h!M\e(B\\)" "\e$(5$`\e(B")
+    ("\\(\e$(5!@!i\e(B\\)" "\e$(5#@\e(B")                    ; Nukta
+    ("\\(\e$(5!A!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"A\e(B")        ;         Half Form
+    ("\\(\e$(5!B!h\e(B\\)\e$(5!B!h!O\e(B" "\e$(5"B\e(B")              ; Special Rule for "t-tr"
+    ("\\(\e$(5!B!h!B!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"c\e(B")    ;         Half Form
+    ("\\(\e$(5!B!h!B\e(B\\)" "\e$(5$a\e(B")
+    ("\\(\e$(5!B!h!F\e(B\\)" "\e$(5$b\e(B")
+    ("\\(\e$(5!B!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"d\e(B")    ;         Half Form   Post "r"
+    ("\\(\e$(5!B!h!O\e(B\\)" "\e$(5"%\e(B")                  ;                     Post "r"
+    ("\\(\e$(5!B!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"B\e(B")        ;         Half Form
+    ("\\(\e$(5!C!h!O\e(B\\)" "\e$(5!C"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!C!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"C\e(B")        ;         Half Form
+    ("\\(\e$(5!D!h!D!h!M\e(B\\)" "\e$(5$c\e(B")
+    ("\\(\e$(5!D!h!E!h!M\e(B\\)" "\e$(5$d\e(B")
+    ("\\(\e$(5!D!h!K!h!M\e(B\\)" "\e$(5$e\e(B")
+    ("\\(\e$(5!D!h!K!h!O\e(B\\)" "\e$(5$r"r\e(B")            ; Special Case for "dbhr" ; ***
+    ("\\(\e$(5!D!h!O!h!M\e(B\\)" "\e$(5$f\e(B")
+    ("\\(\e$(5!D!h!T!h!M\e(B\\)" "\e$(5$g\e(B")
+    ("\\(\e$(5!D!h!5!h!O\e(B\\)" "\e$(5$h\e(B")
+    ("\\(\e$(5!D!h!6!h!O\e(B\\)" "\e$(5$i\e(B")
+    ("\\(\e$(5!D!h!D!h!T\e(B\\)" "\e$(5$j\e(B")
+    ("\\(\e$(5!D!h!E!h!T\e(B\\)" "\e$(5$k\e(B")
+    ("\\(\e$(5!D!h\e(B\\)\e$(5!E!h\e(B[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5!D!h\e(B")  ; Special Half Form (for ddhra)
+    ("\\(\e$(5!D!h!5\e(B\\)" "\e$(5$l\e(B")
+    ("\\(\e$(5!D!h!6\e(B\\)" "\e$(5$m\e(B")
+    ("\\(\e$(5!D!h!D\e(B\\)" "\e$(5$n\e(B")
+    ("\\(\e$(5!D!h!E\e(B\\)" "\e$(5$o\e(B")
+    ("\\(\e$(5!D!h!F\e(B\\)" "\e$(5$p\e(B")
+    ("\\(\e$(5!D!h\e(B\\)\e$(5!J!h\e(B" "\e$(5!D!h\e(B")              ; Suppressing "db-"
+    ("\\(\e$(5!D!h!J\e(B\\)" "\e$(5$q\e(B")
+    ("\\(\e$(5!D!h!K\e(B\\)" "\e$(5$r\e(B")
+    ("\\(\e$(5!D!h!L\e(B\\)" "\e$(5$s\e(B")
+    ("\\(\e$(5!D!h!M\e(B\\)" "\e$(5$t\e(B")
+    ("\\(\e$(5!D!h!T\e(B\\)" "\e$(5$u\e(B")
+    ("\\(\e$(5!E!h!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"e\e(B")    ;         Half Form
+    ("\\(\e$(5!E!h!F\e(B\\)" "\e$(5$v\e(B")
+    ("\\(\e$(5!E!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"f\e(B")    ;         Half Form     Post "r"
+    ("\\(\e$(5!E!h!O\e(B\\)" "\e$(5!E"q\e(B")                ;                       Post "r"
+    ("\\(\e$(5!E!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"E\e(B")        ;         Half Form
+    ("\\(\e$(5!F!h!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"k\e(B")    ;         Half Form
+    ("\\(\e$(5!F!h!F\e(B\\)" "\e$(5$w\e(B")
+    ("\\(\e$(5!F!h!O\e(B\\)" "\e$(5!F"q\e(B")
+    ("\\(\e$(5!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"F\e(B")        ;         Half Form
+    ("\\(\e$(5!G!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"G\e(B")        ; Nukta   Half Form
+    ("\\(\e$(5!H!h\e(B\\)\e$(5!B!h!O\e(B" "\e$(5"H\e(B")              ; Special Rule for "p-tr"
+    ("\\(\e$(5!H!h!B!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"g\e(B")    ;         Half Form
+    ("\\(\e$(5!H!h!B\e(B\\)" "\e$(5$x\e(B")
+    ("\\(\e$(5!H!h!F\e(B\\)" "\e$(5$y\e(B")
+    ("\\(\e$(5!H!h!Q\e(B\\)" "\e$(5$z\e(B")
+    ("\\(\e$(5!H!h!O\e(B\\)" "\e$(5"&\e(B")                  ;                     Post "r"
+    ("\\(\e$(5!H!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"H\e(B")        ;         Half Form
+    ("\\(\e$(5!I!h!O\e(B\\)" "\e$(5"'\e(B")                  ;                     Post "r"
+    ("\\(\e$(5!I!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"I\e(B")        ;         Half Form
+    ("\\(\e$(5!I!i!h!O\e(B\\)" "\e$(5""\e(B")                ; Nukta               Post "r"
+    ("\\(\e$(5!I!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"y\e(B")      ; Nukta   Half Form
+    ("\\(\e$(5!I!i\e(B\\)" "\e$(5#I\e(B")                    ; Nukta
+    ("\\(\e$(5!J!h\e(B\\)\e$(5!F!h\e(B[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"J\e(B")    ; Special Half Form
+    ("\\(\e$(5!J!h!F\e(B\\)" "\e$(5${\e(B")
+    ("\\(\e$(5!J!h\e(B\\)\e$(5!J!h\e(B[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"J\e(B")    ; Special Half Form
+    ("\\(\e$(5!J!h!J\e(B\\)" "\e$(5$|\e(B")
+    ("\\(\e$(5!J!h\e(B\\)\e$(5!T!h\e(B[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"J\e(B")    ; Special Half Form
+    ("\\(\e$(5!J!h!T\e(B\\)" "\e$(5$}\e(B")
+    ("\\(\e$(5!J!h!O\e(B\\)" "\e$(5!J"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!J!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"J\e(B")        ;         Half Form
+    ("\\(\e$(5!K!h!F\e(B\\)" "\e$(5$~\e(B")
+    ("\\(\e$(5!K!h!O\e(B\\)" "\e$(5!K"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!K!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"K\e(B")        ;         Half Form
+    ("\\(\e$(5!L!h!F\e(B\\)" "\e$(5#P\e(B")
+    ("\\(\e$(5!L!h!Q\e(B\\)" "\e$(5#Q\e(B")
+    ("\\(\e$(5!L!h!O\e(B\\)" "\e$(5!L"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!L!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"L\e(B")        ;         Half Form
+    ("\\(\e$(5!M!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"M\e(B")        ;         Half Form
+    ("\\(\e$(5!N!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"N\e(B")        ;         Half Form
+    ;; special form for "ru".
+    ("\\(\e$(5!O!]\e(B\\)" "\e$(5",\e(B")
+    ("\\(\e$(5!O!^\e(B\\)" "\e$(5"-\e(B")
+    ("\\(\e$(5!P!]\e(B\\)" "\e$(5".\e(B")
+    ("\\(\e$(5!P!^\e(B\\)" "\e$(5"/\e(B")
     ;;
-    ;; special forms 
-    ("\\(\e$(5!3!h!V!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"l\e(B")
-    ("\\(\e$(5!:!h!<!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"m\e(B")
-    ;; ordinary forms 
-    ("\\(\e$(5!5!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"`\e(B")
-    ("\\(\e$(5!6!h!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"a\e(B")
-    ;; ("\\(\e$(5!<!h!8!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"c\e(B") ; Mistake, must check later.
-    ("\\(\e$(5!B!h!B!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"c\e(B")
-    ("\\(\e$(5!B!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"d\e(B")
-    ("\\(\e$(5!E!h!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"e\e(B")
-    ("\\(\e$(5!E!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"f\e(B")
-    ("\\(\e$(5!H!h!B!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"g\e(B")
-    ("\\(\e$(5!U!h!8!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"h\e(B")
-    ("\\(\e$(5!U!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"i\e(B")
-    ("\\(\e$(5!U!h!T!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"j\e(B")
-    ;; ("\\(\e$(5!U!h!T!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"k\e(B") ; must check later.
-    ;; Conjunction form associated with Nukta sign.
-    ("\\(\e$(5!3!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"s\e(B")
-    ("\\(\e$(5!4!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"t\e(B")
-    ("\\(\e$(5!5!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"u\e(B")
-    ("\\(\e$(5!:!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"z\e(B")
-    ("\\(\e$(5!I!i!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"y\e(B")
+    ("\\(\e$(5!Q!h!Q\e(B\\)" "\e$(5#`\e(B" sanskrit)
+    ("\\(\e$(5!Q!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"Q\e(B")        ;         Half Form
+    ("\\(\e$(5!R!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"R\e(B")        ;         Half Form
+    ("\\(\e$(5!S!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"S\e(B")        ;         Half Form
+    ("\\(\e$(5!T!h!F\e(B\\)" "\e$(5#a\e(B")
+    ("\\(\e$(5!T!h!T\e(B\\)" "\e$(5#b\e(B")
+    ("\\(\e$(5!T!h!O\e(B\\)" "\e$(5!T"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!T!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"T\e(B")        ;         Half Form
+    ("\\(\e$(5!U!h!8!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"h\e(B")    ;         Half Form
+    ("\\(\e$(5!U!h!8\e(B\\)" "\e$(5#c\e(B")
+    ("\\(\e$(5!U!h!F\e(B\\)" "\e$(5#d\e(B")
+    ("\\(\e$(5!U!h!J\e(B\\)" "\e$(5#e\e(B")
+    ("\\(\e$(5!U!h!Q\e(B\\)" "\e$(5#f\e(B")
+    ("\\(\e$(5!U!h\e(B\\)\e$(5!T!h!O\e(B" "\e$(5"U\e(B")              ; Special Half Form
+    ("\\(\e$(5!U!h!T!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"j\e(B")    ;         Half Form
+;   ("\\(\e$(5!U!h!T\e(B\\)" "\e$(5#g\e(B")
+    ("\\(\e$(5!U!h!O!h!T\e(B\\)" "\e$(5#g\e(B")
+    ("\\(\e$(5!U!h!O!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"i\e(B")    ;         Half Form
+    ("\\(\e$(5!U!h!O\e(B\\)" "\e$(5")\e(B")             ;                     Post "r"
+    ("\\(\e$(5!U!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"U\e(B")        ;         Half Form
+    ("\\(\e$(5!V!h!=!h!O!h!M\e(B\\)" "\e$(5#h\e(B")
+    ("\\(\e$(5!V!h!=!h!M\e(B\\)" "\e$(5#i\e(B")
+    ("\\(\e$(5!V!h!=!h!T\e(B\\)" "\e$(5#j\e(B")
+    ("\\(\e$(5!V!h!=\e(B\\)" "\e$(5#k\e(B")
+    ("\\(\e$(5!V!h!>\e(B\\)" "\e$(5#l\e(B")
+    ("\\(\e$(5!V!h!O\e(B\\)" "\e$(5!V"q\e(B")                ;                     Post "r"
+    ("\\(\e$(5!V!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"V\e(B")        ;         Half Form
+    ("\\(\e$(5!W!h!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"W"F\e(B")  ; Special Half Form
+    ("\\(\e$(5!W!h!F\e(B\\)" "\e$(5#m\e(B")
+    ("\\(\e$(5!W!h!O\e(B\\)" "\e$(5#n\e(B")
+    ("\\(\e$(5!W!h\e(B\\)[\e$(5!3\e(B-\e$(5!N!P\e(B-\e$(5!X\e(B]" "\e$(5"W\e(B")        ;         Half Form
+    ("\\(\e$(5!X!h!A\e(B\\)" "\e$(5#p\e(B")
+    ("\\(\e$(5!X!h!F\e(B\\)" "\e$(5#q\e(B")
+    ("\\(\e$(5!X!h!L\e(B\\)" "\e$(5#r\e(B")
+    ("\\(\e$(5!X!h!M\e(B\\)" "\e$(5#s\e(B")
+    ("\\(\e$(5!X!h!O\e(B\\)" "\e$(5#t\e(B")
+    ("\\(\e$(5!X!h!Q\e(B\\)" "\e$(5#u\e(B")
+    ("\\(\e$(5!X!h!T\e(B\\)" "\e$(5#v\e(B")
+    ;; Special Ligature Rules 
+    ("\\(\e$(5!X!_\e(B\\)" "\e$(5#R\e(B")
 
     ;; For consonants other than listed above, glyph-composition will
     ;; be applied.  If the consonant which is preceding "\e$(5!O\e(B" does not
     ;; have the vertical line (such as "\e$(5!?\e(B"), "\e$(5"r\e(B" is put beneath the
     ;; consonant.
     ;;
-    ;; ("cons-not-yet-listed-up\\(\e$(5!h!O\e(B\\)" . "\e$(5"q\e(B")
-    ("[\e$(5!7!9!=!>!?!@!D!O!P!R!S!X\e(B]\\(\e$(5!h!O\e(B\\)" . "\e$(5"r\e(B")
-    ("\e$(5!?!i\e(B\\(\e$(5!h!O\e(B\\)" . "\e$(5"r\e(B")
-    ("\e$(5!@!i\e(B\\(\e$(5!h!O\e(B\\)" . "\e$(5"r\e(B")
-
-    ;; Nukta 
-    ("\\(\e$(5!!!i\e(B\\)" . "\e$(5#!\e(B")
-    ("\\(\e$(5!&!i\e(B\\)" . "\e$(5#&\e(B")
-    ("\\(\e$(5!'!i\e(B\\)" . "\e$(5#'\e(B")
-    ("\\(\e$(5!*!i\e(B\\)" . "\e$(5#*\e(B")
-    ("\\(\e$(5!3!i\e(B\\)" . "\e$(5#3\e(B")
-    ("\\(\e$(5!4!i\e(B\\)" . "\e$(5#4\e(B")
-    ("\\(\e$(5!5!i\e(B\\)" . "\e$(5#5\e(B")
-    ("\\(\e$(5!:!i\e(B\\)" . "\e$(5#:\e(B")
-    ("\\(\e$(5!?!i\e(B\\)" . "\e$(5#?\e(B")
-    ("\\(\e$(5!@!i\e(B\\)" . "\e$(5#@\e(B")
-    ("\\(\e$(5!I!i\e(B\\)" . "\e$(5#I\e(B")
-    ("\\(\e$(5!j!i\e(B\\)" . "\e$(5#J\e(B")
-
-    ;; Half forms.
-    ("\\(\e$(5!3!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"3\e(B")
-    ("\\(\e$(5!4!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"4\e(B")
-    ("\\(\e$(5!5!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"5\e(B")
-    ("\\(\e$(5!6!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"6\e(B")
-    ("\\(\e$(5!8!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"8\e(B")
-    ("\\(\e$(5!:!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5":\e(B")
-    ("\\(\e$(5!;!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5";\e(B")
-    ("\\(\e$(5!<!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"<\e(B")
-    ("\\(\e$(5!A!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"A\e(B")
-    ("\\(\e$(5!B!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"B\e(B")
-    ("\\(\e$(5!C!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"C\e(B")
-    ("\\(\e$(5!E!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"E\e(B")
-    ("\\(\e$(5!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"F\e(B")
-    ("\\(\e$(5!G!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"G\e(B")
-    ("\\(\e$(5!H!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"H\e(B")
-    ("\\(\e$(5!I!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"I\e(B")
-    ("\\(\e$(5!J!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"J\e(B")
-    ("\\(\e$(5!K!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"K\e(B")
-    ("\\(\e$(5!L!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"L\e(B")
-    ("\\(\e$(5!M!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"M\e(B")
-    ("\\(\e$(5!N!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"N\e(B")
-    ("\\(\e$(5!Q!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"Q\e(B")
-    ("\\(\e$(5!R!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"R\e(B")
-    ("\\(\e$(5!S!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"S\e(B")
-    ("\\(\e$(5!T!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"T\e(B")
-    ("\\(\e$(5!U!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"U\e(B")
-    ("\\(\e$(5!V!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"V\e(B")
-    ("\\(\e$(5!W!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"W\e(B")
+    ("[\e$(5!7!9!=!>!?!@!D!O!P!R!S!X\e(B]\\(\e$(5!h!O\e(B\\)" "\e$(5"r\e(B")
+    ("[\e$(5!6!8!C!E!F!H!J!K!L!M!T!V\e(B]\\(\e$(5!h!O\e(B\\)" "\e$(5"q\e(B")
+    ("\e$(5!?!i\e(B\\(\e$(5!h!O\e(B\\)" "\e$(5"r\e(B")
+    ("\e$(5!@!i\e(B\\(\e$(5!h!O\e(B\\)" "\e$(5"r\e(B")
+
+    ;; Nukta with Non-Consonants
+    ("\\(\e$(5!!!i\e(B\\)" "\e$(5#!\e(B")
+    ("\\(\e$(5!&!i\e(B\\)" "\e$(5#&\e(B")
+    ("\\(\e$(5!'!i\e(B\\)" "\e$(5#'\e(B")
+    ("\\(\e$(5!*!i\e(B\\)" "\e$(5#*\e(B")
+    ("\\(\e$(5![!i\e(B\\)" "\e$(5#L\e(B")
+    ("\\(\e$(5!\!i\e(B\\)" "\e$(5#M\e(B")
+    ("\\(\e$(5!_!i\e(B\\)" "\e$(5#K\e(B")
+    ("\\(\e$(5!j!i\e(B\\)" "\e$(5#J\e(B")
+
+    ;; Special rule for "r + some vowels"
+    ("\\(\e$(5!O!_\e(B\\)" "\e$(5!*"p\e(B")
+    ("\\(\e$(5!O#L\e(B\\)" "\e$(5#&"p\e(B")
+    ("\\(\e$(5!O#K\e(B\\)" "\e$(5#*"p\e(B")
+    ("\\(\e$(5!O#M\e(B\\)" "\e$(5#'"p\e(B")
+    ;; If everything fails, "y" will connect to the front consonant.
+    ("\\(\e$(5!h!M\e(B\\)" "\e$(5"]\e(B")
     )
   "Alist of regexps of Devanagari character sequences vs composed characters.")
 
-;; Example:
-;;("\\(\e$(5!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" . "\e$(5"F\e(B")
-;;(string-match "\\(\e$(5!F!h\e(B\\)[\e$(5!3\e(B-\e$(5!X\e(B]" "\e$(5!X![!F!h!D!\\e(B") => 8
-;;(match-end 1) => 16
-
-;;
-;; Defining character properties : char-to-glyph, glyph-to-char
-;;
-;; *  If char-to-glyph is non-nil, it would be one of the following forms.
-;;
-;;  (("character-regexp" . "glyphs")
-;;   .....) or
-;;  (("character-regexp" . ?glyph)
-;;   .....) or
-;;  ("characters-regexp" . "glyphs")
-;;  or
-;;  ?glyph
-;;
-;; *  If glyph-to-char is non-nil, it would be one of the following forms.
-;;
-;;  (("glyph-regexp" . "characters")  ;; This is the only case in Devanagari
-;;   ....) or
-;;  (("glyph-regexp" . ?character)
-;;   ....) or
-;;  ("glyph-regexp" . "characters")
-;;    or
-;;  "characters"
-;;    or
-;;  ?character  
-;;
-
 (let ((rules devanagari-char-to-glyph-rules))
   (while rules
     (let ((rule (car rules)) 
-         (chars) (char) (glyph))
+         (chars) (char) (glyphs) (glyph))
       (setq rules (cdr rules))
       (string-match "\\\\(\\(.+\\)\\\\)" (car rule))
       (setq chars (substring (car rule) (match-beginning 1) (match-end 1)))
       (setq char (string-to-char chars))
-      (setq glyph (string-to-char (cdr rule))) ; assume one glyph in devan.
+      (setq glyphs (cdr rule))
+      (setq glyph (string-to-char (car glyphs)))
       (put-char-code-property 
-         char 'char-to-glyph 
-        (append (get-char-code-property char 'char-to-glyph) (list rule)))
-      (put-char-code-property glyph 'glyph-to-char chars))))
+       char 'char-to-glyph 
+       ;; We don't "cons" it since priority is top to down.
+       (append (get-char-code-property char 'char-to-glyph) (list rule)))
+
+      (if (and (< ?\e(5z\e(B glyph) ; Glyphs only.
+              (null (get-char-code-property glyph 'glyph-to-char)))
+              ; One glyph may corresponds to multiple characters, 
+              ; e.g., surrounding vowel in Tamil, etc.
+              ; but for Devanagari, we put this restriction
+              ; to make sure the fact that one glyph corresponds to one char.
+         (put-char-code-property 
+          glyph 'glyph-to-char 
+          (cons (list (car glyphs) chars)
+                (get-char-code-property glyph 'glyph-to-char)
+          ))))))
 
 ;;
-;; Convert Character Code to Glyph Code
+;; Function used in both characters-to-glyphs conversion and
+;; glyphs-to-characters conversion.
 ;;
 
-;;;###autoload
-(defun char-to-glyph-devanagari (src-str)
-  "Convert Devanagari characters in the string to Devanagari glyphs.  
-Ligatures and special rules are processed."
+(defun max-match-len (regexp-str)
+  "This returns the possible length of matched string of given regexp.
+   Only [...] pattern of regexp is recognized.  The last character of
+   inside of [....] is used for its length."
+  (let ((dest-str regexp-str))
+    (while (string-match "\\[\\([^\]]\\)+\\]" dest-str)
+      (setq dest-str 
+           (concat (substring dest-str 0 (match-beginning 0))
+                   (substring dest-str (match-beginning 1) (match-end 1))
+                   (substring dest-str (match-end 0)))))
+    (length dest-str)))
+
+(defun string-conversion-by-rule (src-str symbol &rest specs)
+  " This function converts the SRC-STR to the new string according to
+the rules described in the each character's SYMBOL property.  The
+rules are described in the forms of '((regexp str <specs>) ...), and
+the character sequence in the string which matches to 'regexp' are
+replaced with str.  If SPECS are not specified, only rules with no
+<specs> would be applied.  If SPECS are specified, then rules with no
+<specs> specified and rules with <spec> matches with SPECS would be
+applied.  Rules are tested in the order of the list, thus more
+specific rules should be placed in front of less important rules.  No
+composite character is supported, thus such must be converted by
+decompose-char before applying to this function.  If rule is given in
+the forms of regexp '...\\(...\\)...', then inside the parenthesis is
+the subject of the match.  Otherwise, the entire expression is the
+subject of the match."
   (let ((pos 0) 
        (dst-str ""))
     (while (< pos (length src-str))
       (let ((found nil)
            (rules (get-char-code-property 
                    (string-to-char 
-                    ;; caution. other forms not supported for now.
-                    (substring src-str pos)) 'char-to-glyph)))
+                    (substring src-str pos)) symbol)))
        (while rules
          (let* ((rule (car rules))
-                (regexp (car rule)))
-           (if (string-match regexp src-str)
-               (if (= (match-beginning 1) pos)
-                   (progn
-                     (setq dst-str (concat dst-str (cdr rule)))
-                     (setq rules nil) ; Get out of the loop.
-                     (setq found t)
-                     ;; proceed `pos' for replaced characters.
-                     (setq pos (match-end 1)))
-                 (setq rules (cdr rules)))
-             (setq rules (cdr rules)))))
+                (regexp (car rule))
+                (replace-str (car (cdr rule)))
+                (rule-specs (cdr (cdr rule)))
+                search-pos)
+           (if (not (or (null rule-specs)
+                        (intersection specs rule-specs)))
+               (setq rules (cdr rules))
+             (if (null (string-match "\\\\(.+\\\\)" regexp))
+                 (progn
+                   (setq regexp (concat "\\(" regexp "\\)"))
+                   (setq search-pos pos))
+               (setq search-pos (- pos (max-match-len 
+                                        (substring regexp
+                                                   (string-match "^[^\\\\]*" regexp)
+                                                   (match-end 0))))))
+             (if (< search-pos 0) (setq search-pos 0))
+             (if (string-match regexp src-str search-pos)
+                 (if (= (match-beginning 1) pos)
+                     (progn
+                       (setq dst-str (concat dst-str replace-str))
+                       (setq rules nil) ; Get out of the loop.
+                       (setq found t)
+                       ;; proceed `pos' for replaced characters.
+                       (setq pos (match-end 1)))
+                   (setq rules (cdr rules)))
+               (setq rules (cdr rules))))))
        ;; proceed to next position
        (if (not found)
            (let ((nextchar (string-to-char (substring src-str pos))))
@@ -533,6 +631,19 @@ Ligatures and special rules are processed."
              (setq dst-str (concat dst-str (char-to-string nextchar)))))))
     dst-str))
 
+
+;;
+;; Convert Character Code to Glyph Code
+;;
+
+;;;###autoload
+(defun char-to-glyph-devanagari (src-str &rest langs)
+  "Convert Devanagari characters in the string to Devanagari glyphs.  
+Ligatures and special rules are processed."
+  (apply 
+   'string-conversion-by-rule 
+   (append (list src-str 'char-to-glyph) langs)))
+
 ;; Example:
 ;;(char-to-glyph-devanagari "\e$(5!X![!F!h!D!\\e(B") => "\e$(5!X!["F!D!\\e(B"
 ;;(char-to-glyph-devanagari "\e$(5!O!Z!V!h!=!h!O![!M\e(B") => ???
@@ -548,9 +659,9 @@ Ligatures and special rules are processed."
 ;; If application-direction is omitted, it is asumbed to be '(mr . ml).
 
 (defconst devanagari-composition-rules
-  '((?\e$(5!!\e(B 60 (tr . br))
-    (?\e$(5!"\e(B 60 (tr . br))
-    (?\e$(5!#\e(B 60)
+  '((?\e$(5!!\e(B 0 (tr . br))
+    (?\e$(5!"\e(B 0 (mr . mr))
+    (?\e$(5!#\e(B 0)
     (?\e$(5!$\e(B 0)
     (?\e$(5!%\e(B 0)
     (?\e$(5!&\e(B 0)
@@ -605,22 +716,22 @@ Ligatures and special rules are processed."
     (?\e$(5!W\e(B 0)
     (?\e$(5!X\e(B 0)
     (?\e$(5!Y\e(B 0)
-    (?\e$(5!Z\e(B 40)
-    (?\e$(5![\e(B 40 (ml . mr))
-    (?\e$(5!\\e(B 40)
-    (?\e$(5!]\e(B 40 (bc . tc))
-    (?\e$(5!^\e(B 40 (bc . tc))
-    (?\e$(5!_\e(B 40 (bc . tc))
-    (?\e$(5!`\e(B 40 (tc . bc))
-    (?\e$(5!a\e(B 40 (tc . bc))
-    (?\e$(5!b\e(B 40 (tc . bc))
-    (?\e$(5!c\e(B 40 (tc . bc))
-    (?\e$(5!d\e(B 40)
-    (?\e$(5!e\e(B 40)
-    (?\e$(5!f\e(B 40)
-    (?\e$(5!g\e(B 40)
-    (?\e$(5!h\e(B 0 (br . tr))                   ; Halant's special treatment.
-    (?\e$(5!i\e(B 0 (br . tr))                   ; Nukta's special treatment.
+    (?\e$(5!Z\e(B 0)
+    (?\e$(5![\e(B 0 (ml . mr))
+    (?\e$(5!\\e(B 0)
+    (?\e$(5!]\e(B 0 (br . tr))
+    (?\e$(5!^\e(B 0 (br . tr))
+    (?\e$(5!_\e(B 0 (br . tr))
+    (?\e$(5!`\e(B 0 (mr . mr))  ; (tc . bc)
+    (?\e$(5!a\e(B 0 (mr . mr))
+    (?\e$(5!b\e(B 0 (mr . mr))
+    (?\e$(5!c\e(B 0 (mr . mr))
+    (?\e$(5!d\e(B 0)
+    (?\e$(5!e\e(B 0)
+    (?\e$(5!f\e(B 0)
+    (?\e$(5!g\e(B 0)
+    (?\e$(5!h\e(B 0 (br . tr))
+    (?\e$(5!i\e(B 0 (br . tr))
     (?\e$(5!j\e(B 0)
     (nil 0)
     (nil 0)
@@ -721,9 +832,9 @@ Ligatures and special rules are processed."
     (?\e$(5"m\e(B 0)
     (?\e$(5"n\e(B 0)
     (?\e$(5"o\e(B 0)
-    (?\e$(5"p\e(B 20 (tr . br))
-    (?\e$(5"q\e(B 20 (br . tr))
-    (?\e$(5"r\e(B 20 (br . tr))
+    (?\e$(5"p\e(B 10 (mr . mr))
+    (?\e$(5"q\e(B 0 (br . br))
+    (?\e$(5"r\e(B 0 (br . tr))
     (?\e$(5"s\e(B 0)
     (?\e$(5"t\e(B 0)
     (?\e$(5"u\e(B 0)
@@ -778,9 +889,9 @@ Ligatures and special rules are processed."
     (?\e$(5#H\e(B 0)
     (?\e$(5#I\e(B 0)
     (?\e$(5#J\e(B 0)
-    (?\e$(5#K\e(B 0)
-    (?\e$(5#L\e(B 0)
-    (?\e$(5#M\e(B 0)
+    (?\e$(5#K\e(B 0 (br . tr))
+    (?\e$(5#L\e(B 0 (br . tr))
+    (?\e$(5#M\e(B 0 (br . tr))
     (?\e$(5#N\e(B 0)
     (?\e$(5#O\e(B 0)
     (?\e$(5#P\e(B 0)
@@ -929,11 +1040,7 @@ Ligatures and special rules are processed."
 ;; Determine composition priority and rule of the array of Glyphs.
 ;; Sort the glyphs with their priority.
 
-;; Example:
-;;(devanagari-reorder-glyph-for-composition '[?\e$(5"5\e(B ?\e$(5!X\e(B ?\e$(5![\e(B])
-;;     => ((446680 0) (446773 0) (446683 50 (ml . mr)))
-
-(defun devanagari-reorder-glyph-for-composition (glyph-alist)
+(defun devanagari-reorder-glyphs-for-composition (glyph-alist)
   (let* ((pos 0)
         (ordered-glyphs '()))
     (while (< pos (length glyph-alist))
@@ -946,7 +1053,7 @@ Ligatures and special rules are processed."
 ;;(devanagari-compose-to-one-glyph "\e$(5"5!X![\e(B") => "\e2\e$(6!XP"5@![\e1\e(B"
 
 (defun devanagari-compose-to-one-glyph (devanagari-string)
-  (let* ((o-glyph-list (devanagari-reorder-glyph-for-composition
+  (let* ((o-glyph-list (devanagari-reorder-glyphs-for-composition
                        (string-to-vector devanagari-string)))
         ;; List of glyphs to be composed.
         (cmp-glyph-list (list (car (car o-glyph-list)))) 
@@ -966,6 +1073,19 @@ Ligatures and special rules are processed."
     (if (= (length cmp-glyph-list) 1) (char-to-string (car cmp-glyph-list))
       (apply 'compose-chars cmp-glyph-list))))
 
+;; Utility function for Phase 2.5
+;; Check whether given glyph is a Devanagari vertical modifier or not.
+;; If it is a vertical modifier, whether it should be 1-column shape or not
+;; depends on previous non-vertical modifier.
+   ; return nil if it is not vertical modifier.
+(defun devanagari-vertical-modifier-p (glyph)
+  (string-match (char-to-string glyph)
+               "[\e$(5!]!^!_!`!a!b!c!h!i"p"q"r#K#L#M\e(B]"))
+
+(defun devanagari-non-vertical-modifier-p (glyph)
+  (string-match (char-to-string glyph)
+               "[\e$(5!Z![!\!d!e!f!g\e(B]"))
+
 
 ;;
 ;;    Phase 2.5  Convert Appropriate Character to 1-column shape.
@@ -981,91 +1101,55 @@ Ligatures and special rules are processed."
 ;;   with 2 column base-glyph.
 ;;
 ;; Execution Examples
-;;(devanagari-wide-to-narrow '(446680 446773 (ml . mr) 446683))
-;;(devanagari-wide-to-narrow '(?\e$(5!6\e(B (ml . ml) 446773 (tc . mr) 446683))
+;;(devanagari-wide-to-narrow '(?\e$(5!3\e(B (ml . ml) ?\e$(5!a\e(B))
+;;(devanagari-wide-to-narrow '(?\e$(5!F\e(B (ml . ml) ?\e$(5!a\e(B))
+
+;(defun devanagari-wide-to-narrow (src-list)
+;  (if (null src-list) '()
+;    (cons 
+;     (if (and (numberp (car src-list))
+;            (cdr (assq (car src-list) devanagari-1-column-char)))
+;       (cdr (assq (car src-list) devanagari-1-column-char))
+;       (car src-list))
+;     (devanagari-wide-to-narrow (cdr src-list)))))
 
 (defun devanagari-wide-to-narrow (src-list)
-  (if (null src-list) '()
-    (cons 
-     (if (and (numberp (car src-list))
-             (cdr (assq (car src-list) devanagari-1-column-char)))
-        (cdr (assq (car src-list) devanagari-1-column-char))
-       (car src-list))
-     (devanagari-wide-to-narrow (cdr src-list)))))
-
-;; Make this function obsolete temporary Because now Emacs supports
-;; attaching 1 column character at the center 2 column char.  However,
-;; there are still problems attempting to attach Halant or Nukta sign
-;; at the non-vowel consonant.  This problem can not be solved until
-;; Emacs supports attaching the glyph at `temporary-preserved metric'.
-
-(defun devanagari-wide-to-narrow-old (src-list)
-  (if (null src-list) (progn (error "devanagari-wide-to-narrow error") nil)
-    (let* ((base-glyph (cdr (assq (car src-list) devanagari-1-column-char)))
-          (wide-base-glyph nil)
-          (apply-glyph-list (cdr src-list)))
-      (if (null base-glyph)
-         (progn 
-           (setq wide-base-glyph t)
-           (setq base-glyph (car src-list))))
-      (cons base-glyph
-           (devanagari-wide-to-narrow-iter apply-glyph-list wide-base-glyph))
-      )))
-
-;; Convert apply-glyph-list from 2-column to 1-column.
-;;   wide-base-glyph is t when base-glyph is 2-column.
-;;   When apply-glyph is put at the top or bottom of 2-column base-glyph,
-;;   they must be 2-column glyph, too.  Otherwise, they will be 
-;;   converted to 1-column glyph if possible.
-
-(defun devanagari-wide-to-narrow-iter (apply-glyph-list wide-base-glyph)
-  (if (< (length apply-glyph-list) 2) '()
-    (let* ((apply-dir    (car apply-glyph-list))
-          (apply-glyph  (car (cdr apply-glyph-list)))
-          (apply-rest   (cdr (cdr apply-glyph-list)))
-          (put-t-or-b   (member (car apply-dir) '(tl tc tr bl bc br)))
-          (narrow-glyph (cdr (assq apply-glyph devanagari-1-column-char))))
-      (append 
-       (list apply-dir
-            (if (or (and wide-base-glyph put-t-or-b)
-                    (null narrow-glyph))
-                apply-glyph narrow-glyph))
-       (devanagari-wide-to-narrow-iter apply-rest wide-base-glyph)))))
+  (devanagari-wide-to-narrow-iter src-list t))
+
+(defun devanagari-wide-to-narrow-iter (src-list wide-p)
+  (let ((glyph (car src-list)))
+    (cond ((null src-list) '())
+         ; not glyph code
+         ((not (numberp glyph)) 
+          (cons glyph (devanagari-wide-to-narrow-iter (cdr src-list) wide-p)))
+         ; vertical modifier glyph
+         ((devanagari-vertical-modifier-p glyph)
+          (if (and (null wide-p)
+                   (cdr (assq glyph devanagari-1-column-char)))
+              (cons (cdr (assq glyph devanagari-1-column-char))
+                    (devanagari-wide-to-narrow-iter (cdr src-list) nil))
+              (cons glyph
+                    (devanagari-wide-to-narrow-iter (cdr src-list) t))))
+         ; nonvertical modifier glyph
+         ((devanagari-non-vertical-modifier-p glyph)
+          (if (cdr (assq glyph devanagari-1-column-char))
+              (cons (cdr (assq glyph devanagari-1-column-char))
+                    (devanagari-wide-to-narrow-iter (cdr src-list) wide-p))
+              (cons glyph
+                    (devanagari-wide-to-narrow-iter (cdr src-list) wide-p))))
+         ; normal glyph
+         (t
+          (if (cdr (assq glyph devanagari-1-column-char))
+              (cons (cdr (assq glyph devanagari-1-column-char))
+                    (devanagari-wide-to-narrow-iter (cdr src-list) nil))
+              (cons glyph
+                    (devanagari-wide-to-narrow-iter (cdr src-list) t)))))))
+
 
 ;;
 ;; Summary
 ;; 
 
-;;;###autoload
-(defun devanagari-compose-string (str)
-  (let ((len (length str))
-       (src str) (dst "") rest match-b match-e)
-    (while (string-match devanagari-composite-glyph-unit-examine src)
-      (setq match-b (match-beginning 0) match-e (match-end 0))
-      (setq dst 
-           (concat dst 
-                   (substring src 0 match-b)
-                   (devanagari-compose-to-one-glyph 
-                    (char-to-glyph-devanagari
-                     (substring src match-b match-e)))))
-      (setq src (substring src match-e)))
-    (setq dst (concat dst src))
-    dst))
-
-;;;###autoload
-(defun devanagari-compose-region (from to)
-  (interactive "r")
-  (save-restriction
-    (narrow-to-region from to)
-    (goto-char (point-min))
-    (while (re-search-forward devanagari-composite-glyph-unit-examine nil t)
-      (let* ((match-b (match-beginning 0)) (match-e (match-end 0))
-            (cmps (devanagari-compose-to-one-glyph
-                   (char-to-glyph-devanagari
-                    (buffer-substring match-b match-e)))))
-       (delete-region match-b match-e)
-       (insert cmps)))))
-
 ;;
 ;; Decomposition of composite font.
 ;;
@@ -1078,12 +1162,12 @@ Ligatures and special rules are processed."
 
 (defvar devanagari-decomposition-rules
   '(
-    (?\e$(5"p\e(B -20)
+    (?\e$(5"p\e(B -10)
     )
   )
 
-(defun devanagari-reorder-glyph-for-decomposition (glyphlist)
-  "This function re-orders glyph list."
+(defun devanagari-reorder-glyphs-for-decomposition (glyphlist)
+  "This function re-orders glyph list for decomposition."
   (sort glyphlist 
        '(lambda (x y) 
           (let ((xx (assoc x devanagari-decomposition-rules))
@@ -1092,18 +1176,17 @@ Ligatures and special rules are processed."
             (if (null yy) (setq yy 0))
             (< xx yy)))))
 
-(defun devanagari-decompose-char (char)
-  "This function decomposes one Devanagari composite character to 
-   basic Devanagari character."
-  (let ((glyphlist (decompose-composite-char char)))
-    (if (not (listp glyphlist)) 
-       (setq glyphlist (list glyphlist)))
+(defun devanagari-decompose-char (glyph)
+  "This function decomposes one Devanagari composite glyph to 
+   basic Devanagari characters as a string."
+  (let ((glyphlist 
+        (if (eq (car (split-char glyph)) 'composition) 
+            (string-to-list (decompose-composite-char glyph))
+          (list glyph))))
     (setq glyphlist (devanagari-normalize-narrow-glyph glyphlist))
-    (mapconcat '(lambda (x) (let ((char (get-char-code-property 
-                                        x 'glyph-to-char)))
-                          (if (null char) (char-to-string x) char)))
-              (devanagari-reorder-glyph-for-decomposition glyphlist)
-              "")))
+    (setq glyphlist (devanagari-reorder-glyphs-for-decomposition glyphlist))
+    (string-conversion-by-rule 
+     (mapconcat 'char-to-string glyphlist "") 'glyph-to-char)))
 
 ;;;###autoload
 (defun devanagari-decompose-string (str)
@@ -1130,7 +1213,43 @@ basic Devanagari character string."
        (delete-char -1)
        (insert decmps)))))
 
+;;;
+;;; Composition
+;;;
+
+;;;###autoload
+(defun devanagari-compose-string (str &rest langs)
+  (let ((len (length str))
+       (src (devanagari-decompose-string str)) (dst "") rest match-b match-e)
+    (while (string-match devanagari-composite-glyph-unit src)
+      (setq match-b (match-beginning 0) match-e (match-end 0))
+      (setq dst 
+           (concat dst 
+                   (substring src 0 match-b)
+                   (devanagari-compose-to-one-glyph 
+                    (apply 
+                     'char-to-glyph-devanagari
+                     (cons (substring src match-b match-e)
+                           langs)))))
+      (setq src (substring src match-e)))
+    (setq dst (concat dst src))
+    dst))
 
+;;;###autoload
+(defun devanagari-compose-region (from to &rest langs)
+  (interactive "r")
+  (save-restriction
+    (narrow-to-region from to)
+    (goto-char (point-min))
+    (while (re-search-forward devanagari-composite-glyph-unit nil t)
+      (let* ((match-b (match-beginning 0)) (match-e (match-end 0))
+            (cmps (devanagari-compose-to-one-glyph
+                   (apply 
+                    'char-to-glyph-devanagari
+                    (cons (buffer-substring match-b match-e)
+                          langs)))))
+       (delete-region match-b match-e)
+       (insert cmps)))))
 
 ;; For pre-write and post-read conversion
 
@@ -1138,10 +1257,20 @@ basic Devanagari character string."
 (defun devanagari-compose-from-is13194-region (from to)
   "Compose IS 13194 characters in the region to Devanagari characters."
   (interactive "r")
-  (save-restriction
-    (narrow-to-region from to)
-    (indian-to-devanagari-region (point-min) (point-max))
-    (devanagari-compose-region (point-min) (point-max))))
+  (save-excursion
+    (save-restriction
+      (narrow-to-region from to)
+      (indian-to-devanagari-region (point-min) (point-max))
+      (devanagari-compose-region (point-min) (point-max))
+      (- (point-max) (point-min)))))
+
+;;;###autoload
+(defun in-is13194-devanagari-post-read-conversion (len)
+  (let ((pos (point))
+       (buffer-modified-p (buffer-modified-p)))
+    (prog1
+       (devanagari-compose-from-is13194-region pos (+ pos len))
+      (set-buffer-modified-p buffer-modified-p))))
 
 ;;;###autoload
 (defun devanagari-decompose-to-is13194-region (from to)
@@ -1152,10 +1281,40 @@ basic Devanagari character string."
     (devanagari-decompose-region (point-min) (point-max))
     (devanagari-to-indian-region (point-min) (point-max))))
 
+;;;###autoload
+(defun in-is13194-devanagari-pre-write-conversion (from to)
+  (let ((old-buf (current-buffer))
+       (work-buf (get-buffer-create " *devanagari-work*")))
+    (set-buffer work-buf)
+    (erase-buffer)
+    (if (stringp from)
+       (insert from)
+      (insert-buffer-substring old-buf from to))
+    (devanagari-decompose-to-is13194-region (point-min) (point-max))
+    ;; Should return nil as annotations.
+    nil))
+
+;; For input/output of ITRANS
+
+;;;###autoload
+(defun devanagari-encode-itrans-region (from to)
+  (interactive "r")
+  (save-restriction
+    (narrow-to-region from to)
+    (devanagari-decompose-to-is13194-region (point-min) (point-max))
+    (indian-encode-itrans-region (point-min) (point-max))))
+
+;;;###autoload
+(defun devanagari-decode-itrans-region (from to)
+  (interactive "r")
+  (save-restriction
+    (narrow-to-region from to)
+    (indian-decode-itrans-region (point-min) (point-max))
+    (devanagari-compose-from-is13194-region (point-min) (point-max))))
+
+;; Test comment.
+
 ;;
-(provide 'language/devan-util)
+(provide 'devan-util)
 
-;;; Local Variables:
-;;; generated-autoload-file: "../loaddefs.el"
-;;; End:
-;;; devan-util.el ends here
+;;; devan-util.el end here