home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w048 / 2.ddi / MSSRC.ARC / MSMEMOP.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-12-21  |  18.9 KB  |  698 lines

  1. {                            MSMEMOP.PAS
  2.                                MS 4.0
  3.                 Copyright (c) 1985, 87 by Borland International, Inc.         }
  4.  
  5. {$I msdirect.inc}
  6.  
  7. unit MsMemOp;
  8.   {-Allocate and deallocate memory for text lines and windows}
  9.  
  10. interface
  11.  
  12. uses
  13.   Crt,                       {Basic video}
  14.   Dos,                       {DOS interface - standard unit}
  15.   Errors,                    {Runtime error handler}
  16.   MsVars,                    {Global types and declarations}
  17.   MsScrn1,                   {Fast screen writing routines}
  18.   MsString,                  {String primitives}
  19.   MsPtrOp,                   {Primitive pointer operations}
  20.   EscSeq,                    {Returns text string for extended scan codes}
  21.   MsCmds,                    {Maps keystrokes to commands}
  22.   Int24,                     {DOS critical error handler}
  23.   Message,                   {Message system}
  24.   MsUser;                    {User keyboard, prompt and error interactions}
  25.  
  26. var
  27.   ExactAllocation : Boolean; {Set true to allocate buffers of same size as text}
  28.  
  29. function EdBufferSize(Ncols : Integer) : Integer;
  30.   {-Return a proper buffer size for the number of text columns requested}
  31.  
  32. procedure EdDesTextDesc(P : PlineDesc);
  33.   {-Destroy text descriptor}
  34.  
  35. procedure EdPushUndo(var P : PlineDesc);
  36.   {-Save a deleted line on the undo stack if possible}
  37.  
  38. procedure EdDeleteAllText(W : Pwindesc);
  39.   {-delete the entire text stream of a window}
  40.  
  41. function EdMaktextdesc(Ncols : Integer) : PlineDesc;
  42.   {-Make new text descriptor record}
  43.  
  44. function EdSizeline(P : PlineDesc; Ncols : Integer; Init : Boolean) : Boolean;
  45.   {-Expand line size to accommodate Ncols characters}
  46.  
  47. function EdAllocateWindow(Top, Len, Cr, Cc : Integer; Fn : Filepath) : Pwindesc;
  48.   {-Return a pointer to a window structure}
  49.  
  50. function EdNewTextStream(W : Pwindesc) : Boolean;
  51.   {-Create a new text stream, returning true if successful}
  52.  
  53. procedure EdJoinLinePrimitive(P : PlineDesc; LenP : Integer);
  54.   {-Join the line p at column lenP with the line following it}
  55.  
  56. procedure EdJoinline;
  57.   {-Join two lines and fix up block markers}
  58.  
  59. procedure EdInsertLinePrimitive(M : BlockMarker; var P : PlineDesc);
  60.   {-Insert a new line after marker m, return pointer to new line}
  61.  
  62. function EdInsertSpace(P : PlineDesc; Start : Integer; Num : Integer) : Boolean;
  63.   {-Insert num spaces at position start of line p}
  64.  
  65. procedure EdNewLinePrimitive;
  66.   {-Insert a new line, straighten out indents and markers}
  67.  
  68. procedure EdWindowCreate(Wno : Byte);
  69.   {-Create new window by splitting window wno in two}
  70.  
  71. procedure EdPushWindowStack(W : Pwindesc);
  72.   {-Put a window descriptor on the window free list}
  73.  
  74. procedure EdWindowDelete(Wno : Byte);
  75.   {-Perform delete window command processing}
  76.  
  77. procedure EdResetWindow(W : Pwindesc);
  78.   {-Reset the window descriptor}
  79.  
  80. function EdCalcMemory : VarString;
  81.   {-Return the bytes of available heap space, in a string}
  82.  
  83.   {==========================================================================}
  84.  
  85. implementation
  86.  
  87.   function EdBufferSize(Ncols : Integer) : Integer;
  88.     {-Return a proper buffer size for the number of text columns requested}
  89.  
  90.   begin                      {EdBufferSize}
  91.     if ExactAllocation then
  92.       EdBufferSize := Succ(Ncols)
  93.     else
  94.       EdBufferSize := Succ(Ncols shr 3) shl 3;
  95.   end;                       {EdBufferSize}
  96.  
  97.   procedure EdDesTextDesc(P : PlineDesc);
  98.     {-Destroy text descriptor}
  99.  
  100.   begin                      {EdDesTextdesc}
  101.     {Free text line first}
  102.     FreeMem(P^.Txt, Succ(P^.Bufflen));
  103.     {Now the linedesc itself}
  104.     FreeMem(P, SizeOf(Linedesc));
  105.   end;                       {EdDesTextdesc}
  106.  
  107.   procedure EdPushUndo(var P : PlineDesc);
  108.     {-Save a deleted line on the undo stack if possible}
  109.   var
  110.     Q : PlineDesc;
  111.     M : Integer;
  112.  
  113.   begin                      {EdPushUndo}
  114.  
  115.     {Make sure the undo stack hasn't overflowed}
  116.     if UndoLimit <> 0 then
  117.       while (UndoCount >= UndoLimit) do begin
  118.         {If we need to delete a line at the rear}
  119.         Dec(UndoCount);
  120.         Q := UndoEnd^.Backlink;
  121.         EdDesTextDesc(UndoEnd);
  122.         UndoEnd := Q;
  123.         if EdPtrIsNil(UndoEnd) then begin
  124.           UndoCount := 0;
  125.           EdSetPtrNil(UndoStack);
  126.         end else
  127.           EdSetPtrNil(UndoEnd^.Fwdlink);
  128.       end;
  129.  
  130.     {Reset text markers}
  131.     if EdFlagSet(P, InMark) then
  132.       for M := 0 to MaxMarker do
  133.         with Marker[M] do
  134.           if Line = P then
  135.             EdSetPtrNil(Line);
  136.  
  137.     {Push line onto undo stack}
  138.     if UndoLimit = 0 then
  139.       {If undo is not enabled, destroy line}
  140.       EdDesTextDesc(P)
  141.     else if EdPtrIsNil(UndoStack) then begin
  142.       {No lines on the undo stack}
  143.       UndoStack := P;
  144.       UndoEnd := P;
  145.       EdSetPtrNil(P^.Fwdlink);
  146.       EdSetPtrNil(P^.Backlink);
  147.       UndoCount := 1;
  148.     end else begin
  149.       {Just push the line}
  150.       EdSetPtrNil(P^.Backlink);
  151.       P^.Fwdlink := UndoStack;
  152.       if EdPtrNotNil(P^.Fwdlink) then
  153.         P^.Fwdlink^.Backlink := P;
  154.       UndoStack := P;
  155.       Inc(UndoCount);
  156.     end;
  157.   end;                       {EdPushUndo}
  158.  
  159.   procedure EdDeleteAllText(W : Pwindesc);
  160.     {-Delete the entire text stream of a window}
  161.   var
  162.     P, Q : PlineDesc;
  163.     M : Integer;
  164.  
  165.   begin                      {EdDeleteAllText}
  166.     with W^ do begin
  167.  
  168.       {Find top of the text stream}
  169.       P := TopLine;
  170.       while EdPtrNotNil(P^.Backlink) do
  171.         EdBackPtr(P);
  172.  
  173.       {Delete each line in the stream}
  174.       while EdPtrNotNil(P) do begin
  175.         Q := P;
  176.         EdFwdPtr(P);
  177.  
  178.         if (Q = Blockfrom.Line) or (Q = Blockto.Line) then begin
  179.           {Reset block markers if destroyed}
  180.           EdSetPtrNil(Blockfrom.Line);
  181.           EdSetPtrNil(Blockto.Line);
  182.           Blockhide := True;
  183.         end;
  184.  
  185.         if EdFlagSet(Q, InMark) then
  186.           {Reset text markers if destroyed}
  187.           for M := 0 to MaxMarker do
  188.             with Marker[M] do
  189.               if Line = Q then
  190.                 EdSetPtrNil(Line);
  191.  
  192.         {Deallocate heap space}
  193.         EdDesTextDesc(Q);
  194.       end;
  195.  
  196.       {Indicate that top line points to no text}
  197.       EdSetPtrNil(TopLine);
  198.  
  199.     end;
  200.   end;                       {EdDeleteAllText}
  201.  
  202.   function EdMaktextdesc(Ncols : Integer) : PlineDesc;
  203.     {-Make new text descriptor record}
  204.   var
  205.     Len : Integer;
  206.     P : PlineDesc;
  207.  
  208.   begin                      {EdMaktextdesc}
  209.  
  210.     if Ncols > Maxlinelength then begin
  211.       {Line too long}
  212.       EdErrormsg(41);
  213.       EdMaktextdesc := nil;
  214.       Exit;
  215.     end;
  216.  
  217.     {Calculate appropriate length of text buffer}
  218.     Len := EdBufferSize(Ncols);
  219.  
  220.     if not(EdMemAvail(Len+SizeOf(Linedesc), FreeListSpace)) then begin
  221.       {Heap space not available}
  222.       EdErrormsg(35);
  223.       EdMaktextdesc := nil;
  224.       Exit;
  225.     end;
  226.  
  227.     {Get linedesc first}
  228.     GetMem(P, SizeOf(Linedesc));
  229.  
  230.     with P^ do begin
  231.       {Now get the text buffer}
  232.       GetMem(Txt, Len);
  233.  
  234.       {Don't include leading junk byte in size of text buffer}
  235.       Bufflen := Pred(Len);
  236.  
  237.       {Fill line with blanks}
  238.       FillChar(Txt^, Len, Blank);
  239.  
  240.       {We don't yet know anything about its font}
  241.       Flags := NewAttr;
  242.       Font := 0;
  243.     end;
  244.  
  245.     EdMaktextdesc := P;
  246.  
  247.   end;                       {EdMaktextdesc}
  248.  
  249.   function EdSizeline(P : PlineDesc; Ncols : Integer; Init : Boolean) : Boolean;
  250.     {-Expand line size to accommodate Ncols characters}
  251.   var
  252.     Q : PtextLine;
  253.     Len, PbuffLen : Integer;
  254.  
  255.   begin                      {EdSizeline}
  256.  
  257.     PbuffLen := P^.Bufflen;
  258.  
  259.     if PbuffLen > Ncols then begin
  260.       {Get out quickly -- line is long enough}
  261.       EdSizeline := True;
  262.       Exit;
  263.     end;
  264.  
  265.     if Ncols > Maxlinelength then begin
  266.       {Line too long}
  267.       EdErrormsg(41);
  268.       EdSizeline := False;
  269.       Exit;
  270.     end;
  271.  
  272.     {Calculate appropriate length of text buffer}
  273.     Len := EdBufferSize(Ncols);
  274.  
  275.     if not(EdMemAvail(Len, FreeListSpace)) then begin
  276.       EdErrormsg(35);
  277.       EdSizeline := False;
  278.       Exit;
  279.     end;
  280.  
  281.     {Get a new larger text buffer}
  282.     GetMem(Q, Len);
  283.     if Init then begin
  284.       {Copy text buffer}
  285.       Move(P^.Txt^, Q^, Succ(PbuffLen));
  286.       {Blank out rest of line}
  287.       FillChar(Q^[Succ(PbuffLen)], Pred(Len-PbuffLen), Blank);
  288.     end;
  289.     {Get rid of old line buffer}
  290.     FreeMem(P^.Txt, Succ(PbuffLen));
  291.     {Attach new text buffer to line descriptor}
  292.     P^.Txt := Q;
  293.     {Don't include length byte in size}
  294.     P^.Bufflen := Pred(Len);
  295.  
  296.     EdSizeline := True;
  297.   end;                       {EdSizeline}
  298.  
  299.   function EdNewTextStream(W : Pwindesc) : Boolean;
  300.     {-Create a new text stream, returning true if successful}
  301.  
  302.   begin                      {EdNewTextStream}
  303.  
  304.     EdNewTextStream := False;
  305.     with W^ do begin
  306.       TopLine := EdMaktextdesc(1);
  307.       if EdPtrIsNil(TopLine) then
  308.         Exit;
  309.       Curline := TopLine;
  310.       Lineno := 1;
  311.       Colno := 1;
  312.       EdSetPtrNil(TopLine^.Fwdlink);
  313.       EdSetPtrNil(TopLine^.Backlink);
  314.       Stream := EdNewstream;
  315.     end;
  316.     EdNewTextStream := True;
  317.   end;                       {EdNewTextStream}
  318.  
  319.   function EdAllocateWindow(Top, Len, Cr, Cc : Integer; Fn : Filepath) : Pwindesc;
  320.     {-Return a pointer to a window structure}
  321.   var
  322.     W : Pwindesc;
  323.  
  324.   begin                      {EdAllocateWindow}
  325.     {Pop a window off the free list}
  326.     W := WinStack;
  327.     if EdNewTextStream(W) then begin
  328.       EdFwdPtr(WinStack);
  329.       {Initialize window settings}
  330.       EdInitWindowSettings(W);
  331.       with W^ do begin
  332.         EdSetPtrNil(Fwdlink);
  333.         EdSetPtrNil(Backlink);
  334.         Filename := Fn;
  335.         Firstlineno := Top;
  336.         Lastlineno := Pred(Top+Len);
  337.         Lineno := Cr;
  338.         Colno := Cc;
  339.       end;
  340.       EdSetTextNo(W);
  341.       EdAllocateWindow := W;
  342.     end else
  343.       EdAllocateWindow := nil;
  344.   end;                       {EdAllocateWindow}
  345.  
  346.   procedure EdJoinLinePrimitive(P : PlineDesc; LenP : Integer);
  347.     {-Join the line p at column lenP with the line following it}
  348.   var
  349.     LenQ, M : Integer;
  350.     Q : PlineDesc;
  351.  
  352.   begin                      {EdJoinLinePrimitive}
  353.  
  354.     Q := P^.Fwdlink;
  355.     if EdPtrIsNil(Q) then
  356.       Exit;
  357.  
  358.     {Get length of the next line}
  359.     LenQ := EdTextLength(Q);
  360.  
  361.     {Size up this line to hold the next}
  362.     if not(EdSizeline(P, LenP+LenQ, True)) then
  363.       Exit;
  364.  
  365.     {Fix up text markers}
  366.     if EdFlagSet(Q, InMark) then
  367.       for M := 0 to MaxMarker do
  368.         with Marker[M] do
  369.           if Line = Q then begin
  370.             Col := Col+LenP;
  371.             Line := P;
  372.             EdSetFlag(P, InMark);
  373.           end;
  374.  
  375.     {Move the text of the next into this one}
  376.     if LenQ > 0 then
  377.       Move(Q^.Txt^[1], P^.Txt^[Succ(LenP)], LenQ);
  378.  
  379.     {Disconnect the next line}
  380.     P^.Fwdlink := Q^.Fwdlink;
  381.     if EdPtrNotNil(P^.Fwdlink) then
  382.       P^.Fwdlink^.Backlink := P;
  383.  
  384.     {Deallocate next line's space}
  385.     EdDesTextDesc(Q);
  386.  
  387.   end;                       {EdJoinlineprimitive}
  388.  
  389.   procedure EdJoinline;
  390.     {-Join two lines and fix up block markers}
  391.   var
  392.     P, Q : PlineDesc;
  393.     C : Integer;
  394.  
  395.   begin                      {EdJoinline}
  396.     with Curwin^ do begin
  397.  
  398.       P := Curline;
  399.       Q := Curline^.Fwdlink;
  400.       C := Pred(Colno);
  401.  
  402.       if EdPtrNotNil(Q) then begin
  403.  
  404.         {Fix up block markers}
  405.         if Q = Blockfrom.Line then begin
  406.           Blockfrom.Col := Blockfrom.Col+C;
  407.           Blockfrom.Line := P;
  408.           if not(Blockhide) then
  409.             EdSetFlag(P, InBlock);
  410.         end;
  411.         if Q = Blockto.Line then begin
  412.           Blockto.Col := Blockto.Col+C;
  413.           Blockto.Line := P;
  414.         end;
  415.  
  416.         {Correct any windows whose topline, curline or lineno relate to q}
  417.         EdFixUpWindowSpan(Q);
  418.  
  419.         {Attach the next line to this one}
  420.         EdJoinLinePrimitive(P, C);
  421.  
  422.       end;
  423.     end;
  424.   end;                       {EdJoinline}
  425.  
  426.   procedure EdInsertLinePrimitive(M : BlockMarker; var P : PlineDesc);
  427.     {-Insert a new line after marker m, return pointer to new line}
  428.   var
  429.     Llen, Len : Integer;
  430.  
  431.   begin                      {EdInsertLinePrimitive}
  432.     with M do begin
  433.  
  434.       {Number of characters to copy from current line to new line}
  435.       Llen := EdTextLength(Line);
  436.       if Llen < Pred(Col) then
  437.         Len := 0
  438.       else
  439.         Len := Llen-Pred(Col);
  440.  
  441.       {Get a new buffer big enough to hold what's needed}
  442.       P := EdMaktextdesc(Len);
  443.       if EdPtrIsNil(P) then
  444.         Exit;
  445.  
  446.       {Attach the new buffer after the specified line}
  447.       EdLinkbuffer(Line, P);
  448.  
  449.       {Now split the text}
  450.       if Len > 0 then begin
  451.         Move(Line^.Txt^[Col], P^.Txt^[1], Len);
  452.         FillChar(Line^.Txt^[Col], Len, Blank)
  453.       end;
  454.  
  455.       {Fix up text markers}
  456.       if EdFlagSet(Line, InMark) then
  457.         EdFixMarkInsertedLine(Line, P, Col, Col);
  458.  
  459.     end;
  460.   end;                       {EdInsertLinePrimitive}
  461.  
  462.   function EdInsertSpace(P : PlineDesc; Start : Integer; Num : Integer) : Boolean;
  463.     {-Insert num spaces at position start of line p}
  464.   var
  465.     Len, NewLen : Integer;
  466.  
  467.   begin                      {EdInsertSpace}
  468.  
  469.     Len := EdTextLength(P);
  470.     if Start > Len then
  471.       NewLen := Succ(Start+Num)
  472.     else
  473.       NewLen := Succ(Len+Num);
  474.  
  475.     {Size up the line}
  476.     if not(EdSizeline(P, NewLen, True)) then begin
  477.       EdInsertSpace := False;
  478.       Exit;
  479.     end;
  480.  
  481.     {Move the text over and fill with blanks}
  482.     with P^ do begin
  483.       if Start <= Len then
  484.         Move(Txt^[Start], Txt^[Start+Num], Succ(Len-Start));
  485.       FillChar(Txt^[Start], Num, Blank);
  486.     end;
  487.  
  488.     {Fix up markers}
  489.     EdFixMarkInsertedSpace(P, Start, Num);
  490.     EdFixBlockInsertedSpace(P, Start, Num);
  491.  
  492.     EdInsertSpace := True;
  493.  
  494.   end;                       {EdInsertSpace}
  495.  
  496.   procedure EdNewLinePrimitive;
  497.     {-Insert a new line, straighten out indents and markers}
  498.   var
  499.     P : PlineDesc;
  500.     Ind, InsCount, SaveCol : Integer;
  501.     M : BlockMarker;
  502.  
  503.   begin                      {EdNewLinePrimitive}
  504.     with Curwin^ do begin
  505.  
  506.       M.Line := Curline;
  507.       M.Col := Colno;
  508.  
  509.       {Pagination must start over}
  510.       EdResetPageLine(Curwin);
  511.  
  512.       {Insert new line after current}
  513.       EdInsertLinePrimitive(M, P);
  514.       if EdPtrIsNil(P) then
  515.         Exit;
  516.  
  517.       {Clone attribute flags from current line to new}
  518.       if AT then
  519.         EdCloneAttrFlags(M.Line, P, M.Col);
  520.  
  521.       SaveCol := Colno;
  522.       InsCount := 0;
  523.       P := Curline;
  524.  
  525.       {Move to beginning of new line}
  526.       EdFwdPtr(Curline);
  527.       Colno := 1;
  528.  
  529.       if AI or WW then begin
  530.         {Autoindent mode or WordWrap with left margin support}
  531.  
  532.         if AI then
  533.           {Get leading spaces from previous line}
  534.           Ind := EdLineIndent(P)
  535.         else
  536.           Ind := 1;
  537.         if WW and (Ind <= Wmargin) then begin
  538.           Ind := Wmargin;
  539.           if SaveCol < Wmargin then
  540.             Ind := Ind-(Wmargin-SaveCol);
  541.         end;
  542.  
  543.         if Ind > 1 then begin
  544.  
  545.           {Insert spaces at start of curline}
  546.           InsCount := Pred(Ind);
  547.           if not(EdInsertSpace(Curline, 1, InsCount)) then
  548.             Exit;
  549.           Colno := Ind;
  550.  
  551.         end;
  552.       end;
  553.  
  554.       {Fix up block markers}
  555.       EdFixBlockInsertedLine(P, Curline, SaveCol, Pred(SaveCol-InsCount));
  556.  
  557.       Modified := True;
  558.  
  559.       {Guarantee a complete screen update}
  560.       Intrflag := NoInterr;
  561.  
  562.     end;
  563.   end;                       {EdNewLinePrimitive}
  564.  
  565.   procedure EdWindowCreate(Wno : Byte);
  566.     {-Create new window by splitting window wno in two}
  567.   var
  568.     W, V : Pwindesc;
  569.     CurrentSize, Size : Byte;
  570.  
  571.   begin                      {EdWindowCreate}
  572.  
  573.     {Get a pointer to the window to divide and compute the sizes}
  574.     W := EdFindWindesc(Wno);
  575.     with W^ do
  576.       CurrentSize := Succ(Lastlineno-Firstlineno);
  577.     Size := CurrentSize shr 1;
  578.  
  579.     if (Size <= MinWindowLines) then begin
  580.       {New window too small}
  581.       EdErrormsg(22);
  582.       Exit;
  583.     end;
  584.  
  585.     if (CurrentSize-Size) <= MinWindowLines then begin
  586.       {Not enough space left to fit on screen}
  587.       EdErrormsg(120);
  588.       Exit;
  589.     end;
  590.  
  591.     {Make a new window structure}
  592.     V := EdAllocateWindow(Succ(W^.Lastlineno-Size), Size, Line1, Col1, NoFile);
  593.  
  594.     if EdPtrIsNil(V) then
  595.       {No memory for another window, error already displayed}
  596.       Exit;
  597.  
  598.     {Compress existing window}
  599.     W^.Lastlineno := W^.Lastlineno-Size;
  600.  
  601.     {We may be positioned outside the window's area now}
  602.     EdBackupCurline(W);
  603.  
  604.     {New window is linked AFTER wno in the display list}
  605.     V^.Backlink := W;
  606.     V^.Fwdlink := W^.Fwdlink;
  607.     W^.Fwdlink^.Backlink := V;
  608.     W^.Fwdlink := V;
  609.  
  610.   end;                       {EdWindowCreate}
  611.  
  612.   procedure EdPushWindowStack(W : Pwindesc);
  613.     {-Put a window descriptor on the window free list}
  614.  
  615.   begin                      {EdPushWindowStack}
  616.     W^.Fwdlink^.Backlink := W^.Backlink;
  617.     W^.Backlink^.Fwdlink := W^.Fwdlink;
  618.     W^.Fwdlink := WinStack;
  619.     WinStack := W;
  620.   end;                       {EdPushWindowStack}
  621.  
  622.   procedure EdWindowDelete(Wno : Byte);
  623.     {-Remove window from memory}
  624.   var
  625.     W : Pwindesc;
  626.  
  627.   begin                      {EdWindowDelete}
  628.  
  629.     {Find window descriptor}
  630.     W := EdFindWindesc(Wno);
  631.  
  632.     if W = Window1 then begin
  633.  
  634.       {Window below gets the lines}
  635.       EdFwdPtr(Window1);
  636.       if Curwin = W then
  637.         Curwin := Window1;
  638.       Window1^.Firstlineno := W^.Firstlineno;
  639.       EdSetTextNo(Window1);
  640.  
  641.     end else begin
  642.  
  643.       {Window above gets the lines}
  644.       if Curwin = W then
  645.         Curwin := W^.Backlink;
  646.       W^.Backlink^.Lastlineno := W^.Lastlineno;
  647.  
  648.     end;
  649.  
  650.     {If no other object references the text stream, it may be deleted}
  651.     if not(EdLinkedWindow(W)) then
  652.       EdDeleteAllText(W);
  653.  
  654.     {Push window onto free list}
  655.     EdPushWindowStack(W);
  656.  
  657.   end;                       {EdWindowDelete}
  658.  
  659.   procedure EdResetWindow(W : Pwindesc);
  660.     {-Reset the window descriptor}
  661.  
  662.   begin                      {EdResetWindow}
  663.     EdInitWindowSettings(W);
  664.     with W^ do begin
  665.       {Reset top line buffer for the current window}
  666.       if EdPtrNotNil(TopLine) then
  667.         EdDesTextDesc(TopLine);
  668.       TopLine := EdMaktextdesc(1);
  669.       if EdPtrNotNil(TopLine) then begin
  670.         EdSetPtrNil(TopLine^.Fwdlink);
  671.         EdSetPtrNil(TopLine^.Backlink);
  672.       end;
  673.     end;
  674.     EdSetTextNo(W);
  675.     EdResetWindowPrimitive(W);
  676.   end;                       {EdResetWindow}
  677.  
  678.   function EdCalcMemory : VarString;
  679.     {-Return the bytes of available heap space, in a string}
  680.   var
  681.     M : LongInt;
  682.     S : VarString;
  683.  
  684.   begin                      {EdCalcMemory}
  685.     M := MemAvail;
  686.     Str(M, S);
  687.     EdCalcMemory := Blank+S+EdGetMessage(328);
  688.   end;                       {EdCalcMemory}
  689.  
  690. begin
  691.   {Use ExactAllocation only during file reads}
  692.   ExactAllocation := False;
  693.  
  694.   {Allocate current line buffer}
  695.   CurlineBuf := EdMaktextdesc(Maxlinelength);
  696.   Curlinecol := 1;
  697. end.
  698.