Archive for 2011年1月|Monthly archive page

pack と unpack

 UTF-8 版 newLISP では、explode が文字単位で動作します。だから、マニュアルの例にある

> (explode "¥000¥001¥002¥003") 
("¥000" "¥001" "¥002" "¥003")

 が使えません。なので、バイナリ・データを扱う時、UTF-8 版は使えないと思っていたのですが、私の理解が足りないだけでした(汗)。元ネタは、こちら
 こういった場合、unpack を使います。

(define (str2bytes str) (unpack (dup "b" (length str)) str))

 ここで、"b" は符号なし8ビット数を指定しています。ちなみに、"c" だと符号付き8ビット数です。
 これを使えば、

> (str2bytes "¥000¥001¥002¥003") 
(0 1 2 3)

 となります。扱いやすいように数値に変換していますが、文字列のままにしたい時は、unpack"s" を指定します。

> (unpack (dup "s" 4) "¥000¥001¥002¥003") 
("¥000" "¥001" "¥002" "¥003")

 さて、バイト数列から、バイナリ・データ(文字列)に変換するには、当然 pack を使います。

(define (bytes2str lst) (pack (dup "b" (length lst)) lst))

 UTF-8 版 newLISP でなければ、(mappend は newlisp-utility.lsp に定義してあります。)

(define (bytes2str lst) (mappend char lst))
or
(define (bytes2str lst) (apply append (map char lst)))

 とも書けます。

 ということで、UTF-8 版 newLISP でもバイナリ・データを扱えるようになりました。つまり、UTF-8 版 newLISP 上でShift-JIS データを UTF-8 データに変換できるということ。
 これで、Windows 環境でも UTF-8 版 newLISP だけでアプリケーションを組めるようになりました(笑)。

 以上、如何でしょうか?

newLISP v10.2.18 の翻訳マニュアル

 newLISP の開発バージョンが v10.2.18 にバージョンアップされたので、このバージョンのマニュアルの翻訳を up しました。

newLISP マニュアル & リファレンス v10.2.18

 もちろん、目次も日本語併記にしてあります。
 変更された関数は、extend、net-liten、ref、ref-all、signal です。詳細はマニュアルでどうぞ。
 また、同梱されている guiserver は、v1.43 です。

guiserver マニュアル v1.43

 いつものように、間違いやおかしな点が有りましたら、こちらの blog までご一報下さい。

 以上、如何でしょうか?

newLISP マニュアル・アップデート v.10.2.8 rev-22

 newLISP のマニュアルが rev-22 のバージョンアップされたので、それに合わせたアップデートです。
 変更内容は、組込set-refset-ref-all の一部表現の変更です。関数の機能が変わったわけではありません。
 ただし、ついでに、日本語訳を一部訂正しています(汗)。

 newLISP マニュアル & リファレンス の全訳のリリースで、現在のバージョンは、v.10.2.8 rev 22 です。

日本語併記 newLISP ユーザー マニュアル

 目次も含め日本語併記にしてあります。

 いつものように、間違いやおかしな点が有りましたら、こちらの blog までご一報下さい。

 以上、如何でしょうか?

newLISP で音楽を楽しむ...UTF-8化(解説編)

 “newLISP で音楽を楽しむ...UTF-8化”は、如何だったでしょうか?
  WideChar 対応で使う Windows API は、

(import "winmm.dll" "mciSendStringW")
(import "winmm.dll" "mciGetErrorStringW")

 となります。ただし、ファイル名を使わないコマンドには、WideChar は必要ないので、

(import "winmm.dll" "mciSendStringA")

 も残してあります。
 UTF-8 版 newLISP の文字列は、当然、文字コードがUTF-8 コードですので、それを WideChar に変換するには、組込unicode を使います。
 ただし、組込unicode の戻り値は、4バイトの UNICODE文字列。日本語 Windows の WideChar は、2バイトなので、変換しなければなりません。

(define (long2word str)
  (let (res "")
    (dotimes (i (/ (length str) 4))
      (let (c (slice str (* 4 i) 2))
        (unless (= c "¥000¥000")
          (extend res c))))
    res))

 組込explode暗黙のインデックス機能が使えれば良いのですが、どちらも文字単位で動作します。
 そこで、バイト単位で動作する組込slice を使って上位2バイトの “/000/000” を削除しています。
 WideChar から UTF-8 に変換するには、組込utf8 を使います。しかし、引数は 4バイトの UNICODE文字列です。
 そこで、WideChar に上位2バイトの “/000/000” を付加する関数も用意します。

(define (word2long str)
  (let (res "")
    (dotimes (i (/ (length str) 2))
      (let (c (slice str (* 2 i) 2))
        (unless (= c "¥000¥000")
          (extend res c "¥000¥000"))))
    (extend res "¥000¥000¥000¥000")))

 これらを、組込unicodeutf8 に組み合わせるだけです。

(define (toWchar str)
  (long2word (unicode str)))
(define (toChar str)
  (utf8 (word2long str)))

 関数toWchar が UTF-8 文字列を WideChar 文字列に変換し、関数toChar がその逆です。
 そして、ファイルが必要な関数 music:open と エラー内容を表示する関数 get-err-str に組み込めば終わりです。
 残りは、以前の“newLISP で音楽を楽しむ...context 化”と一緒です。

 以上、如何でしょうか?

newLISP で音楽を楽しむ...UTF-8化

 以前、Windows API を使った音楽ファイルを再生するスクリプトを紹介しましたが、WideChar には、対応していなかったので、”é” を含むようなファイル名の音楽ファイルには、使えませんでした(汗)。
 現在では、WIndows 上でも、UTF-8版 newLISP を使えるので、WideChar 対応にできるはず(guiserver.jar には開発版のV1.43がお薦め)。
 ということで、スクリプトを作ってみました。

(context 'MAIN:music) 
(import "winmm.dll" "mciSendStringW")
(import "winmm.dll" "mciSendStringA")
(import "winmm.dll" "mciGetErrorStringW")

(define l_rtnStr 128)
(define rtnStr (dup "¥000" (+ 1 l_rtnStr)))
(define (long2word str)
  (let (res "")
    (dotimes (i (/ (length str) 4))
      (let (c (slice str (* 4 i) 2))
        (unless (= c "¥000¥000")
          (extend res c))))
    res))
(define (word2long str)
  (let (res "")
    (dotimes (i (/ (length str) 2))
      (let (c (slice str (* 2 i) 2))
        (unless (= c "¥000¥000")
          (extend res c "¥000¥000"))))
    (extend res "¥000¥000¥000¥000")))
(define (toWchar str)
  (long2word (unicode str)))
(define (toChar str)
  (utf8 (word2long str)))

(define (get-err-str n)
  (mciGetErrorStringW n rtnStr l_rtnStr)
  (println (toChar rtnStr)))

(define alias-name " Music")
(define wait-time 500) 

(define (music:open m)
  (mciSendStringW (toWchar (string "open \"" m "\" alias" alias-name)) 0 0 0)) 

(define-macro (make-status)
  (letex (_cmd (string "status" alias-name " " (args 0))
          _func (sym (string (args 0))))
    (define (_func) (mciSendStringA _cmd rtnStr l_rtnStr 0) rtnStr)))
(make-status "mode")
(make-status "position")
(make-status "length") 

(define-macro (make-music)
  (letex (_cmd (string (args 0) alias-name)
          _func (sym (string (args 0))))
    (define (_func) (mciSendStringA _cmd 0 0 0)))) 
(make-music "close")
(make-music "play")
(make-music "stop")
(make-music "pause") 

(define (volume-off)
  (mciSendStringA "set Music audio all off" 0 0 0)) 
(define (volume-on)
  (mciSendStringA "set Music audio all on" 0 0 0)) 

(context MAIN)

 使い方は、“newLISP で音楽を楽しむ...context 化”と一緒ですが、動作には、Windows の UTF-8版newLISP が必要です。お間違えなく(笑)。
 WideChar対応の解説は、次回に。

 以上、如何でしょうか?