home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 276.img / FORUM21S.ZIP / ANSIEDIT.PAS < prev    next >
Pascal/Delphi Source File  |  1988-02-13  |  20KB  |  1,038 lines

  1. {$R-,S-,I-,D-,T-,F-,V-,B-,N-,L+ }
  2. {$M 65500,0,0 }
  3.  
  4. {$ifdef testansieditor}
  5. {*}
  6. {*} {*} indicates test code
  7. {*}
  8. {*}uses crt,modem;
  9. {*}
  10. {*}const maxmessagesize=100;
  11. {*}      hungupon=false;
  12. {*}
  13. {*}type anystr=string[255];
  14. {*}     lstr=string[80];
  15. {*}     mstr=string[30];
  16. {*}     sstr=string[15];
  17. {*}
  18. {*}     message=record
  19. {*}       text:array [1..maxmessagesize] of lstr;
  20. {*}       title:mstr;
  21. {*}       anon:boolean;
  22. {*}       numlines:integer
  23. {*}     end;
  24. {*}
  25. {*}     regs=record
  26. {*}       case byte of
  27. {*}         0:(ax,bx,cx,dx,bp,si,di,ds,es,flags:integer);
  28. {*}         1:(al,ah,bl,bh,cl,ch,dl,dh:byte)
  29. {*}     end;
  30. {*}
  31. {*}type configtype=(moreprompts,eightycols,ansigraphics);
  32. {*}
  33. {*}var input:anystr;
  34. {*}    nobreak:boolean;
  35. {*}    urec:record
  36. {*}      displaylen:integer;
  37. {*}      config:set of configtype
  38. {*}    end;
  39. {*}    winds:array [0..0] of record y2:integer end;
  40. {*}
  41. {*}
  42. {*}function strr (n:integer):mstr;
  43. {*}var q:mstr;
  44. {*}begin
  45. {*}  str (n,q);
  46. {*}  strr:=q
  47. {*}end;
  48. {*}
  49. {*}function waitforchar:char;
  50. {*}var k:char;
  51. {*}begin
  52. {*}  repeat until keypressed or (numchars>0);
  53. {*}  read (kbd,k);
  54. {*}  waitforchar:=k
  55. {*}end;
  56. {*}
  57. {*}procedure clearbreak;
  58. {*}begin
  59. {*}end;
  60. {*}
  61. {*}function yes:boolean;
  62. {*}begin
  63. {*}  yes:=false;
  64. {*}  if length(input)>0
  65. {*}    then if upcase(input[1])='Y'
  66. {*}      then yes:=true
  67. {*}end;
  68. {*}
  69. {*}function readchar:char;
  70. {*}var r:regs;
  71. {*}begin
  72. {*}  if keypressed then begin
  73. {*}    r.ah:=0;
  74. {*}    intr ($16,r);
  75. {*}    readchar:=chr(r.al);
  76. {*}    if r.al=29 then halt;
  77. {*}    if r.al=0 then case r.ah of
  78. {*}      72:readchar:=^E;
  79. {*}      75:readchar:=^S;
  80. {*}      77:readchar:=^D;
  81. {*}      80:readchar:=^X;
  82. {*}      115:readchar:=^A;
  83. {*}      116:readchar:=^F;
  84. {*}      73:readchar:=^R;
  85. {*}      81:readchar:=^C;
  86. {*}      71:readchar:=^Q;
  87. {*}      79:readchar:=^W;
  88. {*}      83:readchar:=^G;
  89. {*}      82:readchar:=^V;
  90. {*}      117:readchar:=^P;
  91. {*}    end;
  92. {*}    exit
  93. {*}  end;
  94. {*}  if (numchars>0) and carrier
  95. {*}    then readchar:=getchar
  96. {*}    else readchar:=#0
  97. {*}end;
  98. {*}
  99. {*}procedure writeturbo (k:char);
  100. {*}begin
  101. {*}  inline ($8A/$86/k/$50/$ff/$16/usroutptr)
  102. {*}end;
  103. {*}
  104. {*}procedure writechar (k:char);
  105. {*}var r:regs;
  106. {*}begin
  107. {*}  if k=^J then writeturbo (k) else begin
  108. {*}    r.dl:=ord(k);
  109. {*}    r.ah:=2;
  110. {*}    intr ($21,r)
  111. {*}  end;
  112. {*}  if carrier then sendchar (k)
  113. {*}end;
  114. {*}
  115. {*}procedure getstr;
  116. {*}begin
  117. {*}  readln (input)
  118. {*}end;
  119. {*}
  120. {*}procedure printfile (l:lstr);
  121. {*}begin
  122. {*}end;
  123. {*}
  124. {*}procedure wholescreen;
  125. {*}begin
  126. {*}  window (1,1,80,winds[0].y2)
  127. {*}end;
  128. {*}
  129. {*}procedure bottom;
  130. {*}begin
  131. {*}end;
  132. {*}
  133. {*}procedure bottomline;
  134. {*}begin
  135. {*}end;
  136. {*}
  137. {*}procedure unsplit;
  138. {*}begin
  139. {*}end;
  140. {*}
  141. {*}function ansireedit (var m:message; gettitle:boolean):boolean;
  142. {*}
  143. {$else}
  144.  
  145. unit ansiedit;
  146.  
  147. interface
  148.  
  149. uses crt,
  150.      gentypes,modem,configrt,windows,gensubs,subs1,subs2;
  151.  
  152. function ansireedit (var m:message; gettitle:boolean):boolean;
  153.  
  154. implementation
  155.  
  156. function ansireedit (var m:message; gettitle:boolean):boolean;
  157.  
  158. {$endif}
  159.  
  160. var topline,curline,cx,cy,cols,scrnsize,lines,
  161.     rightmargin,savedx,savedy,topscrn:integer;
  162.     insertmode,msgdone,ansimode:boolean;
  163.  
  164. function curx:integer;
  165. begin
  166.   curx:=wherex
  167. end;
  168.  
  169. function cury:integer;
  170. begin
  171.   cury:=wherey-topscrn+1
  172. end;
  173.  
  174. procedure writevt52 (q:lstr);
  175. var cnt:integer;
  176. begin
  177.   if not carrier then exit;
  178.   for cnt:=1 to length(q) do sendchar (q[cnt])
  179. end;
  180.  
  181. procedure moveto (x,y:integer);
  182. begin
  183.   y:=y+topscrn-1;
  184.   if ansimode then begin
  185.     write (direct,#27'[');
  186.     if y<>1 then write (direct,strr(y));
  187.     if x<>1 then write (direct,';',strr(x));
  188.     write ('H')
  189.   end else begin
  190.     gotoxy (x,y);
  191.     writevt52 (#27'Y'+chr(y+31)+chr(x+31))
  192.   end
  193. end;
  194.  
  195. procedure clearscr;
  196. begin
  197.   if ansimode
  198.     then write (direct,#27'[2J')
  199.     else begin
  200.       writevt52 (#27'H'#27'J');
  201.       clrscr
  202.     end
  203. end;
  204.  
  205. procedure cleareol;
  206. begin
  207.   if ansimode
  208.     then write (direct,#27'[K')
  209.     else begin
  210.       writevt52 (#27'K');
  211.       clreol
  212.     end
  213. end;
  214.  
  215. procedure savecsr;
  216. begin
  217.   if ansimode
  218.     then write (direct,#27'[s')
  219.     else begin
  220.       savedx:=curx;
  221.       savedy:=cury
  222.     end
  223. end;
  224.  
  225. procedure restorecsr;
  226. begin
  227.   if ansimode
  228.     then write (direct,#27'[u')
  229.     else moveto (savedx,savedy)
  230. end;
  231.  
  232. procedure cmove (k:char; n,dx,dy:integer);
  233. var cnt:integer;
  234. begin
  235.   if n<1 then exit;
  236.   if ansimode then begin
  237.     write (direct,#27'[');
  238.     if n<>1 then write (direct,strr(n));
  239.     write (direct,k)
  240.   end else
  241.     for cnt:=1 to n do begin
  242.       writevt52 (#27+k);
  243.       gotoxy (wherex+dx,wherey+dy)
  244.     end
  245. end;
  246.  
  247. procedure cup (n:integer);
  248. begin
  249.   cmove ('A',n,0,-1)
  250. end;
  251.  
  252. procedure cdn (n:integer);
  253. begin
  254.   cmove ('B',n,0,1)
  255. end;
  256.  
  257. procedure clf (n:integer);
  258. var cnt:integer;
  259. begin
  260.   cmove ('D',n,-1,0)
  261. end;
  262.  
  263. procedure crg (n:integer);
  264. begin
  265.   cmove ('C',n,1,0)
  266. end;
  267.  
  268. procedure checkspaces;
  269. var q:^lstr;
  270. begin
  271.   q:=addr(m.text[curline]);
  272.   while q^[length(q^)]=' ' do q^[0]:=pred(q^[0])
  273. end;
  274.  
  275. procedure checkcx;
  276. var n:integer;
  277. begin
  278.   n:=length(m.text[curline])+1;
  279.   if cx>n then cx:=n
  280. end;
  281.  
  282. procedure computecy;
  283. begin
  284.   cy:=curline-topline+1
  285. end;
  286.  
  287. procedure updatecpos;
  288. begin
  289.   computecy;
  290.   moveto (cx,cy)
  291. end;
  292.  
  293. procedure insertabove;
  294. var cnt:integer;
  295. begin
  296.   if m.numlines=maxmessagesize then exit;
  297.   for cnt:=m.numlines downto curline do m.text[cnt+1]:=m.text[cnt];
  298.   m.text[curline]:='';
  299.   m.numlines:=m.numlines+1
  300. end;
  301.  
  302. procedure deletethis;
  303. var cnt:integer;
  304. begin
  305.   if m.numlines=1 then begin
  306.     m.text[1]:='';
  307.     exit
  308.   end;
  309.   for cnt:=curline+1 to m.numlines do m.text[cnt-1]:=m.text[cnt];
  310.   m.text[m.numlines]:='';
  311.   m.numlines:=m.numlines-1;
  312.   checkcx
  313. end;
  314.  
  315. procedure fullrefresh;
  316. var cnt,n:integer;
  317. begin
  318.   clearscr;
  319.   if topline<1 then topline:=1;
  320.   computecy;
  321.   moveto (1,1);
  322.   for cnt:=1 to lines do begin
  323.     n:=cnt+topline-1;
  324.     if n<=m.numlines then begin
  325.       write (m.text[n]);
  326.       if cnt<>lines then writeln
  327.     end
  328.   end;
  329.   updatecpos
  330. end;
  331.  
  332. procedure repos (dorefresh:boolean);
  333. var cl,tl:integer;
  334. begin
  335.   checkspaces;
  336.   cl:=curline;
  337.   tl:=topline;
  338.   if curline<1 then curline:=1;
  339.   if curline>m.numlines then curline:=m.numlines;
  340.   if topline>curline then topline:=curline;
  341.   if topline+lines<curline then topline:=curline-lines;
  342.   if topline<1 then topline:=1;
  343.   checkcx;
  344.   computecy;
  345.   if (cl=curline) and (tl=topline) and (not dorefresh)
  346.     then updatecpos
  347.     else fullrefresh
  348. end;
  349.  
  350. procedure partrefresh;  { Refreshes from CY }
  351. var cnt,n:integer;
  352. begin
  353.   if topline<1 then repos(true) else begin
  354.     moveto (1,cy);
  355.     for cnt:=cy to lines do begin
  356.       n:=cnt+topline-1;
  357.       if n<=m.numlines then write (m.text[n]);
  358.       cleareol;
  359.       if cnt<>lines then writeln
  360.     end;
  361.     updatecpos
  362.   end
  363. end;
  364.  
  365. procedure pageup;
  366. begin
  367.   checkspaces;
  368.   if curline=1 then exit;
  369.   curline:=curline-lines+4;
  370.   topline:=topline-lines+4;
  371.   repos (true)
  372. end;
  373.  
  374. procedure pagedn;
  375. begin
  376.   checkspaces;
  377.   if curline=m.numlines then exit;
  378.   curline:=curline+lines-4;
  379.   topline:=topline+lines-4;
  380.   repos (true)
  381. end;
  382.  
  383. procedure toggleins;
  384. begin
  385.   insertmode:=not insertmode
  386. end;
  387.  
  388. procedure scrolldown;
  389. begin
  390.   topline:=curline-lines+2;
  391.   repos (true)
  392. end;
  393.  
  394. procedure scrollup;
  395. begin
  396.   if topline<1 then begin
  397.     topline:=topline+1;
  398.     moveto (1,lines);
  399.     computecy;
  400.     writeln
  401.   end else begin
  402.     topline:=curline-1;
  403.     repos (true)
  404.   end
  405. end;
  406.  
  407. procedure topofmsg;
  408. begin
  409.   checkspaces;
  410.   cx:=1;
  411.   cy:=1;
  412.   curline:=1;
  413.   if topline=1
  414.     then updatecpos
  415.     else
  416.       begin
  417.         topline:=1;
  418.         fullrefresh
  419.       end
  420. end;
  421.  
  422. procedure updatetoeol;
  423. var cnt:integer;
  424. begin
  425.   savecsr;
  426.   write (copy(m.text[curline],cx,255));
  427.   cleareol;
  428.   restorecsr
  429. end;
  430.  
  431. procedure letterkey (k:char);
  432. var l:^lstr;
  433.     w:lstr;
  434.     n,ox:integer;
  435.     q:char;
  436.     inserted,refr:boolean;
  437.  
  438.   procedure scrollwwrap;
  439.   begin
  440.     if topline>0 then begin
  441.       scrollup;
  442.       exit
  443.     end;
  444.     cy:=cy-1;
  445.     moveto (length(m.text[curline-1])+1,cy);
  446.     cleareol;
  447.     writeln;
  448.     write (m.text[curline]);
  449.     topline:=topline+1;
  450.     cx:=curx
  451.   end;
  452.  
  453. begin
  454.   l:=addr(m.text[curline]);
  455.   if length(l^)>=rightmargin then begin
  456.     if curline=maxmessagesize then exit;
  457.     if cx<=length(l^) then exit;
  458.     l^:=l^+k;
  459.     w:='';
  460.     cx:=length(l^);
  461.     repeat
  462.       q:=l^[cx];
  463.       if q<>' ' then insert (q,w,1);
  464.       cx:=cx-1
  465.     until (q=' ') or (cx<1);
  466.     if cx<1 then begin
  467.       cx:=length(l^)-1;
  468.       w:=k
  469.     end;
  470.     l^[0]:=chr(cx);
  471.     checkspaces;
  472.     curline:=curline+1;
  473.     if curline>m.numlines then m.numlines:=curline;
  474.     inserted:=m.text[curline]<>'';
  475.     if inserted then insertabove;
  476.     m.text[curline]:=w;
  477.     cy:=cy+1;
  478.     ox:=cx;
  479.     cx:=length(w)+1;
  480.     refr:=cy>lines;
  481.     if refr
  482.       then scrollwwrap
  483.       else begin
  484.         if length(w)>0 then begin
  485.           moveto (ox+1,cy-1);
  486.           for n:=1 to length(w) do write (' ')
  487.         end;
  488.         if inserted and (m.numlines>curline)
  489.           then partrefresh
  490.           else begin
  491.             moveto (1,cy);
  492.             write (m.text[curline]);
  493.           end
  494.       end;
  495.     exit
  496.   end;
  497.   if insertmode
  498.     then insert (k,l^,cx)
  499.     else begin
  500.       while length(l^)<cx do l^:=l^+' ';
  501.       l^[cx]:=k
  502.     end;
  503.   write (k);
  504.   cx:=cx+1;
  505.   if insertmode and (cx<=length(l^)) then updatetoeol
  506. end;
  507.  
  508. procedure back;
  509. begin
  510.   if cx=1 then begin
  511.     if curline=1 then exit;
  512.     checkspaces;
  513.     curline:=curline-1;
  514.     cy:=cy-1;
  515.     cx:=length(m.text[curline])+1;
  516.     if cy<1 then scrolldown else updatecpos;
  517.   end else begin
  518.     cx:=cx-1;
  519.     clf (1)
  520.   end
  521. end;
  522.  
  523. procedure fowrd;
  524. begin
  525.   if cx>length(m.text[curline]) then begin
  526.     if curline=maxmessagesize then exit;
  527.     checkspaces;
  528.     curline:=curline+1;
  529.     if curline>m.numlines then m.numlines:=curline;
  530.     cy:=cy+1;
  531.     cx:=1;
  532.     if cy>lines then scrollup else updatecpos
  533.   end else begin
  534.     cx:=cx+1;
  535.     crg (1)
  536.   end
  537. end;
  538.  
  539. procedure del;
  540. begin
  541.   if length(m.text[curline])=0 then begin
  542.     deletethis;
  543.     partrefresh;
  544.     exit
  545.   end;
  546.   delete (m.text[curline],cx,1);
  547.   if cx>length(m.text[curline])
  548.     then write (' '^H)
  549.     else updatetoeol
  550. end;
  551.  
  552. procedure bkspace;
  553. begin
  554.   if length(m.text[curline])=0 then begin
  555.     if curline=1 then exit;
  556.     deletethis;
  557.     checkspaces;
  558.     curline:=curline-1;
  559.     cy:=cy-1;
  560.     cx:=length(m.text[curline])+1;
  561.     if cy<1
  562.       then scrolldown
  563.       else partrefresh;
  564.     exit
  565.   end;
  566.   if cx=1 then exit;
  567.   cx:=cx-1;
  568.   write (^H);
  569.   del
  570. end;
  571.  
  572. procedure beginline;
  573. begin
  574.   if cx=1 then exit;
  575.   cx:=1;
  576.   updatecpos
  577. end;
  578.  
  579. procedure endline;
  580. var dx:integer;
  581. begin
  582.   dx:=length(m.text[curline])+1;
  583.   if cx=dx then exit;
  584.   cx:=dx;
  585.   updatecpos
  586. end;
  587.  
  588. procedure upline;
  589. var chx:boolean;
  590.     l:integer;
  591. begin
  592.   checkspaces;
  593.   if curline=1 then exit;
  594.   curline:=curline-1;
  595.   l:=length(m.text[curline]);
  596.   chx:=cx>l;
  597.   if chx then cx:=l+1;
  598.   cy:=cy-1;
  599.   if cy>0
  600.     then if chx
  601.       then updatecpos
  602.       else cup (1)
  603.     else scrolldown
  604. end;
  605.  
  606. procedure downline;
  607. var chx:boolean;
  608.     l:integer;
  609. begin
  610.   checkspaces;
  611.   if curline=maxmessagesize then exit;
  612.   curline:=curline+1;
  613.   if curline>m.numlines then m.numlines:=curline;
  614.   l:=length(m.text[curline]);
  615.   chx:=cx>l;
  616.   if chx then cx:=l+1;
  617.   cy:=cy+1;
  618.   if cy<=lines
  619.     then if chx
  620.       then updatecpos
  621.       else cdn (1)
  622.     else scrollup
  623. end;
  624.  
  625. procedure crlf;
  626. var k:char;
  627. begin
  628.   if (length(m.text[curline])=2) and (m.text[curline][1]='/') then begin
  629.     k:=upcase(m.text[curline][2]);
  630.     case k of
  631.       'S':begin
  632.         deletethis;
  633.         msgdone:=true;
  634.         ansireedit:=true;
  635.         exit
  636.       end
  637.     end
  638.   end;
  639.   beginline;
  640.   downline
  641. end;
  642.  
  643. function conword:boolean;
  644. var l:^lstr;
  645. begin
  646.   l:=addr(m.text[curline]);
  647.   conword:=false;
  648.   if (cx>length(l^)) or (cx=0) then exit;
  649.   conword:=true;
  650.   if cx=1 then exit;
  651.   if (l^[cx-1]=' ') and (l^[cx]<>' ') then exit;
  652.   conword:=false
  653. end;
  654.  
  655. procedure wordleft;
  656. begin
  657.   repeat
  658.     cx:=cx-1;
  659.     if cx<1 then begin
  660.       if curline=1 then begin
  661.         cx:=1;
  662.         repos (false);
  663.         exit
  664.       end;
  665.       checkspaces;
  666.       curline:=curline-1;
  667.       cy:=cy-1;
  668.       cx:=length(m.text[curline])
  669.     end;
  670.   until conword;
  671.   if cx=0 then cx:=1;
  672.   if cy<1
  673.     then repos (true)
  674.     else updatecpos
  675. end;
  676.  
  677. procedure wordright;
  678. begin
  679.   repeat
  680.     cx:=cx+1;
  681.     if cx>length(m.text[curline]) then begin
  682.       if curline=m.numlines then begin
  683.         repos (false);
  684.         exit
  685.       end;
  686.       checkspaces;
  687.       curline:=curline+1;
  688.       cy:=cy+1;
  689.       cx:=1
  690.     end;
  691.   until conword;
  692.   if cy>lines
  693.     then repos (true)
  694.     else updatecpos
  695. end;
  696.  
  697. procedure worddel;
  698. var l:^lstr;
  699.     b:byte;
  700.     s,n:integer;
  701. begin
  702.   l:=addr(m.text[curline]);
  703.   b:=length(l^);
  704.   if cx>b then exit;
  705.   s:=cx;
  706.   repeat
  707.     cx:=cx+1
  708.   until conword or (cx>b);
  709.   n:=cx-s;
  710.   delete (l^,s,n);
  711.   cx:=s;
  712.   updatetoeol
  713. end;
  714.  
  715. procedure deleteline;
  716. begin
  717.   deletethis;
  718.   partrefresh
  719. end;
  720.  
  721. procedure insertline;
  722. begin
  723.   if m.numlines>=maxmessagesize then exit;
  724.   insertabove;
  725.   checkcx;
  726.   partrefresh
  727. end;
  728.  
  729. procedure help;
  730. var k:char;
  731. begin
  732.   clearscr;
  733.   printfile (textfiledir+'Edithelp.ANS');
  734.   write (^B^M'Press any key...');
  735.   k:=waitforchar;
  736.   fullrefresh
  737. end;
  738.  
  739. procedure breakline;
  740. begin
  741.   if (m.numlines>=maxmessagesize) or (cy=lines) or
  742.     (cx=1) or (cx>length(m.text[curline])) then exit;
  743.   insertabove;
  744.   m.text[curline]:=copy(m.text[curline+1],1,cx-1);
  745.   delete (m.text[curline+1],1,cx-1);
  746.   partrefresh
  747. end;
  748.  
  749. procedure joinlines;
  750. var n:integer;
  751. begin
  752.   if curline=m.numlines then exit;
  753.   if length(m.text[curline])+length(m.text[curline+1])>rightmargin then exit;
  754.   m.text[curline]:=m.text[curline]+m.text[curline+1];
  755.   n:=cx;
  756.   curline:=curline+1;
  757.   deletethis;
  758.   curline:=curline-1;
  759.   cx:=n;
  760.   partrefresh
  761. end;
  762.  
  763. procedure userescape;
  764. var k:char;
  765. begin
  766.   repeat
  767.   k:=waitforchar;
  768.     case k of
  769.       'A':upline;
  770.       'B':downline;
  771.       'C':fowrd;
  772.       'D':back
  773.     end
  774.   until (k<>'[') or hungupon
  775. end;
  776.  
  777. procedure deleteeol;
  778. begin
  779.   cleareol;
  780.   m.text[curline][0]:=chr(cx-1)
  781. end;
  782.  
  783. procedure tab;
  784. var nx,n,cnt:integer;
  785. begin
  786.   nx:=((cx+8) and 248)+1;
  787.   n:=nx-cx;
  788.   if (n+length(m.text[curline])>=cols) or (nx>=cols) then exit;
  789.   for cnt:=1 to n do insert (' ',m.text[curline],cx);
  790.   updatetoeol;
  791.   cx:=cx+n;
  792.   updatecpos
  793. end;
  794.  
  795. procedure commands;
  796.  
  797.   function youaresure:boolean;
  798.   var q:string[1];
  799.   begin
  800.     youaresure:=false;
  801.     moveto (1,0);
  802.     write ('Are you sure? ');
  803.     buflen:=1;
  804.     getstr;
  805.     cup (1);
  806.     write ('               ');
  807.     youaresure:=yes;
  808.     clearbreak;
  809.     nobreak:=true
  810.   end;
  811.  
  812.   procedure savemes;
  813.   begin
  814.     msgdone:=true;
  815.     ansireedit:=true
  816.   end;
  817.  
  818.   procedure abortmes;
  819.   begin
  820.     if youaresure then begin
  821.       m.numlines:=0;
  822.       msgdone:=true
  823.     end
  824.   end;
  825.  
  826.   procedure formattext;
  827.   var ol,il,c:integer;
  828.       oln,wd,iln:lstr;
  829.       k:char;
  830.  
  831.     procedure putword;
  832.     var cnt:integer;
  833.         b:boolean;
  834.     begin
  835.       b:=true;
  836.       for cnt:=1 to length(wd) do if wd[cnt]<>' ' then b:=false;
  837.       if b then exit;
  838.       while wd[length(wd)]=' ' do wd[0]:=pred(wd[0]);
  839.       if length(wd)=0 then exit;
  840.       if length(wd)+length(oln)>rightmargin then begin
  841.         m.text[ol]:=oln;
  842.         ol:=ol+1;
  843.         while (wd[1]=' ') and (length(wd)>0) do delete (wd,1,1);
  844.         oln:=wd
  845.       end else oln:=oln+wd;
  846.       if wd[length(wd)] in ['.','?','!']
  847.         then wd:='  '
  848.         else wd:=' '
  849.     end;
  850.  
  851.   begin
  852.     il:=curline;
  853.     ol:=il;
  854.     c:=1;
  855.     oln:='';
  856.     wd:='';
  857.     iln:=m.text[il];
  858.     repeat
  859.       if length(iln)=0 then begin
  860.         putword;
  861.         m.text[ol]:=oln;
  862.         partrefresh;
  863.         checkcx;
  864.         updatecpos;
  865.         exit
  866.       end;
  867.       if c>length(iln) then begin
  868.         il:=il+1;
  869.         if il>m.numlines
  870.           then iln:=''
  871.           else begin
  872.             iln:=m.text[il];
  873.             m.text[il]:=''
  874.           end;
  875.         c:=0;
  876.         k:=' '
  877.       end else k:=iln[c];
  878.       c:=c+1;
  879.       if k=' '
  880.         then putword
  881.         else wd:=wd+k
  882.     until 0=1
  883.   end;
  884.  
  885. var cmd:string[1];
  886.     k:char;
  887. begin
  888.   clearbreak;
  889.   nobreak:=true;
  890.   moveto (1,0);
  891.   write ('Cmd: ');
  892.   buflen:=1;
  893.   getstr;
  894.   clearbreak;
  895.   nobreak:=true;
  896.   cup (1);
  897.   write ('      ');
  898.   if length(input)=0 then begin
  899.     updatecpos;
  900.     exit
  901.   end;
  902.   k:=upcase(input[1]);
  903.   case k of
  904.     'S':savemes;
  905.     'A':abortmes;
  906.     'F':formattext;
  907.     '?':help
  908.   end;
  909.   updatecpos
  910. end;
  911.  
  912. procedure processkey;
  913. var k:char;
  914. begin
  915.   clearbreak;
  916.   nobreak:=true;
  917.   k:=waitforchar;
  918.   case k of
  919.     ' '..'~':letterkey (k);
  920.     ^S:back;
  921.     ^D:fowrd;
  922.     ^H:bkspace;
  923.     ^M:crlf;
  924.     ^V:toggleins;
  925.     ^E:upline;
  926.     ^X:downline;
  927.     ^U:help;
  928.     ^K:commands;
  929.     ^R:pageup;
  930.     ^C:pagedn;
  931.     ^G:del;
  932.     ^A:wordleft;
  933.     ^F:wordright;
  934.     ^T:worddel;
  935.     ^Q:beginline;
  936.     ^W:endline;
  937.     ^L:fullrefresh;
  938.     ^Y:deleteline;
  939.     ^N:insertline;
  940.     ^I:tab;
  941.     ^B:breakline;
  942.     ^P:deleteeol;
  943.     ^J:joinlines;
  944.     #27:userescape
  945.   end
  946. end;
  947.  
  948. var cnt:integer;
  949.     mp:boolean;
  950. begin
  951.   clearbreak;
  952.   nobreak:=true;
  953.   ansireedit:=false;
  954.  
  955.   for cnt:=m.numlines+1 to maxmessagesize do m.text[cnt]:='';
  956.   scrnsize:=urec.displaylen;
  957.   winds[0].y2:=scrnsize;
  958.   unsplit;
  959.   wholescreen;
  960.   gotoxy (1,25);
  961.   clreol;
  962.   if eightycols in urec.config
  963.     then cols:=80
  964.     else cols:=40;
  965.   ansimode:=ansigraphics in urec.config;
  966.   mp:=moreprompts in urec.config;
  967.   if mp then urec.config:=urec.config-[moreprompts];
  968.   lines:=15;
  969.   topscrn:=scrnsize-lines+1;
  970.   insertmode:=false;
  971.   rightmargin:=cols-1;
  972.   msgdone:=false;
  973.   cx:=1;
  974.   curline:=1;
  975.   topline:=2-lines;
  976.   computecy;
  977.   updatecpos;
  978.   if m.numlines>0
  979.     then fullrefresh
  980.     else
  981.       begin
  982.         writeln (^M'Press ^U for help.'^M);
  983.         m.numlines:=1
  984.       end;
  985.   repeat
  986.     processkey
  987.   until msgdone or hungupon;
  988.   moveto (1,lines);
  989.   cleareol;
  990.   writeln (^M^M^M^M);
  991.   if mp then urec.config:=urec.config+[moreprompts];
  992.   winds[0].y2:=25;
  993.   bottom;
  994.   bottomline
  995. end;
  996.  
  997.  
  998. {$ifdef testansieditor}
  999. {*}
  1000. {*}procedure termmode;
  1001. {*}var k:char;
  1002. {*}begin
  1003. {*}  setparam (1,1200,false);
  1004. {*}  writeln ('Press ^D when connected.');
  1005. {*}  repeat
  1006. {*}    if keypressed then begin
  1007. {*}      read (kbd,k);
  1008. {*}      if k=#4 then exit;
  1009. {*}      if k=#3 then halt;
  1010. {*}      sendchar (k)
  1011. {*}    end;
  1012. {*}    while numchars>0 do write (getchar)
  1013. {*}  until 0=1
  1014. {*}end;
  1015. {*}
  1016. {*}var m:message;
  1017. {*}    cnt:integer;
  1018. {*}begin
  1019. {*}  checkbreak:=false;
  1020. {*}  urec.displaylen:=22;
  1021. {*}  urec.config:=[eightycols]; { ,ansigraphics]; }
  1022. {*}  if not driverpresent then begin
  1023. {*}    writeln ('You fool.');
  1024. {*}    halt
  1025. {*}  end;
  1026. {*}  termmode;
  1027. {*}  coninptr:=ofs(readchar);
  1028. {*}  conoutptr:=ofs(writechar);
  1029. {*}  m.numlines:=0;
  1030. {*}  for cnt:=1 to 100 do m.text[cnt]:='Hello line '+chr(cnt+64);
  1031. {*}  writeln (ansireedit(m,false))
  1032. {*}
  1033. {$endif}
  1034.  
  1035. end.
  1036.  
  1037.  
  1038.