MOSA Multi-OS Software Artists

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

プログラマーに興味がある方なら誰でも入会いただけます。
MOSA Multi-OS Software Artists
===SINCE 1995===

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

MOSADenバックナンバー 2007年4月発行分

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

    2007-04-24

    目次

    • 「りんご味Ruby」       第2回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #113
    • 高橋真人の「プログラミング指南」  第111回
    • 書籍紹介      入門UNIX for Mac OS X

    りんご味Ruby   第2回  藤本 尚邦

    前回の記事を読んで、RSSリーダプログラムをファイルに保存して実行したら

     

    /tmp/print_mosa_rss.rb:1: syntax error
     rss.items.each { |item| puts item.title }

    というエラーになった方はいらっしゃるでしょうか? すみませんでした。書き忘れていたことがあります。ポイントは

     「Rubyプログラムをファイルに保存するときは改行文字をLFにすべし!」

    これだけなのですが、記事の最後に少し詳しく説明を書き加えました。前回はまった方や気になる方はぜひお読みください。

    それでは本題に入りましょう。今回は、RSSリーダプログラムの最初の2行、ライブラリのロードについて説明しようと思います。

    ■ ライブラリのロード — requireメソッド

    今回は、RSSリーダプログラム

     require 'rss/2.0'
     require 'open-uri'
     url = 'http://www.mosa.gr.jp/?feed=rss2'
     rss = open(url) { |io| RSS::Parser.parse(io.read, false) }
     puts "-- #{rss.channel.title} (#{rss.items.size} entries) --"
     puts
     rss.items.each { |item| puts item.title }
    


    の最初の2行、添付ライブラリのロードについて説明します。

    RSSリーダプログラムでは、URLで指定されたRSSデータをネットワークからGETして、そのRSSデータを解析する必要がありますが、Ruby (1.8.1以降)にはこれらの目的に便利なライブラリがすでに添付されているので、それらをロードして使うことにします。

    添付ライブラリ、あるいは別途インストールしたライブラリをロードするときは、通常requireメソッドを使います。ロードしたいライブラリを表わす文字列を引数にしてrequireメソッドを呼び出すと、そのライブラリがロードされます。

     require ロードしたいライブラリを表わす文字列

    このRSSリーダでは

     'rss/2.0'  -- 「RSS 2.0パーサ」ライブラリを示す文字列リテラル
     'open-uri' -- 「HTTP/FTP高レベルAPI」ライブラリを示す文字列リテラル
    


    をrequireメソッド呼び出し時の引数として渡しています。

    requireメソッドは、指定されたライブラリをロードした場合には真(true)を、すでにロードされていた場合には偽(false)を返します。また、指定されたライブラリが見つからなかった場合には、LoadErrorという例外を発生させます。

     

    irb(main):001:0> require 'rss/2.0'
     true                                        # ロードした
     irb(main):002:0> require 'rss/2.0'
     false                                       # すでにロード済み
     irb(main):003:0> require 'vista'
     LoadError: No such file to load -- vista  # そんなライブラリはない!
             from (irb):3:in `require'
             from (irb):3
    

    ■ 添付ライブラリはどこに置いてあるの?

    Tigerに付属しているRuby 1.8.2など、バージョン 1.8.1 以降のRubyには、以前のバージョンと比較して多くのライブラリが添付されています。

    /usr/lib/ruby/1.8とそのサブディレクトリの中を見ると、`.rb’ や`.bundle’
    (Macの場合)という拡張子を持ったファイルがたくさんあるのですが、これらはみなRubyに添付されてきたライブラリです。`.rb’はRubyで書かれているライブラリで、`.bundle’ はCなどの言語で記述されコンパイルされた拡張ライブラリです。

    自分でインストールしたライブラリは、通常、/usr/lib/ruby/site_ruby以下のどこかに置かれます。また、rubygemsというネットワークベースのライブラリ管理システムを導入している場合(Leopardからは標準的に付いてくるかも。本連載でもいずれ取り上げたいと思います)には、rubygemsで管理されているライブラリは/usr/lib/ruby/gemsの下に置かれます。

    ところで、requireメソッドはどうやってロードするライブラリのファイルを探しているのでしょうか? これを説明するためには、グローバル変数$LOAD_PATH (Rubyでは名前の前に`$’がついているものがグローバル変数になります)について言及しなくてはなりません。requireメソッドは$LOAD_PATHに格納されているディレクトリパス名を順番に検索し、各ディレクトリの中から指定されたライブラリを探します。

    (グローバル変数を含め、Rubyにおける変数の意味、種類、オブジェクトとの関係については、いずれ詳しく説明するつもりです)

    ■ まとめ

    2回目にして、requireという地味でやや面白みにかけるメソッドについて説明してしまいました、うむむ。しかし、かなり使用頻度が高く、またプログラムの最初の方で使うことが多い重要なメソッドではあるので、まあ良しとさせてください。

    実は、今回の記事では、requireが構文ではなく「メソッドである」ことをさりげなく強調したつもりです。いわゆる伏線を張ったってやつです。張った伏線は忘れず活かしたいものですが果たしてどうなることやら...

    さて、今回の説明の中に

     irb(main):001:0> require 'rss/2.0'
     true                                        # ロードした
    


    というようなものがありましたが、このirbとは一体なんでしょうか?

    これはRubyに付属のコマンドirbを使って、対話的にRubyプログラムを入力・実行して結果を確認している様子です。このirbコマンド、私にとっては、これがあるからRubyが便利・楽しい・やめられないと言っても過言ではない、それくらい重要なコマンドです。

    次回は、このirbコマンド、および前回紹介したCocoaReplを使って、Rubyインタープリタと対話する方法について書こうと思います。

    ■ [補足] Rubyプログラムをファイルに保存するときは改行文字をLFにすべし!

    Macでは、テキストファイルの改行文字としてCR(0x0D)が使用されることがありますが、Rubyプログラムが解析(parse)されるとき、改行として扱われるのはUNIX系OSで一般的なLF(0x0A)のみで、CRは単なる空白文字の一種として扱われてしまいます。

    したがって、Rubyプログラムをファイルに保存するときには、改行文字をLF(もしくはWindowsで使われているCRLF)にする必要があります。Xcodeの場合は、形式メニューの行末コードでUNIX(LF)を選択しておくと、編集中のファイルを改行文字がLFで保存することができます。

    また、Rubyプログラムでは、セミコロン`;’だけではなく、改行文字LFにも「文(式)の区切り」という意味が含まれています。C,Java,Perlなどと異なり、行末にセミコロンを置かない(置く必要がない) のがRuby流のプログラミングなのですが、改行文字をCRにしている場合、それは行末として解釈されないため、意図した文(式)の区切りが抜けてしまい、RSSリーダにおいては前述したような文法エラーとなってしまうわけです。

    藤本裕之のプログラミング夜話 #113

     白状する。実はワタシ、前回のでシステムサービスについては全部書いた、もうおしまいで今回から違う話を始めるつもりでありました。ところがふと気がついてみると、「プロバイダー型」(#110で出てきた分類、覚えてますか?)についてはあれでいいが、サービスの結果としてなんらかのデータを返す「プロセッサー型」の場合のその「返し方」についてなんも説明してないではないか……と、#110を読み返して驚いた。これの記述、プロバイダー型とプロセッサー型が逆です。データを受け取りそれを元になんか処理して戻すのがプロセッサー型(単語の意味を考えりゃ当然だな)、そのデータを受け取ってアプリケーションがなんかやるだけ、戻さないのがプロバイダー型であります。おわびして訂正。

     で、そのプロバイダー……ぢゃなかったプロセッサー型の処理なんだが(どっちもプロナントカなのがいけないのだ)、実を言えば別にそんなに難しいことをしなくちゃならんわけぢゃないので、このまましらばっくれてスルーしちゃおうか、と0.68秒(アンドロイドには永遠の長さ)ほど考えた。が、その瞬間、脳裏にコイケさんが現れて「今年からMOSAは学生会員と研究室会員の会費を無料にしてもっと初心者や若い人に参加してもらう方針なんですよ」と言ったので、判ってるヒトには言わずもがなかも知れぬがそのプロセッサー型の場合にどうやって「プロセスしたデータ」をリクエスター・アプリケーショ
    ンに返すかを以下に示す。

    (void) processThisString:(NSPasteboard*) pboard
                   userData:(NSString*) userData
                       error:(NSString**)error ;

     これは前回作った(名前だけだけど)サービスを実行するメソッドの名前だけプロセッサー型風に変えたものである。前回のは確かsearchThisStringByYahoo とかいう名前だったので pboard から文字列を引っ張り出してそれをYahooで検索する処理を書けばOKだったんだが、今度は受け取った文字列を例えば……そうだな、逆さにしてみようか。 pboard から文字列タイプのデータを引っ張り出して逆さにする(なければエラーね)。

      

      if([[pboard types] containsObject:NSStringPboardType] != YES){
             *error = @"文字列が入ってねぇぢゃねぇかこのアンポンタン";
             return;
        }
        NSString* reverseThis = [pboard stringForType:NSStringPboardType];
        NSMutableString* reversed = [NSMutableString stringWithCapacity:0];
        int  cc = [reverseThis length];
        do{
             --cc;
             [reversed appendString:[reverseThis substringWithRange:
                                                     NSMakeRange(cc, 1)]];
        }while(cc > 0) ;
    
     あとはこれを ペーストボードにセットして戻るだけ。
    
        [pboard declareTypes:
             [NSArray arrayWithObject:NSStringPboardType] owner:nil];
        [pboard setString:reversed forType:NSStringPboardType];
        return;
    


     もちろん error にセットする文字列はできればローカライズ可能にしておくこと。上の例はサンプルならではの手抜きであります。

     最後になったけど、このサービスメニュー、プログラムから呼び出すことも可能(まぁそれがサービスメニューに存在することが前提だけどね)。方法も簡単で、呼び出すサービスの名前と受け渡すデータをセットしたペーストボードをパラメータにして、以下のファンクションをコールするだけ。

    BOOL NSPerformService(NSString* serviceItem, NSPasteboard* pboard);

     これ、NSAppとかのメソッドにあるかと思ったら Appkit にファンクションとして定義されているだけだった。アップルは「Leopard (10月に延期になってしまったねぇ)で追加される機能の多くはCocoaでしか提供しません」とかアナウンスしてるけど、その前にこういうコワザみたいなのをできるかぎりCocoaの体系の中に取り込んで欲しいもんである。
                                (2007_04_19)

    高橋真人のプログラミング指南  第111回

    プログラマのためのオブジェクト指向再入門(19)

    〜XcodeによるPowerPlant X入門(3)〜

     こんにちは。高橋真人です。
     今回は、前回のコードの簡単な説明をします。今回のプログラムはコード自体も極めて単純ですが、これだけで一応れっきとしたCarbonアプリケーションが動くのですから、当然内部では「それなりのこと」をやっているわけです。
     短いですので再掲します。

    #include <PPxApplication.h>
    
    int main()
    {
        PPx::Application app;
        app.Run();
    
        return 0;
    }
    
     まず、PPxApplicationとい

    うヘッダをincludeしていますが、ここでPPxのヘッダについてちょっと予備知識を。
     PPxでは、前にもお話ししたようにCarbonイベントの仕組みをかなり利用した形でフレームワークを形成しています。そのため、フレームワークを構成するクラスには大きく分けて二つの種類があるのです。
     まず、システムが標準で持っているものに関しては、”Sys”というプレフィックス(頭辞子=先頭に付く識別子)が付きます。例えばCFStringというCoreFoundationの“型”がありますが、通常のC/C++のプログラムでこれを利用する場合は、

    #include <CoreFoundation/CoreFoundation.h>

    と、他のCoreFoundationの“型”をひっくるめて、まとめて取り込んでしまう
    方法もありますが、個別に取り込む場合には、

    #include <CoreFoundation/CFString.h>

    なんてやるわけです。
     で、PPxにおけるCFStringはこれをくるんだラッパクラスが用意されていて、CFStringを直接呼び出して使うよりは多少メモリ管理などがラクになっているのですが、これを利用するために取り込むヘッダファイルは、SysCFString.hという名前です。
     勘違いしそうなのですが、このSysというのはヘッダの名前の先頭に付くプレフィックスなのであって、決して名前空間の名ではないということです。CFStringのラッパクラスも、PPxにおいてはやはりPPxという名前空間に属していますので、お間違えなく。
     つまり、システムが標準で提供しているクラス(というか、型なのですが)をラッピングしたクラスはSysというプレフィックスが付き、それ以外のもの、つまりPPxが独自に提供しているクラス群についてはPPxというプレフィックスが付くということです。
     繰り返しますが、あくまでヘッダの名前の話であって、名前空間ではありません。PPxにおける名前空間は、基本的にすべてがPPxです。

     さて話は戻りますが、ヘッダの取り込みが終了すれば、あとは単にmain()だけのプログラムで、main関数の中身でやっていることは、アプリケーションクラスのオブジェクトを一つ作って、それを走らせているだけです。
     ApplicationクラスのRun()というインスタンス関数は、Carbonイベントでおなじみのメインのイベントループを走らせるための関数であるRunApplicationEventLoop()を呼び出しているだけです。
     さて、今回の冒頭で「内部ではそれなりのことをやっている」と言いましたが、Carbonを多少ご存知の方であれば、単にプログラムの中でRunApplicationEventLoop()を呼び出すだけで今回と同じアプリケーションが動作することはご存知でしょう。実は、「それなり」の中身は実質的にこの関数を呼んでいるのとほぼ同等です。
     もっとも、本当にそれだけだったら面白くも何ともありません。あえてアプリケーションのために専用のクラスを用意するのには、もちろんですが理由があります。そのためにはこれを拡張していかないと始まりませんので、早速次のステップに進みましょう。

     今度は、メニューもウインドウもあるアプリケーションに挑戦します。
     前回のものを流用して作業をしますので、まずは、FinderでPPxForXcode01フォルダを複製し、名前をPPxForXcode02とします。このフォルダを開き、

    PPxForXcode01.xcodeproj
    PPxForXcode01_Prefix.pch
    PPxForXcode01Proj.xcconfig
    PPxForXcode01Target.xcconfig
    


    の01をすべて02に変更したいのですが、この作業をFinder上で行ってしまうと、プロジェクトがこれらのファイルを見失ってしまうので、Finderで名前を変更するのは.xcodeprojだけにします。念のため、ついでにbuildフォルダをゴミ箱に捨てておきましょう。
     次にプロジェクトファイルを開き、残りのファイルの名前を変更していきます。
     やり方ですが、プロジェクトウインドウ内でファイルを選択し、ツールバーの「情報」ボタンをクリックして、表示されたダイアログで、「一般」タブが選択された状態であれば、ファイル名の変更ができるはずです。
     ついでに、他にもいくつか「01→02」の変更作業を行います。
     まず、「ターゲットグループ」(前回参照)の左端の三角をクリックして開き、ターゲット名を変更します。(やり方は上記と同様)
     ターゲットの情報ウインドウを閉じる前に、ついでにプロパティタブに切り替え、「識別子」のところも変更します。
     あともう一つ、これは重要ですが、上記で名前を変更してあったPPxForXcode02Target.xcconfigをダブルクリックで開き、2行目の

    GCC_PREFIX_HEADER = PPxForXcode01_Prefix.pch;

    の01のところも02に変更しておきます。

     以上でプロジェクトの複製作業は完了です。次回はこれを元に新たに機能を組み込んでいくところをご説明します。

    書籍紹介                  入門UNIX for Mac OS X

     解説担当:高橋政明

    入門 Unix for Mac OS X 第4版
      Dave Taylor 著
      酒井 皇治 訳
      オライリー・ジャパン ISBN 4-87311-274-5  2,625円

     虎の表紙でTiger(Mac OS X 10.4)対応とわかるUNIXの入門書です。原著はLearning Unix for Mac OS X Tigerです。
     モサ伝読者諸氏にはUNIXの入門書など不要の方も多いことでしょう。ただ必要に迫られてターミナル.appは使うけれどUNIXにあまりなじみがなければ(あるいはコマンドライン操作にアレルギーがあれば)このような入門書を一冊手元に置くのも良いかも知れません。

     本書のまえがきにあるように、この本はMacintoshユーザーのために書かれています。(ですので開発者向けの情報には期待しないでください)
     この本が読者にとって必要かどうかは出版社のwebに目次がありますのでご自身で確認してください。

     Macintoshユーザーのために書かれて内容も現在のところ最新ですので、これからUNIXを学ぶ方にはおすすめです。コラムや注釈にMac独自の部分に対する解説もあります。

    ▼出版社のweb(詳しい目次と正誤表があります)
    http://www.oreilly.co.jp/books/4873112745/

    ▼原著のweb(目次・索引・サンプル本文を確認できます)
    http://www.oreilly.com/catalog/ltigerunix/index.html

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

       

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

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

    2007-04-17 

    目次

    • 「「Wonderful Server Life」    第45回    田畑 英和
    • 小池邦人の「Carbon API 徒然草」
    • SqueakではじめるSmalltalk入門  最終回    鷲見 正人
    • 書籍紹介Ship It!ソフトウェアプロジェクト成功のための達人式ガイドブック

    「Wonderful Server Life」  第45回  田畑 英和
      〜アカウント編〜

     Mac Proのラインナップに8コアが追加されました。8コアの内訳ですが、4コアのCPUが2基搭載されています。オンラインのAppleStoreでは、8コアの構成を選択できますが、クロックは3.0GHzのみとなっています。
     今のところXserveに動きはありませんが、はたして1Uの筐体にも8コア時代がやってくるのでしょうか?

    ◇グループフォルダ
     さて、前回に引き続きグループアカウントを説明していきたいと思います。前回は複数のユーザ(あるいはグループ)をグループとして管理できることを説明しました。今回はグループアカウントの機能である、グループフォルダについて説明します。
     各ユーザにホームフォルダが設定できるように、グループにもグループ専用のフォルダを設定することができます。このグループ専用のフォルダのことをグループフォルダと呼んでおり、グループ間でのファイルの共有などに利用することができます。

     グループフォルダの設定方法ですが、「ワークグループマネージャ」を使って設定します。ツールバーから「アカウント」を選択し、左側のリストからグループフォルダを設定したいグループを選択します。次に、右側の画面で「グループフォルダ」ボタンをクリックし、ここでグループフォルダのパスを設定します。
     「グループフォルダ」設定画面にはユーザの「ホーム」設定画面と同様に、あらかじめネットワークマウントの設定をしておいたパスが自動的に表示されます。つまり、グループフォルダはユーザのネットワークホームと同じように設定することになります。また、環境設定をおこなえばグループフォルダを自動的にクライアント上にマウントさせることもできます。
     Mac OS X Serverには起動ボリュームの直下にあらかじめ「グループ」フォルダが用意されていますので、グループフォルダのパスとしては、こちらを利用するのがよいでしょう。

    ・グループフォルダのパスの設定
    http://homepage.mac.com/htabata/MXS10.3/img/WGM_Group/WGM_Group_03.png

     ホームフォルダのオーナーは、自動的にホームフォルダのユーザがオーナーとして設定されますが、グループフォルダのオーナーは自動的には設定されません。
     そこで、グループフォルダのパスを設定した次に、グループフォルダのオーナーを設定します。「グループフォルダ」設定画面の下に、オーナーを設定するための「オーナー名」の入力フィールドがあります。
     直接オーナーのユーザ名を直接入力することもできますが、タイプミスを防ぐために「…」ボタンからユーザリストを表示し、リストからドラッグ&ドロップして設定するのがよいでしょう。

    ◇グループフォルダの作成
     ユーザのホームフォルダは「ワークグループマネージャ」から作成することができますが、グループフォルダの場合GUI上でこれを作成する方法がありません。そのためグループフォルダの作成はコマンドライン上で実行する必要があります。グループフォルダを作成するコマンドを、ユーザのホームフォルダを作成するコマンドと併せて紹介しておきます。

    ・ユーザのホームフォルダの作成コマンド
       createhomedir
    ・グループフォルダの作成コマンド
       CreateGroupFolder

     CreateGroupFolderコマンドはroot権限で実行する必要があります。コマンドを実行すると、グループフォルダのパスに指定したフォルダ内に、グループの「名前」をフォルダ名とするグループフォルダが作成されます。
     グループフォルダ内には自動的に「Documents」「Library」「Public」の3つのサブフォルダが作成され、それぞれのサブフォルダのオーナーおよびアクセス権はデフォルトで次のようになります。

    ・「Documents」フォルダ
    オーナー:example
    グループ:sample
    アクセス権:rwxr-x—
    ・「Library」フォルダ
    オーナー:example
    グループ:sample
    アクセス権:rwxr-x—
    ・「Public」フォルダ
    オーナー:example
    グループ:sample
    アクセス権:rwxrwxr-x

     「Documents」と「Library」フォルダには、デフォルトでグループの書き込み権がありません。
     グループフォルダのフォルダ名は、デフォルトではグループの「名前」が使用されますが、これをカスタマイズすることもできます。グループフォルダのパスを複製し、「パス」を変更すればグループフォルダの名前を変更することができます。

    ・グループフォルダの「パス」の変更
    http://homepage.mac.com/htabata/MXS10.3/img/WGM_Group/WGM_Group_04.png

     それでは次回はコンピュータアカウントについて説明します。

    つづく                               

    小池邦人のCarbon API 徒然草(2007/04/13)

    〜 Carbonモダンアプリケーションへの道(その14) 〜

    今回からCarbonのファイルシステムについて解説します。こちらもテキストやグラフィックスに負けず劣らず、時代と共に変貌してきた経緯があります。はたしてファイルシステムは、どの程度モダン化されたのでしょうか?

    ファイルシステムの話を始める前に、前回解説した印刷関連の内容に訂正があります。前回「CFArrayCreate()とPMSessionSetDocumentFormatGeneration()の手続きを加えないとCoreGraphics APIでの描画が印刷に反映されない」「Mac OS X 10.5では修正して欲しい」と書いたのですが、MOSAメンバの方からご連絡が有り、この「呪文」は、すでにMac OS 10.4で解消されていることが判明しました(笑)。ご連絡、有り難うございました。

    具体的には、前回最後のサンプルの「呪文的」手続き箇所とPMSessionBeginDocument()をPMSessionBeginCGDocument()に置き換え、引き続
    いてPMSessionGetGraphicsContext()をPMSessionGetCGGraphicsContext( )に
    置き換えればOKとなります。すべてを正しく書き直すと以下の様になります。大変すっきりしましたね。ちなみに、両APIはヘッダファイルのPMApplication.hに定義されています。

    OSErr startPrint( WindowRef window,PMPrintSession pss,
                                         PMPrintSettings set,PMPageFormat form )
    {
       unsigned long   i,st,ed;
       short           err=1;
       CFStringRef     cfstr;
       CGContextRef    ctx;
    
       CopyWindowTitleAsCFString( window,&cfstr ); // ウィンドウタイトルを得る
       PMSetJobNameCFString( set,cfstr );          // 印刷ジョブ名を設定
       CFRelease( cfstr );
    
       PMGetFirstPage( set,&st );                  // 開始ページ番号
       PMGetLastPage( set,&ed );                   // 開終了ページ番号
       if( ! PMSessionBeginCGDocument( pss,set,form ) ) // ドキュメント印刷開始
       {
          for( i=st;i<=ed;i++ )
          {
              if( ! PMSessionBeginPage( pss,form,NULL ) ) // 指定ページ印刷開始
              {
                  PMSessionGetCGGraphicsContext( pss,&ctx ); // CGContextRefを得る
    
               // ここでHIThemeDrawTextBox()などによるテキスト描画を行う
    
                  err=noErr;
                  PMSessionEndPage( pss );   // 指定ページ印刷終了
               }
               if( err )
                   break;
           }
           PMSessionEndDocument( pss );       // ドキュメント印刷終了
       }
       return( err );
    }
    


    ただし、PMSessionBeginCGDocument()とPMSessionGetCGGraphicsContext()
    は、Mac OS X 10.4以降でしか使用できませんので、Mac OS X 10.3も動作環境対象となっているアプリケーションでは、前回のソースコードを使うしか手はありません。御注意ください。また試した結果、SetPortTextFont()やSetPortTextSize()など、CGrafPortの参照が必要な描画関連APIは、引数のCGrafPtrにNULLを渡せば正常に動作するようです。

    ところで、PMSessionGetCGGraphicsContext()でCGContextRefを得てCoreGraphics APIで描画を行う場合、用紙矩形領域の左下が原点(PostScript同等)となります。通常プリンタの印刷可能形領域は用紙矩形領域よりも狭いですので、原点付近に描画した文字や画像は途切れてしまう可能性があり、注意が必要です。

    これとは異なり、QuickDraw環境では用紙矩形領域ではなく印刷可能領域の左上が原点となります。用紙矩形領域をPMGetAdjustedPageRect()で得て、その矩形を考慮して描画すれば、ちゃんと用紙内に印刷結果を納めることができます。CoreGraphics環境では、描画する前に、用紙矩形領域の原点まで座標系を平行移動させておくと便利かもしれません。

    話をファイルシステムに戻しましょう。ファイルシステムを考える上で、まず最初に確認しておくべきことは、ファイルを参照するための「リファレンス」に何を使うかと言う事です。Mac OS 9の時代であればFSSpec構造体(今でも使えるが...)がそれに相当していましたが、現在ではFSRef構造体を使うことが強く推奨されています。

    ヘッダファイルのFiles.hを参照すると、FSSpec構造体は以下の様な構造体メンバを持っていることが分かります。

    struct FSSpec {
     short               vRefNum; // ボリュームリファレンス番号
     long                parID;   // ディレクトリ番号
     StrFileName         name;    // ファイル名
    };
    


    このうちStrFileNameはStr63と同一で、具体的にはStr63[64]と定義されていますから、ファイル名は63バイト以内でしか管理できません。またファイル名のエンコーディングはShift-JISに固定されておりユニコード文字列の扱いも不可です。続いて、FSRef構造体の方を調べてみると、以下のように定義されています。

    struct FSRef {
     UInt8               hidden[80];  // 中身がどう使われるかは謎?
    };
    


    構造体サイズが80バイトであることは理解できますが、その中身がどのように利用されているのかはオープンにされていません。

    現在、FSSpec構造体を引数で渡すファイルアクセス関連APIは、すべてDEPRECATED指定となっています。例えば、ファイル作成に使うFSpCreate()や削除に使うFSpDelete()などもそのうちの一つです。ただし、古いアプリケーションの特定の便宜を図るために、FSSpec構造体をFSRef構造体へコンバートするFSpMakeFSRef()などの一部のAPIは、DEPRECATED指定にはなっておらず、そのまま継続して使用することが可能です。

    extern OSErr  FSpMakeFSRef(const FSSpec *source, FSRef *newRef)

    File.hに定義されているファイルシステム関連のAPIでなくても、FSSpec構造体でファイルを参照するAPIはDEPRECATED指定のものが多いので注意してください。そうしたAPIについては、FSRefで参照する代用APIが必ず存在しています。例えば、Folder.hにはシステムで管理しているフォルダを探し出すAPIが定義されていますが、一昔前にはFindFolder()を利用していました。

    OSErr FindFolder(
     short     vRefNum,       // ボリュームリファレンス番号
     OSType    folderType,    // フォルダの種類
     Boolean   createFolder,  // 無い場合に作成するかどうか
     short *   foundVRefNum,  // 得られたフォルダのボリュームリファレンス番号
     long *    foundDirID);   // 得られたフォルダのディレクトリ番号

    このAPI、FSSpec構造体を渡す必要はないのでDEPRECATED指定にはならず生き残っていますが、代わりとしてFSRef対応のFSFindFolder()というAPIがちゃんと存在しています。

    OSErr FSFindFolder(
     short     vRefNum,       // ボリュームリファレンス番号
     OSType    folderType,    // フォルダの種類
     Boolean   createFolder,  // 無い場合に作成するかどうか
     FSRef *   foundRef)      // 得られたフォルダのFSRef
    


    例えば、システム起動ボリュームにあるデスクトップフォルダのFSRefを得たい場合には、以下のように記述してやればOKです。

    FSRef fsref;
    
    FSFindFolder( kOnSystemDisk,kDesktopFolderType,kCreateFolder,&fsref );
    


    CoreFoundation中には、特定のファイルやフォルダを参照するために、FSRefではなくてCFURLRefを用いるAPIがあります。例えば、アプリケーションバンドルのResourcesフォルダ内にアクセスするためにはCFBundleCopyResourceURL()を利用しますが、このAPIはファイル参照用としてCFURLRefを返してきます。しかし、CFURLRefのままだとファイルアクセスが面倒ですので、CFURLRefをFSRefに変換するCFURLGetFSRef()というAPIがCFBundle.hに用意されています。CFStringRefで名称を指定したResourcesフォルダ内ファイルのFSRefを得るには、以下の様に処理します。

       CFStringRef  cfstr;  //ファイル名を代入する
       short        err=1;
       CFURLRef     url;
    
       if( url=CFBundleCopyResourceURL( CFBundleGetMainBundle(),cfstr,NULL,NULL ) )
       {
           if( CFURLGetFSRef( url,fsref )==true ) // CFURLRefをFSRefに変換
               err=noErr;
           CFRelease( url );
       }
       CFRelease( cfstr );
    


    次回は、FSRefで参照したファイルやフォルダ(ディレクトリ)への基本的なアクセス(作成、書き込み、読み込み、削除など)について調べてみたいと思います。
    つづく
                                    

    SqueakではじめるSmalltalk入門   最終回  鷲見 正人

    前回はSmalltalkファンお手製の、OS Xで動くフリーのSmalltalk処理系をご紹介しました。今回は、一連のSmalltalk処理系のご紹介の締めくくりとして、Squeakの前身であるApple Smalltalkを取り上げます。

    ▼Apple Smalltalkとは

    「Apple Smalltalk」は、もともと、Smalltalkシステムの売り込みに熱心だったXEROXからの技術供与と動作確認用の(純正の)仮想イメージの提供を受けて、AppleがLisa向けに開発したSmalltalk処理系です。のちにMacintoshにも移植され、旧APDA(the Apple Programmers and Developers Association)を通じて比較的安価に販売されました。残念ながら、現在は入手がたいへん困難となっていますが、1990年前半くらいまでは販売されていたので、ベテランMac開発者の皆さんの中にはインストールディスクやインストール後のフォルダを記念にとってあるよ!という方もおられるかもしれませんね。

    Apple Smalltalkは非常に古いソフトですが、「Mini vMac」というMacintoshPlusエミュレータを使えば、OS Xでも制限付きながら(環境内でのファイルのアクセスに失敗する…)も、かろうじて動作させることは可能です。なおその際には、Apple Smalltalkとエミュレータソフトの他に、Macintosh PlusのROMイメージと古いMacintosh System(6.0.x未満)が必要になります。

    http://minivmac.sourceforge.net/

    [fig.A]Mini vMacで動作しているApple Smalltalk

    ▼オリジナルMacのGUIの“ルーツ”としてのSmalltalk GUIを試す

    エミュレータを動作させるために使う“古い”Mac用のシステムと、起動したApple Smalltalkとの比較で一目瞭然ですが、左上を指し示す矢印のポインタ、グレイ(細かな市松模様)のデスクトップ、白地に黒の文字表示など…に象徴されるように、両者はたいへんよく似かよった部分を持っています。知らない人が見たら、SmalltalkとやらはMacのソフトっぽく見えるように、実にうまくしつらえられているのだな…と本来とは逆のことを考えてしまうかもしれませんね。

    [fig.B]両者間で似た部分のあるGUI要素

    当時のSmalltalkのウインドウは、見た目がとてもシンプルであったり、スクロールバーがポップアップでしかも左側に付いていたり…と、いっけんLisaやMacのGUIとはずいぶんと違った印象ではありますが、しかし、作業場としてのウインドウが持つべき要素(オーバーラップ、タイトル表示、移動、サイズ変更、スクロール機能…)は、実はまぎれもなく、このSmalltalkのGUIが元になってそれが広まって定着したものです。たとえば、第三ボタンメニュー(Apple Smalltalkではコマンドクリック、あるいはタイトルバーをクリックしてポップアップ)の項目やスクロールバー操作は、次のように対応付けできます。

    第三ボタンメニューの項目 → Lisa、Macのウインドウ操作
    ---------------------------------------------------------
    move           → タイトルバーの移動
    frame           → サイズボックスのドラッグ
    collapse         → (後の)ウインドウシェード機能
    close           → クロースボタンのクリック

    スクロールパネルの操作  → Lisa、Macのスクロールバー操作
    -------------------------------------------------------------
    ボックスのドラッグ    → 同じ
    ボックス左側のクリック  → 上矢印ボタン(上方向スクロール)
    ボックス右側のクリック  → 下矢印ボタン(下方向スクロール)

    また、マルチフォントやカット&ペーストに象徴されるモードレスな文書編集スタイルについても、Smalltalkが手本になっています。前述のウインドウの場合と違って、当時としては珍しい個性的なテキスト操作スタイルのほうは、ほぼそのままLisaやMac(ひいてはWin…)に受け継がれています。したがって、Macに慣れた皆さんは、ほとんど説明無しで、この1970年代に培われたGUI上でのテキスト編集機能をさほど違和感を感じずに使いこなせるはずです。ただしメニューバーはないので、第二ボタンメニュー(Apple Smalltalkではoptionクリックか、スクロールバー右端領域をクリック)を用いる必要があります。

    [fig.C]両システムで酷似しているテキストの編集スタイル

    他方で、後にAppleによって発明されることになる“新機能”が欠けていることにも気づかれることと思います。横方向のスクロールバー(あるいは、サイズボックスを含むスクロールバーの再配置のアイデア)、前述のメニューバーや(ポップアップではない…)プルダウンメニュー、さらには、Smalltalkでは必要とされなかった「Finder」(Smalltalkではファイルを読み込んで実行したり文書をファイルとして保存するのではなく、すべてをオブジェクトとして仮想デバイスに押し込めるスタイルのため…)や、「計算機」(Smalltalkではたとえワープロの文書中であってもSmalltalk式をprint itできるため…)といった機能やソフトウエアたち。これらは、Apple Smalltalkには見ら
    れません。

    [fig.D] Smalltalkの“print it” vs. Macの“計算機”

    以上のようにApple Smalltalkは、たんに古いSmalltalk処理系のひとつというだけでなく、我らがMacのGUIが「どこから来たのか?」といったことに思いを馳せたり、Appleが何をそこにどのように付け足したのか?を再確認する目的でも、たいへん興味深いソフトだと思います。相応の知識を持っていれば、1979年にPARCを訪れ、ALTO上のSmalltalk GUIを見て驚いたスティーブ・ジョブズよろしく、「こんなものが1970年代半ばにすでに出来上がっていたとは!」と感動すること請け合いです。

    ▼Squeakの“前身”としてのApple Smalltalkと、Squeakの“今”

    Squeakは、このApple Smalltalkから、移植の妨げになるMacintosh ToolboxやMC68000依存部分を排除しするために、Smalltalkで仮想マシンの主要部分を記述して新しい仮想マシンを作り、その仮想マシン上で古い仮想イメージ(Smalltalk自身で書かれたSmalltalkシステム本体)を拡張する…というサイクルを経て作られました。まるで不死鳥が自らの身を焼いて、新しく生まれ変わるかのようなエピソードですね。

    もちろんApple Smalltalk内で動作するSmalltalkで記述された仮想マシンは、動作確認やデバッグ程度のことは可能ですが実用(仮想イメージ開発)には向かないので、それをいったんC言語に変換して、必要なリソースを追加してMacintosh用開発ツールでビルドする…という作業も必要でした。この変換作業には、アラン・ケイたちがPARC時代、C言語の前身のBCPLにSmalltalkを変換するソフトを(やはりSmalltalkで)書いたときのノウハウが活かされていたのだそうです。

    Squeakは、そうして、高い移植性を自らの特徴とし(実際、Mac以外の数多くのプラットフォームに移植されました)、同時に、ALTOやLisa、初期のMac時代には望めなかったカラー表示や広大なメモリ空間への対応を果たします。さらに、本来の目的であった子供向けのビジュアルプログラミング環境「eToys」をはじめ、仮想三次元空間の共有機能を提供する「Croquet」、Rubyon Railsの対抗馬(?)で継続ベースのWebアプリ「Seaside」、CocoaのKVOライクな機構を有する次世代GUIフレームワーク「Tweak」など、さまざまな新旧の技術を取り込みつつ、今も多様な進化を遂げているところです。

    * eToys
    http://squeakland.jp/school/drive_a_car/html/Drivecar12.html

    * Croquet
    http://www.croquetconsortium.org/index.php/Screenshots

    * Seaside
    http://www.seaside.st/

    * Tweak
    http://tweakproject.org/TECHNOLOGY/Tutorials/BankAccountTutorial/

    さて。突然ですが今回をもって本連載はおしまいとさせていただきます。皆さんが、様々な意味でMacとは切っても切れない関係にあるSmalltalkに興味を持たれた際に、本連載での情報が何かしらの役に立つことがあれば幸いに思います。長い間、ありがごうございました。

    バックナンバー:
    http://squab.no-ip.com:8080/mosaren/

    書籍紹介   Ship It! ソフトウェアプロジェクト成功のための達人式ガイドブック

     解説担当:高橋政明

    Ship It! ソフトウェアプロジェクト成功のための達人式ガイドブック
    Jared Richardson・William Gwaltney Jr. 共著でびあんぐる 監訳
    オーム社 ISBN 4-274-06656-8 2,730円(本体2,600円+税)

     今回ご紹介するのは昨年発売された長い書名の本です。「レガシーコードをサポートしなければならない」「修正したはずの機能の不具合が何度も再発する」「コードを統合することに苦痛を感じる」「機能の追加を頻繁に要求される」「いつまでたっても作業が終わらない」これらの項目に一つでも当てはまるならば、この本は『読む価値あり』です。ほかにも具体的な項目が並んでいます。(第5章 一般的によく見られる問題とその解決方
    法)

     具体的な内容と平易な文章でどんどん読み進めることのできる本です。作業の優先度や悪い兆候としての警告サインなど、漠然と認識していた事柄が上司やクライアントを説得できる明確なリストとして載っています。
     新しい本なので紹介されているツールなども最新です。入手するためのURLももちろん載っています。

     42のヒント、コラムそれにおすすめの本と参考文献も大いに役立つと思います。
     残念ながら本書の内容はチームでの開発向けのため個人で開発している場合には採用できないものも少なくありません。しかし個人であっても工夫は可能です。「どこから着手するか」「そのやり方は正しいか?」「警告サイン」など具体的に書かれているので自分の場合どうしたら良いのかが見えてくるのです。もちろん個人でも有用な情報も沢山あります。
     「本書の読み進め方」の項にあるように、開発者やテスター、プロジェクトチームのリーダー、管理者(または製品に関与している顧客)それぞれに役立ち完成(つまり出荷)に導いてくれるはずです。

     前向きな気分にさせてくれる本です。もしまだ読んでいなければ五月の連休におすすめの一冊です。(ハムを料理するとき、いつもハムを切り、最初に3分の1を捨てていた女性の話をご存知ですか? この話の顛末を知りたければこの本をお読みください〔^_^;〕)

    ▼出版社のweb (詳しい目次が載っています)
    http://ssl.ohmsha.co.jp/cgi-bin/menu.cgi?ISBN=4-274-06656-8

     

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

     

    MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

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

    2007-04-10 

    目次

    • 「りんご味Ruby」       第1回  藤本 尚邦 ★新連載★
    • 藤本裕之のプログラミング夜話   #112
    • 高橋真人の「プログラミング指南」  第110回
    • 書籍紹介 木下 誠 著 Happy Macintosh Developing Time

    「りんご味Ruby」   第1回  藤本 尚邦

    Rubyというプログラミング言語をご存知でしょうか? この連載では、世界的に注目されている日本発のオブジェクト指向スクリプト言語Ruby(まつもとゆきひろさん作)について、Macユーザの皆さんにむけて、実践的な内容を織り交ぜながら、Rubyプログラミングの手軽さ・強力さ・心地よさを紹介していきたいと思います。

    (注: 基本的に、本連載で紹介するRubyプログラムは、Tiger以降のMac OS Xに付属しているRubyを前提とします。詳細については「補足 –Rubyのバージョンについて」をご覧ください)

    ■ はじめの一歩 — RSSリーダー

    新しいプログラミング言語について紹介するとき、最初に書くプログラムはhello,worldの印字、というのが「プログラミング言語C」(通称K&R本)第一版以来の伝統ですが、今は21世紀になって7年目、インターネット花盛りの時代ですから、それにふさわしく、簡単なRSSリーダーのプログラムで、はじめの一歩を踏み出します。

      

    require 'rss/2.0'
      require 'open-uri'
      url = 'http://www.mosa.gr.jp/?feed=rss2'
      rss = open(url) { |io| RSS::Parser.parse(io.read, false) }
      puts "-- #{rss.channel.title} (#{rss.items.size} entries) --"
      puts
      rss.items.each { |item| puts item.title }
    

    このRubyプログラムは

      ・RSS解析ライブラリとhttpアクセスライブラリをロードして — 1-2行目
      ・MOSAのWebサイトのRSS情報を取得し                      – 3-4行目
      ・チャンネルと各エントリのタイトルを(標準出力に)印字    – 5-7行目

    しています。それでは、さっそくこのプログラムを実行してみましょう。

    ■ Rubyプログラムの実行その1 — rubyコマンド

    Rubyプログラムを実行するには様々な方法があるのですが、まずは最も基本的なrubyコマンドを使います。ターミナル(Terminal.app)を起動して、シェルのプロンプト(ここでは`$’とします)が表示されたら、rubyと入力してリターンキーを入力します。

      

    $ /usr/bin/ruby

    それに続いて、上のRubyプログラム(全7行)をペーストしてください。7行目の改行も含めることをお忘れなく! 最後に、コントロールキーを押しながら`d’を入力します。

    すると

     

     -- 特定非営利活動法人MOSA (10 entries) --
      WWDC2007参加ツアーのお知らせ
      リピートセミナー:ネットワークプログラミング入門講座・基本編
      (以下省略)
    


    のような内容(各エントリのタイトルは異なるかもしれません)が印字されるはずです。

    もちろん、Rubyプログラムをファイルに保存しておいて、それを実行することもできます。上のプログラムをprint_mosa_rss.rbというの名前のファイルに保存しておき

     

     $ /usr/bin/ruby print_mosa_rss.rb

    とすると、同じように結果が印字されます。

    いかがでしたか? うまくいかなかった方、ごめんなさい。ネットワークつながってますか? 動いたけど文字化けした方は、ターミナルの「情報を見る/ディスプレイ」の文字セットエンコーディングのところがUnicode(UTF-8) になっているかご確認ください。

    ■ Rubyプログラムの実行その2 — CocoaRepl

    次は、拙作のCocoaReplを使って、RSSリーダを実行してみます。CocoaReplは、対話的にRubyプログラムを実行するためのCocoaアプリケーションです。後述のURLからダウンロードすることができます。ターミナルが苦手な方には、こちらの方が気楽かもしれません。

    CocoaReplを起動するとウィンドウが開きます。上側がRubyプログラムを書き込むためのテキストビューになっています。そこに、先ほどのRubyプログラム(全7行)をペーストして、Rubyメニューの一番上にあるEvalコマンドを実行します。すると、ウィンドウの下側にrubyコマンドのときと同じ結果が印字されるはずです。

    ■ まとめ

    さて、今回紹介したRubyプログラムを見て、皆さんはどんな印象をお持ちになったでしょうか? 「短いなぁ」「だけど、そんなに暗号っぽくはないなぁ」というような印象を持っていただけたとすれば、私にとっては大成功です。「何だかよくわからないなぁ」と思われた方もどうぞご安心ください。何しろ、まだほとんど何も説明していないのですから無理もありません。

    わずか7行の短いプログラムながら、ここにはRubyのポイントとも言える要素がいくつか含まれています。

      ・添付ライブラリの使用
      ・文字列の式展開
      ・オブジェクトの生成
      ・メソッド呼び出し
      ・ブロック付きメソッド呼び出し

    次回以降、このプログラムをとっかかりに、Rubyについて丁寧かつ実践的に説明していくつもりです。また、このプログラムを応用して、コマンド・CGIプログラム・Cocoaアプリケーション・Webアプリケーションなどを作ってみましょう。

    ■ 自己紹介

    今回よりモサ伝にてRubyについて記事を書かせていただくことになりましたRubyCocoa作者の藤本尚邦といいます。

    はるか昔、Think C/Pascal, MPW C/Pascal, CodeWarrior C++/PowerPlantなどを使って、Mac周辺機器用の各種プログラム、Photoshopプラグインやプリンタドライバ(PDEFリソース)などを書いたりしていました。10年ほど前にRubyに出会って以来、Lisp系言語などに浮気?しつつも、Rubyプログラミングの手軽さ・強力さ・心地よさに魅了され続けています。

    Mac界隈で「藤本」といえば何といっても藤本裕之さん。昔から数々の素晴らしい記事などをお書きになられていますが(MacJapanなどの記事をよく読ませていただいていました)、私も少しでも皆さんの役に立つような記事を書ければと思います。どうぞよろしくお願いします。

    ■ 参考URL

    RubyのWebサイト
    http://www.ruby-lang.org/

    Rubyリファレンスマニュアル
    http://www.ruby-lang.org/ja/man/

    RubyCocoa
    http://rubycocoa.sourceforge.net/

    CocoaRepl
    http://rubycocoa.sourceforge.net/hisa/files/CocoaRepl.app.zip

    ■ 補足 — Rubyのバージョンについて

    本記事で紹介していくRubyプログラムは、Tiger以降のMac OS Xに付属してくるRuby(Tigerの場合にはRuby 1.8.2)を前提としています。Tigerよりも前のMac OS Xを使っている方や、自分で、あるいはMacPortsなどでインストールしたRubyを使っている場合、記事の内容と若干食い違っている可能性があります。その点、ご了承ください。

    ◇ Mac OS X Panther (10.3.x)をお使いの方へ

    PantherについてくるRubyは、バージョンが古くて(1.6)今となっては不便なことが多いので、できれば、現時点で最新のRuby 1.8.6 をインストールしてください。他にRubyを使っていないのであれば、付属していたRubyを上書きしてしまうのが単純でよいと思います(ただし結果の責任は持てませんのでご了承ください)。

    ◇ Mac OS X 10.3(Panther)のRubyを最新の1.8.6に上書き更新する方法

      

    ・RubyのWebサイトからruby-1.8.6.tar.gzをダウンロード
      ・Terminal.appを起動
      ・ruby-1.8.6.tar.gzファイルを展開
           $ cd /tmp
           $ tar zxf ruby-1.8.6.tar.gz
      ・Rubyを作る
           $ cd ruby-1.8.6
           $ ./configure --prefix=/usr --enable-shared --enable-pthread
           $ make && make test
      ・Rubyをインストール
           $ sudo make install
    

    藤本裕之のプログラミング夜話 #112

     再び問う。実現したいサービスはお決まりだろうか。いや何を隠そうサンプルにどんなサービスを提供することにしようかオレ自身も迷っているのだ。つか、このサービスという機能は通常、(1)既に何かアプリケーションがあって、(2)そのアプリケーションが持つ機能を手軽にアプリケーション外から利用できるようにする、もんなんであって、サービスを実現するためにアプリケーションを作るというのは本末転倒星から本末転倒で作った宇宙船に乗って地球まで本末転倒を広めに来ましたみたいな話では、ある。
     が、やっぱり一応なんか例をだして説明をしなくてはならないので、ここはひとつ想像してください。天国なんかないと…ぢゃなくて、あなたはそこに自分で書いたとっても高機能のWebブラウザを持っています、と。で、Safariにある「Googleで検索」というサービスの真似をして、このブラウザから「Yahoo! で検索」という新サービスを提供しちゃおうと、考えてる。

     ある文字列 String を「Yahoo! で検索」するのは簡単だ。早い話が自分のブラウザで以下のURLを叩けばいい。実際にはこれにやれエンコードはどれだとかあれはなにだとかなにのほうはいずれなにしてその節ゆっくりだとかいろいろオプションがつくが、基本はこれ。

    http://search.yahoo.co.jp/search?p=String

    オプションの方はその節ゆっくり勉強して対応してもらうとして、当面の問題はサービス・リクエスターからこの文字列 String をどうやって受け取るか、だけである。

     ここで前回の話を思い出していただきたい。サービス・プロバイダとなるアプリケーションの「info.plist」に「NSMessage」というキーでアプリケーションが受け取るメッセージを記述した。しましたね? あのメッセージ、このアプリケーション内のどのオブジェクトが受け取るのであろうか。ちうか、例えばここに SearcherByYahoo というクラスのインスタンス searcher があり、そいつがシステムから送られてくるメッセージを ……おっとこれを書きわすれてた、実際にはこのメッセージは以下のようなパラメータを引き連れてくる(searchThisStringByYahooつうのは今適当にでっちあげた名前)。

    (void) searchThisStringByYahoo:(NSPasteboard*) pboard
                           userData:(NSString*) userData
                               error:(NSString**) error
    


    pboard にサービスメニューが選ばれたときにサービス・リクエスタから受け取ったパラメータが、userData に info.plist で指定したオプション・データが入っており、なにかエラーが発生したらメッセージを error にセットする。このメッセージ(メソッドといったほうが分かりやすい?)を上で書いたように SearcherByYahooクラスのインスタンス searcher が受け取って処理するとする。と、問題はどういう仕組みでこのメッセージがこのオブジェクトに飛んでくるのか、だよね。

     実はそれをセットするためのメッセージが NSApplication にある。こんな風に使う。

    SearcherByYahoo* searcher = [[SearcherByYahoo alloc] init];
    [NSApp setServiceProvider:searcher];

     これを見れば判るように、複数のサービスメッセージを受けて違った処理をする場合でも受け手のオブジェクトは1個である。FinderがなんというオブジェクトをsetServiceProviderにセットしているか知らないが、そのオブジェクトはFinderのinfo.plist に書かれている3つの処理、「情報を見る」、「手前に表示」、「開く」のメッセージを処理できなくてはならない。さて、めでたしめでたし、これで世界は一つになり戦争はなくなる。……あ、その歌ぢゃありませんでしたね。
                                (2007_04_05)

    高橋真人の「プログラミング指南」第110回

    プログラマのためのオブジェクト指向再入門(18)

    〜XcodeによるPowerPlant X入門(2)〜

     こんにちは。高橋真人です。早速続きを始めます。
     今回は、ごく簡単なPowerPlant Xアプリケーションを作成し、動作の確認をします。

    ◆プロジェクトの作成
     XcodeでCarbon C++ Applicationの新規プロジェクトを起こします。名前は、PPxForXcode01と付けましょう。
     次に、Finderでホームフォルダの中に出来たPPxForXcode01フォルダを開き、中のHIFrameworkという名のフォルダを捨てます。
     Xcodeに戻り、「グループとファイル」ペインのSources(以下、単に「Sourcesグループ」と表記します)を展開して、HIFrameworkという名の黄色いフォルダを選択して、deleteキーを押して削除します(今捨てたフォルダに入っていたソースファイルをプロジェクトから削除するわけです)。
     プリコンパイルヘッダ(PPxForXcode01_Prefix.pch)を開き、以下の3行を取り除きます。

    #include "HIFramework.h"
    #include "TApplication.h"
    #include "TWindow.h"
    


    つまり、

    #include 


    のみを残すのです。
     閉じて、保存します。
     Sourcesグループ(上記参照)を選び、メニュー「プロジェクト→プロジェクトに追加…」を選びます。
     ファイル選択ダイアログで/Libraryに行き、PowerPlantXを選択して「追加」ボタンをクリックします。この時、追加のための設定シートダイアログが出るので、以下のように設定します。

    フォルダに項目をコピーのチェック→外したまま参照タイプ→デフォルトエンコーディング→日本語(Mac OS)ラジオボタン→再帰的にグループを作成の方を選択

    ◆検索パスの追加
     メニュー「プロジェクト→プロジェクト設定を編集」を選択し、設定ダイアログを開きます。
     「ビルド」タブを選んで、「ヘッダ検索パス」のところに、

    /Library/PowerPlantX


    と入力します。

    ◆ソースコードの編集
     ソースコード、main.cpを以下に書き換えます。

    #include 
    
    int main()
    {
        PPx::Application app;
        app.Run();
    
        return 0;
    }
    


     ビルドします。
     警告が50近く出ますが、ビルドは成功するはずです。
     では、試しに走らせてみましょう。
     アプリケーションメニューが出るだけで、あとはウインドウもメニューもありませんが、ちゃんとアプリケーションとして起動しています。メニューから「終了」を選んでも、コマンド+Qででも終了させることができます。

     以上で、PowerPlantXアプリケーションが動くところまで漕ぎ着けました。もし、ビルドができないようなら、ここまでの手順を再度見直してください。
     これだけで終わってしまうのも寂しいので(笑)、ビルド時にたくさん表示された警告を表示させないようにしておきましょう。
     以前も説明しましたように、ここで表示されている警告のほとんどは現在のOSにおいて使用が推奨されないAPI、つまりDeprecatedなAPIについてのものと、「未使用の変数」に関するものです。
     まずDeprecatedなAPIの方ですが、これは将来にわたって「いずれは使えなくなる」ことをほのめかしているだけで、すぐにどうこうということではありません。特に、PPxは最初からPanther(Mac OS X 10.3.x)をターゲットに作られたので、そんなに古いAPIが使われていることはないのです。
     よって、この連載ではこれらの根本的な解決を行うことはいたしません。ただ、目障りでもあるし、他にもっと重要度の高い警告やエラーが出た場合にそれらが目立ちにくくなるので、「表示させなく」します。
     それから、後者の未使用変数ですが、CodeWarrior(以下CW)においても未使用の変数は警告が出るのが標準でしたので、PPxの出荷状態においても、当然これらの処置はされていたはずです。
     ところが、以前のバージョンではかなり警告のレベルの低かったGCCが現在のMac OS X 10.4.x標準の4.0からは格段にチェックが厳しくなって、CWよりも厳格なチェックをするようになりました。「未使用」という意味のとらえ方が、CodeWarriorでは「定義しても使われていない」だったのに対して、GCC4.0(以下GCC4)では「定義して、何らかの値が代入されていても、それが使われていない」場合も含めて「未使用」と見なすようになっているようなのです。
     つまり、

    int a;

    と書いてあるだけで、以降そのスコープ内でaが登場しない場合は、CWもGCC4も「未使用」と見なします。しかし、

    int a = 0;

    というように、aに(それがたとえ初期化であっても)何らかの値が代入された場合、CWではこれを未使用とは見なしませんが、GCC4では未使用と見なすわけです。

     さてそれでは、実際に作業をしてみましょう。
     プロジェクトメニューから、「アクティブなターゲット’PPxForXcode01′を編集」を選び、開いたダイアログで「ビルド」タブを選択します。
     「コレクション」のポップアップメニューから「警告」を選んで、中ほどの「未使用静的変数の警告」と下から2番目の「推奨されない関数についての警告」のチェックを外します。
     これで、OKなはずです。ビルドをし直して警告が一つも出なくなったら成功です。

    書籍紹介 木下 誠 著 Happy Macintosh Developing Time [Second Edition]

     解説担当:高橋政明

    Happy Macintosh Developing Time [Second Edition]
    木下 誠著
    株式会社ビー・エヌ・エヌ新社 ISBN4-86100-124-2 ¥3,780 (税込)

     広範囲に解説されているCocoaプログラマ必携の書です。著者はモサ伝でニュース解説を担当していただいていた木下さんです。
    Cocoaではシンプルなプログラムであってもいろいろなクラスを使います。このため網羅する範囲の広いこのような本が必要です。
     このSecond EditionはMac OS X 10.3に対応しています。もちろん現在でも役立つ情報です。
     Third Editionもあり、10.4の新機能が解説されていますがSecond Editionの内容と重複する部分はありません。Second EditionとThird Editionはまったく独立した内容なので購入の際にはご注意ください。

     下記出版社のwebなどで目次を見るとわかりますが実際のソフトウェアで頻繁に使う様々なクラスが載っています。単なるクラスやメソッドの羅列だけでなく、シンプルで具体的な利用例があるのでプログラミング中に調べる時も助かります。

     2004年に出た本で、残念ながら完売し2006年末時点で増刷の予定無しだそうです。
    http://hmdt.jp/archives/2006_12.html
    (「本が半額のお店」などであれば見つかるかもしれません)

    ▼出版社のweb
    http://www.bnn.co.jp/books/title_index/mac/happy_macintosh_developing_timesecond_edition_xcod.html

    ▼著者のweb (ソースコ−ドのダウンロードサービスあり)
    http://hmdt.jp/books/hmdtSecond/index.html

    ▼著者による初版解説(当然初版は古く、Xcodeが出る前に出版されました)
    http://homepage.mac.com/mkino2/books/hmdt.html

     さてCocoaの本を三冊連続でご紹介してきました。Cocoaは開発効率を高めることのできる強力なツールです。しかし大規模であるためたくさんの情報が必要で手強いことも事実です。まだ『これ一冊でCocoaは完璧』と言える決定版の書籍はありません。
     これからCocoaをはじめる方はこれまでご紹介した三冊を手始めに取り組んでみてください。疑問点の相談にはMOSAの掲示板MOSAdeBBをご活用ください。
    http://www.mosa.gr.jp/mosadebb/modules/newbb/

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

       

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

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

    2007-04-03  

    目次

    • 「「Wonderful Server Life」    第44回   田畑 英和
    • 小池邦人の「Carbon API 徒然草」
    • SqueakではじめるSmalltalk入門  第81回   鷲見 正人
    • 書籍紹介 アーロン・ヒレガス著 Mac OS X Cocoaプログラミング

    「Wonderful Server Life」  第44回  田畑 英和

      〜アカウント編〜

     WWDC2007のセッション概要もぼちぼち公開され始めましたね。Leopardの発売日はまだあきらかにされていませんが、今年のWWDCの目玉はいったいどうなるのでしょうか。

    ◇アカウント管理
     さて、今回はアカウント管理の解説をしたいと思います。アカウントについてはすでにネットワークユーザの解説を以前行いましたが、OpenDirectoryでは管理可能なアカウントとして次の3種類があります。

    ・管理可能なアカウント
      - ユーザ
      - グループ
      - コンピュータ

     ユーザについてはすでに解説済みですので、残りのグループとコンピュータについて解説していきたいと思います。Mac OS Xを1人のユーザだけが使用している場合には、グループやコンピュータといったアカウントを直接意識することはないかもしれません。ですが、サーバを使ってクライアント管理を行う場合には、グループやコンピュータのアカウントを利用することで効率よく管理ができるようになります。
     グループでは、複数のユーザ(あるいはグループ)をメンバーとして1つにまとめて管理することができます。たとえばファイルサービスの場合では、グループ単位でアクセス権の管理を行うことができます。
     さらに、コンピュータもアカウントとして管理することができ、ユーザ、グループ、コンピュータごとにサーバ上で環境設定の一元管理を行うことができます。

    ◇グループ
     ではグループから解説していきましょう。グループの管理はユーザの管理と同様に「ワークグループマネージャ」を使用します。「ワークグループマネージャ」を起動し、まずツールバーから「アカウント」をクリックします。すると画面左側にアカウントのリストが表示されます。
     アカウントのリストはユーザ、グループ、コンピュータの3つに分かれており、リスト上部のボタンでそれぞれの表示を切換えることができます。左から2番目のボタンがグループのボタンです。

     初期状態ではグループのリストにはまだなにも表示されません。ユーザを新規に作成したときと同じ要領で、ツールバーから「新規グループ」ボタンをクリックすると新規グループを追加することができます。グループのパラメータとしては次のようなものがあります。

    ・名前
      最大長255byte
      フォーマット:UTF-8
    ・ユーザ名
      最大長255byte、ショートネームとも呼ばれる
      フォーマット:A〜Z、a〜z、0〜9、_で構成されるASCII文字
    ・グループID
      グループごとに一意に割り当てられるID
      フォーマット:32ビットの数値

    ・グループレコード内の標準属性
    「オープンディレクトリの管理」P.222
    http://images.apple.com/jp/server/pdfs/Open_Directory_v10.4_j.pdf

     以上の3つがグループの基本的なパラメータになります。「グループID」はグループを新規に作成したときに自動的に割り当てられますので、あとは「名前」と「ユーザ名」を指定すればよいことになります。
     グループの設定をしているにもかかわらず、画面上の表示は「ユーザ名」となっていますが、英語環境で「ワークグループマネージャ」を起動しますと「Short name」と表示されています。ユーザの管理画面でも同様の名前が使われていますので、おそらくリソースの翻訳ミスでしょう。ここは「グループ名」のことです。パラメータの設定が終われば最後に画面右下の「保存」ボタンをクリックします。

    ・グループの管理画面
    http://homepage.mac.com/htabata/MXS10.3/img/WGM_Group/WGM_Group_01.png

    ◇グループメンバーの管理
     グループには複数のユーザをメンバーとして登録することができます。MacOS X Server v10.4ではグループに登録できるユーザ数に制限はありません。また、ユーザがメンバーになれるグループの数にも制限はありません。
     さらにMac OS X Server v10.4からは、ほかのグループをメンバーとして登録できるようにもなりました。つまりグループの階層構造を実現することができるのです。グループの階層構造により、実際の組織体系に合わせたグループ管理が可能になります。

     メンバーの追加方法ですが、メンバーリストの右側にある「+」ボタンをクリックすると画面の端にユーザおよびグループのリストが表示されます。このリストから任意のユーザあるいはグループを選択して、グループのメンバーリストにドラッグ&ドロップします。

    ・グループメンバーの登録
    http://homepage.mac.com/htabata/MXS10.3/img/WGM_Group/WGM_Group_02.png

     グループの管理画面ではグループのメンバーとしてユーザを登録しますが、ユーザの管理画面でもグループに関する設定ができます。ユーザの管理画面から「グループ」を選択しますと、ここでは左側のリストで選択中のユーザがメンバーとして登録されているグループのリストを表示することができます。さらに、この画面からはユーザを任意のグループに登録することもできます。
     この画面には「プライマリグループID」というパラメータがありますが、これはユーザがデフォルトで所属するグループのことです。ユーザは最低1つのグループに所属する必要がありますが、ユーザを新規に登録すると自動的にグループIDが20(staffグループ)のグループに登録されます。

    ・ユーザ管理画面の「グループ」
    http://homepage.mac.com/htabata/MXS10.3/img/WGM_Group/WGM_User_12.png

     それでは次回はグループフォルダなどについて解説したいと思います。
                                   つづく

    小池邦人のCarbon API 徒然草(2007/03/30)

    〜 Carbonモダンアプリケーションへの道(その13) 〜

    今回は、HIThemeOrientation()によるテキスト描画を印刷(プリントアウト)に利用してみたいと思います。印刷といっても、ウィンドウ上のテキスト描画とそれほど違いはないのですが、幾つか注意すべきポイントを解説します。

    せっかくですので、まず最初にCarbonアプリケーションでの印刷手順をおさらいしておきましょう。昔から印刷作業には2種類のダイアログ、もしくはシートウィンドウを利用します。それらは、用紙設定ダイアログ(Page Setup)とプリントダイアログ(Print)と呼ばれており、ファイルメニューの「ページ設定…」や「用紙設定…」そして、「プリント…」を選択することで表示されます。用紙設定ダイアログでは、印刷のための用紙サイズや印刷方向を設定できます。その後、プリントダイアログで印刷枚数等を入力し「プリント」ボタンをクリックすれば、印刷が始まる手順となります。

    昔から、このように印刷関連のダイアログが2つに分かれている点については、使い勝手の面からも議論の対象となっています。まあ用途によりけりなので、どちらかが最良と言うわけでもないと思いますが、両ダイアログを一つにまとめたオプションが存在しても良いのではないでしょうか(近々そうなるとの噂アリ)。まずは、用紙設定ダイアログ(シート)の表示方法を調べてみます。

    先んじて、両ダイアログの設定内容を保持するための2つのリファレンス
    (PMPageFormatとPMPrintSettings)を外部変数として定義しておきます。

    PMPageFormat       pt_form=NULL;       //  用紙設定ダイアログ設定を参照
    PMPrintSettings    pt_set=NULL;        //  プリントダイアログ設定を参照

    getDefaultFormatPrint()は、指定された印刷セッションにおける(PMPrintSessionで参照する)用紙設定のディフォルト内容(つまり初期値)を引数で渡したPMPageFormatに代入する簡単なルーチンです。具体的にはメモリ内に構造体を確保し、そのメンバーに初期値を代入します。

    short getDefaultFormatPrint( PMPrintSession pss,PMPageFormat *form )
    {
       short    err=1;
    
       if( ! PMCreatePageFormat( form ) )  // PMPageFormatを作成する
       {
           if( *form )
               err=PMSessionDefaultPageFormat( pss,*form );
       }                                       // 用紙設定の初期値を代入する
       return( err );
    }
    


    次が、pt_formの設定内容を変更するための用紙設定ダイアログ(今回はシート)を表示するpageSetupPrint()ルーチンです。シートを表示して「OK」か「キャンセル」ボタンをクリックすると、PMSessionUseSheets()の引数として登録しておいたpageDoneProc()(終了ルーチン)が呼ばれます。ちなみに、この処理からPMSessionUseSheets()を外せば、用紙設定シートはダイアログとして表示されます。しかし、Mac OS X 10.4(Tiger)では、モニターの変な場所にダイアログが表示されるバグが存在しますので注意してください。このバグは、Mac OS X 10.5(Leopard)で修正されるそうです。

    short pageSetupPrint( WindowRef window )
    {
       Boolean           chk=0;
       PMPrintSession    pss;
    
       if( ! PMCreateSession( &pss ) )                    // 印刷セッションを開始
       {
           PMSessionUseSheets( pss,window,pageDoneProc ); // 終了ルーチンを登録
           if( pt_form )                                  // 用紙設定情報登録済み
           {
               if( PMSessionValidatePageFormat( pss,pt_form,kPMDontWantBoolean ) )
                   getDefaultFormatPrint( pss,&pt_form ); // 情報内容が妥当か検査
           }
           else
               getDefaultFormatPrint( pss,&pt_form );     // 未登録の場合は初期化
            PMSessionPageSetupDialog( pss,pt_form,&chk ); // 用紙設定シートを表示
       }
       return( chk );
    }
    


    以下が、用紙設定シートを閉じる時に呼び出されるpageDoneProc()ルーチンです。渡されてくるchkの内容により、「OK」ボタンが押されたのか「キャンセル」ボタンが押されたのかを判断可能です。もし、PMSessionUseSheets()を実行せず、シートでなくダイアログの方を表示している時には、PMSessionPageSetupDialog()が返すchkの値により、押されたボタンの種類を判断することができます。

    void pageDoneProc( PMPrintSession pss,WindowRef window, Boolean chk )
    {
       if( chk==1 )     // OKボタンが押された
       {
            // ここには用紙設定情報(pt_formの内容)を保存する処理などを記述する
       }
       PMRelease( pss ); // 印刷セッションを終了
    }
    


    次は、プリントシートを表示するstartPrint()ルーチンです。startPrint()を実行する時点で、まだ一度も用紙設定シートがオープンされていない可能性がありますので、先んじてpt_formに対して前記ルーチンと同様な処理を行っています。

    short startPrint(WindowRef window)
    {
       Boolean           chk=0;
       PMPrintSession    pss;
    
       if( ! PMCreateSession( &pss ) )                     // 印刷セッションを開始
       {
           PMSessionUseSheets( pss,window,printDoneProc ); // 終了ルーチンを登録
           if( pt_form )                                   // 用紙設定情報登録済み
           {
               if( PMSessionValidatePageFormat( pss,pt_form,kPMDontWantBoolean ) )
                   getDefaultFormatPrint( pss,&pt_form );  // 情報内容が妥当か検査
           }
           else
               getDefaultFormatPrint( pss,&pt_form );      // 未登録の場合は初期化
    
           if( ! PMCreatePrintSettings( &pt_set ) )        // pt_setを作成する
           {
               if( pt_set )
               {
                   PMSessionDefaultPrintSettings( pss,pt_set );  // 初期値代入
                   PMSessionPrintDialog( pss,pt_set,pt_form,&chk );
               }                                        // プリントシートを表示
           }
       }
       return( chk );
    }
    


    続いて、プリントシートを閉じる時に呼び出されるprintDoneProc()ルーチンです。OKボタンが押された時のみstartPrint()ルーチンを実行し、実施の印刷作業を開始します。

    void printDoneProc( PMPrintSession pss,WindowRef window, Boolean chk )
    {
       if( chk==1 )      // OKボタンが押された
           startPrint( window,pss,pt_set,pt_form );  //  実際の印刷処理
       PMRelease( pss ); // 印刷セッションを終了
    }
    


    最後は、実際の印刷作業を受け持つstartPrint()ルーチンです。印刷処理自体については詳しく解説しませんが、この処理中で重要な箇所は、PMSessionGetGraphicsContext()でkPMGraphicsContextQuickdrawを指定し、まずはQuickDraw APIによる描画を印刷に反映させるためのCGrafPtrを得ている所です。しかしこのままでは、HIThemeDrawTextBox()など描画環境をCGContextRefで参照するAPIは利用できません。そこで、QDBeginCGContext()を使いCGrafPtrからCCGContextRefを得て、それを引数で渡すことで初めてCoreGraphics APIでの描画を印刷に反映させることが可能となります。

    OSErr startPrint( WindowRef window,PMPrintSession pss,
                                         PMPrintSettings set,PMPageFormat form )
    {
       unsigned long   i,st,ed;
       CFStringRef     cfstr;
       short           err=1;
       CGrafPtr        port;
       CGContextRef    ctx;
    
       CopyWindowTitleAsCFString( window,&cfstr ); // ウィンドウタイトルを得る
       PMSetJobNameCFString( set,cfstr );          // 印刷ジョブ名を設定
       CFRelease( cfstr );
    
       PMGetFirstPage( set,&st );                      // 開始ページ
       PMGetLastPage( set,&ed );                       // 終了ページ
       if( ! PMSessionBeginDocument( pss,set,form ) )  // ドキュメント印刷開始
       {
           for( i=st;i<=ed;i++ )
           {
               if( ! PMSessionBeginPage( pss,form,NULL ) )  // 指定ページ印刷
               {
                   PMSessionGetGraphicsContext( pss,
                                      kPMGraphicsContextQuickdraw,(void**)&port );
                                                    // 印刷環境のCGrafPtrを得る
                   if( ! QDBeginCGContext( port,&ctx ) )  // CGContextRefを得る
                   {
                        // ここでHIThemeDrawTextBox()などによるテキスト描画を行う
                       err=noErr;
                       QDEndCGContext( port,&ctx );       // CGContextRefを解放
                   }
                   PMSessionEndPage( pss );   // 指定ページ印刷終了
               }
               if( err )
                   break;
           }
           PMSessionEndDocument( pss );       // ドキュメント印刷終了
       }
       return( err );
    }
    


    上記処理のような回りくどいことをせずとも、単純にPMSessionGetGraphicsContext()にkPMGraphicsContextCoreGraphicsを代入し、ダイレクトにCGContextRefを得ることができれば、すぐにCoreGraphicsAPIを使えるような気がします...。

    ところが、下記のようにCFArrayCreate()とPMSessionSetDocumentFormatGeneration()で行っている手続きを加えないと、この作戦は成功しません。この追加処理の部分、なんだか「おまじない」のような感じなのですが(笑)残念ながら、現状ではこう記述しないとCoreGraphics APIでの描画が印刷に反映されないのです。どう考えても、これは余分な手続きだと思いますので、Mac OS X 10.5では修正してほしいところです。

    OSErr startPrint( WindowRef window,PMPrintSession pss,
                                         PMPrintSettings set,PMPageFormat form )
    {
       CFStringRef     sref,cfstr;
       unsigned long   i,st,ed;
       short           err=1;
       CGContextRef    ctx;
       CFArrayRef      arr;
    
       CopyWindowTitleAsCFString( window,&cfstr ); // ウィンドウタイトルを得る
       PMSetJobNameCFString( set,cfstr );          // 印刷ジョブ名を設定
       CFRelease( cfstr );
    
       PMGetFirstPage( set,&st );
       PMGetLastPage( set,&ed );
       sref=kPMGraphicsContextCoreGraphics;
       if( arr=CFArrayCreate( kCFAllocatorDefault,(const void **)sref,1,
                                                        &kCFTypeArrayCallBacks ) )
       {
           PMSessionSetDocumentFormatGeneration(pss,kPMDocumentFormatPDF,arr,NULL);
           CFRelease( arr );                    // CGContextRefを得るための手続き
           if( ! PMSessionBeginDocument( pss,set,form ) ) // ドキュメント印刷開始
           {
               for( i=st;i<=ed;i++ )
               {
                   if( ! PMSessionBeginPage( pss,form,NULL ) ) // 指定ページ印刷
                   {
                       PMSessionGetGraphicsContext( pss,
                                  kPMGraphicsContextCoreGraphics,(void**)&ctx );
                                                  // 印刷環境のCGContextRefを得る
    
                        // ここでHIThemeDrawTextBox()などによるテキスト描画を行う
    
                       err=noErr;
                       PMSessionEndPage( pss );   // 指定ページ印刷終了
                   }
                   if( err )
                       break;
               }
               PMSessionEndDocument( pss );       // ドキュメント印刷終了
           }
       }
       return( err );
    }
    


    今回でテキスト関連の話題は終了し、次回からはCarbonのファイルシステムについて解説します。こちらもテキストやグラフィックスに負けず劣らず、時代と共に変貌してきた経緯があります。はたしてファイルシステムは、どの程度モダン化されたのでしょうか?

    つづく                                

    SqueakではじめるSmalltalk入門   第82回  鷲見 正人

    前回は、Squeakと同じXEROXのオリジナルSmalltalk-80の系譜の、しかし子供向けの暫定ダイナブック色の濃いSqueakとは違い、プロプログラマ向けの本格的IDE然としたVisualWorksをご紹介しました。今回は、これら“純正”のSmalltalkに触発されて、いまなお作られ続けているSmalltalkファンお手製の独自のアレンジのSmalltalk処理系について、とくにOS Xで動作させられるものをご紹介します。

    ▼Little Smalltalk、GNU Smalltalk
    Smalltalkのある意味“クセ”のあるGUIは介さずに、通常の言語処理系のようにUNIX系OSの標準入出力を通じて(つまりCUIで)Smalltalkを使いたい…という要望は古くから根強くあるようです。そうしたGUI抜きSmalltalk処理系としての存在で、古くから有名なものに「Little Smalltalk」があります。文字通り、非常にコンパクトなSmalltalk処理系を作るための技術解説書籍とともに、全ソースコードも提供されていました。当時は高価で縁遠い存在だった“ホンモノ”のSmalltalk-80に直に触れて、ハックすることができなかった言語オタク達には、Little Smalltalkはよい遊び道具になっていたようです。

    驚いたことにLittle Smalltalkは、Little Smalltalk自身のファンの手により現在も「Little Smalltalkプロジェクト」管轄下でのメンテナンスが行なわれています。

    http://www.littlesmalltalk.org/index.php?page=home

    余談ですが、Little Smalltalkの生みの親であるティモシー バッドは、これとは別に「Javaアップレット版Little Smalltalk」と呼べそうな「SmallWorld」を作って公開しています。

    http://web.engr.oregonstate.edu/~budd/SmallWorld/ReadMe.html

    さて。Little Smalltalkは、CUIであることよりは、むしろその小ささやシンプルさが“売り”だったわけですが、同じGUI抜きでも、GUI以外の部分は本家のSmalltalk言語処理系と同じくらい本格的なSmalltalkを目指した処理系もあります。それが「GNU Smalltalk」です。

    MacPorts(http://www.macports.org/)を利用していれば、ターミナルから「sudo port install gst」でインストールし、「gst」で専用のシェルを起動して使うことができるようになります。「gst」のあとにファイル名を付せば、通常のスクリプト言語同様、そのファイルに記述されたSmalltalkコードを実行できます。

    GNU Smalltalkは、CUIで使う以上、GUI付きのSmalltalkではお馴染みの「コードを入力して選択 → do it(あるいはprint it)」という実行スタイルはとれません。そのため、一連の式の最後に「!」を付けて、do it(つまり式の評価)のタイミングを処理系に伝える方法をとります。

    $ gst
    GNU Smalltalk ready
    
    st> 3 + 4!
    7
    st> | a b |
    st> a := 3.
    st> b := 4.
    st> a + b!
    7
    st>
    
    


    ところで、Little SmalltalkもGNU Smalltalkも最近のバージョンでは、立派なGUIを使えるようになっています。なんとも、本末転倒のような気もしなくもないのですが、やはりMac同様、GUIベースOSの始祖的存在であるSmalltalkは、どうあってもGUIとは切っては切れない関係にあるのだろうな…と思えば納得です。たとえば、GNU SmalltalkならX11が使える環境で起動時に、

    gst -qK browser/Run.st
    


    とすることで、ごく普通に、選択した式を右クリックメニューからprint itできてしまう、本格的GUI付きSmalltalk環境として機能させられます。

    [fig.A]GUI付きで起動したGNU Smalltalk

    ▼Ambrai Smalltalk
    SmalltalkをCUIで使いたい…という願いは、あたかも“独立したOS”がごとく自己完結し自由奔放に振る舞うSmalltalkを、UNIXライクOSの流儀で“たんなる言語処理系”のひとつとしてねじ伏せて飼い慣らしたい…という欲求の表れであるとの解釈もできそうです。これがMacやWinでなら、ネイティブGUIで(あるいは、ダブルクリックで起動可能なアプリのための開発環境として)Smalltalkを使いたい…ということになりましょうか。実際、SmalltalkをCUIで使いたい…というのと同じくらい、ネイティブGUIでSmalltalkを動かしたい、ネイティブGUIをSmalltalkから使いたい…という要求も古くから根強くあ
    ります。

    そうした要望を自分の手で叶えようとする流れのひとつでしょう。我らがOS X向きにも、Cocoaオブジェクトとの連携を強く意識したSmalltalk処理系が作られています。そのひとつが「Ambrai Smalltalk」です。まだ製品化される前のパブリックベータ公開の段階ですが、安定していて普通に使えます。ワークスペース、トランスクリプト、ブラウザ、インスペクタなど基本的なGUIツールを備え、Smalltalk言語処理系としてもANSIの規格に準拠した本格的なものです。

    http://www.ambrai.com/smalltalk/index.html

    Ambrai Smalltalkでは、「do it」が「Evaluate It」に、「print it」が「Display It」に変えられていますが、それ以外はSqueakやVisualWorksとさほど違いを意識せずとも使うことができそうです。もしもMacがSmalltalk(=暫定ダイナブック)の遺伝子をもっと色濃く受け継いでいたならば、Undo、Copy、Cut、Paste(ちなみにこれらはSmalltalkがルーツ…)だけでなく、Smalltalkのdo itやprint itに相当する項目も、ちゃっかりEditメニューに加えられていたかもしれませんね。MacっぽさとSmalltalkっぽさをうまくミックスしてあるAmbrai Smalltalkをながめていると、そんな“来なかった未来”が見えてきそうで楽しいです。

    Ambrai Smalltalkの面白いところは、CocoaのオブジェクトやAPIに、Smalltalkを使ってアクセスできることです。たとえば、ワースペースなどで

    MacWindowFrame new open

    と入力して選択してからdo it…もとい、Evaluate Itすることで、新しいウインドウを開くことができます。Ambrai Smalltalkのサイトには、この調子でCocoaのチュートリアルでもお馴染みのCurrency Converterを記述して実際に動作させる方法が紹介されています。コードもSqueakでMorphicアプリケーションを記述する感じとよく似ていますね。

    http://www.ambrai.com/smalltalk/tutorials/tutorial1/index.html

    さらに、Interface Builderで作成したnibファイルを読み込んで、AmbraiSmalltalkで書いたコントローラオブジェクトと連携させるための手順も書かれています。

    http://www.ambrai.com/smalltalk/tutorials/tutorial2/index.html

    バックナンバー:
    http://squab.no-ip.com:8080/mosaren/

    書籍紹介    アーロン・ヒレガス著  Mac OS X Cocoaプログラミング

     解説担当:高橋政明

    Mac OS X Cocoaプログラミング
    アーロン・ヒレガス (Aaron Hillegass) 著
    村上 雅章 訳
    ピアソンエデュケーション ISBN4-89471-440-X ¥3,885(税込)

     通称ヒレガス本と呼ばれているCocoa独学のためのテキストです。2002年の本なのでツールなどのバージョンが古いのですがCocoaを理解するにはとても重要な価値ある一冊です。

     著者はNeXT社のOpenStepプログラミングの教育担当として働いていたそうです。プログラマにCocoaを教えてきた著者ならではのバランス感覚で説明されていて、サンプルプログラムもシンプルです。(NeXTがAppleに買収された当時はAppleのエンジニアにもCocoaを教えていたそうです)
     この本は自習形式で書かれています。残念ながら執筆時点が古いため Xcodeではなく Project Builder での例が紹介されていますが、基本的な部分はそのまま通用します。もちろん操作する画面やパネルが違っているところもあるのでその点は注意してください。

     原著は2004年に改訂されていますが対応する日本語版はまだ出ていません。Objective-C はレパード(Mac OS X 10.5)で2.0に変わるので、さらに改訂版が出ることを期待しましょう。残念ながら下記原著のwebで第3版の予定はないと載っていますが...

    ▼出版社のweb
    http://www.pearsoned.co.jp/hed/search/onlinecatalog.html?id=282

    ▼原著 Cocoa Programming for Mac OS X のweb(原著の正誤表あり)
    http://bignerdranch.com/products/cocoa1.shtml

     

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

     

    MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.