<CodeWarrior for Pilotのプログラム上のTIPS 971214加筆> 1:日本語の扱いについて 鈴木幸成氏(ysuzuki@gix.or.jp)がPilotRezを日本語にも対応できるようにするためのパッチを公開してくださいました。以下にその手順を引用させていただきます。 「次にPilotRezに対するパッチの アドレスを書きます。 もちろん、これはMetroWerks社とはなんの関係もないので決して問い合わせなど しないでください。 --------------------------------- CODE ID=1 008B9A 651E->601E bcc.s ->bra.s 008BFC 651E->601E bcc.s ->bra.s --------------------------------- この2bytesを変更すると MENU, tSTRなどのリソースに日本語を入れても文字化け しません。PiloGameもこのパッチを当てたPilotRezでリソース変換をしていま す。 PilotRezはインストールした後3ヵ所に存在すると思いますが、MPWから呼ばれる のは'CodeWarrior MPW:Tools'の中にあるものです。パッチを当てたものは PilotRezJとか別の名前にしてsaveするといいでしょう。(その時はもちろん Makefileの中味もPilotRezJにしてください)」 プログラム上のヒントになるかもしれないので以前書いた日本語化の方法も記しておきます。 「まず表示したい日本語の文字列をJ-OSがONの状態でPilotのMemoPadに入力する。そしてJ-OSをOFFにしてその文字を調べて、もし幸運にもトランプのマーク(スペード、クラブ等)が含まれていないときはHotSyncでマックにその文字列を送ります。当然マック上では化け化けになりますが(たとえば"戻る"->"ミァ竡")その文字列をCut & Pasteでリソースに張り付け、試しにtBTN あたりに入れコンパイルし、Pilotに転送して表示を確認します。もしだめだったり不幸のトランプが出てきたときはリソース経由の文字列の持ち込みはできませんので例えば FrmCopyTitle(frm, "祝日一覧"); CtlSetLabel ((ControlPtr) GetObjectPtr (prefDayFormatLBL), "月日"); StrCopy(LstGetSelectionText((ListPtr) GetObjectPtr(prefDayFormatList), 0), "月/日"); とコードでリソース上の文字列を定義してあげなければなりません。また文字列を英語のフォントで見たときにバックシュラッシュ(\)が含まれている場合はCの構文上 CtlSetLabel ((ControlPtr) GetObjectPtr (prefClockOptionLBL), "時計表\示オプション"); といったように\を文字列だと示さないと化け化けになります(試しにフォントを英語に変えてみてください)。そして大変重要なことは置き換えられるリソースにはあらかじめ置き換えたい文字列(以上の)文字数を入れておくことです。そうしないと後ろにつづくリソースが壊されてリソースは(見掛け上)あるはずなのにObjectがないといってリスタートになります。 またSTRリソース等に文字列を入れておき、プログラム中でセットする方法がありますが、マックのリソースの文字列はPascal文字列で格納される点に注意してください。以下にSTRリソースから文字列を取ってくるルーチンを記します。ご自由にお使いください。 void MyGetStrFromSTRRes(short resID, char *strPtr) { VoidHand resH; CharPtr resP; char num; resH = DmGetResource ('STR ', resID); ErrFatalDisplayIf( !resH, "Missing STR res" ); resP = (Char*) MemHandleLock(resH); num = *(resP++); for (short i = 0; i < (short) num; i++) *strPtr++ = *resP++; *strPtr = '\0'; MemHandleUnlock (resH); } また複雑なものを書こうとするならメモリーは食いますがPICTで張り付けるという手もあります。(PICTもどうやらPilot用にリソース変換しているみたいで、WinDrawBitmapでDraw系のPICTを指定しても良きに計らってくれるみたいです。圧縮はそれなりにしているみたいですがビット展開をしているようなのでDraw系でつくったPICTリソースでのサイズはあてになりません。画面サイズに大きな制約があるため、私はDrawで大まかに描いてからビットに落とし、気の済むまでいじくりまわしています。) トランプマーク以外にも鬼門の文字があるみたいですが、あとは試行錯誤というところでしょう。」 2:エミュレーターで動くのにMPWでエラーが出る場合 これにはなかなか泣かされます。だってエミュレーションで動作確認を済ませているのに結局書き直しになるからです。 A)文字列の扱いについて 1とも関連するのですが static char *strWeek[] = {"日", "月", "火", "水", "木", "金","土"}; strWeek[myWeekday] で曜日の文字を取得しようとした場合、MPWでbuildしたときlinkエラーがでます。この回避法として例えば static char strWeek [] = "日月火水木金土"; char str[3]; str[0] = strWeek[2*myWeekday]; str[1] = strWeek[2*myWeekday + 1]; str[2] = '\0'; があげられます。 B)ANSI関数について ANSI関数はエミュレーションで通るのにMPWではエラーを起こします(全部を試したわけではありませんが)。 3:なかなか見つけるのが困難で陥りやすいバグの避け方 私が経験し、原因を突き止めるのに苦労したものについて記します。 A)ルーチン内で大きなローカル変数を使っている場合 Pilotではスタックにあまり余裕がありません。マック上のエミュレーターで正常に動作してもPilotで暴走する場合はローカル変数をグローバル変数にして試してみてください。それでもだめなときは変数をビットにわけて有効に使ってみてください。 typedef struct { Word year :7; Word month :4; Word day :5; } DateType; がいいお手本になります。 またそれでもダメなときはデーターベースを使う手もあります。 B)リソース上の文字列をプログラムで置き換えている場合 日本語の扱いの項目にも書いておきましたが、リソース上にあらかじめ置き換える文字列(漢字は2文字で計算)以上の文字をセットしておく必要があります。(あとから文字列を変えたときは要注意です。あらかじめリソースのほうに4文字ほど多めに入れておくのも手です。対象となる物の数が多いときは探すのが大変です。) C) FormHandleEventルーチンでeventチェック(switch (event->eType){})の後にFrm内のobjectを定期的にアップデートするルーチンを入れた場合(例えば時々刻々変化する時刻を書き直すとか画面に点をチカチカ点滅させるとか) FrmGotoForm(mainForm)といったFormの切り替えをおこなった場合にはこれらのルーチンをスキップさせないと何だかよくわからないけどよく落ちるとか画面の表示がなんだか変だということになります。 D)一つのFormに複数のメニューバーを切り替えて使う場合 結論からいいますとこのような使い方はMenuHackを利用できるようにしようとする限り現状では不可能だと思ってください。これについてはシステム上のバグであるとEd(HackMasterの作者)も考えており、USRに連絡してあります。(試されたい方はサンプルプログラム (MemoPad 03)ではMenuHackが効かず、ID=1000のtFrmのMenu Rsc IDに1500(MBARのID)を入れてた場合MenuHackと一緒に使うとfreezeします。MenuSetActiveMenuをSetCurrentMenuルーチンの最後(MenuInitのあと)にガイドラインに沿って入れた場合、ダイアログを開いたりしたときにめちゃくちゃになります。)メニューバーを複数使いたいときはその数だけFormを用意し、Formを切り替えて使うことになります。 E)tFLDを利用して文字列を表示する場合 状況によって異なる文字列を表示する場合tFLDを用いるとなにかと便利ですが、この場合マック上のエミュレーターでtFLDの領域をクリックしないでください。(Pilot上では問題ないのですがマックが落ちます。) 4:知っていると時間が節約できるTIPS A)リソースを変更し、画面のレイアウトのチェック等の目的でエミュレーターで動かす時、ソースに変更がない場合はコンパイルは必要ありません。これはエミュレーターが実行時にリソースファイルを参照するためです。裏返すとResEditでリソースをオープンしたままエミュレーターを動かすとエラーを起こします。 B)ディスクキャッシュを大きくとっておくとmakefileでbuildするときに時間が短縮できます(たとえば38秒->27秒ぐらい)。コントロールパネルでいろいろいじってみて試してみてください。makefileでのbuildは比較的時間がかかるので最適な値を決めるだけの価値は十分にあります。 5:知っていると便利なTIPS A)ボタンのアイコン化 絵を画面に描いておきその枠に合わせてボタンを用意しておくと絵をタップしたときにボタンで指定していた枠の範囲が反転し、あたかもアイコンを押したような効果がありあす。J-Infoのメニュー画面で利用しています。 6:バージョン管理について バージョンアップに伴いプレファレンスの内容が変わる場合には以下の点を注意してください。 私の知る限りバージョンの設定をする部位は全部で3箇所あります。 a.tverリソース b.makefile の中のPilotRezのコマンドラインの中 たとえば、 PilotRez -v 07 -t appl -c JInf -it J-Info.i -ot "J-Info" の場合"-v 07"の部分でバージョンを指定しています。 c.preference fileを扱うコマンド(PrefGetAppPreferencesやPrefSetAppPreferences)の中でのバージョン指定 ここで注意するのはcのプレファレンスファイルの扱い時のバージョン指定がint変換される事です。つまりv0.7だからといってバージョン指定を0.7としてしまうと切り捨て御免の0となり、当分更新されないことになります。(昔はマックから転送するのにPilotDebuggerを使っていたのですが、このときはあらかじめPilot上の古いバージョンを消しておく必要がありました。hotsyncでアプリを上書きできるようになり、プレファレンスのバージョンの扱いのミスが表面化しました。)プレファレンスのデーター構造に変更のあるバージョンアップの場合、プログラムをかぶせてインストールせずに一旦前のプログラムを消してからインストールをすることをお勧めします。以前のプレファレンスはゴミとなってメモリー上に残るか最悪の場合暴走の原因になります。 7:その他注意点(OSのバグを含む) A)StrIToA関数について 文字列操作の StrIToA(CharPtr s, Long i) のLong i には正の数字しか正しく変換されません。負の数字は正の数字に変換し、あとから符号を付ける必要があります。(PalmOS 2.0では直っていますがPilot1000/5000で正しく動かすためには気をつける必要があります。添付のcommon.cpのMyStrIToAという関数をお使いください。) B)実数(浮動小数点計算)について 実数はfloatやdoubleが使えずFloatTypeというPilot特有の型を使うことになるのですが、二つの数字の大小の判定の関数がなく、自分で関数をいろいろ書くはめになります。また文字列への変換(画面に数字を書かせるときは数字はあらかじめ文字列にしておく必要があります)がx.yyyyyyyezz という形しか準備されていないのも不便です。結局整数部をLongに変換するルーチンを使って整数部と小数部をそれぞれ求めて文字列に変換後くっつけるということになりますが、たとえば小数部を10000倍してLong変換して小数部を得る場合に小数部が切り上がる(=10000)ことがあるので注意が必要です。 Pilotの浮動小数点演算ルーチンにバグがあるのは有名な話ですが、詳細は調査中です。(思っていたほど致命的でないかも知れません。以前Pilotの電卓で1.1-0.1=0.1になるバグが浮動小数点演算ルーチンのバグによると言われていましたが、そうではなさそうな気がします。) C)PalmOS 2.0になって導入されたバグについて tFLDのフォントを変更するAPIであるFldSetFontは使わないでください。PalmPilotでFatal Errorを起こします。(tFLDであらかじめ指定しているフォントならエラーは起こらないのですが、フォントを変更しようとすると落ちます。J-Infoで起こったPalmPilot とのコンフリクトはこれが原因でした。)プログラムは世の中に(相当数)出回っているロムに対してはすべからく対応する必要があるため、全てのバージョンのOSが内包する全てのバグを回避する必要があります。 7:Pilotの汎用ルーチンを添付します(Common.cp)。使用上の制限はありません。ご自由にご利用ください。 金井克光(かない よしみつ)ykanai@m.u-tokyo.ac.jp P.S. もし間違っていたらご連絡ください。 このTIPSはFAQに(必要なら体裁を変更して)自由に転載していただいて結構です。その時は御連絡ください。