This is MiscFindPanel.m in view mode; [Download] [Up]
/*
* Copyright (c) 1993 Christopher J. Kane. All rights reserved.
*
* This software is subject to the terms of the MiscKit license
* agreement. Refer to the license document included with the
* MiscKit distribution for these terms.
*
* Version: 1.1.1 (14 December 1993)
*
* Incorporates a bug-fix by Annard Brouwer <annard@stack.urc.tue.nl>.
* The nextText outlet of the findTextField was remaining set to the
* replaceTextField. When the replace controls were hidden, this
* caused the Tab key in the findTextField to appear to do nothing.
* The text in the field is now correctly selected when the Tab key
* is pressed.
*/
#import "MiscFindPanel.h"
#import <misckit/SearchableText.h>
#import "Composer.h"
#import "MainWindowControl.h"
#import "descriptors.h"
#import <misckit/MiscAppDefaults.h>
#define DURING NX_DURING
#define HANDLER NX_HANDLER switch (NXLocalHandler.code) {
#define ENDHANDLER default: NXLogError("Uncaught exception: %d," \
" in %s:%s.\n", NXLocalHandler.code, __FILE__, \
sel_getName(_cmd)); abort();} NX_ENDHANDLER
#define IGNORE(E) case E: NXLogError("%s exception in %s:%s. " \
"Ignored.\n", #E, __FILE__, sel_getName(_cmd)); break
#define LocalString(K) NXLoadLocalizedStringFromTableInBundle(NULL, \
[NXBundle bundleForClass:[self class]], K, "")
static MiscFindPanel *_sharedFindPanel=nil;
static Pasteboard *_findPb=nil;
static Object *_firstConformer=nil;
static int _pbChangeCount=0;
static BOOL _replEnabled=YES;
static BOOL _useFindPb=YES;
static BOOL _allocationOK=NO;
static BOOL _resizeOK=NO;
static BOOL _fpLoaded=NO;
#define GSCOPE_TEXT 0
#define GSCOPE_SUBJECT 1
#define GSCOPE_MSGID 2
#define GSCOPE_NEWSGROUPS 3
#define GSCOPE_AUTHOR 4
#define GSCOPE_REFERENCES 5
@interface otherMethods
- newsgroupMatrix;
- articleMatrix;
- mySet;
- (int)grep:(const char *)pattern regexpr:(BOOL)regexpr cases:(BOOL)cases;
@end
@implementation MiscFindPanel
- _calcFindPanelTarget
{
id d,r=nil;
id i=[NXApp keyWindow];
if(i==self)
i=[NXApp mainWindow];
if((i==nil)||(i==self)) return nil;
d=[i delegate];
if(d==nil) return nil;
if([d isKindOf:[MainWindowControl class]]){
int scope=[[scopeSelection selectedCell] tag];
if(scope==GSCOPE_TEXT)
r=[d articleText];
else if(scope==GSCOPE_NEWSGROUPS)
r=[d newsgroupMatrix];
else
r=[d articleMatrix];
}
else if([d isKindOf:[Composer class]])
r=[d theText];
if([r isKindOf:[Text class]]){
NXSelPt start,end;
[r getSel:&start :&end];
if(start.cp==-1)
[r setSel:0 :0];
}
return r;
}
/*
id i;
if (_firstConformer!=nil)
return _firstConformer;
if (self!=[NXApp keyWindow])
{
for(i=[[NXApp keyWindow] firstResponder]; i; i = [i nextResponder])
if ([i conformsTo:@protocol(SearchableText)])
return i;
i = [[NXApp keyWindow] delegate];
if ([i conformsTo:@protocol(SearchableText)])
return i;
}
if ([NXApp keyWindow]!=[NXApp mainWindow])
{
for(i=[[NXApp mainWindow] firstResponder]; i; i = [i nextResponder])
if ([i conformsTo:@protocol(SearchableText)])
return i;
i = [[NXApp mainWindow] delegate];
if ([i conformsTo:@protocol(SearchableText)])
return i;
}
i = NXApp;
if ([i conformsTo:@protocol(SearchableText)])
return i;
i = [NXApp delegate];
if ([i conformsTo:@protocol(SearchableText)])
return i;
return nil;
}
*/
- (void)_getFindPbData
{
if (_pbChangeCount==[_findPb changeCount])
return;
DURING
if ([_findPb findAvailableTypeFrom:&NXAsciiPboardType num:1])
{
char *text;
int len;
if ([_findPb readType:NXAsciiPboardType data:&text length:&len])
{
[findTextField setStringValue:text];
[_findPb deallocatePasteboardData:text length:len];
}
}
HANDLER
IGNORE(NX_pasteboardComm);
IGNORE(NX_appkitVMError);
ENDHANDLER
_pbChangeCount = [_findPb changeCount];
}
- (void)_modifyFindPanel
{
NXRect r;
[contentView getBounds:&r];
[self disableFlushWindow];
if (_replEnabled)
{
_resizeOK = YES;
[super sizeWindow:NX_WIDTH(&r) :NX_HEIGHT(&r)+25.0];
_resizeOK = NO;
[[[findTextField superview] superview] moveBy:0.0 :25.0];
[contentView addSubview:_replBox :NX_BELOW relativeTo:nil];
[findTextField setNextText:replaceTextField]; /* added by Annard */
}
else
{
[_replBox removeFromSuperview];
[[[findTextField superview] superview] moveBy:0.0 :-25.0];
_resizeOK = YES;
[super sizeWindow:NX_WIDTH(&r) :NX_HEIGHT(&r)-25.0];
_resizeOK = NO;
[findTextField setNextText:findTextField]; /* added by Annard */
}
[self display];
[[self reenableFlushWindow] flushWindowIfNeeded];
}
- (void)_resetFindPanel
{
[messageTextField setStringValue:""];
[findTextField selectText:nil];
}
- (void)_setFindPbData
{
const char *text;
if (_pbChangeCount==[_findPb changeCount])
return;
text = [findTextField stringValue];
if (*text=='\0')
return;
DURING
_pbChangeCount = [_findPb declareTypes:&NXAsciiPboardType num:1 owner:NULL];
[_findPb writeType:NXAsciiPboardType data:text length:(int)strlen(text)];
HANDLER
IGNORE(NX_pasteboardComm);
ENDHANDLER
}
+ setFindPbEnabled:(BOOL)aBool
{
_useFindPb = aBool;
return self;
}
+ setFirstConformer:aConformer
{
id formerConformer = _firstConformer;
if (aConformer==nil || [aConformer conformsTo:@protocol(SearchableText)])
_firstConformer = aConformer;
return formerConformer;
}
+ setReplacementEnabled:(BOOL)aBool
{
if (aBool!=_replEnabled)
{
_replEnabled = aBool;
[_sharedFindPanel _modifyFindPanel];
}
return self;
}
+ sharedInstance
{
if (_sharedFindPanel==nil && !_fpLoaded)
{
char path[MAXPATHLEN+16];
_fpLoaded = YES;
_findPb = [Pasteboard newName:NXFindPboard];
_allocationOK = YES;
if ([[NXBundle bundleForClass:self] getPath:path forResource:"FindPanel.nib" ofType:NULL])
_sharedFindPanel = [NXApp loadNibFile:path owner:NXApp withNames:NO];
_allocationOK = NO;
if (_sharedFindPanel==nil)
NXRunAlertPanel(LocalString("LOAD_ERR"), LocalString("LOAD_ERR_MSG"), NULL, NULL, NULL);
else
{
if (!_replEnabled)
[_sharedFindPanel _modifyFindPanel];
[_sharedFindPanel setExcludedFromWindowsMenu:YES];
[_sharedFindPanel useOptimizedDrawing:YES];
}
}
return _sharedFindPanel;
}
- enterSelection:sender
{
[[self _calcFindPanelTarget] writeSelectionToPasteboard:_findPb asType:NXAsciiPboardType];
[self _getFindPbData];
[self _resetFindPanel];
return self;
}
- findBackward:sender
{
[self _resetFindPanel];
if (*[findTextField stringValue]=='\0' && _useFindPb)
[self _getFindPbData];
if (*[findTextField stringValue]=='\0')
[self makeKeyAndOrderFront:nil];
else
{
int pos, size, result;
id target = [self _calcFindPanelTarget];
if (_useFindPb)
[self _setFindPbData];
result = [target searchFor:[findTextField stringValue] mode:SelStartToSelEnd reverse:YES regexpr:[regExprButton state] cases:![ignoreCaseButton state] position:&pos size:&size];
if (target==nil || result<0)
{
[messageTextField setStringValue:LocalString("INVALID_OP")];
NXBeep();
}
else if (result==0)
{
[messageTextField setStringValue:LocalString("NOT_FOUND")];
NXBeep();
}
else
{
[target selectTextFrom:pos to:pos+size];
[target makeSelectionVisible];
}
}
return self;
}
- findForward:sender
{
[self _resetFindPanel];
if (*[findTextField stringValue]=='\0' && _useFindPb)
[self _getFindPbData];
if (*[findTextField stringValue]=='\0')
[self makeKeyAndOrderFront:nil];
else
{
int pos, size, result;
id target = [self _calcFindPanelTarget];
if (_useFindPb)
[self _setFindPbData];
result = [target searchFor:[findTextField stringValue] mode:SelEndToSelStart reverse:NO regexpr:[regExprButton state] cases:![ignoreCaseButton state] position:&pos size:&size];
if (target==nil || result<0)
{
[messageTextField setStringValue:LocalString("INVALID_OP")];
NXBeep();
}
else if (result==0)
{
[messageTextField setStringValue:LocalString("NOT_FOUND")];
NXBeep();
}
else
{
[target selectTextFrom:pos to:pos+size];
[target makeSelectionVisible];
}
}
return self;
}
- jumpToSelection:sender
{
[[self _calcFindPanelTarget] makeSelectionVisible];
return self;
}
- replace:sender
{
[self _resetFindPanel];
[[self _calcFindPanelTarget] replaceSelection:[replaceTextField stringValue]];
return self;
}
- replaceAll:sender
{
id target;
int count;
[self _resetFindPanel];
if (*[findTextField stringValue]=='\0')
return self;
target = [self _calcFindPanelTarget];
count = [target replaceAll:[findTextField stringValue] with:[replaceTextField stringValue] mode:([scopeMatrix selectedRow]?SelStartToSelEnd:TextEdgeToTextEdge) regexpr:[regExprButton state] cases:![ignoreCaseButton state]];
if (count<0 || target==nil)
{
[messageTextField setStringValue:LocalString("INVALID_OP")];
NXBeep();
}
else
{
char buffer[256];
sprintf(buffer, LocalString("N_REPLACED"), count);
[messageTextField setStringValue:buffer];
[target makeSelectionVisible];
}
return self;
}
- replaceAndFind:sender
{
[[self replace:sender] findForward:sender];
return self;
}
- grep:sender
{
[self _resetFindPanel];
if (*[findTextField stringValue]=='\0' && _useFindPb)
[self _getFindPbData];
if (*[findTextField stringValue]=='\0')
[self makeKeyAndOrderFront:nil];
else
{
int result;
id target = [self _calcFindPanelTarget];
if (_useFindPb)
[self _setFindPbData];
if((![target respondsTo:@selector(mySet)])||
(![[target mySet] respondsTo:@selector(grep:regexpr:cases:)]))
target=nil;
result = [[target mySet] grep:[findTextField stringValue] regexpr:[regExprButton state] cases:![ignoreCaseButton state]];
if (target==nil || result<0)
{
[messageTextField setStringValue:LocalString("INVALID_OP")];
NXBeep();
}
else if (result==0)
{
[messageTextField setStringValue:LocalString("NOT_FOUND")];
NXBeep();
}
}
return self;
}
- gscopeChanged:sender
{
int sel=[[scopeSelection selectedCell] tag];
int newDefault=-1;
switch(sel){
case GSCOPE_SUBJECT:
newDefault=SUBJECT;
break;
case GSCOPE_MSGID:
newDefault=MSG_ID;
break;
case GSCOPE_AUTHOR:
newDefault=FROM;
break;
case GSCOPE_REFERENCES:
newDefault=REFS;
break;
}
if(newDefault>=0)
[NXApp setDefault:"findGeneralScope" toInt:newDefault];
[replButton1 setEnabled:(sel==GSCOPE_TEXT)];
[replButton2 setEnabled:(sel==GSCOPE_TEXT)];
[replButton3 setEnabled:(sel==GSCOPE_TEXT)];
[replButton4 setEnabled:(sel!=GSCOPE_TEXT)];
return self;
}
- (TextField *)findTextField
{
return findTextField;
}
- (Button *)ignoreCaseButton
{
return ignoreCaseButton;
}
- (TextField *)messageTextField
{
return messageTextField;
}
- (Button *)regExprButton
{
return regExprButton;
}
- (TextField *)replaceTextField
{
return replaceTextField;
}
- (Matrix *)scopeMatrix
{
return scopeMatrix;
}
- (Matrix *)scopeSelection
{
return scopeSelection;
}
- textDidEnd:sender endChar:(unsigned short)theChar
{
if (theChar==NX_RETURN)
[self orderOut:nil];
return self;
}
- (BOOL)textWillChange:sender
{
return NO;
}
- (BOOL)textWillEnd:sender
{
return NO;
}
+ (BOOL)_canAlloc
{
return _allocationOK;
}
+ alloc
{
if (!_allocationOK)
return [self doesNotRecognize:_cmd];
return class_createInstanceFromZone(self, 0, NXDefaultMallocZone());
}
+ allocFromZone:(NXZone *)zone
{
if (!_allocationOK)
return [self doesNotRecognize:_cmd];
if (zone!=NX_NOZONE)
return class_createInstanceFromZone(self, 0, zone);
return nil;
}
+ (BOOL)instancesRespondTo:(SEL)aSel
{
if (aSel==@selector(copy) ||
aSel==@selector(copyFromZone:) ||
aSel==@selector(free) ||
aSel==@selector(init) ||
aSel==@selector(initContent:style:backing:buttonMask:defer:) ||
aSel==@selector(initContent:style:backing:buttonMask:defer:screen:) ||
aSel==@selector(miniaturize:) ||
aSel==@selector(placeWindow:) ||
aSel==@selector(placeWindow:screen:) ||
aSel==@selector(placeWindowAndDisplay:) ||
aSel==@selector(setDocEdited:) ||
aSel==@selector(sizeWindow::))
return NO;
return [super instancesRespondTo:aSel];
}
+ new
{
return [self doesNotRecognize:_cmd];
}
+ newContent:(const NXRect *)contentRect style:(int)aStyle backing:(int)bufferingType buttonMask:(int)mask defer:(BOOL)flag
{
return [self doesNotRecognize:_cmd];
}
+ newContent:(const NXRect *)contentRect style:(int)aStyle backing:(int)bufferingType buttonMask:(int)mask defer:(BOOL)flag screen:(const NXScreen *)screen
{
return [self doesNotRecognize:_cmd];
}
- copyFromZone:(NXZone *)zone
{
return self;
}
- free
{
return self;
}
- init
{
return [self doesNotRecognize:_cmd];
}
- initContent:(const NXRect *)contentRect style:(int)aStyle backing:(int)bufferingType buttonMask:(int)mask defer:(BOOL)flag
{
if (!_allocationOK)
return [self doesNotRecognize:_cmd];
return [super initContent:contentRect style:aStyle backing:bufferingType buttonMask:mask defer:flag];
}
- initContent:(const NXRect *)contentRect style:(int)aStyle backing:(int)bufferingType buttonMask:(int)mask defer:(BOOL)flag screen:(const NXScreen *)screen
{
return [self doesNotRecognize:_cmd];
}
- miniaturize:sender
{
return self;
}
- orderWindow:(int)place relativeTo:(int)otherWin
{
if (place!=NX_OUT)
{
if (_useFindPb)
[self _getFindPbData];
[self _resetFindPanel];
}
return [super orderWindow:place relativeTo:otherWin];
}
- placeWindow:(const NXRect *)aRect
{
if (_resizeOK)
return [super placeWindow:aRect];
return [self moveTo:NX_X(aRect) :NX_Y(aRect)];
}
- placeWindow:(const NXRect *)aRect screen:(const NXScreen *)aScreen
{
if (_resizeOK)
return [super placeWindow:aRect screen:aScreen];
return [self moveTo:NX_X(aRect) :NX_Y(aRect) screen:aScreen];
}
- placeWindowAndDisplay:(const NXRect *)aRect
{
if (_resizeOK)
return [super placeWindowAndDisplay:aRect];
return [[self moveTo:NX_X(aRect) :NX_Y(aRect)] display];
}
- read:(NXTypedStream *)stream
{
[super read:stream];
findTextField = NXReadObject(stream);
replaceTextField = NXReadObject(stream);
messageTextField = NXReadObject(stream);
ignoreCaseButton = NXReadObject(stream);
regExprButton = NXReadObject(stream);
scopeMatrix = NXReadObject(stream);
_replBox = NXReadObject(stream);
return self;
}
- (BOOL)respondsTo:(SEL)aSel
{
if (aSel==@selector(alloc) ||
aSel==@selector(allocFromZone:) ||
aSel==@selector(new) ||
aSel==@selector(newContent:style:backing:buttonMask:defer:) ||
aSel==@selector(newContent:style:backing:buttonMask:defer:screen:) ||
aSel==@selector(copy) ||
aSel==@selector(copyFromZone:) ||
aSel==@selector(free) ||
aSel==@selector(init) ||
aSel==@selector(initContent:style:backing:buttonMask:defer:) ||
aSel==@selector(initContent:style:backing:buttonMask:defer:screen:) ||
aSel==@selector(miniaturize:) ||
aSel==@selector(placeWindow:) ||
aSel==@selector(placeWindow:screen:) ||
aSel==@selector(placeWindowAndDisplay:) ||
aSel==@selector(setDocEdited:) ||
aSel==@selector(sizeWindow::))
return NO;
return [super respondsTo:aSel];
}
- setDocEdited:(BOOL)aBool
{
return self;
}
- sizeWindow:(float)x :(float)y
{
return self;
}
- write:(NXTypedStream *)stream
{
[super write:stream];
NXWriteObjectReference(stream, findTextField);
NXWriteObjectReference(stream, replaceTextField);
NXWriteObjectReference(stream, messageTextField);
NXWriteObjectReference(stream, ignoreCaseButton);
NXWriteObjectReference(stream, regExprButton);
NXWriteObjectReference(stream, scopeMatrix);
NXWriteObjectReference(stream, _replBox);
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.