#import "HexEditorDelegate.h" #import "HexWindowController.h" #import "HexTextView.h" @implementation HexEditorDelegate - (id)init { self = [super init]; if(!self) return nil; editedLow = NO; return self; } - (void)awakeFromNib { // - MOVED TO HEX WINDOW CONTROLLER DUE TO BUG IN IB MEANING OFFSET, HEX AND ASCII AREN'T SET AT THIS TIME // notify me when a view scrolls so I can update the other two // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[offset enclosingScrollView] contentView]]; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[hex enclosingScrollView] contentView]]; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[ascii enclosingScrollView] contentView]]; } /* REMOVE THESE WHEN I.B. IS FIXED */ - (void)setHex:(id)newView { hex = newView; } - (void)setAscii:(id)newView { ascii = newView; } /* END REMOVE MARKER */ /* data re-representation methods */ - (NSString *)offsetRepresentation:(NSData *)data { int dataLength = [data length], bytesPerRow = [controller bytesPerRow]; int rows = (dataLength / bytesPerRow) + ((dataLength % bytesPerRow)? 1:0); NSMutableString *representation = [NSMutableString string]; int row; for( row = 0; row < rows; row++ ) [representation appendFormat:@"%08lX:", row * bytesPerRow]; return representation; } /* delegation methods */ - (void)viewDidScroll:(NSNotification *)notification { // get object refs for increased speed NSClipView *object = (NSClipView *) [notification object]; NSClipView *offsetClip = [[offset enclosingScrollView] contentView]; NSClipView *hexClip = [[hex enclosingScrollView] contentView]; NSClipView *asciiClip = [[ascii enclosingScrollView] contentView]; // remove observer to stop myself from receiving bounds changed notifications (n.b. -setPostsBoundsChangedNotifications: only suspends them temporarilly - you get a unified bounds changed notification upon enabling it again and is designed for live resizing and such, so of no use here) [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewBoundsDidChangeNotification object:nil]; // when a view scrolls, update the other two if( object != offsetClip ) [offsetClip setBoundsOrigin:[object bounds].origin]; if( object != hexClip ) [hexClip setBoundsOrigin:[object bounds].origin]; if( object != asciiClip ) [asciiClip setBoundsOrigin:[object bounds].origin]; // restore notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:offsetClip]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:hexClip]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:asciiClip]; } - (NSRange)textView:(NSTextView *)textView willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange toCharacterRange:(NSRange)newSelectedCharRange { NSRange hexRange, asciiRange, byteRange = NSMakeRange(0,0); // temporarilly removing the delegate stops this function being called recursivly! id oldDelegate = [hex delegate]; [hex setDelegate:nil]; [ascii setDelegate:nil]; if( textView == hex ) // we're selecting hexadecimal { byteRange = [HexWindowController byteRangeFromHexRange:newSelectedCharRange]; asciiRange = [HexWindowController asciiRangeFromByteRange:byteRange]; [ascii setSelectedRange:asciiRange]; } else if( textView == ascii ) // we're selecting ASCII { byteRange = [HexWindowController byteRangeFromAsciiRange:newSelectedCharRange]; hexRange = [HexWindowController hexRangeFromByteRange:byteRange]; [hex setSelectedRange:hexRange]; } // put the new selection into the message bar [message setStringValue:[NSString stringWithFormat:@"Current selection: %@", NSStringFromRange(byteRange)]]; // restore delegates [hex setDelegate:oldDelegate]; [ascii setDelegate:oldDelegate]; return newSelectedCharRange; } - (HexWindowController *)controller { return controller; } - (NSTextView *)hex { return hex; } - (NSTextView *)ascii { return ascii; } - (BOOL)editedLow { return editedLow; } - (void)setEditedLow:(BOOL)flag { editedLow = flag; } - (NSRange)rangeForUserTextChange { // if editing hex, convert hex selection to byte selection if( [[controller window] firstResponder] == hex ) rangeForUserTextChange = [HexWindowController byteRangeFromHexRange:[hex rangeForUserTextChange]]; // if editing ascii, convert ascii selection to byte selection else if( [[controller window] firstResponder] == ascii ) rangeForUserTextChange = [HexWindowController byteRangeFromAsciiRange:[ascii rangeForUserTextChange]]; return rangeForUserTextChange; } @end