============================================== 2004.02.29 発行 =========
         極私的 Emacs カスタマイズ紹介マガヂン
            Emacs をわたし色に染めて♪
------------------------------------------------------------------------
                第 27 回 Emacs 内部の文字コードの話
                (その1)内部コードから JIS コードへ
------------------------------------------------------------------------
※あなたのカスタマイズをぜひ教えてください。一般的なものから、他の人は
 絶対にしないような「外道」なものまで、何でも結構です。

※解除の方法は、このメールの末尾をごらんください。
========================================================================

	ごぶさたしております、でるもんた・いいじまです。

	実は、今日(2 月 29 日)になってから、「今月中(=今日中)に発行
	しないとまぐまぐさんに休刊措置をとられてしまう」という事に気づき、
	慌てて書いています。

☆目次☆
	・近況報告
	・前回の訂正
	・今回のお題
	・what-cursor-position の不便
	・内部コードの正体
	・split-char/char-component と make-char/make-character
	・バージョンの違いを吸収する関数を作る
	・文法解説(1)
	・文字コードを表示する関数
	・文法解説(2)
	・シフト JIS コードを表示する
	・cond の条件式に setq を入れるトリック
	・できあがったマクロは…
	・次回予告

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆近況報告☆

	またしても、まぐまぐさんの発行間隔の限度である「6 か月」に達して
	しまいました。

	そのあいだ私は何をしていたか、という話はちょっとややこしい問題を
	抱えているので伏せさせていただきます(体調不良とだけお伝えして
	おきます)が、今月になってから徐々に暖かくなってきて、体調が回復
	してきました。

	ちょっとした駄文を
	http://www.ht.sakura.ne.jp/~delmonta/gruss/20040204.html
	に上梓させていただきましたので、お読みいただければ幸いです。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆前回の訂正☆

	前回、

		?\x1234567890

	といった書き方をご紹介しました。ここで、通常の PC では下位 8 桁
	のみ有効、と書きましたが、実は Emacs の内部処理の関係上、下位 7
	桁しか有効になりません。

	【余談】これは、Emacs の変数には文字列でも数でも何でも代入できる
		ので、そのために、32 ビットの変数のうち 4 ビットを、「この
		変数にはどんな型のデータが入っているのか?」という情報の
		ために使ってしまっているからです。

	では Alpha のような 64 ビットプロセッサではどうかというと、これも
	実機で確認したところ、下位 8 桁しか有効になりませんでした。なんと
	なく中途半端な印象を受けるのですが、仕方ないのでしょうか。
	この内容はウェブ上のバックナンバーでは訂正してあります。


	また、Emacs 21 では、#x1234567890 という書き方ができますが、Mule
	2.3 や Emacs 20 にはこの機能はありませんので、?\x... という書き
	方でいくことにします。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆今回のお題☆

	今回は、「Emacs 内部の文字コード」を扱います。

	Emacs では、ひとつのファイルにいろんな文字(たとえば、欧文用のア
	クセント記号のついた英字、日本語の漢字仮名交じり文、ハングル文字、
	中国語の簡体字など)を混在できるので、その内部では、文章をファイ
	ルに保存するときの文字コードとは違う、特殊な内部コードが使われて
	います。

	また、最近の Emacs は Unicode を扱うこともできますが、かといって
	内部コードは Unicode ではありません。

	この内部コードはそのままでは扱いづらいので、通常の文字コードとの
	相互変換の方法を今回は扱います。

	ついでに、新しくマクロを作っていく上で、いろいろと新しい文法事項が
	出てきましたので、折に触れてそれも解説していくことにします。

  ○おことわり その1

	いままで、当マガヂンでは、出来るだけプログラミングの知識がない方
	でも読んでいただけるように執筆してきましたが、この回に限っては、
	文字コードというものを扱う関係上、16 進数やビット演算についての
	知識を前提とさせていただきます。

	申し訳ありませんが、「難しくて読めない」というかたは、とりあえずは
	完成したマクロだけを利用していただき、勉強が進んでから本文を読み
	返していただければ幸いです。

  ○おことわり その2

	当初は、Emacs で扱える文字コード一通りと Unicode をカバーしたかった
	のですが、時間の都合上、今回対応するコードは次のものに限らせていた
	だきます。

		○1 バイトの各種文字コード
		○JIS コード各種のうち、次のもの
			・JIS C6226:1978(いわゆる旧 JIS)
			・JIS X0208:1997(いわゆる新 JIS)
			・JIS X0212(補助漢字)
			・JIS X0213(新 JIS をさらに拡張したもの)の
			 第一面(94 区まで)
			・JIS X0201(1 バイト文字)
		○韓国語(KS C5601 のみ。Windows などの拡張には非対応)
		○簡体字中国語(GB2312 のみ)
		○繁体字中国語(EUC-TW のみ。Big5 には非対応)

	ただし、日本語以外については、充分な調査をする時間がとれなかった
	ため、バグを含んでいるかもしれません。

	なお、今回対応外の JIS X0213 第二面、Big5、Unicode については、
	機会があれば調査して対応しようと思いますが、いかんせん使う機会が
	ないので、いつになることやら…

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆what-cursor-position の不便☆

	Emacs には、カーソル位置の文字コードを知る機能があります。
	標準のキー操作で C-x =(飯嶋式では M-o C-x =)、コマンド名では
	M-x what-cursor-position です。そうするとたとえば、カーソル位置の
	文字が、

		Char: a (0141, 97, 0x61)  point=1166 of 2582(45%)
					column 14 ASCII ISO8859-1

	のように文字コードで表示されます。ところが、日本語の文字を表示
	させてみると、

		Char: あ (0151042, 53794, 0xd222)  point=1056 of 2704(39%)
			column 56  Japanese JISX0208.\(1983\|1990\)

	という、奇妙なコードが表示されます。point= と column= のところは
	現在のカーソル位置ですが、表示されるコードが奇妙です。

	半角カタカナの場合は、
		Char: ア (06261, 3249, 0xcb1)  point=1635 of 2879(57%)
			column 49  Japanese Katakana JISX0201.1976
	といった具合になります。確かに 16 進表記の下二桁は JIS コードです
	が、最上位の桁の 0xC00 は謎です。

	実は、ここで表示されているコードは JIS コードそのものではなく、
	Emacs の内部コードで、
		○全角文字………0xC000 + JIS上位バイト×128 + JIS下位バイト
		○半角カタカナ…0x0C00 + JISコード
	となっているのです。

	でも、我々が実際に知りたいのは、Emacs の内部コードではなく、JIS
	コードや EUC コード、シフト JIS コードなどですよね。今回は、

		カーソル位置の文字を、JIS コードや EUC コード、シフト JIS
		コードで表示する

	ということを目標にしていきます。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆内部コードの正体☆

	Emacs 内部の文字コードは
		○ASCII 文字とコントロールコード(タブなど)は、そのまま
		 ASCII コードで表す
		○8 ビット文字は、文字セットの種類を表す 17 以降の番号を
		 使って、
			セットの番号×128 + ひとつひとつの文字の番号
		○2 バイト文字は、文字セットの種類を表す 1〜15 の番号を
		 使って、
			セットの番号×128^2 + 上位バイト×128 + 下位バイト
	となっています。

	たとえば、JIS X0208(通常の日本語の全角文字)の場合は文字セットの
	番号が 3 なので、'あ' の場合は、
		3×128^2 + 36×128 + 34 = 53794
	となります。また、半角カタカナの場合は文字セットの番号が 25 なので、
	半角カタカナの 'ア'(文字コードは 0xB1 ですが、Emacs 内部では下位
	7 ビットをとって 0x31、つまり 10 進数で 49 と考えます)なので、
		25×128 + 49 = 3249
	となるわけです。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆split-char/char-component と make-char/make-character☆

	ところが、内部コードは Emacs のバージョンが変わると変更される可能
	性があります。実際、一部の文字では手元の Mule 2.3 と Emacs 21.3
	とで内部コードが違います。

	というわけで、内部コード⇔実際のコードの相互換算をする関数が用意
	されています。

	まず、Emacs 20 以降には、split-char という関数があります。たとえば、

		(split-char 53794)	; 'あ' で表示されたコードです

	という式を評価すると、(japanese-jisx0208 36 34) というリストが
	返ってきます。36 と 34 をそれぞれ 16 進数に直すと 24、22 ですから、
	ここから JIS コード「2422」が計算できることになります。

	一方で、Mule 2.3 には、この関数はありません。
	そのかわりに、char-component という関数があります。

		(char-component 53794 0)
		(char-component 53794 1)
		(char-component 53794 2)

	をそれぞれ評価してみると、順に、
		日本語を示す 146(lc-jp)
		'あ' の EUC コードの上位バイト、164(0xA2)
		'あ' の EUC コードの下位バイト、162(0xA0)
	が得られます。

	なお、1 バイト文字の場合は、
		(split-char 3249)	→(katakana-jisx0201 49)
		(char-component 3249 0)	→137(lc-kana)
		(char-component 3249 1)	→177(0xB1、'ア' の文字コード)
		(char-component 3249 2)	→0
	となります。ASCII 文字の場合は、
		(split-char 64)		→(ascii 64)
		(char-component 64 0)	→64
		(char-component 64 1)	→0
	です。

	逆に、実際の文字コードから内部コードに変換するには、Emacs 20 以降
	では make-char を、Mule 2.3 では make-character を使います。
		(make-char 'japanese-jisx0208 34 32)	→53536
		(make-character lc-jp 34 32)		→53576

	ちなみに、Emacs でどんな文字がサポートされているのかを知るには、

	; Emacs 20 以降の場合
	(setq i 1)
	(while (< i 128)
		(insert (format "%d %S\t%S\n"
			i
			(car (split-char (* i 128)))
			(car (split-char (* i 128 128)))
		))
		(setq i (1+ i))
	)

	; Mule 2.3 の場合
	(setq i 1)
	(while (< i 128)
	        (insert (format "%d %s\t%s\n"
			i
			(char-description (* i 128))
			(char-description (* i 128 128))
		))
		(setq i (1+ i))
	)

	で知ることができます。

	【補足】Emacs 20 以降の場合、文字コード 0x80〜0xFF については、
		・0x80〜0x9F は eight-bit-control
		・0xA0〜0xFF は eight-bit-graphic
		と、別々のカテゴリーに入れられています。
	    
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆バージョンの違いを吸収する関数を作る☆

	というわけで、まずは、バージョンの違いを吸収する関数を作るところ
	から始まります。次のように書きます。

	(cond
	((fboundp 'split-char)	;Emacs 20 以降
		(fset 'ds-char-charset (symbol-function 'char-charset))

		(defun ds-char-description (c)
			(charset-short-name (char-charset c))
		)

		(defun ds-char-to-7bit (c) (let ((L (split-char c)))
			(if (nth 2 L)
				(+ (* 256 (nth 1 L)) (nth 2 L))
				(nth 1 L)
			)
		))

		; その他、Emacs 20 以降用の関数定義をここに書く

	)((boundp 'lc-jp)        ; Mule 2.3
		(fset 'ds-char-charset    (symbol-function 'char-leading-char))

		(defun ds-char-description (c)
			(or (char-description c) "ASCII")
		)

		(defun ds-char-to-7bit (c)
		(let (
			(zeroth (char-component c 0))
			(first  (char-component c 1))
			(second (char-component c 2))
		     )

			(cond
				((= first  0) (logand 127 zeroth))
				((= second 0) (logand 127 first ))
				(t (logand ?\x7F7F (+ (* first 256) second)))
			)
		))

		; その他、Mule 2.3 用の関数定義をここに書く
	))

	ds-char-to-7bit は 7 ビットコードでの文字コードを返す関数で、
	たとえば 'あ' なら JIS コードの 0x2422 を返します。

	半角カタカナの 'ア' の場合は、JIS コードの 0xB1 ではなく、その
	下位  7 ビットの 0x31 を返します。0xB1 という値を算出するための
	措置は次で説明します。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆文法解説(1)☆

	先に進む前に、ここで使われている文法について一通り説明しておきます。

  ○fset

	まず、fset という関数を使っています。これは
		(fset 'X (symbol-function 'Y))
	という形で使い、関数 X に関数 Y をコピーします。つまり、関数 X を
	呼び出すと関数 Y が呼び出されるようになります。

	このコードでは、ほとんど同じ内容の関数 char-charset(Emacs 20 以降)
	と char-leading-char(Mule 2.3)を同じ ds-char-charset という名前で
	呼び出すために使っています。

	ただ、ds-char-description については、Mule 2.3 の char-description
	と Emacs 20 以降の charset-short-name とでは与えるべき引数が違い、
	また、char-description は ASCII の範囲の文字に対しては nil を返す
	ので、普通に defun しています。

	この fset は、既存の関数の内容を書き換える時にも使います(C++ や
	Java などのオブジェクト指向言語をご存じの方は、クラスを継承して
	関数をオーバーライドするのと同じだといえばわかりやすいでしょう)
	が、そういう使い方については、またの機会に説明することにします。

  ○let

	次に、let という命令を使っています。これは、ローカル変数(let の
	括弧の中でのみ通用する変数)を作るためのもので、たとえば
		(setq a 1)
		(let (a)
			(setq a 2)
			(message "letの内側ではa=%d" a)
			(sleep-for 1)
		)
		(message "letの外に出るとa=%d" a)
	とすると、
		letの内側ではa=2
		letの外に出るとa=1
	と表示されます。

	ここでは、ds-char-to-7bit 関数の中で L、zeroth、first、second と
	いう変数を使いたいのですが、別の関数の中で同名の変数が使われて
	いるとそれを書き換えてしまって困るので、let で囲んでいます。

	なお、上記の例からも分かるように、let の直後の括弧の中には、単な
	る変数名だけでなく、(変数名 初期値) という形のものも入れることが
	できます。複数の変数を入れることも可能です。

	【補足】よく似た構文として let* というものがありますが、ここでは
		割愛します。

  ○logand

	Mule 2.3 のほうのコードでは、logand(LOGical AND の略)という関数
	を使っています。これは、条件判断に使う and 関数と違って、ビット
	単位での AND 演算をする関数です。C、Perl、Java などの言語を使った
	ことのあるかたなら、「&&」と「&」の違いだといえばわかりやすいで
	しょうか。

	ここで logand が必要なのは、上で見たように、コードによっては
	char-component 関数が 8 ビットの値を返すことがあるためです。

	ちなみに、logand と同様に logior(LOGIcal OR)という関数もあって、
	C/Perl/Java の「|」と同じようにビット単位で OR 演算をします。
	こちらは、次項で使います。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆文字コードを表示する関数☆

	次に、この ds-char-to-7bit を使って、JIS コードと EUC コードを
	表示する関数を作ります。

	(defun ds-describe-char (&optional c)
		(interactive)
		(or c (setq c (char-after (point))))

		(if (integerp c) (let (7bit)
		    (setq 7bit (ds-char-to-7bit c))
		    (message "%s, %s, 7bit=0x%x, 8bit=0x%x"
			(ds-char-description c)
			(cond
				((< c 32) "<control>")

				((and (>= c 127) (< c 160)) "<control>")
				(t (format "'%c'" c))
			)
			7bit
			(if (< 7bit ?\x100)
				(logior ?\x80 7bit)
				(logior ?\x8080 7bit)
			)
	            )
	        ))
	)

	7 ビットコードはそのまま JIS コードや ASCII コードになります。
	そのコードと 0x80(2 バイト文字の場合は 0x8080)との OR をとった
	ものが 8 ビットコードで、2 バイト文字ならそのまま EUC コード
	(EUC-JP、EUC-CN、EUC-KR、補助漢字のコード、EUC-TW の下位ビット)
	になりますし、欧文(ISO-8859 系)や半角カタカナの場合は通常使わ
	れる 8 ビットの文字コードになります。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆文法解説(2)☆

  ○&optional

	この関数の定義では、引数 c に &optional という指定をしてあります。
	これは、この引数は省略可能という意味です。省略した場合は c には
	nil が入ります。

	普通にこの関数をキーに割り当ててそのキーを押したり、M-x ds-describe-
	char RET と入力したりした場合は引数が省略されたものとして c には
	nil が入ります。一方で、Lisp プログラムから (ds-describe-char ?a)
	などと呼び出した場合には、c には ?a、つまりは 'a' の文字コードで
	ある 97 が入ります。

	この関数では、
		○キーボードからこの関数を呼び出した場合には、カーソル位
		 置の文字のコードを表示
		○Lisp プログラムからは、カーソル位置以外の文字のコードを
		 表示したい場合を考慮して、引数で文字を指定できるように
		 する
	という設計にしてあります。これが、
		(or c (setq c (char-after (point))))
	というコードの意図です。

  ○integerp

	文字通り、引数が整数型かどうかを判定する関数です。ここでは、カー
	ソルがファイルの末尾にある場合に (char-after (point)) が nil を
	返すので、後々の処理でエラーにならないようにするためです。

	【蛇足】boundp、commandp、y-or-n-p などで薄々お気づきだと思います
		が、Lisp では一般に、「XXX か否か」を判定する関数には
		XXXp という名前をつけます。読み方は単に「ピー」で、たと
		えば integerp の場合は「インテジャーピー」です。

  ○「7bit」という変数名

	以前、第 6 回で「/」という文字を含んだ関数を作りましたが、Emacs
	Lisp では、「/」の他にも、数字で始まる関数・変数名も使うことが
	できるのです。もちろん、数字だけの変数名は使えません。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆シフト JIS コードを表示する☆

	次は、シフト JIS コードを表示する機能の制作です。

  ○そもそも、シフト JIS コードとは?

	シフト JIS コードは、ASCII 文字、半角カタカナ、全角文字を同時に
	扱うために考え出されたコードで、ASCII と半角カタカナで使われて
	いない 0x81〜0x9F、0xE0〜0xEF(と、環境によっては 0xF0〜0xFC)
	だけを 1 バイト目に使用して全角文字を表現します。

	JIS コードの 2 つの区(たとえば 0x2121〜0x227E;1 つの区は 94 文
	字です)をシフト JIS では 1 つの第一バイト(この場合は 0x81)で
	表現するために、2 バイト目には 0x40〜0xFC を使います(ただし、
	0x7F は DEL コードなので使用しません)。

	【余談】シフト JIS コードは Microsoft の OS とともに普及したこと
		から、別名「MS 漢字コード」ともいいますが、一説には、こ
		れを考案したのは Microsoft ではなく、アスキー社が UNIX で
		日本語を扱うために考え出したのがはじまりだとも言われて
		います。

  ○JIS コードからシフト JIS コードへの変換

	というわけで、JIS コードからシフト JIS コードへの変換は、次のよ
	うなコードで行うことができます。

	(defun jis-to-sjis (H L &optional plane)
		(or plane (setq plane 1))
		(setq H (- H ?\x21))
		(setq L (- L ?\x21))

		(setq L (+ (* (% H 2) 94) L ?\x40))
		(if (>= L ?\x7F) (setq L (1+ L)))

		(setq H (+ (/ H 2) ?\x81))
		(if (>= H ?\x9F) (setq H (+ H ?\x40)))

		(+ (* H 256) L)
	)

	H と L にはそれぞれ、JIS コードの第一バイト、第二バイトを与えます。
	関数内部で使っていない引数「plane」は、後日、JIS X0213 の第二面
	(第四水準)に対応するために用意してあるものですので、省略して
	使うこともできるようにしてあります。省略した場合は 1(第一面)と
	して取り扱うことにします。

	この関数を使うと、
		(jis-to-sjis 36 34) → 33440(=0x82A0、'あ'のコード)
	という具合に、シフト JIS コードに変換することができます。

  ○Emacs の内部コードからの変換

	ここで作ったのは、JIS コードからシフト JIS コードへの変換部分です。
	次に、Emacs の内部コードからの変換部分を作らなければいけません。

	これは次のようにします。

	;Emacs 20 以降の場合
	(defun ds-char-to-sjis (c)
	    (setq c (split-char c))
	    (cond
		((eq (car c) 'japanese-jisx0208-1978)
				(jis-to-sjis (nth 1 c) (nth 2 c) 1))
		((eq (car c) 'japanese-jisx0208)
				(jis-to-sjis (nth 1 c) (nth 2 c) 1))
		((eq (car c) 'japanese-jisx0213-1)
				(jis-to-sjis (nth 1 c) (nth 2 c) 1))
                ;((eq (car c) 'japanese-jisx0213-2)
		;		(jis-to-sjis (nth 1 c) (nth 2 c) 2))
		;第二面は今のところ jis-to-sjis がサポートしていないので
		;コメントアウト
            )
        )

	;Mule 2.3 の場合
        (defun ds-char-to-sjis (c)
        (let (
                (charset (char-component c 0))
                (first   (logand (char-component c 1) ?\x7F))
                (second  (logand (char-component c 2) ?\x7F))
             )

                (cond
                        ((= charset lc-jp   ) (jis-to-sjis first second 1))
                        ((= charset lc-jpold) (jis-to-sjis first second 1))
                )
        ))

	Emacs 20 以降では、文字の種類を表す japanese-jisx0208 などはシン
	ボル(名前)なので、eq を使って比較します。一方で、Mule 2.3 では
	lc-jp、lc-jpold は数値(具体的には、それぞれ 146 と144)なので、
	= を使って比較します。詳しい説明は長くなるのでここでは省きますが、
	とりあえずはそういうものなのだと思ってください。

	なお、Emacs 20 以降、Mule 2.3、どちらの場合も、cond 文の比較条件
	に合致しない場合は、ds-char-to-sjis は nil を返します。0 を返すと
	いう仕様にすることもできるのですが、「nil を返す」という仕様にして
	おくと、それが次項で活きてきます。

  ○ds-describe-char に組み込む

	最後に、この関数の呼び出しを ds-describe-char に組み込みます。
	次のようになります。

	(defun ds-describe-char (&optional c)
	    (interactive)
	    (or c (setq c (char-after (point))))

	    (if (integerp c) (let (7bit a)			;ここ修正
		(setq 7bit (ds-char-to-7bit c))
		(message "%s, %s, 7bit=0x%x, 8bit=0x%x%s"	;ここ修正
		    (ds-char-description c)
		    (cond
			((< c 32) "<control>")
			((and (>= c 127) (< c 160)) "<control>")
			(t (format "'%c'" c))
		    )
		    7bit
		    (if (< 7bit ?\x100)
			(logior ?\x80 7bit)
			(logior ?\x8080 7bit)
		    )

		    ;この cond 文を追加
		    (cond
			((setq a (ds-char-to-sjis  c)) (format ", SJIS=%x" a))
			((setq a (ds-char-to-big5  c)) (format ", Big5=%x" a))
			((setq a (ds-char-to-euctw c)) (format ", EUC=%x"  a))
			(t "")
		    )
	        )
	    ))
	)

	ここでは割愛しますが、ds-char-to-euctw という関数も用意しました。
	ds-char-to-big5 はまだ作っていないので、
		(defun ds-char-to-big5 (c)
			nil
		)
	というダミーの関数を作っておいて、当分はそれでごまかすことにします。
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆cond の条件式に setq を入れるトリック☆

	上記のコードでは、cond の条件式に setq 関数を書くというトリックを
	書いています。setq は変数への代入文ですが、同時に、(setq ....) と
	いう式の値は、変数に代入された値になります。C 言語をご存じの方は、
		if ( (fp=fopen("input.txt","r")) == NULL )
		{
			...
		}
	といった書き方と同じようなものだと思えばわかりやすいでしょう。

	この場合、a に代入された値を cond での条件判定に使います。

	ここで、「ds-char-to-sjis は、シフト JIS に変換できない文字が
	与えられたときには nil を返す」という仕様が活きてきます。もし、
	0 を返す仕様にしていたら、この条件式を
		(= 0 (setq (ds-char-to-sjis c)))
	などと書き直す必要が出てきて、字数が増えますし、それ以上に括弧が
	増えるので読みにくくなります。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆できあがったマクロは…☆

	できあがったマクロは、
	http://www.ht.sakura.ne.jp/~delmonta/emacs/ds-char.el
	に置いてあります。次のようにしてお使いください。

		(autoload 'ds-describe-char "ds-char")
		(define-key ctl-x-map "=" 'ds-describe-char)

	こうすると、C-x =(飯嶋式キー操作では M-o C-x =)で ds-describe-
	char が呼び出されるようになります。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆次回予告☆

	今後の予定は、
		○文字コードの話の続編
			・Big5のサポート
			・JIS コードや区点コードでの文字入力
		○便利なマクロ (4) ローマ字のミスタイプからの立ち直り
		○Backspace と Emacs 21 と Linux に関する奇妙な問題
		○コピー&ペーストの話
		○モードライン(反転行)をいじる
	などを予定しています。詳細はホームページをごらんください。

	それではまた♪

========================================================================
極私的 Emacs カスタマイズ紹介マガジン Emacs をわたし色に染めて♪

発行人  でるもんた・いいじま <delmonta@ht.sakura.ne.jp>
        [ホームページ] http://www.ht.sakura.ne.jp/~delmonta/emacs/
        [掲示板]       http://6036.teacup.com/delmonta/bbs

配信    インターネットの本屋さん・まぐまぐ
        http://www.mag2.com/m/0000013484.htm

登録解除・メールアドレス変更は発行人ホームページからどうぞ。また、発行人
ホームページでは、第 0 回からのすべてのバックナンバーを公開しています。
========================================================================

トップページツッコミは掲示板へ

© IIJIMA Hiromitsu, aka Delmonta
でるもんた@電腦外道學會-ndd.org