/* * Name: OgreTextFindThread.m * Project: OgreKit * * Creation Date: Sep 26 2003 * Author: Isao Sonobe * Copyright: Copyright (c) 2003 Isao Sonobe, All rights reserved. * License: OgreKit License * * Encoding: UTF8 * Tabsize: 4 */ #import #import #import @implementation OgreTextFindThread /* Creating and initializing */ - (id)initWithComponent:(NSObject *)aComponent; { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-initWithComponent: of %@", [self className]); #endif self = [super init]; if (self != nil) { _targetAdapter = [aComponent retain]; _enumeratorStack = [[NSMutableArray alloc] initWithCapacity:10]; _branchStack = [[NSMutableArray alloc] initWithCapacity:10]; _terminated = NO; _exceptionRaised = NO; _processTime = 0; _asynchronous = NO; _shouldFinish = NO; _rootAdapter = [[OgreTextFindRoot alloc] initWithComponent:_targetAdapter]; [_targetAdapter setParent:_rootAdapter]; [_targetAdapter setIndex:0]; } return self; } - (void)dealloc { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-dealloc of %@", [self className]); #endif [self finalizeFindingAll]; [_targetAdapter release]; [_rootAdapter release]; [_metronome release]; [_processTime release]; [_textFindResult release]; [_didEndTarget release]; [_highlightColor release]; [_repex release]; [_regex release]; [super dealloc]; } - (void)finalizeFindingAll { if (_leafProcessing != nil) { [_leafProcessing finalizeFinding]; [_leafProcessing release]; _leafProcessing = nil; } else { [(OgreTextFindBranch*)[_branchStack lastObject] finalizeFinding]; } while ([self popBranch] != nil); [_branchStack release]; _branchStack = nil; while ([self popEnumerator] != nil); [_enumeratorStack release]; _enumeratorStack = nil; } /* Running and stopping */ /* Template Methods */ - (void)detach { _processTime = [[NSDate alloc] init]; _metronome = [[NSDate alloc] init]; _textFindResult = [[OgreTextFindResult alloc] initWithTarget:[_targetAdapter target] thread:self]; NS_DURING _numberOfTotalLeaves = [_rootAdapter numberOfDescendantsInSelection:_inSelection]; // <= 0: indeterminate _numberOfDoneLeaves = 0; [self willProcessFindingAll]; if (!_shouldFinish) [self visitBranch:_rootAdapter]; NS_HANDLER _exceptionRaised =YES; [self exceptionRaised:localException]; [self didProcessFindingAll]; [self finishingUp:nil]; NS_ENDHANDLER } - (void)willProcessFindingAll { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-willProcessFindingAll of %@", [self className]); #endif /* do nothing */ } - (void)didProcessFindingAll { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-didProcessFindingAll of %@", [self className]); #endif /* do nothing */ } /* visitor pattern */ - (void)visitLeaf:(OgreTextFindLeaf*)aLeaf // aLeaf == nil: resume from a break { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-visitLeaf: of %@", [self className]); #endif NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (aLeaf != nil) { /* begin */ _numberOfDoneLeaves++; _leafProcessing = [aLeaf retain]; [_leafProcessing willProcessFinding:self]; [self willProcessFindingInLeaf:_leafProcessing]; } #ifdef DEBUG_OGRE_FIND_PANEL else { NSLog(@"RESUME of %@", [self className]); } #endif NS_DURING BOOL shouldContinue; while (!_shouldFinish) { shouldContinue = [self shouldContinueFindingInLeaf:_leafProcessing]; if (_numberOfMatches % 40 == 0) { [pool release]; pool = [[NSAutoreleasePool alloc] init]; } if (_asynchronous && (-[_metronome timeIntervalSinceNow] >= 1.0)) { /* coffee break */ if (shouldContinue) { [_progressDelegate setProgress:[self progressPercentage] message:[self progressMessage]]; [_progressDelegate setDonePerTotalMessage:[NSString stringWithFormat:@"%d/%@", _numberOfDoneLeaves, (_numberOfTotalLeaves <= 0? @"???" : [NSString stringWithFormat:@"%d", _numberOfTotalLeaves])]]; } [_metronome release]; _metronome = [[NSDate alloc] init]; #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"BREAK of %@", [self className]); #endif [self performSelector:@selector(visitLeaf:) withObject:nil afterDelay:0]; [pool release]; NS_VOIDRETURN; } if (!shouldContinue) break; } /* end */ [_leafProcessing didProcessFinding:self]; [self didProcessFindingInLeaf:_leafProcessing]; [_leafProcessing release]; _leafProcessing = nil; [pool release]; if (aLeaf == nil) [self visitBranch:nil]; NS_HANDLER _exceptionRaised =YES; [self exceptionRaised:localException]; [_leafProcessing didProcessFinding:self]; [self didProcessFindingInLeaf:_leafProcessing]; [pool release]; [self didProcessFindingAll]; [self finishingUp:nil]; NS_ENDHANDLER } - (void)visitBranch:(OgreTextFindBranch*)aBranch // aBranch == nil: resume from a break { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-visitBranch: of %@", [self className]); #endif if (aBranch != nil) { /* begin */ _enumeratorProcessing = [aBranch componentEnumeratorInSelection:[self inSelection]]; [self pushEnumerator:_enumeratorProcessing]; [self pushBranch:aBranch]; [aBranch willProcessFinding:self]; [self willProcessFindingInBranch:aBranch]; } NSObject *component; while (!_shouldFinish) { component = [_enumeratorProcessing nextObject]; if (component == nil) break; [component acceptVisitor:self]; if (_leafProcessing != nil) break; // BREAK } if (_leafProcessing == nil && !_exceptionRaised) { /* end */ id processingBranch = [self topBranch]; [processingBranch didProcessFinding:self]; [self didProcessFindingInBranch:processingBranch]; [self popBranch]; [self popEnumerator]; _enumeratorProcessing = [self topEnumerator]; if (_enumeratorProcessing != nil) { /* continue */ if (aBranch == nil) [self visitBranch:nil]; } else { /* finish up */ [_progressDelegate done:[self donePercentage] message:[self doneMessage]]; [_progressDelegate setDonePerTotalMessage:[NSString stringWithFormat:@"%d/%@", _numberOfDoneLeaves, (_numberOfTotalLeaves == -1? @"???" : [NSString stringWithFormat:@"%d", _numberOfTotalLeaves])]]; [self didProcessFindingAll]; if (_shouldFinish) { if (_asynchronous) { [self performSelector:@selector(finishingUp:) withObject:nil afterDelay:0]; } else { [self finishingUp:nil]; } } } } } - (void)finishingUp:(id)sender { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-finishingUp: of %@", [self className]); #endif [_metronome release]; _metronome = nil; #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"processTime: %lf", -[_processTime timeIntervalSinceNow]); #endif [_processTime release]; _processTime = nil; [_textFindResult setNumberOfMatches:_numberOfMatches]; [_didEndTarget performSelector:_didEndSelector withObject:self]; } - (void)exceptionRaised:(NSException*)exception { [_textFindResult setType:OgreTextFindResultError]; [_textFindResult setAlertSheet:_progressDelegate exception:exception]; _shouldFinish = YES; } - (void)terminate { [self terminate:self]; } - (void)terminate:(id)sender { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-terminate: of %@", [self className]); #endif _terminated = YES; _shouldFinish = YES; } - (void)finish { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-terminate: of %@", [self className]); #endif _shouldFinish = YES; } /* result */ - (OgreTextFindResult*)result { return _textFindResult; } /* Configuration */ - (void)setRegularExpression:(OGRegularExpression*)regex { [_regex autorelease]; _regex = [regex retain]; } - (void)setReplaceExpression:(OGReplaceExpression*)repex { [_repex autorelease]; _repex = [repex retain]; } - (void)setHighlightColor:(NSColor*)highlightColor { [_highlightColor autorelease]; _highlightColor = [highlightColor retain]; } - (void)setOptions:(unsigned)options { _searchOptions = options; } - (void)setInSelection:(BOOL)inSelection { _inSelection = inSelection; } - (void)setDidEndSelector:(SEL)aSelector toTarget:(id)aTarget { _didEndSelector = aSelector; [_didEndTarget autorelease]; _didEndTarget = [aTarget retain]; } - (void)setProgressDelegate:(NSObject *)aDelegate { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-setProgressDelegate: of %@", [self className]); #endif _progressDelegate = aDelegate; // retain しない。むしろretainしてもらう。 [_progressDelegate setCancelSelector:@selector(terminate:) toTarget:self // will be retained withObject:nil]; } - (NSObject *)progressDelegate { return _progressDelegate; } /* Accessors */ - (OGRegularExpression*)regularExpression { return _regex; } - (OGReplaceExpression*)replaceExpression { return _repex; } - (NSColor*)highlightColor { return _highlightColor; } - (unsigned)options { return _searchOptions; } - (BOOL)inSelection { return _inSelection; } - (BOOL)isTerminated { return _terminated; } - (NSTimeInterval)processTime { return -[_processTime timeIntervalSinceNow]; } - (void)setAsynchronous:(BOOL)asynchronous { _asynchronous = asynchronous; } /* Methods implemented by subclasses */ - (void)willProcessFindingInBranch:(OgreTextFindBranch*)aBranch; { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-willProcessFindingInBranch: of %@ (BUG?)", [self className]); #endif /* do nothing */ } - (void)willProcessFindingInLeaf:(OgreTextFindLeaf*)aLeaf; { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-willProcessFindingInLeaf: of %@ (BUG?)", [self className]); #endif /* do nothing */ } - (BOOL)shouldContinueFindingInLeaf:(OgreTextFindLeaf*)aLeaf { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-shouldContinueFindingInLeaf: of %@ (BUG?)", [self className]); #endif return NO; // stop } - (void)didProcessFindingInLeaf:(OgreTextFindLeaf*)aLeaf; { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-didProcessFindingInLeaf: of %@ (BUG?)", [self className]); #endif /* do nothing */ } - (void)didProcessFindingInBranch:(OgreTextFindBranch*)aBranch; { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-didProcessFindingInBranch: of %@ (BUG?)", [self className]); #endif /* do nothing */ } - (SEL)didEndSelectorForFindPanelController { return @selector(didEndUnknownTextFindThread:); } - (NSString*)progressMessage { return @"Illegal progress message"; } - (NSString*)doneMessage { return @"Illegal progress message"; } /* Protected methods */ - (unsigned)numberOfMatches { return _numberOfMatches; } - (void)incrementNumberOfMatches { _numberOfMatches++; } - (double)progressPercentage { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-progressPercentage of %@ (BUG?)", [self className]); #endif return 0; } - (double)donePercentage { #ifdef DEBUG_OGRE_FIND_PANEL NSLog(@"-donePercentage of %@ (BUG?)", [self className]); #endif return 1; } - (void)pushEnumerator:(NSEnumerator*)anEnumerator { _enumeratorProcessing = anEnumerator; [_enumeratorStack addObject:anEnumerator]; } - (NSEnumerator*)topEnumerator { return [_enumeratorStack lastObject]; } - (NSEnumerator*)popEnumerator { if ([_enumeratorStack count] == 0) return nil; NSEnumerator *anObject = [[_enumeratorStack lastObject] retain]; [_enumeratorStack removeLastObject]; return [anObject autorelease]; } - (OgreTextFindBranch*)rootAdapter { return _rootAdapter; } - (NSObject *)targetAdapter { return _targetAdapter; } - (void)pushBranch:(OgreTextFindBranch*)aBranch { [_branchStack addObject:aBranch]; } - (OgreTextFindBranch*)topBranch { return [_branchStack lastObject]; } - (OgreTextFindBranch*)popBranch { if ([_branchStack count] == 0) return nil; OgreTextFindBranch *anObject = [[_branchStack lastObject] retain]; [_branchStack removeLastObject]; return [anObject autorelease]; } - (void)_setLeafProcessing:(OgreTextFindLeaf*)aLeaf { [_leafProcessing autorelease]; _leafProcessing = [aLeaf retain]; } - (void)addResultLeaf:(id)aResultLeaf { if (aResultLeaf != nil) [_textFindResult addLeaf:aResultLeaf]; } - (void)beginGraftingToBranch:(OgreTextFindBranch*)aBranch { OgreFindResultBranch *findResult = [aBranch findResultBranchWithThread:self]; [_textFindResult beginGraftingToBranch:findResult]; } - (void)endGrafting { [_textFindResult endGrafting]; } @end