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