home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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.2 (22 March 1994)
- */
-
- #import <misckit/MiscSearchText.h>
- #import <misckit/MiscTBMK.h>
- #import <misckit/regexpr.h>
-
- @implementation Text (SearchText)
-
- - (oneway void)makeSelectionVisible
- {
- [self scrollSelToVisible];
- }
-
- - (int)replaceAll:(const char *)pattern with:(const char *)replacement mode:(SearchMode)mode regexpr:(BOOL)regexpr cases:(BOOL)cases
- {
- unsigned char fm[256], tr[256];
- struct re_pattern_buffer rpat;
- Misc_TBMKpattern lpat=NULL;
- NXStream *in_strm=NULL, *out_strm=NULL;
- int s1=0, e1=0, s2=0, e2=0, ret_val, plen, rlen, pos, searchTextMaxSize;
-
- if (sp0.cp<0 && mode!=TextEdgeToTextEdge)
- return SEARCH_NO_SELECTION;
- if (![self isEditable])
- return SEARCH_CANNOT_WRITE;
- switch (mode)
- {
- case TextEdgeToTextEdge:
- case SelStartToSelStart:
- case SelEndToSelEnd: s1 = 0; e1 = textLength; break;
- case TextEdgeToSelStart: s1 = 0; e1 = sp0.cp; break;
- case TextEdgeToSelEnd: s1 = 0; e1 = spN.cp; break;
- case SelStartToSelEnd: s1 = sp0.cp; e1 = spN.cp-sp0.cp; break;
- case SelStartToTextEdge: s1 = sp0.cp; e1 = textLength-sp0.cp; break;
- case SelEndToTextEdge: s1 = spN.cp; e1 = textLength-spN.cp; break;
- case SelEndToSelStart: s1 = 0; e1 = sp0.cp; s2 = spN.cp; e2 = textLength-spN.cp; break;
- default: return SEARCH_INVALID_ARGUMENT;
- }
- searchTextMaxSize = s1+e1;
- plen = strlen(pattern);
- rlen = strlen(replacement);
- if (regexpr)
- {
- char *str;
- int i;
- memset(&rpat, 0, sizeof(rpat));
- for(i=256; i--;)
- tr[i] = i;
- if (!cases)
- for(i='A'; i<='Z'; i++) tr[i] = i-'A'+'a';
- rpat.translate = tr;
- rpat.fastmap = fm;
- str = re_compile_pattern((char *)pattern, plen, &rpat);
- if (str!=NULL)
- return (strcmp(str, "Out of memory")?SEARCH_INVALID_REGEXPR:SEARCH_INTERNAL_ERROR);
- }
- else
- {
- lpat = Misc_TBMKpattern_alloc(pattern, plen, 0, !cases);
- if (lpat==NULL)
- return SEARCH_INTERNAL_ERROR;
- }
- out_strm = NXOpenMemory(NULL, 0, NX_READWRITE);
- in_strm = NXOpenMemory(NULL, 0, NX_READWRITE);
- if (out_strm==NULL || in_strm==NULL)
- {
- ret_val = SEARCH_INTERNAL_ERROR;
- goto exit;
- }
- [self writeText:in_strm];
- NXSeek(in_strm, 0, NX_FROMSTART);
- ret_val = 0;
- NXWrite(out_strm, in_strm->buf_base, s1); /* get up to start of searching */
- /* invariant for searching: in_strm->buf_base+s1+e1 is the position _after_ the last one searched */
- start_searching:
- if (regexpr)
- {
- while (!NXUserAborted() && e1>0 && (pos = re_search_pattern(&rpat, in_strm->buf_base, searchTextMaxSize, s1, e1, 0))>=0)
- {
- int len = re_match_pattern(&rpat, in_strm->buf_base, searchTextMaxSize, pos, 0);
- if (len<0)
- {
- ret_val = SEARCH_INTERNAL_ERROR;
- goto exit;
- }
- NXWrite(out_strm, in_strm->buf_base+s1, pos-s1);
- NXWrite(out_strm, replacement, rlen);
- e1 -= (pos-s1+len);
- s1 = (pos+len);
- ret_val++;
- }
- if (pos==-2)
- {
- ret_val = SEARCH_INTERNAL_ERROR;
- goto exit;
- }
- }
- else
- {
- while (!NXUserAborted() && e1>0 && Misc_TBMKsearch_memory(lpat, in_strm->buf_base+s1, e1, 0, &pos)>0)
- {
- NXWrite(out_strm, in_strm->buf_base+s1, pos);
- NXWrite(out_strm, replacement, rlen);
- s1 += (pos+plen);
- e1 -= (pos+plen);
- ret_val++;
- }
- }
- if (NXUserAborted())
- {
- ret_val = SEARCH_ABORTED;
- goto exit;
- }
- if (e1>0)
- NXWrite(out_strm, in_strm->buf_base+s1, e1); /* get remainder of searched material */
- if (e2!=0)
- {
- NXWrite(out_strm, in_strm->buf_base+s1+e1, s2-(s1+e1)); /* get gap */
- s1 = s2;
- e1 = e2;
- s2 = e2 = 0;
- goto start_searching;
- }
- NXWrite(out_strm, in_strm->buf_base+s1+e1, textLength-(s1+e1)); /* after searched to end */
- NXSeek(out_strm, 0, NX_FROMSTART);
- [self readText:out_strm];
- [self setSel:0 :0];
- exit:
- Misc_TBMKpattern_free(&lpat);
- if (in_strm!=NULL)
- NXCloseMemory(in_strm, NX_FREEBUFFER);
- if (out_strm!=NULL)
- NXCloseMemory(out_strm, NX_FREEBUFFER);
- return ret_val;
- }
-
- - (oneway void)replaceSelection:(const char *)replacement
- {
- if ([self isEditable])
- [self replaceSel:replacement];
- }
-
- - (int)searchFor:(const char *)pattern mode:(SearchMode)mode reverse:(BOOL)rev regexpr:(BOOL)regexpr cases:(BOOL)cases position:(out int *)pos size:(out int *)size
- {
- unsigned char fm[256], tr[256];
- struct re_pattern_buffer rpat;
- Misc_TBMKpattern lpat=NULL;
- NXStream *in_strm=NULL;
- int s1=0, e1=0, s2=0, e2=0, ret_val, plen, p, position;
-
- if (sp0.cp<0 && mode!=TextEdgeToTextEdge)
- return SEARCH_NO_SELECTION;
- if (rev)
- switch (mode)
- {
- case TextEdgeToSelStart: s1 = textLength-1; e1 = sp0.cp-textLength; break;
- case TextEdgeToSelEnd: s1 = textLength-1; e1 = spN.cp-textLength; break;
- case TextEdgeToTextEdge: s1 = textLength-1; e1 = -textLength; break;
- case SelStartToSelEnd: s1 = sp0.cp-1; e1 = -sp0.cp+1; s2 = textLength-1; e2 = spN.cp-textLength+1; break;
- case SelStartToTextEdge: s1 = sp0.cp-1; e1 = -sp0.cp+1; break;
- case SelStartToSelStart: s1 = sp0.cp-1; e1 = -sp0.cp+1; s2 = textLength-1; e2 = sp0.cp-textLength+1; break;
- case SelEndToTextEdge: s1 = spN.cp-1; e1 = -spN.cp+1; break;
- case SelEndToSelStart: s1 = spN.cp-1; e1 = sp0.cp-spN.cp+1; break;
- case SelEndToSelEnd: s1 = spN.cp-1; e1 = -spN.cp+1; s2 = textLength-1; e2 = spN.cp-textLength+1; break;
- default: return SEARCH_INVALID_ARGUMENT;
- }
- else
- switch (mode)
- {
- case TextEdgeToSelStart: s1 = 0; e1 = sp0.cp; break;
- case TextEdgeToSelEnd: s1 = 0; e1 = spN.cp; break;
- case TextEdgeToTextEdge: s1 = 0; e1 = textLength; break;
- case SelStartToSelEnd: s1 = sp0.cp; e1 = spN.cp-sp0.cp; break;
- case SelStartToTextEdge: s1 = sp0.cp; e1 = textLength-sp0.cp; break;
- case SelStartToSelStart: s1 = sp0.cp; e1 = textLength-sp0.cp; s2 = 0; e2 = sp0.cp; break;
- case SelEndToTextEdge: s1 = spN.cp; e1 = textLength-spN.cp; break;
- case SelEndToSelStart: s1 = spN.cp; e1 = textLength-spN.cp; s2 = 0; e2 = sp0.cp; break;
- case SelEndToSelEnd: s1 = spN.cp; e1 = textLength-spN.cp; s2 = 0; e2 = spN.cp; break;
- default: return SEARCH_INVALID_ARGUMENT;
- }
- plen = strlen(pattern);
- if (regexpr)
- {
- char *str;
- int i;
- memset(&rpat, 0, sizeof(rpat));
- for(i=256; i--;)
- tr[i] = i;
- if (!cases)
- for(i='A'; i<='Z'; i++) tr[i] = i-'A'+'a';
- rpat.translate = tr;
- rpat.fastmap = fm;
- str = re_compile_pattern((char *)pattern, plen, &rpat);
- if (str!=NULL)
- return (strcmp(str, "Out of memory")?SEARCH_INVALID_REGEXPR:SEARCH_INTERNAL_ERROR);
- }
- else
- {
- lpat = Misc_TBMKpattern_alloc(pattern, plen, rev, !cases);
- if (lpat==NULL)
- return SEARCH_INTERNAL_ERROR;
- }
- in_strm = NXOpenMemory(NULL, 0, NX_READWRITE);
- if (in_strm==NULL)
- {
- ret_val = SEARCH_INTERNAL_ERROR;
- goto exit;
- }
- [self writeText:in_strm];
- NXSeek(in_strm, 0, NX_FROMSTART);
- ret_val = 0;
- start_searching:
- if (NXUserAborted())
- {
- ret_val = SEARCH_ABORTED;
- goto exit;
- }
- if (regexpr)
- {
- p = -1;
- if (s1>=0)
- p = re_search_pattern(&rpat, in_strm->buf_base, textLength, s1, e1, 0);
- if (p==-1 && e2!=0)
- {
- s1 = s2;
- e1 = e2;
- s2 = e2 = 0;
- goto start_searching;
- }
- if (p==-2)
- {
- ret_val = SEARCH_INTERNAL_ERROR;
- goto exit;
- }
- if (p>-1)
- {
- *pos = p;
- *size = re_match_pattern(&rpat, in_strm->buf_base, textLength, p, 0);
- if (*size<0)
- {
- ret_val = SEARCH_INTERNAL_ERROR;
- goto exit;
- }
- ret_val = 1;
- }
- }
- else
- {
- p = 0;
- if (s1>=0)
- p = Misc_TBMKsearch_memory(lpat, in_strm->buf_base+s1, e1, 0, &position);
- if (p<0)
- {
- ret_val = SEARCH_INTERNAL_ERROR;
- goto exit;
- }
- if (p==0 && e2!=0)
- {
- s1 = s2;
- e1 = e2;
- s2 = e2 = 0;
- goto start_searching;
- }
- if (p>0)
- {
- *pos = position+s1;
- *size = plen;
- ret_val = 1;
- }
- }
- exit:
- Misc_TBMKpattern_free(&lpat);
- if (in_strm!=NULL)
- NXCloseMemory(in_strm, NX_FREEBUFFER);
- return ret_val;
- }
-
- - (oneway void)selectTextFrom:(int)start to:(int)end
- {
- if ([self isSelectable] && start<=end && 0<=start)
- [self setSel:start :end];
- }
-
- - (int)setRegExprSyntax:(int)syntax
- {
- return re_set_syntax(syntax);
- }
-
- - (void)writeSelectionToPasteboard:(in Pasteboard *)pboard asType:(in NXAtom)type
- {
- char text[spN.cp-sp0.cp+1];
- [self getSubstring:text start:sp0.cp length:spN.cp-sp0.cp];
- text[spN.cp-sp0.cp] = '\0';
- if (*text!='\0')
- {
- [pboard declareTypes:&type num:1 owner:NULL];
- [pboard writeType:type data:text length:spN.cp-sp0.cp];
- }
- }
-
- @end
-