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