GNU Smalltalk GTK で 他文字コードの表示とか

ハマったのでメモ。


* * *


こんな風に ワークスペースとして作っておけば、そのアプリに存在しない機能も直接コード実行でどうにかなっちゃうものです。というわけでテキストエディタ風に使ってみようとファイルアクセス。

| file |
file := '/home/minekoa/install-memo' asFile.
textbuf insertAtEnd: file contents.


おぉ、いい感じ!・・と思ったのもつかの間、別のファイルを開こうとすると、そちらでは開けません。

(gst:18604): Gtk-CRITICAL **: gtk_text_buffer_emit_insert: assertion `g_utf8_validate (text, len, NULL)' failed
(ip 8)GtkTextBuffer>>#insert:text:len:
(ip 16)GtkTextBuffer>>#insert:text:
(ip 8)GtkTextBuffer>>#insertAtEnd:
(ip 18)[] in PettitWorkspace>>#Doit
(ip 6)PettitWorkspace>>#Doit
(ip 6)[] in Behavior>>#evalString:to:
(ip 14)
(ip 54)Behavior class(Behavior)>>#evalString:to:
(ip 10)PettitWorkspace>>#doit
(ip 0)

あー、文字コードですかー。最初のテキストは UTF-8 で作成されていたので、何もしなくても問題なく表示されていたのですが、今回開こうとしたのは Shirt-JIS。

というわけで クラスブラウザで関係しそうなあたりをあさってみたけれど Squeak の文字コードいじりっぽいのは無い。

ていうか、

String >> encoding [
    "Answer the encoding of the receiver.  This is not implemented unless
     you load the Iconv package."

    <category: 'converting'>
    self notYetImplemented
]

とか書いてあって、なるほど GNU (というかUnix) ライズされてるなーとか思ったり。でもパッケージを読み込むと String なんて超基本的なクラスにメソッドが追加されていっちゃうあたりは、非常に Smalltalk っぽい ので何とも複雑な気分です。

| file |
PackageLoader fileInPackage: 'Iconv'.

file := '/home/minekoa/sample.txt' asFile.
textbuf insertAtEnd: (file contents asUnicodeString: 'CP932') 

でも、今度は別のエラー。

./pettitworkspace.st:73: Attempt to pass an instance of UnicodeString as a char *
(ip 8)GtkTextBuffer>>#insert:text:len:
(ip 16)GtkTextBuffer>>#insert:text:
(ip 8)GtkTextBuffer>>#insertAtEnd:
(ip 22)[] in PettitWorkspace>>#Doit
(ip 6)PettitWorkspace>>#Doit
(ip 6)[] in Behavior>>#evalString:to:
(ip 14)
(ip 54)Behavior class(Behavior)>>#evalString:to:
(ip 10)PettitWorkspace>>#doit
(ip 0)

で、ここでしばらく「なんだろ〜」とハマって I18N.EncodedString とかをこねこねしてたのですが、結局は単純な話で、

| file |
PackageLoader fileInPackage: 'Iconv'.

file := '/home/minekoa/sample.txt' asFile.
textbuf insertAtEnd: (file contents asUnicodeString: 'CP932') asByteArray

と、asByteArray すれば OK でした。


よかった、できて。


* * *


文字コードUnicode じゃなきゃだめなのに、 渡すときは char* になる Smalltalk オブジェクト(=ByteArray) じゃないとだめというところが味噌でした。

理屈は分かるけれど、これは GtkTextBuffer >> inseratAtEnd: とか中で asByteArray するようにしといて欲しいと思いました。