Macintosh Developer Online (MDOnline)


2000年7月5日発行号 - METAL v1.6T



アメリカは夏休みに入り、また、独立記念日の休暇のようで、ほとんどニュースが出てこない状態ですね。火曜日が独立記念日だから、月曜も休みとしても、学校も夏休みなら、まとめてこの時期に休暇を取るって人もけっこういるのかもしれません。
あるページを見ていたら、「Webアクセスするだけで個人情報が漏えいする」ということをまことしやかに書いてありました。Webサーバを管理している人なら御存じのように、IPアドレスや、クライアントのドメインくらいはWebサーバでも分かります。まあ、クッキーやらを使っても経由してきたページやどこかで入力した内容は分からなくもないですが、そのページは、名前や住所までが分かってしまうような書き方をしていました。そりゃあ、レアケースとして、常時接続で、ファイル共有がアクティブで、ゲストでしたい放題ができる状態になっているのなら別です。だけどもそれは実社会で言えば、窓や入り口を全開にして長期のバケーションに行くようなものですから、普通はそんな状態になっていません。で、どうやら、ドメインが会社のものなら、そこから住所が分かるというようなことのようなのです。
まあ、それはそうなんですが、センセーショナルなタイトルで過剰に煽り立てるだけの文章でしかありません。目を引くためとは言え、困ったものです。世の中にはスポーツ新聞という独特のマスコミ形態がありますけど、あれはあれで、それこそプロレス的な面白さを、出す側も受ける側も了解の上で…ということがありますよね。でも、インターネットの裾野が広がるにつれて、不安がられせて喜ぶやからは、ある意味では愉快犯なんでしょうけど、ちょっと脅迫めいているというか、あやしげな壷でも買わされるのじゃないかと思ってしまうほどです。セキュリティの正確な知識が広がることを切に願います。知り合いの中にもクッキーは絶対にオフにするという人は何人も知っていますけど、クッキーで知られてしまう内容が漏えいされた場合のコストよりも、いちいち出てくる警告に対応する方が明らかにコストが高いと思うのですが、どうでしょうか。それに、ほんとうに危険なのは、Webよりもメールであることはあまり知られていません。簡単になりすますことができるのに…。
(新居雅行 msyk@mdonline.jp


METAL Basicがバージョンアップ、高速化やQuickTime対応など

Galactic Dreams Softwareより、フリーのBasicプログラミング環境、「METAL v1.6Turbo」がリリースされた。1月にVer.1.3がリリースされて以来のバージョンアップの模様だ。PowerPC向けの高速な実行速度を実現しているBasic言語の開発環境で、グラフィックスや算術演算、QuickTime、サウンド、スピーチ、スプライトなど豊富な機能を持つ。また、単独の実行ファイルを作成することも可能だ。科学的な調査会社での利用や、ソフトハウスでのプロトタイプ作成、あるいは教育機関での利用がなされていると紹介されている。METALのファンサイトも同社のページからリンクが張られており、ユーザも広がっている模様だ。新しいバージョンは実行速度が2倍になるほか、QuickTime対応などが行われている。

関連リンク:Galactic Dreams Software
カテゴリ:開発ツール


【Carbon化シリーズ】Navigation Serviceでファイル保存ダイアログ(3)

Navigation Servicesについて延々と対応方法を説明してきたが、今回で最後になる。何回もかかって説明しているだけに、いわば、それなりに大変なところでもある。APIを置き換えるだけでは済まなくなるというのが総括的なところとなるだろうか。今回は、名前を付けて保存、つまり、Save Asコマンドのときのファイル指定ダイアログボックスを組み込む。もちろん、前々回と同様に、NavPutFileを使うのであるが、TextDrawでは書類ファイルだけでなく、PICTファイルやテキストファイルへの保存もサポートしたい。つまり、保存フォーマットを選択するユーザインタフェースを付け、その選択結果に従って分岐処理をしたいというわけだ。ここでは、ポップアップメニューをカスタマイズすることと、ポップアップメニューの選択結果をダイアログボックスを閉じた後に取得する方法がポイントになる。

FileメニューのSave Asを選択して呼び出されるのが、DoCommand.cというソースファイルにあるDoSaveAsCommand関数だ。まずは、フォーマットを選択するポップアップメニューのカスタマイズの方法を追ってみよう。もちろん、NavPutFileが保存ダイアログボックスを表示するもので、詳細は前々回に説明しているためここでは違いだけを説明するが、3つ目の引数にNavDialogOptions型構造体で、ダイアログボックスの各種の設定を行う。この構造体のメンバであるpopupExtensionに、カスタマイズするメニュー項目を指定することになる。ただ、この指定がややこしい。具体的には構造体の配列を指定すると、その配列の1つ1つの要素がメニュー項目の1つ1つを指定することができる。メニュー項目の1つ1つを指定する構造体は、NavMenuItemSpecであるが、その構造体へのポインタ、ハンドルして、NavMenuItemSpecArrayPtrとNavMenuItemSpecArrayHandleという型が用意されている。Insde Carbonのドキュメントには間違いがあるので、正しい定義はNavigation.hヘッダファイルで確認するのが良いだろう。そして、構造体へのポインタは、構造体の配列へのポインタとも認識できるというC言語のもっともややこしいプログラムをここでしなければならない。おそらく、NavPutFileは、ハンドルの先にあるメモリ領域のサイズを見て、構造体がいくつ連続しているかを判断しているものと思われるが、ドキュメントにもその点についてはあいまいにしか書いていなかった。
DoSaveAsCommand関数の前半を見てもらおう。ここではポップアップメニューとして、3項目を用意したいので、まずはNewHandleを使って、NavMenuItemSpec構造体3つ分のメモリ領域を確保する。NavDialogOptions構造体のpopupExtensionメンバには、このハンドルを指定するのでよい。そして、ハンドルが指し示すメモリ領域に、メニュー名をセットするのだが、各構造体の中身は、versionメンバに規定の定義定数をセット、menuCreatorにクリエイタ情報(TextDrawではあまり意味はない)、nemuTypeにメニューを選択したときに得られる値、nemuItemNameにメニュー項目として実際に表示されるPascal文字列を指定する。ポインタと配列とが入り乱れ、正直なところちょっと苦労したが、示しているようなプログラムでとりあえずうまく動いた。3つの構造体のいずれにも必要な値を代入している。なお、何もしなくても、そのアプリケーションの書類を示す項目と、書類かひな形かを選択するダイアログボックスを表示するメニュー項目は自動的に追加される。このプログラムでは、前者は使うが後者は表示しないことにする。その場合には、NavDialogOptions構造体dialogOptionFlagsのあるビットを落とせばよい。そのために、kNavAllowStationeryという定数が用意されているので、-=演算子でビットを落としている。実際に表示されたダイアログボックスの、フォーマットのポップアップメニューを表示したところは次の通りだ。ポップアップメニューは合計4つの項目を持っている。

◇Save Asのダイアログボックスを表示したところ


では、実際にダイアログボックスで、フォーマットの選択のどの項目が選ばれているのかを検知する方法を説明しよう。NavReplyRecord構造体で分かる…なら話は早いのだが、それはできないようだ。この方法は、従来のStandard File Packageと同じような方法を取らないといけない。
ダイアログボックスでポップアップメニューを選択すると、Navgation Servicesベースのイベントが発生する。つまり、そのイベントを捕らえ、どのメニューが選ばれたかを得て、それを記録し、NavPutFileを実行後に残さないといけない。データを残す手段としては、もちろんNavPutFileの最後に指定するユーザデータを使う。ここではMyUserData2という構造体を定義して、選択された項目を記録するようにした。構造体もNewHandleで作り、初期値として、書類ファイルの形式を設定し、それをPutNavFileの引数として指定している。
Navigation Servicesからコールバックされるイベントプロシージャは、ここでは、myNavEventProc2関数として定義をした。以前から何度か紹介しているイベントプロシージャと同じようなものだ。ポップアップメニューが選択されたときには、イベントプロシージャの引数callBackSelecterの値が、定義定数のkNavCBPopupMenuSelectになる。case文でこの場合のプログラムを追加すればいいが、どのメニューが選択されたかがcallBackParam引数から得られるイベントレコードのwhenメンバに記録されている。ちょっとこれは分かりづらい仕様だ。通常、whenはイベント発生時刻を示すが、ポップアップメニューが選ばれた時には、NavMenuItemSpec構造体のmenyTypeというメンバに代入した値が、イベントプロシージャではイベントレコードのメンバwhenで得られるのである。その値を、ユーザデータの構造体にセットしておく。そうすれば、NavPutFileを終了後、ユーザデータの構造体を調べることで、選択したポップアップメニューの項目を知ることができるのである。

DoSaveAsCommandでは、NavPutFile実行後は、NavReplyRecordからダイアログボックスで指定したファイルとフォルダを取得し、ポップアップメニューで選択した項目に応じた処理を行っている。やはりカスタマイズを行うとプログラムはややこしくなると言えるだろう。

関連リンク:Inside Carbon: Navigation Services
カテゴリ:Carbon/CF, Carbon化


【Carbon化シリーズ】プログラム-myNavEventProc2, MyUserData2


《ソースファイル:DoCommand.c》

typedef struct MyUserData2 {
OSType selectedType;
} MyUserData2, *MyUserData2Ptr, **MyUserData2Handle;

void myNavEventProc2(
NavEventCallbackMessage callBackSelector,
NavCBRecPtr callBackParms,
NavCallBackUserData callBackUD)
{
EventRecord* thisEvent = ((callBackParms->eventData).eventDataParms).event;
//イベント情報を取得しておく
MyUserData2Handle userData = (MyUserData2Handle)callBackUD;
//ユーザデータを、コールバックルーチンで取り出す
switch (callBackSelector) { //イベントの種類に応じ
case kNavCBEvent: //一般的なイベントなら
switch (thisEvent->what) { //イベントの種類に応じ
case updateEvt: //アップデートイベントなら
break; //ここでは何もしないけど…
}
break;
case kNavCBPopupMenuSelect:
(**userData).selectedType = (*thisEvent).when;
//選択されたメニュー項目を記録する
break;
case kNavCBCancel: //キャンセルボタンが押されたなら
SysBeep(1); //システム警告音を鳴らす
break;
} //…という風にイベントごとの処理を記述する
}

カテゴリ:


【Carbon化シリーズ】プログラム-DoSaveAsCommand


《ソースファイル:DoCommand.c》

// File-Save Asを選択したとき(レコーディングには非対応)
void DoSaveAsCommand()
{
WindowPtr targetWindow;
DocRecHandle docH;

OSErr er;
AEDesc defLoc;
FSSpec defLocSpec;
NavReplyRecord reply;
NavDialogOptions dialogOptions;
NavMenuItemSpecArrayHandle extPMenu;
NavMenuItemSpecArrayPtr menuArrayPtr;
NavEventUPP neProc = NewNavEventProc(myNavEventProc2);
MyUserData2Handle popSelection;

popSelection = (MyUserData2Handle)NewHandle(sizeof(MyUserData));
(**popSelection).selectedType = myFileType;

if((targetWindow = FrontWindow()) != 0) { //アクティブなウインドウが存在する場合
docH = (DocRecHandle)GetWRefCon(targetWindow);
// FSMakeFSSpec((**docH).vRefNum, (**docH).parID , //保存ファイル名を整える
// (unsigned char*)(**docH).fileName, &savingFile);

NavGetDefaultDialogOptions(&dialogOptions); //ダイアログ設定は既定値
dialogOptions.dialogOptionFlags -= kNavAllowStationery; //既定のステーショナリ指定を表示しない
//ポップアップメニューの構造体を作成する
extPMenu = (NavMenuItemSpecArrayHandle)NewHandle( 3*sizeof(NavMenuItemSpec));
//構造体のメモリ領域を確保。ここが構造体の配列のようにふるまわせる
dialogOptions.popupExtension = extPMenu; //オプションに設定

menuArrayPtr = *extPMenu; //一連のメモリ領域を構造体の配列として認識させる
menuArrayPtr[0].version = kNavMenuItemSpecVersion; //1つめの構造体
menuArrayPtr[0].menuCreator = myCreator;
menuArrayPtr[0].menuType = ’TEXT’;
CopyString(menuArrayPtr[0].menuItemName, (unsigned char*)"\pテキストファイル");
menuArrayPtr[1].version = kNavMenuItemSpecVersion; //2つ目の構造体
menuArrayPtr[1].menuCreator = myCreator;
menuArrayPtr[1].menuType = ’PICT’;
CopyString(menuArrayPtr[1].menuItemName, (unsigned char*)"\pPICTファイル");
menuArrayPtr[2].version = kNavMenuItemSpecVersion; //3つ目の構造体
menuArrayPtr[2].menuCreator = myCreator;
menuArrayPtr[2].menuType = ’tdST’;
CopyString(menuArrayPtr[2].menuItemName, (unsigned char*)"\pステーショナリ");

CopyString(dialogOptions.savedFileName, (unsigned char*)(**docH).fileName);
//最初から設定されているファイル名を文字列で指定できる
er = FSMakeFSSpec((**docH).vRefNum, (**docH).parID, "\p", &defLocSpec);
//ファイルのあるフォルダのFSSpecを構築
er = AECreateDesc(typeFSS, &defLocSpec, sizeof(FSSpec), &defLoc);
//書類フォルダのAppleEventディスクリプタを生成

er = NavPutFile(&defLoc, &reply, &dialogOptions, neProc, myFileType, myCreator, popSelection);
//ファイル保存のダイアログボックスを表示
DisposeHandle((Handle)extPMenu);
if(er == noErr && reply.validRecord) { //ファイル選択が指定されれば
AEKeyword theKeyword;
DescType actualType;
Size actualSize;
FSSpec documentFSSpec;

er = AEGetNthPtr(&(reply.selection), 1, typeFSS, &theKeyword,
&actualType, &documentFSSpec, sizeof(FSSpec), &actualSize);
//指定したファイルの情報を取得する
switch((**popSelection).selectedType) { //保存するファイルのタイプに応じ
case myFileType: //TextDrawの書類ファイルの場合
SaveToFile(&documentFSSpec, targetWindow); //アクティブウインドウの内容を保存
(**docH).vRefNum = documentFSSpec.vRefNum; //DocRecordの更新
(**docH).parID = documentFSSpec.parID;
CopyString((**docH).fileName, documentFSSpec.name);
SetWTitle(targetWindow, documentFSSpec.name); //ウインドウタイトルを変更
(**docH).isDarty = 2;
case ’tdST’: //ステーショナリとして保存する場合
SaveToFile(&documentFSSpec, targetWindow); //アクティブウインドウの内容を保存
SetStatBit(&documentFSSpec);
break;
case ’PICT’: //PICTに保存するのなら
SaveToPict(&documentFSSpec, targetWindow);
break;
case ’TEXT’: //TEXTに保存するのなら
SaveToText(&documentFSSpec, targetWindow);
break;
}
}
}
DisposeHandle((Handle)popSelection);
}

カテゴリ: