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

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