.
developing primaries

ここには私が開発の途中に調べたこと、見つけたことをそぞろに書き付けておきます。基本的には、トピックとして独立させるほど有用でない、あるいはほんの些細な情報を書いていく場所ですので、そのつもりでどうぞ。

10 pitfalls 10の落とし穴の話
デフォルト・アイコン システム・リソースにあるぞ
アプリケーションの亡霊 削除しても亡霊が残るぞ
Icons on OS 3.5 OS 3.5 ではアイコンの大きさが違うぞ
Draggable on OS 3.5 OS 3.5 で Draggable DA を作れるぞ
...? "..." を表示したいぞ
gdb の初期コマンドファイル cygnus な gdb で .gdbinit が効かないぞ
ソースが出ない Meadow + gdb でソースが出ないぞ
日付の幅 日付は何ピクセルで表示できるか?

10 pitfalls

Palm OS Programming という本があります。日本語訳も出ているいわゆる鳩本ですが、この本の著者である Neil Rhodes さんと Julie McKeehan さんが、O'reilly のサイトに

というコラムを掲載しています。詳細は省きますが、とりあえず中身はこんな感じです。

  1. フォームのオブジェクト・インデックスを使うべきところで、あやまってオブジェクト ID を使ってしまう
  2. イベント・ハンドラーにおいて、どういう時に True または False を返すべきなのかを分かっていない
  3. コンジットにはデバイス側に対応するアプリケーションが必要であることを忘れている
  4. 標準 C ライブラリの誤用
  5. ポップアップ・トリガーで扱われるイベントを勘違いしている
  6. 最初の FrmDrawForm の前に画面に対して描画を行う
  7. 最初の FrmDrawForm の後に FrmSetFocus を呼んでいない
  8. FrmCopyLabel を使うべきところで CtlSetLabel を使用する
  9. C 言語を勉強しながら Palm OS のプログラミングを覚えようとする
  10. POSE や Debug ROM を使わない

‥‥9番なんかはけっこうキビシイことを言っていますが ;-)、2番なんかはけっこう本質的かつ重要な話だと思います。とりあえず、6、7番は過去の OS のバグも絡む話なので、ぜひ原文にあたってみてください。


デフォルト・アイコン

Palm の標準ランチャーなどでは、独自のアイコンを持たないアプリケーションは「円に鉛筆」というデザインのアイコンで表示されます。最近ではアイコンのないアプリケーションも少なくなっているようですが、やはりアマチュアのディベロッパーにとってはアイコンを作るのが面倒、というのは根強くあるようで ;-)、それでも時々はアイコンなしのアプリケーションに出会います。

で、オリジナルのランチャーを作ろうと思うと、やはりそういうものに対応しなければならないので、RonDo なんかでもブランク・アイコン用のビットマップをわざわざ持っていたりしました。が、標準ランチャーが使っている例のアイコンはランチャー自身が持っているのではなく、システム・リソースとして置いてあるものだ、ということをつい最近になって知りました。単純に、'tAIB'ID = 10000 を指定すればラージ・アイコンが、同じく ID = 10001 を指定すればスモール・アイコンが取れます。

いろいろ探して 'psys' の 'rsrc' にあるんだーとか何とか分かったんですが、別にそれをデータベースとしてオープンする必要はありませんので、念のため。;-)


アプリケーションの亡霊

Palmware には、データベースを独自に操作できるものがけっこうあります。こういったアプリケーションにはデータベース削除機能があったりして、標準ランチャーのアプリケーション削除機能よりむしろこっちを使ったりしてしまいがちです。アレは何か遅いので。;-)

で、私も実は普段アプリケーションを削除するのにそういうことをやっていたんですが、ある時、デバッグ作業中に、原因不明のクラッシュに見舞われるようになったんですね。どう調べても原因が分からなかったので、結局、ハード・リセットをかけたんですが、後になって気づきました。

アプリケーション・データベースだけを削除すると、そのアプリケーションのプリファレンスだけが残ってしまうんです。考えてみれば当たり前なんですが、これは盲点でした。;-)

で、RonDo のアプリケーション削除機能も実は同じ仕組みだったので早速、修正しておきました。今の RonDo は、アプリケーションを削除すると、そのアプリケーションの CreatorID と同じ ResType を持つプリファレンス・レコードをクリーンアップします。これ、意外と見落とされがちなんじゃないかと思いますが、データベース操作系ソフトでは必須の機能かもしれません。

プリファレンスをお掃除する Palmware もたしかあったと思いますが。


Icons onOS 3.5

また OS 3.5 の話なんですが、OS 3.5 のビルトイン・アプリケーション(「メモ帳」とか「予定」とか)のアイコンは、今までのバージョンよりちょっと小さくなっています。これまでは 32 x 32 で作って、その下側はアプリケーションの名前で描き潰される、というのがスタンダードだったんですが、OS 3.5 はカラー・アイコンなどで容量が大きくなる関係上、メモリを節約しているのかもしれません。

で、Launcha などで表示がややずれてしまうようになったので、アイコン表示の際に以下のようなことをするようにしました。

bitmap_ptr = MemHandleLock(bitmap_handle);



WinDrawBitmap(bitmap_ptr, x + (32 - bitmap_ptr->width) / 2, y);

まぁ、解説するほどのこともないですね。要は、アプリケーションのアイコンを一覧表示する場合には、センタリングする必要がある場合もある、と。

(2000-06-30 追記) あと、アイコンが Transparent 属性を持つようになったので、上から描き潰す、というような横着はできなくなりました。Transparent なアイコンの場合、後ろに前のアイコンが残ってしまいます。


Draggable onOS 3.5

OS 3.5 ではカラー対応というばかりでなくいろいろコマゴマとした、しかしながら重要な変更がいくつも加えられています。特に Form や Window まわりの変更はけっこう大変なもので、おかげで DA のドラッガブル・テクノロジーが動作しなくなってしまっています。以下は、恐らく、自作 DA でドラッガブル・テクノロジーを実装していた人だけに有用な情報です。(必ず有用とは限りませんが。)

DA のドラッグ時、FrmEraseForm で DA の Form を消しますが、OS 3.5 ではこの時点で、その DA の Form が描画対象の Window でなくなってしまいます。3.5 以前では相変わらず form->WindowBounds.topLeft.[xy] などが基準だったので、相対座標 (0, 0) に WinInvertRectangleFrame を行えばよかったんですが、3.5 でこれをやると画面の左上に枠が描かれ続けます。

正しい対応はきっと、OS のバージョン番号を取得して別ロジックを回すことなんですが、横着をしたかった私は DA 起動時の初期化作業中に global_ptr->rootWindow = WinGetDisplayWindow(); などとしておき、ドラッグ開始時に WinSetDrawWindow(global_ptr->rootWindow); で描画の基準点をスクリーン・ウィンドウに指定することで OS バージョンの差異を乗り越えることにしました。

しかしこれだけだと ドラッグを開始する penDownEvent と、ドラッグ中の penMoveEvent の間で、タップ位置の座標基準がずれてしまいます。(penDownEvent では Form 相対の座標なので、これと比べて移動量を計算すると、Form の topLeft の分だけ、ズレが生じる。)

これは移動量計算の基準点を取る時に、

global_ptr->fromX = event->screenX + form->window.windowBounds.topLeft.x;

などとしてやれば大丈夫です。Y 座標についてももちろん、同様。


...?

Palm の画面サイズはひじょーに限られた資源ですので、「表示したい文字列を、全部は表示しきれない」ということはよくあります。そんな時、私は自前の TruncateString なんていう関数を呼んで、表示したい文字列をスペースに合わせて切り詰めます。この時、「切り詰めたよー」ということを明示するのが親切というものですが、そこで使われるのが "..." というキャラクタ(ここではピリオドを三つ書いていますが、PalmOS のフォントでは1キャラクタで用意されています)です。例えば、"This will be truncated.""This will be trunc..."みたいになるわけです。

ところが、このキャラクタ、二種類存在していたりします。私は何の気なしに一方を使っていたんですが、実は一方は日本語 OS 搭載機では文字化けしてしまいます。やれやれ。文字コードは以下のようになっていますので、なるべく日本語 OS で文字化けしない方を使用するようにしましょうね。

文字化けしない 文字化けする
\30 \205

gdb の初期コマンドファイル

gdb では .gdbinit というファイルを用意しておくと gdb の起動時に自動的にその中に記述されたコマンドを実行してくれます。PalmOS プログラミングの場合、

target pilot localhost:2000

とターゲットを指定する手順が毎回必要ですので、.gdbinit にこれを書いておくとすごくラク〜とか思ったんですが、.gdbinit を作って置いても全然反応なし。gdb の実行ファイルがあるディレクトリ、カレントの作業ディレクトリ、HOME として設定してあるディレクトリ、どこに置いても効きません。まぁ大したことじゃないし、などと思って放っておいたんですが、gdb のドキュメントを読むとちゃんと書いてありました。

DOS/Windows 環境では .gdbinit でなく gdb.ini を使うんですね。なるほどたしかに Windows の Explorer からは .gdbinit という名前のファイルは作れませんしね。というわけで、Windows で cygnus な gdb を使っている人は、.gdbinit でなく gdb.ini を用意しましょう、というお話でした。私は1年以上も気付かなかったんですが、普通はすぐ気付く?


ソースが出ない

私は Meadow + gdb でデバッグする人なんですが、この環境を作るために、昔はけっこう苦労したものです。gdbplug というプログラムが仲立ちしてくれないと、POSE(当時は CoPilot だったか)と gdb が連携できなかったりして。しかもタイミング次第で connect に失敗することもありました。

今の POSE(現時点で 3.0a5)では直接 gdb に繋がるので何かと楽になっているんですが、Meadow から gdb を、と思うと依然として残っている不具合に遭遇します。Windows で Mule(emacs) を使う以上しょうがないことなんですが、ドライブレターの扱いが問題になって、gdb は Meadow 上にソースを出せないんですよね。覚え書き代わりに、その対応策を書いておきます。元ネタはたしか、Meadow か mule-win32 のメーリング・リスト。

Meadow をインストールした所の下、Meadow/1.10/LISP/ にある gud.el を修正します。

(defun gud-find-file (file)
;; Don't get confused by double slashes in the name that comes from GDB.
  (while (string-match "//+" file)
    (setq file (replace-match "/" t t file)))
  (funcall gud-find-file file))

上記の関数を以下のように改めます。

(defun gud-find-file (file)
  (if (eq (string-match "//\\([a-zA-Z]\\)" file) 0)
    (setq file (replace-match "\\1:" t nil file))
    (while (string-match "//+" file)
      (setq file (replace-match "/" t t file))))
  (funcall gud-find-file file))

これで大丈夫。Meadow の現行バージョン 1.10 ではこれでうまくいきます。次バージョン以降はきちんと対応されるといいですね。あ、そうそう修正後は byte-compile を忘れずに。


日付の幅

PalmOS ではいわゆるプロポーショナル・フォントを使用していますので、開発にあたっては、表示しようとする文字列が何 pixel になるのか、ということを意識していないといけません。まぁ何とでもなる場合もありますが、たとえば、UI 画面を設計する時には、事前に「ここに入る文字には何 pixel 必要だろう」ということを見越しておかなければならない場合が多かったりします。

たまたま Watch-Ya! viewer の UI を設計し直している時に、日付って何ピクセル使うのか、ということを計算しなければならなかったので、結果を書いておきます。とりあえず標準の FontID 0 のみ。

数字のフォントは 5 pixel で固定なので考える必要はありません。問題は、月を "Jan, Feb, Mar ..." などと表示している時です。まぁ手計算しても多分、たかは知れていたんですが、Palm に実際にやらせてみました(FntCharsWidth)。この時必要だったのは Watch-Ya! で使っている、"MMM DD" というフォーマットだったんですが、これについては 5/10〜31 まで(つまり May 10 から May 31 まで)の 31 pixel が最大値となりました。要するに、たとえば Table の Width などとしては、33 Pixel 程度、場合によっては 31 Pixel ちょうど用意しておけば、まぁキレイに収まる、ということです。なるほどね。