comparison lisp/language/ethio-util.el @ 17299:1d2c8b8a2875

Completely updated.
author Kenichi Handa <handa@m17n.org>
date Sat, 05 Apr 1997 02:40:11 +0000
parents 70194012fb3a
children f438ebf1c679
comparison
equal deleted inserted replaced
17298:0c7ab61707c4 17299:1d2c8b8a2875
1 ;; ethio-util.el -- utilities for Ethiopic 1 ;; ethio-util.el -- utilities for Ethiopic
2 2
3 ;; Copyright (C) 1995 Free Software Foundation, Inc. 3 ;; Copyright (C) 1995 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Electrotechnical Laboratory, JAPAN. 4 ;; Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
5 5
6 ;; Keywords: mule, multilingual, Chinese 6 ;; Keywords: mule, multilingual, Ethiopic
7 7
8 ;; This file is part of GNU Emacs. 8 ;; This file is part of GNU Emacs.
9 9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify 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 11 ;; it under the terms of the GNU General Public License as published by
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details. 18 ;; GNU General Public License for more details.
19 19
20 ;; You should have received a copy of the GNU General Public License 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 21 ;; along with GNU Emacs; see the file COPYING. If not, write to
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 ;; Boston, MA 02111-1307, USA. 23
24 ;; Author: TAKAHASHI Naoto <ntakahas@etl.go.jp>
24 25
25 ;;; Code: 26 ;;; Code:
26 27
27 ;; 28 ;;
28 ;; ETHIOPIC UTILITY FUNCTIONS 29 ;; ETHIOPIC UTILITY FUNCTIONS
29 ;; 30 ;;
30 31
32 ;; If the filename ends in ".sera", editing is done in fidel
33 ;; but file I/O is done in SERA.
34 ;;
35 ;; If the filename ends in ".java", editing is done in fidel
36 ;; but file I/O is done in the \uXXXX style, where XXXX is
37 ;; the Unicode codepoint for the Ethiopic character.
38 ;;
39 ;; If the filename ends in ".tex", editing is done in fidel
40 ;; but file I/O is done in EthioTeX format.
41 ;;
31 ;; To automatically convert Ethiopic text to SERA format when sending mail, 42 ;; To automatically convert Ethiopic text to SERA format when sending mail,
32 ;; (add-hook 'mail-send-hook 'fidel-to-sera-mail) 43 ;; (add-hook 'mail-send-hook 'ethio-fidel-to-sera-mail)
33 ;; 44 ;;
34 ;; To automatically convert SERA format to Ethiopic when receiving mail, 45 ;; To automatically convert SERA format to Ethiopic when receiving mail,
35 ;; (add-hook 'rmail-show-message-hook 'sera-to-fidel-mail) 46 ;; (add-hook 'rmail-show-message-hook 'ethio-sera-to-fidel-mail)
36 ;; 47 ;;
37 ;; To automatically convert Ethiopic text to SERA format when posting news, 48 ;; To automatically convert Ethiopic text to SERA format when posting news,
38 ;; (add-hook 'news-inews-hook 'fidel-to-sera-mail) 49 ;; (add-hook 'news-inews-hook 'ethio-fidel-to-sera-mail)
39 ;; 50
40 ;; If the filename ends in ".sera", editing will be done in fidel 51 ;;
41 ;; while file I/O will be done in sera. 52 ;; users' preference
53 ;;
54
55 (defvar ethio-primary-language 'tigrigna
56 "*Symbol that defines the primary language in SERA --> FIDEL conversion.
57 The value should be one of: `tigrigna', `amharic' or `english'.")
58
59 (defvar ethio-secondary-language 'english
60 "*Symbol that defines the secondary language in SERA --> FIDEL conversion.
61 The value should be one of: `tigrigna', `amharic' or `english'.")
62
63 (defvar ethio-use-colon-for-colon nil
64 "*Non-nil means associate ASCII colon with Ethiopic colon.
65 If nil, associate ASCII colon with Ethiopic word separator, i.e., two
66 vertically stacked dots. All SERA <--> FIDEL converters refer this
67 variable.")
68
69 (defvar ethio-use-three-dot-question nil
70 "*Non-nil means associate ASCII question mark with Ethiopic old style question mark (three vertically stacked dots).
71 If nil, associate ASCII question mark with Ethiopic stylised question
72 mark. All SERA <--> FIDEL converters refer this variable.")
73
74 (defvar ethio-quote-vowel-always nil
75 "*Non-nil means always put an apostrophe before an isolated vowel (except at word initial) in FIDEL --> SERA conversion.
76 If nil, put an apostrophe only between a sixth-form consonant and an
77 isolated vowel.")
78
79 (defvar ethio-W-sixth-always nil
80 "*Non-nil means convert the Wu-form of a 12-form consonant to \"W'\" instead of \"Wu\" in FIDEL --> SERA conversion.")
81
82 (defvar ethio-numeric-reduction 0
83 "*Degree of reduction in converting Ethiopic digits into Arabic digits.
84 Should be 0, 1 or 2.
85 For example, ({10}{9}{100}{80}{7}) is converted into:
86 `10`9`100`80`7 if `ethio-numeric-reduction' is 0,
87 `109100807 if `ethio-numeric-reduction' is 1,
88 `10900807 if `ethio-numeric-reduction' is 2.")
89
90 (defvar ethio-implicit-period-conversion t
91 "*Non-nil means replacing the Ethiopic dot at the end of an Ethiopic sentence
92 with an Ethiopic full stop.")
93
94 (defvar ethio-java-save-lowercase nil
95 "*Non-nil means save Ethiopic characters in lowercase hex numbers to Java files.
96 If nil, use uppercases.")
42 97
43 ;; 98 ;;
44 ;; SERA to FIDEL 99 ;; SERA to FIDEL
45 ;; 100 ;;
46 101
47 (defconst sera-to-fidel-table 102 (defconst ethio-sera-to-fidel-table
48 [ 103 [
49 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 104 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
50 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 105 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
51 ;;; SP ! " # $ % & ' ( ) * + , - . / 106 ;;; SP
52 nil nil nil nil nil nil nil ("") nil nil nil nil ("$(2$Q(B") nil ("$(2$P(B") nil 107 (" "
53 ;;; 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 108 (?: (if ethio-use-colon-for-colon " $(3$l(B" "$(3$h(B")
54 nil nil nil nil nil nil nil nil nil nil ("$(2$S(B") ("$(2$R(B") nil nil nil nil nil 109 (32 (if ethio-use-colon-for-colon " $(3$l(B " "$(3$h(B"))
110 (?- " $(3$m(B")
111 (?: " $(3$i(B")
112 (?| (if ethio-use-colon-for-colon " $(3$l(B|" " $(3$h(B|")
113 (?: " $(3$o(B"))))
114
115 ;;; ! " # $ % & '
116 nil nil nil nil nil nil ("" (?' "$(3%s(B"))
117 ;;; ( ) * + , - .
118 nil nil nil nil ("$(3$j(B") ("-" (?: "$(3$l(B")) ("$(3%u(B")
119 ;;; / 0 1 2 3 4 5 6 7 8 9
120 nil nil nil nil nil nil nil nil nil nil nil
121 ;;; :
122 ((if ethio-use-colon-for-colon "$(3$l(B" "$(3$h(B")
123 (32 (if ethio-use-colon-for-colon "$(3$l(B " "$(3$h(B"))
124 (?- "$(3$m(B")
125 (?: "$(3$i(B")
126 (?| (if ethio-use-colon-for-colon "$(3$l(B|" "$(3$h(B|")
127 (?: "$(3$o(B")))
128 ;;; ; < = >
129 ("$(3$k(B") ("<" (?< "$(3%v(B")) nil (">" (?> "$(3%w(B"))
130 ;;; ?
131 ((if ethio-use-three-dot-question "$(3$n(B" "$(3%x(B"))
132 ;;; @
133 nil
55 ;;; A 134 ;;; A
56 ("$(2"V(B" (?2 "$(2#b(B")) 135 ("$(3"f(B" (?2 "$(3#8(B"))
57 ;;; B 136 ;;; B
58 ("$(2!F(B" (?e "$(2!A(B") (?u "$(2!B(B") (?i "$(2!C(B") (?a "$(2!D(B") (?E "$(2!E(B") (?o "$(2!G(B") (?| "$(2!F(B") 137 ("$(3"((B" (?e "$(3"#(B") (?u "$(3"$(B") (?i "$(3"%(B") (?a "$(3"&(B") (?E "$(3"'(B") (?o "$(3")(B")
59 (?W "$(2!H(B" (?a "$(2!H(B") 138 (?W "$(3%b(B" (?e "$(3%2(B") (?u "$(3%b(B") (?i "$(3%B(B") (?a "$(3"*(B") (?E "$(3%R(B")))
60 (?e "$(2!F#L(B") (?u "$(2!F#M(B") (?i "$(2!F#N(B") (?E "$(2!F#P(B") (?' "$(2!F#M(B")))
61 ;;; C 139 ;;; C
62 ("$(2"8(B" (?e "$(2"3(B") (?u "$(2"4(B") (?i "$(2"5(B") (?a "$(2"6(B") (?E "$(2"7(B") (?o "$(2"9(B") (?| "$(2"8(B") 140 ("$(3$4(B" (?e "$(3$/(B") (?u "$(3$0(B") (?i "$(3$1(B") (?a "$(3$2(B") (?E "$(3$3(B") (?o "$(3$5(B")
63 (?W "$(2":(B" (?a "$(2":(B") 141 (?W "$(3$6(B" (?a "$(3$6(B")
64 (?e "$(2"8#L(B") (?u "$(2"8#M(B") (?i "$(2"8#N(B") (?E "$(2"8#P(B") (?' "$(2"8#M(B"))) 142 (?e "$(3$4%n(B") (?u "$(3$4%r(B") (?i "$(3$4%o(B") (?E "$(3$4%q(B")))
65 ;;; D 143 ;;; D
66 ("$(2$0(B" (?e "$(2$+(B") (?u "$(2$,(B") (?i "$(2$-(B") (?a "$(2$.(B") (?E "$(2$/(B") (?o "$(2$1(B") (?| "$(2$0(B")) 144 ("$(3#b(B" (?e "$(3#](B") (?u "$(3#^(B") (?i "$(3#_(B") (?a "$(3#`(B") (?E "$(3#a(B") (?o "$(3#c(B")
145 (?W "$(3#d(B" (?a "$(3#d(B")
146 (?e "$(3#b%n(B") (?u "$(3#b%r(B") (?i "$(3#b%o(B") (?E "$(3#b%q(B")))
67 ;;; E 147 ;;; E
68 ("$(2"W(B" (?2 "$(2#c(B")) 148 ("$(3"g(B" (?2 "$(3#9(B"))
69 ;;; F 149 ;;; F
70 ("$(2"@(B" (?e "$(2";(B") (?u "$(2"<(B") (?i "$(2"=(B") (?a "$(2">(B") (?E "$(2"?(B") (?o "$(2"A(B") (?| "$(2"@(B") 150 ("$(3$T(B" (?e "$(3$O(B") (?u "$(3$P(B") (?i "$(3$Q(B") (?a "$(3$R(B") (?E "$(3$S(B") (?o "$(3$U(B")
71 (?W "$(2"B(B" (?a "$(2"B(B") 151 (?W "$(3%d(B" (?e "$(3%4(B") (?u "$(3%d(B") (?i "$(3%D(B") (?a "$(3$V(B") (?E "$(3%T(B"))
72 (?e "$(2"@#L(B") (?u "$(2"@#M(B") (?i "$(2"@#N(B") (?E "$(2"@#P(B") (?' "$(2"@#M(B"))) 152 (?Y "$(3$a(B" (?a "$(3$a(B")))
73 ;;; G 153 ;;; G
74 ("$(2$>(B" (?e "$(2$9(B") (?u "$(2$:(B") (?i "$(2$;(B") (?a "$(2$<(B") (?E "$(2$=(B") (?o "$(2$?(B") (?| "$(2$>(B")) 154 ("$(3$$(B" (?e "$(3#}(B") (?u "$(3#~(B") (?i "$(3$!(B") (?a "$(3$"(B") (?E "$(3$#(B") (?o "$(3$%(B")
155 (?W "$(3%c(B" (?e "$(3%3(B") (?u "$(3%c(B") (?i "$(3%C(B") (?a "$(3$&(B") (?E "$(3%S(B")))
75 ;;; H 156 ;;; H
76 ("$(2$"(B" (?e "$(2#{(B") (?u "$(2#|(B") (?i "$(2#}(B") (?a "$(2#~(B") (?E "$(2$!(B") (?o "$(2$#(B") (?| "$(2$"(B")) 157 ("$(3!6(B" (?e "$(3!1(B") (?u "$(3!2(B") (?i "$(3!3(B") (?a "$(3!4(B") (?E "$(3!5(B") (?o "$(3!7(B")
158 (?W "$(3!8(B" (?a "$(3!8(B")
159 (?e "$(3!6%n(B") (?u "$(3!6%r(B") (?i "$(3!6%o(B") (?E "$(3!6%q(B")))
77 ;;; I 160 ;;; I
78 ("$(2"X(B" (?2 "$(2#d(B")) 161 ("$(3"h(B" (?2 "$(3#:(B"))
79 ;;; J 162 ;;; J
80 ("$(2$7(B" (?e "$(2$2(B") (?u "$(2$3(B") (?i "$(2$4(B") (?a "$(2$5(B") (?E "$(2$6(B") (?o "$(2$8(B") (?| "$(2$7(B")) 163 ("$(3#j(B" (?e "$(3#e(B") (?u "$(3#f(B") (?i "$(3#g(B") (?a "$(3#h(B") (?E "$(3#i(B") (?o "$(3#k(B")
164 (?W "$(3#l(B" (?a "$(3#l(B")
165 (?e "$(3#j%n(B") (?u "$(3#j%r(B") (?i "$(3#j%o(B") (?E "$(3#j%q(B")))
81 ;;; K 166 ;;; K
82 ("$(2"x(B" (?e "$(2"s(B") (?u "$(2"t(B") (?i "$(2"u(B") (?a "$(2"v(B") (?E "$(2"w(B") (?o "$(2"y(B") (?| "$(2"x(B") 167 ("$(3#"(B" (?e "$(3"{(B") (?u "$(3"|(B") (?i "$(3"}(B") (?a "$(3"~(B") (?E "$(3#!(B") (?o "$(3##(B")
83 (?W "$(2"{(B" (?e "$(2"z(B") (?u "$(2"{(B") (?i "$(2"|(B") (?a "$(2"}(B") (?E "$(2"~(B"))) 168 (?W "$(3#*(B" (?e "$(3#%(B") (?u "$(3#*(B") (?i "$(3#'(B") (?a "$(3#((B") (?E "$(3#)(B")))
84 ;;; L 169 ;;; L
85 ("$(2!&(B" (?e "$(2!!(B") (?u "$(2!"(B") (?i "$(2!#(B") (?a "$(2!$(B") (?E "$(2!%(B") (?o "$(2!'(B") (?| "$(2!&(B") 170 ("$(3!.(B" (?e "$(3!)(B") (?u "$(3!*(B") (?i "$(3!+(B") (?a "$(3!,(B") (?E "$(3!-(B") (?o "$(3!/(B")
86 (?W "$(2!((B" (?a "$(2!((B") 171 (?W "$(3!0(B" (?a "$(3!0(B")
87 (?e "$(2!&#L(B") (?u "$(2!&#M(B") (?i "$(2!&#N(B") (?E "$(2!&#P(B") (?' "$(2!&#M(B"))) 172 (?e "$(3!.%n(B") (?u "$(3!.%r(B") (?i "$(3!.%o(B") (?E "$(3!.%q(B")))
88 ;;; M 173 ;;; M
89 ("$(2!.(B" (?e "$(2!)(B") (?u "$(2!*(B") (?i "$(2!+(B") (?a "$(2!,(B") (?E "$(2!-(B") (?o "$(2!/(B") (?| "$(2!.(B") 174 ("$(3!>(B" (?e "$(3!9(B") (?u "$(3!:(B") (?i "$(3!;(B") (?a "$(3!<(B") (?E "$(3!=(B") (?o "$(3!?(B")
90 (?W "$(2!0(B" (?a "$(2!0(B") 175 (?W "$(3%a(B" (?e "$(3%1(B") (?u "$(3%a(B") (?i "$(3%A(B") (?a "$(3!@(B") (?E "$(3%Q(B"))
91 (?e "$(2!.#L(B") (?u "$(2!.#M(B") (?i "$(2!.#N(B") (?E "$(2!.#P(B") (?' "$(2!.#M(B"))) 176 (?Y "$(3$_(B" (?a "$(3$_(B")))
92 ;;; N 177 ;;; N
93 ("$(2!n(B" (?e "$(2!i(B") (?u "$(2!j(B") (?i "$(2!k(B") (?a "$(2!l(B") (?E "$(2!m(B") (?o "$(2!o(B") (?| "$(2!n(B") 178 ("$(3"`(B" (?e "$(3"[(B") (?u "$(3"\(B") (?i "$(3"](B") (?a "$(3"^(B") (?E "$(3"_(B") (?o "$(3"a(B")
94 (?W "$(2!p(B" (?a "$(2!p(B") 179 (?W "$(3"b(B" (?a "$(3"b(B")
95 (?e "$(2!n#L(B") (?u "$(2!n#M(B") (?i "$(2!n#N(B") (?E "$(2!n#P(B") (?' "$(2!n#M(B"))) 180 (?e "$(3"`%n(B") (?u "$(3"`%r(B") (?i "$(3"`%o(B") (?E "$(3"`%q(B")))
96 ;;; O 181 ;;; O
97 ("$(2"Y(B" (?2 "$(2#e(B")) 182 ("$(3"i(B" (?2 "$(3#;(B"))
98 ;;; P 183 ;;; P
99 ("$(2$E(B" (?e "$(2$@(B") (?u "$(2$A(B") (?i "$(2$B(B") (?a "$(2$C(B") (?E "$(2$D(B") (?o "$(2$F(B") (?| "$(2$E(B")) 184 ("$(3$<(B" (?e "$(3$7(B") (?u "$(3$8(B") (?i "$(3$9(B") (?a "$(3$:(B") (?E "$(3$;(B") (?o "$(3$=(B")
185 (?W "$(3$>(B" (?a "$(3$>(B")
186 (?e "$(3$<%n(B") (?u "$(3$<%r(B") (?i "$(3$<%o(B") (?E "$(3$<%q(B")))
100 ;;; Q 187 ;;; Q
101 ("$(2#2(B" (?e "$(2#-(B") (?u "$(2#.(B") (?i "$(2#/(B") (?a "$(2#0(B") (?E "$(2#1(B") (?o "$(2#3(B") (?| "$(2#2(B") 188 ("$(3!v(B" (?e "$(3!q(B") (?u "$(3!r(B") (?i "$(3!s(B") (?a "$(3!t(B") (?E "$(3!u(B") (?o "$(3!w(B")
102 (?W "$(2#5(B" (?e "$(2#4(B") (?u "$(2#5(B") (?i "$(2#6(B") (?a "$(2#7(B") (?E "$(2#8(B"))) 189 (?W "$(3!~(B" (?e "$(3!y(B") (?u "$(3!~(B") (?i "$(3!{(B") (?a "$(3!|(B") (?E "$(3!}(B")))
103 ;;; R 190 ;;; R
104 ("$(2!6(B" (?e "$(2!1(B") (?u "$(2!2(B") (?i "$(2!3(B") (?a "$(2!4(B") (?E "$(2!5(B") (?o "$(2!7(B") (?| "$(2!6(B") 191 ("$(3!N(B" (?e "$(3!I(B") (?u "$(3!J(B") (?i "$(3!K(B") (?a "$(3!L(B") (?E "$(3!M(B") (?o "$(3!O(B")
105 (?W "$(2!8(B" (?a "$(2!8(B") 192 (?W "$(3!P(B" (?a "$(3!P(B")
106 (?e "$(2!6#L(B") (?u "$(2!6#M(B") (?i "$(2!6#N(B") (?E "$(2!6#P(B") (?' "$(2!6#M(B"))) 193 (?e "$(3!N%n(B") (?u "$(3!N%r(B") (?i "$(3!N%o(B") (?E "$(3!N%q(B"))
194 (?Y "$(3$`(B" (?a "$(3$`(B")))
107 ;;; S 195 ;;; S
108 ("$(2"P(B" (?e "$(2"K(B") (?u "$(2"L(B") (?i "$(2"M(B") (?a "$(2"N(B") (?E "$(2"O(B") (?o "$(2"Q(B") (?| "$(2"P(B") 196 ("$(3$D(B" (?e "$(3$?(B") (?u "$(3$@(B") (?i "$(3$A(B") (?a "$(3$B(B") (?E "$(3$C(B") (?o "$(3$E(B")
109 (?W "$(2"R(B" (?a "$(2"R(B") 197 (?W "$(3$F(B" (?a "$(3$F(B")
110 (?e "$(2"P#L(B") (?u "$(2"P#M(B") (?i "$(2"P#N(B") (?E "$(2"P#P(B") (?' "$(2"P#M(B")) 198 (?e "$(3$D%n(B") (?u "$(3$D%r(B") (?i "$(3$D%o(B") (?E "$(3$D%q(B"))
111 (?2 "$(2#](B" (?| "$(2#](B") 199 (?2 "$(3$L(B"
112 (?e "$(2#X(B") (?u "$(2#Y(B") (?i "$(2#Z(B") (?a "$(2#[(B") (?E "$(2#\(B") (?o "$(2#^(B") 200 (?e "$(3$G(B") (?u "$(3$H(B") (?i "$(3$I(B") (?a "$(3$J(B") (?E "$(3$K(B") (?o "$(3$M(B")
113 (?W "$(2"R(B" 201 (?W "$(3$F(B" (?a "$(3$F(B")
114 (?a "$(2"R(B") 202 (?e "$(3$L%n(B") (?u "$(3$L%r(B") (?i "$(3$L%o(B") (?E "$(3$L%q(B"))))
115 (?e "$(2#]#L(B") (?u "$(2#]#M(B") (?i "$(2#]#N(B") (?E "$(2#]#P(B") (?' "$(2#]#M(B"))))
116
117 ;;; T 203 ;;; T
118 ("$(2"0(B" (?e "$(2"+(B") (?u "$(2",(B") (?i "$(2"-(B") (?a "$(2".(B") (?E "$(2"/(B") (?o "$(2"1(B") (?| "$(2"0(B") 204 ("$(3$,(B" (?e "$(3$'(B") (?u "$(3$((B") (?i "$(3$)(B") (?a "$(3$*(B") (?E "$(3$+(B") (?o "$(3$-(B")
119 (?W "$(2"2(B" (?a "$(2"2(B") 205 (?W "$(3$.(B" (?a "$(3$.(B")
120 (?e "$(2"0#L(B") (?u "$(2"0#M(B") (?i "$(2"0#N(B") (?E "$(2"0#P(B") (?' "$(2"0#M(B"))) 206 (?e "$(3$,%n(B") (?u "$(3$,%r(B") (?i "$(3$,%o(B") (?E "$(3$,%q(B")))
121 ;;; U 207 ;;; U
122 ("$(2"T(B" (?2 "$(2#`(B")) 208 ("$(3"d(B" (?2 "$(3#6(B"))
123 ;;; V 209 ;;; V
124 ("$(2!N(B" (?e "$(2!I(B") (?u "$(2!J(B") (?i "$(2!K(B") (?a "$(2!L(B") (?E "$(2!M(B") (?o "$(2!O(B") (?| "$(2!N(B") 210 ("$(3"0(B" (?e "$(3"+(B") (?u "$(3",(B") (?i "$(3"-(B") (?a "$(3".(B") (?E "$(3"/(B") (?o "$(3"1(B")
125 (?W "$(2!P(B" (?a "$(2!P(B") 211 (?W "$(3"2(B" (?a "$(3"2(B")
126 (?e "$(2!N#L(B") (?u "$(2!N#M(B") (?i "$(2!N#N(B") (?E "$(2!N#P(B") (?' "$(2!N#M(B"))) 212 (?e "$(3"0%n(B") (?u "$(3"0%r(B") (?i "$(3"0%o(B") (?E "$(3"0%q(B")))
127 ;;; W 213 ;;; W
128 ("$(2#M(B" (?e "$(2#L(B") (?u "$(2#M(B") (?i "$(2#N(B") (?a "$(2#O(B") (?E "$(2#P(B")) 214 ("$(3%r(B" (?e "$(3%n(B") (?u "$(3%r(B") (?i "$(3%o(B") (?a "$(3%p(B") (?E "$(3%q(B"))
129 ;;; X 215 ;;; X
130 ("$(2#y(B" (?e "$(2#t(B") (?u "$(2#u(B") (?i "$(2#v(B") (?a "$(2#w(B") (?E "$(2#x(B") (?o "$(2#z(B") (?| "$(2#y(B")) 216 ("$(3%N(B" (?e "$(3%I(B") (?u "$(3%J(B") (?i "$(3%K(B") (?a "$(3%L(B") (?E "$(3%M(B") (?o "$(3%O(B"))
131 ;;; Y 217 ;;; Y
132 ("$(2$)(B" (?e "$(2$$(B") (?u "$(2$%(B") (?i "$(2$&(B") (?a "$(2$'(B") (?E "$(2$((B") (?o "$(2$*(B") (?| "$(2$)(B")) 218 ("$(3#R(B" (?e "$(3#M(B") (?u "$(3#N(B") (?i "$(3#O(B") (?a "$(3#P(B") (?E "$(3#Q(B") (?o "$(3#S(B")
219 (?W "$(3#T(B" (?a "$(3#T(B")
220 (?e "$(3#R%n(B") (?u "$(3#R%r(B") (?i "$(3#R%o(B") (?E "$(3#R%q(B")))
133 ;;; Z 221 ;;; Z
134 ("$(2!~(B" (?e "$(2!y(B") (?u "$(2!z(B") (?i "$(2!{(B") (?a "$(2!|(B") (?E "$(2!}(B") (?o "$(2"!(B") (?| "$(2!~(B") 222 ("$(3#J(B" (?e "$(3#E(B") (?u "$(3#F(B") (?i "$(3#G(B") (?a "$(3#H(B") (?E "$(3#I(B") (?o "$(3#K(B")
135 (?W "$(2""(B" (?a "$(2""(B") 223 (?W "$(3#L(B" (?a "$(3#L(B")
136 (?e "$(2!~#L(B") (?u "$(2!~#M(B") (?i "$(2!~#N(B") (?E "$(2!~#P(B") (?' "$(2!~#M(B"))) 224 (?e "$(3#J%n(B") (?u "$(3#J%r(B") (?i "$(3#J%o(B") (?E "$(3#J%q(B")))
137 ;;; [ \ ] ^ _ 225 ;;; [ \ ] ^ _
138 nil nil nil nil nil 226 nil nil nil nil nil
139 ;;; ` 227 ;;; `
140 ("`" 228 (""
141 (?e "$(2#_(B") (?u "$(2#`(B") (?U "$(2#`(B") (?i "$(2#a(B") (?a "$(2#b(B") (?A "$(2#b(B") 229 (?: "$(3$h(B")
142 (?E "$(2#c(B") (?I "$(2#d(B") (?o "$(2#e(B") (?O "$(2#e(B") 230 (?? (if ethio-use-three-dot-question "$(3%x(B" "$(3$n(B"))
143 (?s "$(2#V(B" 231 (?! "$(3%t(B")
144 (?e "$(2#Q(B") (?u "$(2#R(B") (?i "$(2#S(B") (?a "$(2#T(B") (?E "$(2#U(B") (?o "$(2#W(B") (?| "$(2#V(B") 232 (?e "$(3#5(B") (?u "$(3#6(B") (?U "$(3#6(B") (?i "$(3#7(B") (?a "$(3#8(B") (?A "$(3#8(B")
145 (?W "$(2"J(B" (?a "$(2"J(B") 233 (?E "$(3#9(B") (?I "$(3#:(B") (?o "$(3#;(B") (?O "$(3#;(B")
146 (?e "$(2#V#L(B") (?u "$(2#V#M(B") (?i "$(2#V#N(B") (?E "$(2#V#P(B") (?' "$(2#V#M(B"))) 234 (?g "$(3%^(B"
147 (?S "$(2#](B" 235 (?e "$(3%Y(B") (?u "$(3%Z(B") (?i "$(3%[(B") (?a "$(3%\(B") (?E "$(3%](B") (?o "$(3%_(B"))
148 (?e "$(2#X(B") (?u "$(2#Y(B") (?i "$(2#Z(B") (?a "$(2#[(B") (?E "$(2#\(B") (?o "$(2#^(B") (?| "$(2#](B") 236 (?h "$(3"H(B"
149 (?W "$(2"R(B" (?a "$(2"R(B") 237 (?e "$(3"C(B") (?u "$(3"D(B") (?i "$(3"E(B") (?a "$(3"F(B") (?E "$(3"G(B") (?o "$(3"I(B")
150 (?e "$(2#]#L(B") (?u "$(2#]#M(B") (?i "$(2#]#N(B") (?E "$(2#]#P(B") (?' "$(2#]#M(B"))) 238 (?W "$(3"P(B" (?e "$(3"K(B") (?u "$(3"P(B") (?i "$(3"M(B") (?a "$(3"N(B") (?E "$(3"O(B")))
151 (?h "$(2#k(B" 239 (?k "$(3%>(B"
152 (?e "$(2#f(B") (?u "$(2#g(B") (?i "$(2#h(B") (?a "$(2#i(B") (?E "$(2#j(B") (?o "$(2#l(B") (?| "$(2#k(B") 240 (?e "$(3%9(B") (?u "$(3%:(B") (?i "$(3%;(B") (?a "$(3%<(B") (?E "$(3%=(B") (?o "$(3%?(B"))
153 (?W "$(2"c(B" (?e "$(2"b(B") (?u "$(2"c(B") (?i "$(2"d(B") (?a "$(2"e(B") (?E "$(2"f(B"))) 241 (?s "$(3!F(B"
154 (?k "$(2#r(B" 242 (?e "$(3!A(B") (?u "$(3!B(B") (?i "$(3!C(B") (?a "$(3!D(B") (?E "$(3!E(B") (?o "$(3!G(B")
155 (?e "$(2#m(B") (?u "$(2#n(B") (?i "$(2#o(B") (?a "$(2#p(B") (?E "$(2#q(B") (?o "$(2#s(B") (?| "$(2#r(B"))) 243 (?W "$(3!H(B" (?a "$(3!H(B")
244 (?e "$(3!F%n(B") (?u "$(3!F%r(B") (?i "$(3!F%o(B") (?E "$(3!F%q(B")))
245 (?S "$(3$L(B"
246 (?e "$(3$G(B") (?u "$(3$H(B") (?i "$(3$I(B") (?a "$(3$J(B") (?E "$(3$K(B") (?o "$(3$M(B")
247 (?W "$(3$F(B" (?a "$(3$F(B")
248 (?e "$(3$L%n(B") (?u "$(3$L%r(B") (?i "$(3$L%o(B") (?E "$(3$L%q(B")))
249 (?q "$(3%.(B" (?e "$(3%)(B") (?u "$(3%*(B") (?i "$(3%+(B") (?a "$(3%,(B") (?E "$(3%-(B") (?o "$(3%/(B")))
156 ;;; a 250 ;;; a
157 ("$(2"S(B" (?2 "$(2#b(B")) 251 ("$(3"f(B" (?2 "$(3#8(B"))
158
159 ;;; b 252 ;;; b
160 ("$(2!F(B" (?e "$(2!A(B") (?u "$(2!B(B") (?i "$(2!C(B") (?a "$(2!D(B") (?E "$(2!E(B") (?o "$(2!G(B") (?| "$(2!F(B") 253 ("$(3"((B" (?e "$(3"#(B") (?u "$(3"$(B") (?i "$(3"%(B") (?a "$(3"&(B") (?E "$(3"'(B") (?o "$(3")(B")
161 (?W "$(2!H(B" (?a "$(2!H(B") 254 (?W "$(3%b(B" (?e "$(3%2(B") (?u "$(3%b(B") (?i "$(3%B(B") (?a "$(3"*(B") (?E "$(3%R(B")))
162 (?e "$(2!F#L(B") (?u "$(2!F#M(B") (?i "$(2!F#N(B") (?E "$(2!F#P(B") (?' "$(2!F#M(B")))
163 ;;; c 255 ;;; c
164 ("$(2!^(B" (?e "$(2!Y(B") (?u "$(2!Z(B") (?i "$(2![(B") (?a "$(2!\(B") (?E "$(2!](B") (?o "$(2!_(B") (?| "$(2!^(B") 256 ("$(3"@(B" (?e "$(3";(B") (?u "$(3"<(B") (?i "$(3"=(B") (?a "$(3">(B") (?E "$(3"?(B") (?o "$(3"A(B")
165 (?W "$(2!`(B" (?a "$(2!`(B") 257 (?W "$(3"B(B" (?a "$(3"B(B")
166 (?e "$(2!^#L(B") (?u "$(2!^#M(B") (?i "$(2!^#N(B") (?E "$(2!^#P(B") (?' "$(2!^#M(B"))) 258 (?e "$(3"@%n(B") (?u "$(3"@%r(B") (?i "$(3"@%o(B") (?E "$(3"@%q(B")))
167 ;;; d 259 ;;; d
168 ("$(2"((B" (?e "$(2"#(B") (?u "$(2"$(B") (?i "$(2"%(B") (?a "$(2"&(B") (?E "$(2"'(B") (?o "$(2")(B") (?| "$(2"((B") 260 ("$(3#Z(B" (?e "$(3#U(B") (?u "$(3#V(B") (?i "$(3#W(B") (?a "$(3#X(B") (?E "$(3#Y(B") (?o "$(3#[(B")
169 (?W "$(2"*(B" (?a "$(2"*(B") 261 (?W "$(3#\(B" (?a "$(3#\(B")
170 (?e "$(2"(#L(B") (?u "$(2"(#M(B") (?i "$(2"(#N(B") (?E "$(2"(#P(B") (?' "$(2"(#M(B"))) 262 (?e "$(3#Z%o(B") (?u "$(3#Z%r(B") (?i "$(3#Z%p(B") (?E "$(3#Z%q(B")))
171 ;;; e 263 ;;; e
172 ("$(2"S(B" (?2 "$(2#_(B") (?3 "$(2"Z(B")) 264 ("$(3"c(B" (?2 "$(3#5(B") (?a "$(3"j(B"))
173 ;;; f 265 ;;; f
174 ("$(2"@(B" (?e "$(2";(B") (?u "$(2"<(B") (?i "$(2"=(B") (?a "$(2">(B") (?E "$(2"?(B") (?o "$(2"A(B") (?| "$(2"@(B") 266 ("$(3$T(B" (?e "$(3$O(B") (?u "$(3$P(B") (?i "$(3$Q(B") (?a "$(3$R(B") (?E "$(3$S(B") (?o "$(3$U(B")
175 (?W "$(2"B(B" (?a "$(2"B(B") 267 (?W "$(3%d(B" (?e "$(3%4(B") (?u "$(3%d(B") (?i "$(3%D(B") (?a "$(3$V(B") (?E "$(3%T(B"))
176 (?e "$(2"@#L(B") (?u "$(2"@#M(B") (?i "$(2"@#N(B") (?E "$(2"@#P(B") (?' "$(2"@#M(B"))) 268 (?Y "$(3$a(B" (?a "$(3$a(B")))
177 ;;; g 269 ;;; g
178 ("$(2#>(B" (?e "$(2#9(B") (?u "$(2#:(B") (?i "$(2#;(B") (?a "$(2#<(B") (?E "$(2#=(B") (?o "$(2#?(B") (?| "$(2#>(B") 270 ("$(3#r(B" (?e "$(3#m(B") (?u "$(3#n(B") (?i "$(3#o(B") (?a "$(3#p(B") (?E "$(3#q(B") (?o "$(3#s(B")
179 (?W "$(2#A(B" (?e "$(2#@(B") (?u "$(2#A(B") (?i "$(2#B(B") (?a "$(2#C(B") (?E "$(2#D(B"))) 271 (?W "$(3#z(B" (?e "$(3#u(B") (?u "$(3#z(B") (?i "$(3#w(B") (?a "$(3#x(B") (?E "$(3#y(B"))
272 (?2 "$(3%^(B" (?e "$(3%Y(B") (?u "$(3%Z(B") (?i "$(3%[(B") (?a "$(3%\(B") (?E "$(3%](B") (?o "$(3%_(B")))
180 ;;; h 273 ;;; h
181 ("$(2"`(B" (?e "$(2"[(B") (?u "$(2"\(B") (?i "$(2"](B") (?a "$(2"^(B") (?E "$(2"_(B") (?o "$(2"a(B") (?| "$(2"`(B") 274 ("$(3!&(B" (?e "$(3!!(B") (?u "$(3!"(B") (?i "$(3!#(B") (?a "$(3!$(B") (?E "$(3!%(B") (?o "$(3!'(B")
182 (?W "$(2"c(B" (?e "$(2"b(B") (?u "$(2"c(B") (?i "$(2"d(B") (?a "$(2"e(B") (?E "$(2"f(B")) 275 (?W "$(3"P(B" (?e "$(3"K(B") (?u "$(3"P(B") (?i "$(3"M(B") (?a "$(3"N(B") (?E "$(3"O(B"))
183 (?2 "$(2#k(B" (?e "$(2#f(B") (?u "$(2#g(B") (?i "$(2#h(B") (?a "$(2#i(B") (?E "$(2#j(B") (?o "$(2#l(B") 276 (?2 "$(3"H(B" (?e "$(3"C(B") (?u "$(3"D(B") (?i "$(3"E(B") (?a "$(3"F(B") (?E "$(3"G(B") (?o "$(3"I(B")
184 (?| "$(2#k(B") 277 (?W "$(3"P(B" (?e "$(3"K(B") (?u "$(3"P(B") (?i "$(3"M(B") (?a "$(3"N(B") (?E "$(3"O(B"))))
185 (?W "$(2"c(B" (?e "$(2"b(B") (?u "$(2"c(B") (?i "$(2"d(B") (?a "$(2"e(B") (?E "$(2"f(B"))))
186 ;;; i 278 ;;; i
187 ("$(2"U(B" (?2 "$(2#a(B")) 279 ("$(3"e(B" (?2 "$(3#7(B"))
188 ;;; j 280 ;;; j
189 ("$(2$7(B" (?e "$(2$2(B") (?u "$(2$3(B") (?i "$(2$4(B") (?a "$(2$5(B") (?E "$(2$6(B") (?o "$(2$8(B") (?| "$(2$7(B")) 281 ("$(3#j(B" (?e "$(3#e(B") (?u "$(3#f(B") (?i "$(3#g(B") (?a "$(3#h(B") (?E "$(3#i(B") (?o "$(3#k(B")
282 (?W "$(3#l(B" (?a "$(3#l(B")
283 (?e "$(3#j%n(B") (?u "$(3#j%r(B") (?i "$(3#j%o(B") (?E "$(3#j%q(B")))
190 ;;; k 284 ;;; k
191 ("$(2"l(B" (?e "$(2"g(B") (?u "$(2"h(B") (?i "$(2"i(B") (?a "$(2"j(B") (?E "$(2"k(B") (?o "$(2"m(B") (?| "$(2"l(B") 285 ("$(3"p(B" (?e "$(3"k(B") (?u "$(3"l(B") (?i "$(3"m(B") (?a "$(3"n(B") (?E "$(3"o(B") (?o "$(3"q(B")
192 (?W "$(2"o(B" (?e "$(2"n(B") (?u "$(2"o(B") (?i "$(2"p(B") (?a "$(2"q(B") (?E "$(2"r(B")) 286 (?W "$(3"x(B" (?e "$(3"s(B") (?u "$(3"x(B") (?i "$(3"u(B") (?a "$(3"v(B") (?E "$(3"w(B"))
193 (?2 "$(2#r(B" (?e "$(2#m(B") (?u "$(2#n(B") (?i "$(2#o(B") (?a "$(2#p(B") (?E "$(2#q(B") (?o "$(2#s(B") 287 (?2 "$(3%>(B" (?e "$(3%9(B") (?u "$(3%:(B") (?i "$(3%;(B") (?a "$(3%<(B") (?E "$(3%=(B") (?o "$(3%?(B")))
194 (?| "$(2#r(B")))
195 ;;; l 288 ;;; l
196 ("$(2!&(B" (?e "$(2!!(B") (?u "$(2!"(B") (?i "$(2!#(B") (?a "$(2!$(B") (?E "$(2!%(B") (?o "$(2!'(B") (?| "$(2!&(B") 289 ("$(3!.(B" (?e "$(3!)(B") (?u "$(3!*(B") (?i "$(3!+(B") (?a "$(3!,(B") (?E "$(3!-(B") (?o "$(3!/(B")
197 (?W "$(2!((B" (?a "$(2!((B") 290 (?W "$(3!0(B" (?a "$(3!0(B")
198 (?e "$(2!&#L(B") (?u "$(2!&#M(B") (?i "$(2!&#N(B") (?E "$(2!&#P(B") (?' "$(2!&#M(B"))) 291 (?e "$(3!.%n(B") (?u "$(3!.%r(B") (?i "$(3!.%o(B") (?E "$(3!.%q(B")))
199 ;;; m 292 ;;; m
200 ("$(2!.(B" (?e "$(2!)(B") (?u "$(2!*(B") (?i "$(2!+(B") (?a "$(2!,(B") (?E "$(2!-(B") (?o "$(2!/(B") (?| "$(2!.(B") 293 ("$(3!>(B" (?e "$(3!9(B") (?u "$(3!:(B") (?i "$(3!;(B") (?a "$(3!<(B") (?E "$(3!=(B") (?o "$(3!?(B")
201 (?W "$(2!0(B" (?a "$(2!0(B") 294 (?W "$(3%a(B" (?e "$(3%1(B") (?u "$(3%a(B") (?i "$(3%A(B") (?a "$(3!@(B") (?E "$(3%Q(B"))
202 (?e "$(2!.#L(B") (?u "$(2!.#M(B") (?i "$(2!.#N(B") (?E "$(2!.#P(B") (?' "$(2!.#M(B"))) 295 (?Y "$(3$_(B" (?a "$(3$_(B")))
203 ;;; n 296 ;;; n
204 ("$(2!f(B" (?e "$(2!a(B") (?u "$(2!b(B") (?i "$(2!c(B") (?a "$(2!d(B") (?E "$(2!e(B") (?o "$(2!g(B") (?| "$(2!f(B") 297 ("$(3"X(B" (?e "$(3"S(B") (?u "$(3"T(B") (?i "$(3"U(B") (?a "$(3"V(B") (?E "$(3"W(B") (?o "$(3"Y(B")
205 (?W "$(2!h(B" (?a "$(2!h(B") 298 (?W "$(3"Z(B" (?a "$(3"Z(B")
206 (?e "$(2!f#L(B") (?u "$(2!f#M(B") (?i "$(2!f#N(B") (?E "$(2!f#P(B") (?' "$(2!f#M(B"))) 299 (?e "$(3"X%n(B") (?u "$(3"X%r(B") (?i "$(3"X%o(B") (?E "$(3"X%q(B")))
207 ;;; o 300 ;;; o
208 ("$(2"Y(B" (?2 "$(2#e(B")) 301 ("$(3"i(B" (?2 "$(3#;(B"))
209 ;;; p 302 ;;; p
210 ("$(2$L(B" (?e "$(2$G(B") (?u "$(2$H(B") (?i "$(2$I(B") (?a "$(2$J(B") (?E "$(2$K(B") (?o "$(2$M(B") (?| "$(2$L(B")) 303 ("$(3$\(B" (?e "$(3$W(B") (?u "$(3$X(B") (?i "$(3$Y(B") (?a "$(3$Z(B") (?E "$(3$[(B") (?o "$(3$](B")
304 (?W "$(3%e(B" (?e "$(3%5(B") (?u "$(3%e(B") (?i "$(3%E(B") (?a "$(3$^(B") (?E "$(3%U(B")))
211 ;;; q 305 ;;; q
212 ("$(2#&(B" (?e "$(2#!(B") (?u "$(2#"(B") (?i "$(2##(B") (?a "$(2#$(B") (?E "$(2#%(B") (?o "$(2#'(B") (?| "$(2#&(B") 306 ("$(3!f(B" (?e "$(3!a(B") (?u "$(3!b(B") (?i "$(3!c(B") (?a "$(3!d(B") (?E "$(3!e(B") (?o "$(3!g(B")
213 (?W "$(2#)(B" (?e "$(2#((B") (?u "$(2#)(B") (?i "$(2#*(B") (?a "$(2#+(B") (?E "$(2#,(B"))) 307 (?W "$(3!n(B" (?e "$(3!i(B") (?u "$(3!n(B") (?i "$(3!k(B") (?a "$(3!l(B") (?E "$(3!m(B"))
308 (?2 "$(3%.(B" (?e "$(3%)(B") (?u "$(3%*(B") (?i "$(3%+(B") (?a "$(3%,(B") (?E "$(3%-(B") (?o "$(3%/(B")))
214 ;;; r 309 ;;; r
215 ("$(2!6(B" (?e "$(2!1(B") (?u "$(2!2(B") (?i "$(2!3(B") (?a "$(2!4(B") (?E "$(2!5(B") (?o "$(2!7(B") (?| "$(2!6(B") 310 ("$(3!N(B" (?e "$(3!I(B") (?u "$(3!J(B") (?i "$(3!K(B") (?a "$(3!L(B") (?E "$(3!M(B") (?o "$(3!O(B")
216 (?W "$(2!8(B" (?a "$(2!8(B") 311 (?W "$(3!P(B" (?a "$(3!P(B")
217 (?e "$(2!6#L(B") (?u "$(2!6#M(B") (?i "$(2!6#N(B") (?E "$(2!6#P(B") (?' "$(2!6#M(B"))) 312 (?e "$(3!N%n(B") (?u "$(3!N%r(B") (?i "$(3!N%o(B") (?E "$(3!N%q(B"))
313 (?Y "$(3$`(B" (?a "$(3$`(B")))
218 ;;; s 314 ;;; s
219 ("$(2"H(B" (?e "$(2"C(B") (?u "$(2"D(B") (?i "$(2"E(B") (?a "$(2"F(B") (?E "$(2"G(B") (?o "$(2"I(B") (?| "$(2"H(B") 315 ("$(3!V(B" (?e "$(3!Q(B") (?u "$(3!R(B") (?i "$(3!S(B") (?a "$(3!T(B") (?E "$(3!U(B") (?o "$(3!W(B")
220 (?W "$(2"J(B" (?a "$(2"J(B") 316 (?W "$(3!X(B" (?a "$(3!X(B")
221 (?e "$(2"H#L(B") (?u "$(2"H#M(B") (?i "$(2"H#N(B") (?E "$(2"H#P(B") (?' "$(2"H#M(B")) 317 (?e "$(3!V%n(B") (?u "$(3!V%r(B") (?i "$(3!V%o(B") (?E "$(3!V%q(B"))
222 (?2 "$(2#V(B" (?e "$(2#Q(B") (?u "$(2#R(B") (?i "$(2#S(B") (?a "$(2#T(B") (?E "$(2#U(B") (?o "$(2#W(B") 318 (?2 "$(3!F(B" (?e "$(3!A(B") (?u "$(3!B(B") (?i "$(3!C(B") (?a "$(3!D(B") (?E "$(3!E(B") (?o "$(3!G(B")
223 (?| "$(2#V(B") 319 (?W "$(3!H(B" (?a "$(3!H(B")
224 (?W "$(2"J(B" (?a "$(2"J(B") 320 (?e "$(3!F%n(B") (?u "$(3!F%r(B") (?i "$(3!F%o(B") (?E "$(3!F%q(B"))))
225 (?e "$(2#V#L(B") (?u "$(2#V#M(B") (?i "$(2#V#N(B") (?E "$(2#V#P(B")
226 (?' "$(2#V#M(B"))))
227 ;;; t 321 ;;; t
228 ("$(2!V(B" (?e "$(2!Q(B") (?u "$(2!R(B") (?i "$(2!S(B") (?a "$(2!T(B") (?E "$(2!U(B") (?o "$(2!W(B") (?| "$(2!V(B") 322 ("$(3"8(B" (?e "$(3"3(B") (?u "$(3"4(B") (?i "$(3"5(B") (?a "$(3"6(B") (?E "$(3"7(B") (?o "$(3"9(B")
229 (?W "$(2!X(B" (?a "$(2!X(B") 323 (?W "$(3":(B" (?a "$(3":(B")
230 (?e "$(2!V#L(B") (?u "$(2!V#M(B") (?i "$(2!V#N(B") (?E "$(2!V#P(B") (?' "$(2!V#M(B"))) 324 (?e "$(3"8%n(B") (?u "$(3"8%r(B") (?i "$(3"8%o(B") (?E "$(3"8%q(B")))
231 ;;; u 325 ;;; u
232 ("$(2"T(B" (?2 "$(2#`(B")) 326 ("$(3"d(B" (?2 "$(3#6(B"))
233 ;;; v 327 ;;; v
234 ("$(2!N(B" (?e "$(2!I(B") (?u "$(2!J(B") (?i "$(2!K(B") (?a "$(2!L(B") (?E "$(2!M(B") (?o "$(2!O(B") (?| "$(2!N(B") 328 ("$(3"0(B" (?e "$(3"+(B") (?u "$(3",(B") (?i "$(3"-(B") (?a "$(3".(B") (?E "$(3"/(B") (?o "$(3"1(B")
235 (?W "$(2!P(B" (?a "$(2!P(B") 329 (?W "$(3"2(B" (?a "$(3"2(B")
236 (?e "$(2!N#L(B") (?u "$(2!N#M(B") (?i "$(2!N#N(B") (?E "$(2!N#P(B") (?' "$(2!N#M(B"))) 330 (?e "$(3"0%n(B") (?u "$(3"0%r(B") (?i "$(3"0%o(B") (?E "$(3"0%q(B")))
237 ;;; w 331 ;;; w
238 ("$(2#J(B" (?e "$(2#E(B") (?u "$(2#F(B") (?i "$(2#G(B") (?a "$(2#H(B") (?E "$(2#I(B") (?o "$(2#K(B") (?| "$(2#J(B") 332 ("$(3#2(B" (?e "$(3#-(B") (?u "$(3#.(B") (?i "$(3#/(B") (?a "$(3#0(B") (?E "$(3#1(B") (?o "$(3#3(B")
239 (?W "$(2#M(B" (?e "$(2#L(B") (?u "$(2#M(B") (?i "$(2#N(B") (?a "$(2#O(B") (?E "$(2#P(B"))) 333 (?W "$(3%p(B" (?e "$(3%n(B") (?u "$(3%r(B") (?i "$(3%o(B") (?a "$(3%p(B") (?E "$(3%q(B")))
240 ;;; x 334 ;;; x
241 ("$(2!>(B" (?e "$(2!9(B") (?u "$(2!:(B") (?i "$(2!;(B") (?a "$(2!<(B") (?E "$(2!=(B") (?o "$(2!?(B") (?| "$(2!>(B") 335 ("$(3!^(B" (?e "$(3!Y(B") (?u "$(3!Z(B") (?i "$(3![(B") (?a "$(3!\(B") (?E "$(3!](B") (?o "$(3!_(B")
242 (?W "$(2!@(B" (?a "$(2!@(B") 336 (?W "$(3!`(B" (?a "$(3!`(B")
243 (?e "$(2!>#L(B") (?u "$(2!>#M(B") (?i "$(2!>#N(B") (?E "$(2!>#P(B") (?' "$(2!>#M(B"))) 337 (?e "$(3!^%n(B") (?u "$(3!^%r(B") (?i "$(3!^%o(B") (?E "$(3!^%q(B")))
244 ;;; y 338 ;;; y
245 ("$(2$)(B" (?e "$(2$$(B") (?u "$(2$%(B") (?i "$(2$&(B") (?a "$(2$'(B") (?E "$(2$((B") (?o "$(2$*(B") (?| "$(2$)(B")) 339 ("$(3#R(B" (?e "$(3#M(B") (?u "$(3#N(B") (?i "$(3#O(B") (?a "$(3#P(B") (?E "$(3#Q(B") (?o "$(3#S(B")
340 (?W "$(3#T(B" (?a "$(3#T(B")
341 (?e "$(3#R%n(B") (?u "$(3#R%r(B") (?i "$(3#R%o(B") (?E "$(3#R%q(B")))
246 ;;; z 342 ;;; z
247 ("$(2!v(B" (?e "$(2!q(B") (?u "$(2!r(B") (?i "$(2!s(B") (?a "$(2!t(B") (?E "$(2!u(B") (?o "$(2!w(B") (?| "$(2!v(B") 343 ("$(3#B(B" (?e "$(3#=(B") (?u "$(3#>(B") (?i "$(3#?(B") (?a "$(3#@(B") (?E "$(3#A(B") (?o "$(3#C(B")
248 (?W "$(2!x(B" (?a "$(2!x(B") 344 (?W "$(3#D(B" (?a "$(3#D(B")
249 (?e "$(2!v#L(B") (?u "$(2!v#M(B") (?i "$(2!v#N(B") (?E "$(2!v#P(B") (?' "$(2!v#M(B"))) 345 (?e "$(3#B%n(B") (?u "$(3#B%r(B") (?i "$(3#B%o(B") (?E "$(3#B%q(B")))
346 ;;; { | } ~ DEL
347 nil nil nil nil nil
250 ]) 348 ])
251 349
252 ;;;###autoload 350 ;;;###autoload
253 (defun sera-to-fidel-region (beg end &optional ascii-mode force) 351 (defun ethio-sera-to-fidel-region (beg end &optional secondary force)
254 "Translates the characters in region from SERA to FIDEL. 352 "Convert the characters in region from SERA to FIDEL.
255 353 The variable `ethio-primary-language' specifies the primary language
256 If the 1st optional parameter ASCII-MODE is non-NIL, assumes that the 354 and `ethio-secondary-language' specifies the secondary.
257 region begins in ASCII script. 355
258 356 If the 3rd parameter SECONDARY is given and non-nil, assume the region
259 If the 2nd optional parametr FORCE is non-NIL, translates even if the 357 begins begins with the secondary language; otherwise with the primary
260 buffer is read-only." 358 language.
359
360 If the 4th parameter FORCE is given and non-nil, perform conversion
361 even if the buffer is read-only.
362
363 See also the descriptions of the variables
364 `ethio-use-colen-for-colon' and
365 `ethio-use-three-dot-question'."
261 366
262 (interactive "r\nP") 367 (interactive "r\nP")
263 (save-excursion 368 (save-restriction
264 (save-restriction 369 (narrow-to-region beg end)
265 (narrow-to-region beg end) 370 (ethio-sera-to-fidel-buffer secondary force)))
266 (sera-to-fidel-buffer ascii-mode force))))
267 371
268 ;;;###autoload 372 ;;;###autoload
269 (defun sera-to-fidel-buffer (&optional ascii-mode force) 373 (defun ethio-sera-to-fidel-buffer (&optional secondary force)
270 "Translates the current buffer from SERA to FIDEL. 374 "Convert the current buffer from SERA to FIDEL.
271 375
272 If the 1st optional parameter ASCII-MODE is non-NIL, assumes that the 376 The variable `ethio-primary-language' specifies the primary
273 current buffer begins in ASCII script. 377 language and `ethio-secondary-language' specifies the secondary.
274 378
275 If the 2nd optional panametr FORCE is non-NIL, translates even if the 379 If the 1st optional parameter SECONDARY is non-nil, assume the buffer
276 buffer is read-only." 380 begins with the secondary language; otherwise with the primary
277 381 language.
382
383 If the 2nd optional parametr FORCE is non-nil, perform conversion even if the
384 buffer is read-only.
385
386 See also the descriptions of the variables
387 `ethio-use-colen-for-colon' and
388 `ethio-use-three-dot-question'."
389
390 (interactive "P")
391
392 (if (and buffer-read-only
393 (not force)
394 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
395 (error ""))
396
397 (let ((ethio-primary-language ethio-primary-language)
398 (ethio-secondary-language ethio-secondary-language)
399 (ethio-use-colon-for-colon ethio-use-colon-for-colon)
400 (ethio-use-three-dot-question ethio-use-three-dot-question)
401 ;; The above four variables may be changed temporary
402 ;; by tilde escapes during conversion. So we bind them to other
403 ;; variables but of the same names.
404 (buffer-read-only nil)
405 (case-fold-search nil)
406 current-language
407 next-language)
408
409 (setq current-language
410 (if secondary
411 ethio-secondary-language
412 ethio-primary-language))
413
414 (goto-char (point-min))
415
416 (while (not (eobp))
417 (setq next-language
418 (cond
419 ((eq current-language 'english)
420 (ethio-sera-to-fidel-english))
421 ((eq current-language 'amharic)
422 (ethio-sera-to-fidel-ethio 'amharic))
423 ((eq current-language 'tigrigna)
424 (ethio-sera-to-fidel-ethio 'tigrigna))
425 (t ; we don't know what to do
426 (ethio-sera-to-fidel-english))))
427
428 (setq current-language
429 (cond
430
431 ;; when language tag is explicitly specified
432 ((not (eq next-language 'toggle))
433 next-language)
434
435 ;; found a toggle in a primary language section
436 ((eq current-language ethio-primary-language)
437 ethio-secondary-language)
438
439 ;; found a toggle in a secondary, third, fourth, ...
440 ;; language section
441 (t
442 ethio-primary-language))))
443
444 ;; If ethio-implicit-period-conversion is non-nil, the
445 ;; Ethiopic dot "$(3%u(B" at the end of an Ethiopic sentence is
446 ;; replaced with the Ethiopic full stop "$(3$i(B".
447 (if ethio-implicit-period-conversion
448 (progn
449 (goto-char (point-min))
450 (while (re-search-forward "\\([$(3!!(B-$(3$a%)(B-$(3%e%n(B-$(3%r%s(B]\\)$(3%u(B\\([ \t]\\)"
451 nil t)
452 (replace-match "\\1$(3$i(B\\2"))
453 (goto-char (point-min))
454 (while (re-search-forward "\\([$(3!!(B-$(3$a%)(B-$(3%e%n(B-$(3%r%s(B]\\)$(3%u(B$" nil t)
455 (replace-match "\\1$(3$i(B"))))
456
457 ;; gemination
458 (goto-char (point-min))
459 (while (re-search-forward "\\ce$(3%s(B" nil 0)
460 (compose-region
461 (save-excursion (backward-char 2) (point))
462 (point)))
463 ))
464
465 (defun ethio-sera-to-fidel-english nil
466 "Handle English section in SERA to FIDEL conversion.
467 Conversion stops when a language switch is found. Then delete that
468 switch and return the name of the new language as a symbol."
469 (let ((new-language nil))
470
471 (while (and (not (eobp)) (null new-language))
472 (cond
473
474 ;; if no more "\", nothing to do.
475 ((not (search-forward "\\" nil 0)))
476
477 ;; hereafter point is put after a "\".
478 ;; first delete that "\", then check the following chars
479
480 ;; "\\" : leave the second "\"
481 ((progn
482 (delete-backward-char 1)
483 (= (following-char) ?\\ ))
484 (forward-char 1))
485
486 ;; "\ " : delete the following " "
487 ((= (following-char) 32)
488 (delete-char 1)
489 (setq new-language 'toggle))
490
491 ;; a language flag
492 ((setq new-language (ethio-process-language-flag)))
493
494 ;; just a "\" : not special sequence.
495 (t
496 (setq new-language 'toggle))))
497
498 new-language))
499
500 (defun ethio-sera-to-fidel-ethio (lang)
501 "Handle Ethiopic section in SERA to FIDEL conversion.
502 Conversion stops when a language switch is found. Then delete that
503 switch and return the name of the new language as a symbol.
504
505 The parameter LANG (symbol, either `amharic' or `tigrigna') affects
506 the conversion of \"a\"."
507
508 (let ((new-language nil)
509 (verbatim nil)
510 start table table2 ch)
511
512 (setcar (aref ethio-sera-to-fidel-table ?a)
513 (if (eq lang 'tigrigna) "$(3"f(B" "$(3"c(B"))
514
515 (while (and (not (eobp)) (null new-language))
516 (setq ch (following-char))
517 (cond
518
519 ;; skip from "<" to ">" (or from "&" to ";") if in w3-mode
520 ((and (boundp 'sera-being-called-by-w3)
521 sera-being-called-by-w3
522 (or (= ch ?<) (= ch ?&)))
523 (search-forward (if (= ch ?<) ">" ";")
524 nil 0))
525
526 ;; leave non-ASCII characters as they are
527 ((>= ch 128)
528 (forward-char 1))
529
530 ;; ethiopic digits
531 ((looking-at "`[1-9][0-9]*")
532 (delete-char 1)
533 (ethio-convert-digit))
534
535 ;; if not seeing a "\", do sera to fidel conversion
536 ((/= ch ?\\ )
537 (setq start (point))
538 (forward-char 1)
539 (setq table (aref ethio-sera-to-fidel-table ch))
540 (while (setq table2 (cdr (assoc (following-char) table)))
541 (setq table table2)
542 (forward-char 1))
543 (if (setq ch (car table))
544 (progn
545 (delete-region start (point))
546 (if (stringp ch)
547 (insert ch)
548 (insert (eval ch))))))
549
550 ;; if control reaches here, we must be looking at a "\"
551
552 ;; verbatim mode
553 (verbatim
554 (if (looking-at "\\\\~! ?")
555
556 ;; "\~!" or "\~! ". switch to non-verbatim mode
557 (progn
558 (replace-match "")
559 (setq verbatim nil))
560
561 ;; "\" but not "\~!" nor "\~! ". skip the current "\".
562 (forward-char 1)))
563
564 ;; hereafter, non-verbatim mode and looking at a "\"
565 ;; first delete that "\", then check the following chars.
566
567 ;; "\ " : delete the following " "
568 ((progn
569 (delete-char 1)
570 (setq ch (following-char))
571 (= ch 32))
572 (delete-char 1)
573 (setq new-language 'toggle))
574
575 ;; "\~!" or "\~! " : switch to verbatim mode
576 ((looking-at "~! ?")
577 (replace-match "")
578 (setq verbatim t))
579
580 ;; a language flag
581 ((setq new-language (ethio-process-language-flag)))
582
583 ;; "\~" but not "\~!" nor a language flag
584 ((= ch ?~)
585 (delete-char 1)
586 (ethio-tilde-escape))
587
588 ;; ASCII punctuation escape. skip
589 ((looking-at "\\(,\\|\\.\\|;\\|:\\|'\\|`\\|\?\\|\\\\\\)+")
590 (goto-char (match-end 0)))
591
592 ;; "\", but not special sequence
593 (t
594 (setq new-language 'toggle))))
595
596 new-language))
597
598 (defun ethio-process-language-flag nil
599 "Process a language flag of the form \"~lang\" or \"~lang1~lang2\".
600
601 If looking at \"~lang1~lang2\", set `ethio-primary-language' and
602 `ethio-une-secondary-language' based on \"lang1\" and \"lang2\".
603 Then delete the language flag \"~lang1~lang2\" from the buffer.
604 Return value is the new primary language.
605
606 If looking at \"~lang\", delete that language flag \"~lang\" from the
607 buffer and return that language. In this case
608 `ethio-primary-language' and `ethio-uni-secondary-language'
609 are left unchanged.
610
611 If an unsupported language flag is found, just return nil without
612 changing anything."
613
614 (let (lang1 lang2)
615 (cond
616
617 ;; ~lang1~lang2
618 ((and (looking-at
619 "~\\([a-z][a-z][a-z]?\\)~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
620 (setq lang1
621 (ethio-flag-to-language
622 (buffer-substring (match-beginning 1) (match-end 1))))
623 (setq lang2
624 (ethio-flag-to-language
625 (buffer-substring (match-beginning 2) (match-end 2)))))
626 (setq ethio-primary-language lang1
627 ethio-secondary-language lang2)
628 (delete-region (point) (match-end 2))
629 (if (= (following-char) 32)
630 (delete-char 1))
631 ethio-primary-language)
632
633 ;; ~lang
634 ((and (looking-at "~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
635 (setq lang1
636 (ethio-flag-to-language
637 (buffer-substring (match-beginning 1) (match-end 1)))))
638 (delete-region (point) (match-end 1))
639 (if (= (following-char) 32)
640 (delete-char 1))
641 lang1)
642
643 ;; otherwise
644 (t
645 nil))))
646
647 (defun ethio-tilde-escape nil
648 "Handle a SERA tilde escape in Ethiopic section and delete it.
649 Delete the escape even it is not recognised."
650
651 (let ((p (point)) command)
652 (skip-chars-forward "^ \t\n\\\\")
653 (setq command (buffer-substring p (point)))
654 (delete-region p (point))
655 (if (= (following-char) 32)
656 (delete-char 1))
657
658 (cond
659
660 ;; \~-:
661 ((string= command "-:")
662 (setq ethio-use-colon-for-colon t))
663
664 ;; \~`:
665 ((string= command "`:")
666 (setq ethio-use-colon-for-colon nil))
667
668 ;; \~?
669 ((string= command "?")
670 (setq ethio-use-three-dot-question nil))
671
672 ;; \~`|
673 ((string= command "`|")
674 (setq ethio-use-three-dot-question t))
675
676 ;; \~e
677 ((string= command "e")
678 (insert "$(3%j(B"))
679
680 ;; \~E
681 ((string= command "E")
682 (insert "$(3%k(B"))
683
684 ;; \~a
685 ((string= command "a")
686 (insert "$(3%l(B"))
687
688 ;; \~A
689 ((string= command "A")
690 (insert "$(3%m(B"))
691
692 ;; \~X
693 ((string= command "X")
694 (insert "$(3%i(B"))
695
696 ;; unsupported tilde escape
697 (t
698 nil))))
699
700 (defun ethio-flag-to-language (flag)
701 (cond
702 ((or (string= flag "en") (string= flag "eng")) 'english)
703 ((or (string= flag "ti") (string= flag "tir")) 'tigrigna)
704 ((or (string= flag "am") (string= flag "amh")) 'amharic)
705 (t nil)))
706
707 (defun ethio-convert-digit nil
708 "Convert Arabic digits to Ethiopic digits."
709 (let (ch z)
710 (while (and (>= (setq ch (following-char)) ?1)
711 (<= ch ?9))
712 (delete-char 1)
713
714 ;; count up following zeros
715 (setq z 0)
716 (while (= (following-char) ?0)
717 (delete-char 1)
718 (setq z (1+ z)))
719
720 (cond
721
722 ;; first digit is 10, 20, ..., or 90
723 ((= (mod z 2) 1)
724 (insert (aref [?$(3$y(B ?$(3$z(B ?$(3${(B ?$(3$|(B ?$(3$}(B ?$(3$~(B ?$(3%!(B ?$(3%"(B ?$(3%#(B] (- ch ?1)))
725 (setq z (1- z)))
726
727 ;; first digit is 2, 3, ..., or 9
728 ((/= ch ?1)
729 (insert (aref [?$(3$q(B ?$(3$r(B ?$(3$s(B ?$(3$t(B ?$(3$u(B ?$(3$v(B ?$(3$w(B ?$(3$x(B] (- ch ?2))))
730
731 ;; single 1
732 ((= z 0)
733 (insert "$(3$p(B")))
734
735 ;; 100
736 (if (= (mod z 4) 2)
737 (insert "$(3%$(B"))
738
739 ;; 10000
740 (insert-char ?$(3%%(B (/ z 4)))))
741
742 ;;;###autoload
743 (defun ethio-sera-to-fidel-mail (&optional arg)
744 "Convert SERA to FIDEL to read/write mail and news.
745
746 If the buffer contains the markers \"<sera>\" and \"</sera>\",
747 convert the segments between them into FIDEL.
748
749 If invoked interactively and there is no marker, convert the subject field
750 and the body into FIDEL using `ethio-sera-to-fidel-region'."
751
752 (interactive "p")
753 (let ((buffer-read-only nil)
754 border)
755 (save-excursion
756
757 ;; look for the header-body separator
758 (goto-char (point-min))
759 (if (search-forward
760 (if (eq major-mode 'rmail-mode)
761 "\n\n" (concat "\n" mail-header-separator "\n"))
762 nil t)
763 (setq border (point))
764 (error "header separator not found"))
765
766 ;; note that the point is placed at the border
767 (if (or (re-search-forward "^<sera>$" nil t)
768 (progn
769 (goto-char (point-min))
770 (re-search-forward "^Subject: <sera>" border t)))
771
772 ;; there are markers
773 (progn
774 ;; we start with the body so that the border will not change
775 ;; use "^<sera>\n" instead of "^<sera>$" not to leave a blank line
776 (goto-char border)
777 (while (re-search-forward "^<sera>\n" nil t)
778 (replace-match "")
779 (ethio-sera-to-fidel-region
780 (point)
781 (progn
782 (if (re-search-forward "^</sera>\n" nil 0)
783 (replace-match ""))
784 (point))))
785 ;; now process the subject
786 (goto-char (point-min))
787 (if (re-search-forward "^Subject: <sera>" border t)
788 (ethio-sera-to-fidel-region
789 (progn (delete-backward-char 6) (point))
790 (progn
791 (if (re-search-forward "</sera>$" (line-end-position) 0)
792 (replace-match ""))
793 (point)))))
794
795 ;; in case there are no marks but invoked interactively
796 (if arg
797 (progn
798 (ethio-sera-to-fidel-region border (point-max))
799 (goto-char (point-min))
800 (if (re-search-forward "^Subject: " border t)
801 (ethio-sera-to-fidel-region (point) (line-end-position))))))
802
803 ;; adjust the rmail marker
804 (if (eq major-mode 'rmail-mode)
805 (set-marker
806 (aref rmail-message-vector (1+ rmail-current-message))
807 (point-max))))))
808
809 ;;;###autoload
810 (defun ethio-sera-to-fidel-marker (&optional force)
811 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL.
812 Assume that each region begins with `ethio-primary-language'.
813 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
278 (interactive "P") 814 (interactive "P")
279 (if (and buffer-read-only 815 (if (and buffer-read-only
280 (not force) 816 (not force)
281 (not (y-or-n-p "Buffer is read-only. Force to convert? "))) 817 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
282 (error "")) 818 (error ""))
283 (let (start pre fol hard table table2 (buffer-read-only nil))
284 (goto-char (point-min))
285 (while (not (eobp))
286 (setq start (point))
287 (forward-char 1)
288 (setq pre (preceding-char)
289 fol (following-char))
290
291 (if ascii-mode
292 (cond
293
294 ;; ascii mode, pre != \
295 ((/= pre ?\\ ))
296
297 ;; ascii mode, pre = \, fol = !
298 ((= fol ?!)
299 (backward-delete-char 1)
300 (delete-char 1)
301 (setq ascii-mode nil
302 hard (not hard)))
303
304 ;; hard ascii mode, pre = \, fol != !
305 (hard)
306
307 ;; soft ascii mode, pre = \, fol = {\ _ * < > 0..9 ~}
308 ((or (backward-delete-char 1) ; always nil
309 (eobp)
310 (sera-to-fidel-backslash)))
311
312 ;; soft ascii mode, pre = \, fol = SPC
313 ((= fol 32)
314 (delete-char 1)
315 (setq ascii-mode nil))
316
317 ;; soft ascii mode, pre = \, fol = .
318 ((= fol ?.)
319 (delete-char 1)
320 (insert ?$(2$P(B))
321
322 ;; soft ascii mode, pre = \, fol = ,
323 ((= fol ?,)
324 (delete-char 1)
325 (insert ?$(2$Q(B))
326
327 ;; soft ascii mode, pre = \, fol = ;
328 ((= fol ?\;)
329 (delete-char 1)
330 (insert ?$(2$R(B))
331
332 ;; soft ascii mode, pre = \, fol = :
333 ((= fol ?:)
334 (delete-char 1)
335 (insert ?$(2$S(B))
336
337 ;; soft ascii mode, pre = \, fol = others
338 (t
339 (setq ascii-mode nil)))
340
341 (cond
342
343 ;; very special: skip "<" to ">" (or "&" to ";") if in w3-mode
344 ((and (boundp 'sera-being-called-by-w3)
345 sera-being-called-by-w3
346 (or (= pre ?<) (= pre ?&)))
347 (search-forward (if (= pre ?<) ">" ";")
348 nil 0))
349
350 ;; ethio mode, pre != sera
351 ((or (< pre ?') (> pre ?z)))
352
353 ;; ethio mode, pre != \
354 ((/= pre ?\\ )
355 (setq table (aref sera-to-fidel-table pre))
356 (while (setq table2 (cdr (assoc (following-char) table)))
357 (setq table table2)
358 (forward-char 1))
359 (if (car table)
360 (progn
361 (delete-region start (point))
362 (insert (car table)))))
363
364 ;; ethio mode, pre = \, fol = !
365 ((= fol ?!)
366 (backward-delete-char 1)
367 (delete-char 1)
368 (setq ascii-mode t
369 hard (not hard)))
370
371 ;; hard ethio mode, pre = \, fol != !
372 (hard)
373
374 ;; soft ethio mode, pre = \, fol = {\ _ * < > 0..9 ~}
375 ((or (backward-delete-char 1) ; always nil
376 (eobp)
377 (sera-to-fidel-backslash)))
378
379 ;; soft ethio mode, pre = \, fol = SPC
380 ((= fol 32)
381 (delete-char 1)
382 (setq ascii-mode t))
383
384 ;; soft ethio mode, pre = \, fol = {. , ; : | ' `}
385 ((memq fol '(?. ?, ?\; ?: ?| ?' ?`))
386 (forward-char 1))
387
388 ;; soft ethio mode, pre = \, fol = others
389 (t
390 (setq ascii-mode t))))))
391 (goto-char (point-min)))
392
393 (defun sera-to-fidel-backslash ()
394 "Handle SERA backslash escapes common to ethio- and ascii-mode.
395 Returns t if something has been processed."
396 (let ((ch (following-char))
397 (converted t))
398 (if (and (>= ch ?1) (<= ch ?9))
399 (ethio-convert-digit)
400 (delete-char 1)
401 (cond
402 ((= ch ?\\ )
403 (insert ?\\ ))
404 ((= ch ?_)
405 (insert ?$(2$O(B))
406 ((= ch ?*)
407 (insert ?$(2$T(B))
408 ((= ch ?<)
409 (insert ?$(2$U(B))
410 ((= ch ?>)
411 (insert ?$(2$V(B))
412 ((= ch ?~)
413 (setq ch (following-char))
414 (delete-char 1)
415 (cond
416 ((= ch ?e)
417 (insert "$(2$k(B"))
418 ((= ch ?E)
419 (insert "$(2$l(B"))
420 ((= ch ?a)
421 (insert "$(2$m(B"))
422 ((= ch ?A)
423 (insert "$(2$n(B"))))
424 (t
425 (insert ch)
426 (backward-char 1)
427 (setq converted nil))))
428 converted))
429
430 (defun ethio-convert-digit ()
431 "Convert Arabic digits to Ethiopic digits."
432 (let (ch z)
433 (while (and (>= (setq ch (following-char)) ?1)
434 (<= ch ?9))
435 (delete-char 1)
436
437 ;; count up following zeros
438 (setq z 0)
439 (while (= (following-char) ?0)
440 (delete-char 1)
441 (setq z (1+ z)))
442
443 (cond
444
445 ;; first digit is 10, 20, ..., or 90
446 ((= (mod z 2) 1)
447 ;; (- ch 40) means ?1 -> 9, ?2 -> 10, etc.
448 (insert (aref [?$(2$`(B ?$(2$a(B ?$(2$b(B ?$(2$c(B ?$(2$d(B ?$(2$e(B ?$(2$f(B ?$(2$g(B ?$(2$h(B] (- ch ?1)))
449 (setq z (1- z)))
450
451 ;; first digit is 2, 3, ..., or 9
452 ((/= ch ?1)
453 (insert (aref [?$(2$X(B ?$(2$Y(B ?$(2$Z(B ?$(2$[(B ?$(2$\(B ?$(2$](B ?$(2$^(B ?$(2$_(B] (- ch ?2))))
454
455 ;; single 1
456 ((= z 0)
457 (insert "$(2$W(B")))
458
459 ;; 100
460 (if (= (mod z 4) 2)
461 (insert"$(2$i(B"))
462
463 ;; 10000
464 (insert-char ?$(2$j(B (/ z 4)))))
465
466 ;;;###autoload
467 (defun sera-to-fidel-mail (&optional arg)
468 "Does SERA to FIDEL conversion for reading/writing mail and news.
469
470 If the buffer contains the markers \"<sera>\" and \"</sera>\",
471 converts the segment between the two markers in Ethio start mode and
472 the subject field in ASCII start mode.
473
474 If invoked interactively and there is no marker, converts both the
475 whole body and the subject field in Ethio start mode.
476
477 For backward compatibility, \"<ethiopic>\" and \"<>\" can be used instead of
478 \"<sera>\" and \"</sera>\"."
479
480 (interactive "p")
481 (let* ((buffer-read-only nil) border)
482
483 (save-excursion
484 (goto-char (point-min))
485 (setq border
486 (search-forward
487 (if (eq major-mode 'rmail-mode)
488 "\n\n"
489 (concat "\n" mail-header-separator "\n"))))
490
491 (cond
492
493 ;; with markers
494 ((re-search-forward "^<sera>\n" nil t)
495 (goto-char (match-beginning 0))
496 (while (re-search-forward "^<sera>\n" nil t)
497 (replace-match "" nil t)
498 (sera-to-fidel-region
499 (point)
500 (progn
501 (if (re-search-forward "^</sera>\n" nil 0)
502 (replace-match "" nil t))
503 (point))))
504
505 (goto-char (point-min))
506 (if (re-search-forward "^Subject: " border t)
507 (sera-to-fidel-region
508 (point)
509 (progn (end-of-line) (point))
510 'ascii-start)))
511
512 ;; backward compatibility
513 ((re-search-forward "^<ethiopic>\n" nil t)
514 (goto-char (match-beginning 0))
515 (while (re-search-forward "^<ethiopic>\n" nil t)
516 (replace-match "" nil t)
517 (sera-to-fidel-region
518 (setq border (point))
519 (progn
520 (if (re-search-forward "^<>\n" nil 0)
521 (replace-match "" nil t))
522 (point))))
523
524 (goto-char (point-min))
525 (if (re-search-forward "^Subject: " border t)
526 (sera-to-fidel-region
527 (point)
528 (progn (end-of-line) (point))
529 'ascii-start)))
530
531 ;; interactive & no markers
532 (arg
533 (sera-to-fidel-region border (point-max))
534 (goto-char (point-min))
535 (if (re-search-forward "^Subject: " border t)
536 (sera-to-fidel-region
537 (point)
538 (progn (end-of-line) (point))))))
539
540 ;; adjust the rmail marker
541 (if (eq major-mode 'rmail-mode)
542 (set-marker
543 (aref rmail-message-vector (1+ rmail-current-message))
544 (point-max))))))
545
546 ;;;###autoload
547 (defun sera-to-fidel-marker ()
548 "If the buffer contains the markers \"<sera>\" and \"</sera>\",
549 converts the segment between the two markers from SERA to Fidel
550 in Ethio start mode. The markers will not be removed."
551
552 (interactive)
553 (if (and buffer-read-only
554 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
555 (error ""))
556 (save-excursion 819 (save-excursion
557 (goto-char (point-min)) 820 (goto-char (point-min))
558 (while (re-search-forward "<sera>" nil t) 821 (while (re-search-forward "<sera>" nil t)
559 (sera-to-fidel-region 822 (ethio-sera-to-fidel-region
560 (point) 823 (point)
561 (if (re-search-forward "</sera>" nil t) 824 (if (re-search-forward "</sera>" nil t)
562 (match-beginning 0) 825 (match-beginning 0)
563 (point-max)) 826 (point-max))
564 nil 827 nil
566 829
567 ;; 830 ;;
568 ;; FIDEL to SERA 831 ;; FIDEL to SERA
569 ;; 832 ;;
570 833
571 (defconst fidel-to-sera-map 834 (defconst ethio-fidel-to-sera-map
572 ["le" "lu" "li" "la" "lE" "l" "lo" "lWa" 835 [ "he" "hu" "hi" "ha" "hE" "h" "ho" "" ;; 0 - 7
573 "me" "mu" "mi" "ma" "mE" "m" "mo" "mWa" 836 "le" "lu" "li" "la" "lE" "l" "lo" "lWa" ;; 8
574 "re" "ru" "ri" "ra" "rE" "r" "ro" "rWa" 837 "He" "Hu" "Hi" "Ha" "HE" "H" "Ho" "HWa" ;; 16
575 "xe" "xu" "xi" "xa" "xE" "x" "xo" "xWa" 838 "me" "mu" "mi" "ma" "mE" "m" "mo" "mWa" ;; 24
576 "be" "bu" "bi" "ba" "bE" "b" "bo" "bWa" 839 "`se" "`su" "`si" "`sa" "`sE" "`s" "`so" "`sWa" ;; 32
577 "ve" "vu" "vi" "va" "vE" "v" "vo" "vWa" 840 "re" "ru" "ri" "ra" "rE" "r" "ro" "rWa" ;; 40
578 "te" "tu" "ti" "ta" "tE" "t" "to" "tWa" 841 "se" "su" "si" "sa" "sE" "s" "so" "sWa" ;; 48
579 "ce" "cu" "ci" "ca" "cE" "c" "co" "cWa" 842 "xe" "xu" "xi" "xa" "xE" "x" "xo" "xWa" ;; 56
580 "ne" "nu" "ni" "na" "nE" "n" "no" "nWa" 843 "qe" "qu" "qi" "qa" "qE" "q" "qo" "" ;; 64
581 "Ne" "Nu" "Ni" "Na" "NE" "N" "No" "NWa" 844 "qWe" "" "qWi" "qWa" "qWE" "qW'" "" "" ;; 72
582 "ze" "zu" "zi" "za" "zE" "z" "zo" "zWa" 845 "Qe" "Qu" "Qi" "Qa" "QE" "Q" "Qo" "" ;; 80
583 "Ze" "Zu" "Zi" "Za" "ZE" "Z" "Zo" "ZWa" 846 "QWe" "" "QWi" "QWa" "QWE" "QW'" "" "" ;; 88
584 "de" "du" "di" "da" "dE" "d" "do" "dWa" 847 "be" "bu" "bi" "ba" "bE" "b" "bo" "bWa" ;; 96
585 "Te" "Tu" "Ti" "Ta" "TE" "T" "To" "TWa" 848 "ve" "vu" "vi" "va" "vE" "v" "vo" "vWa" ;; 104
586 "Ce" "Cu" "Ci" "Ca" "CE" "C" "Co" "CWa" 849 "te" "tu" "ti" "ta" "tE" "t" "to" "tWa" ;; 112
587 "fe" "fu" "fi" "fa" "fE" "f" "fo" "fWa" 850 "ce" "cu" "ci" "ca" "cE" "c" "co" "cWa" ;; 120
588 "se" "su" "si" "sa" "sE" "s" "so" "sWa" 851 "`he" "`hu" "`hi" "`ha" "`hE" "`h" "`ho" "" ;; 128
589 "Se" "Su" "Si" "Sa" "SE" "S" "So" "SWa" 852 "hWe" "" "hWi" "hWa" "hWE" "hW'" "" "" ;; 136
590 "a" "u" "i" "A" "E" "I" "o" "e3" 853 "ne" "nu" "ni" "na" "nE" "n" "no" "nWa" ;; 144
591 "he" "hu" "hi" "ha" "hE" "h" "ho" "hWe" "hWu" "hWi" "hWa" "hWE" 854 "Ne" "Nu" "Ni" "Na" "NE" "N" "No" "NWa" ;; 152
592 "ke" "ku" "ki" "ka" "kE" "k" "ko" "kWe" "kWu" "kWi" "kWa" "kWE" 855 "e" "u" "i" "A" "E" "I" "o" "ea" ;; 160
593 "Ke" "Ku" "Ki" "Ka" "KE" "K" "Ko" "KWe" "KWu" "KWi" "KWa" "KWE" 856 "ke" "ku" "ki" "ka" "kE" "k" "ko" "" ;; 168
594 "qe" "qu" "qi" "qa" "qE" "q" "qo" "qWe" "qWu" "qWi" "qWa" "qWE" 857 "kWe" "" "kWi" "kWa" "kWE" "kW'" "" "" ;; 176
595 "Qe" "Qu" "Qi" "Qa" "QE" "Q" "Qo" "QWe" "QWu" "QWi" "QWa" "QWE" 858 "Ke" "Ku" "Ki" "Ka" "KE" "K" "Ko" "" ;; 184
596 "ge" "gu" "gi" "ga" "gE" "g" "go" "gWe" "gWu" "gWi" "gWa" "gWE" 859 "KWe" "" "KWi" "KWa" "KWE" "KW'" "" "" ;; 192
597 "we" "wu" "wi" "wa" "wE" "w" "wo" "wWe" "wWu" "wWi" "wWa" "wWE" 860 "we" "wu" "wi" "wa" "wE" "w" "wo" "" ;; 200
598 "`se" "`su" "`si" "`sa" "`sE" "`s" "`so" 861 "`e" "`u" "`i" "`a" "`E" "`I" "`o" "" ;; 208
599 "`Se" "`Su" "`Si" "`Sa" "`SE" "`S" "`So" 862 "ze" "zu" "zi" "za" "zE" "z" "zo" "zWa" ;; 216
600 "`e" "`u" "`i" "`a" "`E" "`I" "`o" 863 "Ze" "Zu" "Zi" "Za" "ZE" "Z" "Zo" "ZWa" ;; 224
601 "`he" "`hu" "`hi" "`ha" "`hE" "`h" "`ho" 864 "ye" "yu" "yi" "ya" "yE" "y" "yo" "yWa" ;; 232
602 "`ke" "`ku" "`ki" "`ka" "`kE" "`k" "`ko" 865 "de" "du" "di" "da" "dE" "d" "do" "dWa" ;; 240
603 "Xe" "Xu" "Xi" "Xa" "XE" "X" "Xo" 866 "De" "Du" "Di" "Da" "DE" "D" "Do" "DWa" ;; 248
604 "He" "Hu" "Hi" "Ha" "HE" "H" "Ho" 867 "je" "ju" "ji" "ja" "jE" "j" "jo" "jWa" ;; 256
605 "ye" "yu" "yi" "ya" "yE" "y" "yo" 868 "ge" "gu" "gi" "ga" "gE" "g" "go" "" ;; 264
606 "De" "Du" "Di" "Da" "DE" "D" "Do" 869 "gWe" "" "gWi" "gWa" "gWE" "gW'" "" "" ;; 272
607 "je" "ju" "ji" "ja" "jE" "j" "jo" 870 "Ge" "Gu" "Gi" "Ga" "GE" "G" "Go" "GWa" ;; 280
608 "Ge" "Gu" "Gi" "Ga" "GE" "G" "Go" 871 "Te" "Tu" "Ti" "Ta" "TE" "T" "To" "TWa" ;; 288
609 "Pe" "Pu" "Pi" "Pa" "PE" "P" "Po" 872 "Ce" "Cu" "Ci" "Ca" "CE" "C" "Co" "CWa" ;; 296
610 "pe" "pu" "pi" "pa" "pE" "p" "po" 873 "Pe" "Pu" "Pi" "Pa" "PE" "P" "Po" "PWa" ;; 304
611 " " "\\_" "." "," ";" ":" "\\*" "\\<" "\\>" 874 "Se" "Su" "Si" "Sa" "SE" "S" "So" "SWa" ;; 312
612 "1" "2" "3" "4" "5" "6" "7" "8" "9" 875 "`Se" "`Su" "`Si" "`Sa" "`SE" "`S" "`So" "" ;; 320
613 "10" "20" "30" "40" "50" "60" "70" "80" "90" 876 "fe" "fu" "fi" "fa" "fE" "f" "fo" "fWa" ;; 328
614 "100" "10000" 877 "pe" "pu" "pi" "pa" "pE" "p" "po" "pWa" ;; 336
615 "\\~e" "\\~E" "\\~a" "\\~A"]) 878 "mYa" "rYa" "fYa" "" "" "" "" "" ;; 344
616 879 " " " : " "::" "," ";" "-:" ":-" "`?" ;; 352
617 (defvar ethio-use-tigrigna-style nil 880 ":|:" "1" "2" "3" "4" "5" "6" "7" ;; 360
618 "*If non-NIL, use \"e\" instead of \"a\" for the first lone vowel 881 "8" "9" "10" "20" "30" "40" "50" "60" ;; 368
619 translation in sera-to-fidel and fidel-to-sera conversions.") 882 "70" "80" "90" "100" "10000" "" "" "" ;; 376
620 883 "`qe" "`qu" "`qi" "`qa" "`qE" "`q" "`qo" "" ;; 384
621 (defvar ethio-quote-vowel-always nil 884 "mWe" "bWe" "GWe" "fWe" "pWe" "" "" "" ;; 392
622 "*If non-NIL, lone vowels are always transcribed by \"an apostrophe 885 "`ke" "`ku" "`ki" "`ka" "`kE" "`k" "`ko" "" ;; 400
623 + the vowel\" except at word initial. Otherwise, they are quoted by 886 "mWi" "bWi" "GWi" "fWi" "pWi" "" "" "" ;; 408
624 an apostrophe only if the preceding Ethiopic character is a lone 887 "Xe" "Xu" "Xi" "Xa" "XE" "X" "Xo" "" ;; 416
625 consonant.") 888 "mWE" "bWE" "GWE" "fWE" "pWE" "" "" "" ;; 424
626 889 "`ge" "`gu" "`gi" "`ga" "`gE" "`g" "`go" "" ;; 432
627 (defvar ethio-W-sixth-always nil 890 "mW'" "bW'" "GW'" "fW'" "pW'" "" "" "" ;; 440
628 "*If non-NIL, the Wu-form of a 12-form consonant is transcribed by 891 "\\~X " "\\~e " "\\~E " "\\~a " "\\~A " "wWe" "wWi" "wWa" ;; 448
629 \"W'\" instead of \"Wu\".") 892 "wWE" "wW'" "''" "`!" "." "<<" ">>" "?" ]) ;; 456
630 893
631 (defvar ethio-numeric-reduction 0 894 (defun ethio-prefer-amharic-p nil
632 "*Degree of reduction in transcribing Ethiopic digits by Arabic 895 (or (eq ethio-primary-language 'amharic)
633 digits. For example, $(2$`$_$i$g$](B ({10}{9}{100}{80}{7}) will be 896 (and (not (eq ethio-primary-language 'tigrigna))
634 transcribed by: 897 (eq ethio-secondary-language 'amharic))))
635 \10\9\100\80\7 if ETHIO-NUMERIC-REDUCTION is 0, 898
636 \109100807 is 1, 899 (defun ethio-language-to-flag (lang)
637 \10900807 is 2.") 900 (cond
901 ((eq lang 'english) "eng")
902 ((eq lang 'tigrigna) "tir")
903 ((eq lang 'amharic) "amh")
904 (t "")))
638 905
639 ;;;###autoload 906 ;;;###autoload
640 (defun fidel-to-sera-region (begin end &optional ascii-mode force) 907 (defun ethio-fidel-to-sera-region (begin end &optional secondary force)
641 "Replaces all the FIDEL characters in the region to sera format. 908 "Replace all the FIDEL characters in the region to the SERA format.
642 909 The variable `ethio-primary-language' specifies the primary
643 If the 1st optional parameter ASCII-MODE is non-NIL, converts the 910 language and `ethio-secondary-language' specifies the secondary.
644 region so that it begins in ASCII script. 911
645 912 If the 3dr parameter SECONDARY is given and non-nil, try to convert
646 If the 2nd optional parameter FORCE is non-NIL, converts even if the 913 the region so that it begins in the secondary language; otherwise with
647 buffer is read-only." 914 the primary language.
915
916 If the 4th parameter FORCE is given and non-nil, convert even if the
917 buffer is read-only.
918
919 See also the descriptions of the variables
920 `ethio-use-colen-for-colon', `ethio-use-three-dot-question',
921 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
648 922
649 (interactive "r\nP") 923 (interactive "r\nP")
650 (save-excursion 924 (save-restriction
651 (save-restriction 925 (narrow-to-region begin end)
652 (narrow-to-region begin end) 926 (ethio-fidel-to-sera-buffer secondary force)))
653 (fidel-to-sera-buffer ascii-mode force))))
654 927
655 ;;;###autoload 928 ;;;###autoload
656 (defun fidel-to-sera-buffer (&optional ascii-mode force) 929 (defun ethio-fidel-to-sera-buffer (&optional secondary force)
657 "Replace all the FIDEL characters in the current buffer to sera format. 930 "Replace all the FIDEL characters in the current buffer to the SERA format.
658 931 The variable `ethio-primary-language' specifies the primary
659 If the 1st optional parameter ASCII-MODE is non-NIL, 932 language and `ethio-secondary-language' specifies the secondary.
660 convert the current buffer so that it begins in ASCII script. 933
661 934 If the 1st optional parameter SECONDARY is non-nil, try to convert the
662 If the 2nd optional parameter FORCE is non-NIL, converts even if the 935 region so that it begins in the secondary language; otherwise with the
936 primary language.
937
938 If the 2nd optional parameter FORCE is non-nil, convert even if the
663 buffer is read-only. 939 buffer is read-only.
664 940
665 See also the description of the variables ethio-use-tigrigna-style, 941 See also the descriptions of the variables
666 ethio-quote-vowel-on-demand and ethio-numeric-reduction." 942 `ethio-use-colen-for-colon', `ethio-use-three-dot-question',
943 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
667 944
668 (interactive "P") 945 (interactive "P")
669 (if (and buffer-read-only 946 (if (and buffer-read-only
670 (not force) 947 (not force)
671 (not (y-or-n-p "Buffer is read-only. Force to convert? "))) 948 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
672 (error "")) 949 (error ""))
673 950
674 ;; user's preference in transcription 951 (let ((buffer-read-only nil)
675 (aset fidel-to-sera-map 144 (if ethio-use-tigrigna-style "e" "a")) 952 (case-fold-search nil)
676 (let ((i 160) 953 (lonec nil) ;; t means previous char was a lone consonant
677 (x (if ethio-W-sixth-always 954 (fidel nil) ;; t means previous char was a FIDEL
678 '("hW'" "kW'" "KW'" "qW'" "QW'" "gW'" "wW'") 955 (digit nil) ;; t means previous char was an Ethiopic digit
679 '("hWu" "kWu" "KWu" "qWu" "QWu" "gWu" "wWu")))) 956 (flag (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir "))
680 (while x 957 mode ch)
681 (aset fidel-to-sera-map i (car x)) 958
682 (setq i (+ i 12) 959 ;; user's preference in transcription
683 x (cdr x)))) 960 (if ethio-use-colon-for-colon
684 961 (progn
685 ;; main conversion routine 962 (aset ethio-fidel-to-sera-map 353 "`:")
686 (let ((lonec nil) ; if lonec = t, previous char was a lone consonant. 963 (aset ethio-fidel-to-sera-map 357 ":"))
687 (fidel nil) ; if fidel = t, previous char was a fidel. 964 (aset ethio-fidel-to-sera-map 353 " : ")
688 (digit nil) ; if digit = t, previous char was an Ethiopic digit. 965 (aset ethio-fidel-to-sera-map 357 "-:"))
689 (buffer-read-only nil) 966
690 ch) 967 (if ethio-use-three-dot-question
968 (progn
969 (aset ethio-fidel-to-sera-map 359 "?")
970 (aset ethio-fidel-to-sera-map 463 "`?"))
971 (aset ethio-fidel-to-sera-map 359 "`?")
972 (aset ethio-fidel-to-sera-map 463 "?"))
973
974 (mapcar
975 '(lambda (x)
976 (aset (aref ethio-fidel-to-sera-map x)
977 2
978 (if ethio-W-sixth-always ?' ?u)))
979 '(77 93 141 181 197 277 440 441 442 443 444 457))
980
981 (if (ethio-prefer-amharic-p)
982 (aset ethio-fidel-to-sera-map 160 "a")
983 (aset ethio-fidel-to-sera-map 160 "e"))
984 ;; end of user's preference
985
986 ;; first, decompose geminated characters
987 (decompose-region (point-min) (point-max))
988
989 ;; main conversion routine
691 (goto-char (point-min)) 990 (goto-char (point-min))
692 (while (not (eobp)) 991 (while (not (eobp))
693 (setq ch (following-char)) 992 (setq ch (following-char))
694 993
695 ;; ethiopic charactes 994 (cond ; ethiopic, english, neutral
696 (if (eq (char-charset ch) 'ethiopic) 995
697 (progn 996 ;; ethiopic character. must go to ethiopic mode, if not in it.
698 (setq ch (char-to-ethiocode ch)) 997 ((eq (char-charset ch) 'ethiopic)
699 (delete-char 1) 998 (setq ch (ethio-char-to-ethiocode ch))
700 999 (delete-char 1)
701 (cond 1000 (if (not (eq mode 'ethiopic))
702 1001 (progn
703 ;; fidels 1002 (insert flag)
704 ((<= ch 326) 1003 (setq mode 'ethiopic)))
705 (if ascii-mode 1004
706 (insert "\\ ")) 1005 (cond ; fidel, punc, digit
707 (if (and (memq ch '(144 145 146 147 148 150 151)) ; (auiAEoe3) 1006
708 (or lonec 1007 ;; fidels
709 (and ethio-quote-vowel-always 1008 ((or (<= ch 346) ; he - fYa
710 fidel))) 1009 (and (>= ch 384) (<= ch 444)) ; `qe - pw
711 (insert "'")) 1010 (and (>= ch 453) (<= ch 457))) ; wWe - wW
712 (insert (aref fidel-to-sera-map ch)) 1011 (if (and (memq ch '(160 161 162 163 164 166 167)) ; (e - ea)
713 (setq ascii-mode nil 1012 (or lonec
714 lonec (ethio-lone-consonant-p ch) 1013 (and ethio-quote-vowel-always
715 fidel t 1014 fidel)))
716 digit nil)) 1015 (insert "'"))
717 1016 (insert (aref ethio-fidel-to-sera-map ch))
718 ;; punctuations and symbols 1017 (setq lonec (ethio-lone-consonant-p ch)
719 ((or (< ch 336) (> ch 355)) 1018 fidel t
720 (if (and ascii-mode 1019 digit nil))
721 (memq ch '(329 330 331 332))) ; (.,;:) 1020
722 (insert "\\")) 1021 ;; punctuations or icons
723 (insert (aref fidel-to-sera-map ch)) 1022 ((or (and (>= ch 353) (<= ch 360)) ; : - :|:
724 (setq lonec nil 1023 (>= ch 458) ; '' - ?
725 fidel nil 1024 (and (>= ch 448) (<= ch 452))) ; \~X \~e \~E \~a \~A
726 digit nil)) 1025 (insert (aref ethio-fidel-to-sera-map ch))
727 1026 (setq lonec nil
728 ;; now CH must be an ethiopic digit 1027 fidel nil
729 1028 digit nil))
730 ;; reduction = 0 or leading digit 1029
731 ((or (= ethio-numeric-reduction 0) 1030 ;; now CH must be an ethiopic digit
732 (not digit)) 1031
733 (insert "\\" (aref fidel-to-sera-map ch)) 1032 ;; reduction = 0 or not preceded by Ethiopic number(s)
734 (setq lonec nil 1033 ((or (= ethio-numeric-reduction 0)
735 fidel nil 1034 (not digit))
736 digit t)) 1035 (insert "`" (aref ethio-fidel-to-sera-map ch))
737 1036 (setq lonec nil
738 ;; reduction = 2 and following 10s, 100s, 10000s 1037 fidel nil
739 ((and (= ethio-numeric-reduction 2) 1038 digit t))
740 (memq ch '(345 354 355))) 1039
741 (insert (substring (aref fidel-to-sera-map ch) 1)) 1040 ;; reduction = 2 and following 10s, 100s, 10000s
742 (setq lonec nil 1041 ((and (= ethio-numeric-reduction 2)
743 fidel nil 1042 (memq ch '(370 379 380)))
744 digit t)) 1043 (insert (substring (aref ethio-fidel-to-sera-map ch) 1))
745 1044 (setq lonec nil
746 ;; ordinary following digits 1045 fidel nil
747 (t 1046 digit t))
748 (insert (aref fidel-to-sera-map ch)) 1047
749 (setq lonec nil 1048 ;; ordinary following digits
750 fidel nil 1049 (t
751 digit t)))) 1050 (insert (aref ethio-fidel-to-sera-map ch))
752 1051 (setq lonec nil
753 ;; non-ethiopic characters 1052 fidel nil
754 (cond 1053 digit t))))
1054
1055 ;; english character. must go to english mode, if not in it.
1056 ((or (and (>= ch ?a) (<= ch ?z))
1057 (and (>= ch ?A) (<= ch ?Z)))
1058 (if (not (eq mode 'english))
1059 (insert "\\~eng "))
1060 (forward-char 1)
1061 (setq mode 'english
1062 lonec nil
1063 fidel nil
1064 digit nil))
1065
1066 ;; ch can appear both in ethiopic section and in english section.
1067 (t
1068
1069 ;; we must decide the mode, if not decided yet
1070 (if (null mode)
1071 (progn
1072 (setq mode
1073 (if secondary
1074 ethio-secondary-language
1075 ethio-primary-language))
1076 (if (eq mode 'english)
1077 (insert "\\~eng ")
1078 (insert flag)
1079 (setq mode 'ethiopic)))) ; tigrigna & amharic --> ethiopic
1080
1081 (cond ; \ , eng-mode , punc , w3 , other
755 1082
756 ;; backslash is always quoted 1083 ;; backslash is always quoted
757 ((= ch ?\\ ) 1084 ((= ch ?\\ )
758 (insert "\\")) 1085 (insert "\\")
759 1086 (forward-char 1))
760 ;; nothing to do if in ascii-mode 1087
761 (ascii-mode) 1088 ;; nothing to do if in english mode
762 1089 ((eq mode 'english)
763 ;; ethio-mode -> ascii-mode 1090 (forward-char 1))
764 ((or (and (>= ch ?a) (<= ch ?z)) 1091
765 (and (>= ch ?A) (<= ch ?Z)) 1092 ;; now we must be in ethiopic mode and seeing a non-"\"
766 (memq ch '(?| ?' ?`))) 1093
767 (insert "\\ ") 1094 ;; ascii punctuations in ethiopic mode
768 (setq ascii-mode t)) 1095 ((looking-at "[,.;:'`?]+")
769 1096 (insert "\\")
770 ;; ascii punctuations in ethio-mode 1097 (goto-char (1+ (match-end 0)))) ; because we inserted one byte (\)
771 ((memq ch '(?. ?, ?\; ?:)) 1098
772 (insert "\\"))) 1099 ;; skip from "<" to ">" (or from "&" to ";") if called from w3
773 1100 ((and (boundp 'sera-being-called-by-w3)
774 (forward-char 1) 1101 sera-being-called-by-w3
1102 (or (= ch ?<) (= ch ?&)))
1103 (search-forward (if (= ch ?<) ">" ";")
1104 nil 0))
1105
1106 ;; neutral character. no need to quote. just skip it.
1107 (t
1108 (forward-char 1)))
1109
775 (setq lonec nil 1110 (setq lonec nil
776 fidel nil 1111 fidel nil
777 digit nil))) 1112 digit nil)))
778 1113 ;; end of main conversion routine
779 ;; a few modifications for readability 1114 )))
780 (goto-char (point-min)) 1115
781 (while (re-search-forward "\\([]!\"#$%&()*+/<=>?@[^_-]+\\)\\\\ " nil t) 1116 (defun ethio-lone-consonant-p (ethiocode)
782 (replace-match "\\\\ \\1")) 1117 "If ETHIOCODE is an Ethiopic lone consonant, return t."
783 1118 (or (and (< ethiocode 344) (= (% ethiocode 8) 5))
784 (goto-char (point-min)) 1119
785 (while (re-search-forward "\n\\([ \t]*\\)\\\\ " nil t) 1120 ;; `q `k X `g mW bW GW fW pW wW
786 (replace-match "\\\\\n\\1"))) 1121 (memq ethiocode '(389 405 421 437 440 441 442 443 444 457))))
787
788 (goto-char (point-min)))
789
790 (defun ethio-lone-consonant-p (code)
791 "If the ethiocode CODE is an Ethiopic lone consonant, return t."
792 (cond
793 ((< code 144)
794 (= (mod code 8) 5))
795 ((< code 153)
796 nil)
797 ((< code 236)
798 (= (mod code 12) 1))
799 ((< code 327)
800 (= (mod code 7) 3))))
801 1122
802 ;;;###autoload 1123 ;;;###autoload
803 (defun fidel-to-sera-mail () 1124 (defun ethio-fidel-to-sera-mail nil
804 "Does FIDEL to SERA conversion for reading/writing mail and news. 1125 "Convert FIDEL to SERA to read/write mail and news.
805 1126
806 If the buffer contains at least one Ethiopic character, 1127 If the body contains at least one Ethiopic character,
807 1) inserts the string \"<sera>\" right after the header-body separator, 1128 1) insert the string \"<sera>\" at the beginning of the body,
808 2) inserts \"</sera>\" at the end of the buffer, 1129 2) insert \"</sera>\" at the end of the body, and
809 3) converts the body into SERA in Ethiopic start mode, and 1130 3) convert the body into SERA.
810 4) converts the subject field in ASCII start mode." 1131
1132 The very same procedure applies to the subject field, too."
811 1133
812 (interactive) 1134 (interactive)
813 (save-excursion 1135 (let ((buffer-read-only nil)
814 (goto-char (point-min)) 1136 border)
815 (if (re-search-forward "\\cE" nil t) 1137 (save-excursion
816 (let ((buffer-read-only nil) border) 1138
817 1139 ;; look for the header-body separator
818 (goto-char (point-min)) 1140 (goto-char (point-min))
819 (setq border 1141 (if (search-forward
820 (search-forward 1142 (if (eq major-mode 'rmail-mode)
821 (if (eq major-mode 'rmail-mode) 1143 "\n\n" (concat "\n" mail-header-separator "\n"))
822 "\n\n" 1144 nil t)
823 (concat "\n" mail-header-separator "\n")))) 1145 (setq border (point))
824 (insert "<sera>\n") 1146 (error "header separator not found"))
825 1147
826 (fidel-to-sera-region (point) (point-max)) 1148 ;; process body first not to change the border
827 1149 ;; note that the point is already at the border
828 (goto-char (point-max)) 1150 (if (re-search-forward "\\ce" nil t)
829 (if (/= (preceding-char) ?\n) 1151 (progn
830 (insert "\n")) 1152 (ethio-fidel-to-sera-region border (point-max))
831 (insert "</sera>\n") 1153 (goto-char border)
832 1154 (insert "<sera>")
833 (goto-char (point-min)) 1155 (goto-char (point-max))
834 (if (re-search-forward "^Subject: " border t) 1156 (insert "</sera>")))
835 (fidel-to-sera-region 1157
836 (point) 1158 ;; process subject
837 (progn (end-of-line) (point)) 1159 (goto-char (point-min))
838 'ascii-start)) 1160 (if (re-search-forward "^Subject: " border t)
839 1161 (let ((beg (point))
840 ;; adjust the rmail marker 1162 (end (line-end-position)))
841 (if (eq major-mode 'rmail-mode) 1163 (if (re-search-forward "\\ce" end t)
842 (set-marker 1164 (progn
843 (aref rmail-message-vector (1+ rmail-current-message)) 1165 (ethio-fidel-to-sera-region beg end)
844 (point-max)))) 1166 (goto-char beg)
845 1167 (insert "<sera>")
846 (message "No Ethiopic characters in this buffer.")))) 1168 (end-of-line)
1169 (insert "</sera>")))))
1170
1171 ;; adjust the rmail marker
1172 (if (eq major-mode 'rmail-mode)
1173 (set-marker
1174 (aref rmail-message-vector (1+ rmail-current-message))
1175 (point-max))))))
847 1176
848 ;;;###autoload 1177 ;;;###autoload
849 (defun fidel-to-sera-marker () 1178 (defun ethio-fidel-to-sera-marker (&optional force)
850 "If the buffer contains the markers \"<sera>\" and \"</sera>\", 1179 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA.
851 converts the segment between the two markers from Fidel to SERA 1180 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
852 in Ethio start mode. The markers will not be removed." 1181
853 1182 (interactive "P")
854 (interactive)
855 (if (and buffer-read-only 1183 (if (and buffer-read-only
1184 (not force)
856 (not (y-or-n-p "Buffer is read-only. Force to convert? "))) 1185 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
857 (error "")) 1186 (error ""))
858 (save-excursion 1187 (save-excursion
859 (goto-char (point-min)) 1188 (goto-char (point-min))
860 (while (re-search-forward "^<sera>\n" nil t) 1189 (while (re-search-forward "<sera>" nil t)
861 (fidel-to-sera-region 1190 (ethio-fidel-to-sera-region
862 (point) 1191 (point)
863 (if (re-search-forward "^</sera>\n" nil t) 1192 (if (re-search-forward "</sera>" nil t)
864 (match-beginning 0) 1193 (match-beginning 0)
865 (point-max)) 1194 (point-max))
866 nil 1195 nil
867 'force)))) 1196 'force))))
868 1197
869 ;; 1198 ;;
870 ;; file I/O hooks 1199 ;; vowel modification
871 ;; 1200 ;;
872
873 (if (not (assoc "\\.sera$" auto-mode-alist))
874 (setq auto-mode-alist
875 (cons '("\\.sera$" . sera-to-fidel-find-file) auto-mode-alist)))
876 (add-hook 'write-file-hooks 'fidel-to-sera-write-file)
877 (add-hook 'after-save-hook 'sera-to-fidel-after-save)
878 1201
879 ;;;###autoload 1202 ;;;###autoload
880 (defun sera-to-fidel-find-file () 1203 (defun ethio-modify-vowel nil
881 "Intended to be called when a file whose name ends in \".sera\" is read in."
882 (sera-to-fidel-buffer nil 'force)
883 (set-buffer-modified-p nil)
884 nil)
885
886 ;;;###autoload
887 (defun fidel-to-sera-write-file ()
888 "Intended to be used as write-file-hooks for the files
889 whose name ends in \".sera\"."
890 (if (string-match "\\.sera$" (buffer-file-name))
891 (save-excursion
892 (fidel-to-sera-buffer nil 'force)
893 (set-buffer-modified-p nil)))
894 nil)
895
896 ;;;###autoload
897 (defun sera-to-fidel-after-save ()
898 "Intended to be used as after-save-hook for the files
899 whose name ends in \".sera\"."
900 (if (string-match "\\.sera$" (buffer-file-name))
901 (save-excursion
902 (sera-to-fidel-buffer nil 'force)
903 (set-buffer-modified-p nil)))
904 nil)
905
906 ;;
907 ;; vowel modification
908 ;;
909
910 ;;;###autoload
911 (defun ethio-modify-vowel ()
912 "Modify the vowel of the FIDEL that is under the cursor." 1204 "Modify the vowel of the FIDEL that is under the cursor."
913 (interactive) 1205 (interactive)
914 (let ((ch (following-char)) newch base vowel) 1206 (let ((ch (following-char))
915 (if (eq (char-charset ch) 'ethiopic) 1207 (composite nil) ; geminated or not
916 (setq ch (char-to-ethiocode ch)) 1208 newch base vowel modulo)
917 (error "Not a valid character.")) 1209
918 (if (or (and (>= ch 144) (<= ch 151)) ; lone vowels 1210 (cond
919 (and (>= ch 250) (<= ch 256)) ; secondary lone vowels 1211 ;; in case of gemination
920 (>= ch 327)) ; not FIDEL 1212 ((eq (char-charset ch) 'composition)
1213 (setq ch (string-to-char (decompose-composite-char ch))
1214 composite t))
1215 ;; neither gemination nor fidel
1216 ((not (eq (char-charset ch) 'ethiopic))
1217 (error "Not a valid character.")))
1218
1219 ;; set frequently referred character features
1220 (setq ch (ethio-char-to-ethiocode ch)
1221 base (* (/ ch 8) 8)
1222 modulo (% ch 8))
1223
1224 (if (or (and (>= ch 344) (<= ch 380)) ;; mYa - `10000
1225 (and (>= ch 448) (<= ch 452)) ;; \~X - \~A
1226 (>= ch 458)) ;; private punctuations
921 (error "Not a valid character.")) 1227 (error "Not a valid character."))
922 (message "Modify vowel to: ") 1228
923 (if (null (setq vowel (memq (read-char) '(?e ?u ?i ?a ?E ?' ?o)))) 1229 (setq
924 (error "Not a valid vowel.") 1230 newch
925 ;; ?e -> 0, ?u -> 1, ?i -> 2, ?a -> 3, ?E -> 4, ?' -> 5, ?o -> 6 1231 (cond
926 (setq vowel (- 7 (length vowel)))) 1232
1233 ;; first standalone vowels
1234 ((= base 160)
1235 (if (ethio-prefer-amharic-p)
1236 (message "Modify vowel to: [auiAEIoW\"] ")
1237 (message "Modify vowel to: [euiAEIoW\"] "))
1238 (setq vowel (read-char))
1239 (cond
1240 ((= vowel ?e) 160)
1241 ((= vowel ?u) 161)
1242 ((= vowel ?i) 162)
1243 ((= vowel ?A) 163)
1244 ((= vowel ?E) 164)
1245 ((= vowel ?I) 165)
1246 ((= vowel ?o) 166)
1247 ((= vowel ?W) 167)
1248 ((= vowel ?a) (if (ethio-prefer-amharic-p) 160 163))
1249 ((= vowel ?\") (setq composite t) ch)
1250 (t nil)))
1251
1252 ;; second standalone vowels
1253 ((= base 208)
1254 (message "Modify vowel to: [euiaEIo\"] ")
1255 (setq vowel (read-char))
1256 (cond
1257 ((= vowel ?e) 208)
1258 ((= vowel ?u) 209)
1259 ((= vowel ?i) 210)
1260 ((= vowel ?a) 211)
1261 ((= vowel ?E) 212)
1262 ((= vowel ?I) 213)
1263 ((= vowel ?o) 214)
1264 ((= vowel ?\") (setq composite t) ch)
1265 (t nil)))
1266
1267 ;; 12-form consonants, *W* form
1268 ((memq base '(72 88 136 176 192 272)) ; qW QW hW kW KW gW
1269 (message "Modify vowel to: [euiaE'\"] ")
1270 (setq vowel (read-char))
1271 (cond
1272 ((= vowel ?e) base)
1273 ((= vowel ?u) (+ base 5))
1274 ((= vowel ?i) (+ base 2))
1275 ((= vowel ?a) (+ base 3))
1276 ((= vowel ?E) (+ base 4))
1277 ((= vowel ?') (+ base 5))
1278 ((= vowel ?\") (setq composite t) ch)
1279 (t nil)))
1280
1281 ;; extended 12-form consonants, mWa bWa GWa fWa pWa
1282 ((= ch 31) ; mWa
1283 (message "Modify vowel to: [euiaE'\"] ")
1284 (setq vowel (read-char))
1285 (cond
1286 ((= vowel ?e) 392)
1287 ((= vowel ?u) 440)
1288 ((= vowel ?i) 408)
1289 ((= vowel ?a) ch)
1290 ((= vowel ?E) 424)
1291 ((= vowel ?') 440)
1292 ((= vowel ?\") (setq composite t) ch)
1293 (t nil)))
1294 ((= ch 103) ; bWa
1295 (message "Modify vowel to: [euiaE'\"] ")
1296 (setq vowel (read-char))
1297 (cond
1298 ((= vowel ?e) 393)
1299 ((= vowel ?u) 441)
1300 ((= vowel ?i) 409)
1301 ((= vowel ?a) ch)
1302 ((= vowel ?E) 425)
1303 ((= vowel ?') 441)
1304 ((= vowel ?\") (setq composite t) ch)
1305 (t nil)))
1306 ((= ch 287) ; GWa
1307 (message "Modify vowel to: [euiaE'\"] ")
1308 (setq vowel (read-char))
1309 (cond
1310 ((= vowel ?e) 394)
1311 ((= vowel ?u) 442)
1312 ((= vowel ?i) 410)
1313 ((= vowel ?a) ch)
1314 ((= vowel ?E) 426)
1315 ((= vowel ?') 442)
1316 ((= vowel ?\") (setq composite t) ch)
1317 (t nil)))
1318 ((= ch 335) ; fWa
1319 (message "Modify vowel to: [euiaE'\"] ")
1320 (setq vowel (read-char))
1321 (cond
1322 ((= vowel ?e) 395)
1323 ((= vowel ?u) 443)
1324 ((= vowel ?i) 411)
1325 ((= vowel ?a) ch)
1326 ((= vowel ?E) 427)
1327 ((= vowel ?') 443)
1328 ((= vowel ?\") (setq composite t) ch)
1329 (t nil)))
1330 ((= ch 343) ; pWa
1331 (message "Modify vowel to: [euiaE'\"] ")
1332 (setq vowel (read-char))
1333 (cond
1334 ((= vowel ?e) 396)
1335 ((= vowel ?u) 444)
1336 ((= vowel ?i) 412)
1337 ((= vowel ?a) ch)
1338 ((= vowel ?E) 428)
1339 ((= vowel ?') 444)
1340 ((= vowel ?\") (setq composite t) ch)
1341 (t nil)))
1342
1343 ;; extended 12-form consonatns, mW* bW* GW* fW* pW*
1344 ((memq base '(392 408 424 440)) ; *We *Wi *WE *W
1345 (message "Modify vowel to: [eiEau'\"] ")
1346 (setq vowel (read-char))
1347 (cond
1348 ((= vowel ?e) (+ 392 modulo))
1349 ((= vowel ?i) (+ 408 modulo))
1350 ((= vowel ?E) (+ 424 modulo))
1351 ((= vowel ?a) (cond
1352 ((= modulo 0) 31) ; mWa
1353 ((= modulo 1) 103) ; bWa
1354 ((= modulo 2) 287) ; GWa
1355 ((= modulo 3) 335) ; fWa
1356 ((= modulo 4) 343) ; pWa
1357 (t nil))) ; never reach here
1358 ((= vowel ?') (+ 440 modulo))
1359 ((= vowel ?u) (+ 440 modulo))
1360 ((= vowel ?\") (setq composite t) ch)
1361 (t nil)))
1362
1363 ((and (>= ch 453) (<= ch 457)) ; wWe wWi wWa wWE wW
1364 (message "Modify vowel to: [eiaE'u\"] ")
1365 (setq vowel (read-char))
1366 (cond
1367 ((= vowel ?e) 453)
1368 ((= vowel ?i) 454)
1369 ((= vowel ?a) 455)
1370 ((= vowel ?E) 456)
1371 ((= vowel ?') 457)
1372 ((= vowel ?u) 457)
1373 ((= vowel ?\") (setq composite t) ch)
1374 (t nil)))
1375
1376 ;; 7-form consonants, or
1377 ;; first 7 of 8-form consonants
1378 ((<= modulo 6)
1379 (message "Modify vowel to: [euiaE'o\"] ")
1380 (setq vowel (read-char))
1381 (cond
1382 ((= vowel ?e) base)
1383 ((= vowel ?u) (+ base 1))
1384 ((= vowel ?i) (+ base 2))
1385 ((= vowel ?a) (+ base 3))
1386 ((= vowel ?E) (+ base 4))
1387 ((= vowel ?') (+ base 5))
1388 ((= vowel ?o) (+ base 6))
1389 ((= vowel ?\") (setq composite t) ch)
1390 (t nil)))
1391
1392 ;; otherwise
1393 (t
1394 nil)))
927 1395
928 (cond 1396 (cond
929 1397
930 ;; 8-form consonant 1398 ;; could not get new character
931 ((<= ch 143) 1399 ((null newch)
932 (setq base (* (/ ch 8) 8)) 1400 (error "Invalid vowel"))
933 (cond 1401
934 ((< (mod ch 8) 7) ; e-form <= ch <= o-form 1402 ;; vowel changed on a composite Fidel
935 (setq newch (+ base vowel))) 1403 (composite
936 ((= vowel 3) ; 3 = a 1404 (delete-char 1)
937 (setq newch (+ base 7))) ; (+ base 7) = Wa-form 1405 (insert
938 ((= vowel 5) ; 5 = ' 1406 (compose-string
939 (setq newch 1407 (concat (char-to-string (ethio-ethiocode-to-char newch)) "$(3%s(B"))))
940 (cons (+ base 5) ; (+ base 5) = lone consonant 1408
941 232))) ; 232 = Wu 1409 ;; simple vowel modification
942 (t
943 (setq newch
944 (cons (+ base 5) ; (+ base 5) = lone consonant
945 (+ 231 vowel)))))) ; 231 = We
946
947 ;; 12-form consonant
948 ((<= ch 235)
949 (setq ch (- ch 152) ; 152 = 12-form consonant offset
950 base (* (/ ch 12) 12))
951 (cond
952 ((< (mod ch 12) 7) ; e-form <= ch <= o-form
953 (setq newch (+ base vowel 152)))
954 ((< vowel 5) ; We-form <= ch <= WE-form
955 (setq newch (+ base vowel 159))) ; 159 = 152 (offset) + 7 (We-form)
956 ((= vowel 5) ; 5 = ' (= u in this case)
957 (setq newch (+ base 160))) ; 160 = 152 (offset) + 8 (Wu-form)
958 (t
959 (error "Not a valid vowel."))))
960
961 ;; 7-form consonant
962 (t ; 236 = 7-form consonant offset
963 (setq newch (+ (* (/ (- ch 236) 7) 7) vowel 236))))
964
965 (delete-char 1)
966
967 (cond
968 ((consp newch)
969 (insert (ethiocode-to-char (car newch))
970 (ethiocode-to-char (cdr newch)))
971 (backward-char 2))
972 (t 1410 (t
973 (insert (ethiocode-to-char newch)) 1411 (delete-char 1)
974 (backward-char 1))))) 1412 (insert (ethio-ethiocode-to-char newch))))))
975 1413
976 (defun ethiocode-to-char (code) 1414 (defun ethio-ethiocode-to-char (ethiocode)
977 (make-char 'ethiopic (/ code 94) (mod code 94))) 1415 (make-char
978 1416 'ethiopic
979 (defun char-to-ethiocode (ch) 1417 (+ (/ ethiocode 94) 33)
1418 (+ (mod ethiocode 94) 33)))
1419
1420 (defun ethio-char-to-ethiocode (ch)
980 (and (eq (char-charset ch) 'ethiopic) 1421 (and (eq (char-charset ch) 'ethiopic)
981 (let ((char-components (split-char ch))) 1422 (let ((char-components (split-char ch)))
982 (+ (* (- (nth char-components 1) 161) 94) 1423 (+ (* (- (nth 1 char-components) 33) 94)
983 (- (nth char-components 2) 161))))) 1424 (- (nth 2 char-components) 33)))))
984 1425
985 ;; 1426 ;;
986 ;; space replacement 1427 ;; space replacement
987 ;; 1428 ;;
988 1429
989 ;;;###autoload 1430 ;;;###autoload
990 (defun ethio-replace-space (ch begin end) 1431 (defun ethio-replace-space (ch begin end)
991 "In the specified region, replace spaces between two Ethiopic characters." 1432 "Replace ASCII spaces with Ethiopic word separators in the region.
1433
1434 In the specified region, replace word separators surrounded by two
1435 Ethiopic characters, depending on the first parameter CH, which should
1436 be 1, 2, or 3.
1437
1438 If CH = 1, word separator will be replaced with an ASCII space.
1439 If CH = 2, with two ASCII spaces.
1440 If CH = 3, with the Ethiopic colon-like word separator.
1441
1442 The second and third parameters BEGIN and END specify the region."
1443
992 (interactive "*cReplace spaces to: 1 (sg col), 2 (dbl col), 3 (Ethiopic)\nr") 1444 (interactive "*cReplace spaces to: 1 (sg col), 2 (dbl col), 3 (Ethiopic)\nr")
993 (if (not (memq ch '(?1 ?2 ?3))) 1445 (if (not (memq ch '(?1 ?2 ?3)))
994 (error "")) 1446 (error ""))
995 (save-excursion 1447 (save-excursion
996 (save-restriction 1448 (save-restriction
997 (narrow-to-region begin end) 1449 (narrow-to-region begin end)
998 (goto-char (point-min))
999 1450
1000 (cond 1451 (cond
1001
1002 ((= ch ?1) 1452 ((= ch ?1)
1003 1453 ;; an Ethiopic word separator --> an ASCII space
1004 ;; A double column space or an Ethiopic word separator is always 1454 (goto-char (point-min))
1005 ;; converted to an ASCII space. 1455 (while (search-forward "$(3$h(B" nil t)
1006 (while (re-search-forward "[$(2$N$O(B]" nil t) 1456 (replace-match " " nil t))
1007 (replace-match " " nil nil))) 1457
1458 ;; two ASCII spaces between Ethiopic characters --> an ASCII space
1459 (goto-char (point-min))
1460 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1461 (replace-match "\\1 \\2")
1462 (goto-char (match-beginning 2))))
1008 1463
1009 ((= ch ?2) 1464 ((= ch ?2)
1010 1465 ;; An Ethiopic word separator --> two ASCII spaces
1011 ;; An Ethiopic word separator is always converted to
1012 ;; a double column space.
1013 (while (search-forward "$(2$O(B" nil t)
1014 (replace-match "$(2$N(B"))
1015
1016 (goto-char (point-min)) 1466 (goto-char (point-min))
1017 1467 (while (search-forward "$(3$h(B" nil t)
1018 ;; ASCII spaces are converted only if they are placed 1468 (replace-match " "))
1019 ;; between two Ethiopic characters. 1469
1020 (while (re-search-forward "\\(\\cE\\)\\( \\)\\( *\\cE\\)" nil t) 1470 ;; An ASCII space between Ethiopic characters --> two ASCII spaces
1021 1471 (goto-char (point-min))
1022 ;; Converting the first ASCII space 1472 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1023 (replace-match "\\1$(2$N(B\\3") 1473 (replace-match "\\1 \\2")
1024
1025 ;; A double column space is \cE, so going back to the just
1026 ;; converted double column space makes it possible to find
1027 ;; the following ASCII spaces.
1028 (goto-char (match-beginning 2)))) 1474 (goto-char (match-beginning 2))))
1029 1475
1030 ((= ch ?3) 1476 (t
1031 1477 ;; One or two ASCII spaces between Ethiopic characters
1032 ;; If more than one consecutive space (either ASCII or double 1478 ;; --> An Ethiopic word separator
1033 ;; width) is found between two Ethiopic characters, the first 1479 (goto-char (point-min))
1034 ;; space will be converted to an Ethiopic word separator. 1480 (while (re-search-forward "\\(\\ce\\) ?\\(\\ce\\)" nil t)
1035 (let (pred succ) 1481 (replace-match "\\1$(3$h(B\\2")
1036 (while (re-search-forward "[ $(2$N(B]\\([ $(2$N(B]*\\)" nil t) 1482 (goto-char (match-beginning 2)))
1037 (and (setq pred (char-before (match-beginning 0))) 1483
1038 (eq (char-charset pred) 'ethiopic) 1484 ;; Three or more ASCII spaces between Ethiopic characters
1039 (setq succ (char-after (match-end 0))) 1485 ;; --> An Ethiopic word separator + (N - 2) ASCII spaces
1040 (eq (char-charset succ) 'ethiopic) 1486 (goto-char (point-min))
1041 (replace-match "$(2$O(B\\1" nil nil))))))))) 1487 (while (re-search-forward "\\(\\ce\\) \\( *\\ce\\)" nil t)
1042 1488 (replace-match "\\1$(3$h(B\\2")
1043 ;; 1489 (goto-char (match-beginning 2))))))))
1044 ;; special characters 1490
1491 ;;
1492 ;; special icons
1045 ;; 1493 ;;
1046 1494
1047 ;;;###autoload 1495 ;;;###autoload
1048 (defun ethio-input-special-character (arg) 1496 (defun ethio-input-special-character (arg)
1049 "Allow the user to input special characters." 1497 "Allow the user to input special characters."
1050 (interactive "*cInput number: 1.$(2$k(B 2.$(2$l(B 3.$(2$m(B 4.$(2$n(B") 1498 (interactive "*cInput number: 1.$(3%j(B 2.$(3%k(B 3.$(3%l(B 4.$(3%m(B 5.$(3%i(B")
1051 (cond 1499 (cond
1052 ((= arg ?1) 1500 ((= arg ?1)
1053 (insert ?$(2$k(B)) 1501 (insert "$(3%j(B"))
1054 ((= arg ?2) 1502 ((= arg ?2)
1055 (insert ?$(2$l(B)) 1503 (insert "$(3%k(B"))
1056 ((= arg ?3) 1504 ((= arg ?3)
1057 (insert ?$(2$m(B)) 1505 (insert "$(3%l(B"))
1058 ((= arg ?4) 1506 ((= arg ?4)
1059 (insert ?$(2$n(B)) 1507 (insert "$(3%m(B"))
1508 ((= arg ?5)
1509 (insert "$(3%i(B"))
1060 (t 1510 (t
1061 (error "")))) 1511 (error ""))))
1512
1513 ;;
1514 ;; TeX support
1515 ;;
1516
1517 (defconst fidel-to-tex-map
1518 [ "heG" "huG" "hiG" "haG" "hEG" "hG" "hoG" "" ;; 0 - 7
1519 "leG" "luG" "liG" "laG" "lEG" "lG" "loG" "lWaG" ;; 8
1520 "HeG" "HuG" "HiG" "HaG" "HEG" "HG" "HoG" "HWaG" ;; 16
1521 "meG" "muG" "miG" "maG" "mEG" "mG" "moG" "mWaG" ;; 24
1522 "sseG" "ssuG" "ssiG" "ssaG" "ssEG" "ssG" "ssoG" "ssWaG" ;; 32
1523 "reG" "ruG" "riG" "raG" "rEG" "rG" "roG" "rWaG" ;; 40
1524 "seG" "suG" "siG" "saG" "sEG" "sG" "soG" "sWaG" ;; 48
1525 "xeG" "xuG" "xiG" "xaG" "xEG" "xG" "xoG" "xWaG" ;; 56
1526 "qeG" "quG" "qiG" "qaG" "qE" "qG" "qoG" "" ;; 64
1527 "qWeG" "" "qWi" "qWaG" "qWEG" "qWG" "" "" ;; 72
1528 "QeG" "QuG" "QiG" "QaG" "QEG" "QG" "QoG" "" ;; 80
1529 "QWeG" "" "QWiG" "QWaG" "QWEG" "QWG" "" "" ;; 88
1530 "beG" "buG" "biG" "baG" "bEG" "bG" "boG" "bWaG" ;; 96
1531 "veG" "vuG" "viG" "vaG" "vEG" "vG" "voG" "vWaG" ;; 104
1532 "teG" "tuG" "tiG" "taG" "tEG" "tG" "toG" "tWaG" ;; 112
1533 "ceG" "cuG" "ciG" "caG" "cEG" "cG" "coG" "cWaG" ;; 120
1534 "hheG" "hhuG" "hhiG" "hhaG" "hhEG" "hhG" "hhoG" "" ;; 128
1535 "hWeG" "" "hWiG" "hWaG" "hWEG" "hWG" "" "" ;; 136
1536 "neG" "nuG" "niG" "naG" "nEG" "nG" "noG" "nWaG" ;; 144
1537 "NeG" "NuG" "NiG" "NaG" "NEG" "NG" "NoG" "NWaG" ;; 152
1538 "eG" "uG" "iG" "AG" "EG" "IG" "oGG" "eaG" ;; 160
1539 "keG" "kuG" "kiG" "kaG" "kEG" "kG" "koG" "" ;; 168
1540 "kWeG" "" "kWiG" "kWa" "kWEG" "kWG" "" "" ;; 176
1541 "KeG" "KuG" "KiG" "KaG" "KEG" "KG" "KoG" "" ;; 184
1542 "KWeG" "" "KWiG" "KWa" "KWEG" "KWG" "" "" ;; 192
1543 "weG" "wuG" "wiG" "waG" "wEG" "wG" "woG" "" ;; 200
1544 "eeG" "uuG" "iiG" "aaG" "EEG" "IIG" "ooG" "" ;; 208
1545 "zeG" "zuG" "ziG" "zaG" "zEG" "zG" "zoG" "zWaG" ;; 216
1546 "ZeG" "ZuG" "ZiG" "ZaG" "ZEG" "ZG" "ZoG" "ZWaG" ;; 224
1547 "yeG" "yuG" "yiG" "yaG" "yEG" "yG" "yoG" "yWaG" ;; 232
1548 "deG" "duG" "diG" "daG" "dEG" "dG" "doG" "dWaG" ;; 240
1549 "DeG" "DuG" "DiG" "DaG" "DEG" "DG" "DoG" "DWaG" ;; 248
1550 "jeG" "juG" "jiG" "jaG" "jEG" "jG" "joG" "jWaG" ;; 256
1551 "geG" "guG" "giG" "gaG" "gEG" "gG" "goG" "" ;; 264
1552 "gWeG" "" "gWiG" "gWaG" "gWEG" "gWG" "" "" ;; 272
1553 "GeG" "GuG" "GiG" "GaG" "GEG" "GG" "GoG" "GWaG" ;; 280
1554 "TeG" "TuG" "TiG" "TaG" "TEG" "TG" "ToG" "TWaG" ;; 288
1555 "CeG" "CuG" "CiG" "CaG" "CEG" "CG" "CoG" "CWaG" ;; 296
1556 "PeG" "PuG" "PiG" "PaG" "PEG" "PG" "PoG" "PWaG" ;; 304
1557 "SeG" "SuG" "SiG" "SaG" "SEG" "SG" "SoG" "SWaG" ;; 312
1558 "SSeG" "SSuG" "SSiG" "SSaG" "SSEG" "SSG" "SSoG" "" ;; 320
1559 "feG" "fuG" "fiG" "faG" "fEG" "fG" "foG" "fWaG" ;; 328
1560 "peG" "puG" "piG" "paG" "pEG" "pG" "poG" "pWaG" ;; 336
1561 "mYaG" "rYaG" "fYaG" "" "" "" "" "" ;; 344
1562 "" "spaceG" "periodG" "commaG" ;; 352
1563 "semicolonG" "colonG" "precolonG" "oldqmarkG" ;; 356
1564 "pbreakG" "andG" "huletG" "sostG" "aratG" "amstG" "sadstG" "sabatG" ;; 360
1565 "smntG" "zeteNG" "asrG" "heyaG" "selasaG" "arbaG" "hemsaG" "slsaG" ;; 368
1566 "sebaG" "semanyaG" "zeTanaG" "metoG" "asrxiG" "" "" "" ;; 376
1567 "qqeG" "qquG" "qqiG" "qqaG" "qqEG" "qqG" "qqoG" "" ;; 384
1568 "mWeG" "bWeG" "GWeG" "fWeG" "pWeG" "" "" "" ;; 392
1569 "kkeG" "kkuG" "kkiG" "kkaG" "kkEG" "kkG" "kkoG" "" ;; 400
1570 "mWiG" "bWiG" "GWiG" "fWiG" "pWiG" "" "" "" ;; 408
1571 "XeG" "XuG" "GXiG" "XaG" "XEG" "XG" "XoG" "" ;; 416
1572 "mWEG" "bWEG" "GWEG" "fWEG" "pWEG" "" "" "" ;; 424
1573 "ggeG" "gguG" "ggiG" "ggaG" "ggEG" "ggG" "ggoG" "" ;; 432
1574 "mWG" "bWG" "GWG" "fWG" "pWG" "" "" "" ;; 440
1575 "ornamentG" "flandG" "iflandG" "africaG" ;; 448
1576 "iafricaG" "wWeG" "wWiG" "wWaG" ;; 452
1577 "wWEG" "wWG" "" "slaqG" "dotG" "lquoteG" "rquoteG" "qmarkG" ]) ;; 456
1578
1579 ;;
1580 ;; To make tex-to-fidel mapping.
1581 ;; The following code makes
1582 ;; (get 'ethio-tex-command-he 'ethio-fidel-char) ==> ?$(3!!(B
1583 ;; etc.
1584 ;;
1585
1586 (let ((i 0) str)
1587 (while (< i (length ethio-fidel-to-tex-map))
1588 (setq str (aref ethio-fidel-to-tex-map i))
1589 (if (not (string= str ""))
1590 (put
1591 (intern (concat "ethio-tex-command-" (aref ethio-fidel-to-tex-map i)))
1592 'ethio-fidel-char
1593 (ethio-ethiocode-to-char i)))
1594 (setq i (1+ i))))
1595
1596 ;;;###autoload
1597 (defun ethio-fidel-to-tex-buffer nil
1598 "Convert each fidel characters in the current buffer into a fidel-tex command.
1599 Each command is always surrounded by braces."
1600 (interactive)
1601 (let ((buffer-read-only nil))
1602
1603 ;; Isolated gemination marks need special treatement
1604 (goto-char (point-min))
1605 (while (search-forward "$(3%s(B" nil t)
1606 (replace-match "\\geminateG{}" t t))
1607
1608 ;; First, decompose geminations
1609 ;; Here we assume that each composed character consists of
1610 ;; one Ethiopic character and the Ethiopic gemination mark.
1611 (decompose-region (point-min) (point-max))
1612
1613 ;; Special treatment for geminated characters
1614 ;; The geminated character (la'') will be "\geminateG{\la}".
1615 (goto-char (point-min))
1616 (while (search-forward "$(3%s(B" nil t)
1617 (delete-backward-char 1)
1618 (backward-char 1)
1619 (insert "\\geminateG")
1620 (forward-char 1))
1621
1622 ;; Ethiopic characters to TeX macros
1623 (goto-char (point-min))
1624 (while (re-search-forward "\\ce" nil t)
1625 (insert
1626 "{\\"
1627 (aref ethio-fidel-to-tex-map
1628 (prog1 (ethio-char-to-ethiocode (preceding-char))
1629 (backward-delete-char 1)))
1630 "}"))
1631 (goto-char (point-min))
1632 (set-buffer-modified-p nil)))
1633
1634 ;;;###autoload
1635 (defun ethio-tex-to-fidel-buffer nil
1636 "Convert fidel-tex commands in the current buffer into fidel chars."
1637 (interactive)
1638 (let ((buffer-read-only nil)
1639 (p) (ch))
1640
1641 ;; Special treatment for gemination
1642 ;; "\geminateG{\la}" or "\geminateG{{\la}}" will be "\la$(3%s(B"
1643 ;; "\geminateG{}" remains unchanged.
1644 (goto-char (point-min))
1645 (while (re-search-forward "\\\\geminateG{\\(\\\\[a-zA-Z]+\\)}" nil t)
1646 (replace-match "\\1$(3%s(B"))
1647
1648 ;; TeX macros to Ethiopic characters
1649 (goto-char (point-min))
1650 (while (search-forward "\\" nil t)
1651 (setq p (point))
1652 (skip-chars-forward "a-zA-Z")
1653 (setq ch
1654 (get (intern (concat "ethio-tex-command-"
1655 (buffer-substring p (point))))
1656 'ethio-fidel-char))
1657 (if ch
1658 (progn
1659 (delete-region (1- p) (point)) ; don't forget the preceding "\"
1660 (if (and (= (preceding-char) ?{)
1661 (= (following-char) ?}))
1662 (progn
1663 (backward-delete-char 1)
1664 (delete-char 1)))
1665 (insert ch))))
1666
1667 ;; compose geminated characters
1668 (goto-char (point-min))
1669 (while (re-search-forward "\\ce$(3%s(B" nil 0)
1670 (compose-region
1671 (save-excursion (backward-char 2) (point))
1672 (point)))
1673
1674 ;; Now it's time to convert isolated gemination marks.
1675 (goto-char (point-min))
1676 (while (search-forward "\\geminateG{}" nil t)
1677 (replace-match "$(3%s(B"))
1678
1679 (goto-char (point-min))
1680 (set-buffer-modified-p nil)))
1681
1682 ;;
1683 ;; Java support
1684 ;;
1685
1686 ;;;###autoload
1687 (defun ethio-fidel-to-java-buffer nil
1688 "Convert Ethiopic characters into the Java escape sequences.
1689
1690 Each escape sequence is of the form \uXXXX, where XXXX is the
1691 character's codepoint (in hex) in Unicode.
1692
1693 If `ethio-java-save-lowercase' is non-nil, use [0-9a-f].
1694 Otherwise, [0-9A-F]."
1695 (let ((ucode))
1696
1697 ;; first, decompose geminations
1698 (decompose-region (point-min) (point-max))
1699
1700 (goto-char (point-min))
1701 (while (re-search-forward "\\ce" nil t)
1702 (setq ucode (+ ?\x1200 (ethio-char-to-ethiocode (preceding-char))))
1703 (if (> ucode ?\x13bc)
1704 (setq ucode (+ ucode 59952)))
1705 (delete-backward-char 1)
1706 (if ethio-java-save-lowercase
1707 (insert (format "\\u%4x" ucode))
1708 (insert (upcase (format "\\u%4x" ucode)))))))
1709
1710 ;;;###autoload
1711 (defun ethio-java-to-fidel-buffer nil
1712 "Convert the Java escape sequences into corresponding Ethiopic characters."
1713 (let ((ucode))
1714 (goto-char (point-min))
1715 (while (re-search-forward "\\\\u\\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\)" nil t)
1716 (setq ucode
1717 (read
1718 (concat
1719 "?\\x"
1720 (buffer-substring (match-beginning 1) (match-end 1)))))
1721 (cond
1722 ((and (>= ucode ?\x1200) (<= ucode ?\x13bc))
1723 (replace-match "")
1724 (insert (ethio-ethiocode-to-char (- ucode ?\x1200))))
1725 ((and (>= ucode ?\xfdf1) (<= ucode ?\xfdff))
1726 (replace-match "")
1727 (insert (ethio-ethiocode-to-char (- ucode 64560))))
1728 (t
1729 nil)))
1730
1731 ;; gemination
1732 (goto-char (point-min))
1733 (while (re-search-forward "\\ce$(3%s(B" nil 0)
1734 (compose-region
1735 (save-excursion (backward-char 2) (point))
1736 (point)))
1737 ))
1738
1739 ;;
1740 ;; file I/O hooks
1741 ;;
1742
1743 ;;;###autoload
1744 (defun ethio-find-file nil
1745 "Transcribe file content into Ethiopic dependig on filename suffix."
1746 (cond
1747
1748 ((string-match "\\.sera$" (buffer-file-name))
1749 (save-excursion
1750 (ethio-sera-to-fidel-buffer nil 'force)
1751 (set-buffer-modified-p nil)))
1752
1753 ((string-match "\\.html$" (buffer-file-name))
1754 (let ((sera-being-called-by-w3 t))
1755 (save-excursion
1756 (ethio-sera-to-fidel-marker 'force)
1757 (goto-char (point-min))
1758 (while (re-search-forward "&[lr]aquote;" nil t)
1759 (if (= (char-after (1+ (match-beginning 0))) ?l)
1760 (replace-match "$(3%v(B")
1761 (replace-match "$(3%w(B")))
1762 (set-buffer-modified-p nil))))
1763
1764 ((string-match "\\.tex$" (buffer-file-name))
1765 (save-excursion
1766 (ethio-tex-to-fidel-buffer)
1767 (set-buffer-modified-p nil)))
1768
1769 ((string-match "\\.java$" (buffer-file-name))
1770 (save-excursion
1771 (ethio-java-to-fidel-buffer)
1772 (set-buffer-modified-p nil)))
1773
1774 (t
1775 nil)))
1776
1777 ;;;###autoload
1778 (defun ethio-write-file nil
1779 "Transcribe Ethiopic characters in ASCII depending on the file extension."
1780 (cond
1781
1782 ((string-match "\\.sera$" (buffer-file-name))
1783 (save-excursion
1784 (ethio-fidel-to-sera-buffer nil 'force)
1785 (goto-char (point-min))
1786 (ethio-record-user-preference)
1787 (set-buffer-modified-p nil)))
1788
1789 ((string-match "\\.html$" (buffer-file-name))
1790 (save-excursion
1791 (let ((sera-being-called-by-w3 t)
1792 (lq (aref ethio-fidel-to-sera-map 461))
1793 (rq (aref ethio-fidel-to-sera-map 462)))
1794 (aset ethio-fidel-to-sera-map 461 "&laquote;")
1795 (aset ethio-fidel-to-sera-map 462 "&raquote;")
1796 (ethio-fidel-to-sera-marker 'force)
1797 (goto-char (point-min))
1798 (if (search-forward "<sera>" nil t)
1799 (ethio-record-user-preference))
1800 (aset ethio-fidel-to-sera-map 461 lq)
1801 (aset ethio-fidel-to-sera-map 462 rq)
1802 (set-buffer-modified-p nil))))
1803
1804 ((string-match "\\.tex$" (buffer-file-name))
1805 (save-excursion
1806 (ethio-fidel-to-tex-buffer)
1807 (set-buffer-modified-p nil)))
1808
1809 ((string-match "\\.java$" (buffer-file-name))
1810 (save-excursion
1811 (ethio-fidel-to-java-buffer)
1812 (set-buffer-modified-p nil)))
1813
1814 (t
1815 nil)))
1816
1817 (defun ethio-record-user-preference nil
1818 (if (looking-at "\\\\~\\(tir?\\|amh?\\) ")
1819 (goto-char (match-end 0))
1820 (insert (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir ")))
1821 (insert (if ethio-use-colon-for-colon "\\~-: " "\\~`: ")
1822 (if ethio-use-three-dot-question "\\~`| " "\\~`? ")))
1823
1824 (add-hook 'find-file-hooks 'ethio-find-file)
1825 (add-hook 'write-file-hooks 'ethio-write-file)
1826 (add-hook 'after-save-hook 'ethio-find-file)
1062 1827
1063 ;; 1828 ;;
1064 (provide 'language/ethio-util) 1829 (provide 'language/ethio-util)
1065 1830
1066 ;;; Local Variables: 1831 ;;; Local Variables: