高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technote 1092

A Print Loop That Cares...
The Sequel


目次

印刷処理の古い方法

新しい方法: C 言語による印刷ループ

印刷中のエラー条件のチェック

いくつかの一般的なエラー処理のためのガイドライン

印刷プロセスのキャンセルまたは一時停止

エラーメッセージ

要約
の TECHNOTE は「TECHNOTE PR 10: A Printing Loop That Cares」を改訂したものです。この TECHNOTE では、最新のプリンタドライバとの互換性を維持するために、アプリケーションにジェネリックな印刷ループを追加する方法とその理由について説明します。

この改訂版の TECHNOTE は、現在の Macintosh Printing Manager の機能を反映しており、PrOpenPrClose を呼び出すことで Macintosh Printing Manager のオープンとクローズを適切に行う方法について説明します。また、アプリケーションが印刷時のエラーを処理する方法や最新のエラーコードの一覧も示します。


印刷処理の古い方法
かつて (System 7 以前)、Appleでは、アプリケーションの起動時に PrOpen を呼び出し、アプリケーションを終了して Finder に戻る前に PrClose を呼び出すことを推奨していました。これは、アプリケーションが 1 つのプリンタドライバだけを取り扱えばよいときには適切な処理といえます。しかし、多くのプリンタが市場に登場するにつれ、アプリケーションの側で、起動中の他のアプリケーションや複数のプリンタドライバの存在を考慮することが重要になりました。

たとえば、ユーザがいつでもセレクタを開くことができ、使用中のアプリケーションの機能とは関係なく、現在のプリンタドライバを変更することができるとしましょう。アプリケーションが古い形式に従っている場合、アプリケーションの実行中に現在のプリンタドライバを変更すると、次に印刷しようとしたときに誤ったドライバがオープンされてしまい、Printing Manager では必要なリソースを見つけることができず、エラーが発生することになります。

この TECHNOTE のオリジナル版では、アプリケーションがこれらの問題を回避するための方法について説明していました。この改訂版では、さらに優れた方法を示します。


新しい方法: C 言語による印刷ループ
次の PrintStuff というコード例では、アプリケーションで使用することが望ましい簡単な印刷ループを示します。この印刷ループは、次のように動作します。

  1. 書類の印刷に必要なすべての Printing Manager 呼び出しを実行します。
  2. それぞれの Printing Manager 呼び出しを実行するたびに PrError をチェックします。
  3. エラーが検出されれば、エラーをポストする前に、オープンしているすべての Printing Manager 呼び出し (つまり、PrOpenPrOpenDoc、...) に対応するクローズ呼び出しを実行します。

ステップ 3 ではエラーチェックを行って、Printing Manager によるクローズが適切であるかどうか、またすべての一時メモリが解放されているかどうかを確認してください。

注意:
現在、Apple Developer Technical Support では、Printing Manager を使用するたびに、アプリケーションがプリンタドライバのオープンとクローズを行うことを推奨しています。また、次のコード例で示すように、適切なエラーチェックを実行することも強く推奨しています。


PrintStuff 印刷ループ




印刷中のエラー条件のチェック
アプリケーションでは、書類の印刷中に常にエラー条件をチェックするようにしてください。この処理は PrError を呼び出して実行できます。PrError は、印刷中に発生する Printing Manager のエラー (および一部の AppleTalk エラーと OS エラー) を返します。

前出のコード例で示したように、Printing Manager の関数またはプロシージャを呼び出すたびに、アプリケーションでは PrError を呼び出す必要があります。呼び出しを実行するたびに一貫して PrError をチェックすることで、アプリケーションは印刷時に発生したエラーを捕捉し、ダイアログボックス経由でアプリケーションのユーザにそれらのエラーをレポートできるようになります。


いくつかの一般的なエラー処理のためのガイドライン
次に、いくつかの一般的なエラー処理を行うためのガイドラインを示します。

pIdle プロシージャの内部では PrError を呼び出さないでください。pIdle プロシージャの実行中に発生するエラーは通常一時的なもので、プリンタドライバ内の通信に対する内部フラグとしてのみ機能します。これらは、アプリケーションに向けられたエラーではありません。アイドルプロシージャの実行中に印刷を中止する必要がある場合は、シグナルを送るためのフラグを自分でセットして、Printing Manager の関数を実行するたびにそのフラグをチェックします。フラグがセットされている場合は、エラーが発生したときとまったく同じ方法で処理を終了することができます。
ある印刷ルーチンの終了後にエラーが検出されたときは、その時点で描画を停止し、次のプロシージャに進んで、それまでにオープンされている呼び出しをクローズします。たとえば、PrOpenDoc を呼び出した後でエラーが検出された場合は、次の PrCloseDoc へスキップします。あるいは、PrOpenPage を呼び出した後でエラーが発生した場合は、次の PrClosePagePrCloseDoc へスキップします。なお、PrOpen を呼び出している場合は、対応する PrClose を呼び出して印刷を適切に終了し、すべての一時的なメモリ割り当てを解放して、ヒープに戻す必要があります。

印刷ループの最後にくるまで、アラートまたはダイアログボックスによるエラーのレポートは行わないでください。ループの最後でもう一度エラーをチェックします。エラーが発生していない場合は、印刷が正常に終了したと見なします。その時点でまだエラーが残っている場合はユーザに警告します。

アラートまたはダイアログボックスを表示しないという、この手続きが重要なのは次の 2 つの理由によります。

  1. 印刷ループの途中でダイアログボックスを表示すると、通常のジョブまで終了させてしまうようなエラーの原因になることがあります。たとえば、プリンタがAppleTalk プリンタである場合は、接続が異常な形で切断されてしまいます。これは、ダイアログボックスがユーザ入力を待っている間、ドライバがプリンタから受信したAppleTalk リクエストに応答できないためです。短時間 (たとえば 30 秒間) にわたってプリンタとMacintosh との間でデータのやり取りができないと、Macintosh が存在しないものと見なされ、印刷ジョブはタイムアウトになってしまいます。その結果、接続が切断され、アプリケーションが応答しなければならない別のエラーが発生してしまいます。

  2. エラーに応答して、ドライバが独自のダイアログボックスを表示することもあります。この場合、ドライバはエラーをポストし、問題が発生したために印刷を中止したことをアプリケーションに"認識" させます。たとえば、LaserWriter ドライバが、ダウンロードされた LaserPrep のバージョンと、ユーザが印刷に使おうとしたバージョンが異なることを検出すると、適切なダイアログボックスが表示されてユーザに状況が通知され、プリンタの再初期化を行うためのオプションが提示されます。ユーザが印刷のキャンセルを選択すると、ドライバはエラーをポストし、印刷を中止する必要があることをアプリケーションに"認識" させます。しかし、ドライバはダイアログボックスを表示することで、すでにエラー処理を行っているため、印刷ループが終了する前にそのエラーはゼロにリセットされています。アプリケーションでは、印刷ループが終了した時点でもう一度エラーをチェックする必要があります。その時点でもまだエラーが残っている場合、アプリケーションは適切なダイアログボックスを表示することができます。


PrGeneral を使っている場合は、NoSuchRslOpNotImpl、およびresNotFound エラーを受け取るための準備をしてください。これら 3 つのエラーが発生した場合、アプリケーションでは、特殊なopcode の機能を使用することなく、印刷を継続する準備を整えておく必要があります。

ただし、resNotFound エラーは、現在のプリンタドライバで PrGeneral がサポートされていないということを意味します。サポートされていないこと自体はアプリケーションにとって問題ではありませんが、アプリケーションではこのエラーを処理する準備を整えておく必要があります。PrError から resNotFound エラーを取得した場合は、PrSetError(0) を呼び出してエラーをクリアします。そうしないと、PrError を次にチェックするまで、PrError にこのエラーが残ってしまい、アプリケーションが印刷できなくなってしまいます。


印刷プロセスのキャンセルまたは一時停止
印刷プロセスを一時停止するオプションを使って、印刷のキャンセルをリクエストするプロシージャをインストールする場合は、印刷にネットワークプリンタを使用するときのタイムアウトの問題に注意してください。Macintosh とネットワークプリンタとの通信は、ジョブまたは待機タイムアウトを防ぐために常時維持されている必要があります。一定の時間 (ほぼ 2 分程度) にわたってデータのやり取りがないと、プリンタはタイムアウトになり、印刷ジョブは待機タイムアウトのために中止されてしまいます。また、印刷を終了するまでに 3 分を超える時間が必要な場合は、ジョブタイムアウトのために印刷ジョブが中止されてしまいます。印刷に使用しているプリンタのタイプを確実に決定する方法が存在しないため、2 分あるいはそれ以上にわたって "一時停止" ボタンを選択していると、ネットワークプリンタのタイムアウトが発生することを、アプリケーションの README ファイルに明記しておくのが最善の方法といえます。


エラーメッセージ
Printing Manager は、ここで説明するエラーメッセージをレポートします。Printing Manager に関係のないエラーが発生すると、Printing Manager ではそのエラーを下位メモリに置き、必要な場合は印刷ループの実行を中止します。下位メモリに置かれたエラーは PrError を呼び出して取得することができます。すでに説明したように、印刷ループの途中でエラーが発生した場合は、ループを抜けずにループの実行が失敗するのを待ち、Printing Manager を適切な形で終了させます。

最も一般的に発生する可能性のあるエラーは -4101 です。このエラーは、選択した LaserWriter がネットワーク上で使用できない場合に発生します。このエラーはかなり頻繁に発生するため、このエラーが発生したときには、セレクタから別のプリンタを選択するよう要求するダイアログボックスを表示するのがよいでしょう。


一般的な Printing Manager エラーとシステムエラー
次に、一般的な Printing Manager エラーとシステムエラーのコードを示します。

エラーコード

定数

説明

0

noErr エラーなし。

28

[不定] スタックまたはヒープで衝突が発生している。QuickDraw の内部であまりにも多くのスタックが使用されている (QT の圧縮画像に対して DrawPicture を呼び出しているときに頻繁に発生する)。

128

iPrAbort 印刷プロセスが中止された (command - ピリオドキーを押して)。

- 1

iPrSavePFil プリントファイルの保存に問題が発生した。

-17

controlErr インプリメントされていないコントロールを呼び出した。

-27

iIOAbort I/O の問題。

-108

iMemFullErr 十分なヒープスペースがない。


PrGeneral のエラー
C 言語では、次のように PrGeneral を宣言します。

pascal void PrGeneral (Ptr pData);

pData パラメータは、TGnlData というレコードに対するポインタです。先頭の 8 バイトには、すべての PrGeneral 呼び出しで共有されるヘッダが含まれています。

struct TGnlData {
   short  iOpCode;
   short  iError;
   long   lReserved;
};

PrGeneral を呼び出すたびに、アプリケーションでは iError フィールドの値をチェックしてください。次に、返される可能性のある結果コードの一覧を示します。

エラーコード

定数

説明

0

noErr エラーなし。

1

NoSuchRsl サポートされていない解像度。

2

OpNotImpl サポートされていない Opcode

-192

resNotfound 現在のプリンタドライバでは PrGeneral はサポートされていない。

PrGeneral の詳細については、Pete 'Luke' Alexander による「develop 3: Meet PrGeneral」を参照してください。


LaserWriter ドライバファミリのエラー

エラーコード

定数

説明

-4101

?/CODE> プリンタが見つからない、またはクローズされている。

-4100

?/CODE> 接続がクローズされた。

-4099

?/CODE> 書き込みリクエストが大きすぎる。

-4098

?/CODE> リクエストはすでにアクティブになっている。

-4097

?/TD> 接続参照番号が不正。

-4096

?/TD> 使用可能な接続コントロールブロック (CCB) がない。


LaserWriter 8 の内部エラー
注意: 次に示すエラーコードは、LaserWriter 8 の内部コードに対応するものです。これらのエラーコードはデバッグには役立ちますが、アプリケーションの実行時にこれらのエラーを解釈したり使用したりすることは絶対に避けてください。

エラーコード

定数

説明

-8998

errNotAKey 目的のフォント番号のキーが見つからなかった。

-8997

errFaceListBad (現在では使用されていません)

-8996

errSizeListBad サイズリストとフェースリストが矛盾していた。

-8995

errFontNotFound フォントクエリーの応答が PostScript フォントのいずれとも一致しなかった。

-8994

errUnknownPSLevel プリンタの PostScript レベルを問い合わせたのに、予期しない回答を取得した。

-8993

errInLineTimeout プリンタからの応答を待ったが、何の応答もない。

-8991

errNoProcSetRes PostScript のプロローグを生成するとき、必要なプロシージャセットを含むリソースを見つけることができなかった。

-8990

errBadSpoolFileVersion フォアグラウンド印刷時に (LW 8.4 以前のバージョンで)、スプールファイルを読み込もうとしたが、ヘッダ情報に問題があった。

-8989

errCouldNotMakeNumberedFilename ベース名に番号を追加して重複のないスプールファイル名を付けることができなかった。番号がすべて使用されている。

-8987

errPSFileName PS をディスクに保存するとき、ファイル名が不正だった。

-8986

errBitmapFontMissing 1 ビットのビットマップを作成しようとしたが失敗した。

-8985

errDidNotDownloadFont PS のアウトラインを見つけることができなかった。'sfnt' リソースが存在しない。

-8984

errBadConverterIndex "ファイルとして保存" ポップアップで選択した項目に一致するエントリを見つけることができなかった。

-8983

errSpoolFolderIsAFile (現在では使用されていません)

-8982

errPSFileNameNull (現在では使用されていません)

-8981

errNullColorInfo NULL ハンドルを使って GetColor が呼び出された。

-8980

errNoPagesSpooled アプリケーションが PrOpenDocPrCloseDoc を呼び出したが、ページが印刷されない。

-8979

errBadConverterID コンバータとして実行しようとした PDEF が存在しなかった。

-8978

errNoPattern pixpat を見つけることができないか、作成することができなかった

-8977

errPSStateUnderFlow 上端のグラフィックのステータスをポップしようとしたが失敗した。

-8976

errChannelNotBinary アプリケーションではバイナリデータを必要としているが (PrGeneral 経由で)、プリンタへの実際のチャネルはバイナリではない。

-8975

errPrinterNotLevel2 アプリケーションでは Level 2 PS を使用しようとしたが、プリンタが Level 2 に対応していない。

-8974

errBadFontKeyType フォントのタイプが PS、TT、またはビットマップではなかった。

-8973

errFunctionNotAvailable (現在では使用されていません)

-8972

errNULLFormatString printf 類似の内部関数に渡された書式文字列が null だった。

-8971

errNotAFolderAlias "プリントモニタ書類" フォルダをポイントするはずのエイリアスがフォルダをポイントしていない。

-8970

errMissingPAPA 検索していた PAPA リソースが見つからない。

-8969

errMissingPrinterInfo 現在のプリンタはプリンタデータベース内にエントリを持っていない。通常、プリンタがセットアップされていないために発生する。

-8968

errUnsupportedDestColorMode 出力カラースペースがサポートされていない。

-8967

errUnknownColorUsage (現在では使用されていません)

-8966

errUnsupportedCodec 圧縮された pixmap では、取り扱うことのできない codec を必要としている。

-8965

errInvalidPPD PPD をオープンしようとしたがオープンできなかった。

-8964

errBadColorSync2Comment ColorSync2 PicComment では 4 バイトのセレクタを要求しているが、4 バイトよりも小さなデータサイズしか見つからない。

-8963

errBadFlattenRefCon フラットプロシージャの中で、ColorSync から NULL refcon が返された。

-8962

errGlyphsDontFit 1 つの字体が 4 バイトの境界で終わっていない (フォントのバグ)、あるいはサイズが 64K を超えている。

-8961

errGenericComponentErr ジェネリックエラー

-8960

errUnsupportedStream 指定されたライブラリ呼び出しに渡された PSStream のデータ型がサポートされていない。

-8959

errProfileNotInList 内部のテンポラリプロファイルリストが不正だった。

-8958

errUninitializedPort ポートが初期化されていない。

-8957

errHintWrongSize コンバータのヒントのいずれかが予期しないサイズだった。

-8956

errSystemProfileNotFound ColorSync を使おうとしたが、デフォルトのシステム特性が見つからなかった。

-8955

errCFM_EnablerNotPresent CFM-68K を使おうとしたが、適切なイネーブラが存在しなかった。

-8954

errCouldNotIDArchitecture ?/TD>

-8953

errPSStreamNullOutProc 出力ルーチンに対する不正な関数ポインタを取得した。

-8952

errTriedToWriteNullBuffer このようなエラーは起こるはずがない。

-8951

errWhoTookThatOutBuffer いっぱいになっているバッファがあるが、このバッファが不正である。

-8950

errMoreDataToFlush 処理すべきデータがまだ残っている。

-8160

zoomRangeErr ?/TD>

-8152

noPrepErr ?/TD>

-8151

prepMismatchErr ?/TD>

-8150

noChosenPrinterErr ?/TD>

-8133

generalPSErr データをプリンタに転送するときに PostScript エラーが発生した。このエラーの大部分は、ダウンロードされた PostScript コードのバグによって発生する。

-8132

manualFeedTOErr タイムアウトが発生した。

-8131

?/CODE> プリンタが応答しない。




要約
これ以上、特に付け加えることはありません。このTECHNOTEで説明したルールに従ってエラーメッセージを適切に処理すれば、アプリケーションは Macintosh Printing Manager を使って正常に印刷することができるはずです。

参考文献
Inside Macintosh: Imaging With QuickDraw, Chapter 9
StdFileSaver サンプルコード (Developer CD Series: Tool Chest Edition に収録)
Technote PR02- Device-Independent Printing by Ginger Jernigan
develop 3- Meet PrGeneral, the Trap That Makes the Most of the Printing Manager by Pete "Luke" Alexander.
develop 27 - Print Hints: The All-New LaserWriter Driver Version 8.4 by Dave Polaschek.

改訂の履歴
初版は、1990 年 10 月に「Technote PR10 -- A Printing Loop That Cares...」というタイトルで Ginger Jernigan と Pete "Luke" Alexander によって書かれました。

1994 年 1 月に「Technote PR10 -- A Printing Loop That Cares...」というタイトルで Matt Deatherage によって改訂されました。

本文中のコードは、Ginger Jernigan (1990)、Pete "Luke" Alexander (1990)、および Matt Deatherage (1994) によって書かれ、また改訂されました。

1997 年 1 月、現在の Macintosh Printing Manager の機能を反映させ、C 言語のコードを使用するために、この TECHNOTE は更新されました。これまでの Pascal のコードは削除されています。また、「エラーメッセージ」のセクションには、更新されたエラーコードが追加されています。