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