Use HexFiend.framework for the hex editor.

This commit is contained in:
Nate Weaver 2013-08-26 08:22:22 -05:00
parent 5f3978744c
commit 3944d28d43
40 changed files with 2510 additions and 2 deletions

View File

@ -507,9 +507,9 @@ static NSRange draggedRange;
@updated 2003-11-10 NGS: Changed algorithm.
*/
- (unsigned int)_insertionGlyphIndexForDrag:(id <NSDraggingInfo>)sender
- (NSUInteger)_insertionGlyphIndexForDrag:(id <NSDraggingInfo>)sender
{
unsigned int glyphIndex = (unsigned int) [super _insertionGlyphIndexForDrag:sender];
NSUInteger glyphIndex = (unsigned int) [super _insertionGlyphIndexForDrag:sender];
if(glyphIndex % 3 == 1) glyphIndex--;
if(glyphIndex % 3 == 2) glyphIndex++;
return glyphIndex;

1
HexFiend.framework/Headers Symbolic link
View File

@ -0,0 +1 @@
Versions/Current/Headers

1
HexFiend.framework/HexFiend Symbolic link
View File

@ -0,0 +1 @@
Versions/Current/HexFiend

View File

@ -0,0 +1 @@
Versions/Current/Resources

View File

@ -0,0 +1,26 @@
//
// HFAttributedByteArray.h
// HexFiend_2
//
// Copyright 2011 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFByteArray.h>
/*! @class HFAttributedByteArray
@brief An extension of HFByteArray that supports attributes.
HFAttributedByteArray is a subclass of HFByteArray that provides suitable overrides of the HFAttributes category.
*/
@class HFByteRangeAttributeArray;
@interface HFAttributedByteArray : HFByteArray {
@private
HFByteArray *impl;
HFByteRangeAttributeArray *attributes;
}
@end

View File

@ -0,0 +1,30 @@
//
// HFBTreeByteArray.h
// HexFiend_2
//
// Created by peter on 4/28/09.
// Copyright 2009 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFByteArray.h>
@class HFBTree;
/*! @class HFBTreeByteArray
@brief The principal efficient implementation of HFByteArray.
HFBTreeByteArray is an efficient subclass of HFByteArray that stores @link HFByteSlice HFByteSlices@endlink, using a 10-way B+ tree. This allows for insertion, deletion, and searching in approximately log-base-10 time.
Create an HFBTreeByteArray via \c -init. It has no methods other than those on HFByteArray.
*/
@interface HFBTreeByteArray : HFByteArray {
@private
HFBTree *btree;
}
/*! Designated initializer for HFBTreeByteArray.
*/
- init;
@end

View File

@ -0,0 +1,170 @@
//
// HFByteArray.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class HFByteSlice, HFProgressTracker, HFFileReference, HFByteRangeAttributeArray;
/*! @class HFByteArray
@brief The principal Model class for HexFiend's MVC architecture.
HFByteArray implements the Model portion of HexFiend.framework. It is logically a mutable, resizable array of bytes, with a 64 bit length. It is somewhat analagous to a 64 bit version of NSMutableData, except that it is designed to enable efficient (faster than O(n)) implementations of insertion and deletion.
HFByteArray, being an abstract class, will raise an exception if you attempt to instantiate it directly. For most uses, instantiate HFBTreeByteArray instead, with the usual <tt>[[class alloc] init]</tt>.
HFByteArray also exposes itself as an array of @link HFByteSlice HFByteSlices@endlink, which are logically immutable arrays of bytes. which is useful for operations such as file saving that need to access the underlying byte slices.
HFByteArray contains a generation count, which is incremented whenever the HFByteArray changes (to allow caches to be implemented on top of it). It also includes the notion of locking: a locked HFByteArray will raise an exception if written to, but it may still be read.
ByteArrays have the usual threading restrictions for non-concurrent data structures. It is safe to read an HFByteArray concurrently from multiple threads. It is not safe to read an HFByteArray while it is being modified from another thread, nor is it safe to modify one simultaneously from two threads.
HFByteArray is an abstract class. It will raise an exception if you attempt to instantiate it directly. The principal concrete subclass is HFBTreeByteArray.
*/
enum
{
HFHexDataStringType,
HFASCIIDataStringType
};
typedef NSUInteger HFByteArrayDataStringType;
@class HFByteRangeAttributeArray;
@interface HFByteArray : NSObject <NSCopying, NSMutableCopying> {
@private
NSUInteger changeLockCounter;
NSUInteger changeGenerationCount;
}
/*! @name Accessing raw data
*/
//@{
/*! Returns the length of the HFByteArray as a 64 bit unsigned long long. This is an abstract method that concrete subclasses must override. */
- (unsigned long long)length;
/*! Copies a range of bytes into a buffer. This is an abstract method that concrete subclasses must override. */
- (void)copyBytes:(unsigned char *)dst range:(HFRange)range;
//@}
/*! @name Accessing byte slices
Methods to access the byte slices underlying the HFByteArray.
*/
//@{
/*! Returns the contents of the receiver as an array of byte slices. This is an abstract method that concrete subclasses must override. */
- (NSArray *)byteSlices;
/*! Returns an NSEnumerator representing the byte slices of the receiver. This is implemented as enumerating over the result of -byteSlices, but subclasses can override this to be more efficient. */
- (NSEnumerator *)byteSliceEnumerator;
/*! Returns the byte slice containing the byte at the given index, and the actual offset of this slice. */
- (HFByteSlice *)sliceContainingByteAtIndex:(unsigned long long)offset beginningOffset:(unsigned long long *)actualOffset;
//@}
/*! @name Modifying the byte array
Methods to modify the given byte array.
*/
//@{
/*! Insert an HFByteSlice in the given range. The maximum value of the range must not exceed the length of the subarray. The length of the given slice is not required to be equal to length of the range - in other words, this method may change the length of the receiver. This is an abstract method that concrete subclasses must override. */
- (void)insertByteSlice:(HFByteSlice *)slice inRange:(HFRange)lrange;
/*! Insert an HFByteArray in the given range. This is implemented via calling <tt>insertByteSlice:inRange:</tt> with the byte slices from the given byte array. */
- (void)insertByteArray:(HFByteArray *)array inRange:(HFRange)lrange;
/*! Delete bytes in the given range. This is implemented on the base class by creating an empty byte array and inserting it in the range to be deleted, via <tt>insertByteSlice:inRange:</tt>. */
- (void)deleteBytesInRange:(HFRange)range;
/*! Returns a new HFByteArray containing the given range. This is an abstract method that concrete subclasses must override. */
- (HFByteArray *)subarrayWithRange:(HFRange)range;
//@}
/*! @name Write locking and generation count
Methods to lock and query the lock that prevents writes.
*/
//@{
/*! Increment the change lock. Until the change lock reaches 0, all modifications to the receiver will raise an exception. */
- (void)incrementChangeLockCounter;
/*! Decrement the change lock. If the change lock reaches 0, modifications will be allowed again. */
- (void)decrementChangeLockCounter;
/*! Query if the changes are locked. This method is KVO compliant. */
- (BOOL)changesAreLocked;
//@}
/* @name Generation count
Manipulate the generation count */
// @{
/*! Increments the generation count, unless the receiver is locked, in which case it raises an exception. All subclasses of HFByteArray should call this method at the beginning of any overridden method that may modify the receiver.
@param sel The selector that would modify the receiver (e.g. <tt>deleteBytesInRange:</tt>). This is usually <tt>_cmd</tt>. */
- (void)incrementGenerationOrRaiseIfLockedForSelector:(SEL)sel;
/*! Return the change generation count. Every change to the ByteArray increments this by one or more. This can be used for caching layers on top of HFByteArray, to known when to expire their cache. */
- (NSUInteger)changeGenerationCount;
//@}
/*! @name Searching
*/
//@{
/*! Searches the receiver for a byte array matching findBytes within the given range, and returns the index that it was found. This is a concrete method on HFByteArray.
@param findBytes The HFByteArray containing the data to be found (the needle to the receiver's haystack).
@param range The range of the receiver in which to search. The end of the range must not exceed the receiver's length.
@param forwards If this is YES, then the first match within the range is returned. Otherwise the last is returned.
@param progressTracker An HFProgressTracker to allow progress reporting and cancelleation for the search operation.
@return The index in the receiver of bytes equal to <tt>findBytes</tt>, or ULLONG_MAX if the byte array was not found (or the operation was cancelled)
*/
- (unsigned long long)indexOfBytesEqualToBytes:(HFByteArray *)findBytes inRange:(HFRange)range searchingForwards:(BOOL)forwards trackingProgress:(HFProgressTracker *)progressTracker;
//@}
@end
/*! @category HFByteArray(HFFileWriting)
@brief HFByteArray methods for writing to files, and preparing other HFByteArrays for potentially destructive file writes.
*/
@interface HFByteArray (HFFileWriting)
/*! Attempts to write the receiver to a file. This is a concrete method on HFByteArray.
@param targetURL A URL to the file to be written to. It is OK for the receiver to contain one or more instances of HFByteSlice that are sourced from the file.
@param progressTracker An HFProgressTracker to allow progress reporting and cancelleation for the write operation.
@param error An out NSError parameter.
@return YES if the write succeeded, NO if it failed.
*/
- (BOOL)writeToFile:(NSURL *)targetURL trackingProgress:(HFProgressTracker *)progressTracker error:(NSError **)error;
/*! Returns the ranges of the file that would be modified, if the receiver were written to it. This is useful (for example) in determining if the clipboard can be preserved after a save operation. This is a concrete method on HFByteArray.
@param reference An HFFileReference to the file to be modified
@return An array of @link HFRangeWrapper HFRangeWrappers@endlink, representing the ranges of the file that would be affected. If no range would be affected, the result is an empty array.
*/
- (NSArray *)rangesOfFileModifiedIfSavedToFile:(HFFileReference *)reference;
/*! Attempts to modify the receiver so that it no longer depends on any of the HFRanges in the array within the given file. It is not necessary to perform this operation on the byte array that is being written to the file.
@param ranges An array of HFRangeWrappers, representing ranges in the given file that the receiver should no longer depend on.
@param reference The HFFileReference that the receiver should no longer depend on.
@param hint A dictionary that can be used to improve the efficiency of the operation, by allowing multiple byte arrays to share the same state. If you plan to call this method on multiple byte arrays, pass the first one an empty NSMutableDictionary, and pass the same dictionary to subsequent calls.
@return A YES return indicates the operation was successful, and the receiver no longer contains byte slices that source data from any of the ranges of the given file (or never did). A NO return indicates that breaking the dependencies would require too much memory, and so the receiver still depends on some of those ranges.
*/
- (BOOL)clearDependenciesOnRanges:(NSArray *)ranges inFile:(HFFileReference *)reference hint:(NSMutableDictionary *)hint;
@end
/*! @category HFByteArray(HFAttributes)
@brief HFByteArray methods for attributes of byte arrays.
*/
@interface HFByteArray (HFAttributes)
/*! Returns a byte range attribute array for the bytes in the given range. */
- (HFByteRangeAttributeArray *)attributesForBytesInRange:(HFRange)range;
/*! Returns the HFByteArray level byte range attribute array. Default is to return nil. */
- (HFByteRangeAttributeArray *)byteRangeAttributeArray;
@end

View File

@ -0,0 +1,60 @@
//
// HFByteArrayEditScript.h
// HexFiend_2
//
// Copyright 2010 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <HexFiend/HFTYpes.h>
/*! @class HFByteArrayEditScript
@brief A class that represents an sequence of instructions for editing an @link HFByteArray @endlink.
HFByteArrayEditScript is useful for representing a diff between two HFByteArrays.
*/
@class HFByteArray, HFProgressTracker;
/*! @struct HFEditInstruction_t
@brief A struct that represents a single instruction in an @link HFByteArrayEditScript @endlink.
Replace the bytes in the source in range 'src' with bytes from the destination in range 'dst'. Note that if src is empty, then it is a pure insertion at src.location; if dst is empty it is a pure deletion of src. If neither is empty, it is replacing some bytes with others. It should never happen that both are empty.
*/
struct HFEditInstruction_t {
/*! Source range, to be replaced */
HFRange src;
/*! Destination range, that does the replacing */
HFRange dst;
};
@interface HFByteArrayEditScript : NSObject {
HFByteArray *source;
HFByteArray *destination;
unsigned long long sourceLength;
unsigned long long destLength;
volatile const int *cancelRequested;
volatile int64_t *currentProgress;
int32_t concurrentProcesses;
dispatch_queue_t insnQueue;
__strong struct HFEditInstruction_t *insns;
size_t insnCount, insnCapacity;
}
/*! Computes the edit script (differences) from src to dst. This retains both src and dst, and if they are modified then the receiver will likely no longer function. You may optionally pass an HFProgressTracker for progress reporting and cancellation. This returns nil if it was cancelled. */
- (id)initWithDifferenceFromSource:(HFByteArray *)src toDestination:(HFByteArray *)dst trackingProgress:(HFProgressTracker *)progressTracker;
/*! Applies the receiver to an HFByteArray. */
- (void)applyToByteArray:(HFByteArray *)byteArray;
/*! Returns the number of instructions. */
- (NSUInteger)numberOfInstructions;
/*! Returns the instruction at a given index. */
- (struct HFEditInstruction_t)instructionAtIndex:(NSUInteger)index;
@end

View File

@ -0,0 +1,22 @@
#import <Foundation/NSString.h>
/* Attributes used to illustrate diffs. */
extern NSString * const kHFAttributeDiffInsertion;
/* Attribute used for illustrating a focused range of characters. */
extern NSString * const kHFAttributeFocused;
/* Attributes used for address spaces of other processes. */
extern NSString * const kHFAttributeUnmapped; /* A range that is not allocated, used to describe sparse data sets (e.g. a virtual address space). */
extern NSString * const kHFAttributeUnreadable; /* A range that is allocated but is not readable. */
extern NSString * const kHFAttributeWritable; /* A range that is writable. */
extern NSString * const kHFAttributeExecutable; /* A range that is executable. */
extern NSString * const kHFAttributeShared; /* A range that is shared memory. */
extern NSString * const kHFAttributeMagic; /* For testing. */
/* Bookmark attribute. Pass an integer (the bookmark) and get back a string that can be used as an attribute. */
extern NSString *HFBookmarkAttributeFromBookmark(NSInteger bookmark);
/* Given a bookmark string, return the bookmark index for it, or NSNotFound if the string does not represent a bookmark attribute. */
extern NSInteger HFBookmarkFromBookmarkAttribute(NSString *bookmark);

View File

@ -0,0 +1,63 @@
//
// HFByteRangeAttributeArray.h
// HexFiend_2
//
// Copyright 2009 ridiculous_fish. All rights reserved.
//
#import <Foundation/Foundation.h>
/*! @class HFByteRangeAttributeArray
@brief A class that represents sets of attributes, attached to ranges of bytes.
*/
@interface HFByteRangeAttributeArray : NSObject <NSMutableCopying> {
}
/*! Returns the set of attributes at the given index, and the length over which those attributes are valid (if not NULL). */
- (NSSet *)attributesAtIndex:(unsigned long long)index length:(unsigned long long *)length;
/*! Returns the set of attributes within the given range. */
- (NSSet *)attributesInRange:(HFRange)range;
/*! Returns the first range of a given attribute. If it is not present, returns {ULLONG_MAX, ULLONG_MAX} */
- (HFRange)rangeOfAttribute:(NSString *)attribute;
/*! Adds a given attribute for a given range. */
- (void)addAttribute:(NSString *)attributeName range:(HFRange)range;
/*! Removes the given attribute within the given range. */
- (void)removeAttribute:(NSString *)attributeName range:(HFRange)range;
/*! Removes the given attribute entirely. */
- (void)removeAttribute:(NSString *)attributeName;
/*! Removes the given attributes entirely. */
- (void)removeAttributes:(NSSet *)attributeName;
/*! Returns whether the receiver is empty. This should be a count instead. */
- (BOOL)isEmpty;
/*! Returns an NSEnumerator of the attributes. The attributes are returned in order, but there is no way to get the range of each attribute. */
- (NSEnumerator *)attributeEnumerator;
/*! Called from HFByteArray to indicate when the bytes have changed, and the attributes need to be fixed up. */
- (void)byteRange:(HFRange)srcRange wasReplacedByBytesOfLength:(unsigned long long)replacementLength;
/*! Transfer attributes in the given range from array, adding baseOffset to each attribute range. range is interpreted as a range in array. If validator is not NULL, then it is called for each attribute; a YES return allows it to be added and a NO return prevents it. */
- (void)transferAttributesFromAttributeArray:(HFByteRangeAttributeArray *)array range:(HFRange)range baseOffset:(unsigned long long)baseOffset validator:(BOOL (^)(NSString *))allowTransfer;
@end
#ifndef DOXYGEN_ONLY
@interface HFNaiveByteRangeAttributeArray : HFByteRangeAttributeArray {
NSMutableArray *attributeRuns;
}
@end
@class HFAnnotatedTree;
@interface HFAnnotatedTreeByteRangeAttributeArray : HFByteRangeAttributeArray {
HFAnnotatedTree *atree;
NSMutableDictionary *attributesToNodes;
}
@end
#endif

View File

@ -0,0 +1,53 @@
//
// HFByteSlice.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class HFFileReference, HFByteRangeAttributeArray;
/*! @class HFByteSlice
@brief A class representing a source of data for an HFByteArray.
HFByteSlice is an abstract class encapsulating primitive data sources (files, memory buffers, etc.). Each source must support random access reads, and have a well defined length. All HFByteSlices are \b immutable.
The two principal subclasses of HFByteSlice are HFSharedMemoryByteSlice and HFFileByteSlice, which respectively encapsulate data from memory and from a file.
*/
@interface HFByteSlice : NSObject {
NSUInteger retainCount;
}
/*! Return the length of the byte slice as a 64 bit value. This is an abstract method that concrete subclasses must override. */
- (unsigned long long)length;
/*! Copies a range of data from the byte slice into an in-memory buffer. This is an abstract method that concrete subclasses must override. */
- (void)copyBytes:(unsigned char *)dst range:(HFRange)range;
/*! Returns a new slice containing a subrange of the given slice. This is an abstract method that concrete subclasses must override. */
- (HFByteSlice *)subsliceWithRange:(HFRange)range;
/*! Attempts to create a new byte slice by appending one byte slice to another. This does not modify the receiver or the slice argument (after all, both are immutable). This is provided as an optimization, and is allowed to return nil if the appending cannot be done efficiently. The default implementation returns nil.
*/
- (id)byteSliceByAppendingSlice:(HFByteSlice *)slice;
/*! Returns YES if the receiver is sourced from a file. The default implementation returns NO. This is used to estimate cost when writing to a file.
*/
- (BOOL)isSourcedFromFile;
/*! For a given file reference, returns the range within the file that the receiver is sourced from. If the receiver is not sourced from this file, returns {ULLONG_MAX, ULLONG_MAX}. The default implementation returns {ULLONG_MAX, ULLONG_MAX}. This is used during file saving to to determine how to properly overwrite a given file.
*/
- (HFRange)sourceRangeForFile:(HFFileReference *)reference;
@end
/*! @category HFByteSlice(HFAttributes)
@brief Methods for querying attributes of individual byte slices. */
@interface HFByteSlice (HFAttributes)
/*! Returns the attributes for the bytes in the given range. */
- (HFByteRangeAttributeArray *)attributesForBytesInRange:(HFRange)range;
@end

View File

@ -0,0 +1,16 @@
//
// HFCancelButton.h
// HexFiend_2
//
// Created by peter on 6/11/08.
// Copyright 2008 ridiculous_fish. All rights reserved.
//
#import <AppKit/NSButton.h>
/*! @class HFCancelButton
@brief A simple subclass of NSButton that has the correct appearance for cancelling. This is not a generally useful class. */
@interface HFCancelButton : NSButton
@end

View File

@ -0,0 +1,459 @@
//
// HFController.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <HexFiend/HFTypes.h>
/*! @header HFController
@abstract The HFController.h header contains the HFController class, which is a central class in Hex Fiend.
*/
@class HFRepresenter, HFByteArray, HFFileReference, HFControllerCoalescedUndo, HFByteRangeAttributeArray;
/*! @enum HFControllerPropertyBits
The HFControllerPropertyBits bitmask is used to inform the HFRepresenters of a change in the current state that they may need to react to. A bitmask of the changed properties is passed to representerChangedProperties:. It is common for multiple properties to be included in such a bitmask.
*/
enum
{
HFControllerContentValue = 1 << 0, /*!< Indicates that the contents of the ByteArray has changed within the document. There is no indication as to what the change is. If redisplaying everything is expensive, Representers should cache their displayed data and compute any changes manually. */
HFControllerContentLength = 1 << 1, /*!< Indicates that the length of the ByteArray has changed. */
HFControllerDisplayedLineRange = 1 << 2, /*!< Indicates that the displayedLineRange property of the document has changed (e.g. the user scrolled). */
HFControllerSelectedRanges = 1 << 3, /*!< Indicates that the selectedContentsRanges property of the document has changed (e.g. the user selected some other range). */
HFControllerSelectionPulseAmount = 1 << 4, /*!< Indicates that the amount of "pulse" to show in the Find pulse indicator has changed. */
HFControllerBytesPerLine = 1 << 5, /*!< Indicates that the number of bytes to show per line has changed. */
HFControllerBytesPerColumn = 1 << 6, /*!< Indicates that the number of bytes per column (byte grouping) has changed. */
HFControllerEditable = 1 << 7, /*!< Indicates that the document has become (or is no longer) editable. */
HFControllerFont = 1 << 8, /*!< Indicates that the font property has changed. */
HFControllerAntialias = 1 << 9, /*!< Indicates that the shouldAntialias property has changed. */
HFControllerLineHeight = 1 << 10, /*!< Indicates that the lineHeight property has changed. */
HFControllerViewSizeRatios = 1 << 11, /*!< Indicates that the optimum size for each view may have changed; used by HFLayoutController after font changes. */
HFControllerByteRangeAttributes = 1 << 12, /*!< Indicates that some attributes of the ByteArray has changed within the document. There is no indication as to what the change is. */
HFControllerByteGranularity = 1 << 13, /*!< Indicates that the byte granularity has changed. For example, when moving from ASCII to UTF-16, the byte granularity increases from 1 to 2. */
HFControllerBookmarks = 1 << 14 /*!< Indicates that a bookmark has been added or removed. */
};
typedef NSUInteger HFControllerPropertyBits;
/*! @enum HFControllerMovementDirection
The HFControllerMovementDirection enum is used to specify a direction (either left or right) in various text editing APIs. HexFiend does not support left-to-right languages.
*/
enum
{
HFControllerDirectionLeft,
HFControllerDirectionRight
};
typedef NSInteger HFControllerMovementDirection;
/*! @enum HFControllerSelectionTransformation
The HFControllerSelectionTransformation enum is used to specify what happens to the selection in various APIs. This is mainly interesting for text-editing style Representers.
*/
enum
{
HFControllerDiscardSelection, /*!< The selection should be discarded. */
HFControllerShiftSelection, /*!< The selection should be moved, without changing its length. */
HFControllerExtendSelection /*!< The selection should be extended, changing its length. */
};
typedef NSInteger HFControllerSelectionTransformation;
/*! @enum HFControllerMovementGranularity
The HFControllerMovementGranularity enum is used to specify the granularity of text movement in various APIs. This is mainly interesting for text-editing style Representers.
*/
enum
{
HFControllerMovementByte, /*!< Move by individual bytes */
HFControllerMovementColumn, /*!< Move by a column */
HFControllerMovementLine, /*!< Move by lines */
HFControllerMovementPage, /*!< Move by pages */
HFControllerMovementDocument /*!< Move by the whole document */
};
typedef NSInteger HFControllerMovementGranularity;
/*! @enum HFEditMode
HFEditMode enumerates the different edit modes that a document might be in.
*/
typedef enum {
HFInsertMode,
HFOverwriteMode,
HFReadOnlyMode,
} HFEditMode;
/*! @class HFController
@brief A central class that acts as the controller layer for HexFiend.framework
HFController acts as the controller layer in the MVC architecture of HexFiend. The HFController plays several significant central roles, including:
- Mediating between the data itself (in the HFByteArray) and the views of the data (the @link HFRepresenter HFRepresenters@endlink).
- Propagating changes to the views.
- Storing properties common to all Representers, such as the currently diplayed range, the currently selected range(s), the font, etc.
- Handling text editing actions, such as selection changes or insertions/deletions.
An HFController is the top point of ownership for a HexFiend object graph. It retains both its ByteArray (model) and its array of Representers (views).
You create an HFController via <tt>[[HFController alloc] init]</tt>. After that, give it an HFByteArray via setByteArray:, and some Representers via addRepresenter:. Then insert the Representers' views in a window, and you're done.
*/
@interface HFController : NSObject <NSCoding> {
@private
NSMutableArray *representers;
HFByteArray *byteArray;
NSMutableArray *selectedContentsRanges;
HFRange displayedContentsRange;
HFFPRange displayedLineRange;
NSUInteger bytesPerLine;
NSUInteger bytesPerColumn;
NSFont *font;
CGFloat lineHeight;
NSUInteger currentPropertyChangeToken;
NSMutableArray *additionalPendingTransactions;
HFControllerPropertyBits propertiesToUpdateInCurrentTransaction;
NSUndoManager *undoManager;
NSMutableSet *undoOperations;
HFControllerCoalescedUndo *undoCoalescer;
unsigned long long selectionAnchor;
HFRange selectionAnchorRange;
CFAbsoluteTime pulseSelectionStartTime, pulseSelectionCurrentTime;
NSTimer *pulseSelectionTimer;
/* Basic cache support */
HFRange cachedRange;
NSData *cachedData;
NSUInteger cachedGenerationIndex;
struct {
unsigned antialias:1;
HFEditMode editMode:2;
unsigned editable:1;
unsigned selectable:1;
unsigned selectionInProgress:1;
unsigned shiftExtendSelection:1;
unsigned commandExtendSelection:1;
unsigned reserved1:25;
unsigned reserved2:32;
} _hfflags;
}
/*! @name Representer handling.
Methods for modifying the list of HFRepresenters attached to a controller. Attached representers receive the controllerDidChange: message when various properties of the controller change. A representer may only be attached to one controller at a time. Representers are retained by the controller.
*/
//@{
/*! Gets the current array of representers attached to this controller. */
- (NSArray *)representers;
/*! Adds a new representer to this controller. */
- (void)addRepresenter:(HFRepresenter *)representer;
/*! Removes an existing representer from this controller. The representer must be present in the array of representers. */
- (void)removeRepresenter:(HFRepresenter *)representer;
//@}
/*! @name Property transactions
Methods for temporarily delaying notifying representers of property changes. There is a property transaction stack, and all property changes are collected until the last token is popped off the stack, at which point all representers are notified of all collected changes via representerChangedProperties:. To use this, call beginPropertyChangeTransaction, and record the token that is returned. Pass it to endPropertyChangeTransaction: to notify representers of all changed properties in bulk.
Tokens cannot be popped out of order - they are used only as a correctness check.
*/
//@{
/*! Begins delaying property change transactions. Returns a token that should be passed to endPropertyChangeTransactions:. */
- (NSUInteger)beginPropertyChangeTransaction;
/*! Pass a token returned from beginPropertyChangeTransaction to this method to pop the transaction off the stack and, if the stack is empty, to notify Representers of all collected changes. Tokens cannot be popped out of order - they are used strictly as a correctness check. */
- (void)endPropertyChangeTransaction:(NSUInteger)token;
//@}
/*! @name Byte array
Set and get the byte array. */
//@{
/*! Sets the byte array for the HFController. The byte array must be non-nil. */
- (void)setByteArray:(HFByteArray *)val;
/*! Returns the byte array for the HFController. In general, HFRepresenters should not use this to determine what bytes to display. Instead they should use copyBytes:range: or dataForRange: below. */
- (HFByteArray *)byteArray;
/*! Replaces the entire byte array with a new one, preserving as much of the selection as possible. Unlike setByteArray:, this method is undoable, and intended to be used from representers that make a global change (such as Replace All). */
- (void)replaceByteArray:(HFByteArray *)newArray;
//@}
/*! @name Properties shared between all representers
The following properties are considered global among all HFRepresenters attached to the receiver.
*/
//@{
/*! Returns the number of lines on which the cursor may be placed. This is always at least 1, and is equivalent to (unsigned long long)(HFRoundUpToNextMultiple(contentsLength, bytesPerLine) / bytesPerLine) */
- (unsigned long long)totalLineCount;
/*! Indicates the number of bytes per line, which is a global property among all the line-oriented representers. */
- (NSUInteger)bytesPerLine;
/*! Returns the height of a line, in points. This is generally determined by the font. Representers that wish to align things to lines should use this. */
- (CGFloat)lineHeight;
//@}
/*! @name Selection pulsing
Used to show the current selection after a change, similar to Find in Safari
*/
//{@
/*! Begins selection pulsing (e.g. following a successful Find operation). Representers will receive callbacks indicating that HFControllerSelectionPulseAmount has changed. */
- (void)pulseSelection;
/*! Return the amount that the "Find pulse indicator" should show. 0 means no pulse, 1 means maximum pulse. This is useful for Representers that support find and replace. */
- (double)selectionPulseAmount;
//@}
/*! @name Selection handling
Methods for manipulating the current selected ranges. Hex Fiend supports discontiguous selection.
*/
//{@
/*! Returns an array of HFRangeWrappers, representing the selected ranges. This method always contains at least one range. If there is no selection, then the result will contain a single range of length 0, with the location equal to the position of the cursor. */
- (NSArray *)selectedContentsRanges;
/*! Explicitly set the selected contents ranges. Pass an array of HFRangeWrappers that meets the following criteria:
The array must not be NULL.
There always must be at least one selected range.
If any range has length 0, there must be exactly one selected range.
No range may extend beyond the contentsLength, with the exception of a single zero-length range, which may be at the end.
*/
- (void)setSelectedContentsRanges:(NSArray *)selectedRanges;
/*! Selects the entire contents. */
- (IBAction)selectAll:(id)sender;
/*! Returns the smallest value in the selected contents ranges, or the insertion location if the selection is empty. */
- (unsigned long long)minimumSelectionLocation;
/*! Returns the largest HFMaxRange of the selected contents ranges, or the insertion location if the selection is empty. */
- (unsigned long long)maximumSelectionLocation;
/*! Convenience method for creating a byte array containing all of the selected bytes. If the selection has length 0, this returns an empty byte array. */
- (HFByteArray *)byteArrayForSelectedContentsRanges;
//@}
/*! @name Bytes per column
Set and get the number of bytes per column. */
//@{
/* Sets the number of bytes used in each column for a text-style representer. */
- (void)setBytesPerColumn:(NSUInteger)val;
/* Returns the number of bytes used in each column for a text-style representer. */
- (NSUInteger)bytesPerColumn;
//@}
/*! @name Edit Mode
Determines what mode we're in, read-only, overwrite or insert. */
//@{
- (HFEditMode)editMode;
- (void)setEditMode:(HFEditMode)val;
//@}
/*! @name Displayed line range
Methods for setting and getting the current range of displayed lines.
*/
//{@
/*! Get the current displayed line range. The displayed line range is an HFFPRange (range of long doubles) containing the lines that are currently displayed.
The values may be fractional. That is, if only the bottom half of line 4 through the top two thirds of line 8 is shown, then the displayedLineRange.location will be 4.5 and the displayedLineRange.length will be 3.17 ( = 7.67 - 4.5). Representers are expected to be able to handle such fractional values.
*/
- (HFFPRange)displayedLineRange;
/*! Sets the displayed line range. When setting the displayed line range, the given range must be nonnegative, and the maximum of the range must be no larger than the total line count. See the -displayedLineRange method for more information. */
- (void)setDisplayedLineRange:(HFFPRange)range;
/*! Modify the displayedLineRange as little as possible so that as much of the given range as can fit is visible. */
- (void)maximizeVisibilityOfContentsRange:(HFRange)range;
/*! Modify the displayedLineRange as to center the given contents range. If the range is near the bottom or top, this will center as close as possible. If contents range is too large to fit, it centers the top of the range. contentsRange may be empty. */
- (void)centerContentsRange:(HFRange)range;
//@}
/*! @name Font
Get and set the current font.
*/
//@{
/*! Get the current font. */
- (NSFont *)font;
/*! Set the current font. */
- (void)setFont:(NSFont *)font;
/*! @name Undo management
Get and set the undo manager. If no undo manager is set, then undo is not supported.
*/
//@{
/*! Set the undo manager for this HFController. By default the undo manager for an HFController is nil. If one is not set, undo does not occur. This retains the undo manager. */
- (void)setUndoManager:(NSUndoManager *)manager;
/*! Gets the undo manager for this HFController. By default the undo manager is nil. Undo will not be supported unless an undo manager is set. */
- (NSUndoManager *)undoManager;
//@}
/*! @name Editability
Set and get whether representers should allow editing the data.
*/
//@{
/*! Get the editable property, which determines whether the user can edit the document. */
- (BOOL)editable;
/*! Set the editable property, which determines whether the user can edit the document. */
- (void)setEditable:(BOOL)flag;
//@}
/*! @name Antialiasing
Set and get whether the text should be antialiased. Note that Mac OS X settings may prevent antialiasing text below a certain point size. */
//@{
/*! Returns whether text should be antialiased. */
- (BOOL)shouldAntialias;
/*! Sets whether text should be antialiased. */
- (void)setShouldAntialias:(BOOL)antialias;
//@}
/*! Representer initiated property changes
Called from a representer to indicate when some internal property of the representer has changed which requires that some properties be recalculated.
*/
//@{
/*! Callback for a representer-initiated change to some property. For example, if some property of a view changes that would cause the number of bytes per line to change, then the representer should call this method which will trigger the HFController to recompute the relevant properties. */
- (void)representer:(HFRepresenter *)rep changedProperties:(HFControllerPropertyBits)properties;
//@}
/*! @name Mouse selection
Methods to handle mouse selection. Representers that allow text selection should call beginSelectionWithEvent:forByteIndex: upon receiving a mouseDown event, and then continueSelectionWithEvent:forByteIndex: for mouseDragged events, terminating with endSelectionWithEvent:forByteIndex: upon receiving the mouse up. HFController will compute the correct selected ranges and propagate any changes via the HFControllerPropertyBits mechanism. */
//@{
/*! Begin a selection session, with a mouse down at the given byte index. */
- (void)beginSelectionWithEvent:(NSEvent *)event forByteIndex:(unsigned long long)byteIndex;
/*! Continue a selection session, whe the user drags over the given byte index. */
- (void)continueSelectionWithEvent:(NSEvent *)event forByteIndex:(unsigned long long)byteIndex;
/*! End a selection session, with a mouse up at the given byte index. */
- (void)endSelectionWithEvent:(NSEvent *)event forByteIndex:(unsigned long long)byteIndex;
/*! @name Scrollling
Support for the mouse wheel and scroll bars. */
//@{
/*! Trigger scrolling appropriate for the given scroll event. */
- (void)scrollWithScrollEvent:(NSEvent *)scrollEvent;
/*! Trigger scrolling by the given number of lines. If lines is positive, then the document is scrolled down; otherwise it is scrolled up. */
- (void)scrollByLines:(long double)lines;
//@}
/*! @name Keyboard navigation
Support for chaging the selection via the keyboard
*/
/*! General purpose navigation function. Modify the selection in the given direction by the given number of bytes. The selection is modifed according to the given transformation. If useAnchor is set, then anchored selection is used; otherwise any anchor is discarded.
This has a few limitations:
- Only HFControllerDirectionLeft and HFControllerDirectionRight movement directions are supported.
- Anchored selection is not supported for HFControllerShiftSelection (useAnchor must be NO)
*/
- (void)moveInDirection:(HFControllerMovementDirection)direction byByteCount:(unsigned long long)amountToMove withSelectionTransformation:(HFControllerSelectionTransformation)transformation usingAnchor:(BOOL)useAnchor;
/*! Navigation designed for key events. */
- (void)moveInDirection:(HFControllerMovementDirection)direction withGranularity:(HFControllerMovementGranularity)granularity andModifySelection:(BOOL)extendSelection;
- (void)moveToLineBoundaryInDirection:(HFControllerMovementDirection)direction andModifySelection:(BOOL)extendSelection;
/*! @name Text editing
Methods to support common text editing operations */
//@{
/*! Replaces the selection with the given data. For something like a hex view representer, it takes two keypresses to create a whole byte; the way this is implemented, the first keypress goes into the data as a complete byte, and the second one (if any) replaces it. If previousByteCount > 0, then that many prior bytes are replaced, without breaking undo coalescing. For previousByteCount to be > 0, the following must be true: There is only one selected range, and it is of length 0, and its location >= previousByteCount
These functions return YES if they succeed, and NO if they fail. Currently they may fail only in overwrite mode, if you attempt to insert data that would require lengthening the byte array.
These methods are undoable.
*/
- (BOOL)insertByteArray:(HFByteArray *)byteArray replacingPreviousBytes:(unsigned long long)previousByteCount allowUndoCoalescing:(BOOL)allowUndoCoalescing;
- (BOOL)insertData:(NSData *)data replacingPreviousBytes:(unsigned long long)previousByteCount allowUndoCoalescing:(BOOL)allowUndoCoalescing;
/*! Deletes the selection. This operation is undoable. */
- (void)deleteSelection;
/*! If the selection is empty, deletes one byte in a given direction, which must be HFControllerDirectionLeft or HFControllerDirectionRight; if the selection is not empty, deletes the selection. Undoable. */
- (void)deleteDirection:(HFControllerMovementDirection)direction;
//@}
/*! @name Reading data
Methods for reading data */
/*! Returns an NSData representing the given HFRange. The length of the HFRange must be of a size that can reasonably be fit in memory. This method may cache the result. */
- (NSData *)dataForRange:(HFRange)range;
/*! Copies data within the given HFRange into an in-memory buffer. This is equivalent to [[controller byteArray] copyBytes:bytes range:range]. */
- (void)copyBytes:(unsigned char *)bytes range:(HFRange)range;
/*! Convenience method that returns the attributes of the underlying byte array. You can message it directly to add and remove attributes. If you do so, be sure to call representer:changedProperties: with the HFControllerByteRangeAttributes bit */
- (HFByteRangeAttributeArray *)byteRangeAttributeArray;
/*! Returns the attributes for the given range. This is a union of the receiver's byteRangeAttributeArray properties and the properties returned by the byte array itself. range.length must be <= NSUIntegerMax. */
- (HFByteRangeAttributeArray *)attributesForBytesInRange:(HFRange)range;
/*! Returns the range for the given bookmark. If there is no bookmark, returns {ULLONG_MAX, ULLONG_MAX}. */
- (HFRange)rangeForBookmark:(NSInteger)bookmark;
/*! Sets the range for the given bookmark. Pass {ULLONG_MAX, ULLONG_MAX} to remove the bookmark. Undoable. */
- (void)setRange:(HFRange)range forBookmark:(NSInteger)bookmark;
/*! Returns an NSIndexSet of the bookmarks in the given range. */
- (NSIndexSet *)bookmarksInRange:(HFRange)range;
/*! Returns total number of bytes. This is equivalent to [[controller byteArray] length]. */
- (unsigned long long)contentsLength;
/*! @name File writing dependency handling
*/
//@{
/*! Attempts to clear all dependencies on the given file (clipboard, undo, etc.) that could not be preserved if the file were written. Returns YES if we successfully prepared, NO if someone objected. This works by posting a HFPrepareForChangeInFileNotification. HFController does not register for this notification: instead the owners of the HFController are expected to register for HFPrepareForChangeInFileNotification and react appropriately. */
+ (BOOL)prepareForChangeInFile:(NSURL *)targetFile fromWritingByteArray:(HFByteArray *)array;
/*! Attempts to break undo stack dependencies for writing the given file. If it is unable to do so, it will clear the controller's contributions to the stack. Returns YES if it successfully broke the dependencies, and NO if the stack had to be cleared. */
- (BOOL)clearUndoManagerDependenciesOnRanges:(NSArray *)ranges inFile:(HFFileReference *)reference hint:(NSMutableDictionary *)hint;
//@}
@end
/*! A notification posted whenever any of the HFController's properties change. The object is the HFController. The userInfo contains one key, HFControllerChangedPropertiesKey, which contains an NSNumber with the changed properties as a HFControllerPropertyBits bitmask. This is useful for external objects to be notified of changes. HFRepresenters added to the HFController are notified via the controllerDidChange: message.
*/
extern NSString * const HFControllerDidChangePropertiesNotification;
/*! @name HFControllerDidChangePropertiesNotification keys
*/
//@{
extern NSString * const HFControllerChangedPropertiesKey; //!< A key in the HFControllerDidChangeProperties containing a bitmask of the changed properties, as a HFControllerPropertyBits
//@}
/*! A notification posted from prepareForChangeInFile:fromWritingByteArray: because we are about to write a ByteArray to a file. The object is the FileReference.
Currently, HFControllers do not listen for this notification. This is because under GC there is no way of knowing whether the controller is live or not. However, pasteboard owners do listen for it, because as long as we own a pasteboard we are guaranteed to be live.
*/
extern NSString * const HFPrepareForChangeInFileNotification;
/*! @name HFPrepareForChangeInFileNotification keys
*/
//@{
extern NSString * const HFChangeInFileByteArrayKey; //!< A key in the HFPrepareForChangeInFileNotification specifying the byte array that will be written
extern NSString * const HFChangeInFileModifiedRangesKey; //!< A key in the HFPrepareForChangeInFileNotification specifying the array of HFRangeWrappers indicating which parts of the file will be modified
extern NSString * const HFChangeInFileShouldCancelKey; //!< A key in the HFPrepareForChangeInFileNotification specifying an NSValue containing a pointer to a BOOL. If set to YES, then someone was unable to prepare and the file should not be saved. It's a good idea to check if this value points to YES; if so your notification handler does not have to do anything.
extern NSString * const HFChangeInFileHintKey; //!< The hint parameter that you may pass to clearDependenciesOnRanges:inFile:hint:
//@}

View File

@ -0,0 +1,29 @@
//
// HFFileByteSlice.h
// HexFiend_2
//
// Copyright 2008 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFByteSlice.h>
@class HFFileReference;
/*! @class HFFileByteSlice
@brief A subclass of HFByteSlice for working data stored in files.
HFFileByteSlice is a subclass of HFByteSlice that represents a portion of data from a file. The file is specified as an HFFileReference; since the HFFileReference encapsulates the file descriptor, multiple HFFileByteSlices may all reference the same file without risking overrunning the limit on open files.
*/
@interface HFFileByteSlice : HFByteSlice {
HFFileReference *fileReference;
unsigned long long offset;
unsigned long long length;
}
/*! Initialize an HFByteSlice from a file. The receiver represents the entire extent of the file. */
- initWithFile:(HFFileReference *)file;
/*! Initialize an HFByteSlice from a portion of a file, specified as an offset and length. The sum of the offset and length must not exceed the length of the file. This is the designated initializer. */
- initWithFile:(HFFileReference *)file offset:(unsigned long long)offset length:(unsigned long long)length;
@end

View File

@ -0,0 +1,74 @@
//
// HFFileReference.h
// HexFiend_2
//
// Copyright 2008 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
/*! @class HFFileReference
@brief A reference to an open file.
HFFileReference encapsulates a reference to an open file. Multiple instances of HFFileByteSlice may share an HFFileReference, so that the file only needs to be opened once.
HFFileReference is an abstract class. You must instantiate HFConcreteFileReference.
All HFFileReferences use non-caching IO (F_NOCACHE is set).
*/
@interface HFFileReference : NSObject {
@protected
int fileDescriptor;
dev_t device;
unsigned long long inode;
unsigned long long fileLength;
mode_t fileMode;
BOOL isWritable;
uint32_t blockSize;
BOOL isPrivileged;
BOOL isFixedLength;
}
@property (readonly) BOOL isPrivileged;
@property (readonly) BOOL isFixedLength;
/*! Open a file for reading and writing at the given path. The permissions mode of any newly created file is 0744. Returns nil if the file could not be opened, in which case the error parameter (if not nil) will be set. */
- initWritableWithPath:(NSString *)path error:(NSError **)error;
/*! Open a file for reading only at the given path. Returns nil if the file could not be opened, in which case the error parameter (if not nil) will be set. */
- initWithPath:(NSString *)path error:(NSError **)error;
/*! Closes the file. */
- (void)close;
/*! Reads from the file into a local memory buffer. The sum of the length and the offset must not exceed the length of the file.
@param buff The buffer to read into.
@param length The number of bytes to read.
@param offset The offset in the file to read.
*/
- (void)readBytes:(unsigned char *)buff length:(NSUInteger)length from:(unsigned long long)offset;
/*! Writes data to the file, which must have been opened writable.
@param buff The data to write.
@param length The number of bytes to write.
@param offset The offset in the file to write to.
@return 0 on success, or an errno-style error code on failure
*/
- (int)writeBytes:(const unsigned char *)buff length:(NSUInteger)length to:(unsigned long long)offset;
/*! Returns the length of the file, as a 64 bit unsigned long long. */
- (unsigned long long)length;
/*! Changes the length of the file via \c ftruncate. Returns YES on success, NO on failure; on failure it optionally returns an NSError by reference. */
- (BOOL)setLength:(unsigned long long)length error:(NSError **)error;
/*! isEqual: returns whether two file references both reference the same file, as in have the same inode and device. */
- (BOOL)isEqual:(id)val;
@end
/*! @class HFConcreteFileReference
@brief A reference to an open file that can be read (and possibly written) using normal C functions
*/
@interface HFConcreteFileReference : HFFileReference
@end

View File

@ -0,0 +1,21 @@
//
// HFFullMemoryByteArray.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFByteArray.h>
/*!
@class HFFullMemoryByteArray
@brief A naive subclass of HFByteArray suitable mainly for testing. Use HFBTreeByteArray instead.
HFFullMemoryByteArray is a simple subclass of HFByteArray that does not store any byte slices. Because it stores all data in an NSMutableData, it is not efficient. It is mainly useful as a naive implementation for testing. Use HFBTreeByteArray instead.
*/
@interface HFFullMemoryByteArray : HFByteArray {
NSMutableData *data;
}
@end

View File

@ -0,0 +1,21 @@
//
// HFFullMemoryByteSlice.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFByteSlice.h>
/*! @class HFFullMemoryByteSlice
@brief A simple subclass of HFByteSlice that wraps an NSData. For most uses, prefer HFSharedMemoryByteSlice.
*/
@interface HFFullMemoryByteSlice : HFByteSlice {
NSData *data;
}
/*! Init with a given NSData, which is copied via the \c -copy message. */
- initWithData:(NSData *)val;
@end

View File

@ -0,0 +1,451 @@
/* Functions and convenience methods for working with HFTypes */
#import <HexFiend/HFTypes.h>
#import <libkern/OSAtomic.h>
#define HFZeroRange (HFRange){0, 0}
/*!
Makes an HFRange. An HFRange is like an NSRange except it uses unsigned long longs.
*/
static inline HFRange HFRangeMake(unsigned long long loc, unsigned long long len) {
return (HFRange){loc, len};
}
/*!
Returns true if a given location is within a given HFRange. If the location is at the end of the range (range.location + range.length) this returns NO.
*/
static inline BOOL HFLocationInRange(unsigned long long location, HFRange range) {
return location >= range.location && location - range.location < range.length;
}
/*!
Like NSRangeToString but for HFRanges
*/
static inline NSString* HFRangeToString(HFRange range) {
return [NSString stringWithFormat:@"{%llu, %llu}", range.location, range.length];
}
/*!
Converts a given HFFPRange to a string.
*/
static inline NSString* HFFPRangeToString(HFFPRange range) {
return [NSString stringWithFormat:@"{%Lf, %Lf}", range.location, range.length];
}
/*!
Returns true if two HFRanges are equal.
*/
static inline BOOL HFRangeEqualsRange(HFRange a, HFRange b) {
return a.location == b.location && a.length == b.length;
}
/*!
Returns true if a + b does not overflow an unsigned long long.
*/
static inline BOOL HFSumDoesNotOverflow(unsigned long long a, unsigned long long b) {
return a + b >= a;
}
/*!
Returns true if a * b does not overflow an unsigned long long.
*/
static inline BOOL HFProductDoesNotOverflow(unsigned long long a, unsigned long long b) {
if (b == 0) return YES;
unsigned long long result = a * b;
return result / b == a;
}
/*!
Returns a * b as an NSUInteger. This asserts on overflow, unless NDEBUG is defined.
*/
static inline NSUInteger HFProductInt(NSUInteger a, NSUInteger b) {
NSUInteger result = a * b;
assert(a == 0 || result / a == b); //detect overflow
return result;
}
/*!
Returns a + b as an NSUInteger. This asserts on overflow unless NDEBUG is defined.
*/
static inline NSUInteger HFSumInt(NSUInteger a, NSUInteger b) {
assert(a + b >= a);
return a + b;
}
/*!
Returns a + b as an NSUInteger, saturating at NSUIntegerMax
*/
static inline NSUInteger HFSumIntSaturate(NSUInteger a, NSUInteger b) {
NSUInteger result = a + b;
return (result < a) ? NSUIntegerMax : result;
}
/*!
Returns a + b as an unsigned long long, saturating at ULLONG_MAX
*/
static inline unsigned long long HFSumULLSaturate(unsigned long long a, unsigned long long b) {
unsigned long long result = a + b;
return (result < a) ? ULLONG_MAX : result;
}
/*!
Returns a * b as an unsigned long long. This asserts on overflow, unless NDEBUG is defined.
*/
static inline unsigned long long HFProductULL(unsigned long long a, unsigned long long b) {
unsigned long long result = a * b;
assert(HFProductDoesNotOverflow(a, b)); //detect overflow
return result;
}
/*!
Returns a + b as an unsigned long long. This asserts on overflow, unless NDEBUG is defined.
*/
static inline unsigned long long HFSum(unsigned long long a, unsigned long long b) {
assert(HFSumDoesNotOverflow(a, b));
return a + b;
}
/*!
Returns a - b as an unsigned long long. This asserts on underflow (if b > a), unless NDEBUG is defined.
*/
static inline unsigned long long HFSubtract(unsigned long long a, unsigned long long b) {
assert(a >= b);
return a - b;
}
/*!
Returns the smallest multiple of B that is equal to or larger than A, and asserts on overflow.
*/
static inline unsigned long long HFRoundUpToMultiple(unsigned long long a, unsigned long long b) {
// The usual approach of ((a + (b - 1)) / b) * b doesn't handle overflow correctly
unsigned long long remainder = a % b;
if (remainder == 0) return a;
else return HFSum(a, b - remainder);
}
/*!
Returns the smallest multiple of B that is equal to or larger than A, and asserts on overflow.
*/
static inline NSUInteger HFRoundUpToMultipleInt(NSUInteger a, NSUInteger b) {
// The usual approach of ((a + (b - 1)) / b) * b doesn't handle overflow correctly
NSUInteger remainder = a % b;
if (remainder == 0) return a;
else return (NSUInteger)HFSum(a, b - remainder);
}
/*!
Returns the least common multiple of A and B, and asserts on overflow or if A or B is zero.
*/
static inline NSUInteger HFLeastCommonMultiple(NSUInteger a, NSUInteger b) {
assert(a > 0);
assert(b > 0);
/* Compute GCD. It ends up in U. */
NSUInteger t, u = a, v = b;
while (v > 0) {
t = v;
v = u % v;
u = t;
}
/* Return the product divided by the GCD, in an overflow safe manner */
return HFProductInt(a/u, b);
}
/*!
Returns the smallest multiple of B strictly larger than A, or ULLONG_MAX if it would overflow
*/
static inline unsigned long long HFRoundUpToNextMultipleSaturate(unsigned long long a, unsigned long long b) {
assert(b > 0);
unsigned long long result = a + (b - a % b);
if (result < a) result = ULLONG_MAX; //the saturation...on overflow go to the max
return result;
}
/*! Like NSMaxRange, but for an HFRange. */
static inline unsigned long long HFMaxRange(HFRange a) {
assert(HFSumDoesNotOverflow(a.location, a.length));
return a.location + a.length;
}
/*! Returns YES if needle is fully contained within haystack. Equal ranges are always considered to be subranges of each other (even if they are empty). Furthermore, a zero length needle at the end of haystack is considered a subrange - for example, {6, 0} is a subrange of {3, 3}. */
static inline BOOL HFRangeIsSubrangeOfRange(HFRange needle, HFRange haystack) {
// If needle starts before haystack, or if needle is longer than haystack, it is not a subrange of haystack
if (needle.location < haystack.location || needle.length > haystack.length) return NO;
// Their difference in lengths determines the maximum difference in their start locations. We know that these expressions cannot overflow because of the above checks.
return haystack.length - needle.length >= needle.location - haystack.location;
}
/*! Splits a range about a subrange, returning by reference the prefix and suffix (which may have length zero). */
static inline void HFRangeSplitAboutSubrange(HFRange range, HFRange subrange, HFRange *outPrefix, HFRange *outSuffix) {
// Requires it to be a subrange
assert(HFRangeIsSubrangeOfRange(subrange, range));
outPrefix->location = range.location;
outPrefix->length = HFSubtract(subrange.location, range.location);
outSuffix->location = HFMaxRange(subrange);
outSuffix->length = HFMaxRange(range) - outSuffix->location;
}
/*! Returns YES if the given ranges intersect. Two ranges are considered to intersect if they share at least one index in common. Thus, zero-length ranges do not intersect anything. */
static inline BOOL HFIntersectsRange(HFRange a, HFRange b) {
// Ranges are said to intersect if they share at least one value. Therefore, zero length ranges never intersect anything.
if (a.length == 0 || b.length == 0) return NO;
// rearrange (a.location < b.location + b.length && b.location < a.location + a.length) to not overflow
// = ! (a.location >= b.location + b.length || b.location >= a.location + a.length)
BOOL clause1 = (a.location >= b.location && a.location - b.location >= b.length);
BOOL clause2 = (b.location >= a.location && b.location - a.location >= a.length);
return ! (clause1 || clause2);
}
/*! Returns a range containing the union of the given ranges. These ranges must either intersect or be adjacent: there cannot be any "holes" between them. */
static inline HFRange HFUnionRange(HFRange a, HFRange b) {
assert(HFIntersectsRange(a, b) || HFMaxRange(a) == b.location || HFMaxRange(b) == a.location);
HFRange result;
result.location = MIN(a.location, b.location);
assert(HFSumDoesNotOverflow(a.location, a.length));
assert(HFSumDoesNotOverflow(b.location, b.length));
result.length = MAX(a.location + a.length, b.location + b.length) - result.location;
return result;
}
/*! Returns whether a+b > c+d, as if there were no overflow (so ULLONG_MAX + 1 > 10 + 20) */
static inline BOOL HFSumIsLargerThanSum(unsigned long long a, unsigned long long b, unsigned long long c, unsigned long long d) {
#if 1
// Theory: compare a/2 + b/2 to c/2 + d/2, and if they're equal, compare a%2 + b%2 to c%2 + d%2. We may get into trouble if a and b are both even and c and d are both odd: e.g. a = 2, b = 2, c = 1, d = 3. We would compare 1 + 1 vs 0 + 1, and therefore that 2 + 2 > 1 + 3. To address this, if both remainders are 1, we add this to the sum. We know this cannot overflow because ULLONG_MAX is odd, so (ULLONG_MAX/2) + (ULLONG_MAX/2) + 1 does not overflow.
unsigned int rem1 = (unsigned)(a%2 + b%2);
unsigned int rem2 = (unsigned)(c%2 + d%2);
unsigned long long sum1 = a/2 + b/2 + rem1/2;
unsigned long long sum2 = c/2 + d/2 + rem2/2;
if (sum1 > sum2) return YES;
else if (sum1 < sum2) return NO;
else {
// sum1 == sum2, so compare the remainders. But we have already added in the remainder / 2, so compare the remainders mod 2.
if (rem1%2 > rem2%2) return YES;
else return NO;
}
#else
/* Faster version, but not thoroughly tested yet. */
unsigned long long xor1 = a^b;
unsigned long long xor2 = c^d;
unsigned long long avg1 = (a&b)+(xor1/2);
unsigned long long avg2 = (c&d)+(xor2/2);
unsigned s1l = avg1 > avg2;
unsigned eq = (avg1 == avg2);
return s1l | ((xor1 & ~xor2) & eq);
#endif
}
/*! Returns the absolute value of a - b. */
static inline unsigned long long HFAbsoluteDifference(unsigned long long a, unsigned long long b) {
if (a > b) return a - b;
else return b - a;
}
/*! Returns true if the end of A is larger than the end of B. */
static inline BOOL HFRangeExtendsPastRange(HFRange a, HFRange b) {
return HFSumIsLargerThanSum(a.location, a.length, b.location, b.length);
}
/*! Returns a range containing all indexes in common betwen the two ranges. If there are no indexes in common, returns {0, 0}. */
static inline HFRange HFIntersectionRange(HFRange range1, HFRange range2) {
unsigned long long minend = HFRangeExtendsPastRange(range2, range1) ? range1.location + range1.length : range2.location + range2.length;
if (range2.location <= range1.location && range1.location - range2.location < range2.length) {
return HFRangeMake(range1.location, minend - range1.location);
}
else if (range1.location <= range2.location && range2.location - range1.location < range1.length) {
return HFRangeMake(range2.location, minend - range2.location);
}
return HFRangeMake(0, 0);
}
/*! ceil() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
static inline CGFloat HFCeil(CGFloat a) {
if (sizeof(a) == sizeof(float)) return (CGFloat)ceilf((float)a);
else return (CGFloat)ceil((double)a);
}
/*! floor() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
static inline CGFloat HFFloor(CGFloat a) {
if (sizeof(a) == sizeof(float)) return (CGFloat)floorf((float)a);
else return (CGFloat)floor((double)a);
}
/*! round() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
static inline CGFloat HFRound(CGFloat a) {
if (sizeof(a) == sizeof(float)) return (CGFloat)roundf((float)a);
else return (CGFloat)round((double)a);
}
/*! fmin() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
static inline CGFloat HFMin(CGFloat a, CGFloat b) {
if (sizeof(a) == sizeof(float)) return (CGFloat)fminf((float)a, (float)b);
else return (CGFloat)fmin((double)a, (double)b);
}
/*! fmax() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
static inline CGFloat HFMax(CGFloat a, CGFloat b) {
if (sizeof(a) == sizeof(float)) return (CGFloat)fmaxf((float)a, (float)b);
else return (CGFloat)fmax((double)a, (double)b);
}
/*! Returns true if the given HFFPRanges are equal. */
static inline BOOL HFFPRangeEqualsRange(HFFPRange a, HFFPRange b) {
return a.location == b.location && a.length == b.length;
}
/*! copysign() for a CGFloat */
static inline CGFloat HFCopysign(CGFloat a, CGFloat b) {
#if __LP64__
return copysign(a, b);
#else
return copysignf(a, b);
#endif
}
/*! Atomically increments an NSUInteger, returning the new value. Optionally invokes a memory barrier. */
static inline NSUInteger HFAtomicIncrement(NSUInteger *ptr, BOOL barrier) {
#if __LP64__
return (barrier ? OSAtomicIncrement64Barrier : OSAtomicIncrement64)((volatile int64_t *)ptr);
#else
return (barrier ? OSAtomicIncrement32Barrier : OSAtomicIncrement32)((volatile int32_t *)ptr);
#endif
}
/*! Atomically decrements an NSUInteger, returning the new value. Optionally invokes a memory barrier. */
static inline NSUInteger HFAtomicDecrement(NSUInteger *ptr, BOOL barrier) {
#if __LP64__
return (barrier ? OSAtomicDecrement64Barrier : OSAtomicDecrement64)((volatile int64_t *)ptr);
#else
return (barrier ? OSAtomicDecrement32Barrier : OSAtomicDecrement32)((volatile int32_t *)ptr);
#endif
}
/*! Converts a long double to unsigned long long. Assumes that val is already an integer - use floorl or ceill */
static inline unsigned long long HFFPToUL(long double val) {
assert(val >= 0);
assert(val <= ULLONG_MAX);
unsigned long long result = (unsigned long long)val;
assert((long double)result == val);
return result;
}
/*! Converts an unsigned long long to a long double. */
static inline long double HFULToFP(unsigned long long val) {
long double result = (long double)val;
assert(HFFPToUL(result) == val);
return result;
}
/*! Convenience to return information about a CGAffineTransform for logging. */
static inline NSString *HFDescribeAffineTransform(CGAffineTransform t) {
return [NSString stringWithFormat:@"%f %f 0\n%f %f 0\n%f %f 1", t.a, t.b, t.c, t.d, t.tx, t.ty];
}
/*! Returns 1 + floor(log base 10 of val). If val is 0, returns 1. */
static inline NSUInteger HFCountDigitsBase10(unsigned long long val) {
const unsigned long long kValues[] = {0ULL, 9ULL, 99ULL, 999ULL, 9999ULL, 99999ULL, 999999ULL, 9999999ULL, 99999999ULL, 999999999ULL, 9999999999ULL, 99999999999ULL, 999999999999ULL, 9999999999999ULL, 99999999999999ULL, 999999999999999ULL, 9999999999999999ULL, 99999999999999999ULL, 999999999999999999ULL, 9999999999999999999ULL};
NSUInteger low = 0, high = sizeof kValues / sizeof *kValues;
while (high > low) {
NSUInteger mid = (low + high)/2; //low + high cannot overflow
if (val > kValues[mid]) {
low = mid + 1;
}
else {
high = mid;
}
}
return MAX(1, low);
}
/*! Returns 1 + floor(log base 16 of val). If val is 0, returns 1. This works by computing the log base 2 based on the number of leading zeros, and then dividing by 4. */
static inline NSUInteger HFCountDigitsBase16(unsigned long long val) {
/* __builtin_clzll doesn't like being passed 0 */
if (val == 0) return 1;
/* Compute the log base 2 */
NSUInteger leadingZeros = (NSUInteger)__builtin_clzll(val);
NSUInteger logBase2 = (CHAR_BIT * sizeof val) - leadingZeros - 1;
return 1 + logBase2/4;
}
/*! Returns YES if the given string encoding is a superset of ASCII. */
BOOL HFStringEncodingIsSupersetOfASCII(NSStringEncoding encoding);
/*! Returns the "granularity" of an encoding, in bytes. ASCII is 1, UTF-16 is 2, etc. Variable width encodings return the smallest (e.g. Shift-JIS returns 1). */
uint8_t HFStringEncodingCharacterLength(NSStringEncoding encoding);
/*! Converts an unsigned long long to NSUInteger. The unsigned long long should be no more than ULONG_MAX. */
static inline unsigned long ll2l(unsigned long long val) { assert(val <= ULONG_MAX); return (unsigned long)val; }
/*! Returns an unsigned long long, which must be no more than ULLONG_MAX, as an unsigned long. */
static inline CGFloat ld2f(long double val) {
#if ! NDEBUG
if (isfinite(val)) {
assert(val <= CGFLOAT_MAX);
assert(val >= -CGFLOAT_MAX);
if ((val > 0 && val < CGFLOAT_MIN) || (val < 0 && val > -CGFLOAT_MIN)) {
NSLog(@"Warning - conversion of long double %Lf to CGFloat will result in the non-normal CGFloat %f", val, (CGFloat)val);
}
}
#endif
return (CGFloat)val;
}
/*! Returns the quotient of a divided by b, rounding up, for unsigned long longs. Will not overflow. */
static inline unsigned long long HFDivideULLRoundingUp(unsigned long long a, unsigned long long b) {
if (a == 0) return 0;
else return ((a - 1) / b) + 1;
}
/*! Returns the quotient of a divided by b, rounding up, for NSUIntegers. Will not overflow. */
static inline NSUInteger HFDivideULRoundingUp(NSUInteger a, NSUInteger b) {
if (a == 0) return 0;
else return ((a - 1) / b) + 1;
}
/*! Draws a shadow. */
void HFDrawShadow(CGContextRef context, NSRect rect, CGFloat size, NSRectEdge rectEdge, BOOL active, NSRect clip);
/*! Registers a view to have the given notificationSEL invoked (taking the NSNotification object) when the window becomes or loses key. If appToo is YES, this also registers with NSApplication for Activate and Deactivate methods. */
void HFRegisterViewForWindowAppearanceChanges(NSView *view, SEL notificationSEL, BOOL appToo);
/*! Unregisters a view to have the given notificationSEL invoked when the window becomes or loses key. If appToo is YES, this also unregisters with NSApplication. */
void HFUnregisterViewForWindowAppearanceChanges(NSView *view, BOOL appToo);
/*! Returns a description of the given byte count (e.g. "24 kilobytes") */
NSString *HFDescribeByteCount(unsigned long long count);
/*! @brief An object wrapper for the HFRange type.
A simple class responsible for holding an immutable HFRange as an object. Methods that logically work on multiple HFRanges usually take or return arrays of HFRangeWrappers. */
@interface HFRangeWrapper : NSObject {
@public
HFRange range;
}
/*! Returns the HFRange for this HFRangeWrapper. */
- (HFRange)HFRange;
/*! Creates an autoreleased HFRangeWrapper for this HFRange. */
+ (HFRangeWrapper *)withRange:(HFRange)range;
/*! Creates an NSArray of HFRangeWrappers for this HFRange. */
+ (NSArray *)withRanges:(const HFRange *)ranges count:(NSUInteger)count;
/*! Given an NSArray of HFRangeWrappers, get all of the HFRanges into a C array. */
+ (void)getRanges:(HFRange *)ranges fromArray:(NSArray *)array;
/*! Given an array of HFRangeWrappers, returns a "cleaned up" array of equivalent ranges. This new array represents the same indexes, but overlapping ranges will have been merged, and the ranges will be sorted in ascending order. */
+ (NSArray *)organizeAndMergeRanges:(NSArray *)inputRanges;
@end
#ifndef NDEBUG
void HFStartTiming(const char *name);
void HFStopTiming(void);
#endif

View File

@ -0,0 +1,21 @@
//
// HFHexTextRepresenter.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFTextRepresenter.h>
/*! @class HFHexTextRepresenter
@brief HFHexTextRepresenter is an HFRepresenter responsible for showing data in hexadecimal form.
HFHexTextRepresenter is an HFRepresenter responsible for showing data in hexadecimal form. It has no methods except those inherited from HFTextRepresenter.
*/
@interface HFHexTextRepresenter : HFTextRepresenter {
unsigned long long omittedNybbleLocation;
unsigned char unpartneredLastNybble;
}
@end

View File

@ -0,0 +1,78 @@
//
// HFIndexSet.h
// HexFiend_2
//
// Copyright 2010 ridiculous_fish. All rights reserved.
//
#import <Foundation/Foundation.h>
/*! @class HFIndexSet
@brief Hex Fiend's answer to NSIndexSet. It can contain any unsigned long long value.
*/
@interface HFIndexSet : NSObject <NSCopying, NSMutableCopying> {
@protected
NSUInteger rangeCount;
NSUInteger rangeCapacity;
HFRange singleRange;
__strong HFRange *multipleRanges;
}
/*! Initializes the receiver as empty. */
- (id)init;
/*! Initializes the receiver with a single index. */
- (id)initWithValue:(unsigned long long)value;
/*! Initializes the receiver with the indexes in a single range. */
- (id)initWithValuesInRange:(HFRange)range;
/*! Initializes the receiver with the indexes in an NSIndexSet. */
- (id)initWithIndexSet:(HFIndexSet *)otherSet;
/*! Returns the number of ranges in the set. */
- (NSUInteger)numberOfRanges;
/*! Returns the range at a given index. */
- (HFRange)rangeAtIndex:(NSUInteger)idx;
/*! Returns the number of values in a given range. */
- (unsigned long long)countOfValuesInRange:(HFRange)range;
/*! Returns the number of values in the set. */
- (unsigned long long)countOfValues;
#if ! NDEBUG
- (void)verifyIntegrity;
#endif
/*! Returns the range containing the given value. If the index is not present in the set, returns {ULLONG_MAX, ULLONG_MAX}. */
- (HFRange)rangeContainingValue:(unsigned long long)idx;
/*! Indicates whether the receiver contains exactly the same indexes as the given NSIndexSet. */
- (BOOL)isEqualToNSIndexSet:(NSIndexSet *)indexSet;
@end
/*! @class HFMutableIndexSet
@brief The mutable subclass of HFIndexSet
*/
@interface HFMutableIndexSet : HFIndexSet
/*! Adds indexes in the given range. */
- (void)addIndexesInRange:(HFRange)range;
/*! Removes indexes in the given range. */
- (void)removeIndexesInRange:(HFRange)range;
/*! Shifts all values equal to or greater than the given value right (increase) by the given delta. This raises an exception if indexes are shifted past ULLONG_MAX. */
- (void)shiftValuesRightByAmount:(unsigned long long)delta startingAtValue:(unsigned long long)value;
/*! Shifts all values equal to or greater than the given value left (decrease) by the given delta. Values within the range {value - delta, delta} are deleted. This raises an exception if indexes are shifted below 0. */
- (void)shiftValuesLeftByAmount:(unsigned long long)delta startingAtValue:(unsigned long long)value;
/*! Shifts all values less than the given value left (decrease) by the given delta. This raises an exception of indexes are shifted below 0. */
- (void)shiftValuesLeftByAmount:(unsigned long long)delta endingAtValue:(unsigned long long)value;
@end

View File

@ -0,0 +1,87 @@
//
// HFLayoutRepresenter.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFRepresenter.h>
/*! @class HFLayoutRepresenter
@brief An HFRepresenter responsible for arranging the views of other HFRepresenters attached to the same HFController.
HFLayoutRepresenter is an HFRepresenter that manages the views of other HFRepresenters. It arranges their views in its own view, mediating between them to determine their position and size, as well as global properties such as bytes per line.
HFLayoutRepresenter has an array of representers attached to it. When you add an HFRepresenter to this array, HFLayoutRepresenter will add the view of the representer as a subview of its own view.
\b Layout
HFLayoutRepresenter is capable of arranging the views of other HFRepresenters to fit within the bounds of its view. The layout process depends on three things:
-# The \c frame and \c autoresizingMask of the representers' views.
-# The \c minimumViewWidthForBytesPerLine: method, which determines the largest number of bytes per line that the representer can display for a given view width.
-# The representer's \c layoutPosition. This is an NSPoint, but it is not used geometrically. Instead, the relative values of the X and Y coordinates of the \c layoutPosition determine the relative positioning of the views, as described below.
Thus, to have your subclass of HFRepresenter participate in the HFLayoutRepresenter system, override \c defaultLayoutPosition: to control its positioning, and possibly \\c minimumViewWidthForBytesPerLine: if your representer requires a certain width to display some bytes per line. Then ensure your view has its autoresizing mask set properly, and if its frame is fixed size, ensure that its frame is correct as well.
The layout process, in detail, is:
-# The views are sorted vertically by the Y component of their representers' \c layoutPosition into "slices." Smaller values appear towards the bottom of the layout view. There is no space between slices.
-# Views with equal Y components are sorted horizontally by the X component of their representers' \c layoutPosition, with smaller values appearing on the left.
-# The height of each slice is determined by the tallest view within it, excluding views that have \c NSViewHeightSizable set. If there is any leftover vertical space, it is distributed equally among all slices with at least one view with \c NSViewHeightSizable set.
-# If the layout representer is not set to maximize the bytes per line (BPL), then the BPL from the HFController is used. Otherwise:
-# Each representer is queried for its \c minimumViewWidthForBytesPerLine:
-# The largest BPL allowing each row to fit within the layout width is determined via a binary search.
-# The BPL is rounded down to a multiple of the bytes per column (if non-zero).
-# The BPL is then set on the controller.
-# For each row, each view is assigned its minimum view width for the BPL.
-# If there is any horizontal space left over, it is divided evenly between all views in that slice that have \c NSViewWidthSizable set in their autoresizing mask.
*/
@interface HFLayoutRepresenter : HFRepresenter {
NSMutableArray *representers;
BOOL maximizesBytesPerLine;
}
/*! @name Managed representers
Managing the list of representers laid out by the receiver
*/
//@{
/*! Return the array of representers managed by the receiver. */
- (NSArray *)representers;
/*! Adds a new representer to the receiver, triggering relayout. */
- (void)addRepresenter:(HFRepresenter *)representer;
/*! Removes a representer to the receiver (which must be present in the receiver's array of representers), triggering relayout. */
- (void)removeRepresenter:(HFRepresenter *)representer;
//@}
/*! @name Configuration
*/
//@{
/*! Sets whether the receiver will attempt to maximize the bytes per line so as to consume as much as possible of the bounds rect. If this is YES, then upon relayout, the receiver will recalculate the maximum number of bytes per line that can fit in its boundsRectForLayout. If this is NO, then the receiver will not change the bytes per line. */
- (void)setMaximizesBytesPerLine:(BOOL)val;
/*! Returns whether the receiver maximizes the bytes per line. */
- (BOOL)maximizesBytesPerLine;
//@}
/*! @name Layout
Methods to get information about layout, and to explicitly trigger it.
*/
//@{
/*! Returns the smallest width that produces the same layout (and, if maximizes bytesPerLine, the same bytes per line) as the proposed width. */
- (CGFloat)minimumViewWidthForLayoutInProposedWidth:(CGFloat)proposedWidth;
/*! Returns the maximum bytes per line that can fit in the proposed width (ignoring maximizesBytesPerLine). This is always a multiple of the bytesPerColumn, and always at least bytesPerColumn. */
- (NSUInteger)maximumBytesPerLineForLayoutInProposedWidth:(CGFloat)proposedWidth;
/*! Returns the smallest width that can support the given bytes per line. */
- (CGFloat)minimumViewWidthForBytesPerLine:(NSUInteger)bytesPerLine;
/*! Relayouts are triggered when representers are added and removed, or when the view is resized. You may call this explicitly to trigger a relayout. */
- (void)performLayout;
//@}
@end

View File

@ -0,0 +1,67 @@
//
// HFLineCountingRepresenter.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFRepresenter.h>
/*! @enum HFLineNumberFormat
HFLineNumberFormat is a simple enum used to determine whether line numbers are in decimal or hexadecimal format.
*/
enum
{
HFLineNumberFormatDecimal, //!< Decimal line numbers
HFLineNumberFormatHexadecimal, //!< Hexadecimal line numbers
HFLineNumberFormatMAXIMUM //!< One more than the maximum valid line number format, so that line number formats can be cycled through easily
};
typedef NSUInteger HFLineNumberFormat;
/*! @class HFLineCountingRepresenter
@brief The HFRepresenter used to show the "line number gutter."
HFLineCountingRepresenter is the HFRepresenter used to show the "line number gutter." HFLineCountingRepresenter makes space for a certain number of digits.
*/
@interface HFLineCountingRepresenter : HFRepresenter {
CGFloat lineHeight;
NSUInteger digitsToRepresentContentsLength;
NSUInteger minimumDigitCount;
HFLineNumberFormat lineNumberFormat;
NSInteger interiorShadowEdge;
CGFloat preferredWidth;
CGFloat digitAdvance;
}
/*! Sets the minimum digit count. The receiver will always ensure it is big enough to display at least the minimum digit count. The default is 2. */
- (void)setMinimumDigitCount:(NSUInteger)count;
/*! Gets the minimum digit count. */
- (NSUInteger)minimumDigitCount;
/*! Returns the number of digits we are making space for. */
- (NSUInteger)digitCount;
/*! Returns the current width that the HFRepresenter prefers to be laid out with. */
- (CGFloat)preferredWidth;
/*! Returns the current line number format. */
- (HFLineNumberFormat)lineNumberFormat;
/*! Sets the current line number format to a new format. */
- (void)setLineNumberFormat:(HFLineNumberFormat)format;
/*! Switches to the next line number format. This is called from the view. */
- (void)cycleLineNumberFormat;
/*! Sets on which edge (as an NSRectEdge) the view draws an interior shadow. Pass -1 to mean no edge. */
- (void)setInteriorShadowEdge:(NSInteger)interiorShadowEdge;
/*! Returns the edge (as an NSRectEdge) on which the view draws a shadow, or -1 if no edge. */
- (NSInteger)interiorShadowEdge;
@end
/*! Notification posted when the HFLineCountingRepresenter's width has changed because the number of digits it wants to show has increased or decreased. The object is the HFLineCountingRepresenter; there is no user info.
*/
extern NSString *const HFLineCountingRepresenterMinimumViewWidthChanged;

View File

@ -0,0 +1,21 @@
//
// HFProcessMemoryByteSlice.h
// HexFiend_2
//
// Copyright 2009 Apple Computer. All rights reserved.
//
#import <HexFiend/HFByteSlice.h>
/*! @class HFProcessMemoryByteSlice
@brief Some day
*/
@interface HFProcessMemoryByteSlice : HFByteSlice {
pid_t processIdentifier;
HFRange memoryRange;
}
- (id)initWithAddressSpaceOfPID:(pid_t)pid;
- (id)initWithPID:(pid_t)pid range:(HFRange)memoryRange;
@end

View File

@ -0,0 +1,107 @@
//
// HFProgressTracker.h
// HexFiend_2
//
// Created by peter on 2/12/08.
// Copyright 2008 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
/*!
@class HFProgressTracker
@brief A class that helps handle progress indication and cancellation for long running threaded operations.
HFProgressTracker is a class that helps handle progress indication and cancellation for long running threaded operations, while imposing minimal overhead. Operations such as Find/Replace or Save take an HFProgressTracker to provide cancellation and progress reporting.
The thread is expected to write directly into the public currentProgress field (perhaps with atomic functions) as it makes progress. Once beginTrackingProgress is called, the HFProgressTracker will poll currentProgress until endTrackingProgress is called.
The thread is also expected to read directly from cancelRequested, which is set by the requestCancel method. If requestCancel is set, it should end the operation.
Lastly, the thread is expected to call noteFinished: when it is done, either through cancellation or completing normally.
On the client side, you can set a delegate. progressTracker: didChangeProgressTo: is called on your delegate at regular intervals in the main thread, as the progress changes. Likewise, progressTrackerDidFinish: is called on the main thread after noteFinished: is called.
There is also a progressIndicator property, which if set to an NSProgressIndicator will cause it to be updated regularly.
*/
@interface HFProgressTracker : NSObject {
@public
volatile unsigned long long currentProgress;
volatile int cancelRequested;
@private
unsigned long long maxProgress;
NSProgressIndicator *progressIndicator;
NSTimer *progressTimer;
double lastSetValue;
NSDictionary *userInfo;
id delegate;
}
/*!
HFProgressTracker determines the progress as an unsigned long long, but passes the progress to the delegate as a double, which is computed as the current progress divided by the max progress.
*/
- (void)setMaxProgress:(unsigned long long)max;
- (unsigned long long)maxProgress;
/*!
The userInfo property is a convenience to allow passing information to the thread. The property is not thread safe - the expectation is that the main thread will set it before the operation starts, and the background thread will read it once after the operation starts.
*/
- (void)setUserInfo:(NSDictionary *)info;
- (NSDictionary *)userInfo;
/*!
The progressIndicator property allows an NSProgressIndicator to be associated with the HFProgressTracker. The progress indicator should have values in the range 0 to 1, and it will be updated with the fraction currentProgress / maxProgress.
*/
- (void)setProgressIndicator:(NSProgressIndicator *)indicator;
- (NSProgressIndicator *)progressIndicator;
/*!
Called to indicate you want to begin tracking the progress, which means that the progress indicator will be updated, and the delegate callbacks may fire.
*/
- (void)beginTrackingProgress;
/*!
Called to indicate you want to end tracking progress. The progress indicator will no longer be updated.
*/
- (void)endTrackingProgress;
/*!
noteFinished: should be called by the thread when it is done. It is safe to call this from the background thread.
*/
- (void)noteFinished:(id)sender;
/*!
requestCancel: may be called to mark the cancelRequested variable. The thread should poll this variable to determine if it needs to cancel.
*/
- (void)requestCancel:(id)sender;
/*!
Set and get the delegate, which may implement the optional methods below.
*/
- (void)setDelegate:(id)delegate;
- (id)delegate;
@end
/*!
@protocol HFProgressTrackerDelegate
@brief The delegate methods for the HFProgressTracker class.
The HFProgressTrackerDelegate methods are called on the the HFProgressTracker's delegate. These are always called on the main thread.
*/
@protocol HFProgressTrackerDelegate <NSObject>
/*!
Once beginTrackingProgress is called, this is called on the delegate at regular intervals to report on the new progress.
*/
- (void)progressTracker:(HFProgressTracker *)tracker didChangeProgressTo:(double)fraction;
/*!
Once the thread has called noteFinished:, this is called on the delegate in the main thread to report that the background thread is done.
*/
- (void)progressTrackerDidFinish:(HFProgressTracker *)tracker;
@end

View File

@ -0,0 +1,125 @@
//
// HFRepresenter.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <HexFiend/HFController.h>
/*! @class HFRepresenter
@brief The principal view class of Hex Fiend's MVC architecture.
HFRepresenter is a class that visually represents some property of the HFController, such as the data (in various formats), the scroll position, the line number, etc. An HFRepresenter is added to an HFController and then gets notified of changes to various properties, through the controllerDidChange: methods.
HFRepresenters also have a view, accessible through the -view method. The HFRepresenter is expected to update its view to reflect the relevant properties of its HFController. If the user can interact with the view, then the HFRepresenter should pass any changes down to the HFController, which will subsequently notify all HFRepresenters of the change.
HFRepresenter is an abstract class, with a different subclass for each possible view type. Because HFController interacts with HFRepresenters, rather than views directly, an HFRepresenter can use standard Cocoa views and controls.
To add a new view type:
-# Create a subclass of HFRepresenter
-# Override \c -createView to return a view (note that this method should transfer ownership)
-# Override \c -controllerDidChange:, checking the bitmask to see what properties have changed and updating your view as appropriate
-# If you plan on using this view together with other views, override \c +defaultLayoutPosition to control how your view gets positioned in an HFLayoutRepresenter
-# If your view's width depends on the properties of the controller, override some of the measurement methods, such as \c +maximumBytesPerLineForViewWidth:, so that your view gets sized correctly
*/
@interface HFRepresenter : NSObject <NSCoding> {
@private
id view;
HFController *controller;
NSPoint layoutPosition;
}
/*! @name View management
Methods related to accessing and initializing the representer's view.
*/
//@{
/*! Returns the view for the receiver, creating it if necessary. The view for the HFRepresenter is initially nil. When the \c -view method is called, if the view is nil, \c -createView is called and then the result is stored. This method should not be overridden; however you may want to call it to access the view.
*/
- (id)view;
/*! Returns YES if the view has been created, NO if it has not. To create the view, call the view method.
*/
- (BOOL)isViewLoaded;
/*! Override point for creating the view displaying this representation. This is called on your behalf the first time the \c -view method is called, so you would not want to call this explicitly; however this method must be overridden. This follows the "create" rule, and so it should return a retained view.
*/
- (NSView *)createView NS_RETURNS_RETAINED;
/*! Override point for initialization of view, after the HFRepresenter has the view set as its -view property. The default implementation does nothing.
*/
- (void)initializeView;
//@}
/*! @name Accessing the HFController
*/
//@{
/*! Returns the HFController for the receiver. This is set by the controller from the call to \c addRepresenter:. A representer can only be in one controller at a time. */
- (HFController *)controller;
//@}
/*! @name Property change notifications
*/
//@{
/*! Indicates that the properties indicated by the given bits did change, and the view should be updated as to reflect the appropriate properties. This is the main mechanism by which representers are notified of changes to the controller.
*/
- (void)controllerDidChange:(HFControllerPropertyBits)bits;
//@}
/*! @name HFController convenience methods
Convenience covers for certain HFController methods
*/
//@{
/*! Equivalent to <tt>[[self controller] bytesPerLine]</tt> */
- (NSUInteger)bytesPerLine;
/*! Equivalent to <tt>[[self controller] bytesPerColumn]</tt> */
- (NSUInteger)bytesPerColumn;
/*! Equivalent to <tt>[[self controller] representer:self changedProperties:properties]</tt> . You may call this when some internal aspect of the receiver's view (such as its frame) has changed in a way that may globally change some property of the controller, and the controller should recalculate those properties. For example, the text representers call this with HFControllerDisplayedLineRange when the view grows vertically, because more data may be displayed.
*/
- (void)representerChangedProperties:(HFControllerPropertyBits)properties;
//@}
/*! @name Measurement
Methods related to measuring the HFRepresenter, so that it can be laid out properly by an HFLayoutController. All of these methods are candidates for overriding.
*/
//@{
/*! Returns the maximum number of bytes per line for the given view size. The default value is NSUIntegerMax, which means that the representer can display any number of lines for the given view size. */
- (NSUInteger)maximumBytesPerLineForViewWidth:(CGFloat)viewWidth;
/*! Returns the minimum view frame size for the given bytes per line. Default is to return 0, which means that the representer can display the given bytes per line in any view size. Fixed width views should return their fixed width. */
- (CGFloat)minimumViewWidthForBytesPerLine:(NSUInteger)bytesPerLine;
/*! Returns the maximum number of lines that could be displayed at once for a given view height. Default is to return DBL_MAX. */
- (double)maximumAvailableLinesForViewHeight:(CGFloat)viewHeight;
//@}
/*! Returns the required byte granularity. HFLayoutRepresenter will constrain the bytes per line to a multiple of the granularity, e.g. so that UTF-16 characters are not split across lines. If different representers have different granularities, then it will constrain it to a multiple of all granularities, which may be very large. The default implementation returns 1. */
- (NSUInteger)byteGranularity;
/*! @name Auto-layout methods
Methods for simple auto-layout by HFLayoutRepresenter. See the HFLayoutRepresenter class for discussion of how it lays out representer views.
*/
//@{
/*! Sets the receiver's layout position to the given value.
*/
- (void)setLayoutPosition:(NSPoint)position;
/*! Returns the layout position for the receiver.
*/
- (NSPoint)layoutPosition;
/*! Returns the default layout position for representers of this class. Within the -init method, the view's layout position is set to the default for this class. You may override this to control the default layout position. See HFLayoutRepresenter for a discussion of the significance of the layout postition.
*/
+ (NSPoint)defaultLayoutPosition;
//@}
@end

View File

@ -0,0 +1,32 @@
//
// HFSharedMemoryByteSlice.h
// HexFiend_2
//
// Copyright 2008 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFByteSlice.h>
/*! @class HFSharedMemoryByteSlice
@brief A subclass of HFByteSlice for working with data stored in memory.
HFSharedMemoryByteSlice is a subclass of HFByteSlice that represents a portion of data from memory, e.g. typed or pasted in by the user. The term "shared" refers to the ability for mutiple HFSharedMemoryByteSlices to reference the same NSData; it does not mean that the data is in shared memory or shared between processes.
Instances of HFSharedMemoryByteSlice are immutable (like all instances of HFByteSlice). However, to support efficient typing, the backing data is an instance of NSMutableData that may be grown. A referenced range of the NSMutableData will never have its contents changed, but it may be allowed to grow larger, so that the data does not have to be copied merely to append a single byte. This is implemented by overriding the -byteSliceByAppendingSlice: method of HFByteSlice.
*/
@interface HFSharedMemoryByteSlice : HFByteSlice {
NSMutableData *data;
NSUInteger offset;
NSUInteger length;
unsigned char inlineTailLength;
unsigned char inlineTail[15]; //size chosen to exhaust padding of 32-byte allocator
}
// copies the data
- (id)initWithUnsharedData:(NSData *)data;
// retains, does not copy
- (id)initWithData:(NSMutableData *)data;
- (id)initWithData:(NSMutableData *)data offset:(NSUInteger)offset length:(NSUInteger)length;
@end

View File

@ -0,0 +1,33 @@
//
// HFStatusBarRepresenter.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFRepresenter.h>
/*! @enum HFStatusBarMode
The HFStatusBarMode enum is used to describe the format of the byte counts displayed by the status bar.
*/
enum {
HFStatusModeDecimal, ///< The status bar should display byte counts in decimal
HFStatusModeHexadecimal, ///< The status bar should display byte counts in hexadecimal
HFStatusModeApproximate, ///< The text should display byte counts approximately (e.g. "56.3 KB")
HFSTATUSMODECOUNT ///< The number of modes, to allow easy cycling
};
typedef NSUInteger HFStatusBarMode;
/*! @class HFStatusBarRepresenter
@brief The HFRepresenter for the status bar.
HFStatusBarRepresenter is a subclass of HFRepresenter responsible for showing the status bar, which displays information like the total length of the document, or the number of selected bytes.
*/
@interface HFStatusBarRepresenter : HFRepresenter {
HFStatusBarMode statusMode;
}
- (HFStatusBarMode)statusMode;
- (void)setStatusMode:(HFStatusBarMode)mode;
@end

View File

@ -0,0 +1,27 @@
//
// HFASCIITextRepresenter.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFTextRepresenter.h>
/*! @class HFStringEncodingTextRepresenter
@brief An HFRepresenter responsible for showing data interpreted via an NSStringEncoding.
HFHexTextRepresenter is an HFRepresenter responsible for showing and editing data interpreted via an NSStringEncoding. Currently only supersets of ASCII are supported.
*/
@interface HFStringEncodingTextRepresenter : HFTextRepresenter {
NSStringEncoding stringEncoding;
}
/*! Get the string encoding for this representer. The default encoding is <tt>[NSString defaultCStringEncoding]</tt>. */
- (NSStringEncoding)encoding;
/*! Set the string encoding for this representer. */
- (void)setEncoding:(NSStringEncoding)encoding;
@end

View File

@ -0,0 +1,55 @@
//
// HFTextField.h
// HexFiend_2
//
// Copyright 2008 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class HFLayoutRepresenter, HFRepresenter, HFController, HFHexTextRepresenter, HFStringEncodingTextRepresenter;
/*! @class HFTextField
@brief A high-level view class that is analagous to NSTextField.
HFTextField encapsulates a HFController and HFRepresenters into a single "do it all" NSControl analagous to NSTextField. Its objectValue is an HFByteArray. It sends its \c action to its \c target when the user hits return. It has no control.
An HFTextField can be configured to show a hexadecimal view, an ASCII (really the \c defaultCStringEncoding) view, or both.
This class is currently missing a fair amount of functionality, such as enabled state.
*/
@interface HFTextField : NSControl {
HFController *dataController;
HFLayoutRepresenter *layoutRepresenter;
HFHexTextRepresenter *hexRepresenter;
HFStringEncodingTextRepresenter *textRepresenter;
IBOutlet id target;
SEL action;
}
/*! Returns whether the hexadecimal view is shown. */
- (BOOL)usesHexArea;
/*! Sets whether the hexadecimal view is shown. */
- (void)setUsesHexArea:(BOOL)val;
/*! Returns whether the text area is shown. */
- (BOOL)usesTextArea;
/*! Sets whether the text area is shown. */
- (void)setUsesTextArea:(BOOL)val;
/*! Sets the string encoding used by the text area. */
- (void)setStringEncoding:(NSStringEncoding)encoding;
/*! Gets the string encoding used by the text area. */
- (NSStringEncoding)stringEncoding;
/*! Sets editability. */
- (void)setEditable:(BOOL)flag;
/*! Returns editability. */
- (BOOL)isEditable;
@end

View File

@ -0,0 +1,49 @@
//
// HFTextRepresenter.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFRepresenter.h>
#import <HexFiend/HFByteArray.h>
/*! @class HFTextRepresenter
@brief An HFRepresenter that draws text (e.g. the hex or ASCII view).
HFTextRepresenter is an abstract subclass of HFRepresenter that is responsible for displaying text. There are two concrete subclass, HFHexTextRepresenter and HFStringEncodingTextRepresenter.
Most of the functionality of HFTextRepresenter is private, and there is not yet enough exposed to allow creating new representers based on it. However, there is a small amount of configurability.
*/
@interface HFTextRepresenter : HFRepresenter {
BOOL behavesAsTextField;
NSArray *rowBackgroundColors;
}
/*! Given a rect edge, return an NSRect representing the maximum edge in that direction, in the coordinate system of the receiver's view. The dimension in the direction of the edge is 0 (so if edge is NSMaxXEdge, the resulting width is 0). The returned rect is in the coordinate space of the receiver's view. If the byte range is not displayed, returns NSZeroRect.
If range is entirely above the visible region, returns an NSRect whose width and height are 0, and whose origin is -CGFLOAT_MAX (the most negative CGFloat). If range is entirely below the visible region, returns the same except with CGFLOAT_MAX (positive).
This raises an exception if range is empty.
*/
- (NSRect)furthestRectOnEdge:(NSRectEdge)edge forByteRange:(HFRange)range;
/*! Returns the origin of the character at the given byte index. The returned point is in the coordinate space of the receiver's view. If the character is not displayed because it would be above the displayed range, returns {0, -CGFLOAT_MAX}. If it is not displayed because it is below the displayed range, returns {0, CGFLOAT_MAX}. As a special affordance, you may pass a byte index one greater than the contents length of the controller, and it will return the result as if the byte existed.
*/
- (NSPoint)locationOfCharacterAtByteIndex:(unsigned long long)byteIndex;
/*! Returns the per-row background colors. The default is <tt>-[NSControl controlAlternatingRowBackgroundColors]</tt>. */
- (NSArray *)rowBackgroundColors;
/*! Sets the per-row background colors. Each row is drawn with the next color in turn, cycling back to the beginning when the array is exhausted. Any empty space is filled with the first color in the array. If the array is empty, then the background is drawn with \c clearColor. */
- (void)setRowBackgroundColors:(NSArray *)colors;
/*! Set whether the text view behaves like a text field (YES) or a text view (NO). Currently this determines whether it draws a focus ring when it is the first responder.
*/
- (void)setBehavesAsTextField:(BOOL)val;
/*! Returns whether the text view behaves like a text field (YES) or a text view (NO).
*/
- (BOOL)behavesAsTextField;
@end

View File

@ -0,0 +1,98 @@
//
// HFTextView.h
// HexFiend_2
//
// Copyright 2009 ridiculous_fish. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <HexFiend/HFController.h>
@class HFLayoutRepresenter;
/*! @class HFTextView
@brief A high-level view class analagous to NSTextView.
HFTextField encapsulates a HFController and HFRepresenters into a single "do it all" NSControl analagous to NSTextView.
*/
@interface HFTextView : NSControl {
HFController *dataController;
HFLayoutRepresenter *layoutRepresenter;
NSArray *backgroundColors;
BOOL bordered;
IBOutlet id delegate;
NSData *cachedData;
}
/*! @name Accessing MVC components
*/
//@{
/*! Returns the HFController for the receiver. You may want to access this to add or remove HFRepresenters from the text view at runtime. */
- (HFController *)controller;
/*! Sets the HFController for the receiver. An HFTextView comes with its own HFController, but you can use this to replace it. */
- (void)setController:(HFController *)controller;
/*! Returns the HFLayoutRepresenter for the receiver. You may want to access this to add or remove HFRepresenters from the text view at runtime. */
- (HFLayoutRepresenter *)layoutRepresenter;
/*! Sets the HFLayoutRepresenter for the receiver. An HFTextView comes with its own HFLayoutRepresenter, but you can use this to replace it. */
- (void)setLayoutRepresenter:(HFLayoutRepresenter *)layoutRepresenter;
/*! Returns the HFByteArray for the receiver. This is equivalent to <tt>[[self controller] byteArray]</tt>. */
- (HFByteArray *)byteArray;
//@}
/*! @name Display configuration
*/
//@{
/*! Sets the arry of background colors for the receiver. The background colors are used in sequence to draw each row. */
- (void)setBackgroundColors:(NSArray *)colors;
/*! Returns the array of background colors for the receiver. */
- (NSArray *)backgroundColors;
/*! Sets whether the receiver draws a border. */
- (void)setBordered:(BOOL)val;
/*! Returns whether the receiver draws a border. */
- (BOOL)bordered;
//@}
/*! @name Delegate handling
*/
//@{
/*! Sets the delegate, which may implement the methods in HFTextViewDelegate */
- (void)setDelegate:(id)delegate;
/*! Returns the delegate, which is initially nil. */
- (id)delegate;
//@}
/*! @name Accessing contents as NSData
*/
//@{
/*! Returns the contents of the HFTextView's HFByteArray as an NSData This NSData proxies an HFByteArray, and therefore it is usually more efficient than naively copying all of the bytes. However, access to the \c -byte method will necessitate copying, a potentially expensive operation. Furthermore, the NSData API is inherently 32 bit in a 32 bit process. Lastly, there is no protection if the backing file for the data disappears.
For those reasons, this should only be used when its convenience outweighs the downside (e.g. some bindings scenarios). For most use cases, it is better to use the \c -byteArray method above.
*/
- (NSData *)data;
/*! Sets the contents of the HFTextView's HFByteArray to an \c NSData. Note that the data is copied via the \c -copy message, so prefer to pass an immutable \c NSData when possible.
*/
- (void)setData:(NSData *)data;
//@}
@end
/*! @protocol HFTextViewDelegate
@brief Delegate methods for HFTextView
*/
@protocol HFTextViewDelegate <NSObject>
/*! Called on the delegate when the HFTextView's HFController changed some properties. See the documentation for the #HFControllerPropertyBits enum. */
- (void)hexTextView:(HFTextView *)view didChangeProperties:(HFControllerPropertyBits)properties;
@end

View File

@ -0,0 +1,47 @@
/* Hide this compatibility junk from Doxygen */
#ifndef DOXYGEN_ONLY
#ifndef NSINTEGER_DEFINED
#if __LP64__ || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
#define NSIntegerMax LONG_MAX
#define NSIntegerMin LONG_MIN
#define NSUIntegerMax ULONG_MAX
#define NSINTEGER_DEFINED 1
#endif
#ifndef CGFLOAT_DEFINED
#if defined(__LP64__) && __LP64__
typedef double CGFloat;
#define CGFLOAT_MIN DBL_MIN
#define CGFLOAT_MAX DBL_MAX
#define CGFLOAT_IS_DOUBLE 1
#else /* !defined(__LP64__) || !__LP64__ */
typedef float CGFloat;
#define CGFLOAT_MIN FLT_MIN
#define CGFLOAT_MAX FLT_MAX
#define CGFLOAT_IS_DOUBLE 0
#endif /* !defined(__LP64__) || !__LP64__ */
#define CGFLOAT_DEFINED 1
#endif
#endif
/*! @brief HFRange is the 64 bit analog of NSRange, containing a 64 bit location and length. */
typedef struct {
unsigned long long location;
unsigned long long length;
} HFRange;
/*! @brief HFFPRange is a struct used for representing floating point ranges, similar to NSRange. It contains two long doubles.
This is useful for (for example) showing the range of visible lines. A double-precision value has 53 significant bits in the mantissa - so we would start to have precision problems at the high end of the range we can represent. Long double has a 64 bit mantissa on Intel, which means that we would start to run into trouble at the very very end of our range - barely acceptable. */
typedef struct {
long double location;
long double length;
} HFFPRange;

View File

@ -0,0 +1,21 @@
//
// HFRepresenterVerticalScroller.h
// HexFiend_2
//
// Copyright 2007 ridiculous_fish. All rights reserved.
//
#import <HexFiend/HFRepresenter.h>
/*! @class HFVerticalScrollerRepresenter
@brief An HFRepresenter responsible for showing a vertical scroll bar.
HFVerticalScrollerRepresenter is an HFRepresenter whose view is a vertical NSScroller, that represents the current position within an HFController "document." It has no methods beyond those of HFRepresenter.
As HFVerticalScrollerRepresenter is an especially simple representer, it makes for good sample code.
*/
@interface HFVerticalScrollerRepresenter : HFRepresenter {
}
@end

View File

@ -0,0 +1,98 @@
/*! @mainpage HexFiend.framework
*
* @section intro Introduction
* HexFiend.framework (hereafter "Hex Fiend" when there is no risk of confusion with the app by the same name) is a framework designed to enable applications to support viewing and editing of binary data. The emphasis is on editing data in a natural way, following Mac OS X text editing conventions.
*
* Hex Fiend is designed to work efficiently with large amounts (64 bits worth) of data. As such, it can work with arbitrarily large files without reading the entire file into memory. This includes insertions, deletions, and in-place editing. Hex Fiend can also efficiently save such changes back to the file, without requiring any additional temporary disk space.
*
* Hex Fiend has a clean separation between the model, view, and controller layers. The model layer allows for efficient manipulation of raw data of mixed sources, making it useful for tools that need to work with large files.
*
* Both the framework and the app are open source under a BSD-style license. In summary, you may use Hex Fiend in any project as long as you include the copyright notice somewhere in the documentation.
*
* @section requirements Requirements
* Hex Fiend is only available on Mac OS X, and supported on SnowLeopard and later. It is compiled "hybrid" (works with both garbage collection and reference counting) and 2-way fat (64 bit and 32 bit, Intel only). Support for 64 bits worth of data is available in both 32 bit and 64 bit - there is no functional difference between the 32 bit and 64 bit versions.
*
* @section getting_started Getting Started
*
* The Hex Fiend source code is available at http://ridiculousfish.com/hexfiend/
*
* Hex Fiend comes with some sample code ("HexFiendling"), distributed as part of the project. And of course the Hex Fiend application itself is open source, acting as a more sophisticated sample code.
*/
#import <HexFiend/HFTypes.h>
#import <HexFiend/HFFunctions.h>
#import <HexFiend/HFController.h>
#import <HexFiend/HFRepresenter.h>
#import <HexFiend/HFFullMemoryByteArray.h>
#import <HexFiend/HFFullMemoryByteSlice.h>
#import <HexFiend/HFHexTextRepresenter.h>
#import <HexFiend/HFLineCountingRepresenter.h>
#import <HexFiend/HFStatusBarRepresenter.h>
#import <HexFiend/HFLayoutRepresenter.h>
#import <HexFiend/HFStringEncodingTextRepresenter.h>
#import <HexFiend/HFVerticalScrollerRepresenter.h>
#import <HexFiend/HFByteArray.h>
#import <HexFiend/HFFileByteSlice.h>
#import <HexFiend/HFFileReference.h>
#import <HexFiend/HFByteArrayEditScript.h>
#import <HexFiend/HFBTreeByteArray.h>
#import <HexFiend/HFAttributedByteArray.h>
#import <HexFiend/HFProgressTracker.h>
#import <HexFiend/HFTextField.h>
#import <HexFiend/HFTextView.h>
#import <HexFiend/HFSharedMemoryByteSlice.h>
#import <HexFiend/HFIndexSet.h>
#import <HexFiend/HFByteRangeAttribute.h>
#import <HexFiend/HFByteRangeAttributeArray.h>
/* The following is all for Doxygen */
/*! @defgroup model Model
* Hex Fiend's model classes
*/
///@{
///@class HFByteArray
///@class HFBTreeByteArray
///@class HFFullMemoryByteArray
///@class HFByteSlice
///@class HFFileByteSlice
///@class HFSharedMemoryByteSlice
///@class HFFullMemoryByteSlice
///@}
/*! @defgroup view View
* Hex Fiend's view classes
*/
///@{
///@class HFRepresenter
///@class HFHexTextRepresenter
///@class HFStringEncodingTextRepresenter
///@class HFLayoutRepresenter
///@class HFLineCountingRepresenter
///@class HFStatusBarRepresenter
///@class HFVerticalScrollerRepresenter
///@class HFLineCountingRepresenter
///@}
/*! @defgroup controller Controller
* Hex Fiend's controller classes
*/
///@{
///@class HFController
///@}
/*! @defgroup highlevel High Level
* Hex Fiend's "do it all" classes
*/
///@{
///@class HFTextView
///@class HFTextField
///@}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>12A269</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>HexFiend</string>
<key>CFBundleIdentifier</key>
<string>com.ridiculousfish.HexFiend-Framework</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>200</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>4F1003</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>12A264</string>
<key>DTSDKName</key>
<string>macosx10.8</string>
<key>DTXcode</key>
<string>0441</string>
<key>DTXcodeBuild</key>
<string>4F1003</string>
<key>SMPrivilegedExecutables</key>
<dict>
<key>com.ridiculousfish.HexFiend.PrivilegedHelper</key>
<string>certificate leaf[subject.CN] = "Hex Fiend"</string>
</dict>
</dict>
</plist>

View File

@ -0,0 +1 @@
A