1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            M   M   AAA    CCCC                              %
7 %                            MM MM  A   A  C                                  %
8 %                            M M M  AAAAA  C                                  %
9 %                            M   M  A   A  C                                  %
10 %                            M   M  A   A   CCCC                              %
11 %                                                                             %
12 %                                                                             %
13 %                    Macintosh Utility Methods for MagickCore                 %
14 %                                                                             %
15 %                               Software Design                               %
16 %                                    Cristy                                   %
17 %                                September 1996                               %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %  The directory methods are strongly based on similar methods written
37 %  by Steve Summit, scs@eskimo.com.  The Ghostscript launch code is strongly
38 %  based on Dave Schooley's Mac Gnuplot and contributed by
39 %  schindall@wave14i.nrl.navy.mil.  Mac-centric improvements contributed by
40 %  leonardr@digapp.com.
41 %
42 %
43 */
44 
45 #if defined(macintosh)
46 /*
47   Include declarations.
48 */
49 #define _X_H
50 #define _WIDGET_H
51 #include <AppleEvents.h>
52 #include <AERegistry.h>
53 #include <AEObjects.h>
54 #include <AEPackObject.h>
55 #include <Processes.h>
56 #include <QuickDraw.h>
57 #include <QDOffscreen.h>
58 #include <Palettes.h>
59 #include <ImageCompression.h>
60 #include <PictUtils.h>
61 #include <Files.h>
62 #include <Gestalt.h>
63 #include <TextUtils.h>
64 #define ColorInfo  KolorInfo
65 #include "magick/studio.h"
66 #include "magick/blob.h"
67 #include "magick/client.h"
68 #include "magick/exception.h"
69 #include "magick/exception-private.h"
70 #include "magick/image-private.h"
71 #include "magick/list.h"
72 #include "magick/magick.h"
73 #include "magick/monitor.h"
74 #include "magick/monitor-private.h"
75 #include "magick/pixel-accessor.h"
76 #include "magick/quantum.h"
77 #include "magick/string_.h"
78 #include "magick/utility.h"
79 #include "magick/mac.h"
80 
81 /*
82   Global declaractions.
83 */
84 ImageDescriptionHandle
85   image_description = nil;
86 
87 /*
88   Forward declaractions.
89 */
90 static Boolean
91   SearchForFile(OSType,OSType,FSSpec *,short);
92 
93 static pascal void
94   ArcMethod(GrafVerb,Rect *,short,short),
95   BitsMethod(BitMap *,Rect *,Rect *,short,RgnHandle),
96   FilenameToFSSpec(const char *filename,FSSpec *fsspec),
97   LineMethod(Point),
98   OvalMethod(GrafVerb,Rect *),
99   PolyMethod(GrafVerb,PolyHandle),
100   RRectMethod(GrafVerb,Rect *,short,short),
101   RectMethod(GrafVerb,Rect *),
102   RegionMethod(GrafVerb,RgnHandle),
103   StandardPixmap(PixMapPtr,Rect *,MatrixRecordPtr,short,RgnHandle,PixMapPtr,
104     Rect *,short),
105   TextMethod(short,Ptr,Point,Point);
106 
107 /*
108   Static declarations
109  */
110 #if defined(DISABLE_SIOUX)
111 static MACEventHookPtr
112   event_hook = nil;
113 
114 static MACErrorHookPtr
115   exception.hook = nil;
116 #endif
117 
118 /*
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 %                                                                             %
121 %                                                                             %
122 %                                                                             %
123 %   B o t t l e n e c k T e s t                                               %
124 %                                                                             %
125 %                                                                             %
126 %                                                                             %
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 %
129 %  BottleneckTest() intercepts any compressed images.
130 %
131 %  The format of the BottleneckTest method is:
132 %
133 %      int BottleneckTest(const char *magick)
134 %
135 %  A description of each parameter follows:
136 %
137 %    o picture: Specifies a pointer to a PicHandle structure.
138 %
139 %    o codec: the code type is returned in this CodecType pointer structure.
140 %
141 %    o depth: the image depth is returned as an integer pointer.
142 %
143 %    o colormap_id: the colormap ID is returned in this short pointer.
144 %
145 %
146 */
147 
ArcMethod(GrafVerb verb,Rect * r,short startAngle,short arcAngle)148 static pascal void ArcMethod(GrafVerb verb,Rect *r,short startAngle,
149   short arcAngle)
150 {
151 #pragma unused (verb,r,startAngle,arcAngle)
152 }
153 
BitsMethod(BitMap * bitPtr,Rect * source_rectangle,Rect * dstRect,short mode,RgnHandle maskRgn)154 static pascal void BitsMethod(BitMap *bitPtr,Rect *source_rectangle,
155   Rect *dstRect,short mode,RgnHandle maskRgn)
156 {
157 #pragma unused (bitPtr,source_rectangle,dstRect,mode,maskRgn)
158 }
159 
LineMethod(Point newPt)160 static pascal void LineMethod(Point newPt)
161 {
162 #pragma unused (newPt)
163 }
164 
OvalMethod(GrafVerb verb,Rect * r)165 static pascal void OvalMethod(GrafVerb verb,Rect *r)
166 {
167 #pragma unused (verb,r)
168 }
169 
PolyMethod(GrafVerb verb,PolyHandle poly)170 static pascal void PolyMethod(GrafVerb verb,PolyHandle poly)
171 {
172 #pragma unused (verb,poly)
173 }
174 
RectMethod(GrafVerb verb,Rect * r)175 static pascal void RectMethod(GrafVerb verb,Rect *r)
176 {
177 #pragma unused (verb,r)
178 }
179 
RegionMethod(GrafVerb verb,RgnHandle rgn)180 static pascal void RegionMethod(GrafVerb verb,RgnHandle rgn)
181 {
182 #pragma unused (verb,rgn)
183 }
184 
RRectMethod(GrafVerb verb,Rect * r,short ovalWidth,short ovalHeight)185 static pascal void RRectMethod(GrafVerb verb,Rect *r,short ovalWidth,
186   short ovalHeight)
187 {
188 #pragma unused (verb,r,ovalWidth,ovalHeight)
189 }
190 
StandardPixmap(PixMapPtr source,Rect * source_rectangle,MatrixRecordPtr matrix,short mode,RgnHandle mask,PixMapPtr matte,Rect * matte_rectangle,short flags)191 static pascal void StandardPixmap(PixMapPtr source,Rect *source_rectangle,
192   MatrixRecordPtr matrix,short mode,RgnHandle mask,PixMapPtr matte,
193   Rect *matte_rectangle,short flags)
194 {
195 #pragma unused (source_rectangle,matrix,mode,mask,matte,matte_rectangle,flags)
196 
197   Ptr
198     data;
199 
200   ssize_t
201     size;
202 
203   GetCompressedPixMapInfo(source,&image_description,&data,&size,nil,nil);
204 }
205 
TextMethod(short byteCount,Ptr textBuf,Point numer,Point denom)206 static pascal void TextMethod(short byteCount,Ptr textBuf,Point numer,
207   Point denom)
208 {
209 #pragma unused (byteCount,textBuf,numer,denom)
210 }
211 
212 #if !defined(DISABLE_QUICKTIME)
BottleneckTest(PicHandle picture,CodecType * codec,int * depth,short * colormap_id)213 static short BottleneckTest(PicHandle picture,CodecType *codec,int *depth,
214   short *colormap_id)
215 {
216   CQDProcs
217     bottlenecks;
218 
219   int
220     status;
221 
222   Rect
223     rectangle;
224 
225   ssize_t
226     version;
227 
228   status=Gestalt(gestaltQuickTime,&version);
229   if (status != noErr)
230     {
231       ParamText("\pQuickTime not installed.  Please install, then try again.",
232         "\p","\p","\p");
233       Alert(128,nil);
234       return(-1);
235     }
236   /*
237     Define our own bottlenecks to do nothing.
238   */
239   SetStdCProcs(&bottlenecks);
240   bottlenecks.textProc=NewQDTextUPP(&TextMethod);
241   bottlenecks.lineProc=NewQDLineUPP(&LineMethod);
242   bottlenecks.rectProc=NewQDRectUPP(&RectMethod);
243   bottlenecks.rRectProc=NewQDRRectUPP(&RRectMethod);
244   bottlenecks.ovalProc=NewQDOvalUPP(&OvalMethod);
245   bottlenecks.arcProc=NewQDArcUPP(&ArcMethod);
246   bottlenecks.polyProc=NewQDPolyUPP(&PolyMethod);
247   bottlenecks.rgnProc=NewQDRgnUPP(&RegionMethod);
248   bottlenecks.bitsProc=NewQDBitsUPP(&BitsMethod);
249   bottlenecks.newProc1=(UniversalProcPtr) NewStdPixUPP(&StandardPixmap);
250   /*
251     Install our custom bottlenecks to intercept any compressed images.
252   */
253   (*(qd.thePort)).grafProcs=(QDProcs *) &bottlenecks;
254   DrawPicture(picture,&((**picture).picFrame));
255   PaintRect(&rectangle);
256   (*(qd.thePort)).grafProcs=0L;
257   /*
258     Initialize our return values.
259   */
260   *codec='unkn';
261   *depth=0;
262   *colormap_id=(-1);
263   if (image_description != nil)
264     {
265       *codec=(**image_description).cType;
266       *depth=(**image_description).depth;
267       *colormap_id=(**image_description).clutID;
268     }
269   DisposeQDTextUPP(bottlenecks.textProc);
270   DisposeQDLineUPP(bottlenecks.lineProc);
271   DisposeQDRectUPP(bottlenecks.rectProc);
272   DisposeQDRRectUPP(bottlenecks.rRectProc);
273   DisposeQDOvalUPP(bottlenecks.ovalProc);
274   DisposeQDArcUPP(bottlenecks.arcProc);
275   DisposeQDPolyUPP(bottlenecks.polyProc);
276   DisposeQDRgnUPP(bottlenecks.rgnProc);
277   DisposeQDBitsUPP(bottlenecks.bitsProc);
278   DisposeStdPixUPP(bottlenecks.newProc1);
279   return(0);
280 }
281 #endif
282 
283 #if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
284 /*
285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286 %                                                                             %
287 %                                                                             %
288 %                                                                             %
289 %   c l o s e d i r                                                           %
290 %                                                                             %
291 %                                                                             %
292 %                                                                             %
293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294 %
295 %  closedir() closes the named directory stream and frees the DIR structure.
296 %
297 %  The format of the closedir method is:
298 %
299 %      closedir(entry)
300 %
301 %  A description of each parameter follows:
302 %
303 %    o entry: Specifies a pointer to a DIR structure.
304 %
305 %
306 */
closedir(DIR * entry)307 MagickExport void closedir(DIR *entry)
308 {
309   if (image->debug != MagickFalse)
310     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
311   assert(entry != (DIR *) NULL);
312   RelinquishMagickMemory(entry);
313 }
314 #endif
315 
316 /*
317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 %                                                                             %
319 %                                                                             %
320 %                                                                             %
321 %   E x i t                                                                   %
322 %                                                                             %
323 %                                                                             %
324 %                                                                             %
325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 %
327 %  Exit() exits the process.
328 %
329 %  The format of the exit method is:
330 %
331 %      Exit(status)
332 %
333 %  A description of each parameter follows:
334 %
335 %    o status: an integer value representing the status of the terminating
336 %      process.
337 %
338 %
339 */
Exit(int status)340 MagickExport int Exit(int status)
341 {
342 #if !defined(DISABLE_SIOUX)
343   (void) FormatLocaleFile(stdout,"Select File->Quit to exit.\n");
344 #endif
345   exit(status);
346   return(0);
347 }
348 
349 /*
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
351 %                                                                             %
352 %                                                                             %
353 %                                                                             %
354 %   F i l e n a m e T o F S S p e c                                           %
355 %                                                                             %
356 %                                                                             %
357 %                                                                             %
358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359 %
360 %  FilenameToFSSpec() sets the file type of an image.
361 %
362 %  The format of the FilenameToFSSpec method is:
363 %
364 %      FilenameToFSSpec(filename,fsspec)
365 %
366 %  A description of each parameter follows:
367 %
368 %    o filename: Specifies the name of the file.
369 %
370 %    o fsspec: A pointer to type FSSpec.
371 %
372 %
373 */
FilenameToFSSpec(const char * filename,FSSpec * fsspec)374 MagickExport void pascal FilenameToFSSpec(const char *filename,FSSpec *fsspec)
375 {
376   Str255
377     name;
378 
379   assert(filename != (char *) NULL);
380   c2pstrcpy(name,filename);
381   FSMakeFSSpec(0,0,name,fsspec);
382 }
383 
384 /*
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386 %                                                                             %
387 %                                                                             %
388 %                                                                             %
389 %   I s M a g i c k C o n f l i c t                                           %
390 %                                                                             %
391 %                                                                             %
392 %                                                                             %
393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394 %
395 %  MACIsMagickConflict() returns true if the image format conflicts with a
396 %  logical drive (.e.g. X:).
397 %
398 %  Contributed by Mark Gavin of Digital Applications, Inc.
399 %
400 %  The format of the MACIsMagickConflict method is:
401 %
402 %      status=MACIsMagickConflict(magick)
403 %
404 %  A description of each parameter follows:
405 %
406 %    o magick: Specifies the image format.
407 %
408 %
409 */
410 
HGetVInfo(short volume_index,StringPtr volume_name,short * volume,size_t * free_bytes,size_t * total_bytes)411 static OSErr HGetVInfo(short volume_index,StringPtr volume_name,short *volume,
412   size_t *free_bytes,size_t *total_bytes)
413 {
414   HParamBlockRec
415     pb;
416 
417   OSErr
418     result;
419 
420   size_t
421     blocksize;
422 
423   unsigned short
424     allocation_blocks,
425     free_blocks;
426 
427   /*
428     Use the File Manager to get the real vRefNum.
429   */
430   pb.volumeParam.ioVRefNum=0;
431   pb.volumeParam.ioNamePtr=volume_name;
432   pb.volumeParam.ioVolIndex=volume_index;
433   result=PBHGetVInfoSync(&pb);
434   if (result != noErr)
435     return(result);
436   *volume=pb.volumeParam.ioVRefNum;
437   blocksize=(size_t) pb.volumeParam.ioVAlBlkSiz;
438   allocation_blocks=(unsigned short) pb.volumeParam.ioVNmAlBlks;
439   free_blocks=(unsigned short) pb.volumeParam.ioVFrBlk;
440   *free_bytes=free_blocks*blocksize;
441   *total_bytes=allocation_blocks*blocksize;
442   return(result);
443 }
444 
MACIsMagickConflict(const char * magick)445 MagickExport MagickBooleanType MACIsMagickConflict(const char *magick)
446 {
447   size_t
448     free_bytes,
449     number_bytes;
450 
451   OSErr
452     status;
453 
454   short
455     volume;
456 
457   Str255
458     volume_name;
459 
460   assert(magick != (char *) NULL);
461   if (image->debug != MagickFalse)
462     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",magick);
463   (void) CopyMagickString((char *) volume_name,magick,MaxTextExtent);
464   c2pstr((char *) volume_name);
465   if (volume_name[volume_name[0]] != ':')
466     volume_name[++volume_name[0]]=':';
467   status=HGetVInfo(-1,volume_name,&volume,&free_bytes,&number_bytes);
468   return(status != 0 ? MagickFalse : MagickTrue);
469 }
470 
471 /*
472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473 %                                                                             %
474 %                                                                             %
475 %                                                                             %
476 +   M A C E r r o r H a n d l e r                                             %
477 %                                                                             %
478 %                                                                             %
479 %                                                                             %
480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 %
482 %  MACErrorHandler() displays an error reason and then terminates the program.
483 %
484 %  The format of the MACErrorHandler method is:
485 %
486 %      void MACErrorHandler(const ExceptionType error,const char *reason,
487 %        const char *description)
488 %
489 %  A description of each parameter follows:
490 %
491 %    o exception: Specifies the numeric error category.
492 %
493 %    o reason: Specifies the reason to display before terminating the
494 %      program.
495 %
496 %    o description: Specifies any description to the reason.
497 %
498 %
499 */
MACErrorHandler(const ExceptionType error,const char * reason,const char * description)500 MagickExport void MACErrorHandler(const ExceptionType error,const char *reason,
501   const char *description)
502 {
503   char
504     buffer[3*MaxTextExtent];
505 
506   if (reason == (char *) NULL)
507     return;
508   if (description == (char *) NULL)
509     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
510       reason);
511   else
512     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
513       GetClientName(),reason,description);
514 #if defined(DISABLE_SIOUX)
515   if(exception.hook != (MACErrorHookPtr) NULL)
516     exception.hook(error,buffer);
517   else
518     {
519       MagickCoreTerminus();
520       exit(error);
521     }
522 #else
523   puts(buffer);
524   MagickCoreTerminus();
525   exit(error);
526 #endif
527 }
528 
529 #if defined(DISABLE_SIOUX)
530 /*
531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532 %                                                                             %
533 %                                                                             %
534 %                                                                             %
535 +   M A C F a t a l E r r o r H a n d l e r                                   %
536 %                                                                             %
537 %                                                                             %
538 %                                                                             %
539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
540 %
541 %  MACFatalErrorHandler() displays an error reason and then terminates the
542 %  program.
543 %
544 %  The format of the MACFatalErrorHandler method is:
545 %
546 %      void MACFatalErrorHandler(const ExceptionType severity,
547 %        const char *reason,const char *description)
548 %
549 %  A description of each parameter follows:
550 %
551 %    o severity: Specifies the numeric error category.
552 %
553 %    o reason: Specifies the reason to display before terminating the
554 %      program.
555 %
556 %    o description: Specifies any description to the reason.
557 %
558 */
MACFatalErrorHandler(const ExceptionType severity,const char * reason,const char * description)559 static void MACFatalErrorHandler(const ExceptionType severity,
560   const char *reason,const char *description)
561 {
562   char
563     buffer[3*MaxTextExtent];
564 
565   if (reason == (char *) NULL)
566     return;
567   if (description == (char *) NULL)
568     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
569       reason);
570   else
571     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
572       GetClientName(),reason,description);
573   if(exception.hook != (MACErrorHookPtr) NULL)
574     exception.hook(severity, buffer);
575   else
576     {
577       MagickCoreTerminus();
578       exit(severity);
579     }
580 }
581 #endif
582 
583 /*
584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585 %                                                                             %
586 %                                                                             %
587 %                                                                             %
588 %   M a c G S E x e c u t e C o m m a n d                                     %
589 %                                                                             %
590 %                                                                             %
591 %                                                                             %
592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 %
594 %  MacGSExecuteCommand() executes the Ghostscript command.
595 %
596 %
597 */
MacGSExecuteCommand(const char * command,ssize_t length)598 static OSErr MacGSExecuteCommand(const char *command,ssize_t length)
599 {
600   AEAddressDesc
601     event_descriptor;
602 
603   AEDesc
604     reply = {typeNull, NULL};
605 
606   AppleEvent
607     event = {typeNull, NULL};
608 
609   DescType
610     descriptor_type;
611 
612   int
613     error;
614 
615   OSType
616     id = 'gsVR';
617 
618   Size
619     actualSize;
620 
621   /*
622     Send the Apple Event.
623   */
624   (void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
625   (void) AECreateAppleEvent(id,'exec',&event_descriptor,-1,kAnyTransactionID,
626     &event);
627   (void) AEPutParamPtr(&event,keyDirectObject,typeChar,command,length);
628   (void) AESend(&event,&reply,kAEWaitReply+kAENeverInteract,kAENormalPriority,
629     kNoTimeOut,NULL,NULL);
630   /*
631     Handle the reply and exit.
632   */
633   (void) AEGetParamPtr(&reply,keyDirectObject,typeInteger,&descriptor_type,
634     &error,sizeof(error),&actualSize);
635   (void) AEDisposeDesc(&event_descriptor);
636   (void) AEDisposeDesc(&event);
637   if (reply.descriptorType != NULL)
638     AEDisposeDesc(&reply);
639   return((OSErr) error);
640 }
641 
642 /*
643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 %                                                                             %
645 %                                                                             %
646 %                                                                             %
647 %   M a c G S L a u n c h A p p l i c a t i o n C o r e                       %
648 %                                                                             %
649 %                                                                             %
650 %                                                                             %
651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 %
653 %  MacGSLaunchApplicationCore() launches the Ghostscript command.
654 %
655 %
656 */
MacGSLaunchApplicationCore(ssize_t flags)657 static OSErr MacGSLaunchApplicationCore(ssize_t flags)
658 {
659   FSSpec
660     file_info;
661 
662   LaunchParamBlockRec
663     launch_info;
664 
665   OSErr
666     error;
667 
668   if (!SearchForFile('gsVR','APPL',&file_info,1))
669     return(-43);
670   launch_info.launchBlockID=extendedBlock;
671   launch_info.launchEPBLength=extendedBlockLen;
672   launch_info.launchFileFlags=0;
673   launch_info.launchControlFlags=launchContinue+launchNoFileFlags+flags;
674   launch_info.launchAppSpec=(&file_info);
675   launch_info.launchAppParameters=nil;
676   error=LaunchApplication(&launch_info);
677   return(error);
678 }
679 
680 /*
681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682 %                                                                             %
683 %                                                                             %
684 %                                                                             %
685 %   M a c G S L a u n c h A p p l i c a t i o n                               %
686 %                                                                             %
687 %                                                                             %
688 %                                                                             %
689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 %
691 %  MacGSLaunchApplication() launches the Ghostscript command.
692 %
693 %
694 */
MacGSLaunchApplication(void)695 static OSErr MacGSLaunchApplication(void)
696 {
697   return(MacGSLaunchApplicationCore(launchDontSwitch));
698 }
699 
700 /*
701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702 %                                                                             %
703 %                                                                             %
704 %                                                                             %
705 %   M a c G S L a u n c h A p p l i c a t i o n T o F r o n t                 %
706 %                                                                             %
707 %                                                                             %
708 %                                                                             %
709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710 %
711 %  MacGSLaunchApplicationToFront() moves the Ghostscript window to the front.
712 %
713 %
714 */
MacGSLaunchApplicationToFront(void)715 static OSErr MacGSLaunchApplicationToFront(void)
716 {
717   return(MacGSLaunchApplicationCore(0));
718 }
719 
720 /*
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 %                                                                             %
723 %                                                                             %
724 %                                                                             %
725 %   M a c G S Q u i t A p p l i c a t i o n                                   %
726 %                                                                             %
727 %                                                                             %
728 %                                                                             %
729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730 %
731 %  MacGSQuitApplication() quits the Ghostscript application.
732 %
733 %
734 */
MacGSQuitApplication(void)735 static void MacGSQuitApplication(void)
736 {
737   AEAddressDesc
738     event_descriptor;
739 
740   AEDesc
741     reply = {typeNull, NULL};
742 
743   AppleEvent
744     event = {typeNull, NULL};
745 
746   OSType
747     id = 'GPLT';
748 
749   /*
750     Send the Apple Event.
751   */
752   (void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
753   (void) AECreateAppleEvent(typeAppleEvent,kAEQuitApplication,
754     &event_descriptor,-1,kAnyTransactionID,&event);
755   (void) AESend(&event,&reply,kAENoReply,kAENormalPriority,kNoTimeOut,NULL,
756     NULL);
757   /*
758     Clean up and exit.
759   */
760   (void) AEDisposeDesc(&event_descriptor);
761   (void) AEDisposeDesc(&event);
762   if (reply.descriptorType != NULL)
763     AEDisposeDesc(&reply);
764 }
765 
766 /*
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768 %                                                                             %
769 %                                                                             %
770 %                                                                             %
771 %   M a c G S S e t W o r k i n g F o l d e r                                 %
772 %                                                                             %
773 %                                                                             %
774 %                                                                             %
775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776 %
777 %  MacGSSetWorkingFolder() set the Ghostscript working folder.
778 %
779 %
780 */
MacGSSetWorkingFolder(char * directory)781 static OSErr MacGSSetWorkingFolder(char *directory)
782 {
783   AEDesc
784     application_descriptor,
785     event_descriptor,
786     object,
787     path_descriptor,
788     type_descriptor,
789     reply;
790 
791   AppleEvent
792     event;
793 
794   DescType
795     folder_type = 'wfdr';
796 
797   OSErr
798     error;
799 
800   OSType
801     id = 'GPLT';
802 
803   /*
804     Send the Apple Event.
805   */
806   AECreateDesc(typeNull,NULL,0,&application_descriptor);
807   AECreateDesc(typeChar,directory,strlen(directory),&path_descriptor);
808   (void) AECreateDesc(typeType,&folder_type,sizeof(DescType),&type_descriptor);
809   CreateObjSpecifier(cProperty,&application_descriptor,formPropertyID,
810     &type_descriptor,0,&object);
811   (void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
812   (void) AECreateAppleEvent(kAECoreSuite,kAESetData,&event_descriptor,-1,
813     kAnyTransactionID,&event);
814   (void) AEPutParamDesc(&event,keyDirectObject,&object);
815   (void) AEPutParamDesc(&event,keyAEData,&path_descriptor);
816   error=AESend(&event,&reply,kAENoReply+kAENeverInteract,kAENormalPriority,
817     kNoTimeOut,NULL,NULL);
818   (void) AEDisposeDesc(&event);
819   (void) AEDisposeDesc(&event_descriptor);
820   (void) AEDisposeDesc(&object);
821   (void) AEDisposeDesc(&type_descriptor);
822   (void) AEDisposeDesc(&path_descriptor);
823   (void) AEDisposeDesc(&application_descriptor);
824   return(error);
825 }
826 
827 /*
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 %                                                                             %
830 %                                                                             %
831 %                                                                             %
832 %   M A C S e t E r r o r H o o k                                             %
833 %                                                                             %
834 %                                                                             %
835 %                                                                             %
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 %
838 %   MACSetErrorHook sets a callback function which is called if any error
839 %   occurs within ImageMagick.
840 %
841 %  The format of the MACSetErrorHook method is:
842 %
843 %      int MACSetErrorHook(MACErrorHookPtr hook)
844 %
845 %  A description of each parameter follows:
846 %
847 %    o hook: This function pointer is the callback function.
848 %
849 %
850 */
MACSetErrorHook(MACErrorHookPtr hook)851 MagickExport void MACSetErrorHook(MACErrorHookPtr hook)
852 {
853   /*
854     We forget any previously set exception.hook.
855   */
856   exception.hook=hook;
857 }
858 
859 /*
860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861 %                                                                             %
862 %                                                                             %
863 %                                                                             %
864 %   M A C S e t E v e n t H o o k                                             %
865 %                                                                             %
866 %                                                                             %
867 %                                                                             %
868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869 %
870 %   MACSetEventHook sets a callback function which is called every time
871 %   ImageMagick likes to release the processor.
872 %
873 %  The format of the MACSetEventHook method is:
874 %
875 %      int MACSetEventHook(MACEventHookPtr hook)
876 %
877 %  A description of each parameter follows:
878 %
879 %    o hook: This function pointer is the callback function.
880 %
881 %
882 */
MACSetEventHook(MACEventHookPtr hook)883 MagickExport void MACSetEventHook(MACEventHookPtr hook)
884 {
885   /*
886     We forget any previously set event hook.
887    */
888   event_hook=hook;
889 }
890 
891 /*
892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
893 %                                                                             %
894 %                                                                             %
895 %                                                                             %
896 %   M A C S y s t e m C o m m a n d                                           %
897 %                                                                             %
898 %                                                                             %
899 %                                                                             %
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 %
902 %   Method MACSystemCommand executes the specified command and waits until it
903 %   terminates.  The returned value is the exit status of the command.
904 %
905 %  The format of the MACSystemCommand method is:
906 %
907 %      int MACSystemCommand(MagickFalse,const char * command)
908 %
909 %  A description of each parameter follows:
910 %
911 %    o command: This string is the command to execute.
912 %
913 */
MACSystemCommand(const char * command)914 MagickExport int MACSystemCommand(const char * command)
915 {
916   /*
917     We only know how to launch Ghostscript.
918   */
919   if (MacGSLaunchApplicationToFront())
920     return(-1);
921   return(MacGSExecuteCommand(command,strlen(command)));
922 }
923 
924 /*
925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
926 %                                                                             %
927 %                                                                             %
928 %                                                                             %
929 %   M A C W a r n i n g H a n d l e r                                         %
930 %                                                                             %
931 %                                                                             %
932 %                                                                             %
933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 %
935 %  MACWarningHandler() displays a warning reason.
936 %
937 %  The format of the MACWarningHandler method is:
938 %
939 +      void MACWarningHandler(const ExceptionType warning,const char *reason,
940 %        const char *description)
941 %
942 %  A description of each parameter follows:
943 %
944 %    o warning: Specifies the numeric warning category.
945 %
946 %    o reason: Specifies the reason to display before terminating the
947 %      program.
948 %
949 %    o description: Specifies any description to the reason.
950 %
951 %
952 */
MACWarningHandler(const ExceptionType warning,const char * reason,const char * description)953 MagickExport void MACWarningHandler(const ExceptionType warning,
954   const char *reason,const char *description)
955 {
956   char
957     buffer[1664];
958 
959   if (reason == (char *) NULL)
960     return;
961   if (description == (char *) NULL)
962     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
963       reason);
964   else
965     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
966       GetClientName(),reason,description);
967 #if defined(DISABLE_SIOUX)
968   if(exception.hook != (MACErrorHookPtr) NULL)
969     exception.hook(warning, buffer);
970 #else
971   (void)warning;
972   puts(buffer);
973 #endif
974 }
975 
976 #if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
977 /*
978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979 %                                                                             %
980 %                                                                             %
981 %                                                                             %
982 %   o p e n d i r                                                             %
983 %                                                                             %
984 %                                                                             %
985 %                                                                             %
986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987 %
988 %  opendir() opens the directory named by filename and associates a directory
989 %  stream with it.
990 %
991 %  The format of the opendir method is:
992 %
993 %      MagickExport DIR *opendir(char *path)
994 %
995 %  A description of each parameter follows:
996 %
997 %    o entry: Specifies a pointer to a DIR structure.
998 %
999 %
1000 */
opendir(const char * path)1001 MagickExport DIR *opendir(const char *path)
1002 {
1003   Str255 pathname;
1004 
1005   CInfoPBRec
1006     search_info;
1007 
1008   DIR
1009     *entry;
1010 
1011   int
1012     error;
1013 
1014   search_info.hFileInfo.ioNamePtr=0;
1015   if ((path != (char *) NULL) || (*path != '\0'))
1016     if ((path[0] != '.') || (path[1] != '\0'))
1017       {
1018         c2pstrcpy(pathname,path);
1019         search_info.hFileInfo.ioNamePtr=pathname;
1020       }
1021   search_info.hFileInfo.ioCompletion=0;
1022   search_info.hFileInfo.ioVRefNum=0;
1023   search_info.hFileInfo.ioFDirIndex=0;
1024   search_info.hFileInfo.ioDirID=0;
1025   error=PBGetCatInfoSync(&search_info);
1026   if (error != noErr)
1027     {
1028       errno=error;
1029       return((DIR *) NULL);
1030     }
1031   entry=(DIR *) AcquireMagickMemory(sizeof(DIR));
1032   if (entry == (DIR *) NULL)
1033     return((DIR *) NULL);
1034   entry->d_VRefNum=search_info.hFileInfo.ioVRefNum;
1035   entry->d_DirID=search_info.hFileInfo.ioDirID;
1036   entry->d_index=1;
1037   return(entry);
1038 }
1039 #endif
1040 
1041 /*
1042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043 %                                                                             %
1044 %                                                                             %
1045 %                                                                             %
1046 %   P r o c e s s P e n d i n g E v e n t s                                   %
1047 %                                                                             %
1048 %                                                                             %
1049 %                                                                             %
1050 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1051 %
1052 %  ProcessPendingEvents() processes any pending events.  This prevents
1053 %  ImageMagick from monopolizing the processor.
1054 %
1055 %  The format of the ProcessPendingEvents method is:
1056 %
1057 %      ProcessPendingEvents(text)
1058 %
1059 %  A description of each parameter follows:
1060 %
1061 %    o text: A character string representing the current process.
1062 %
1063 %
1064 */
ProcessPendingEvents(const char * text)1065 MagickExport void ProcessPendingEvents(const char *text)
1066 {
1067 #if defined(DISABLE_SIOUX)
1068   if (event_hook != (MACEventHookPtr) NULL)
1069     event_hook(text);
1070 #else
1071   static const char
1072     *mark = (char *) NULL;
1073 
1074   EventRecord
1075     event;
1076 
1077   while (WaitNextEvent(everyEvent,&event,0L,nil))
1078     SIOUXHandleOneEvent(&event);
1079   if (isatty(STDIN_FILENO) && (text != mark))
1080     {
1081       (void) puts(text);
1082       mark=text;
1083     }
1084 #endif
1085 }
1086 
1087 #if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
1088 /*
1089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1090 %                                                                             %
1091 %                                                                             %
1092 %                                                                             %
1093 %   r e a d d i r                                                             %
1094 %                                                                             %
1095 %                                                                             %
1096 %                                                                             %
1097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098 %
1099 %  readdir() returns a pointer to a structure representing the directory entry
1100 %  at the current position in the directory stream to which entry refers.
1101 %
1102 %  The format of the readdir
1103 %
1104 %      struct dirent *readdir(DIR *entry)
1105 %
1106 %  A description of each parameter follows:
1107 %
1108 %    o entry: Specifies a pointer to a DIR structure.
1109 %
1110 %
1111 */
readdir(DIR * entry)1112 MagickExport struct dirent *readdir(DIR *entry)
1113 {
1114   CInfoPBRec
1115     search_info;
1116 
1117   int
1118     error;
1119 
1120   static struct dirent
1121     dir_entry;
1122 
1123   static unsigned char
1124     pathname[MaxTextExtent];
1125 
1126   if (entry == (DIR *) NULL)
1127     return((struct dirent *) NULL);
1128   search_info.hFileInfo.ioCompletion=0;
1129   search_info.hFileInfo.ioNamePtr=pathname;
1130   search_info.hFileInfo.ioVRefNum=0;
1131   search_info.hFileInfo.ioFDirIndex=entry->d_index;
1132   search_info.hFileInfo.ioDirID=entry->d_DirID;
1133   error=PBGetCatInfoSync(&search_info);
1134   if (error != noErr)
1135     {
1136       errno=error;
1137       return((struct dirent *) NULL);
1138     }
1139   entry->d_index++;
1140   p2cstrcpy(dir_entry.d_name,search_info.hFileInfo.ioNamePtr);
1141   dir_entry.d_namlen=strlen(dir_entry.d_name);
1142   return(&dir_entry);
1143 }
1144 #endif
1145 
1146 /*
1147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1148 %                                                                             %
1149 %                                                                             %
1150 %                                                                             %
1151 %  R e a d P I C T I m a g e                                                  %
1152 %                                                                             %
1153 %                                                                             %
1154 %                                                                             %
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156 %
1157 %  ReadPICTImage() reads an Apple Macintosh QuickDraw/PICT image file using
1158 %  MacOS QuickDraw methods and returns it.  It allocates the memory necessary
1159 %  for the new Image structure and returns a pointer to the new image.
1160 %
1161 %  This method was written and contributed by spd@daphne.cps.unizar.es
1162 %  (feel free to copy and use it as you want. No warranty).
1163 %
1164 %  The format of the ReadPICTImage method is:
1165 %
1166 %      Image *ReadPICTImage(const ImageInfo *image_info,
1167 %        ExceptionInfo *exception)
1168 %
1169 %  A description of each parameter follows:
1170 %
1171 %    o image:  Method ReadPICTImage returns a pointer to the image after
1172 %      reading.  A null image is returned if there is a memory shortage or
1173 %      if the image cannot be read.
1174 %
1175 %    o image_info: the image info..
1176 %
1177 %    o exception: return any errors or warnings in this structure.
1178 %
1179 */
1180 
MagickMax(const size_t x,const size_t y)1181 static inline size_t MagickMax(const size_t x,const size_t y)
1182 {
1183   if (x > y)
1184     return(x);
1185   return(y);
1186 }
1187 
ReadPICTImage(const ImageInfo * image_info,ExceptionInfo * exception)1188 MagickExport Image *ReadPICTImage(const ImageInfo *image_info,
1189   ExceptionInfo *exception)
1190 {
1191 #define PICTHeaderSize    512
1192 
1193   CodecType
1194     codec;
1195 
1196   GDHandle
1197     device;
1198 
1199   GWorldPtr
1200     graphic_world,
1201     port;
1202 
1203   Image
1204     *image;
1205 
1206   int
1207     depth,
1208     status;
1209 
1210   MagickBooleanType
1211     proceed,
1212     status;
1213 
1214   PicHandle
1215     picture_handle;
1216 
1217   PictInfo
1218     picture_info;
1219 
1220   QDErr
1221     theErr = noErr;
1222 
1223   Rect
1224     rectangle;
1225 
1226   RGBColor
1227     Pixel;
1228 
1229   short
1230     colormap_id;
1231 
1232   ssize_t
1233     y;
1234 
1235   /*
1236     Open image file.
1237   */
1238   image=AcquireImage(image_info);
1239   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1240   if (status == MagickFalse)
1241     return(NULL);
1242   picture_handle=(PicHandle) NewHandle(MagickMax(GetBlobSize(image)-
1243     PICTHeaderSize,PICTHeaderSize));
1244   if (picture_handle == nil)
1245     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1246   HLock((Handle) picture_handle);
1247   (void) ReadBlob(image,PICTHeaderSize,*(unsigned char **) picture_handle);
1248   status=ReadBlob(image,GetBlobSize(image)-PICTHeaderSize,*(unsigned char **)
1249     picture_handle);
1250   if (status == MagickFalse)
1251     {
1252       DisposeHandle((Handle) picture_handle);
1253       ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1254     }
1255   GetGWorld(&port,&device);
1256   theErr=NewGWorld(&graphic_world,0,&(**picture_handle).picFrame,nil,nil,
1257     useTempMem | keepLocal);
1258   if ((theErr != noErr) && (graphic_world == nil))
1259     {
1260       DisposeHandle((Handle) picture_handle);
1261       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1262     }
1263   HUnlock((Handle) picture_handle);
1264   SetGWorld(graphic_world,nil);
1265   theErr=GetPictInfo(picture_handle,&picture_info,0,1,systemMethod,0);
1266   if (theErr != noErr)
1267     {
1268       DisposeGWorld(graphic_world);
1269       DisposeHandle((Handle) picture_handle);
1270       ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1271     }
1272 #if defined(DISABLE_QUICKTIME)
1273   codec='unkn';
1274   colormap_id=(-1);
1275   depth=picture_info.depth;
1276 #else
1277   BottleneckTest(picture_handle,&codec,&depth,&colormap_id);
1278 #endif
1279   switch (codec)
1280   {
1281     case 'rpza':
1282     case 'jpeg':
1283     case 'rle ':
1284     case 'raw ':
1285     case 'smc ':
1286     {
1287       if (depth > 200)
1288         {
1289           depth-=32;
1290           picture_info.theColorTable=GetCTable(colormap_id);
1291         }
1292       break;
1293     }
1294     default:
1295     {
1296       depth=picture_info.depth;
1297       if (depth <= 8)
1298         (void) GetPictInfo(picture_handle,&picture_info,returnColorTable,
1299           (short) (1 << picture_info.depth),systemMethod,0);
1300       break;
1301     }
1302   }
1303   image->x_resolution=(picture_info.hRes) >> 16;
1304   image->y_resolution=(picture_info.vRes) >> 16;
1305   image->units=PixelsPerInchResolution;
1306   image->columns=picture_info.sourceRect.right-picture_info.sourceRect.left;
1307   image->rows=picture_info.sourceRect.bottom-picture_info.sourceRect.top;
1308   if ((depth <= 8) && ((*(picture_info.theColorTable))->ctSize != 0))
1309     {
1310       size_t
1311         number_colors;
1312 
1313       /*
1314         Colormapped PICT image.
1315       */
1316       number_colors=(*(picture_info.theColorTable))->ctSize;
1317       if (!AcquireImageColormap(image,number_colors))
1318         {
1319           if (picture_info.theColorTable != nil)
1320             DisposeHandle((Handle) picture_info.theColorTable);
1321           DisposeGWorld(graphic_world);
1322           DisposeHandle((Handle) picture_handle);
1323           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1324         }
1325       for (x=0; x < image->colors; x++)
1326       {
1327         image->colormap[x].red=
1328           (*(picture_info.theColorTable))->ctTable[x].rgb.red;
1329         image->colormap[x].green=
1330           (*(picture_info.theColorTable))->ctTable[x].rgb.green;
1331         image->colormap[x].blue=
1332           (*(picture_info.theColorTable))->ctTable[x].rgb.blue;
1333       }
1334     }
1335   SetRect(&rectangle,0,0,image->columns,image->rows);
1336   (void) UpdateGWorld(&graphic_world,depth,&rectangle,
1337     picture_info.theColorTable,nil,0);
1338   LockPixels(GetGWorldPixMap(graphic_world));  /*->portPixMap); */
1339   EraseRect(&rectangle);
1340   DrawPicture(picture_handle,&rectangle);
1341   if ((depth <= 8) && (colormap_id == -1))
1342     {
1343       DisposeHandle((Handle) picture_info.theColorTable);
1344       picture_info.theColorTable=nil;
1345     }
1346   DisposeHandle((Handle) picture_handle);
1347   /*
1348     Convert PICT pixels to pixel packets.
1349   */
1350   for (y=0; y < image->rows; y++)
1351   {
1352     IndexPacket
1353       *restrict indexes;
1354 
1355     ssize_t
1356       x;
1357 
1358     PixelPacket
1359       *restrict q;
1360 
1361     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1362     if (q == (PixelPacket *) NULL)
1363       break;
1364     indexes=GetAuthenticIndexQueue(image);
1365     for (x=0; x < image->columns; x++)
1366     {
1367       GetCPixel(x,y,&Pixel);
1368       SetPixelRed(q,ScaleCharToQuantum(Pixel.red & 0xff));
1369       SetPixelGreen(q,ScaleCharToQuantum(Pixel.green & 0xff));
1370       SetPixelBlue(q,ScaleCharToQuantum(Pixel.blue & 0xff));
1371       if (image->storage_class == PseudoClass)
1372         SetPixelIndex(indexes+x,Color2Index(&Pixel));
1373       q++;
1374     }
1375     if (SyncAuthenticPixels(image,exception) == MagickFalse)
1376       break;
1377     proceed=SetImageProgress(image,LoadImageTag,y,image->rows);
1378     if (proceed == MagickFalse)
1379       break;
1380   }
1381   UnlockPixels(GetGWorldPixMap(graphic_world));
1382   SetGWorld(port,device);
1383   if (picture_info.theColorTable != nil)
1384     DisposeHandle((Handle) picture_info.theColorTable);
1385   DisposeGWorld(graphic_world);
1386   (void) CloseBlob(image);
1387   return(image);
1388 }
1389 
1390 /*
1391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1392 %                                                                             %
1393 %                                                                             %
1394 %                                                                             %
1395 %   S e a r c h F o r F i l e                                                 %
1396 %                                                                             %
1397 %                                                                             %
1398 %                                                                             %
1399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400 %
1401 %  SearchForFile() searches for a file.
1402 %
1403 %
1404 */
SearchForFile(OSType creator_type,OSType file_type,FSSpec * file,short count)1405 static Boolean SearchForFile(OSType creator_type,OSType file_type,FSSpec *file,
1406   short count)
1407 {
1408   char
1409     *buffer;
1410 
1411   CInfoPBRec
1412     search1_info,
1413     search2_info;
1414 
1415   FSSpec
1416     application;
1417 
1418   HParamBlockRec
1419     parameter_info;
1420 
1421   OSErr
1422     error;
1423 
1424   ProcessInfoRec
1425     application_info;
1426 
1427   ProcessSerialNumber
1428     serial_number;
1429 
1430   ssize_t
1431     buffer_size = MagickMinBufferExtent;
1432 
1433   serial_number.lowLongOfPSN=kCurrentProcess;
1434   serial_number.highLongOfPSN=0;
1435   application_info.processInfoLength=sizeof(ProcessInfoRec);
1436   application_info.processName=NULL;
1437   application_info.processAppSpec=(&application);
1438   GetProcessInformation(&serial_number,&application_info);
1439   buffer=NewPtr(buffer_size);
1440   if (buffer == (char *) NULL)
1441     return(false);
1442   parameter_info.csParam.ioCompletion=NULL;
1443   parameter_info.csParam.ioNamePtr=NULL;
1444   parameter_info.csParam.ioVRefNum=application.vRefNum;
1445   parameter_info.csParam.ioMatchPtr=file;
1446   parameter_info.csParam.ioReqMatchCount=count;
1447   parameter_info.csParam.ioSearchBits=fsSBFlFndrInfo;
1448   parameter_info.csParam.ioSearchInfo1=&search1_info;
1449   parameter_info.csParam.ioSearchInfo2=&search2_info;
1450   parameter_info.csParam.ioSearchTime=0;
1451   parameter_info.csParam.ioCatPosition.initialize=0;
1452   parameter_info.csParam.ioOptBuffer=buffer;
1453   parameter_info.csParam.ioOptBufSize=buffer_size;
1454   search1_info.hFileInfo.ioNamePtr=NULL;
1455   search1_info.hFileInfo.ioFlFndrInfo.fdType=file_type;
1456   search1_info.hFileInfo.ioFlFndrInfo.fdCreator=creator_type;
1457   search1_info.hFileInfo.ioFlAttrib=0;
1458   search1_info.hFileInfo.ioFlParID=0;
1459   search2_info=search1_info;
1460   search2_info.hFileInfo.ioFlAttrib=0x10;
1461   search2_info.hFileInfo.ioFlFndrInfo.fdCreator=creator_type;
1462   search2_info.hFileInfo.ioFlFndrInfo.fdType=(-1);
1463   search2_info.hFileInfo.ioFlFndrInfo.fdFlags=0;
1464   search2_info.hFileInfo.ioFlFndrInfo.fdLocation.h=0;
1465   search2_info.hFileInfo.ioFlFndrInfo.fdLocation.v=0;
1466   search2_info.hFileInfo.ioFlFndrInfo.fdFldr=0;
1467   search2_info.hFileInfo.ioFlParID=0;
1468   error=PBCatSearchSync((CSParamPtr) &parameter_info);
1469   DisposePtr(buffer);
1470   if (parameter_info.csParam.ioReqMatchCount ==
1471       parameter_info.csParam.ioActMatchCount)
1472     error=eofErr;
1473   if (parameter_info.csParam.ioActMatchCount == 0)
1474     error=0;
1475   return(error == eofErr);
1476 }
1477 
1478 #if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
1479 /*
1480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1481 %                                                                             %
1482 %                                                                             %
1483 %                                                                             %
1484 %   s e e k d i r                                                             %
1485 %                                                                             %
1486 %                                                                             %
1487 %                                                                             %
1488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489 %
1490 %  seekdir() sets the position of the next readdir() operation on the directory
1491 %  stream.
1492 %
1493 %  The format of the seekdir method is:
1494 %
1495 %      void seekdir(DIR *entry,ssize_t position)
1496 %
1497 %  A description of each parameter follows:
1498 %
1499 %    o entry: Specifies a pointer to a DIR structure.
1500 %
1501 %    o position: specifies the position associated with the directory
1502 %      stream.
1503 %
1504 %
1505 %
1506 */
seekdir(DIR * entry,ssize_t position)1507 MagickExport void seekdir(DIR *entry,ssize_t position)
1508 {
1509   assert(entry != (DIR *) NULL);
1510   entry->d_index=position;
1511 }
1512 #endif
1513 
1514 /*
1515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1516 %                                                                             %
1517 %                                                                             %
1518 %                                                                             %
1519 %   S e t A p p l i c a t i o n T y p e                                       %
1520 %                                                                             %
1521 %                                                                             %
1522 %                                                                             %
1523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1524 %
1525 %  SetApplicationType() sets the file type of an image.
1526 %
1527 %  The format of the SetApplicationType method is:
1528 %
1529 %      void SetApplicationType(const char *filename,const char *magick,
1530 %        OSType application)
1531 %
1532 %  A description of each parameter follows:
1533 %
1534 %    o filename: Specifies the name of the file.
1535 %
1536 %    o filename: Specifies the file type.
1537 %
1538 %    o application: Specifies the type of the application.
1539 %
1540 */
1541 
MagickMin(const size_t x,const size_t y)1542 static inline size_t MagickMin(const size_t x,const size_t y)
1543 {
1544   if (x < y)
1545     return(x);
1546   return(y);
1547 }
1548 
SetApplicationType(const char * filename,const char * magick,OSType application)1549 MagickExport void SetApplicationType(const char *filename,const char *magick,
1550   OSType application)
1551 {
1552   FSSpec
1553     file_specification;
1554 
1555   OSType
1556     filetype;
1557 
1558   Str255
1559     name;
1560 
1561   assert(filename != (char *) NULL);
1562   if (image->debug != MagickFalse)
1563     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1564   assert(magick != (const char *) NULL);
1565   filetype='    ';
1566   (void) CopyMagickString((char *) &filetype,magick,MagickMin(strlen(magick),
1567     4));
1568   if (LocaleCompare(magick,"JPG") == 0)
1569     (void) CopyMagickString((char *) &filetype,"JPEG",MaxTextExtent);
1570   c2pstrcpy(name,filename);
1571   FSMakeFSSpec(0,0,name,&file_specification);
1572   FSpCreate(&file_specification,application,filetype,smSystemScript);
1573 }
1574 
1575 #if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
1576 /*
1577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578 %                                                                             %
1579 %                                                                             %
1580 %                                                                             %
1581 %   t e l l d i r                                                             %
1582 %                                                                             %
1583 %                                                                             %
1584 %                                                                             %
1585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1586 %
1587 %   Method telldir returns the current location associated  with  the
1588 %   named directory stream.
1589 %
1590 %  The format of the telldir method is:
1591 %
1592 %      telldir(DIR *entry)
1593 %
1594 %  A description of each parameter follows:
1595 %
1596 %    o entry: Specifies a pointer to a DIR structure.
1597 %
1598 %
1599 */
telldir(DIR * entry)1600 MagickExport ssize_t telldir(DIR *entry)
1601 {
1602   return(entry->d_index);
1603 }
1604 #endif
1605 
1606 #endif
1607