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