comparison lisp/language/ethio-util.el @ 165:5a88923fcbfe r20-3b9

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