home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol270 / sed.inc < prev    next >
Encoding:
Text File  |  1986-05-22  |  18.0 KB  |  725 lines

  1. {  Small editor                              }
  2. {    by K.Nakazato  Ver. 1.00  Feb. 10, 1984 }
  3. {                        1.12  Jun.  2, 1984 }
  4. {                        1.13  Jul. 14, 1984 }
  5. {                        1.14  Dec. 16, 1984 }
  6.  
  7. { const maxtext =$7FFF;                      }
  8. { type  texttype=array [0..maxtext] of char; }
  9.  
  10. procedure sedit(var textbuf:texttype; onmemory:boolean;
  11.                 var position:integer);
  12.  
  13. {*****    machine dependent routine     *****}
  14.  
  15. const
  16.   screen_width =80;
  17.   screen_length=23;
  18.  
  19. { Set VRAM address, here.                    }
  20. {   vramaddr[0]= home position of screen     }
  21. {   vramaddr[1]= left edge of second line    }
  22. {    .......                                 }
  23. { The following is for NEC PC8001, PC8801.   }
  24.  
  25. var vramaddr:array [0..screen_length] of integer;
  26.  
  27. procedure setvramaddr;
  28. var i:byte;
  29. begin
  30.   vramaddr[0]:=$F300;
  31.   for i:=1 to screen_length do vramaddr[i]:=vramaddr[i-1]+$78
  32. end;
  33.  
  34. {***** end of machine dependent routine *****}
  35.  
  36. { constants and main variables }
  37.  
  38. const
  39.     newline   =#$0D; { mark of CR/LF       }
  40.     mark      =#$87; { mark of work        }
  41.     startblock=#$E7; { mark of start block }
  42.     endblock  =#$E4; { mark of end   block }
  43.     swidth  :byte=screen_width;
  44.     slength :byte=screen_length;
  45.     wordset :set of char=['a'..'z','A'..'Z','0'..'9','_'];
  46.     ctrlcode:set of char=[#0,#$A,#$D,#$1A];
  47. type
  48.     linetype=string[30];
  49.     frtype=(nosym,findsym,replacesym);
  50. var
  51.     ptop    :integer;              { stack pointer of top    text   }
  52.     pbotm   :integer;              { stack pointer of bottom text   }
  53.     address :integer;              { address of searched character  }
  54.     buffer  :string[screen_width]; { buffer of current line         }
  55.     numbuf  :byte absolute buffer; { number of characters in buffer }
  56.     insertsw:boolean;              { insert/overwrite switch        }
  57.     outflag :boolean;              { quit flag                      }
  58.     x,y     :byte;                 { cursor position                }
  59.     halflen :byte;                 { half length of screen          }
  60.     fr      :frtype;               { find/replace                   }
  61.     infile  :text;                 { text file control block        }
  62.     filename:linetype;             { main file name                 }
  63.     bkname  :linetype;             { block file name                }
  64.     line    :linetype;             { work string for input          }
  65.     linefrom:linetype;             { string of find / replace(from) }
  66.     lineto  :linetype;             { string of        replace(to)   }
  67.  
  68. { text basic routines }
  69.  
  70. procedure setnumbuf;
  71. begin
  72.   while buffer[numbuf]=' ' do numbuf:=numbuf-1
  73. end;
  74.  
  75. procedure pushtop;
  76. begin
  77.   setnumbuf;
  78.   inline($21/ buffer/ $7E/ $ED/ $5B/ ptop/ $13/ $B7/ $28/ $06/
  79.          $06/ $00/ $4F/ $23/ $ED/ $B0/ $EB/ $36/ $0D/ $23/ $36/
  80.          $0A/ $22/ ptop)
  81. end;
  82.  
  83. procedure poptop;
  84. begin
  85.   inline($2A/ ptop/ $7E/ $B7/ $28/ $1D/ $0E/ $00/ $2B/
  86.          $0C/ $7E/ $B7/ $28/ $04/ $FE/ $0A/ $20/ $F6/
  87.          $22/ ptop/ $0D/ $0D/ $79/ $28/ $09/ $06/ $00/
  88.          $23/ $11/ buffer/ $13/ $ED/ $B0/ $32/ buffer)
  89. end;
  90.  
  91. procedure pushbottom;
  92. begin
  93.   setnumbuf;
  94.   inline($3A/ buffer/ $2A/ pbotm/ $2B/ $36/ $0A/ $2B/ $36/
  95.          $0D/ $B7/ $28/ $0D/ $2B/ $EB/ $06/ $00/ $4F/ $21/
  96.          buffer/ $09/ $ED/ $B8/ $EB/ $23/ $22/ pbotm)
  97. end;
  98.  
  99. procedure popbottom;
  100. begin
  101.   inline($2A/ pbotm/ $0E/ $00/ $11/ buffer/ $13/ $7E/ $FE/ $1A/
  102.          $28/ $0C/ $FE/ $0D/ $28/ $06/ $12/ $13/ $23/ $0C/
  103.          $18/ $F1/ $23/ $23/ $22/ pbotm/ $79/ $32/ buffer)
  104. end;
  105.  
  106. procedure topbottom;
  107. begin
  108.   inline($2A/ ptop/ $23/ $ED/ $5B/ pbotm/ $1A/ $FE/ $1A/
  109.          $28/ $0B/ $FE/ $0D/ $28/ $05/ $77/ $13/ $23/ $18/
  110.          $F2/ $13/ $13/ $ED/ $53/ pbotm/ $36/ $0D/
  111.          $23/ $36/ $0A/ $22/ ptop)
  112. end;
  113.  
  114. procedure bottomtop;
  115. begin
  116.   inline($2A/ pbotm/ $2B/ $36/ $0A/ $2B/ $36/ $0D/ $2B/ $ED/
  117.          $5B/ ptop/ $1A/ $B7/ $28/ $0F/ $1B/ $1B/ $1A/ $B7/
  118.          $28/ $09/ $FE/ $0A/ $28/ $05/ $77/ $1B/ $2B/
  119.          $18/ $F3/ $ED/ $53/ ptop/ $23/ $22/ pbotm)
  120. end;
  121.  
  122. procedure textbottom;
  123. begin
  124.   pushtop;
  125.   while mem[pbotm]<>$1A do topbottom;
  126.   repeat
  127.     poptop
  128.   until (numbuf>0) or (mem[ptop]=0)
  129. end;
  130.  
  131. procedure texttop;
  132. begin
  133.   pushbottom;
  134.   while mem[ptop]<>0 do bottomtop;
  135.   repeat
  136.     popbottom
  137.   until (numbuf>0) or (mem[pbotm]=$1A)
  138. end;
  139.  
  140. function getline(yto,yfrom:byte):byte;
  141. var i:byte;
  142. begin
  143.   if yto>yfrom then
  144.     begin
  145.       pushtop;
  146.       for i:=yfrom+1 to yto-1 do topbottom;
  147.       popbottom
  148.     end
  149.   else if yto<yfrom then
  150.     begin
  151.       pushbottom;
  152.       for i:=yfrom-1 downto yto+1 do bottomtop;
  153.       poptop
  154.     end;
  155.   getline:=yto
  156. end;
  157.  
  158. { screen basic routines }
  159.  
  160. function tline(yto,yfrom:byte):byte; { transfer line }
  161. var vram,vram1:integer;
  162. begin
  163.   vram1:=vramaddr[yfrom]; vram:=vramaddr[yto];
  164.   inline($2A/ vram1/ $ED/ $5B/ vram/
  165.          $3A/ swidth/ $4F/ $06/ $00/ $ED/ $B0);
  166.   tline:=yfrom
  167. end;
  168.  
  169. procedure sline(y:byte); { erase line }
  170. var vram:integer;
  171. begin
  172.   vram:=vramaddr[y];
  173.   inline($2A/ vram/ $3A/ swidth/ $47/
  174.          $3E/ $20/ $77/ $23/ $10/ $FC)
  175. end;
  176.  
  177. procedure pline(y:byte); { print line }
  178. var vram:integer;
  179. begin
  180.   vram:=vramaddr[y];
  181.   inline($21/ buffer/ $7E/ $23/ $ED/ $5B/ vram/ $B7/
  182.          $28/ $05/ $06/ $00/ $4F/ $ED/ $B0/ $47/ $3A/
  183.          swidth/ $90/ $28/ $0B/ $38/ $09/ $47/ $3E/
  184.          $20/ $12/ $77/ $13/ $23/ $10/ $FA)
  185. end;
  186.  
  187. procedure rolldown(y1,y2:byte);
  188. begin
  189.   while y1<y2 do y2:=tline(y2,y2-1)
  190. end;
  191.  
  192. procedure rollup(y1,y2:byte);
  193. begin
  194.   while y1<y2 do y1:=tline(y1,y1+1)
  195. end;
  196.  
  197. procedure newscreen;
  198. var n:byte;
  199. begin
  200.   pline(getline(1,y));
  201.   for n:=2 to slength do
  202.     begin pushtop; popbottom; pline(n) end;
  203.   y:=getline(y,slength)
  204. end;
  205.  
  206. { primitives }
  207.  
  208. procedure dispinsert;
  209. begin
  210.   gotoxy(screen_width-10,1);
  211.   if insertsw then write('insert   ') else write('overwrite')
  212. end;
  213.  
  214. procedure newcommandline;
  215. begin
  216.   sline(0); dispinsert
  217. end;
  218.  
  219. procedure readline(prompt:linetype; var line:linetype);
  220. begin
  221.   sline(0); gotoxy(1,1);
  222.   write(prompt,' ? '); readln(line);
  223.   newcommandline
  224. end;
  225.  
  226. procedure putmem(var i:byte; var k:integer; c:char);
  227. begin
  228.   if (pbotm-k)>250 then
  229.     begin
  230.       if (c=newline) or (i>=swidth) then
  231.         begin mem[k]:=$D; mem[k+1]:=$A; k:=k+2; i:=0 end;
  232.       if not (c in ctrlcode) then
  233.         begin mem[k]:=ord(c); k:=k+1; i:=i+1 end
  234.     end
  235.   else begin mem[k-2]:=$D; mem[k-1]:=$A end
  236. end;
  237.  
  238. { elementary routines }
  239.  
  240. procedure replaceline(xfrom,xlength:byte; line:linetype);
  241. var i,n:byte; k:integer;
  242. begin
  243.   setnumbuf; k:=ptop+1; n:=0;
  244.   for i:=1 to xfrom-1 do putmem(n,k,buffer[i]);
  245.   for i:=1 to length(line) do putmem(n,k,line[i]);
  246.   for i:=xfrom+xlength to numbuf do putmem(n,k,buffer[i]);
  247.   putmem(n,k,newline); ptop:=k-1; poptop
  248. end;
  249.  
  250. procedure connect;
  251. var i,n:byte; k:integer;
  252. begin
  253.   pushtop; n:=numbuf; k:=ptop-1; popbottom;
  254.   for i:=1 to numbuf do putmem(n,k,buffer[i]);
  255.   putmem(n,k,newline); ptop:=k-1; poptop
  256. end;
  257.  
  258. procedure searchmem(s:byte; c:char);
  259. var len:integer;
  260. begin
  261.   if s=1 then
  262.     begin
  263.       len:=ptop-addr(textbuf[0]);
  264.       if len>0 then
  265.         inline($3A/ c/ $ED/ $4B/ len/ $2A/ ptop/
  266.                $ED/ $B9/ $23/ $22/ address)
  267.     end
  268.   else if s=2 then
  269.     begin
  270.       len:=addr(textbuf[maxtext])-pbotm;
  271.       if len>0 then
  272.         inline($3A/ c/ $ED/ $4B/ len/ $2A/ pbotm/
  273.                $ED/ $B1/ $2B/ $22/ address)
  274.     end
  275. end;
  276.  
  277. procedure erasemem(s:byte; mem1,mem2:integer);
  278. var len:integer;
  279. begin
  280.   if s=1 then
  281.     begin
  282.       len:=ptop-mem2;
  283.       if len>0 then
  284.         inline($ED/ $4B/ len/ $ED/ $5B/ mem1/ $2A/ mem2/
  285.                $23/ $ED/ $B0/ $1B/ $ED/ $53/ ptop)
  286.     end
  287.   else if s=2 then
  288.     begin
  289.       len:=mem1-pbotm;
  290.       if len>0 then
  291.         inline($ED/ $4B/ len/ $ED/ $5B/ mem2/ $2A/ mem1/
  292.                $2B/ $ED/ $B8/ $13/ $ED/ $53/ pbotm)
  293.       else if len=0 then pbotm:=mem2+1
  294.     end
  295. end;
  296.  
  297. procedure search1(c:char; var s:byte; var m:integer);
  298. begin
  299.   s:=2; m:=0;
  300.   while (s>0) and (m=0) do
  301.     begin
  302.       searchmem(s,c);
  303.       if mem[address]=ord(c) then m:=address else s:=s-1
  304.     end
  305. end;
  306.  
  307. { block routines }
  308.  
  309. procedure eraseblock;
  310. var s,t:byte; mem1,mem2:integer;
  311. begin
  312.   pushtop; search1(startblock,s,mem1); search1(endblock,t,mem2);
  313.   if (mem2-mem1)>0 then
  314.     begin
  315.       if (s=t) then erasemem(s,mem1,mem2)
  316.       else if (s=1) and (t=2) then
  317.         begin
  318.           mem[mem1]:=$D; mem[mem1+1]:=$A;
  319.           ptop:=mem1+1; pbotm:=mem2+1; x:=1
  320.         end
  321.     end;
  322.   poptop; newscreen
  323. end;
  324.  
  325. procedure writeblock;
  326. var s,t:byte; mem1,mem2,i:integer;
  327. begin
  328.   pushtop; search1(startblock,s,mem1); search1(endblock,t,mem2);
  329.   if ((mem2-mem1)>0) and (mem1<>0)  then
  330.     begin
  331.       readline('write block name',bkname);
  332.       assign(infile,bkname); rewrite(infile); i:=mem1+1;
  333.       if t>s then
  334.         begin
  335.           while i<>ptop+1 do
  336.             begin write(infile,chr(mem[i])); i:=i+1 end;
  337.           i:=pbotm
  338.         end;
  339.       while i<>mem2 do
  340.         begin write(infile,chr(mem[i])); i:=i+1 end;
  341.       close(infile)
  342.     end;
  343.   poptop
  344. end;
  345.  
  346. procedure readblock;
  347. var c:char; k:integer;
  348. begin
  349.   replaceline(x,0,newline); pushbottom; numbuf:=x-1; k:=ptop-1;
  350.   readline('read block name',bkname);
  351.   assign(infile,bkname); {$I-} reset(infile) {$I+};
  352.   if ioresult=0 then
  353.     begin
  354.       putmem(numbuf,k,startblock);
  355.       while not eof(infile) do
  356.         begin read(infile,c); putmem(numbuf,k,c) end;
  357.       putmem(numbuf,k,endblock)
  358.     end;
  359.   close(infile); putmem(numbuf,k,newline); ptop:=k-1; poptop;
  360.   connect; newscreen
  361. end;
  362.  
  363. procedure cmblock(copy:boolean);
  364. var s,t:byte; k,m,mem1,mem2:integer;
  365. begin
  366.   replaceline(x,0,newline); pushbottom; numbuf:=x-1; k:=ptop-1;
  367.   search1(startblock,s,mem1); search1(endblock,t,mem2); m:=mem1;
  368.   if ((mem2-mem1)>0) and (s=t) then
  369.     while m<>(mem2+1) do
  370.       begin putmem(numbuf,k,chr(mem[m])); m:=m+1 end;
  371.   putmem(numbuf,k,newline); ptop:=k-1;
  372.   if ((mem2-mem1)>0) and (s=t) then
  373.     if copy then
  374.       begin
  375.         if s=1 then
  376.           begin erasemem(s,mem2,mem2); erasemem(s,mem1,mem1) end
  377.         else if s=2 then
  378.           begin erasemem(s,mem1,mem1); erasemem(s,mem2,mem2) end
  379.       end
  380.     else erasemem(s,mem1,mem2);
  381.   poptop; connect; newscreen
  382. end;
  383.  
  384. procedure erasemark;
  385. var s:byte; m:integer;
  386. begin
  387.   pushtop;
  388.   repeat search1(startblock,s,m); erasemem(s,m,m) until s=0;
  389.   repeat search1(endblock  ,s,m); erasemem(s,m,m) until s=0;
  390.   poptop; newscreen
  391. end;
  392.  
  393. { find/replace }
  394.  
  395. function find1:boolean;
  396. var n:integer;
  397. begin
  398.   find1:=false;
  399.   if linefrom<>'' then
  400.   begin
  401.     pushbottom; delete(buffer,1,x); n:=pos(linefrom,buffer); popbottom;
  402.     if n>0 then n:=x+n;
  403.     while (n=0) and (mem[pbotm]<>$1A) do
  404.       begin pushtop; popbottom; n:=pos(linefrom,buffer) end;
  405.     if n>0 then begin x:=n; find1:=true end
  406.            else begin textbottom; x:=numbuf end;
  407.     if x>swidth then x:=swidth;
  408.     y:=halflen; newscreen
  409.   end
  410. end;
  411.  
  412. procedure find;
  413. var junk:boolean;
  414. begin
  415.   readline('find',line);
  416.   if line<>'' then begin
  417.     fr:=findsym; linefrom:=line; junk:=find1 end
  418. end;
  419.  
  420. procedure replace1;
  421. var c:char;
  422. begin
  423.   if find1 then
  424.     begin
  425.       sline(0); gotoxy(1,1);
  426.       write('replace - space -');
  427.       gotoxy(x,y+1); read(kbd,c); newcommandline;
  428.       if c=' ' then
  429.         begin
  430.           replaceline(x,length(linefrom),lineto);
  431.           newscreen
  432.         end
  433.     end
  434. end;
  435.  
  436. procedure replace;
  437. var n:integer;
  438. begin
  439.   readline('replace from',line);
  440.   if line<>'' then begin
  441.     fr:=replacesym; linefrom:=line;
  442.     readline('to',lineto); replace1
  443.   end
  444. end;
  445.  
  446. { elements }
  447.  
  448. function getnextc(c:char):char;
  449. var r:char;
  450. begin
  451.   gotoxy(1,1); write('^',c);
  452.   gotoxy(x,y+1); read(kbd,r); getnextc:=r;
  453.   gotoxy(1,1); write('  ')
  454. end;
  455.  
  456. procedure deletechar;
  457. begin
  458.   delete(buffer,x,1)
  459. end;
  460.  
  461. procedure insertchar(r:char);
  462. begin
  463.   if buffer[numbuf]=' ' then
  464.     begin
  465.       numbuf:=numbuf-1;
  466.       insert(r,buffer,x)
  467.     end
  468.   else write(^G)
  469. end;
  470.  
  471. procedure deleteword;
  472. var i:byte; c:char;
  473. begin
  474.   i:=x; c:=buffer[i];
  475.   if c in wordset then
  476.     while (buffer[i] in wordset) and (i<=numbuf) do i:=i+1
  477.   else if c=' ' then
  478.     while (buffer[i]=c) and (i<=numbuf) do i:=i+1
  479.   else i:=i+1;
  480.   delete(buffer,x,i-x)
  481. end;
  482.  
  483. procedure linedown;
  484. begin
  485.   if y<slength then y:=getline(y+1,y)
  486.   else begin rollup(1,slength); pushtop; popbottom end
  487. end;
  488.  
  489. procedure lineup;
  490. begin
  491.   if y>1 then y:=getline(y-1,y)
  492.   else begin rolldown(1,slength); pushbottom; poptop end
  493. end;
  494.  
  495. procedure screenup;
  496. var i:byte;
  497. begin
  498.   i:=getline(slength,y-1);
  499.   rollup(1,slength); pline(slength);
  500.   if y>1 then y:=y-1;
  501.   y:=getline(y,slength)
  502. end;
  503.  
  504. procedure screendown;
  505. var i:byte;
  506. begin
  507.   i:=getline(1,y+1);
  508.   rolldown(1,slength); pline(1);
  509.   if y<slength then y:=y+1;
  510.   y:=getline(y,1)
  511. end;
  512.  
  513. procedure wordleft;
  514. begin
  515.   x:=x-1;
  516.   repeat
  517.     if x=0 then begin lineup; pline(y); x:=swidth end;
  518.     while not (buffer[x] in wordset) and (x>0) do x:=x-1
  519.   until (x>0) or (mem[ptop]=0);
  520.   while (buffer[x] in wordset) and (x>0) do x:=x-1;
  521.   x:=x+1
  522. end;
  523.  
  524. procedure wordright;
  525. begin
  526.   while (buffer[x] in wordset) and (x<=swidth) do x:=x+1;
  527.   repeat
  528.     if x>swidth then begin linedown; pline(y); x:=1 end;
  529.     while not (buffer[x] in wordset) and (x<=swidth) do x:=x+1
  530.   until (x<=swidth) or (mem[pbotm]=$1A);
  531.   if x>swidth then x:=1
  532. end;
  533.  
  534. procedure connectline;
  535. var s:byte; m:integer;
  536. begin
  537.   buffer[x]:=mark; numbuf:=x;
  538.   while mem[pbotm]=ord(' ') do pbotm:=pbotm+1;
  539.   connect; pushtop; search1(mark,s,m); erasemem(s,m,m); poptop
  540. end;
  541.  
  542. procedure mostleft;
  543. begin
  544.   x:=1;
  545.   while (buffer[x]=' ') and (x<=swidth) do x:=x+1;
  546.   if x>swidth then x:=1
  547. end;
  548.  
  549. procedure mostright;
  550. begin
  551.   setnumbuf;
  552.   if (numbuf=0) or (numbuf>=swidth) then x:=swidth
  553.   else x:=numbuf+1
  554. end;
  555.  
  556. procedure findpos(c:char);
  557. begin
  558.   texttop; textbottom; pushtop; mem[ptop+1]:=$1A;
  559.   searchmem(1,c); position:=address
  560. end;
  561.  
  562. procedure setposition;
  563. begin
  564.   while (ptop-position)>=0 do begin pushbottom; poptop end;
  565.   x:=position-ptop; if x>swidth then x:=swidth
  566. end;
  567.  
  568. procedure gotoc(c:char);
  569. begin
  570.   findpos(c); popbottom; setposition; y:=halflen; newscreen
  571. end;
  572.  
  573. procedure endtext;
  574. var c:char;
  575. begin
  576.   c:=buffer[x]; buffer[x]:=mark; findpos(mark);
  577.   mem[position]:=ord(c)
  578. end;
  579.  
  580. { disk input/output routines }
  581.  
  582. procedure settext(onmemory:boolean);
  583. var c:char; j:byte; i:integer;
  584. begin
  585.   textbuf[0]:=#0; textbuf[maxtext]:=#$1A;
  586.   pbotm:=addr(textbuf[maxtext]);
  587.   i:=addr(textbuf[0])+1;
  588.   if onmemory then begin
  589.     while mem[i]<>$1A do i:=i+1;
  590.     ptop:=i-1; popbottom;
  591.     if ((position-addr(textbuf[0]))>0) and ((ptop-position)>=0)
  592.     then begin setposition; y:=halflen end
  593.     else begin texttop; x:=1; y:=1 end
  594.   end
  595.   else begin
  596.     j:=0;
  597.     write('file name ? '); readln(filename);
  598.     assign(infile,filename); {$I-} reset(infile); {$I+}
  599.     if ioresult<>0 then
  600.       begin  write('*** new file ***'); delay(500) end
  601.     else
  602.       while not eof(infile) do begin read(infile,c); putmem(j,i,c) end;
  603.     close(infile); putmem(j,i,newline);
  604.     ptop:=i-1; poptop; texttop; x:=1; y:=1
  605.   end;
  606.   clrscr; insertsw:=true; dispinsert; newscreen
  607. end;
  608.  
  609. procedure outtext;
  610. var c:char; i:integer;
  611. begin
  612.   if onmemory then outflag:=true
  613.   else begin
  614.     repeat
  615.       sline(0); gotoxy(1,1);
  616.       write('> Save Write Return New Quit ? '); read(trm,c); c:=upcase(c);
  617.       if c='W' then readline('file name',filename);
  618.       if ((c='S') or (c='W')) and (filename<>'') then
  619.         begin
  620.           endtext; assign(infile,filename); rewrite(infile); i:=1;
  621.           while textbuf[i]<>#$1A do
  622.             begin write(infile,textbuf[i]); i:=i+1 end;
  623.           close(infile); popbottom; setposition
  624.         end
  625.     until c in ['N','R','Q'];
  626.     newcommandline;
  627.     if c='Q' then outflag:=true
  628.     else if c='N' then begin gotoxy(1,1); settext(false) end
  629.   end
  630. end;
  631.  
  632. procedure checkbuf;
  633. begin
  634.   if (pbotm-ptop)<255 then
  635.     begin
  636.       gotoxy(1,1); write('Text buffer full !'^G);
  637.       delay(500); outtext
  638.     end
  639. end;
  640.  
  641. {*** main ***}
  642.  
  643. var r:char; i:byte; junk:boolean;
  644. begin
  645.   outflag:=false; fr:=nosym; halflen:=slength div 2+1;
  646.   position:=position+addr(textbuf[0]);
  647.   crtinit; setvramaddr; settext(onmemory);
  648.   repeat
  649.     pline(y); numbuf:=swidth;
  650.     gotoxy(x,y+1); read(kbd,r);
  651.     case r of
  652.       ^G:deletechar;
  653.       ^S,^H:if x>1 then x:=x-1;
  654.       ^V:begin insertsw:=not insertsw; dispinsert end;
  655.       ^I:begin x:=8*((x-1) div 8)+9; if x>swidth then x:=swidth end;
  656.       ^D:if x<swidth then x:=x+1;
  657.       ^T:begin
  658.            setnumbuf;
  659.            if x<=numbuf then deleteword
  660.            else begin connectline; newscreen end
  661.          end;
  662.       ^N:begin replaceline(x,0,newline); pushbottom; poptop; newscreen end;
  663.       ^R:begin i:=getline(1,slength); newscreen end;
  664.       ^C:begin i:=getline(slength,1); newscreen end;
  665.       ^L:if fr=findsym then junk:=find1
  666.          else if fr=replacesym then replace1;
  667.       ^X:linedown;
  668.       ^E:lineup;
  669.       ^M:begin linedown; mostleft end;
  670.       ^B:begin mostleft; pushbottom; numbuf:=0; rolldown(y,slength) end;
  671.       ^Y:begin
  672.            rollup(y,slength); popbottom;
  673.            pline(getline(slength,y)); y:=getline(y,slength)
  674.          end;
  675.       ^A:wordleft;
  676.       ^F:wordright;
  677.       ^Z:screenup;
  678.       ^W:screendown;
  679.       ^P:begin
  680.            r:=getnextc('P');
  681.            if not (r in ctrlcode) then
  682.              begin
  683.               if insertsw then insertchar(r) else buffer[x]:=r;
  684.               if x<swidth then x:=x+1
  685.              end
  686.          end;
  687.       #$7F:if x>1 then begin x:=x-1; deletechar end;
  688.       ^Q:case getnextc('Q') of
  689.            ^Y:numbuf:=x-1;
  690.            ^S:x:=1;
  691.            ^D:mostright;
  692.            ^R:begin x:=1; y:=1; texttop; newscreen end;
  693.            ^C:begin y:=halflen; textbottom; x:=numbuf; newscreen end;
  694.            ^F:find;
  695.            ^A:replace;
  696.            ^B:gotoc(startblock);
  697.            ^K:gotoc(endblock);
  698.            ^E:begin x:=1; y:=getline(1,y) end;
  699.            ^X:begin y:=getline(slength,y); mostright end;
  700.          else
  701.          end;
  702.       ^K:case getnextc('K') of
  703.            ^B:insertchar(startblock);
  704.            ^K:insertchar(endblock);
  705.            ^W:writeblock;
  706.            ^D:outtext;
  707.            ^C:cmblock(true);
  708.            ^V:cmblock(false);
  709.            ^Y:eraseblock;
  710.            ^R:readblock;
  711.            ^X:erasemark;
  712.          else
  713.          end;
  714.     else
  715.       if r>=' ' then begin
  716.         if insertsw then insertchar(r) else buffer[x]:=r;
  717.         if x<swidth then x:=x+1
  718.       end
  719.     end;
  720.     checkbuf
  721.   until outflag;
  722.   endtext; position:=position-addr(textbuf[0]);
  723.   clrscr; crtexit
  724. end;
  725.