#import #import #import #import "Preview.h" #import "Controller.h" #import "DiagnosticsPanel.h" #import "Options.h" @implementation PrevImageView - (id)initWithFrame:(NSRect)frameRect { image = nil; return [super initWithFrame:frameRect]; } - (NSImage *)image { return image; } - setImage:(NSImage *)anImage { if(image!=nil){ [image release]; } image = anImage; if(image!=nil){ [image retain]; NSSize newSize = [image size]; NSRect oldFrame = [self frame], newFrame = NSMakeRect(0, 0, newSize.width, newSize.height); if(!NSEqualSizes(oldFrame.size, newFrame.size)){ [self setFrame:newFrame]; } } [self setNeedsDisplay:YES]; } - (void)drawRect:(NSRect)aRect { // idea for this method by A. Malmberg if(image!=nil){ NSRectClip(aRect); [[[image representations] objectAtIndex:0] draw]; } } - (void)mouseDown:(NSEvent *)theEvent { NSPoint startp = [theEvent locationInWindow], curp; startp = [self convertPoint:startp fromView: nil]; NSWindow *win = [self window]; NSEvent *curEvent = theEvent; unsigned int mflags = [theEvent modifierFlags], cmask = NSLeftMouseUpMask | NSLeftMouseDraggedMask; NSSize fsize = [self frame].size; NSRect box, bbox, cachebox; BOOL first = YES; do { float bminx, bmaxx, bminy, bmaxy; if(first==NO){ [win restoreCachedImage]; } first = NO; curp = [curEvent locationInWindow]; curp = [self convertPoint:curp fromView: nil]; if(startp.x < curp.x){ bminx = startp.x; bmaxx = curp.x; } else{ bminx = curp.x; bmaxx = startp.x; } if(startp.y < curp.y){ bminy = startp.y; bmaxy = curp.y; } else{ bminy = curp.y; bmaxy = startp.y; } if(bminx<0){ bminx = 0; } if(bminy<0){ bminy = 0; } if(bmaxx>fsize.width){ bmaxx = fsize.width; } if(bmaxy>fsize.height){ bmaxy = fsize.height; } box.origin.x = bminx; box.origin.y = bminy; box.size.width = bmaxx-bminx; box.size.height = bmaxy-bminy; bbox = box; bbox.origin.x += 1; bbox.origin.y += 1; bbox.size.width -= 2; bbox.size.height -= 2; cachebox = box; cachebox.origin.x -= 2; cachebox.origin.y -= 2; cachebox.size.width += 4; cachebox.size.height += 4; cachebox = [self convertRect:cachebox toView:nil]; [win cacheImageInRect:cachebox]; [self lockFocus]; [[NSColor redColor] set]; [NSBezierPath strokeRect:box]; [[NSColor greenColor] set]; [NSBezierPath strokeRect:bbox]; [self unlockFocus]; [win flushWindow]; curEvent = [[self window] nextEventMatchingMask:cmask]; } while([curEvent type] != NSLeftMouseUp); [win restoreCachedImage]; [win flushWindow]; if(NSIsEmptyRect(box)){ NSBeep(); return; } NSDate *markdate = [NSDate dateWithTimeIntervalSinceNow:MARKDELAY]; int cflag = 0; NSColor *cols[2] = { [NSColor blueColor], [NSColor yellowColor] }; [win cacheImageInRect:cachebox]; while([markdate timeIntervalSinceNow]>0){ [self lockFocus]; [cols[cflag] set]; [NSBezierPath strokeRect:box]; [cols[1-cflag] set]; [NSBezierPath strokeRect:bbox]; [self unlockFocus]; [win flushWindow]; NSDate *mpause = [NSDate dateWithTimeIntervalSinceNow:MARKPAUSE]; [NSThread sleepUntilDate:mpause]; cflag = 1-cflag; } [win restoreCachedImage]; [win flushWindow]; [self lockFocus]; NSBitmapImageRep *boxRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:box]; AUTORELEASE(boxRep); [self unlockFocus]; NSPasteboard *pb = [NSPasteboard generalPasteboard]; NSArray *types = [NSArray arrayWithObject:NSTIFFPboardType]; [pb declareTypes:types owner:self]; [pb setData:[boxRep TIFFRepresentation] forType:NSTIFFPboardType]; return; } @end @implementation Preview #define PRWIDTH (36*17/2) #define PRHEIGHT (36*11) #define PRBASEX 200 #define PRBASEY 200 #define RESKEY @"Resolution" static int count = 0; - initWithController:(id)theCon andPath:(NSString *)path resolution:(int)rval { NSRect matRect = {0, 0, 50, 20}, scrollRect = {0, 0, {PRWIDTH, PRHEIGHT}}, pageRect, winRect; unsigned int style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; NSButtonCell *proto; NSView *contentView; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; int resdefault = [defaults integerForKey:RESKEY]; NSString *resAndPath = [NSString stringWithFormat:@"%@ %@", RESKEY, path]; // and not imgPath int respath = [defaults integerForKey:resAndPath]; resolution = (rval!=-1 ? rval : (respath>0 ? respath : (resdefault>0 ? resdefault : DEFAULT_RESOLUTION))); useContentDimensions = NO; pageInv = nil; pageTimer = nil; tasks = nil; readPipes = nil; readData = nil; proto = [[NSButtonCell alloc] initImageCell:nil]; [proto setButtonType:NSRadioButton]; [proto setBordered:NO]; [proto setTag:0]; [proto setTitle:@" 1 "]; [proto setTarget:self]; [proto setAction:@selector(a2psGoto:)]; pageMatrix = [[NSMatrix alloc] initWithFrame:matRect mode:NSRadioModeMatrix prototype:proto numberOfRows:1 numberOfColumns:1]; [pageMatrix sizeToFit]; pageRect.size = [NSScrollView frameSizeForContentSize:[pageMatrix frame].size hasHorizontalScroller:YES hasVerticalScroller:NO borderType:NSBezelBorder]; pageRect.size.width = PRWIDTH; pageRect.origin.x = 0; pageRect.origin.y = PRHEIGHT; pageScroller = [[NSScrollView alloc] initWithFrame:pageRect]; [pageScroller setHasVerticalScroller:NO]; [pageScroller setHasHorizontalScroller:YES]; [pageScroller setDocumentView:pageMatrix]; [pageScroller setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin]; winRect = NSMakeRect(PRBASEX+(count%10)*24, PRBASEY-(count%10)*24, PRWIDTH, PRHEIGHT+pageRect.size.height); count++; [self initWithContentRect:winRect styleMask:style backing:NSBackingStoreRetained defer:NO]; [self setMinSize:winRect.size]; [self setReleasedWhenClosed:YES]; con = theCon; imgPath = path; [imgPath retain]; imgFmt = [path pathExtension]; [imgFmt retain]; imgDir = nil; current = pages = -1; imgView = [[PrevImageView alloc] initWithFrame:scrollRect]; [imgView setImage:nil]; scrollView = [[NSScrollView alloc] initWithFrame:scrollRect]; [scrollView setHasVerticalScroller:YES]; [scrollView setHasHorizontalScroller:YES]; [scrollView setDocumentView:imgView]; [scrollView setScrollsDynamically:NO]; [scrollView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; [scrollView setBackgroundColor:[NSColor whiteColor]]; contentView = [self contentView]; [contentView addSubview:pageScroller]; [contentView addSubview:scrollView]; [self setTitleWithRepresentedFilename:path]; [self setDelegate:con]; [self setFrameUsingName:path]; [self a2psPreview:nil]; [self display]; [self makeKeyAndOrderFront:nil]; return self; } - (NSString *)path { return imgPath; } - (NSString *)imgFmt { return imgFmt; } - setImgFmt:(NSString *)fmt { if(imgFmt!=nil){ [imgFmt release]; } imgFmt = fmt; [imgFmt retain]; return self; } #define WAITSECS 1 - countPages:(NSString *)path done:(BOOL)dflag { NSFileManager *fm = [NSFileManager defaultManager]; NSString *page; int newPages; for(newPages = (pages==-1 ? 0 : pages); page = [NSString stringWithFormat:@"%@/%d.%@", path, newPages+1, imgFmt], [fm fileExistsAtPath:page]==YES; newPages++){ if(dflag==NO){ NSDate *mdate = [[fm fileAttributesAtPath:page traverseLink:NO] fileModificationDate]; if(!([mdate timeIntervalSinceNow]<-WAITSECS)){ break; } } } pages = (newPages>0 ? newPages : -1); return self; } - (NSString *)gsDimensionArg { if(useContentDimensions==YES){ NSSize msize = [con mediumSizeFor:self]; return [NSString stringWithFormat:@"-r%dx%d", (int)(72*csize.width/msize.width), (int)(72*csize.height/msize.height)]; } return [NSString stringWithFormat:@"-r%dx%d", resolution, resolution]; } - setResolution:(int)res { if(useContentDimensions==NO && resolution==res){ return self; } NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setInteger:res forKey:RESKEY]; NSString *resAndPath = [NSString stringWithFormat:@"%@ %@", RESKEY, imgPath]; [defaults setInteger:res forKey:resAndPath]; resolution = res; useContentDimensions = NO; [self a2psPreview:nil]; return self; } - useContentDimensions:(id)sender { NSSize size = [[scrollView contentView] frame].size; if(useContentDimensions==YES && csize.width==size.width && csize.height==size.height){ return self; } useContentDimensions = YES; csize = size; [self a2psPreview:nil]; return self; } - a2psResolution:(id)sender { return [self setResolution:[sender tag]]; } - setPage:(int)page { NSString *nextImagePath; NSImage *nextImage; if(page==current || page<0 || page>=pages){ return self; } nextImagePath = [NSString stringWithFormat:@"%@/%d.%@", imgDir, page+1, imgFmt]; if((nextImage = [[NSImage alloc] initWithContentsOfFile:nextImagePath])==nil){ NSRunAlertPanel(@"Error", @"Couldn't read image:\n%@", @"Ok", NULL, NULL, nextImagePath); return self; } if(![[nextImage representations] count]){ [nextImage release]; NSBeep(); return self; } nextImage = [self imageLoadCompleteHook:nextImage]; current = page; [imgView setImage:nextImage]; [nextImage release]; [pageMatrix selectCellAtRow:0 column:page]; [pageMatrix display]; [scrollView display]; return self; } - (NSImage *)imageLoadCompleteHook:(NSImage *)img { return img; } extern int errno; - tiffSave:(id)sender { NSImage *img = [imgView image]; if(img==nil){ NSBeep(); return self; } NSArray *reps = [img representations]; if(![reps count]){ NSBeep(); return self; } NSBitmapImageRep *rep = [reps objectAtIndex:0]; NSSavePanel *savePanel = [NSSavePanel savePanel]; [savePanel setRequiredFileType:@"tiff"]; if([savePanel runModal] == NSOKButton){ NSString *fname = [savePanel filename]; NSData *data = [rep TIFFRepresentation]; if([data writeToFile:fname atomically:YES]==NO){ NSString *msg = [NSString stringWithFormat:@"Couldn't write %@: %s", fname, strerror(errno)]; NSRunAlertPanel(@"Alert", msg, @"Ok", nil, nil); } } [[NSCursor arrowCursor] set]; return self; } - a2psFirst:(id)sender { return [self setPage:0]; } - a2psLast:(id)sender { return [self setPage:pages-1]; } - a2psPage:(id)sender; { return [self setPage:current+[sender tag]]; } - a2psGoto:(id)sender; { return [self setPage:[[sender selectedCell] tag]]; } #define MAXERR 4096 - a2psPreview:(id)sender { [self subclassResponsibility:_cmd]; return nil; } #define READINTERVAL 0.2 - prepareForRead { int pgcount, col, fd; NSEnumerator *pipeEn = [readPipes objectEnumerator]; NSPipe *pipe; while((pipe = [pipeEn nextObject])!=nil){ fd = [[pipe fileHandleForReading] fileDescriptor]; fcntl(fd, F_SETFL, O_NONBLOCK); } pgcount = [pageMatrix numberOfColumns]; for(col=pgcount-1; col>0; col--){ [pageMatrix removeColumn:col]; } [pageMatrix display]; pages = current = -1; pageInv = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector: @selector(a2psRead)]]; [pageInv setSelector:@selector(a2psRead)]; [pageInv setTarget:self]; [pageInv retain]; pageTimer = [NSTimer scheduledTimerWithTimeInterval:READINTERVAL invocation:pageInv repeats:YES]; [pageTimer retain]; return self; } #define BUFSIZE 4096 - a2psRead { int index, fd, len, atEOF = 0, atEND = 0; char *buf[BUFSIZE]; NSPipe *pipe; int pgcount, col; id cell; BOOL dflag = NO; for(index=0; index<[readPipes count]; index++){ pipe = [readPipes objectAtIndex:index]; fd = [[pipe fileHandleForReading] fileDescriptor]; while((len = read(fd, buf, BUFSIZE))>0){ [[readData objectAtIndex:index] appendBytes:buf length:len]; } if(!len){ atEOF++; } } for(index=0; index<[tasks count]; index++){ if([[tasks objectAtIndex:index] isRunning]==NO){ atEND++; } } dflag = (atEOF==[readPipes count] && atEND==[tasks count] ? YES : NO); [self countPages:imgDir done:dflag]; pgcount = [pageMatrix numberOfColumns]; if(pgcount0 && current==-1){ NSString *firstImagePath = [NSString stringWithFormat:@"%@/1.%@", imgDir, imgFmt]; NSImage *img; if((img = [[NSImage alloc] initWithContentsOfFile:firstImagePath])==nil){ int result = NSRunAlertPanel(@"Error", @"%@: Couldn't read first image:\n%@", @"Ok", nil, nil, NSStringFromClass([self class]), firstImagePath); if(result==NSAlertAlternateReturn){ [[NSApplication sharedApplication] terminate:self]; } pages = -1; current = -1; return self; } NSArray *reps; NSImageRep *rep; reps = [img representations]; if(![reps count]){ // try again [img release]; return self; } rep = [reps objectAtIndex:0]; NSRect newFrame = NSMakeRect(0, 0, [rep pixelsWide], [rep pixelsHigh]); [imgView setFrame:newFrame]; [imgView setImage:img]; [img release]; current = 0; [pageMatrix selectCellAtRow:0 column:0]; } if(dflag==YES){ [pageTimer invalidate]; [self allPagesDone]; } // [scrollView display]; return self; } - (BOOL)printFile:(NSString *)path { NSFileManager *fm = [NSFileManager defaultManager]; NSTask *lprTask = [NSTask new]; NSMutableArray *args; BOOL interrupted; NSPipe *err = [NSPipe new]; NSMutableArray *lprCmd = [con lprCommand]; NSString *lpr = [lprCmd objectAtIndex:0]; [lprCmd removeObjectAtIndex:0]; [lprCmd addObject:path]; [lprTask setLaunchPath:lpr]; [lprTask setArguments:lprCmd]; [lprTask setStandardOutput:err]; [lprTask setStandardError:err]; NS_DURING NSLog(@"%@ %@", [lprTask launchPath], [lprTask arguments]); [lprTask launch]; NS_HANDLER NSString *exMsg = [NSString stringWithFormat:@"EXCEPTION: %@ %@", [localException name], [localException reason]]; NSRunAlertPanel(@"Print failed (lpr)", @"%@\n%@", @"Ok", NULL, NULL, path, exMsg); if([lprTask isRunning]==YES){ [lprTask terminate]; } NS_VALUERETURN(NO, BOOL); NS_ENDHANDLER if((interrupted = [con waitForTaskToFinish:lprTask description:@"lpr"])==NO){ NSString *msg; int len; NSData *errData; errData = [[err fileHandleForReading] readDataToEndOfFile]; len = [errData length]; if(len>MAXERR){ len = MAXERR; } msg = [NSString stringWithCString:[errData bytes] length:len]; if(len){ ShowDiagnostics(@"Output from print command", msg); } } else{ [lprTask terminate]; return NO; } return YES; } - (BOOL)validateMenuItem:(id )menuItem { NSString *title = [menuItem title]; SEL pageSEL = @selector(a2psPage:); IMP pSEL1 = [self methodForSelector:pageSEL], pSEL2 = [self methodForSelector:[menuItem action]]; if(current==-1){ if([title isEqual:@"Current"]){ return YES; } return NO; } if([title isEqual:@"First"] || [title isEqual:@"Last"]){ return YES; } if(pSEL1==pSEL2){ int next = current + [menuItem tag]; if(next<0 || next>=pages){ return NO; } } return YES; } - allPagesDone { [self subclassResponsibility:_cmd]; return nil; } Class renderWinClass = NULL, taskClass = NULL; - cleanupPreview { NSFileManager *fm = [NSFileManager defaultManager]; int page; if(pageTimer!=nil){ if([pageTimer isValid]==YES){ NSLog(@"invalidating timer %@: %@", self, pageTimer); [pageTimer invalidate]; } [pageTimer release]; [pageInv release]; } if(taskClass==NULL){ taskClass = [NSTask class]; } if(renderWinClass==NULL){ renderWinClass = [NSWindow class]; } if(tasks!=nil && [tasks count]>0){ taskClass = [[tasks objectAtIndex:0] class]; NSLog(@"cleanup %@; %d page(s); %d", self, pages, current); [tasks makeObjectsPerformSelector:@selector(terminate)]; [tasks makeObjectsPerformSelector:@selector(release)]; [tasks release]; tasks = nil; [readPipes makeObjectsPerformSelector:@selector(release)]; [readPipes release]; readPipes = nil; [readData release]; readData = nil; } if(imgDir!=nil){ BOOL isDir; if([fm fileExistsAtPath:imgDir isDirectory:&isDir]==YES && isDir==YES){ if([fm removeFileAtPath:imgDir handler:nil]==NO){ NSRunAlertPanel(@"Error", @"Couldn't remove temp dir:\n%@", @"Ok", nil, nil, imgDir); } else{ NSLog(@"removed %@", imgDir); } } } [imgPath release]; [imgDir release]; [imgView setImage:nil]; current = pages = -1; #ifdef _GPSText_DEBUG { Class todebug[] = { renderWinClass, [NSImage class], [NSBitmapImageRep class], [NSCachedImageRep class], taskClass, [NSPipe class], [NSTimer class], nil }, *currentClass; currentClass=todebug; while(*currentClass!=nil){ id cl=*currentClass; NSLog(@"%@ count %u total %u peak %u\n", NSStringFromClass(cl), GSDebugAllocationCount(cl), GSDebugAllocationTotal(cl), GSDebugAllocationPeak(cl)); currentClass++; } } #endif return self; } @end @implementation TextPreview - a2psPreview:(id)sender { NSFileManager *fm = [NSFileManager defaultManager]; NSString *tempName = [con tempNameExt:nil]; NSTask *a2psTask = [NSTask new], *gsTask = [NSTask new]; NSMutableArray *args; BOOL interrupted; NSPipe *fromA2PStoGS = [NSPipe new], *err1 = [NSPipe new], *err2 = [NSPipe new]; [imgPath retain]; [self cleanupPreview]; if([fm createDirectoryAtPath:tempName attributes:nil]==NO){ NSRunAlertPanel(@"Error", @"Couldn't create temp dir:\n%@", @"Ok", NULL, NULL, tempName); return self; } args = [con getA2PSArgs]; [args addObject:@"-o"]; [args addObject:@"-"]; [args addObject:imgPath]; [a2psTask setLaunchPath:[con a2psStr]]; [a2psTask setArguments:args]; args = [con getGSArgs]; [self setImgFmt:[con imgFmt]]; [args addObject: [NSString stringWithFormat:@"-sOutputFile=%@/%%d.%@", tempName, imgFmt]]; [args addObject:[self gsDimensionArg]]; [args addObject:@"-"]; [gsTask setLaunchPath:[con gsStr]]; [gsTask setArguments:args]; [a2psTask setStandardOutput:fromA2PStoGS]; [gsTask setStandardInput:fromA2PStoGS]; [a2psTask setStandardError:err1]; [gsTask setStandardOutput:err2]; [gsTask setStandardError:err2]; NS_DURING NSLog(@"%@ %@", [a2psTask launchPath], [a2psTask arguments]); [a2psTask launch]; NSLog(@"%@ %@", [gsTask launchPath], [gsTask arguments]); [gsTask launch]; NS_HANDLER NSString *exMsg = [NSString stringWithFormat:@"EXCEPTION: %@ %@", [localException name], [localException reason]]; NSRunAlertPanel(@"Preview failed", @"%@\n%@", @"Ok", NULL, NULL, imgPath, exMsg); if([a2psTask isRunning]==YES){ [a2psTask terminate]; } if([gsTask isRunning]==YES){ [gsTask terminate]; } NS_VALUERETURN(self, id); NS_ENDHANDLER imgDir = tempName; [imgDir retain]; tasks = [NSArray arrayWithObjects:a2psTask, gsTask, nil]; [tasks retain]; readPipes = [NSArray arrayWithObjects:err1, err2, nil]; [readPipes retain]; readData = [NSArray arrayWithObjects: [NSMutableData dataWithCapacity:4096], [NSMutableData dataWithCapacity:4096], nil]; [readData retain]; [self prepareForRead]; return self; } - (BOOL)saveToFile:(NSString *)path opTitle:(NSString *)ot { NSFileManager *fm = [NSFileManager defaultManager]; NSString *errTitle = [NSString stringWithFormat:@"%@ failed (a2ps)", ot]; NSTask *a2psTask = [NSTask new]; NSMutableArray *args; BOOL interrupted; NSPipe *err = [NSPipe new]; args = [con getA2PSArgs]; [args addObject: [NSString stringWithFormat:@"--output=%@", path]]; [args addObject:imgPath]; [a2psTask setLaunchPath:[con a2psStr]]; [a2psTask setArguments:args]; [a2psTask setStandardOutput:err]; [a2psTask setStandardError:err]; NS_DURING NSLog(@"%@ %@", [a2psTask launchPath], [a2psTask arguments]); [a2psTask launch]; NS_HANDLER NSString *exMsg = [NSString stringWithFormat:@"EXCEPTION: %@ %@", [localException name], [localException reason]]; NSRunAlertPanel(errTitle, @"%@\n%@", @"Ok", NULL, NULL, path, exMsg); if([a2psTask isRunning]==YES){ [a2psTask terminate]; } NS_VALUERETURN(NO, BOOL); NS_ENDHANDLER if((interrupted = [con waitForTaskToFinish:a2psTask description:@"a2ps"])==NO){ if([fm isReadableFileAtPath:path]==NO){ NSString *msg; int len; NSData *errData; errData = [[err fileHandleForReading] readDataToEndOfFile]; len = [errData length]; if(len>MAXERR){ len = MAXERR; } msg = [NSString stringWithCString:[errData bytes] length:len]; ShowDiagnostics(errTitle, msg); return NO; } } else{ [a2psTask terminate]; return NO; } return YES; } - a2psSave:(id)sender; { NSSavePanel *savePanel = [NSSavePanel savePanel]; NSString *dirPath = [[NSFileManager defaultManager] currentDirectoryPath], *item = [imgPath lastPathComponent], *suggest = [[item stringByDeletingPathExtension] stringByAppendingPathExtension:@"ps"]; [savePanel setTitle: [NSString stringWithFormat:@"Save %@", item]]; [savePanel setPrompt:NSStringFromClass([self class])]; [savePanel setRequiredFileType:@"ps"]; if([savePanel runModalForDirectory:dirPath file:suggest] ==NSOKButton){ [self saveToFile:[savePanel filename] opTitle:@"Save"]; } return self; } - a2psPrint:(id)sender; { NSFileManager *fm = [NSFileManager defaultManager]; NSString *tempName = [con tempNameExt:@"ps"]; if([self saveToFile:tempName opTitle:@"Print"]==YES){ [self printFile:tempName]; if([fm removeFileAtPath:tempName handler:nil]==NO){ NSRunAlertPanel(@"Error", @"Couldn't remove temp file:\n%@", @"Ok", NULL, NULL, tempName); } } return self; } - allPagesDone { if(pages==-1){ NSString *title, *msg, *errSrc = nil; int len; NSData *rd; NSMutableData *errData = [NSMutableData data]; rd = [readData objectAtIndex:0]; if([rd length]){ [errData appendData:rd]; errSrc = @"a2ps"; } rd = [readData objectAtIndex:1]; if([rd length]){ [errData appendData:rd]; errSrc = (errSrc==nil ? @"gs" : @"a2ps/gs"); } len = [errData length]; if(len>MAXERR){ len = MAXERR; } title = [NSString stringWithFormat: @"Couldn't read image(s) (%@)", errSrc]; msg = [NSString stringWithCString:[errData bytes] length:len]; msg = [msg stringByAppendingFormat:@"\n%@\n", imgDir]; ShowDiagnostics(title, msg); } return self; } @end @implementation PostScriptOrPDFPreview - a2psPreview:(id)sender { NSFileManager *fm = [NSFileManager defaultManager]; NSString *tempName = [con tempNameExt:nil]; NSTask *gsTask = [NSTask new]; NSMutableArray *args; NSPipe *err = [NSPipe new]; [imgPath retain]; [self cleanupPreview]; if([fm createDirectoryAtPath:tempName attributes:nil]==NO){ NSRunAlertPanel(@"Error", @"Couldn't create temp dir:\n%@", @"Ok", NULL, NULL, tempName); return self; } args = [con getGSArgs]; [args addObject:@"-dBATCH"]; [self setImgFmt:[con imgFmt]]; [args addObject: [NSString stringWithFormat:@"-sOutputFile=%@/%%d.%@", tempName, imgFmt]]; [args addObject:[self gsDimensionArg]]; [args addObject:imgPath]; [gsTask setLaunchPath:[con gsStr]]; [gsTask setArguments:args]; [gsTask setStandardOutput:err]; [gsTask setStandardError:err]; NS_DURING NSLog(@"%@ %@", [gsTask launchPath], [gsTask arguments]); [gsTask launch]; NS_HANDLER NSString *exMsg = [NSString stringWithFormat:@"EXCEPTION: %@ %@", [localException name], [localException reason]]; NSRunAlertPanel(@"Preview failed", @"%@\n%@", @"Ok", NULL, NULL, imgPath, exMsg); if([gsTask isRunning]==YES){ [gsTask terminate]; } NS_VALUERETURN(self, id); NS_ENDHANDLER imgDir = tempName; [imgDir retain]; tasks = [NSArray arrayWithObjects:gsTask, nil]; [tasks retain]; readPipes = [NSArray arrayWithObjects:err, nil]; [readPipes retain]; readData = [NSArray arrayWithObjects: [NSMutableData dataWithCapacity:4096], nil]; [readData retain]; [self prepareForRead]; return self; } - a2psPrint:(id)sender; { NSString *ext = [imgPath pathExtension]; if([ext isEqualToString:@"pdf"]==YES || [ext isEqualToString:@"PDF"]==YES){ int result = NSRunAlertPanel(@"Warning", @"This will send PDF to the print command.\n%@", @"Ok", @"Cancel", nil, imgPath); if(result==NSAlertAlternateReturn){ return self; } } [self printFile:imgPath]; return self; } - allPagesDone { if(pages==-1){ NSString *title, *msg; int len; NSData *errData = [readData objectAtIndex:0]; len = [errData length]; if(len>MAXERR){ len = MAXERR; } title = [NSString stringWithFormat: @"Couldn't read image(s) (gs)"]; msg = [NSString stringWithCString:[errData bytes] length:len]; ShowDiagnostics(title, msg); } return self; } @end @implementation ImagePreview - a2psPreview:(id)sender { current = pages = -1; NSFileManager *fm = [NSFileManager defaultManager]; if(imgDir==nil){ NSString *tempName = [con tempNameExt:nil]; if([fm createDirectoryAtPath:tempName attributes:nil]==NO){ NSRunAlertPanel(@"Error", @"Couldn't create temp dir:\n%@", @"Ok", nil, nil, tempName); return self; } if([pageMatrix numberOfColumns]!=1){ [pageMatrix addColumn]; id cell = [pageMatrix cellAtRow:0 column:0]; [cell setTag:1]; [cell setTitle:@" 1 "]; [pageMatrix sizeToFit]; [pageScroller display]; } imgDir = tempName; [imgDir retain]; } NSString *firstImagePath = [NSString stringWithFormat:@"%@/1.%@", imgDir, imgFmt]; if([fm fileExistsAtPath:firstImagePath]==NO && [fm copyPath:imgPath toPath:firstImagePath handler:nil]==NO){ NSRunAlertPanel(@"Error", @"Couldn't copy\n%@\nto\n%@", @"Ok", nil, nil, imgDir); return self; } NSImage *img; if((img = [[NSImage alloc] initWithContentsOfFile:firstImagePath])==nil){ int result = NSRunAlertPanel(@"Error", @"%@: Couldn't read first image:\n%@", @"Ok", @"Abort", nil, NSStringFromClass([self class]), firstImagePath); if(result==NSAlertAlternateReturn){ [[NSApplication sharedApplication] terminate:self]; } pages = -1; current = -1; return self; } NSArray *reps; NSImageRep *rep; reps = [img representations]; if(![reps count]){ // try again [img release]; return self; } img = [self imageLoadCompleteHook:img]; rep = [reps objectAtIndex:0]; NSRect newFrame = NSMakeRect(0, 0, [rep pixelsWide], [rep pixelsHigh]); [imgView setImage:img]; [img release]; pages = 1; current = 0; [pageMatrix selectCellAtRow:0 column:0]; return self; } - (NSImage *)imageLoadCompleteHook:(NSImage *)img { if(resolution!=IMAGE_DEFAULT_DPI){ float scale = (float)resolution/(float)IMAGE_DEFAULT_DPI; NSSize size = [img size], newSize = NSMakeSize(scale*size.width, scale*size.height); NSLog(@"scaling %@ from %@ to %@", imgPath, NSStringFromSize(size), NSStringFromSize(newSize)); NSBitmapImageRep *oldRep = [[img representations] objectAtIndex:0], *newRep; NSRect winRect = NSMakeRect(0, 0, newSize.width, newSize.height); NSWindow *pad = [[NSWindow alloc] initWithContentRect:winRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; NSView *padView = [pad contentView]; [padView lockFocus]; [[NSColor whiteColor] set]; [NSBezierPath fillRect:winRect]; [NSGraphicsContext saveGraphicsState]; PSscale(scale, scale); [oldRep draw]; [NSGraphicsContext restoreGraphicsState]; [pad flushWindow]; newRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[padView bounds]]; [padView unlockFocus]; renderWinClass = [pad class]; AUTORELEASE(pad); AUTORELEASE(newRep); NSImage *newImage = [[NSImage alloc] initWithSize:newSize]; [newImage addRepresentation:newRep]; AUTORELEASE(img); return newImage; } return img; } @end