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