home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula
/
nebula.bin
/
SourceCode
/
Classes
/
FindManager
/
FindManager.m
< prev
next >
Wrap
Text File
|
1992-01-09
|
10KB
|
523 lines
/* Generated by Interface Builder */
#import "FindManager.h"
#import <objc/Object.h>
#import <appkit/Application.h>
#import <appkit/Panel.h>
#import <appkit/Form.h>
#import <appkit/Text.h>
#import <appkit/Control.h>
#import <appkit/Button.h>
#import <streams/streams.h>
#import <string.h>
#import <stdlib.h>
#import <ctype.h>
#import "regex.h"
static id instance = nil;
static char upcase[0400] =
{000, 001, 002, 003, 004, 005, 006, 007,
010, 011, 012, 013, 014, 015, 016, 017,
020, 021, 022, 023, 024, 025, 026, 027,
030, 031, 032, 033, 034, 035, 036, 037,
040, 041, 042, 043, 044, 045, 046, 047,
050, 051, 052, 053, 054, 055, 056, 057,
060, 061, 062, 063, 064, 065, 066, 067,
070, 071, 072, 073, 074, 075, 076, 077,
0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
};
int search(const char *match, char *text, int start, int most, int matchCase);
@implementation FindManager
+ new
{
if((instance != nil) && [instance isKindOf:[FindManager class]])
return instance;
else
return (instance = [[FindManager alloc] init]);
}
- init
{
if(instance != nil)
return nil;
self = [super init];
instance = self;
[NXApp loadNibSection:"FindManager.nib" owner:self withNames:NO];
countType = line;
extent = all;
regex = NO;
matchCase = NO;
re_set_syntax(RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS);
return self;
}
- textDidEnd:textObject endChar:(unsigned short)whyEnd
{
free(currentText);
currentText = NXCopyStringBuffer([findView stringValue]);
return self;
}
- (char *)currentText
{
return currentText;
}
- checkResponder
{
id fr = [[NXApp mainWindow] firstResponder];
if([fr isKindOf:[Text class]])
return fr;
else
return nil;
}
- orderFrontFindPanel:sender
{
[findPanel makeKeyAndOrderFront:self];
[findView setStringValue:currentText];
[findView selectTextAt:0];
return self;
}
- orderFrontCountPanel:sender
{
id text;
[countPanel makeKeyAndOrderFront:self];
if((text =[self checkResponder]) == nil)
return self;
else
{
NXSelPt start, end;
char buf[20];
[text getSel:&start :&end];
switch(countType)
{
case line :
{
sprintf(buf, "%d", [text lineFromPosition:start.c1st]);
if(start.c1st != end.c1st)
{
sprintf((buf + strlen(buf)), ":%d",
[text lineFromPosition:end.c1st]);
}
break;
}
case character :
{
sprintf(buf, "%d", start.cp);
if(start.cp != end.cp)
{
sprintf((buf + strlen(buf)), ":%d", end.cp);
}
break;
}
}
[countView setStringValue:buf];
[countView selectText:self];
}
return self;
}
- enterSelection:sender
{
id text;
NXSelPt start, end;
if((text = [self checkResponder]) == nil)
return self;
[text getSel:&start :&end];
if(start.cp != end.cp)
{
currentText = (char *)realloc(currentText, end.cp - start.cp + 1);
[text getSubstring:currentText start:start.cp length:end.cp - start.cp];
*(currentText + end.cp - start.cp) = '\0';
[findView setStringValue:currentText];
}
[findView selectText:self];
return self;
}
- replace:sender
{
return [self find:replace];
}
- replaceAll:sender
{
return [self find:rall];
}
- setOptions:sender
{
switch([sender selectedTag])
{
case 0 :
matchCase = ![sender state];
break;
case 1:
regex = [sender state];
break;
default:
break;
}
return self;
}
- findNext:sender
{
return [self find:next];
}
- jumpToSelection:sender
{
id text;
if((text =[self checkResponder]) == nil)
return self;
[text scrollSelToVisible];
return self;
}
- findPrevious:sender
{
return [self find:previous];
}
- replaceAndFind:sender
{
return [self find:(replace | next)];
}
- find:(find_type)findTag
{
id textO;
NXStream *stream;
if((textO =[self checkResponder]) == nil)
return self;
else
{
const char *replaceBuf;
NXSelPt start, end;
int len;
struct re_pattern_buffer buf;
char fastmap[(1 << BYTEWIDTH)];
currentText = (char *)[findView stringValueAt:0];
replaceBuf = [findView stringValueAt:1];
if(findTag & replace)
{
[textO replaceSel:replaceBuf];
}
if(!(findTag & ~replace))
return self;
if(regex)
{
buf.allocated = 40;
buf.buffer = (char *)malloc(buf.allocated);
buf.fastmap = fastmap;
if(!matchCase)
buf.translate = upcase;
else buf.translate = NULL;
re_compile_pattern(currentText, strlen(currentText), &buf);
re_compile_fastmap(&buf);
}
len = [textO textLength];
if(len == 0)
return self;
[textO getSel:&start :&end];
stream = [textO stream];
if(findTag & (next|previous))
{
int i, flen, wrapped = NO, found = NO;
int begin;
int most;
textStart = (char *)realloc(textStart, len);
NXRead(stream, textStart, len);
if(findTag & next)
{
begin = end.cp;
most = len - end.cp;
}
else
{
begin = start.cp - 1;
most = -start.cp + 1;
if(begin < 0)
{
begin = len - 1;
most = start.cp - len + 1;
wrapped = YES;
}
}
do
{
if(regex)
{
i = re_search(&buf, textStart, len, begin, most, 0, &flen);
}
else
{
i = search(currentText, textStart, begin, most, matchCase);
flen = strlen(currentText);
}
if(i < 0)
{
if(!wrapped)
{
wrapped = YES;
if(findTag & next)
{
begin = 0;
most = end.cp;
}
else
{
begin = len - 1;
most = start.cp - len + 1;
}
}
else
{
if(!found)
{
[warningText setStringValue:"Not\nFound"];
}
return self;
}
}
else
{
if(!found)
[warningText setStringValue:""];
found = YES;
[textO setSel:i:i + flen];
[textO scrollSelToVisible];
}
} while(!found);
}
if(findTag & rall)
{
int begin = 0, most, i, flen, found = NO, offset;
int rlen = strlen(replaceBuf);
if(extent != all)
{
offset = start.cp;
most = end.cp - start.cp - 1;
len = most;
}
else
{
offset = 0;
most = len;
}
if(most < 1)
return self;
NXSeek(stream, offset, NX_FROMSTART);
textStart = (char *)realloc(textStart, most);
NXRead(stream, textStart, most);
flen = strlen(currentText);
for(;;)
{
if(regex)
{
i = re_search(&buf, textStart, len, begin, most, 0, &flen);
}
else
{
i = search(currentText, textStart, begin, most, matchCase);
}
if((i < 0) || (i + flen) > len)
{
if(!found)
[warningText setStringValue:"Not\nFound"];
return self;
}
else
{
if(!found)
{
[warningText setStringValue:""];
found = YES;
}
[textO setSel:i + offset :i + offset + flen];
[textO replaceSel:replaceBuf];
offset += rlen - flen;
begin = i + flen;
most = len - begin;
if(most < 0)
{
if(!found)
[warningText setStringValue:"Not\nFound"];
return self;
}
}
}
}
return self;
}
}
- jumpToCount:sender
{
id text;
if((text =[self checkResponder]) == nil)
return self;
else
{
char *test;
int end;
const char *buf = [countView stringValue];
int start = atoi(buf);
if((test = strchr(buf, ':')) != NULL)
end = atoi(test + 1);
else
end = start;
switch(countType)
{
case line :
{
[text setSel:[text positionFromLine:start]
:[text positionFromLine:end + 1]];
break;
}
case character :
{
[text setSel:start :end];
break;
}
}
}
[countPanel orderOut:self];
[text scrollSelToVisible];
return self;
}
- setCountType:sender
{
countType = [sender selectedTag];
return self;
}
- setSearchExtent:sender
{
extent = [sender selectedTag];
return self;
}
int search(const char *match, char *text, int start, int most, int matchCase)
{
int len, offset = 0;
int c, dir;
len = strlen(match);
if(most < 0)
{
c = len - 1;
dir = -1;
}
else
{
c = 0;
dir = 1;
}
offset = 0;
if(abs(offset) > abs(most))
return -1;
if(matchCase)
{
for(;;)
{
while(*(text + start + offset) != *(match + c))
{
offset += dir;
if(abs(offset) > abs(most))
return -1;
}
if(!strncmp(text + start + offset - c, match, abs(len)))
{
return start + offset - c;
}
offset += dir;
}
}
else
{
for(;;)
{
while(tolower(*(text + start + offset)) != tolower(*(match + c)))
{
offset += dir;
if(abs(offset) > abs(most))
return -1;
}
if(!strncasecmp(text + start + offset - c, match, abs(len)))
{
return start + offset - c;
}
offset += dir;
}
}
return -1;
}
@end