This is FindManager.m in view mode; [Download] [Up]
/* 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 count = 0; char countbuf[256]; 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; /* vkyr */ count++; sprintf(countbuf,"%d\nreplaced", count); [warningText setStringValue: countbuf]; /* vkyr */ 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.