前回はPICT画像を取り扱うための代用APIを調査してみました。今回は、文字列(ストリングス)の作成や操作に関係するモダンなCarbon APIを紹介したいと思います。
従来、Macintosh用アプリケーションの開発で文字列を扱う場合には、Cストリングスの代わりにPascalストリングス(Str255)が多用されてきました。これは、初代Macintoshシステム(ひょっとしてLisaからの遺産だったかも...)の開発用言語としてPascalが使われていたのが原因です。そのため、QuickDrawやToolBoxの各Managerの文字列を取り扱うAPIの引数には、必ずPascalストリングスが渡されるように設計されていました。
例えば、Text Utility(TextUtils.h)には、GetIndString()というSTR#リソースからインデックス(番号)参照で特定のPascalストリングスを抽出してくる大変便利なAPIがありました。まあ、これも予想通りDEPRECATED指定なので、そのうち利用できなくなるのですが(寂しい)。色々と調査をしてみると、Pascalストリングスの操作に関連したAPIはDEPRECATED指定になったものが多いようです。
void GetIndString( Str255 theString,short strListID,short index );
筆者は、アプリケーションでエラーアラートなどを表示する場合、このAPIを用いて、その文字列内容をSTR#リソースから抽出して利用していました。ちなみに、2つめの引数はSTR#リソースのID番号でして、これを切り替えることにより、自作アプリケーションを多国語に対応させるような処理も行えました(随分と昔の話です)。ただし、Pascalストリングスは先頭の1バイトにその文字列長の値が代入されています。そのため、1文字が1バイトだとすると、最長で255文字の文字列しか取り扱うことができません。つまり、何らかの処理において長い文字列を扱いたい場合には、必ず制限が付きまといます。
ちなみにCストリングスは、その最終バイトにゼロを代入することで文字列の終わりとしますので、文字列の長さには制限がありません。また現在では、Unicode(Mac OS Xのファイルシステムで利用)をはじめとする多種多様の文字エンコーディングが存在しますので、そうしたものを統一して操作するにはPascalストリングスでは力不足です。まあ、ず〜と今までの間(20年以上も)Macintoshのシステムの中心でPascalストリングスが生き残っていたこと自体が奇跡なのですが(笑)、Mac OS Xでは、その主役の座を別の文字列フォーマットに譲ることになりました。Mac OS Xでの文字列は、Core Foundation APIで多用されているCFString(CFStringRef)として参照されます。
CFStringを直接操作するAPIの解説は後述するとして、古くからあるAPIのCFString対応がどうなっているのかを調べてみましょう。例えば、ウィンドウ、メニュー、コントロールなどのユーザインターフェース・オブジェクトの名称を設定する場合、昔のAPIであれば必ずPascalストリングスが用いられていました。対象がウィンドウであれば、その名称(タイトル)を設定する時にはSetWTitle()を、逆に表示されているタイトルを得る時には、GetWTitle()を用いていました。不思議なことに、実はこの2つのAPIはDEPRECATED指定ではありません。
SetWTitle( WindowRef window,ConstStr255Param title );
GetWTitle( WindowRef window,Str255 title );
現在では、こうしたAPIに対してStr255の代わりにCFStringRefを渡す代用品が用意されています。SetWTitle()の代用品としてはSetWindowTitleWithCFString()が、GetWTitle()の代用品としてはCopyWindowTitleAsCFString()が用意されています。Control ManagerやMenu Managerの同種のAPIについてもまったく同じことが言えます。
SetWindowTitleWithCFString( WindowRef inWindow,CFStringRef inString );
CopyWindowTitleAsCFString( WindowRef inWindow,CFStringRef *outString );
続いて、最初からCFStringを使うように設計されたモダンAPIをいくつか見てみます。以下のopenMyDialog()は、ファイル名が「Dialog.nib」というNibファイルをオープンし、そこに定義されている「Test_Dialog」というオブジェクトを使いウィンドウを作成するルーチンです。

上記の、CreateNibReference()の1つ目の引数とCreateWindowFromNib()の2つ目の引数には、CFStringRefで参照されるNibファイル名とウィンドウオブジェクト名を渡します。定数(固定値)のCFStringRefを引数に渡す時には、例題のようにCFSTR()の内部にCストリングスを記述すればOKです。これは、Pascalストリングスを"\pDialog"と記述したのと同じことです。
引数として渡すCストリングスが不定の場合には、CストリングスからCFStringを作成することで得られるCFStringRefが必要です。CFStringRefを作成したり操作したりするAPIはCFString.hに定義されています。こうしたAPIを用いれば、Pascalストリングス、Cストリングス、Unicode文字列などをCFStringへと変換し、それを参照するためのCFStringRefを得ることができます。例えばCストリングスをCFStringへ変換するためには、以下のようにCFStringCreateWithCString() APIを用いた簡単なルーチンが利用できます。

得られたCFStringRefが不必要になった場合には、他のCore Foundation APIで作成するオブジェクトと同様、CFRelease()に渡して解放する必要があります。この時の注意点は、CFRelease()に渡すCFStringRefがゼロ(NULL)などであると、CFRelease()を実行した時点でアプリケーションが落ちてしまうことです。筆者は、以下のようなルーチンを作り、こうした事故を未然に防ぐようにしています。

逆にCFStringからCストリングスを得るには、CFStringGetCString() APIを用いた以下の様なルーチンを準備しておくと便利です。

今回は、Pascalストリングスの代わりとして登場したCFStringを簡単に紹介しました。次回は、CFString自体を操作するAPIを含め、さらに詳しくその特徴や活用方法などについて解説したいと思います。
copyright 2006 Ottimo, Inc. All rights reserved
無断転載・引用禁止
Contact us: koike@ottimo.co.jp