1;;; ethio-util.el --- utilities for Ethiopic -*- coding: iso-2022-7bit; -*- 2 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 8 9;; Keywords: mule, multilingual, Ethiopic 10 11;; This file is part of GNU Emacs. 12 13;; GNU Emacs is free software; you can redistribute it and/or modify 14;; it under the terms of the GNU General Public License as published by 15;; the Free Software Foundation; either version 2, or (at your option) 16;; any later version. 17 18;; GNU Emacs is distributed in the hope that it will be useful, 19;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21;; GNU General Public License for more details. 22 23;; You should have received a copy of the GNU General Public License 24;; along with GNU Emacs; see the file COPYING. If not, write to the 25;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 26;; Boston, MA 02110-1301, USA. 27 28;; Author: TAKAHASHI Naoto <ntakahas@m17n.org> 29 30;;; Commentary: 31 32;;; Code: 33 34(defvar rmail-current-message) 35(defvar rmail-message-vector) 36 37;; Information for exiting Ethiopic environment. 38(defvar exit-ethiopic-environment-data nil) 39 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) 45 46 ;; these old bindings conflict 47 ;; with Emacs' binding policy 48 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) 61 62 ;; this is the rewritten bindings 63 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 76 )) 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)))) 85 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)) 90 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))) 98 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)) 103 104;; 105;; ETHIOPIC UTILITY FUNCTIONS 106;; 107 108;; If the filename ends in ".sera", editing is done in fidel 109;; but file I/O is done in SERA. 110;; 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. 114;; 115;; If the filename ends in ".tex", editing is done in fidel 116;; but file I/O is done in EthioTeX format. 117;; 118;; To automatically convert Ethiopic text to SERA format when sending mail, 119;; (add-hook 'mail-send-hook 'ethio-fidel-to-sera-mail) 120;; 121;; To automatically convert SERA format to Ethiopic when receiving mail, 122;; (add-hook 'rmail-show-message-hook 'ethio-sera-to-fidel-mail) 123;; 124;; To automatically convert Ethiopic text to SERA format when posting news, 125;; (add-hook 'news-inews-hook 'ethio-fidel-to-sera-mail) 126 127;; 128;; users' preference 129;; 130 131(defvar ethio-primary-language 'tigrigna 132 "*Symbol that defines the primary language in SERA --> FIDEL conversion. 133The value should be one of: `tigrigna', `amharic' or `english'.") 134 135(defvar ethio-secondary-language 'english 136 "*Symbol that defines the secondary language in SERA --> FIDEL conversion. 137The value should be one of: `tigrigna', `amharic' or `english'.") 138 139(defvar ethio-use-colon-for-colon nil 140 "*Non-nil means associate ASCII colon with Ethiopic colon. 141If nil, associate ASCII colon with Ethiopic word separator, i.e., two 142vertically stacked dots. All SERA <--> FIDEL converters refer this 143variable.") 144 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). 147If nil, associate ASCII question mark with Ethiopic stylized question 148mark. All SERA <--> FIDEL converters refer this variable.") 149 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. 152If nil, put an apostrophe only between a sixth-form consonant and an 153isolated vowel.") 154 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.") 157 158(defvar ethio-numeric-reduction 0 159 "*Degree of reduction in converting Ethiopic digits into Arabic digits. 160Should be 0, 1 or 2. 161For 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.") 165 166(defvar ethio-implicit-period-conversion t 167 "*Non-nil means replacing the Ethiopic dot at the end of an Ethiopic sentence 168with an Ethiopic full stop.") 169 170(defvar ethio-java-save-lowercase nil 171 "*Non-nil means save Ethiopic characters in lowercase hex numbers to Java files. 172If nil, use uppercases.") 173 174;; 175;; SERA to FIDEL 176;; 177 178(defconst ethio-sera-to-fidel-table 179 [ 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 " $(3$l(B" "$(3$h(B") 185 (32 (if ethio-use-colon-for-colon " $(3$l(B " "$(3$h(B")) 186 (?- " $(3$m(B") 187 (?: " $(3$i(B") 188 (?| (if ethio-use-colon-for-colon " $(3$l(B|" " $(3$h(B|") 189 (?: " $(3$o(B")))) 190 191;;; ! " # $ % & ' 192 nil nil nil nil nil nil ("" (?' "$(3%s(B")) 193;;; ( ) * + , - . 194 nil nil nil nil ("$(3$j(B") ("-" (?: "$(3$l(B")) ("$(3%u(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 "$(3$l(B" "$(3$h(B") 199 (32 (if ethio-use-colon-for-colon "$(3$l(B " "$(3$h(B")) 200 (?- "$(3$m(B") 201 (?: "$(3$i(B") 202 (?| (if ethio-use-colon-for-colon "$(3$l(B|" "$(3$h(B|") 203 (?: "$(3$o(B"))) 204;;; ; < = > 205 ("$(3$k(B") ("<" (?< "$(3%v(B")) nil (">" (?> "$(3%w(B")) 206;;; ? 207 ((if ethio-use-three-dot-question "$(3$n(B" "$(3%x(B")) 208;;; @ 209 nil 210;;; A 211 ("$(3"f(B" (?2 "$(3#8(B")) 212;;; B 213 ("$(3"((B" (?e "$(3"#(B") (?u "$(3"$(B") (?i "$(3"%(B") (?a "$(3"&(B") (?E "$(3"'(B") (?o "$(3")(B") 214 (?W "$(3%b(B" (?e "$(3%2(B") (?u "$(3%b(B") (?i "$(3%B(B") (?a "$(3"*(B") (?E "$(3%R(B"))) 215;;; C 216 ("$(3$4(B" (?e "$(3$/(B") (?u "$(3$0(B") (?i "$(3$1(B") (?a "$(3$2(B") (?E "$(3$3(B") (?o "$(3$5(B") 217 (?W "$(3$6(B" (?a "$(3$6(B") 218 (?e "$(3$4%n(B") (?u "$(3$4%r(B") (?i "$(3$4%o(B") (?E "$(3$4%q(B"))) 219;;; D 220 ("$(3#b(B" (?e "$(3#](B") (?u "$(3#^(B") (?i "$(3#_(B") (?a "$(3#`(B") (?E "$(3#a(B") (?o "$(3#c(B") 221 (?W "$(3#d(B" (?a "$(3#d(B") 222 (?e "$(3#b%n(B") (?u "$(3#b%r(B") (?i "$(3#b%o(B") (?E "$(3#b%q(B"))) 223;;; E 224 ("$(3"g(B" (?2 "$(3#9(B")) 225;;; F 226 ("$(3$T(B" (?e "$(3$O(B") (?u "$(3$P(B") (?i "$(3$Q(B") (?a "$(3$R(B") (?E "$(3$S(B") (?o "$(3$U(B") 227 (?W "$(3%d(B" (?e "$(3%4(B") (?u "$(3%d(B") (?i "$(3%D(B") (?a "$(3$V(B") (?E "$(3%T(B")) 228 (?Y "$(3$a(B" (?a "$(3$a(B"))) 229;;; G 230 ("$(3$$(B" (?e "$(3#}(B") (?u "$(3#~(B") (?i "$(3$!(B") (?a "$(3$"(B") (?E "$(3$#(B") (?o "$(3$%(B") 231 (?W "$(3%c(B" (?e "$(3%3(B") (?u "$(3%c(B") (?i "$(3%C(B") (?a "$(3$&(B") (?E "$(3%S(B"))) 232;;; H 233 ("$(3!6(B" (?e "$(3!1(B") (?u "$(3!2(B") (?i "$(3!3(B") (?a "$(3!4(B") (?E "$(3!5(B") (?o "$(3!7(B") 234 (?W "$(3!8(B" (?a "$(3!8(B") 235 (?e "$(3!6%n(B") (?u "$(3!6%r(B") (?i "$(3!6%o(B") (?E "$(3!6%q(B"))) 236;;; I 237 ("$(3"h(B" (?2 "$(3#:(B")) 238;;; J 239 ("$(3#j(B" (?e "$(3#e(B") (?u "$(3#f(B") (?i "$(3#g(B") (?a "$(3#h(B") (?E "$(3#i(B") (?o "$(3#k(B") 240 (?W "$(3#l(B" (?a "$(3#l(B") 241 (?e "$(3#j%n(B") (?u "$(3#j%r(B") (?i "$(3#j%o(B") (?E "$(3#j%q(B"))) 242;;; K 243 ("$(3#"(B" (?e "$(3"{(B") (?u "$(3"|(B") (?i "$(3"}(B") (?a "$(3"~(B") (?E "$(3#!(B") (?o "$(3##(B") 244 (?W "$(3#*(B" (?e "$(3#%(B") (?u "$(3#*(B") (?i "$(3#'(B") (?a "$(3#((B") (?E "$(3#)(B"))) 245;;; L 246 ("$(3!.(B" (?e "$(3!)(B") (?u "$(3!*(B") (?i "$(3!+(B") (?a "$(3!,(B") (?E "$(3!-(B") (?o "$(3!/(B") 247 (?W "$(3!0(B" (?a "$(3!0(B") 248 (?e "$(3!.%n(B") (?u "$(3!.%r(B") (?i "$(3!.%o(B") (?E "$(3!.%q(B"))) 249;;; M 250 ("$(3!>(B" (?e "$(3!9(B") (?u "$(3!:(B") (?i "$(3!;(B") (?a "$(3!<(B") (?E "$(3!=(B") (?o "$(3!?(B") 251 (?W "$(3%a(B" (?e "$(3%1(B") (?u "$(3%a(B") (?i "$(3%A(B") (?a "$(3!@(B") (?E "$(3%Q(B")) 252 (?Y "$(3$_(B" (?a "$(3$_(B"))) 253;;; N 254 ("$(3"`(B" (?e "$(3"[(B") (?u "$(3"\(B") (?i "$(3"](B") (?a "$(3"^(B") (?E "$(3"_(B") (?o "$(3"a(B") 255 (?W "$(3"b(B" (?a "$(3"b(B") 256 (?e "$(3"`%n(B") (?u "$(3"`%r(B") (?i "$(3"`%o(B") (?E "$(3"`%q(B"))) 257;;; O 258 ("$(3"i(B" (?2 "$(3#;(B")) 259;;; P 260 ("$(3$<(B" (?e "$(3$7(B") (?u "$(3$8(B") (?i "$(3$9(B") (?a "$(3$:(B") (?E "$(3$;(B") (?o "$(3$=(B") 261 (?W "$(3$>(B" (?a "$(3$>(B") 262 (?e "$(3$<%n(B") (?u "$(3$<%r(B") (?i "$(3$<%o(B") (?E "$(3$<%q(B"))) 263;;; Q 264 ("$(3!v(B" (?e "$(3!q(B") (?u "$(3!r(B") (?i "$(3!s(B") (?a "$(3!t(B") (?E "$(3!u(B") (?o "$(3!w(B") 265 (?W "$(3!~(B" (?e "$(3!y(B") (?u "$(3!~(B") (?i "$(3!{(B") (?a "$(3!|(B") (?E "$(3!}(B"))) 266;;; R 267 ("$(3!N(B" (?e "$(3!I(B") (?u "$(3!J(B") (?i "$(3!K(B") (?a "$(3!L(B") (?E "$(3!M(B") (?o "$(3!O(B") 268 (?W "$(3!P(B" (?a "$(3!P(B") 269 (?e "$(3!N%n(B") (?u "$(3!N%r(B") (?i "$(3!N%o(B") (?E "$(3!N%q(B")) 270 (?Y "$(3$`(B" (?a "$(3$`(B"))) 271;;; S 272 ("$(3$D(B" (?e "$(3$?(B") (?u "$(3$@(B") (?i "$(3$A(B") (?a "$(3$B(B") (?E "$(3$C(B") (?o "$(3$E(B") 273 (?W "$(3$F(B" (?a "$(3$F(B") 274 (?e "$(3$D%n(B") (?u "$(3$D%r(B") (?i "$(3$D%o(B") (?E "$(3$D%q(B")) 275 (?2 "$(3$L(B" 276 (?e "$(3$G(B") (?u "$(3$H(B") (?i "$(3$I(B") (?a "$(3$J(B") (?E "$(3$K(B") (?o "$(3$M(B") 277 (?W "$(3$F(B" (?a "$(3$F(B") 278 (?e "$(3$L%n(B") (?u "$(3$L%r(B") (?i "$(3$L%o(B") (?E "$(3$L%q(B")))) 279;;; T 280 ("$(3$,(B" (?e "$(3$'(B") (?u "$(3$((B") (?i "$(3$)(B") (?a "$(3$*(B") (?E "$(3$+(B") (?o "$(3$-(B") 281 (?W "$(3$.(B" (?a "$(3$.(B") 282 (?e "$(3$,%n(B") (?u "$(3$,%r(B") (?i "$(3$,%o(B") (?E "$(3$,%q(B"))) 283;;; U 284 ("$(3"d(B" (?2 "$(3#6(B")) 285;;; V 286 ("$(3"0(B" (?e "$(3"+(B") (?u "$(3",(B") (?i "$(3"-(B") (?a "$(3".(B") (?E "$(3"/(B") (?o "$(3"1(B") 287 (?W "$(3"2(B" (?a "$(3"2(B") 288 (?e "$(3"0%n(B") (?u "$(3"0%r(B") (?i "$(3"0%o(B") (?E "$(3"0%q(B"))) 289;;; W 290 ("$(3%r(B" (?e "$(3%n(B") (?u "$(3%r(B") (?i "$(3%o(B") (?a "$(3%p(B") (?E "$(3%q(B")) 291;;; X 292 ("$(3%N(B" (?e "$(3%I(B") (?u "$(3%J(B") (?i "$(3%K(B") (?a "$(3%L(B") (?E "$(3%M(B") (?o "$(3%O(B")) 293;;; Y 294 ("$(3#R(B" (?e "$(3#M(B") (?u "$(3#N(B") (?i "$(3#O(B") (?a "$(3#P(B") (?E "$(3#Q(B") (?o "$(3#S(B") 295 (?W "$(3#T(B" (?a "$(3#T(B") 296 (?e "$(3#R%n(B") (?u "$(3#R%r(B") (?i "$(3#R%o(B") (?E "$(3#R%q(B"))) 297;;; Z 298 ("$(3#J(B" (?e "$(3#E(B") (?u "$(3#F(B") (?i "$(3#G(B") (?a "$(3#H(B") (?E "$(3#I(B") (?o "$(3#K(B") 299 (?W "$(3#L(B" (?a "$(3#L(B") 300 (?e "$(3#J%n(B") (?u "$(3#J%r(B") (?i "$(3#J%o(B") (?E "$(3#J%q(B"))) 301;;; [ \ ] ^ _ 302 nil nil nil nil nil 303;;; ` 304 ("" 305 (?: "$(3$h(B") 306 (?? (if ethio-use-three-dot-question "$(3%x(B" "$(3$n(B")) 307 (?! "$(3%t(B") 308 (?e "$(3#5(B") (?u "$(3#6(B") (?U "$(3#6(B") (?i "$(3#7(B") (?a "$(3#8(B") (?A "$(3#8(B") 309 (?E "$(3#9(B") (?I "$(3#:(B") (?o "$(3#;(B") (?O "$(3#;(B") 310 (?g "$(3%^(B" 311 (?e "$(3%Y(B") (?u "$(3%Z(B") (?i "$(3%[(B") (?a "$(3%\(B") (?E "$(3%](B") (?o "$(3%_(B")) 312 (?h "$(3"H(B" 313 (?e "$(3"C(B") (?u "$(3"D(B") (?i "$(3"E(B") (?a "$(3"F(B") (?E "$(3"G(B") (?o "$(3"I(B") 314 (?W "$(3"P(B" (?e "$(3"K(B") (?u "$(3"P(B") (?i "$(3"M(B") (?a "$(3"N(B") (?E "$(3"O(B"))) 315 (?k "$(3%>(B" 316 (?e "$(3%9(B") (?u "$(3%:(B") (?i "$(3%;(B") (?a "$(3%<(B") (?E "$(3%=(B") (?o "$(3%?(B")) 317 (?s "$(3!F(B" 318 (?e "$(3!A(B") (?u "$(3!B(B") (?i "$(3!C(B") (?a "$(3!D(B") (?E "$(3!E(B") (?o "$(3!G(B") 319 (?W "$(3!H(B" (?a "$(3!H(B") 320 (?e "$(3!F%n(B") (?u "$(3!F%r(B") (?i "$(3!F%o(B") (?E "$(3!F%q(B"))) 321 (?S "$(3$L(B" 322 (?e "$(3$G(B") (?u "$(3$H(B") (?i "$(3$I(B") (?a "$(3$J(B") (?E "$(3$K(B") (?o "$(3$M(B") 323 (?W "$(3$F(B" (?a "$(3$F(B") 324 (?e "$(3$L%n(B") (?u "$(3$L%r(B") (?i "$(3$L%o(B") (?E "$(3$L%q(B"))) 325 (?q "$(3%.(B" (?e "$(3%)(B") (?u "$(3%*(B") (?i "$(3%+(B") (?a "$(3%,(B") (?E "$(3%-(B") (?o "$(3%/(B"))) 326;;; a 327 ("$(3"f(B" (?2 "$(3#8(B")) 328;;; b 329 ("$(3"((B" (?e "$(3"#(B") (?u "$(3"$(B") (?i "$(3"%(B") (?a "$(3"&(B") (?E "$(3"'(B") (?o "$(3")(B") 330 (?W "$(3%b(B" (?e "$(3%2(B") (?u "$(3%b(B") (?i "$(3%B(B") (?a "$(3"*(B") (?E "$(3%R(B"))) 331;;; c 332 ("$(3"@(B" (?e "$(3";(B") (?u "$(3"<(B") (?i "$(3"=(B") (?a "$(3">(B") (?E "$(3"?(B") (?o "$(3"A(B") 333 (?W "$(3"B(B" (?a "$(3"B(B") 334 (?e "$(3"@%n(B") (?u "$(3"@%r(B") (?i "$(3"@%o(B") (?E "$(3"@%q(B"))) 335;;; d 336 ("$(3#Z(B" (?e "$(3#U(B") (?u "$(3#V(B") (?i "$(3#W(B") (?a "$(3#X(B") (?E "$(3#Y(B") (?o "$(3#[(B") 337 (?W "$(3#\(B" (?a "$(3#\(B") 338 (?e "$(3#Z%o(B") (?u "$(3#Z%r(B") (?i "$(3#Z%p(B") (?E "$(3#Z%q(B"))) 339;;; e 340 ("$(3"c(B" (?2 "$(3#5(B") (?a "$(3"j(B")) 341;;; f 342 ("$(3$T(B" (?e "$(3$O(B") (?u "$(3$P(B") (?i "$(3$Q(B") (?a "$(3$R(B") (?E "$(3$S(B") (?o "$(3$U(B") 343 (?W "$(3%d(B" (?e "$(3%4(B") (?u "$(3%d(B") (?i "$(3%D(B") (?a "$(3$V(B") (?E "$(3%T(B")) 344 (?Y "$(3$a(B" (?a "$(3$a(B"))) 345;;; g 346 ("$(3#r(B" (?e "$(3#m(B") (?u "$(3#n(B") (?i "$(3#o(B") (?a "$(3#p(B") (?E "$(3#q(B") (?o "$(3#s(B") 347 (?W "$(3#z(B" (?e "$(3#u(B") (?u "$(3#z(B") (?i "$(3#w(B") (?a "$(3#x(B") (?E "$(3#y(B")) 348 (?2 "$(3%^(B" (?e "$(3%Y(B") (?u "$(3%Z(B") (?i "$(3%[(B") (?a "$(3%\(B") (?E "$(3%](B") (?o "$(3%_(B"))) 349;;; h 350 ("$(3!&(B" (?e "$(3!!(B") (?u "$(3!"(B") (?i "$(3!#(B") (?a "$(3!$(B") (?E "$(3!%(B") (?o "$(3!'(B") 351 (?W "$(3"P(B" (?e "$(3"K(B") (?u "$(3"P(B") (?i "$(3"M(B") (?a "$(3"N(B") (?E "$(3"O(B")) 352 (?2 "$(3"H(B" (?e "$(3"C(B") (?u "$(3"D(B") (?i "$(3"E(B") (?a "$(3"F(B") (?E "$(3"G(B") (?o "$(3"I(B") 353 (?W "$(3"P(B" (?e "$(3"K(B") (?u "$(3"P(B") (?i "$(3"M(B") (?a "$(3"N(B") (?E "$(3"O(B")))) 354;;; i 355 ("$(3"e(B" (?2 "$(3#7(B")) 356;;; j 357 ("$(3#j(B" (?e "$(3#e(B") (?u "$(3#f(B") (?i "$(3#g(B") (?a "$(3#h(B") (?E "$(3#i(B") (?o "$(3#k(B") 358 (?W "$(3#l(B" (?a "$(3#l(B") 359 (?e "$(3#j%n(B") (?u "$(3#j%r(B") (?i "$(3#j%o(B") (?E "$(3#j%q(B"))) 360;;; k 361 ("$(3"p(B" (?e "$(3"k(B") (?u "$(3"l(B") (?i "$(3"m(B") (?a "$(3"n(B") (?E "$(3"o(B") (?o "$(3"q(B") 362 (?W "$(3"x(B" (?e "$(3"s(B") (?u "$(3"x(B") (?i "$(3"u(B") (?a "$(3"v(B") (?E "$(3"w(B")) 363 (?2 "$(3%>(B" (?e "$(3%9(B") (?u "$(3%:(B") (?i "$(3%;(B") (?a "$(3%<(B") (?E "$(3%=(B") (?o "$(3%?(B"))) 364;;; l 365 ("$(3!.(B" (?e "$(3!)(B") (?u "$(3!*(B") (?i "$(3!+(B") (?a "$(3!,(B") (?E "$(3!-(B") (?o "$(3!/(B") 366 (?W "$(3!0(B" (?a "$(3!0(B") 367 (?e "$(3!.%n(B") (?u "$(3!.%r(B") (?i "$(3!.%o(B") (?E "$(3!.%q(B"))) 368;;; m 369 ("$(3!>(B" (?e "$(3!9(B") (?u "$(3!:(B") (?i "$(3!;(B") (?a "$(3!<(B") (?E "$(3!=(B") (?o "$(3!?(B") 370 (?W "$(3%a(B" (?e "$(3%1(B") (?u "$(3%a(B") (?i "$(3%A(B") (?a "$(3!@(B") (?E "$(3%Q(B")) 371 (?Y "$(3$_(B" (?a "$(3$_(B"))) 372;;; n 373 ("$(3"X(B" (?e "$(3"S(B") (?u "$(3"T(B") (?i "$(3"U(B") (?a "$(3"V(B") (?E "$(3"W(B") (?o "$(3"Y(B") 374 (?W "$(3"Z(B" (?a "$(3"Z(B") 375 (?e "$(3"X%n(B") (?u "$(3"X%r(B") (?i "$(3"X%o(B") (?E "$(3"X%q(B"))) 376;;; o 377 ("$(3"i(B" (?2 "$(3#;(B")) 378;;; p 379 ("$(3$\(B" (?e "$(3$W(B") (?u "$(3$X(B") (?i "$(3$Y(B") (?a "$(3$Z(B") (?E "$(3$[(B") (?o "$(3$](B") 380 (?W "$(3%e(B" (?e "$(3%5(B") (?u "$(3%e(B") (?i "$(3%E(B") (?a "$(3$^(B") (?E "$(3%U(B"))) 381;;; q 382 ("$(3!f(B" (?e "$(3!a(B") (?u "$(3!b(B") (?i "$(3!c(B") (?a "$(3!d(B") (?E "$(3!e(B") (?o "$(3!g(B") 383 (?W "$(3!n(B" (?e "$(3!i(B") (?u "$(3!n(B") (?i "$(3!k(B") (?a "$(3!l(B") (?E "$(3!m(B")) 384 (?2 "$(3%.(B" (?e "$(3%)(B") (?u "$(3%*(B") (?i "$(3%+(B") (?a "$(3%,(B") (?E "$(3%-(B") (?o "$(3%/(B"))) 385;;; r 386 ("$(3!N(B" (?e "$(3!I(B") (?u "$(3!J(B") (?i "$(3!K(B") (?a "$(3!L(B") (?E "$(3!M(B") (?o "$(3!O(B") 387 (?W "$(3!P(B" (?a "$(3!P(B") 388 (?e "$(3!N%n(B") (?u "$(3!N%r(B") (?i "$(3!N%o(B") (?E "$(3!N%q(B")) 389 (?Y "$(3$`(B" (?a "$(3$`(B"))) 390;;; s 391 ("$(3!V(B" (?e "$(3!Q(B") (?u "$(3!R(B") (?i "$(3!S(B") (?a "$(3!T(B") (?E "$(3!U(B") (?o "$(3!W(B") 392 (?W "$(3!X(B" (?a "$(3!X(B") 393 (?e "$(3!V%n(B") (?u "$(3!V%r(B") (?i "$(3!V%o(B") (?E "$(3!V%q(B")) 394 (?2 "$(3!F(B" (?e "$(3!A(B") (?u "$(3!B(B") (?i "$(3!C(B") (?a "$(3!D(B") (?E "$(3!E(B") (?o "$(3!G(B") 395 (?W "$(3!H(B" (?a "$(3!H(B") 396 (?e "$(3!F%n(B") (?u "$(3!F%r(B") (?i "$(3!F%o(B") (?E "$(3!F%q(B")))) 397;;; t 398 ("$(3"8(B" (?e "$(3"3(B") (?u "$(3"4(B") (?i "$(3"5(B") (?a "$(3"6(B") (?E "$(3"7(B") (?o "$(3"9(B") 399 (?W "$(3":(B" (?a "$(3":(B") 400 (?e "$(3"8%n(B") (?u "$(3"8%r(B") (?i "$(3"8%o(B") (?E "$(3"8%q(B"))) 401;;; u 402 ("$(3"d(B" (?2 "$(3#6(B")) 403;;; v 404 ("$(3"0(B" (?e "$(3"+(B") (?u "$(3",(B") (?i "$(3"-(B") (?a "$(3".(B") (?E "$(3"/(B") (?o "$(3"1(B") 405 (?W "$(3"2(B" (?a "$(3"2(B") 406 (?e "$(3"0%n(B") (?u "$(3"0%r(B") (?i "$(3"0%o(B") (?E "$(3"0%q(B"))) 407;;; w 408 ("$(3#2(B" (?e "$(3#-(B") (?u "$(3#.(B") (?i "$(3#/(B") (?a "$(3#0(B") (?E "$(3#1(B") (?o "$(3#3(B") 409 (?W "$(3%p(B" (?e "$(3%n(B") (?u "$(3%r(B") (?i "$(3%o(B") (?a "$(3%p(B") (?E "$(3%q(B"))) 410;;; x 411 ("$(3!^(B" (?e "$(3!Y(B") (?u "$(3!Z(B") (?i "$(3![(B") (?a "$(3!\(B") (?E "$(3!](B") (?o "$(3!_(B") 412 (?W "$(3!`(B" (?a "$(3!`(B") 413 (?e "$(3!^%n(B") (?u "$(3!^%r(B") (?i "$(3!^%o(B") (?E "$(3!^%q(B"))) 414;;; y 415 ("$(3#R(B" (?e "$(3#M(B") (?u "$(3#N(B") (?i "$(3#O(B") (?a "$(3#P(B") (?E "$(3#Q(B") (?o "$(3#S(B") 416 (?W "$(3#T(B" (?a "$(3#T(B") 417 (?e "$(3#R%n(B") (?u "$(3#R%r(B") (?i "$(3#R%o(B") (?E "$(3#R%q(B"))) 418;;; z 419 ("$(3#B(B" (?e "$(3#=(B") (?u "$(3#>(B") (?i "$(3#?(B") (?a "$(3#@(B") (?E "$(3#A(B") (?o "$(3#C(B") 420 (?W "$(3#D(B" (?a "$(3#D(B") 421 (?e "$(3#B%n(B") (?u "$(3#B%r(B") (?i "$(3#B%o(B") (?E "$(3#B%q(B"))) 422;;; { | } ~ DEL 423 nil nil nil nil nil 424 ]) 425 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) 430 431;;;###autoload 432(defun ethio-sera-to-fidel-region (beg end &optional secondary force) 433 "Convert the characters in region from SERA to FIDEL. 434The variable `ethio-primary-language' specifies the primary language 435and `ethio-secondary-language' specifies the secondary. 436 437If the 3rd parameter SECONDARY is given and non-nil, assume the region 438begins with the secondary language; otherwise with the primary 439language. 440 441If the 4th parameter FORCE is given and non-nil, perform conversion 442even if the buffer is read-only. 443 444See also the descriptions of the variables 445`ethio-use-colon-for-colon' and 446`ethio-use-three-dot-question'." 447 448 (interactive "r\nP") 449 (save-restriction 450 (narrow-to-region beg end) 451 (ethio-sera-to-fidel-buffer secondary force))) 452 453;;;###autoload 454(defun ethio-sera-to-fidel-buffer (&optional secondary force) 455 "Convert the current buffer from SERA to FIDEL. 456 457The variable `ethio-primary-language' specifies the primary 458language and `ethio-secondary-language' specifies the secondary. 459 460If the 1st optional parameter SECONDARY is non-nil, assume the buffer 461begins with the secondary language; otherwise with the primary 462language. 463 464If the 2nd optional parametr FORCE is non-nil, perform conversion even if the 465buffer is read-only. 466 467See also the descriptions of the variables 468`ethio-use-colon-for-colon' and 469`ethio-use-three-dot-question'." 470 471 (interactive "P") 472 473 (if (and buffer-read-only 474 (not force) 475 (not (y-or-n-p "Buffer is read-only. Force to convert? "))) 476 (error "")) 477 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) 489 490 (setq current-language 491 (if secondary 492 ethio-secondary-language 493 ethio-primary-language)) 494 495 (goto-char (point-min)) 496 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)))) 508 509 (setq current-language 510 (cond 511 512 ;; when language tag is explicitly specified 513 ((not (eq next-language 'toggle)) 514 next-language) 515 516 ;; found a toggle in a primary language section 517 ((eq current-language ethio-primary-language) 518 ethio-secondary-language) 519 520 ;; found a toggle in a secondary, third, fourth, ... 521 ;; language section 522 (t 523 ethio-primary-language)))) 524 525 ;; If ethio-implicit-period-conversion is non-nil, the 526 ;; Ethiopic dot "$(3%u(B" at the end of an Ethiopic sentence is 527 ;; replaced with the Ethiopic full stop "$(3$i(B". 528 (if ethio-implicit-period-conversion 529 (progn 530 (goto-char (point-min)) 531 (while (re-search-forward "\\([$(3!!(B-$(3$a%)(B-$(3%e%n(B-$(3%r%s(B]\\)$(3%u(B\\([ \t]\\)" 532 nil t) 533 (replace-match "\\1$(3$i(B\\2")) 534 (goto-char (point-min)) 535 (while (re-search-forward "\\([$(3!!(B-$(3$a%)(B-$(3%e%n(B-$(3%r%s(B]\\)$(3%u(B$" nil t) 536 (replace-match "\\1$(3$i(B")))) 537 538 ;; gemination 539 (goto-char (point-min)) 540 (while (re-search-forward "\\ce$(3%s(B" nil 0) 541 (compose-region 542 (save-excursion (backward-char 2) (point)) 543 (point))) 544 )) 545 546(defun ethio-sera-to-fidel-english nil 547 "Handle English section in SERA to FIDEL conversion. 548Conversion stops when a language switch is found. Then delete that 549switch and return the name of the new language as a symbol." 550 (let ((new-language nil)) 551 552 (while (and (not (eobp)) (null new-language)) 553 (cond 554 555 ;; if no more "\", nothing to do. 556 ((not (search-forward "\\" nil 0))) 557 558 ;; hereafter point is put after a "\". 559 ;; first delete that "\", then check the following chars 560 561 ;; "\\" : leave the second "\" 562 ((progn 563 (delete-backward-char 1) 564 (= (following-char) ?\\ )) 565 (forward-char 1)) 566 567 ;; "\ " : delete the following " " 568 ((= (following-char) 32) 569 (delete-char 1) 570 (setq new-language 'toggle)) 571 572 ;; a language flag 573 ((setq new-language (ethio-process-language-flag))) 574 575 ;; just a "\" : not special sequence. 576 (t 577 (setq new-language 'toggle)))) 578 579 new-language)) 580 581(defun ethio-sera-to-fidel-ethio (lang) 582 "Handle Ethiopic section in SERA to FIDEL conversion. 583Conversion stops when a language switch is found. Then delete that 584switch and return the name of the new language as a symbol. 585 586The parameter LANG (symbol, either `amharic' or `tigrigna') affects 587the conversion of \"a\"." 588 589 (let ((new-language nil) 590 (verbatim nil) 591 start table table2 ch) 592 593 (setcar (aref ethio-sera-to-fidel-table ?a) 594 (if (eq lang 'tigrigna) "$(3"f(B" "$(3"c(B")) 595 596 (while (and (not (eobp)) (null new-language)) 597 (setq ch (following-char)) 598 (cond 599 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)) 608 609 ;; leave non-ASCII characters as they are 610 ((>= ch 128) 611 (forward-char 1)) 612 613 ;; ethiopic digits 614 ((looking-at "`[1-9][0-9]*") 615 (delete-char 1) 616 (ethio-convert-digit)) 617 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)))))) 632 633 ;; if control reaches here, we must be looking at a "\" 634 635 ;; verbatim mode 636 (verbatim 637 (if (looking-at "\\\\~! ?") 638 639 ;; "\~!" or "\~! ". switch to non-verbatim mode 640 (progn 641 (replace-match "") 642 (setq verbatim nil)) 643 644 ;; "\" but not "\~!" nor "\~! ". skip the current "\". 645 (forward-char 1))) 646 647 ;; hereafter, non-verbatim mode and looking at a "\" 648 ;; first delete that "\", then check the following chars. 649 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)) 657 658 ;; "\~!" or "\~! " : switch to verbatim mode 659 ((looking-at "~! ?") 660 (replace-match "") 661 (setq verbatim t)) 662 663 ;; a language flag 664 ((setq new-language (ethio-process-language-flag))) 665 666 ;; "\~" but not "\~!" nor a language flag 667 ((= ch ?~) 668 (delete-char 1) 669 (ethio-tilde-escape)) 670 671 ;; ASCII punctuation escape. skip 672 ((looking-at "\\(,\\|\\.\\|;\\|:\\|'\\|`\\|\?\\|\\\\\\)+") 673 (goto-char (match-end 0))) 674 675 ;; "\", but not special sequence 676 (t 677 (setq new-language 'toggle)))) 678 679 new-language)) 680 681(defun ethio-process-language-flag nil 682 "Process a language flag of the form \"~lang\" or \"~lang1~lang2\". 683 684If looking at \"~lang1~lang2\", set `ethio-primary-language' and 685`ethio-une-secondary-language' based on \"lang1\" and \"lang2\". 686Then delete the language flag \"~lang1~lang2\" from the buffer. 687Return value is the new primary language. 688 689If looking at \"~lang\", delete that language flag \"~lang\" from the 690buffer and return that language. In this case 691`ethio-primary-language' and `ethio-uni-secondary-language' 692are left unchanged. 693 694If an unsupported language flag is found, just return nil without 695changing anything." 696 697 (let (lang1 lang2) 698 (cond 699 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) 715 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) 725 726 ;; otherwise 727 (t 728 nil)))) 729 730(defun ethio-tilde-escape nil 731 "Handle a SERA tilde escape in Ethiopic section and delete it. 732Delete the escape even it is not recognized." 733 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)) 740 741 (cond 742 743 ;; \~-: 744 ((string= command "-:") 745 (setq ethio-use-colon-for-colon t)) 746 747 ;; \~`: 748 ((string= command "`:") 749 (setq ethio-use-colon-for-colon nil)) 750 751 ;; \~? 752 ((string= command "?") 753 (setq ethio-use-three-dot-question nil)) 754 755 ;; \~`| 756 ((string= command "`|") 757 (setq ethio-use-three-dot-question t)) 758 759 ;; \~e 760 ((string= command "e") 761 (insert "$(3%j(B")) 762 763 ;; \~E 764 ((string= command "E") 765 (insert "$(3%k(B")) 766 767 ;; \~a 768 ((string= command "a") 769 (insert "$(3%l(B")) 770 771 ;; \~A 772 ((string= command "A") 773 (insert "$(3%m(B")) 774 775 ;; \~X 776 ((string= command "X") 777 (insert "$(3%i(B")) 778 779 ;; unsupported tilde escape 780 (t 781 nil)))) 782 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))) 789 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) 796 797 ;; count up following zeros 798 (setq z 0) 799 (while (= (following-char) ?0) 800 (delete-char 1) 801 (setq z (1+ z))) 802 803 (cond 804 805 ;; first digit is 10, 20, ..., or 90 806 ((= (mod z 2) 1) 807 (insert (aref [?$(3$y(B ?$(3$z(B ?$(3${(B ?$(3$|(B ?$(3$}(B ?$(3$~(B ?$(3%!(B ?$(3%"(B ?$(3%#(B] (- ch ?1))) 808 (setq z (1- z))) 809 810 ;; first digit is 2, 3, ..., or 9 811 ((/= ch ?1) 812 (insert (aref [?$(3$q(B ?$(3$r(B ?$(3$s(B ?$(3$t(B ?$(3$u(B ?$(3$v(B ?$(3$w(B ?$(3$x(B] (- ch ?2)))) 813 814 ;; single 1 815 ((= z 0) 816 (insert "$(3$p(B"))) 817 818 ;; 100 819 (if (= (mod z 4) 2) 820 (insert "$(3%$(B")) 821 822 ;; 10000 823 (insert-char ?$(3%%(B (/ z 4))))) 824 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. 828If in rmail-mode or in mail-mode, execute the former; otherwise latter." 829 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))) 835 836;;;###autoload 837(defun ethio-sera-to-fidel-mail (&optional arg) 838 "Convert SERA to FIDEL to read/write mail and news. 839 840If the buffer contains the markers \"<sera>\" and \"</sera>\", 841convert the segments between them into FIDEL. 842 843If invoked interactively and there is no marker, convert the subject field 844and the body into FIDEL using `ethio-sera-to-fidel-region'." 845 846 (interactive "p") 847 (let ((buffer-read-only nil) 848 border) 849 (save-excursion 850 851 ;; follow RFC822 rules instead of looking for a fixed separator 852 (rfc822-goto-eoh) 853 (forward-line 1) 854 (setq border (point)) 855 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))) 861 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))))) 884 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)))))) 892 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)))))) 898 899;;;###autoload 900(defun ethio-sera-to-fidel-marker (&optional force) 901 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL. 902Assume that each region begins with `ethio-primary-language'. 903The 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)) 917 nil 918 'force)))) 919 920;; 921;; FIDEL to SERA 922;; 923 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 983 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)))) 988 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 ""))) 995 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. 999The variable `ethio-primary-language' specifies the primary 1000language and `ethio-secondary-language' specifies the secondary. 1001 1002If the 3dr parameter SECONDARY is given and non-nil, try to convert 1003the region so that it begins in the secondary language; otherwise with 1004the primary language. 1005 1006If the 4th parameter FORCE is given and non-nil, convert even if the 1007buffer is read-only. 1008 1009See 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'." 1012 1013 (interactive "r\nP") 1014 (save-restriction 1015 (narrow-to-region begin end) 1016 (ethio-fidel-to-sera-buffer secondary force))) 1017 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. 1021The variable `ethio-primary-language' specifies the primary 1022language and `ethio-secondary-language' specifies the secondary. 1023 1024If the 1st optional parameter SECONDARY is non-nil, try to convert the 1025region so that it begins in the secondary language; otherwise with the 1026primary language. 1027 1028If the 2nd optional parameter FORCE is non-nil, convert even if the 1029buffer is read-only. 1030 1031See 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'." 1034 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 "")) 1040 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) 1048 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 "-:")) 1056 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 "?")) 1063 1064 (mapcar 1065 '(lambda (x) 1066 (aset (aref ethio-fidel-to-sera-map x) 1067 2 1068 (if ethio-W-sixth-always ?' ?u))) 1069 '(77 93 141 181 197 277 440 441 442 443 444 457)) 1070 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 1075 1076 ;; first, decompose geminated characters 1077 (decompose-region (point-min) (point-max)) 1078 1079 ;; main conversion routine 1080 (goto-char (point-min)) 1081 (while (not (eobp)) 1082 (setq ch (following-char)) 1083 1084 (cond ; ethiopic, english, neutral 1085 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))) 1094 1095 (cond ; fidel, punc, digit 1096 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)) 1110 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)) 1119 1120 ;; now CH must be an ethiopic digit 1121 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)) 1129 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)) 1137 1138 ;; ordinary following digits 1139 (t 1140 (insert (aref ethio-fidel-to-sera-map ch)) 1141 (setq lonec nil 1142 fidel nil 1143 digit t)))) 1144 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)) 1155 1156 ;; ch can appear both in ethiopic section and in english section. 1157 (t 1158 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 1170 1171 (cond ; \ , eng-mode , punc , w3 , other 1172 1173 ;; backslash is always quoted 1174 ((= ch ?\\ ) 1175 (insert "\\") 1176 (forward-char 1)) 1177 1178 ;; nothing to do if in english mode 1179 ((eq mode 'english) 1180 (forward-char 1)) 1181 1182 ;; now we must be in ethiopic mode and seeing a non-"\" 1183 1184 ;; ascii punctuations in ethiopic mode 1185 ((looking-at "[,.;:'`?]+") 1186 (insert "\\") 1187 (goto-char (1+ (match-end 0)))) ; because we inserted one byte (\) 1188 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)) 1197 1198 ;; neutral character. no need to quote. just skip it. 1199 (t 1200 (forward-char 1))) 1201 1202 (setq lonec nil 1203 fidel nil 1204 digit nil))) 1205 ;; end of main conversion routine 1206 ))) 1207 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)) 1211 1212 ;; `q `k X `g mW bW GW fW pW wW 1213 (memq ethiocode '(389 405 421 437 440 441 442 443 444 457)))) 1214 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. 1218If in rmail-mode or in mail-mode, execute the former; otherwise latter." 1219 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))) 1225 1226;;;###autoload 1227(defun ethio-fidel-to-sera-mail nil 1228 "Convert FIDEL to SERA to read/write mail and news. 1229 1230If 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. 1234 1235The very same procedure applies to the subject field, too." 1236 1237 (interactive) 1238 (let ((buffer-read-only nil) 1239 border) 1240 (save-excursion 1241 1242 ;; follow RFC822 rules instead of looking for a fixed separator 1243 (rfc822-goto-eoh) 1244 (forward-line 1) 1245 (setq border (point)) 1246 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>"))) 1256 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>"))))) 1269 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)))))) 1275 1276;;;###autoload 1277(defun ethio-fidel-to-sera-marker (&optional force) 1278 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA. 1279The markers \"<sera>\" and \"</sera>\" themselves are not deleted." 1280 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)) 1294 nil 1295 'force)))) 1296 1297;; 1298;; vowel modification 1299;; 1300 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) 1308 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"))) 1317 1318 ;; set frequently referred character features 1319 (setq ch (ethio-char-to-ethiocode ch) 1320 base (* (/ ch 8) 8) 1321 modulo (% ch 8)) 1322 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")) 1327 1328 (setq 1329 newch 1330 (cond 1331 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))) 1350 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))) 1365 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))) 1379 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))) 1441 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))) 1461 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))) 1474 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))) 1490 1491 ;; otherwise 1492 (t 1493 nil))) 1494 1495 (cond 1496 1497 ;; could not get new character 1498 ((null newch) 1499 (error "Invalid vowel")) 1500 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)) "$(3%s(B")))) 1507 1508 ;; simple vowel modification 1509 (t 1510 (delete-char 1) 1511 (insert (ethio-ethiocode-to-char newch)))))) 1512 1513(defun ethio-ethiocode-to-char (ethiocode) 1514 (make-char 1515 'ethiopic 1516 (+ (/ ethiocode 94) 33) 1517 (+ (mod ethiocode 94) 33))) 1518 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))))) 1524 1525;; 1526;; space replacement 1527;; 1528 1529;;;###autoload 1530(defun ethio-replace-space (ch begin end) 1531 "Replace ASCII spaces with Ethiopic word separators in the region. 1532 1533In the specified region, replace word separators surrounded by two 1534Ethiopic characters, depending on the first parameter CH, which should 1535be 1, 2, or 3. 1536 1537If CH = 1, word separator will be replaced with an ASCII space. 1538If CH = 2, with two ASCII spaces. 1539If CH = 3, with the Ethiopic colon-like word separator. 1540 1541The second and third parameters BEGIN and END specify the region." 1542 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) 1549 1550 (cond 1551 ((= ch ?1) 1552 ;; an Ethiopic word separator --> an ASCII space 1553 (goto-char (point-min)) 1554 (while (search-forward "$(3$h(B" nil t) 1555 (replace-match " " nil t)) 1556 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)))) 1562 1563 ((= ch ?2) 1564 ;; An Ethiopic word separator --> two ASCII spaces 1565 (goto-char (point-min)) 1566 (while (search-forward "$(3$h(B" nil t) 1567 (replace-match " ")) 1568 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)))) 1574 1575 (t 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$(3$h(B\\2") 1581 (goto-char (match-beginning 2))) 1582 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$(3$h(B\\2") 1588 (goto-char (match-beginning 2)))))))) 1589 1590;; 1591;; special icons 1592;; 1593 1594;;;###autoload 1595(defun ethio-input-special-character (arg) 1596 "Allow the user to input special characters." 1597 (interactive "*cInput number: 1.$(3%j(B 2.$(3%k(B 3.$(3%l(B 4.$(3%m(B 5.$(3%i(B") 1598 (cond 1599 ((= arg ?1) 1600 (insert "$(3%j(B")) 1601 ((= arg ?2) 1602 (insert "$(3%k(B")) 1603 ((= arg ?3) 1604 (insert "$(3%l(B")) 1605 ((= arg ?4) 1606 (insert "$(3%m(B")) 1607 ((= arg ?5) 1608 (insert "$(3%i(B")) 1609 (t 1610 (error "")))) 1611 1612;; 1613;; TeX support 1614;; 1615 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 1677 1678;; 1679;; To make tex-to-fidel mapping. 1680;; The following code makes 1681;; (get 'ethio-tex-command-he 'ethio-fidel-char) ==> ?$(3!!(B 1682;; etc. 1683;; 1684 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)))) 1694 1695;;;###autoload 1696(defun ethio-fidel-to-tex-buffer nil 1697 "Convert each fidel characters in the current buffer into a fidel-tex command. 1698Each command is always surrounded by braces." 1699 (interactive) 1700 (let ((buffer-read-only nil)) 1701 1702 ;; Isolated gemination marks need special treatement 1703 (goto-char (point-min)) 1704 (while (search-forward "$(3%s(B" nil t) 1705 (replace-match "\\geminateG{}" t t)) 1706 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)) 1711 1712 ;; Special treatment for geminated characters 1713 ;; The geminated character (la'') will be "\geminateG{\la}". 1714 (goto-char (point-min)) 1715 (while (search-forward "$(3%s(B" nil t) 1716 (delete-backward-char 1) 1717 (backward-char 1) 1718 (insert "\\geminateG") 1719 (forward-char 1)) 1720 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))) 1732 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)) 1739 1740 ;; Special treatment for gemination 1741 ;; "\geminateG{\la}" or "\geminateG{{\la}}" will be "\la$(3%s(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$(3%s(B")) 1746 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)))) 1765 1766 ;; compose geminated characters 1767 (goto-char (point-min)) 1768 (while (re-search-forward "\\ce$(3%s(B" nil 0) 1769 (compose-region 1770 (save-excursion (backward-char 2) (point)) 1771 (point))) 1772 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 "$(3%s(B")) 1777 1778 (goto-char (point-min)) 1779 (set-buffer-modified-p nil))) 1780 1781;; 1782;; Java support 1783;; 1784 1785;;;###autoload 1786(defun ethio-fidel-to-java-buffer nil 1787 "Convert Ethiopic characters into the Java escape sequences. 1788 1789Each escape sequence is of the form \\uXXXX, where XXXX is the 1790character's codepoint (in hex) in Unicode. 1791 1792If `ethio-java-save-lowercase' is non-nil, use [0-9a-f]. 1793Otherwise, [0-9A-F]." 1794 (let ((ucode)) 1795 1796 ;; first, decompose geminations 1797 (decompose-region (point-min) (point-max)) 1798 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))))))) 1808 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)))) 1827 (t 1828 nil))) 1829 1830 ;; gemination 1831 (goto-char (point-min)) 1832 (while (re-search-forward "\\ce$(3%s(B" nil 0) 1833 (compose-region 1834 (save-excursion (backward-char 2) (point)) 1835 (point))) 1836 )) 1837 1838;; 1839;; file I/O hooks 1840;; 1841 1842;;;###autoload 1843(defun ethio-find-file nil 1844 "Transcribe file content into Ethiopic depending on filename suffix." 1845 (cond 1846 1847 ((string-match "\\.sera$" (buffer-file-name)) 1848 (save-excursion 1849 (ethio-sera-to-fidel-buffer nil 'force) 1850 (set-buffer-modified-p nil))) 1851 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 "$(3%v(B") 1860 (replace-match "$(3%w(B"))) 1861 (set-buffer-modified-p nil)))) 1862 1863 ((string-match "\\.tex$" (buffer-file-name)) 1864 (save-excursion 1865 (ethio-tex-to-fidel-buffer) 1866 (set-buffer-modified-p nil))) 1867 1868 ((string-match "\\.java$" (buffer-file-name)) 1869 (save-excursion 1870 (ethio-java-to-fidel-buffer) 1871 (set-buffer-modified-p nil))) 1872 1873 (t 1874 nil))) 1875 1876;;;###autoload 1877(defun ethio-write-file nil 1878 "Transcribe Ethiopic characters in ASCII depending on the file extension." 1879 (cond 1880 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))) 1887 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 "«te;") 1894 (aset ethio-fidel-to-sera-map 462 "»te;") 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)))) 1902 1903 ((string-match "\\.tex$" (buffer-file-name)) 1904 (save-excursion 1905 (ethio-fidel-to-tex-buffer) 1906 (set-buffer-modified-p nil))) 1907 1908 ((string-match "\\.java$" (buffer-file-name)) 1909 (save-excursion 1910 (ethio-fidel-to-java-buffer) 1911 (set-buffer-modified-p nil))) 1912 1913 (t 1914 nil))) 1915 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 "\\~`| " "\\~`? "))) 1922 1923;; 1924;; Ethiopic word separator vs. ASCII space 1925;; 1926 1927(defvar ethio-prefer-ascii-space t) 1928(make-variable-buffer-local 'ethio-prefer-ascii-space) 1929 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)) 1938 1939(defun ethio-insert-space (arg) 1940 "Insert ASCII spaces or Ethiopic word separators depending on context. 1941 1942If the current word separator (indicated in mode-line) is the ASCII space, 1943insert an ASCII space. With ARG, insert that many ASCII spaces. 1944 1945If the current word separator is the colon-like Ethiopic word 1946separator and the point is preceded by `an Ethiopic punctuation mark 1947followed by zero or more ASCII spaces', then insert also an ASCII 1948space. With ARG, insert that many ASCII spaces. 1949 1950Otherwise, insert a colon-like Ethiopic word separator. With ARG, insert that 1951many Ethiopic word separators." 1952 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 '(?$(3$h(B ?$(3$i(B ?$(3$j(B ?$(3$k(B ?$(3$l(B ?$(3$m(B ?$(3$n(B ?$(3$o(B ?$(3%t(B ?$(3%u(B ?$(3%v(B ?$(3%w(B ?$(3%x(B))) 1961 (insert-char 32 arg)) 1962 (t 1963 (insert-char ?$(3$h(B arg)))) 1964 1965(defun ethio-insert-ethio-space (arg) 1966 "Insert the Ethiopic word delimiter (the colon-like character). 1967With ARG, insert that many delimiters." 1968 (interactive "*p") 1969 (insert-char ?$(3$h(B arg)) 1970 1971;; 1972;; Ethiopic punctuation vs. ASCII punctuation 1973;; 1974 1975(defvar ethio-prefer-ascii-punctuation nil) 1976(make-variable-buffer-local 'ethio-prefer-ascii-punctuation) 1977 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 '(?$(3$i(B ?$(3%u(B ?. ?$(3$j(B ?, ?$(3$k(B ?\; ?$(3$h(B ?$(3$i(B ?: ?* ?$(3$o(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))) 1995 1996;; 1997;; Gemination 1998;; 1999 2000(defun ethio-gemination nil 2001 "Compose the character before the point with the Ethiopic gemination mark. 2002If the character is already composed, decompose it and remove the gemination 2003mark." 2004 (interactive "*") 2005 (cond 2006 ((eq (char-charset (preceding-char)) 'ethiopic) 2007 (insert "$(3%s(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)) 2017 (t 2018 (error "")))) 2019 2020;; 2021(provide 'ethio-util) 2022 2023;;; arch-tag: c8feb3d6-39bf-4b0a-b6ef-26f03fbc8140 2024;;; ethio-util.el ends here 2025