home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / mmm_pkg.zip / mmmgrep.cpp < prev    next >
C/C++ Source or Header  |  1996-12-05  |  12KB  |  432 lines

  1. /*******************************
  2. * Search functions definitions *
  3. ********************************/
  4.  
  5. #include "mmmgrep.h"
  6. #include "mmm_comm.h"
  7.  
  8. #ifdef __DOS__
  9.     #include "mmm_dos.h"
  10. #endif
  11. #ifdef WIN32
  12.     #include "mmm_w95.h"
  13. #endif
  14. #ifdef __OS2__
  15.     #include "mmm_os2.h"
  16. #endif
  17. #ifdef __linux__
  18.     #include "mmm_lnx.h"
  19. #endif
  20.  
  21. //&<<&struct GrepTbl;
  22.  
  23. struct refs;
  24.  
  25. GrepTbl SearchMasks;
  26.  
  27. //&<<&int GrepTbl::Find(char *s,int &len,int sflg,int r0,int dir);
  28. int GrepTbl::Find(char *s,int &len,int sflg,int r0,int dir){
  29.   if(s==0) return -1;
  30.   int ls=strlen(s);
  31.   if(r0==int(0x8000)) r0=dir==SEARCH_FORWARD ? 0 : ls;
  32.   else if(r0<0){ if(dir!=SEARCH_FORWARD) return -1; r0=0; }
  33.   else if(r0>=ls){ if(dir==SEARCH_FORWARD) return -1; r0=ls; }
  34.   if(readyF==2){
  35. //&<<&    GREP search
  36.   ClrMask(CMask);
  37.  
  38.   if(r0==0) r0--;
  39.   int k;
  40.   for(k=r0;;k++){
  41.     SetBit(CMask,0);
  42.     ClrMask(tMask);
  43.     for(int i=0;i<ncn;i++) if(TstBit(CMask,i)) OrMask(tMask,TMask+lpt*i);
  44.     if(TstBit(tMask,ncn)) break;
  45.     if(k>0 && s[k-1]==0) return -1;
  46.     byte c=k<0 ? 0 : s[k];
  47.     if(sflg&1) AndMask(tMask,AMask+c*lpt);
  48.     else AndMask(tMask,AMask+c*lpt,AMask+lpt*mmm_KBD.AltCase[c]);
  49.     short *tp=tMask; tMask=CMask; CMask=tp;
  50.   }
  51.   ClrMask(CMask);
  52.   SetBit(CMask,ncn);
  53.   int l;
  54.   for(l=k;;){
  55.     assert(!EmptyMask(CMask));
  56.     ClrMask(tMask);
  57.     for(int i=0;i<ncn;i++) if(!EmptyAndMask(CMask,TMask+lpt*i)) SetBit(tMask,i);
  58.     if(TstBit(tMask,0)) break;
  59.     assert(l>r0);
  60.     byte c=l ? s[--l] : 0;
  61.     if(sflg&1) AndMask(tMask,AMask+lpt*c);
  62.     else AndMask(tMask,AMask+lpt*c,AMask+lpt*mmm_KBD.AltCase[c]);
  63.     short *tp=tMask; tMask=CMask; CMask=tp;
  64.   }
  65.   if(s[k-1]==0) k--;
  66.   if(l<0) l++;
  67.   len=k-l;
  68.   return l;
  69. //&>>&1A 0 17 34
  70.   }else if(readyF==1){
  71. //&<<&    Normal search
  72.    len=strlen(Ptrn);
  73.    if(len==0) return r0;
  74.    byte c=Ptrn[0],c1=mmm_KBD.AltCase[c];
  75.    int lc=ls-len;
  76.    if(dir==SEARCH_FORWARD){
  77.      for(;r0<=lc;r0++){
  78.        byte cs=s[r0];
  79.        if(cs!=c && ((sflg&1) || cs!=c1)) continue;
  80.        int i;
  81.        for(i=0;Ptrn[i];i++) if(s[r0+i]!=Ptrn[i] && ((sflg&1) || s[r0+i]!=mmm_KBD.AltCase[byte(Ptrn[i])])) break;
  82.        if(Ptrn[i]==0) return r0;
  83.      }
  84.    }else{
  85.      if(r0>lc) r0=lc;
  86.      for(;r0>=0;r0--){
  87.        byte cs=s[r0];
  88.        if(cs!=c && ((sflg&1) || cs!=c1)) continue;
  89.        int i;
  90.        for(i=0;Ptrn[i];i++) if(s[r0+i]!=Ptrn[i] && ((sflg&1) || s[r0+i]!=mmm_KBD.AltCase[byte(Ptrn[i])])) break;
  91.        if(Ptrn[i]==0) return r0;
  92.      }
  93.    }
  94.    return -1;
  95. //&>>&12 1 12 50
  96.   }else return -1;
  97. }
  98. //&>>&9 0 9 12
  99.  
  100. //&<<&Grep pattern
  101. /*
  102.   Grep pattern::
  103.  
  104.   [set]
  105.     set::   ] - ~ are special
  106.   {expr}
  107.   (expr|expr|expr)
  108.     (){}|[?* \bcqn are special (break/continue/conditional break/start-end of line)
  109.   "\ " = "replace"
  110. */
  111. //&>>&0 0 0 0
  112.  
  113. //&<<&char GetMacroChar(char *&s);
  114. int HexDig(char c){ return c>='0' && c<='9' ? c-'0' : c>='A' && c<='F' ? c-'A'+10 : c>='a' && c<='f' ? c-'a'+10 : -1; }
  115. char GetMacroChar(char *&s){
  116.     if(*s==0) return 0;
  117.     char c=*s++;
  118.     if(c!='\\') return c;
  119.     if(*s=='x'){ s++;
  120.       int i=HexDig(*s); if(i<0) return 0; s++;
  121.       int j=HexDig(*s); if(j<0) return i; s++;
  122.       return i*16+j;
  123.     }
  124.     if(*s==0) return 0;
  125.     return *s++;
  126. }
  127. //&>>&0 0 0 0
  128. //&<<&void GetAsciiSet(char *&s,short *asc,char fend);  // s - first char in [], fend=term char
  129. void GetAsciiSet(char *&s,short *asc,char fend){  // s - first char in [], fend=term char
  130.   memset(asc,0,256/8); int fnot=0;
  131.   if(*s=='^'){ s++; fnot=1; }
  132.   if(*s==']'){ asc[5]|=0x2000; s++; }  /// óºñÑαú¿óáÑΓß∩ í¿Γ ñ½∩ ']'
  133.   while(*s!=fend && *s!=0){
  134.     byte c=GetMacroChar(s);
  135.     if(*s=='-' && s[1]!=fend && s[1]!=0){
  136.       s++; byte c1=GetMacroChar(s);
  137.       for(;c<=c1;c++) asc[c>>4]|=1<<(c&15);
  138.     }else asc[c>>4]|=1<<(c&15);
  139.   }
  140.   if(fnot){ for(int i=1;i<256/16;i++) asc[i]^=-1; asc[0]^=-2; }
  141. }
  142. //&>>&D 0 D F
  143. struct refs{ int r1,r2,a,f; };
  144. //&<<&void GrepTbl::Set(char *ptrn);
  145. //&<<&char *GetPattern(char *&p);
  146. char *GetPattern(char *&p){
  147.   char *q=new char[strlen(p)+1]; MemTest(q!=0);
  148.   char *r=q;
  149.   while(*p){
  150.     if(*p!='\\') *r++=*p++;
  151.     else{
  152.       p++;
  153.       if(*p==' '){ p++; *r=0; return q; }
  154.       if(*p==0){ *r=0; return q; }
  155.       *r++=*p++;
  156.     }
  157.   }
  158.   *r=0;
  159.   return q;
  160. }
  161. //&>>&C 0 C 1B
  162.  
  163. void GrepTbl::Set(char *ptrn){
  164.   int i,j,k;
  165.   char *s;
  166.   short asc[16];
  167.  
  168.   delete Ptrn; delete Repl; Ptrn=Repl=0;
  169.  
  170.   char *s0=ptrn+strlen(ptrn);
  171.   while(s0!=ptrn && s0[-1]==' ') s0--;
  172.   if(*s0==0) s0=0; else *s0=0;
  173.  
  174.   if(ptrn[0]!='\\' || ptrn[1]!=' '){
  175.     Ptrn=GetPattern(ptrn);
  176.     if(*ptrn) Repl=GetPattern(ptrn);
  177.     readyF=1;
  178.     return;
  179.   }
  180.  
  181.   ptrn+=2;
  182.   char *s1=0;
  183. //&<<&  Find Number of multiletters
  184.   int nl=1,nr=1;
  185.   for(s=ptrn;*s!=0;){
  186.     switch(*s){
  187.     case '(': nr++; s++; break;
  188.     case '}': case ')': nl++; s++; break;
  189.     case '{':
  190.     case '|': s++; nr+=2; break;
  191.     case '[': s++; GetAsciiSet(s,asc,']'); if(*s==']') s++; nl++; break;
  192.     case '\\':
  193.       switch(s[1]){
  194.         case 'b': case 'c': case 'q': s+=2; nr++; break;
  195.         case ' ': s1=s; *s1=0; s+=2; Repl=GetPattern(s); goto _1;
  196.         case 0: s1=s; *s1=0; goto _1;
  197.         default: GetMacroChar(s); nl++; break;
  198.       }
  199.       break;
  200.     case '*': nr++;
  201.     default:
  202.       s++; nl++;
  203.     }
  204.   }
  205. _1:
  206.   nr+=nl;
  207. //&>>&C 0 C 25
  208.  
  209. //&<<&  Init memory
  210.   refs *R=new refs[nr];
  211.   lpt=nl/16+1;
  212.   if(lpt>lpt0){
  213.     delete AMask; AMask=new short[256*lpt];
  214.     delete TMask; TMask=new short[nl*lpt];
  215.     delete CMask; CMask=new short[lpt];
  216.     delete tMask; tMask=new short[lpt];
  217.     lpt0=lpt;
  218.   }
  219.   memset((char*)AMask,0,256*lpt*sizeof(short));
  220.   memset((char*)TMask,0,nl*lpt*sizeof(short));
  221. //&>>&0 0 0 5
  222.  
  223.   for(i=0;i<nr;i++){ R[i].r1=i+1; R[i].r2=R[i].a=0; }
  224.   int n=1; ncn=1;
  225.   for(s=ptrn;*s;) ProcChar(s,n,R,0);
  226.   R[n].a=ncn;
  227.  
  228.   for(i=0;i<n;i++) assert(R[i].r1>=0 && R[i].r2>=0);
  229.   for(i=0;i<n;i++) if(i==0 || R[i].a){
  230.     for(j=0;j<=n;j++) R[j].f=0;
  231.     R[R[i].r1].f=R[R[i].r2].f=1;
  232.     for(;;){
  233.       k=0;
  234.       for(j=1;j<n;j++) if(R[j].a==0 && R[j].f==1){
  235.         k=1;
  236.         R[R[j].r1].f|=1;
  237.         R[R[j].r2].f|=1;
  238.         R[j].f=2;
  239.       }
  240.       if(k==0) break;
  241.     }
  242.     for(j=1;j<=n;j++) if(R[j].f && R[j].a){
  243.       TMask[R[i].a*lpt+(R[j].a>>4)]|=1<<(R[j].a&15);
  244.     }
  245.   }
  246.   if(s0) *s0=' '; if(s1) *s1='\\';
  247.   readyF=2;
  248. }
  249. //&>>&11 0 11 14
  250. void GrepTbl::SetASC(char s){ AMask[byte(s)*lpt+(ncn>>4)]|=1<<(ncn&15); }
  251. //&<<&void GrepTbl::GetASC(char *&s);
  252. void GrepTbl::GetASC(char *&s){
  253.   short asc[16];
  254.   s++;
  255.   GetAsciiSet(s,asc,']');
  256.   if(*s==']') s++;
  257.   for(int i=0;i<256;i++) if(asc[i>>4]&(1<<(i&15))) SetASC(i);
  258. }
  259. //&>>&5 0 5 10
  260. //&<<&void GrepTbl::ProcChar(char *&s,int &n,refs *R,int LastLb);
  261. void GrepTbl::ProcChar(char *&s,int &n,refs *R,int LastLb){
  262.   int i;
  263.   switch(*s){
  264.   case '(':{
  265. //&<<&    Process "(...)" }
  266.     int lp=n,lor=n; n++; s++;
  267.     while(*s!=')' && *s){
  268.       if(*s=='|'){
  269.         R[n].r1=0; R[n].r2=-1; n++;
  270.         R[lor].r2=n; lor=n; n++; s++;
  271.       }else ProcChar(s,n,R,LastLb);
  272.     }
  273.     for(;lp<n;lp++) if(R[lp].r2==-1) R[lp].r2=n;
  274.     if(*s==')') s++; return; }
  275. //&>>&0 0 0 17
  276.   case '{':{
  277. //&<<&    Process "{...}" }
  278.     int lp=n,lor=n; n++; s++;
  279.     while(*s!='}' && *s){
  280.       if(*s=='|'){
  281.         R[n].r1=0; R[n].r2=lp; n++;
  282.         R[lor].r2=n; lor=n; n++; s++;
  283.       }else ProcChar(s,n,R,lp);
  284.     }
  285.     R[n].r1=lp; n++;
  286.     i=0;
  287.     for(;lp<n;lp++) if(R[lp].r2==-2) i=R[lp].r2=n;
  288.     if(i==0) R[lor].r2=n;
  289.     if(*s=='}') s++; return; }
  290. //&>>&7 0 7 B
  291.   case '*':           // {\q?}
  292.     R[n].r2=n+2;
  293.     R[n+1].r1=n;
  294.     n++;
  295.   case '?':
  296.     for(i=1;i<256;i++) SetASC(i); R[n++].a=ncn++; s++; return;
  297.   case '[': GetASC(s); R[n++].a=ncn++; return;
  298.   case '\\':
  299.     switch(s[1]){
  300.     case 'b': R[n].r2=-2; R[n].r1=0; s+=2; n++; return;
  301.     case 'c': R[n].r2=LastLb; R[n].r1=0; s+=2; n++; return;
  302.     case 'q': R[n].r2=-2; s+=2; n++; return;
  303.     case 'n': SetASC(0); R[n++].a=ncn++; s+=2; return;
  304.     }
  305.   default:
  306.     SetASC(GetMacroChar(s)); R[n++].a=ncn++; return;
  307.   }
  308. }
  309. //&>>&6 0 6 D
  310. //&>>&5 0 5 19
  311. //&<<&void SearchReplaceTextFragment(int SearchDirection,int DoReplace=0);
  312. void SearchReplaceTextFragment(int SearchDirection,int DoReplace){
  313.   if(cur==0 || cur->pos==0 || //cur->pos->buf==0 ||
  314.            SearchFold==0 || SearchFold->pos==0 || SearchFold->pos->buf==0 ){
  315.       Beep();
  316.       return;
  317.       }
  318.  
  319.   Line *sp_pos=cur->pos;
  320.  
  321.   if(SearchMasks.readyF==0){
  322.     SearchMasks.Set(SearchFold->pos->buf);
  323. //    SearchMasks.readyF=1;
  324.   }
  325.  
  326.   int i,l,k;
  327.   int ccx=cur->cx;
  328.   k=SearchMasks.Find(sp_pos->buf,l,Editor.SearchMode,ccx,SearchDirection);
  329.   char *Repl=SearchMasks.Repl;
  330.   if(k==ccx && DoReplace && Repl){
  331.     int lR=strlen(Repl);
  332.     if(l<lR)    { for(i=0;i<lR-l;i++) sp_pos->InsChar(ccx); }
  333.     else        { for(i=0;i<l-lR;i++) sp_pos->DelChar(ccx); }
  334.     for( i=0;Repl[i];i++) sp_pos->SetChar(ccx+i,Repl[i]);
  335.     cur->cx=ccx+lR;
  336.     Redr();
  337.     return;
  338.   }
  339.   if(k==ccx){
  340.     k=SearchMasks.Find(sp_pos->buf,l,Editor.SearchMode,ccx+GrepTbl::Dir(SearchDirection,SearchMasks.readyF),SearchDirection);
  341.   }
  342.   if(k>=0){ cur->cx=k; Redr(); return; }
  343. // not in current string!
  344.   Fold *f=cur->FindCont(SearchDirection,0,SearchDirection==SEARCH_FORWARD ? 2 : 0);
  345.   if(f){ cur=f; Redr(); }else Beep();
  346. }
  347.  
  348. //&>>&1 0 1 14
  349. //&<<&Fold *Fold::FindCont(int SearchDirection,int fcur,int ft);
  350. Fold *Fold::FindCont(int SearchDirection,int fcur,int ft){
  351.                 // fcur: 0=from current (and up), 1=from start/end (to end/start)
  352.                 // ft:1 if in current line; 2 if in current fold
  353.   if(this==0) return 0;
  354.   Line *CurLine=pos,*CL=pos;
  355.   int cury=sy;
  356.   Fold *rv=0;
  357.   if(SearchDirection!=SEARCH_FORWARD){
  358. //&<<&    Search Backward
  359.     if(fcur){
  360.       while(pos->next){ pos=pos->next; sy++; }
  361.       ft=0;
  362.     }
  363.     for(;;){
  364.       if(ft&2){
  365.         Fold *f=pos->Enter();
  366.         if(f){
  367.           f->top=this;
  368.           rv=f->FindCont(SearchDirection,1,0);
  369.           if(rv) break;
  370.         }
  371.       }
  372.       if(ft&1){
  373.         int l,k;
  374.         k=SearchMasks.Find(pos->buf,l,Editor.SearchMode,0x8000,SearchDirection);
  375.         if(k>=0){ cx=k; rv=this; break; }
  376.       }
  377.       if(!pos->prev) break;
  378.       pos=pos->prev; sy--;
  379.       ft=3;
  380.     }
  381. //&>>&0 0 0 0
  382.   }else{
  383. //&<<&    Search Forward
  384.     if(fcur){
  385.       while(pos->prev){ pos=pos->prev; sy--; }
  386.       ft=3;
  387.     }
  388.     for(;;){
  389.       if(pos->next==0) break;
  390.       if(ft&1){
  391.         int l,k;
  392.         k=SearchMasks.Find(pos->buf,l,Editor.SearchMode,0x8000,SearchDirection);
  393.         if(k>=0){ cx=k; rv=this; break; }
  394.       }
  395.       if(ft&2){
  396.         Fold *f=pos->Enter();
  397.         if(f){
  398.           f->top=this;
  399.           rv=f->FindCont(SearchDirection,1,0);
  400.           if(rv) break;
  401.         }
  402.       }
  403.       pos=pos->next; sy++;
  404.       ft=3;
  405.     }
  406. //&>>&13 0 13 0
  407.   }
  408.   if(rv) return rv;
  409.   assert(CurLine==CL);
  410.   pos=CurLine;
  411.   sy=cury;
  412.   if(fcur || IsFile()) return 0;
  413.   return Exit()->FindCont(SearchDirection,0,SearchDirection);    // 0,1 !!!
  414. }
  415. //&>>&8 0 8 17
  416.  
  417. //&<<&void SwitchIntoSearchPage(); 
  418. void SwitchIntoSearchPage() {
  419.     SearchMasks.readyF=0;
  420.     SaveMarkedBlock();
  421.     Editor.IsInSearchFold=!Editor.IsInSearchFold;
  422.     Fold *u=cur;
  423.     cur=SearchFold;
  424.     SearchFold=u;
  425.     GetCurrentFileNameAndDepth();
  426.     Redr();
  427. }
  428. //&>>&5 0 5 13
  429.  
  430. /// mmmgrep.err mmmgrep.err mmmgrep.err mmmgrep.err mmmgrep.err
  431. //&>>&14 0 14 7
  432.