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