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

  1. /**********************************************
  2. ***********************************************
  3. ***  Base Editor file, contains text manip. ***
  4. ***                 stuff                   ***
  5. ***********************************************
  6. **********************************************/
  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.     #include "mmm_lnx.h"
  23. #endif
  24.  
  25. //&>>&0 0 0 11
  26.  
  27. //&<<&Forward_declarations
  28. //&<<&#ifdef _ENABLE_LOGGING_
  29. #ifdef _ENABLE_LOGGING_
  30. void DoLog(char *format, ... )
  31. {
  32. FILE *lf=fopen("log.","a+");
  33. if(lf==0) exit(0);
  34.  
  35. va_list arglist;
  36. va_start( arglist, format );
  37. vfprintf(lf, format, arglist );
  38. va_end( arglist );
  39.  
  40. fclose(lf);
  41. }
  42. #endif
  43. //&>>&1 0 1 5
  44. void putl(char *s,FILE *f){
  45.   fputs(s,f); putc('\n',f);
  46. }
  47. void putl(char *s1,char *s2,char *s3,FILE *f){
  48.   fputs(s1,f); fputs(s2,f); fputs(s3,f); putc('\n',f);
  49. }
  50. //void MkScan(int scancode);
  51. //&>>&7 0 7 0
  52. //&<<&Constants and variables
  53. Chain *ConstantPage=0;
  54. Chain *CurrentPage=0;
  55.  
  56. Fold *SearchFold=0;
  57.  
  58. Fold *cur=0;           // Current fold
  59.  
  60. Line *mmm_LineClipboard=0;    // Line clipboard
  61. Fold *fLineClipboard=0;
  62.  
  63. unsigned long FileLinesCounter;  // very strange variable....temporary.....
  64.  
  65. int lHead=0;       // number of blank strings on the top of screen (for 2nd statusline)
  66.  
  67. int MarkedBlockLength;    // Number of lines in buffer
  68. MarkedLine *MarkedBlock;  // pointer to buffer with ML-s
  69.                           // it would be better to include it into Editor class,
  70.                           // but mmmx.exe must use <= 64k in DOS (optimization)
  71.  
  72. char *comment;         // comment to be applied to file
  73. int lcomment;          // length of current comment
  74. //&>>&8 0 8 0
  75.  
  76. //&<<&class Line;
  77. //&<<&Line::Line(char *s);
  78. Line::Line(char *s):prev(0),next(0),fchg(0),buf(0),lbuf(0),marked(0){
  79.   if(s){
  80.     Realloc(strlen(s));
  81.     strcpy(buf,s);
  82.   }
  83. }
  84. //&>>&0 0 0 10
  85. //&<<&Line::~Line();
  86. Line::~Line(){
  87.   UnLink();
  88.   delete buf;
  89. }
  90. //&>>&2 0 2 9
  91. //&<<&void Line::UnLink();
  92. void Line::UnLink(){
  93.   if(prev) prev->next=next;
  94.   if(next) next->prev=prev;
  95. }
  96. //&>>&1 0 1 0
  97. //&<<&Line *Line::LinkBefore(Line *f);
  98. Line *Line::LinkBefore(Line *f){         // this is unlinked
  99.   prev=f->prev; next=f;
  100.   if(prev) prev->next=this;
  101.   f->prev=this;
  102.   return this;
  103. }
  104. //&>>&1 0 1 0
  105. //&<<&Line *Line::Copy(int cln){
  106. Line *Line::Copy(int cln){
  107.   Line *x=NewLine(buf,cln?linenumber:0);
  108.   x->type=type;
  109.   x->fchg=LINE_NEW;
  110.   return x;
  111. }
  112. //&>>&0 0 0 1A
  113. //&<<&void Line::Realloc(int x);
  114. void Line::Realloc(int x){
  115.   if(x<lbuf) return;
  116.   int lb=x+(buf ? 20 : 1);
  117.   char *m=new char[lb]; MemTest(m!=0);
  118.   if(lbuf) memcpy(m,buf,lbuf);
  119.   while(lbuf<lb) m[lbuf++]=0;
  120.   delete buf; buf=m;
  121. }
  122. //&>>&3 0 3 14
  123. //&<<&void Line::Write(FILE *f,int);
  124. void Line::Write(FILE *f,int){
  125.   while(lbuf){
  126.     lbuf--; if(buf[lbuf]==' ') buf[lbuf]=0;
  127.     if(buf[lbuf]) break;
  128.   }
  129.   putl(buf,f);
  130. }
  131. //&>>&3 0 3 12
  132.  
  133. //&<<&void Line::InsChar(int cx);
  134. void Line::InsChar(int cx){
  135.   int i;
  136.   if(cx>=lbuf || buf[cx]==0) return;
  137.   if(lbuf<2 || buf[lbuf-2]) Realloc(lbuf+1);
  138.   for(i=lbuf-1;i>cx;i--) buf[i]=buf[i-1];
  139.   buf[cx]=' ';
  140.   fchg|=LINE_CHG;
  141.   Redr(marked?REDRAW_WHOLE_SCREEN:REDRAW_CURRENT_LINE);
  142. }
  143. //&>>&0 0 0 7
  144. //&<<&void Line::DelChar(int cx);
  145. void Line::DelChar(int cx){
  146.   if(cx>=lbuf || buf[cx]==0) return;
  147.   do{ buf[cx]=buf[cx+1]; cx++; }while(buf[cx]);
  148.   fchg|=LINE_CHG;
  149.   Redr(marked?REDRAW_WHOLE_SCREEN:REDRAW_CURRENT_LINE);
  150. }
  151. //&>>&5 0 5 17
  152. //&<<&void Line::SetChar(int cx,char c);
  153. void Line::SetChar(int cx,char c){
  154.   int i;
  155.   if((cx>=lbuf || buf[cx]==0) && c==' ') return;
  156.   Realloc(cx+2);
  157.   if(buf[cx]==0) for(i=cx;i>=0 && buf[i]==0; i--) buf[i]=' ';
  158.   if(buf[cx]!=c){
  159.     fchg|=LINE_CHG;
  160.     Redr(marked?REDRAW_WHOLE_SCREEN:REDRAW_CURRENT_LINE);
  161.     buf[cx]=c;
  162.   }
  163. }
  164. //&>>&7 0 7 0
  165.  
  166. //&<<&char *Line::GetWord(int cx);
  167. char *Line::GetWord(int cx){
  168.   int i,j;
  169.   if(buf==0 || cx>=lbuf) return 0;
  170.   for(i=cx;--i>=0 && byte(buf[i])>' ';) ;
  171.   i++;
  172.   if(byte(buf[i])<=' ') return 0;
  173.   for(j=i;byte(buf[j])>' ';j++) ;
  174.   char *d=new char[j-i+1]; MemTest(d!=0);
  175.   memcpy(d,buf+i,j-i); d[j-i]=0;
  176.   return d;
  177. }
  178. //&>>&0 0 0 1C
  179. //&<<&char *Line::GetFileName(int cx);
  180. char *Line::GetFileName(int cx){
  181.     int i0,i1;
  182.     if(buf==0) return 0;
  183.     if(cx && cx<lbuf && byte(buf[cx])<=' ') cx--;
  184.     if(cx>=lbuf || byte(buf[cx])<=' ') return 0;
  185.  
  186.     if(cx>1 && byte(buf[cx+1])<=' ' && (byte(buf[cx])=='\"' || byte(buf[cx])=='>')) cx--;
  187.     i0=cx;
  188.     while(i0>=0 && byte(buf[i0])>' ' && byte(buf[i0])!='\"' && byte(buf[i0])!='<' )i0--;
  189.     i1=i0+1;
  190.     if(i0>=0 &&(byte(buf[i0])=='\"' || byte(buf[i0])=='<')){
  191.         while(byte(buf[i1])!='\"' && byte(buf[i1])!='>' && i1<lbuf )i1++;
  192.     }else{
  193.         while(i1<lbuf && byte(buf[i1])>' ' && byte(buf[i1])!='\"' && byte(buf[i1])!='>')
  194.             i1++;
  195.         if(byte(buf[i1])=='\"' || byte(buf[i1])=='>'){
  196.             while(byte(buf[i0])!='\"' && byte(buf[i0])!='>' && i0>=0 )  i0--;
  197.             }
  198.         }
  199.     i0++;
  200.     while(i0<lbuf && byte(buf[i0])<=' ') i0++;
  201.     while(i1>=0 && byte(buf[i1-1])<=' ') i1--;
  202.     if(i0>=i1) return 0;
  203.     char *d=new char[i1-i0+1]; MemTest(d!=0);
  204.     memcpy(d,buf+i0,i1-i0); d[i1-i0]=0;
  205.     return d;
  206.     }
  207. //&>>&0 0 0 1E
  208.  
  209. //&<<&Line *NewLine(char *s,unsigned long LinNmb) {
  210. Line *NewLine(char *s,unsigned long LinNmb) {
  211.   Line *l=new Line(s);
  212.   MemTest(l!=0);
  213.   l->linenumber=LinNmb;
  214.   return l;
  215. }
  216. //&>>&3 0 3 5
  217. //&>>&4 0 4 1A
  218. //&<<&class Fold;
  219. //&<<&Fold::~Fold();
  220. Fold::~Fold(){
  221.   while(pos && pos->next) pos=pos->next;
  222.   while(pos && pos->prev) delete pos->prev;
  223.   delete pos;
  224. }
  225. //&>>&3 0 3 0
  226. //&<<&Fold *NewFold(char *buf,unsigned long LinNmb){
  227. Fold *NewFold(char *buf,unsigned long LinNmb){
  228.   Fold *f=new Fold(buf);
  229.   MemTest(f!=0);
  230.   f->linenumber=LinNmb;
  231.   return f;
  232. }
  233. //&>>&4 0 4 0
  234. //&<<&Line *Fold::Copy(int cln){
  235. Line *Fold::Copy(int cln){
  236.   Line *r;
  237.   Fold *f=NewFold(buf,cln?linenumber:0);
  238.   f->type=type;
  239.   Line *rr=f->pos;
  240.   for(r=pos;r->next;r=r->next) r->Copy()->LinkBefore(rr);
  241.   while(rr->prev) rr=rr->prev;
  242.   f->pos=rr;
  243.   for(r=pos->prev;r;r=r->prev) rr=r->Copy()->LinkBefore(rr);
  244.   f->sx=sx; f->cx=cx; f->sy=sy;
  245.   f->fchg=LINE_NEW;
  246.   return f;
  247.   }
  248. //&>>&4 0 4 0
  249. //&<<&void Fold::Write(FILE *f,int flg);
  250. void Fold::Write(FILE *f,int flg){
  251.   if(flg!=FILE_ASCII && buf) putl(comment,"&<<&",buf,f);
  252.   long i=0;
  253.   Line *r=pos;
  254.   if(pos)
  255.     {
  256.     for(r=pos;r->prev;r=r->prev) i++;
  257.     for(;r->next;r=r->next) r->Write(f,flg);
  258.     }
  259.   if(flg!=FILE_ASCII){
  260.     char temp[64];
  261.     sprintf(temp,"%s&>>&%lX %X %X %X\n",comment,i,sx,sy,cx);
  262.     fputs(temp,f);
  263.   }
  264. }
  265. //&>>&1 0 1 0
  266. //&<<&void Fold::Read(FILE *f,int flg);
  267. void Fold::Read(FILE *f,int flg){
  268.   int l;
  269.   while(fgets(templine,INFTY,f)){
  270.     FileLinesCounter++;
  271.     for(l=0;templine[l]!=0;l++) if(templine[l]=='\t') templine[l]=' ';
  272. //    int l=strlen(templine);
  273.     while(l>0 && byte(templine[l-1])<' ') templine[--l]=0;
  274.     if(flg!=FILE_ASCII){
  275.       if(Editor.IsComment(templine,"$<<$") ||
  276.                       Editor.IsComment(templine,"&<<&")){
  277.         Fold *r=NewFold(templine+lcomment+4);
  278.         r->linenumber=FileLinesCounter;
  279.         r->Read(f,flg);
  280.         r->LinkBefore(pos);
  281.         continue;
  282.       }
  283.       if(Editor.IsComment(templine,"$>>$") ||
  284.                       Editor.IsComment(templine,"&>>&")){
  285.         long i=0;
  286.         char *s=templine+lcomment+4;
  287.         i=strtol(s,&s,16);
  288.         sx=int(strtol(s,&s,16));
  289.         sy=int(strtol(s,&s,16));
  290.         cx=int(strtol(s,&s,16));
  291.         pos->linenumber=FileLinesCounter;
  292.         while(pos->prev) pos=pos->prev;
  293.         while(i && pos->next){ i--; pos=pos->next; }
  294.         return;
  295.       }
  296.     }
  297.     NewLine(templine,FileLinesCounter)->LinkBefore(pos);
  298.   }
  299.   while(pos->prev) pos=pos->prev;
  300. }
  301. //&>>&12 0 12 24
  302. //&<<&int Fold::HasChange();
  303. int Fold::HasChange(){
  304.   Line *x;
  305.   for(x=pos;x->prev;x=x->prev) ;
  306.   while(x){
  307.     if(x->fchg) return 1;
  308.     Fold *f=x->Enter();
  309.     if(f && f->HasChange()) return 1;
  310.     x=x->next;
  311.   }
  312.   return 0;
  313. }
  314. //&>>&4 0 0 4
  315. //&<<&void Fold::Draw();
  316. void Fold::Draw(){
  317.   int d=cx-sx;
  318.   int W=mmm_screen.GetW();
  319.   int H=mmm_screen.GetH()-Editor.ShowStatusLineFlag;
  320.   if(d<0 || d>=W){
  321.     if(d<0) sx=cx;
  322.     else sx=cx-W+1;
  323.     d=cx-sx;
  324.     Redr();
  325.   }
  326.   if(sy<lHead){ sy=lHead; Redr(); }
  327.   if(sy>=H){ sy=H-1; Redr(); }
  328.   if(Editor.ShowStatusLineFlag) DrawStatusLine();
  329.   mmm_screen.ClrCursor();
  330.   if(mmm_screen.Need()){
  331.     Line *r; int l;
  332.     switch(mmm_screen.Need()){
  333. //&<<&        case REDRAW_WHOLE_SCREEN:
  334.         case REDRAW_WHOLE_SCREEN:
  335.             if(sx<0) sx=0;
  336.             l=sy;
  337.             for(r=pos;l>lHead && r->prev;r=r->prev) l--;
  338.             if(l>lHead){ sy-=l-lHead; l=lHead; }
  339.             for(;l<H && r;r=r->next,l++){
  340.               if(r->next){
  341.                 DrawLine(r->Buf(sx),l,r->GetTextAttr(),r->lbuf );
  342.               }else{
  343.                 DrawLine(GetEnd(),l,GetTextAttr(), W );
  344.                 }
  345.               }
  346.             while(l<H) DrawLine("",l++,Editor.TextAttr, 0 );
  347.             SetTitle(getcurdir(0),Editor.CurrentFileName);
  348.             break;
  349. //&>>&D 0 D 18
  350. //&<<&        case REDRAW_CURRENT_LINE:
  351.         case REDRAW_CURRENT_LINE:
  352.             if(sx<0) sx=0;
  353.             if(pos && pos->Buf(sx)){
  354.                 DrawLine(pos->Buf(sx),sy,pos->GetTextAttr(),pos->lbuf );
  355.                 }
  356.             break;
  357. //&>>&4 0 4 0
  358.         }
  359.     mmm_screen.Need()=0;
  360.     }
  361.   mmm_screen.SetCursor(d,sy,pos->next ? pos->GetCurAttr() : GetCurAttr());
  362. }
  363. //&>>&16 0 15 C
  364. //&<<&void Fold::DrawStatusLine();
  365. void Fold::DrawStatusLine(){
  366.    static char StatusLineText[StatusLineLength];
  367.    int W=mmm_screen.GetW();
  368.    int H=mmm_screen.GetH()-Editor.ShowStatusLineFlag;
  369.    static char*SSTR[4]={"SI","SS"};
  370.    char *CD=getcurdir(0);
  371.    sprintf(StatusLineText,                   // ?Would it be better to draw without PRINTF??????
  372.            "%4ld,%-2d %02X  %s %s %s %c%c%c%c  %c %16s %d %d %d %-20s",
  373.            cur->pos->linenumber,cur->cx+1,   // current position
  374.            byte(cur->GetCh()),               // current symbol hex ASCII code
  375.            SSTR[Editor.SearchMode],          // search mode
  376.            (Editor.InsFlag==1)?"ins":"ovr",  // insert or overwrite
  377.            (Editor.IndFlag==1)?"AI":"..",    // autoindent or not
  378.            (mmm_f_Shift)?'s':'.',            // Shift pressed | locked
  379.            (mmm_f_Alt)?'a':'.',              // ALT pressed | locked
  380.            (mmm_f_Ctrl)?'c':'.',             // CTRL pressed
  381.            (mmm_f_Caps)?'C':'.',             // CAPS pressed
  382.            (mmm_f_FixAlt^mmm_f_Alt ? acode : mcode)[16*2+(mmm_f_FixShift^mmm_f_Shift)],  //keyboard layout
  383.            Editor.CurrentFileName ,
  384.            Editor.CurrentDepth,
  385.            Editor.NumberOfPages,
  386.            MarkedBlockLength,
  387.            CD
  388.         );
  389.    DrawLine(StatusLineText, H , Editor.StatusLineAttr , W );
  390.    }
  391. //&>>&11 0 11 18
  392. //&>>&7 0 7 4
  393. //&<<&class File;
  394. //&<<&int WildCard(char *n);
  395. int WildCard(char *n){
  396.   while(*n){ if(*n=='?' || *n=='*') return 1; n++; }
  397.   return 0;
  398. }
  399. //&>>&0 0 0 11
  400. //&<<&Fold *File::Exit();
  401. Fold *File::Exit(){
  402.   Fold *ret=top;
  403.   if(flg!=FILE_LIST && HasChange()){
  404.     SaveSetDrive(CurDev);
  405.     SaveChDir(CurDir);
  406.     delete CurDir;
  407.     FILE *f=fopen(buf,"w");
  408.     if(f==0){
  409.         Beep();
  410.         if(buf[0]!='_')buf[0]='_';
  411.         else buf[0]='a';
  412.         f=fopen(buf,"w");
  413.         }
  414.     if(f){
  415.       char *_buf=buf; buf=0;
  416.       Editor.SetComment(_buf);
  417.       Write(f,flg);
  418.       fclose(f);
  419.       buf=_buf;
  420.     }
  421.   }
  422.   delete this;
  423.   return ret;
  424. }
  425. //&>>&0 0 0 0
  426. //&<<&char *File::FileName();
  427. char *File::FileName(){
  428.   char *x=new char[5+strlen(CurDir)+1+strlen(buf)+1]; MemTest(x!=0);
  429.   char *xx=x;
  430.   if(flg!=FILE_FOLD){
  431.     *xx++='-';
  432.     *xx++=flg==FILE_LIST ? 'l' : 'a';
  433.     *xx++=' ';
  434.   }
  435.   *xx++='@'+CurDev;
  436.   *xx++=':';
  437.   strcpy(xx,CurDir); if(xx[strlen(xx)-1]!='\\') strcat(xx,"\\"); strcat(xx,buf);
  438.   return x;
  439. }
  440. //&>>&2 0 2 6
  441. //&<<&void  GetCurrentFileNameAndDepth();
  442. void GetCurrentFileNameAndDepth(){
  443.   Editor.CurrentDepth=0;
  444.   Fold *s;
  445.   s=cur;
  446.   while(!s->IsFile()){
  447.     s=s->Exit();
  448.     if(!s){
  449.         if(Editor.IsInSearchFold)Editor.CurrentFileName="*SEARCH*";
  450.         else Editor.CurrentFileName="*TEMP*";
  451.         return;}
  452.     Editor.CurrentDepth++;
  453.   }
  454. //  unsigned int ndrv;
  455.   if(s->CurDevNum()){ SaveSetDrive(s->CurDevNum()); }
  456.   char *uuu=s->CurDirName();
  457.   SaveChDir(uuu);
  458.   delete uuu;
  459.   Editor.CurrentFileName=s->buf;
  460. }
  461. //&>>&E 0 E 6
  462. //&>>&1 0 1 15
  463. //&<<&class MarkedLine;
  464. //&<<&void Fold::MarkLine();
  465. void Fold::MarkLine(){
  466.     MarkedLine *f;
  467.     if(pos->marked)
  468.         {
  469.         for(f=MarkedBlock; f->Prev() && f->ref!=pos; f=f->Prev());
  470.         if( f->ref==pos) f->ConnectUnMark();
  471.         else Beep();
  472.         }
  473.     else
  474.         {
  475.         if(MarkedBlock->Next())  f=MarkedBlock->Next();   // Move line to Onmmm_Screen lines
  476.         else  f=new MarkedLine(0);         // add one more line to list
  477.         f->ConnectMark(pos);
  478.         }
  479.     Redr();
  480. }
  481. //&>>&A 1 A 50
  482. //&<<&void MarkedLine::ConnectMark(Line *cpos){
  483. void MarkedLine::ConnectMark(Line *cpos){
  484. if(!cpos->next)return;
  485. ref=cpos;
  486. ref->marked=1;
  487. UnLink();
  488. LinkBefore(MarkedBlock);
  489. }
  490. //&>>&0 0 0 1D
  491. //&<<&void MarkedLine::ConnectUnMark(){
  492. void MarkedLine::ConnectUnMark(){
  493. UnLink();
  494. ref->marked=0;
  495. next=MarkedBlock->Next();
  496. MarkedBlock->next=this;
  497. prev=MarkedBlock;
  498. pcb=0;
  499. }
  500. //&>>&0 0 0 0
  501. //&<<&void MarkedLine::AddCcb(char c);
  502. void MarkedLine::AddCcb(char c){
  503.   Realloc(pcb+1);
  504.   buf[pcb++]=(c ? c : ' ');
  505.   qcb=pcb;
  506. }
  507. //&>>&0 0 0 1C
  508. //&<<&void FirstMarked();
  509. void FirstMarked(){
  510.     MarkedLine *f=MarkedBlock;
  511.     if(!f->Prev()) {Beep(); return;}
  512.     while(f->Prev()) f=f->Prev();
  513.     cur->pos=f->ref;
  514.     Redr();
  515. }
  516. //&>>&3 0 3 19
  517. //&<<&void LastMarked();
  518. void LastMarked(){
  519.     MarkedLine *f=MarkedBlock;
  520.     if(!f->Prev()) {Beep(); return;}
  521.     f=f->Prev();
  522.     cur->pos=f->ref;
  523.     Redr();
  524. }
  525. //&>>&3 0 3 D
  526. //&<<&void NextMarked();
  527. void NextMarked(){
  528.     if(!cur->pos->marked){ FirstMarked(); return; }
  529.  
  530.     MarkedLine *f=MarkedBlock;
  531.     if(!f->Prev()){Beep(); return; }
  532.  
  533.     while( f->ref!=cur->pos && f->Prev() )
  534.         f=f->Prev();
  535.  
  536.     if( f->ref==cur->pos && f->Next()!=MarkedBlock && f->Next() ) cur->pos=f->Next()->ref;
  537.     Redr();
  538. }
  539. //&>>&4 0 4 F
  540. //&<<&void PrevMarked();
  541. void PrevMarked(){
  542.     if(!cur->pos->marked){ LastMarked(); return; }
  543.     MarkedLine *f=MarkedBlock;
  544.     if(!f->Prev()) {Beep(); return;}
  545.     for(f=MarkedBlock; f->Prev() && f->ref!=cur->pos; f=f->Prev());
  546.     if( f->ref==cur->pos && f->Prev() ) cur->pos=f->Prev()->ref;
  547.     Redr();
  548. }
  549. //&>>&3 0 3 0
  550. //&<<&void SaveMarkedBlock();
  551. void SaveMarkedBlock(){
  552. MarkedLine *f;
  553. MarkedBlockLength=0;
  554. while(MarkedBlock->Next()) delete MarkedBlock->Next(); // delete the end of buffer
  555. while(MarkedBlock->Prev())
  556.     {
  557.     f=MarkedBlock->Prev();
  558.     f->ConnectUnMark();
  559.     MarkedBlockLength++;
  560.     }
  561. Redr();
  562. }
  563. //&>>&3 0 3 1
  564. //&<<&void RestMarkedBlock();
  565. void RestMarkedBlock(){
  566. MarkedLine *f;
  567. Line *cpos=cur->pos;
  568. while(MarkedBlock->Next() && cpos->next && MarkedBlockLength>0)
  569.     {
  570.     f=MarkedBlock->Next();
  571.     f->ConnectMark(cpos);
  572.     cpos=cpos->next;
  573.     MarkedBlockLength--;
  574.     }
  575. Redr();
  576. }
  577. //&>>&0 0 0 0
  578. //&>>&0 0 0 D
  579. //&<<&class Chain     /// Knows about 'cur' and 'Fold::Exit()' func.
  580. //&<<&Chain *Chain::LinkBefore(Chain *f);
  581. Chain *Chain::LinkBefore(Chain *f){         // 'this' is unlinked
  582.   Editor.NumberOfPages++;
  583.   prev=f->prev; next=f;
  584.   if(prev) prev->next=this;
  585.   f->prev=this;
  586.   return this;
  587.   }
  588. //&>>&7 0 7 0
  589. //&<<&Chain *Chain::PageNext();          /// modify CUR
  590. Chain *Chain::PageNext(){
  591.   if(MarkedBlock->Prev()) SaveMarkedBlock();
  592.   entry=cur;
  593.   MemTest(next!=0);
  594.   cur=next->entry;
  595.   return next;
  596.   }
  597. //&>>&1 0 1 0
  598. //&<<&Chain *Chain::PagePrev();          /// modify CUR
  599. Chain *Chain::PagePrev(){
  600.   if(MarkedBlock->Prev()) SaveMarkedBlock();
  601.   entry=cur;
  602.   MemTest(prev!=0);
  603.   cur=prev->entry;
  604.   return prev;
  605.   }
  606. //&>>&1 0 1 0
  607. //&<<&void   Chain::PageUnlink();
  608. void   Chain::PageUnlink(){
  609.   while(entry) entry->Exit();
  610.   if(next==prev) {    /// there is only one page left
  611.       remove(MFileName("__mmm__.mmm"));
  612.       exit(0);
  613.       }
  614.   next->prev=prev;
  615.   prev->next=next;
  616.   Editor.NumberOfPages--;
  617.   }
  618. //&>>&1 0 1 0
  619. //&>>&2 0 2 C
  620.  
  621. //&<<&void View();
  622. void View(){
  623.   if(cur==0) return;
  624.   cur->Draw();
  625. }
  626. //&>>&4 0 4 9
  627. //&<<&Fold/File Movement
  628. //&<<&void _EXIT(int n);
  629. void _EXIT(int n){
  630.     if(MarkedBlock->Prev()) SaveMarkedBlock();
  631.     Fold *f;
  632.     if(!cur->IsFile() && cur->top) cur->Exit()->pos=cur;
  633.     do{
  634.       f=cur->Exit();
  635.       if(!f){
  636.             if(CurrentPage==ConstantPage) {Beep(); break;}
  637.             if(Editor.IsInSearchFold) {SwitchIntoSearchPage(); break;}
  638.             Chain *pp=CurrentPage;
  639.             CurrentPage=CurrentPage->PageNext();
  640.             pp->entry=0; pp->PageUnlink(); delete pp;
  641.             break;
  642.             }
  643.       cur=f;
  644.     }while(n);
  645.     GetCurrentFileNameAndDepth();
  646.     Redr();
  647. }
  648. //&>>&5 0 5 0
  649. //&<<&int _EDIT_ScriptFile(char *s,int &nx,int &fx);
  650. //&<<&char *get_next_word(char *&str);
  651. char *get_next_word(char *&str){
  652.     char *ccur,*rv;
  653.     while(*str==' ')str++;
  654.     if(*str==0 || *str==0x0d || *str==0x0a)return 0;
  655.     ccur=str;
  656.     while(*str!=' ' && *str!=0 && *str!=0x0d && *str!=0x0a)str++;
  657.     rv=new char[str-ccur+1];
  658.     int i=0;
  659.     while(ccur<str) *(rv+i++)=*(ccur++);
  660.     *(rv+i)=0;
  661.     return rv;
  662.     }
  663. //&>>&0 0 0 F
  664. int _EDIT_ScriptFile(char *s,int &nx,int &fx){  // edit file
  665. FILE *fptr=fopen(s+1,"r");
  666. if(fptr==0)return 0;
  667. char *strin=new char[0x100]; MemTest(strin!=0);
  668. char *word,*scur;
  669. int rv=0,f_page;
  670. while(fgets(strin,0xff,fptr)>0){
  671.   f_page=0; /// if the page was added (for current line)
  672.   scur=strin;
  673.   while(word=get_next_word(scur)){
  674.       Beep();
  675.       if(f_page)  { rv|=_EDIT(word,nx,fx,0); }
  676.       else   rv|=(f_page=_EDIT(word,nx,fx,1));
  677.       delete word;
  678.       }
  679.   }
  680. fclose(fptr);
  681. delete strin;
  682. return rv;
  683. }
  684. //&>>&C 0 C 0
  685. //&<<&int _EDIT(char *s,int &nx,int &fx,int IsNewPage);
  686. int _EDIT(char *s,int &nx,int &fx,int IsNewPage){  // edit file
  687.   if(s[0]=='@') return  _EDIT_ScriptFile( s, nx, fx);
  688. //&<<&  if(s[0]=='-'){ .... exit }
  689.   if(s[0]=='-'){
  690.     char c=s[1];
  691.     switch(c){
  692.       case 'a': case 'A': fx=FILE_ASCII; break;
  693.       case 'l': case 'L': fx=FILE_LIST; break;
  694.       default:
  695.         if(c>'0' && c<='9') nx=int(strtol(s+1,0,10));
  696.     }
  697.     return 0;
  698.   }
  699. //&>>&3 0 3 22
  700.   File *fil=new File(s,fx);
  701.   if(IsNewPage)
  702. //&<<&    Inserting new page
  703.     {
  704.     CurrentPage->entry=cur;
  705.     Chain *NewNode=new Chain(fil);
  706.     CurrentPage=NewNode->LinkBefore(CurrentPage);
  707.     fil->top=0;
  708.     }
  709. //&>>&0 0 0 10
  710.   else fil->top=cur;
  711.   cur=fil;
  712.   while(--nx){
  713.     Fold *f=cur->pos->Enter();
  714.     if(f==0) break;
  715.     f->top=cur; cur=f;
  716.   }
  717.   Redr();
  718.   nx=1; fx=FILE_FOLD;
  719.   return 1;
  720. }
  721. //&>>&11 0 11 5
  722. //&<<&void Fold::FDown(int IsNewPage);
  723. void Fold::FDown(int IsNewPage){
  724.   if(MarkedBlock->Prev()) SaveMarkedBlock();
  725.   Fold *f=pos->Enter();
  726.   if(f){
  727.     f->top=cur; cur=f;
  728.   }else{
  729.     int tcx=cx;
  730.     int fx=FILE_FOLD,fn=1;
  731.     int k=0;
  732.     char *x;
  733.  
  734.     while((x=pos->GetFileName(cx))!=0){
  735.       k=_EDIT(x,fn,fx,IsNewPage);
  736.       delete x;
  737.       if(k) break;
  738.       while(pos->buf[cx++]>' ');
  739.       while(pos->buf[cx++]==' ');
  740.       }
  741.  
  742.     cx=tcx;
  743.     if(k==0) _EDIT("*.*",fx,fn,IsNewPage);
  744.   }
  745.   GetCurrentFileNameAndDepth();
  746.   Redr();
  747. }
  748. //&>>&19 0 19 3
  749. //&<<&void PerformExitingFromFiles(FILE *filelist){
  750. void PerformExitingFromFiles(FILE *filelist){
  751.     char *s, *u;
  752.     int n=1;     // depth counter
  753.  
  754.     s=new char[2]; s[0]='\n'; s[1]=0;
  755.     Fold *curf=cur;
  756.     while(cur){
  757.         u=cur->FileName();
  758.         if(u==0) n++;   // Not in a File, but in Fold
  759. //&<<&        else{           // Print fileinfo to "filelist" (File top reached)
  760.         else{           // Print fileinfo to "filelist" (File top reached)
  761.             cur->pos->fchg|=LINE_OTHER;
  762.             char *ss=new char[strlen(s)+strlen(u)+10]; MemTest(ss!=0);
  763.             sprintf(ss," -%d %s%s",n,u,s);
  764.             delete s; delete u; n=1;
  765.             s=ss;
  766.             }
  767. //&>>&0 0 0 A
  768.         curf=cur->Exit();
  769.         if(curf) cur=curf;  // only exit one level up
  770.         else{               // Sittin' on the top of the Page
  771. //&<<&            #ifdef _ENABLE_LOGGING_
  772.             #ifdef _ENABLE_LOGGING_
  773.                 DoLog("    Top of the Page reached{ \n");
  774.             #endif
  775. //&>>&1 0 1 10
  776.             n=1;
  777.             if(Editor.IsInSearchFold) {SwitchIntoSearchPage(); continue;}
  778. //&<<&            if(CurrentPage==ConstantPage){ NextPage(); continue; }
  779.         if(CurrentPage==ConstantPage && ConstantPage->next!=ConstantPage )
  780.             {
  781.             CurrentPage=CurrentPage->PageNext();
  782.             GetCurrentFileNameAndDepth();
  783.             continue;
  784.             }
  785. //&>>&0 0 0 0
  786.             fputs(s,filelist); delete s; s=0;
  787.             if(CurrentPage->next == CurrentPage->prev)break;
  788.             Chain *pp=CurrentPage;
  789.             CurrentPage=CurrentPage->PagePrev();
  790. //&<<&            #ifdef _ENABLE_LOGGING_
  791.             #ifdef _ENABLE_LOGGING_
  792.                 DoLog("        pp->entry=0; pp->PageUnlink(); delete pp;{ \n");
  793.             #endif
  794. //&>>&1 0 1 10
  795.             pp->entry=0; pp->PageUnlink(); delete pp;
  796. //&<<&            #ifdef _ENABLE_LOGGING_
  797.             #ifdef _ENABLE_LOGGING_
  798.                 DoLog("            }\n");
  799.             #endif
  800. //&>>&1 0 1 10
  801.             GetCurrentFileNameAndDepth();
  802.             s=new char[2]; s[0]='\n'; s[1]=0;
  803. //&<<&            #ifdef _ENABLE_LOGGING_
  804.             #ifdef _ENABLE_LOGGING_
  805.                 DoLog("        }\n");
  806.             #endif
  807. //&>>&1 0 1 10
  808.             }
  809.         }
  810.     if(s!=0) delete s;
  811.     }
  812. //&>>&1A 0 19 21
  813. //&>>&4 0 4 16
  814. //&<<&Copying of characters
  815. Line mmm_CharClipboard("");          //character clipboard
  816. int pmmm_CharClipboard=0,qmmm_CharClipboard=0;
  817.  
  818. //&<<&void AddCcb(char c){
  819. void AddCcb(char c){
  820.   mmm_CharClipboard.Realloc(pmmm_CharClipboard+1);
  821.   mmm_CharClipboard.buf[pmmm_CharClipboard++]=(c ? c : ' ');
  822.   qmmm_CharClipboard=pmmm_CharClipboard;
  823. }
  824. //&>>&3 0 3 27
  825. //&<<&void Fold::MoveCh(int f){
  826. void Fold::MoveCh(int f){
  827.   if(f) DelCh(); else cx++;
  828. }
  829. //&>>&0 0 0 5
  830. void CClear(){ pmmm_CharClipboard=qmmm_CharClipboard=0; }
  831. //&<<&void Fold::CCopy(int f){
  832. void Fold::CCopy(int f){
  833. if(!pos->marked) AddCcb(GetCh());
  834. else{
  835.   MarkedLine *f=MarkedBlock;
  836.   while(f->Prev()){
  837.     f=f->Prev();
  838.     f->AddCcb(f->GetCh());
  839.   }
  840. }
  841. MoveCh(f);
  842. }
  843. //&>>&0 0 0 B
  844. //&<<&void Fold::CRest(){
  845. void Fold::CRest(){
  846. if(!pos->marked) {
  847.   for(pmmm_CharClipboard=0;pmmm_CharClipboard<qmmm_CharClipboard;pmmm_CharClipboard++)
  848.       Ascii(mmm_CharClipboard.buf[pmmm_CharClipboard]);
  849.   pmmm_CharClipboard=0;
  850. }else{
  851.   MarkedLine *f=MarkedBlock;
  852.   int scx;
  853.   while(f->Prev()){
  854.     f=f->Prev();
  855.     scx=cx;
  856.     for(f->pcb=0;f->pcb<f->qcb;f->pcb++)
  857.         {
  858.         if(Editor.InsFlag) f->ref->InsChar(cx);
  859.         f->ref->SetChar(cx,f->buf[f->pcb]);
  860.         cx++;
  861.     }
  862.     f->pcb=0;
  863.     cx=scx;
  864.   }
  865. }}
  866. //&>>&B 0 B 0
  867. //&<<&char Fold::GetCh(){
  868. char Fold::GetCh(){
  869.   return cx>=pos->lbuf ? 0 : pos->buf[cx];
  870. }
  871. //&>>&0 0 0 0
  872. //&<<&void Fold::WCopy(int f){
  873. void Fold::WCopy(int f){
  874.   if(pos->marked) return;
  875.   char c;
  876.   while(byte(c=GetCh())>' '){ AddCcb(c); MoveCh(f); }
  877.   while(GetCh()==' ') MoveCh(f);
  878.   AddCcb(' ');
  879. }
  880. //&>>&0 0 0 B
  881. //&<<&void Fold::TCopy(int f){
  882. void Fold::TCopy(int f){
  883.   if(pos->marked) return;
  884.   char c;
  885.   while((c=GetCh())!=0){ AddCcb(c); MoveCh(f); }
  886. }
  887. //&>>&0 0 0 B
  888. //&>>&3 0 3 1
  889. //&<<&Copying of lines
  890. void LCheck(){
  891.   if(mmm_LineClipboard==0) mmm_LineClipboard=NewLine(0);
  892.   while(mmm_LineClipboard->next){
  893.     mmm_LineClipboard=mmm_LineClipboard->next;
  894.     delete mmm_LineClipboard->prev;
  895.   }
  896. }
  897.  
  898. void LClear(){
  899.   LCheck();
  900.   while(mmm_LineClipboard->prev) delete mmm_LineClipboard->prev;
  901. }
  902.  
  903. void Fold::LSave(int f){
  904.   if(pos->marked)return;
  905.   LCheck();
  906.   while(pos->next){
  907.     pos->Copy()->LinkBefore(mmm_LineClipboard);
  908.     pos=pos->next; sy++;
  909.     if(f==0) break;
  910.   }
  911. }
  912.  
  913. void Fold::LMove(int f){
  914.   if(pos->marked)return;
  915.   LCheck();
  916.   while(pos->next){
  917.     if((pos->fchg&LINE_OTHER) || !(pos->fchg&LINE_NEW)) pos->next->fchg|=LINE_OTHER;
  918.     Line *p=pos;
  919.     pos=pos->next;
  920.     p->UnLink();
  921.     p->LinkBefore(mmm_LineClipboard);
  922.     if(f==0) break;
  923.   }
  924.   Redr();
  925. }
  926.  
  927. void Fold::LRest(){
  928.   if(mmm_LineClipboard){
  929.     while(mmm_LineClipboard->next) mmm_LineClipboard=mmm_LineClipboard->next;
  930.     while(mmm_LineClipboard->prev){
  931.       mmm_LineClipboard=mmm_LineClipboard->prev; pos=mmm_LineClipboard->Copy()->LinkBefore(pos);
  932.     }
  933.     Redr();
  934.   }
  935. }
  936. //&>>&2E 0 1A 0
  937. //&<<&Line Movements
  938. void Fold::TRight(){
  939.   for(cx=pos->lbuf;--cx>=0 && byte(pos->buf[cx])<=' ';) ;
  940.   cx++;
  941. }
  942.  
  943. void Fold::BWord(){
  944.   if(cx>=pos->lbuf || byte(pos->buf[cx])<=' ') return;
  945.   while(cx>=0 && byte(pos->buf[cx])>' ') cx--;
  946.   cx++;
  947. }
  948. //&>>&0 0 0 0
  949. //&<<&InterLine Movements
  950. void Fold::Up(int DoMarkLine){
  951.   if(pos->prev){
  952.     if(DoMarkLine)MarkLine();
  953.     pos=pos->prev; sy--;
  954.     }
  955. }
  956. void Fold::Down(int DoMarkLine){
  957.   if(pos->next){
  958.     if(DoMarkLine)MarkLine();
  959.     pos=pos->next; sy++;
  960.     }
  961. }
  962. void Fold::TUp(int DoMarkLine){
  963.   while(pos->prev){
  964.     if(DoMarkLine)MarkLine();
  965.     pos=pos->prev; sy--;
  966.     }
  967. }
  968. void Fold::TDown(int DoMarkLine){
  969.   while(pos->next){
  970.     if(DoMarkLine)MarkLine();
  971.     pos=pos->next; sy++;
  972.     }
  973. }
  974. void Fold::PUp(int DoMarkLine){
  975.   int i;
  976.   for(i=mmm_screen.GetH()-lHead;--i>1 && pos->prev;){
  977.     if(DoMarkLine)MarkLine();
  978.     pos=pos->prev;
  979.     }
  980.   Redr();
  981. }
  982.  
  983. void Fold::PDown(int DoMarkLine){
  984.   int i;
  985.   for(i=mmm_screen.GetH()-lHead;--i>1 && pos->next;){
  986.     if(DoMarkLine)MarkLine();
  987.     pos=pos->next;
  988.     }
  989.   Redr();
  990. }
  991.  
  992. int lspc(Line *p){
  993.   int i;
  994.   if(!(Editor.IndFlag&1)) return -1;
  995.   char *s=p->buf; if(s==0) return -1;
  996.   for(i=0;s[i]==' ';i++) ;
  997.   if(s[i]==0) return -1;
  998.   return i;
  999. }
  1000.  
  1001. void Fold::_Enter(){
  1002.     int i=lspc(pos);
  1003.     if(pos->next){ pos=pos->next; sy++; }
  1004.     int j=lspc(pos);
  1005.     cx=j<0 ? i : j; if(cx<0) cx=0;
  1006.     return;
  1007. }
  1008. //&>>&20 0 8 0
  1009. //&<<&Line Editing
  1010. //&<<&void Fold::BackSpace()
  1011. void Fold::BackSpace(){
  1012. if(!pos->marked){
  1013.   if(pos->next!=0){
  1014.     if(cx){
  1015.       cx--;
  1016.       if(Editor.InsFlag) pos->DelChar(cx);
  1017.       else pos->SetChar(cx,' ');
  1018.     }
  1019.   }
  1020. }else{
  1021.   MarkedLine *f=MarkedBlock;
  1022.   if(cx){
  1023.     cx--;
  1024.     while(f->Prev()){
  1025.       f=f->Prev();
  1026.       if(Editor.InsFlag) f->ref->DelChar(cx);
  1027.       else f->ref->SetChar(cx,' ');
  1028.     }
  1029.   }
  1030. }}
  1031.  
  1032. //&>>&15 0 15 3
  1033. //&<<&void Fold::Ascii(int code);
  1034. void Fold::Ascii(int code){
  1035. if(!pos->marked){
  1036.   if(pos->next==0) InsLine();
  1037.   if(Editor.InsFlag) pos->InsChar(cx);
  1038.   pos->SetChar(cx,code);
  1039.   cx++;
  1040. }else{
  1041.   MarkedLine *f=MarkedBlock;
  1042.   while(f->Prev()){
  1043.     f=f->Prev();
  1044.     if(Editor.InsFlag) f->ref->InsChar(cx);
  1045.     f->ref->SetChar(cx,code);
  1046.     }
  1047.   cx++;
  1048. }}
  1049. //&>>&2 0 2 6
  1050. //&<<&void Fold::KillEnd();
  1051. void Fold::KillEnd(){
  1052. int i;
  1053. if(!pos->marked){
  1054.   for(i=cx;i<pos->lbuf;i++) pos->buf[i]=0;
  1055.   pos->fchg|=LINE_CHG;
  1056. }else{
  1057.   MarkedLine *f=MarkedBlock;
  1058.   while(f->Prev()){
  1059.     f=f->Prev();
  1060.     for(i=cx;i<f->ref->lbuf;i++) f->ref->buf[i]=0;
  1061.     f->ref->fchg|=LINE_CHG;
  1062.   }
  1063. }
  1064. Redr();
  1065. }
  1066. //&>>&9 0 9 8
  1067. //&<<&void Fold::KillBeg();
  1068. void Fold::KillBeg(){
  1069. int i;
  1070. if(!pos->marked){
  1071.   if(Editor.InsFlag){
  1072.     for(i=0;i+cx<pos->lbuf;i++) pos->buf[i]=pos->buf[i+cx];
  1073.     for(;i<pos->lbuf;i++) pos->buf[i]=0;
  1074.     cx=0;
  1075.   }else{
  1076.     for(i=0;i<cx && pos->buf[i];i++) pos->buf[i]=' ';
  1077.   }
  1078.   pos->fchg|=LINE_CHG;
  1079. }else{
  1080.   MarkedLine *f=MarkedBlock;
  1081.   while(f->Prev()){
  1082.     f=f->Prev();
  1083.     if(Editor.InsFlag){
  1084.       for(i=0;i+cx<f->ref->lbuf;i++) f->ref->buf[i]=f->ref->buf[i+cx];
  1085.       for(;i<f->ref->lbuf;i++) f->ref->buf[i]=0;
  1086.     }else{
  1087.       for(i=0;i<cx && f->ref->buf[i];i++) f->ref->buf[i]=' ';
  1088.     }
  1089.     f->ref->fchg|=LINE_CHG;
  1090.   }
  1091.   if(Editor.InsFlag) cx=0;
  1092. }
  1093. Redr();
  1094. }
  1095. //&>>&13 0 13 A
  1096. //&<<&void Fold::InsCh()
  1097. void Fold::InsCh(){
  1098. if(!pos->marked){
  1099.    if(pos->next) pos->InsChar(cx);}
  1100. else{
  1101.   MarkedLine *f=MarkedBlock;
  1102.   while(f->Prev()){
  1103.     f=f->Prev();
  1104.     f->ref->InsChar(cx);
  1105.   }
  1106. }}
  1107. //&>>&0 0 0 0
  1108. //&<<&void Fold::DelCh()
  1109. void Fold::DelCh(){
  1110. if(!pos->marked){
  1111.    if(pos->next) pos->DelChar(cx);}
  1112. else{
  1113.   MarkedLine *f=MarkedBlock;
  1114.   while(f->Prev()){
  1115.     f=f->Prev();
  1116.     f->ref->DelChar(cx);
  1117.   }
  1118. }}
  1119. //&>>&4 0 0 8
  1120. //&>>&0 0 0 D
  1121. //&<<&void Fold::DelLine();
  1122. void Fold::DelLine(){
  1123.   if(pos->marked)return;
  1124.   if(pos->next){
  1125.     if((pos->fchg&LINE_OTHER) || !(pos->fchg&LINE_NEW)) pos->next->fchg|=LINE_OTHER;
  1126.     pos=pos->next;
  1127.     delete pos->prev;
  1128.     Redr();
  1129.   }
  1130. }
  1131. //&>>&0 0 0 1
  1132.  
  1133. //&>>&17 0 17 E
  1134.