This is MagnifyView.m in view mode; [Download] [Up]
/* File: MagnifyView.m - View class for 'Magnify' * * By: Christopher Lane * Symbolic Systems Resources Group * Knowledge Systems Laboratory * Stanford University * * Date: 9 January 1992 * * Copyright: 1990, 1991 & 1992 by The Leland Stanford Junior University. * This program may be distributed without restriction for non-commercial use. */ #import "Magnify.h" #import "MagnifyView.h" #import <appkit/Pasteboard.h> #define GRIDLINEMODE NX_COPY #define GRIDLINEWIDTH ((float) 1.0) #define NX_ALERTPANELLEVEL (NX_MAINMENULEVEL + 1) #define NXSetWindowLevel _NXSetWindowLevel extern int NXSetWindowLevel(int, int); @implementation MagnifyView + newFrame:(const NXRect *) frameRect; { const char *string; self = [super newFrame:frameRect]; frozen = NO; lock = mutex_alloc(); mouse = frameRect->origin; showCursor = (BOOL) (strncmp(getDefault(CURSORDEFAULTSTRING), YESSTRING, 1) == 0); if ((string = getDefault(SCALEDEFAULTSTRING)) == NULL || sscanf(string, FLOAT, &scale) != 1) scale = DEFAULTSCALE; if ((string = getDefault(GRIDDEFAULTSTRING)) == NULL || sscanf(string, FLOAT, &grid) != 1) grid = DEFAULTGRID; showGrid = (BOOL) (grid > 0.0); return [self createWindows]; } - (BOOL) acceptsFirstResponder { return YES; } - copy:sender { char *buffer; NXStream *stream; int length, maxLength; Pasteboard *pasteboard = [Pasteboard new]; [pasteboard declareTypes:&NXPostScriptPboardType num:1 owner:self]; stream = NXOpenMemory(NULL, 0, NX_WRITEONLY); [self copyPSCodeInside:&bounds to:stream]; NXFlush(stream); NXGetMemoryBuffer(stream, &buffer, &length, &maxLength); [pasteboard writeType:NXPostScriptPboard data:buffer length:length]; NXCloseMemory(stream, NX_FREEBUFFER); return self; } - drawSelf:(const NXRect *) rects :(int) rectCount { mutex_lock(lock); { NXImageBitmap(&virtualBounds, pixelsWide, pixelsHigh, bps, spp, config, mask, data[0], data[1], data[2], data[3], data[4]); if(showGrid) [self drawGrid]; if(showCursor) [self drawCursor]; } mutex_unlock(lock); return self; } - free { unsigned int i; if (invisibleWindow != nil) [invisibleWindow close]; for(i = 0; i < NX_MAXPLANES; i++) if (data[i] != NULL) free(data[i]); return [super free]; } - sizeTo:(NXCoord) newWidth :(NXCoord) newHeight; { id result; mutex_lock(lock); { result = [super sizeTo:newWidth :newHeight]; } mutex_unlock(lock); [self createWindows]; return result; } - mouseMoved:(NXEvent *)theEvent { int eventMask; if (mutex_try_lock(lock)) { eventMask = [window removeFromEventMask:NX_MOUSEMOVEDMASK]; { while([NXApp peekAndGetNextEvent:NX_MOUSEMOVEDMASK] != NULL); mouse = theEvent->location; [window convertBaseToScreen:&mouse]; } [window setEventMask:eventMask]; mutex_unlock(lock); [[self updateBitmap:&mouse] display]; } return [nextResponder mouseMoved:theEvent]; } - drawCursor { NXSize size; NXPoint point; NXImage *image; NXCursor *cursor; const NXPoint origin = { 1, -1 }, *hotSpot = &origin; if((cursor = [NXCursor currentCursor]) == nil) return nil; [(image = [cursor image]) getSize:&size]; // hotSpot = [cursor hotSpot]; /* NeXT left out this method! */ // (void) object_getInstanceVariable(cursor, "hotSpot", (void **) &hotSpot) /* should work, doesn't */ // hotSpot = (NXPoint *) (((void *) cursor) + 4); /* this hack works, 'but it would be wrong' */ point.x = rint((bounds.size.width + scale) * HALF) - hotSpot->x; point.y = rint((bounds.size.height + scale) * HALF) - (size.height + hotSpot->y); [image composite:NX_SOVER toPoint:&point]; return self; } - drawGrid { float x, y, max; max = bounds.origin.y + bounds.size.height; for(y = bounds.origin.y; y < max; y += grid) PScompositerect(bounds.origin.x, y, bounds.size.width, GRIDLINEWIDTH, GRIDLINEMODE); max = bounds.origin.x + bounds.size.width; for(x = bounds.origin.x; x < max; x += grid) PScompositerect(x, bounds.origin.y, GRIDLINEWIDTH, bounds.size.height, GRIDLINEMODE); return self; } - updateBitmap:(NXPoint *) point { NXRect rect; mutex_lock(lock); { [invisibleView getFrame:&rect]; [invisibleWindow moveTo:point->x - offset.width :point->y - offset.height]; [invisibleWindow orderFront:self]; { (void) [invisibleView lockFocus]; { NXReadBitmap(&rect, pixelsWide, pixelsHigh, bps, spp, config, mask, data[0], data[1], data[2], data[3], data[4]); } [invisibleView unlockFocus]; } [invisibleWindow orderOut:self]; } mutex_unlock(lock); return self; } - (float) scale { return scale; } - setScale:(float) value { mutex_lock(lock); { scale = value; } mutex_unlock(lock); return self; } - (float) grid { return grid; } - setGrid:(float) value { mutex_lock(lock); { showGrid = (BOOL) ((grid = value) > 0.0); } mutex_unlock(lock); return self; } - (BOOL) isFrozen { return frozen; } - toggleFrozen:sender { mutex_lock(lock); { if (frozen = !frozen) (void) [window removeFromEventMask:NX_MOUSEMOVEDMASK]; else (void) [window addToEventMask:NX_MOUSEMOVEDMASK]; } mutex_unlock(lock); [[NXApp mainMenu] update]; return self; } - toggleCursor:sender { mutex_lock(lock); { showCursor = !showCursor; } mutex_unlock(lock); return [self display]; } - createWindows { NXRect rect; size_t size; unsigned int i; mutex_lock(lock); { rect = bounds; offset.width = (rect.size.width = sizeof(int) * ceil((bounds.size.width / scale) / sizeof(int))) * HALF; offset.height = (rect.size.height = ceil(bounds.size.height / scale)) * HALF; virtualBounds = rect; virtualBounds.size.width *= scale; virtualBounds.size.height *= scale; if (invisibleWindow != nil) [invisibleWindow sizeWindow:rect.size.width :rect.size.height]; else { invisibleWindow = [Window newContent:&rect style:NX_PLAINSTYLE backing:NX_NONRETAINED buttonMask:NX_NOBUTTONS defer:NO]; PSsetautofill(NO, [invisibleWindow windowNum]); NXSetWindowLevel([invisibleWindow windowNum], NX_ALERTPANELLEVEL); [invisibleWindow setEventMask:NX_NULLEVENTMASK]; [(invisibleView = [invisibleWindow contentView]) allocateGState]; } (void) [invisibleView lockFocus]; { NXSizeBitmap(&rect, (int *) &size, &pixelsWide, &pixelsHigh, &bps, &spp, &config, &mask); } [invisibleView unlockFocus]; for(i = 0; i < NX_MAXPLANES; i++) { if(data[i] == NULL) data[i] = malloc(size); else if (size > malloc_size(data[i])) data[i] = realloc(data[i], size); if(config == NX_MESHED) break; } } mutex_unlock(lock); return [[self updateBitmap:&mouse] display]; } void timer(DPSTimedEntry teNumber, double now, void *id) { MagnifyView *self = (MagnifyView *) id; if (![self isFrozen]) { Window *window = [self window]; [window getMouseLocation:&(self->mouse)]; [window convertBaseToScreen:&(self->mouse)]; [[self updateBitmap:&(self->mouse)] display]; } } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.