home *** CD-ROM | disk | FTP | other *** search
- /* 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
-