MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSA Developer News[MOSADeN=モサ伝]第102号

2004-02-24

目次

  • MOSA Developer News 100号記念プレゼント当選者発表
  • Cocoaでいこう! Macらしく  第39回  Yoshiki(DreamField)
  • 小池邦人の「Carbon API 徒然草」
  • 「Behind the WebObjects」  第14回  田畑 英和
  • ニュース・解説
  • MOSAからのお知らせ

  ★★ MOSA会員限定100号記念プレゼント抽選結果発表! ★★

 この度はWWDC 2003 Sessions DVD-ROMセットプレゼントへ沢山のご応募、誠に有り難うございました!
 2月19日に矢野会長立ち会いの元行われました厳正なる抽選の結果、DVD-ROMセットは横浜市の★★様・和光市の★★様のお二人に、そして以下の20名様がAppleCollection製品及びAppleTシャツに当選されました! ご本人には別途事務局より、当選のお知らせメールを差し上げます。

★★★ web掲載ではお名前は割愛します ★★★

今後ともモサ伝をご支援の程、よろしくお願い致します。

Cocoaでいこう! Macらしく  第39回 Yoshiki(DreamField)

 良くあるMacのアプリのパターンとして、補助的なウィンドウが開き、その中には現在アクティブになっているウィンドウに関する情報が表示されるというものがあります。今までは一つのドキュメントに対して一つのウィンドウを開くだけという構造になっていましたから、ウィンドウ間の連携は必要ありませんでした。ですが、この様なアプリはそうはいきません。今回から数回にかけて、この様なアプリの実装方法の一例を説明したいと思います。

パネルを表示しよう(その1)

 Cocoaの開発環境は、この順番に作らないと駄目、ということはあまりありません。そこで今回は一つの試みとして、思いつくままに実装していってみようと思います。
 まずは、どんな物を作るのか考えてみましょう。開いている画像の情報を表示する補助的なウィンドウを考えます。名前をInfoPanelとします。InfoPanelは、Editメニューの中のGet Infoを選ぶと開きます。InfoPanelはTinyViewに一つだけで、そこに表示されるのはアクティブなウィンドウの画像の情報であるとします。そして、アクティブなウィンドウを切り替えるたびに、InfoPanelの内容もそれに応じて変化します。良くあるパターンですね。それでは、順番に実装して行きましょう。

 補助的なウィンドウを表示するのですから、まずはこれを作ってしまいましょう。補助的なウィンドウはNSPanelを使うこととし、これをどのnibファイルに入れるのか考えます。画像の情報を表示するのですから、MyDocument.nibに入れれば、とても楽が出来るはずです。何故なら、File’s Ownerが画像を管理しているMyDocumentクラスのインスタンスですし、画像を表示しているウィンドウも含んでいますから、Interface Builderで直接コネクトして情報を得られるはずだからです。でも残念ながらこれは出来ません。何故なら、InfoPanelはアプリケーションに一つでないといけないのに、MyDocument.nibは画像を開くたびにロードされてしまうからです。
 それではMainMenu.nibはどうでしょうか。MainMenu.nibは最初に一度しかロードされませんから、これに入れることは可能です。でも、Cocoaのアプリでは、通常これは行いません。何故なら、MainMenu.nibに物を入れれば入れるほど起動が遅くなりますし、InfoPanelを使わない人にとっては、必要も無いのに余計なメモリを食ってしまうからです。通常、この様なオブジェクトは別のnibファイルに入れておき、必要になった時に初めてロードするようにします。

 では、InfoPanel用のnibファイルを作りましょう。最初にXcode(もしくはProject Builder)で、TinyViewのプロジェクトを開いておいて下さい。これは、Interface Builderで新規に作るnibファイルを、後で簡単にプロジェクトに加えられるようにするためです。
 次に、Interface Builderを起動してください。Starting Pointというパネルが開きますので、Emptyを選んでNewボタンを押します(fig.01)。すると、File’s OwnerとFirst Responderしか無いnibファイルウィンドウが開きます(fig.02)。パネルを作りましょう。パレットウィンドウからパネルを選んで、適当な所にドラッグ&ドロップして下さい(fig.03)。
 するとパネルのデザインウィンドウが開き、同時にnibファイルウィンドウにもパネルが現われます(fig04)。このままパネルの中身をデザインすることもできますが、それは後回しにして、まずは保存してしまいましょう。FileメニューからSaveを選んで下さい。ファイル名を入れるパネルが現れますので、InfoPanelという名前にします(fig.05)。
 Saveボタンを押すと、TinyViewプロジェクトに加えるかどうか聞いてきますので、TinyViewにチェックが入っているのを確認して、Addボタンを押してください(fig.06)。するとnibファイルがXcodeのプロジェクトに加えられます。おそらくResourcesの中に入っていませんので、ドラッグして入れて下さい(fig.07)。

[fig.01]新規nibファイルの雛形を選ぶ
http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig01.gif

[fig.02]Emptyなnibファイルウィンドウが現れる
http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig02.jpg

[fig.03]パレットウィンドウからパネルを取り出し配置する
http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig03.gif

[fig.04]パネルが生成される
http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig04.jpg

[fig.05]ファイル名をInfoPanelにしてnewボタンを押す
http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig05.jpg

[fig.06]TinyViewにチェックが入っていることを確認してAddボタンを押す
http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig06.jpg

[fig.07]XcodeにInfoPanel.nibが組み込まれる
http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig07.gif

 これでパネルのnibファイルは出来ました。続きは次回です。

小池邦人の「Carbon API 徒然草」(2004/02/22)

アプリ起動…我思う故に我あり

Carbonアプリケーションでは、起動時に実行しなければいけない「約束事」が随分と減りました。ToolBoxでおなじみの(もう、そんなの知らない人も多いかもしれませんが…)Macintoshの各マネージャの初期化を実行する必要はありません。よって、InitGraf()、InitFonts()、InitWindows()、InitMenus()、InitDialogs()といった初期化のためのAPIは使用不可となりました。再度、今回のサンプルアプリケーションのmain()ルーチンを見てみることにします。

int main( int argc, char* argv[] )
{
    long    ver;

    if( ! Gestalt( gestaltSystemVersion,&ver ) )
    {
        if( ver >= 0x1020L )
            startApplication();
        else
            doErrAlert( 1 );
    }
    return( 0 );
}


まず最初に開発者が考慮すべきことは、現在のシステム環境で本アプリケーションが使用可能かどうかを判断することです。アプリケーションの実行を左右する環境要因には、システム環境とアプリケーション固有の環境(リソース、プラグインモジュール、環境設定ファイルな)の2種類があります。自分で用意しているリソースやモジュールが不足している場合には、新規に作成したりインターネット経由で自動ダウンロードさせるなど、いくつかの解決方法が考えられます。しかし、システム環境が原因(OSのバージョンが古いなど)の場合には、アプリケーション側では手の打ちようがありませんので、エラーメッセージなどを表示し、そのまま終了することになります。

今回のmain()ルーチンでは、Gestalt() APIを利用して現在のMac OS Xのバージョンを調べ、それが10.2以上であれば起動可能と判断しstartApplication()へと処理を継続します。そうでない場合は、エラー表示ルーチンdoErrAlert()により「このアプリケーションはMac OS X 10.2以上でしか起動できません。」というエラーダイアログを表示しアプリケーションを終了させます。この環境チェック用API、何故かGestalt()と非常に「意味深」の名称がついていますが(笑)、これによりMacintoshシステムのあらゆる環境要因を調べることが可能です。

Gestalt()の最初の引数には、調べたい対象を指示するためのパラメータ(定数)を代入します。すると、次の引数にバージョン番号などの固有情報が返されます。こうしたパラメータはすべてGestalt.hに記載されています。もし判断しなければいけない環境要因があれば、それがちゃんとGestalt.hに定義されているかどうかを調べます。例えば、システムにQuickTimeがインストールされているかどうかは、以下のように調べることができます。Mac OS XはQuickTimeのインストールが必須ですので、存在しているかどうかを調べる必要はありませんが、バージョンにより機能の違いがありますので、処理を切り替えるためにバージョン番号を調べるケースは多々あります。

    if( ! Gestalt( gestaltQuickTime,&qt ) )
    {
        ver=qt>>16;
        if( ver < 0x600 )
        {
            doErrAlert( 1 );
            ExitToShell();
        }
    }


次の例では、MacintoshのCPUがAltivec(Velocity Engine)ユニットを搭載しているかどうかを調べています。現状だと、PowerPC G4とG5系のCPUを搭載したMacintoshが起動対象となります。ちなみに、ExitToShell()はアプリケーションを終了させるAPIです。

    if( ! Gestalt( gestaltPowerPCProcessorFeatures,&att ) )
    {
        chk=att&( 1<

搭載CPUの種類をより詳しく調べることも可能です。その場合には、G3やG4といった大ざっぱな識別ではなく、7450、7447、750FX、970など、CPUの型番を得ることができます。ちなみに、Gestalt.hには以下のような定義もなされていたりしますが、はてさて、これは何を意味するのでしょうか(笑)。

num {
  gestaltCPU486                 = 'i486',
  gestaltCPUPentium             = 'i586',
  gestaltCPUPentiumPro          = 'i5pr',
  gestaltCPUPentiumII           = 'i5ii',
  gestaltCPUX86                 = 'ixxx'
};

enum {
  gestaltX86VectorUnit          = 'x86v',
  gestaltX86VectorUnitNone      = 0,
  gestaltX86VectorUnitSSE2      = 4,
  gestaltX86VectorUnitSSE       = 3,
  gestaltX86VectorUnitMMX       = 2
};


しかし、状況によっては、環境の違いをGestalt()だけでは判断できない場合もあります。例えば、同じOSバージョンであってもFramework APIのバグフィックスの程度に差がある場合もあります。加えて、Gestalt()のパラメータの追加が間に合わない状況も考えられるでしょう。そうした場合には、各システムモジュールのバージョンを別途調べるなど、少々やっかいな処理が必要となります。以下が、Apple社が提示しているHIToolbox Frameworkの細かなバージョンの違いを調べるサンプルコードです。

CFBundleRef            bundle;
CFStringRefversion    Str = NULL;
UInt32                 version = 0;

bundle=CFBundleGetBundleWithIdentifier( CFSTR("com.apple.HIToolbox") );

if( bundle != NULL )
    versionStr = CFBundleGetValueForInfoDictionaryKey( bundle,
                                       CFSTR("CFBundleShortVersionString") );
if( versionStr != NULL && CFGetTypeID( versionStr ) == CFStringGetTypeID() )
{
    int     major = 0, minor = 0, bugfix = 0;
    char    sz[20];

    CFStringGetCString( versionStr, sz, sizeof( sz ), kCFStringEncodingUTF8 );
    sscanf( sz, "%d.%d.%d", &major, &minor, &bugfix );
    version = ( major << 8 ) + ( minor << 4 ) + bugfix;
}

if( version >= 0x100 )  // これは例で現状バージョンとは関係ありません。
    // おおっ、ちゃんとバグが取れたHIToolboxだぜ!
else
    // 残念、まだバグが取れていないHIToolboxだ(涙)

Framework APIのバグが取れるのは嬉しいのですが、そうしたことがあまりにも頻繁に行われると、その判別と処理の切り分けだけで大仕事になります。よって、せっかく新機能のAPIのバグが取れたのに、旧バージョンを考慮するとそれが使えず、相変わらず古いAPIでの処理を継続しなければいけないといった悲しい現実に遭遇したりします。やはりバグは最初から存在しないのが一番ですね(笑)。次回は、startApplication()ルーチンへと解説を進めたいと思います。

つづく

「Behind the WebObjects」  第14回  田畑 英和

 ここしばらくD2Wの解説が続いてきましたが、今回は話題を変えて以前少し紹介した日本語エンコーディングの扱いについて詳しく解説したいと思います。

 WebObjectsを用いたシステムでは通常、Webブラウザ、データベース、アプリケーション本体のそれぞれでどのようなエンコーディングを用いているかを考慮し、相互にデータをやり取りするときのエンコーディング変換処理を必要に応じておこなっていかなければなりません。
 まずアプリケーション本体からみていきましょう。WebObjectsではVer5.0以降からはJavaのみがサポートされていますので、プログラムはJavaで開発します。Javaですので文字列の表現はUnicodeが標準で用いられます。次にデータベースですが、サポートされるエンコーディング形式はデータベースによって異なります。最近では主要なデータベースであればUnicodeをサポートしており、それに加えEUCやSJISがサポートされていたりします。
 ここでアプリケーション本体とデータベース間でのエンコーディング変換が必要になってくるのですが、WebObjects5.0以降ではリレーショナルデータベースとの接続は標準でJDBCに統一されています。そしてアプリケーション本体とデータベースとの間でのエンコーディング変換処理はJDBC側で処理がおこなわれることになっていますので、アプリケーション側ではデータベース側のエンコーディングを意識する必要がなく自動的に適切な処理がおこなわれます。
※もちろんJDBC内で適切な処理がおこなわれている場合ですが。

 最後にブラウザ側ですが、例えばブラウザ側ではSJISでデータを扱うとなると以下のようなエンコーディング変換が必要になってきます。

    アプリケーション(Unicode) <-> ブラウザ(SJIS)

 具体的にどのような処理が必要かといいますと、まずブラウザから送信されるSJISのリクエストデータをアプリケーションが受け取ったときにUnicodeに変換する必要があります。またアプリケーションで生成したレスポンスデータをブラウザに送信するさいにSJISに変換する必要があります。このようなエンコーディング変換処理が必要になってきますが、この変換処理は明示的にコーディングして対応しなければなりません。

ではまずアプリケーションとブラウザ間のエンコーディング変換処理を説明する前に、WebObjectsにおけるリクエストの処理について説明しておきましょう。
 ハイパーリンクからのリクエストの場合はただ特定のURLを呼び出すだけですが、HTML Formが用いられた場合はブラウザからFormデータがリクエストデータとして送信されます。
 ブラウザから送信されたFormデータはあらかじめWebObjects Builderで設定しておいたバインドにしたがって適切な変数へとセットされます。ですので通常はリクエストデータのハンドリングを直接意識する必要はないのですが、それはWebObjectsのフレームワークが自動的に処理をおこなっていてくれるからです。このFormデータのハンドリングですが実際には次のメソッドで実行されています。

     public void takeValuesFromRequest(WORequest aRequest,
                                       WOContext aContext)

 このメソッドはWOApplication, WOSession, WOComponentの3つのクラスで実装されており、それぞれのインスタンスごとに実行され、引数のaRequestにはFormデータが含まれています。よってこのメソッドをオーバーライドすることにより、Formデータにアクセスできるようになります。
 以下のようにこのメソッドをオーバーライドすることでブラウザから送信されてきたFormデータを任意のエンコーディング(この場合はSJIS)からUnicodeへと変換することができます。Application.javaにこのメソッドをコーディングすることにより、すべてのFormデータの送信時に変換処理がおこなわれます。

     public void takeValuesFromRequest(WORequest aRequest,
                                       WOContext aContext){
         aRequest.setDefaultFormValueEncoding("SJIS");

         super.takeValuesFromRequest(aRequest, aContext);
     }

 これでブラウザ -> アプリケーションの変換は対応できました。後はアプリケーション -> ブラウザの対応になりますが、リクエストの生成処理は次のメソッドで実行され、このメソッドもWOApplication, WOSession, WOComponentの3つのクラスで実装されています。

     public void appendToResponse(WOResponse aResponse,
                                  WOContext aContext)


 引数aResponseがレスポンスデータなので、次のようにこのメソッドをオーバライドすることでレスポンスデータを任意のエンコーディング(この場合はSJIS)に変換することができます。また仕様上HTTPのヘッダーでContent-Typeによりエンコーディング名を指定する必要があるため、ここではWOResponseのsetHeader()メソッドを用いてContent-Typeの設定もおこなっています。これでブラウザに送信したレスポンスデータのエンコーディング名を知らせることができます。

     public void appendToResponse(WOResponse aResponse,
                                  WOContext aContext){
         aResponse.setContentEncoding("SJIS");

         super.appendToResponse(aResponse, aContext);

         aResponse.setHeader("text/html; charset=Shift_JIS",
                             "Content-Type");
     }


 上記の方法ではリクエストとレスポンスでそれぞれエンコーディング名の指定をおこないましたが、WOMessageクラス(WOResponseとWORequestのスーパークラス)のstaticメソッドを以下のように用いればリクエストとレスポンスのエンコーディング名を一括して指定することもできます。

     WOMessage.setDefaultEncoding("SJIS");

 このようなコーディングをおこなえばアプリケーション本体とブラウザ間のエンコーディング変換にも対応することができます。ただしこれだけでは対応しきれない場合もありますので、それは次回に解説したいと思います。
 なおWebObjectsのAPIで用いるエンコーディング名ですが、Javaで使用することのできるエンコーディング名をそのまま用いることができます。Javaのエンコーディング処理についてはJDKのバージョンによって異なる場合がありますので、詳しくはJavaでの日本語処理に関する文献などを参照していただければと思います。

ニュース・解説

 今週の解説担当:新居雅行

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃アップル、開発者向けのセミナーを日本で開催
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
アップルコンピュータは、「アップル デベロッパ ブリーフィング & QuickTime モバイル コンテンツ セミナー」として、開発者やQuickTimeコンテンツ制作者向けのセミナーを開催する。WWDCの日本版とまでは行かないとしても、Macの開発関連情報を国内で得る数少ない機会となる。
2004年3月11日(木)の13:00〜19:30に、東京国際フォーラムを使って行われ、参加費は無料だ。G5に最適化するためのラボやXcodeでの開発に移行するラボも開催されるので、開発中の案件を持ち込んでチェックあるいはアドバイスをもらうことも可能としている。開発ビジネスやテクノロジーのアップデート、コンテンツ関連のセッションなどが用意されている。

アップル デベロッパ ブリーフィング & QuickTime モバイル コンテンツ セミナー
http://www.apple.co.jp/hotnews/2004/0311devbrief.html

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃WWDC 2004の募集を開始
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
今年のWWDC(WorldWide Developers Conference)の募集が開始された。かねてよりのアナウンス通り、2004年6月28日から7月2日まで、サンフランシスコのモスコーニセンターで開催される。詳細なセッションについてはまだ公開されていないが、Application Technologies、Development Tools、Enterprise IT、Graphics and Media、Hardware Technologies、OS Foundations、QuickTime Digital Mediaといったカテゴリーで数多くのセッションが1週間にわたって開催される予定だ。なお、日本からのツアーについては現在はまだアナウンスはない。

WWDC 2004
http://developer.apple.com/wwdc/

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ファイルメーカーProの初級から実践までのセミナー
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
コンピュータワークスは、2004年の4月上旬に大阪でファイルメーカーProのセミナーを開催する。講師は鬼頭英嗣氏で、「エントリー編」は4月1〜2日、「リレーション編」は4月7日、「スクリプト編」は4月8〜9日に開催される。場所は大阪のEPSONスクエア御堂筋で、受講料はエントリー編とスクリプト編は41,000円、リレーション編は21,000円となっている。いずれのセミナーでも、ノートパソコンなどを持ち込んでの受講ができる。
また、2004年3月19日には、同じく大阪のEPSONスクエア御堂筋で、「ファイルメーカーPro実例・実践セミナー」を開催する。具体的な事例に則したデータベース構築を行うことで、実践的な技術を身につけようというものである。受講料は20,000円(過去に同社のセミナーを受講した人は17,000円)である。

コンピュータワークス
http://www.computerworks.co.jp/

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃NSViewからOpenGLのテクスチャを生成
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NSViewの表示結果をOpenGLのテクスチャとして利用する方法を解説した文書が公開された。ビットマップ化してテクスチャとして利用する方法であるが、サンプルプログラムが掲載されているので、それを手がかりにすることもできるだろう。

Technical Q&A: Creating an OpenGL texture from an NSView
http://developer.apple.com/qa/qa2001/qa1325.html

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃システムサウンドなどのサウンド関連文書が公開
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
警告音やユーザインタフェースでの効果音を出したいような場合に利用するAPIが紹介された文書が公開された。また、「サウンド」のシステム環境設定での警告音出力先とシステムサウンドの出力先の利用方法も解説されている。Mac OS X 10.3から利用できる機能も紹介されており、システムでのサウンド機能を改めてチェックしておく必要があるだろう。
また、Audio Unitのイベントについての文書も掲載されている。Core Audioを使ったプログラミングにおいて必要となる知識である。

Technical Note: The System Sound APIs for Mac OS X 10.2, 10.3 and later
http://developer.apple.com/technotes/tn2002/tn2102.html
Technical Note: Handling Audio Unit Events
http://developer.apple.com/technotes/tn2002/tn2104.html

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃Rendezvousに関する文書が公開
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Technical Q&AにRendezvousに関する文書がいくつか公開されている。サービスタイプ名といった仕様の部分や、あるいは機能の利用の仕方などがまとめられている。ソフト開発者はもちろん、ネットワーク機能を知りたい人も要チェックだろう。

QA1310 - Clearing the Rendezvous service cache
http://developer.apple.com/qa/qa2001/qa1310.html
QA1312 - Rendezvous service types used in Mac OS X
http://developer.apple.com/qa/qa2001/qa1312.html
QA1339 - The state of mDNSResponde
http://developer.apple.com/qa/qa2001/qa1339.html
QA1333 - Duplicate Rendezvous services while browsing
http://developer.apple.com/qa/qa2001/qa1333.html
QA1331 - Use empty string for Rendezvous domains
http://developer.apple.com/qa/qa2001/qa1331.html

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃Swingのルック&フィールを変更する方法
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mac OS Xで稼働させるSwingアプリケーションは、ルック&フィールにAquaを使うようになっている。その変更方法をまとめた文書が公開された。他のルック&フィールをデフォルトにしたい場合、コマンドラインからはシステムプロパティで指定する。アプリケーションではInfo.plistに設定を加える。また、Javaの設定そのものの変更方法も公開されており、稼働するすべてのSwingのルック&フィールを設定する方法も解説されている。

QA1059: Setting the look-and-feel for Swing applications
http://developer.apple.com/qa/qa2001/qa1059.html

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃Mac OS X Server 10.3でのスパム対策を解説
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
デベロッパ向けのドキュメントで、Mac OS X Server 10.3で、メールのスパム除去を行う方法が紹介されている。Mac OS X Serverでメールサーバを運用する場合、通常はPostfixをMTAとして利用する。さらに、オープンソースで開発されているスパム除去ツールのSpamAssassinを使い、procmailの処理をメールの受け取りにかませることで、送られてきたメールのスパム判断を組み込むことができる。コマンド等での処理が必要だが、手順を細かく説明しているので、スパム対策を施したい管理者にとっては有益な情報になるだろう。

Fighting Spam on Mac OS X Server
http://developer.apple.com/server/fighting_spam.html

MOSAからのお知らせと編集後記は割愛します

MOSA Developer News   略称[MOSADeN=モサ伝]
Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
このメールの再配信、および掲載された記事の無断転載を禁じます。
http://www.mosa.gr.jp/
Copyright (C)2004-2006 MOSA. All rights reserved.