home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / tptools.zip / FIRSTED.ZIP / EDBLOK.PAS < prev    next >
Pascal/Delphi Source File  |  1987-12-21  |  15KB  |  538 lines

  1. {                          EDBLOK.PAS
  2.                              ED 4.0
  3.              Copyright (c) 1985, 87 by Borland International, Inc.            }
  4.  
  5. {$I eddirect.inc}
  6.  
  7. unit EdBlok;
  8.   {-Block move, copy and delete}
  9.  
  10. interface
  11.  
  12. uses
  13.   crt,                       {Basic video operations - standard unit}
  14.   Dos,                       {DOS calls - standard unit}
  15.   Errors,                    {Runtime error handler}
  16.   EdVars,                    {Global types and declarations}
  17.   EdScrn1,                   {Fast screen writing routines}
  18.   EdString,                  {String primitives}
  19.   EdPtrOp,                   {Primitive pointer operations}
  20.   EdCmds,                    {Maps keystrokes to commands}
  21.   int24,                     {DOS critical error handler}
  22.   Message,                   {Message system}
  23.   EdUser,                    {User keyboard input, line editing and error reporting}
  24.   EdMemOp,                   {Text buffer allocation and deallocation}
  25.   EdBack,                    {Background processes}
  26.   EdScrn2,                   {Editor screen updating}
  27.   EdEdit;                    {Basic editing commands}
  28.  
  29.  
  30. procedure EdBlockMove;
  31.   {-Process move block command}
  32.  
  33. procedure EdBlockCopy;
  34.   {-Process copy block command}
  35.  
  36. procedure EdBlockDelete;
  37.   {-Process delete block command}
  38.  
  39.   {==========================================================================}
  40.  
  41. implementation
  42.  
  43.   procedure EdBlockCleanup;
  44.     {-Reset markers and generally clean up when done with a block operation}
  45.  
  46.   begin                      {EdBlockCleanup}
  47.     CurWin^.Modified := True;
  48.     EdJumpMarker(Blockfrom);
  49.     EdRealign;
  50.     EdOffblock;
  51.     Blockhide := False;
  52.   end;                       {EdBlockCleanup}
  53.  
  54.   {***}
  55.   procedure EdBlockMove;
  56.     {-Process move block command}
  57.   var
  58.     WindFrom : PwinDesc;
  59.     F, T, C : BlockMarker;
  60.     Cline, fRight, Tright, Cright : PlineDesc;
  61.     M, ColFrom, ColTo, ColPos, NewColFrom, NewColTo : Integer;
  62.  
  63.   begin                      {EdBlockMove}
  64.  
  65.     {A block must be defined and unhidden}
  66.     if EdNoBlock then
  67.       Exit;
  68.  
  69.     {Don't allow the cursor within the block}
  70.     if EdCursorInBlock(CurWin^.CurLine, CurWin^.ColNo, False) then
  71.       Exit;
  72.  
  73.     {Provide some temporary margin for the move, which overall conserves memory}
  74.     FreeListSpace := FreeListPerm-(MaxLineLength shl 2);
  75.  
  76.     if (Blockfrom.Line = Blockto.Line) and (CurWin^.CurLine = Blockfrom.Line) then begin
  77.  
  78.       {Move within a single line is special case}
  79.  
  80.       {Temporary variables}
  81.       ColFrom := Blockfrom.Col;
  82.       ColTo := Blockto.Col;
  83.       ColPos := CurWin^.ColNo;
  84.       Cline := CurWin^.CurLine;
  85.  
  86.       with Cline^ do begin
  87.  
  88.         if ColPos >= Bufflen then
  89.           {Size up line}
  90.           if not(EdSizeline(Cline, Succ(ColPos), True)) then begin
  91.             {Insufficient memory - should be impossible to reach here}
  92.             FreeListSpace := FreeListPerm;
  93.             Exit;
  94.           end;
  95.  
  96.         {Initialize buffer}
  97.         Move(Txt^[1], WorkBuf[1], Bufflen);
  98.  
  99.         if ColPos < ColFrom then begin
  100.  
  101.           {Cursor to left of marked block}
  102.           Move(Txt^[ColFrom], WorkBuf[ColPos], ColTo-ColFrom);
  103.           Move(Txt^[ColPos], WorkBuf[ColPos+ColTo-ColFrom], ColFrom-ColPos);
  104.           NewColFrom := ColPos;
  105.           NewColTo := ColPos+ColTo-ColFrom;
  106.  
  107.         end else begin
  108.  
  109.           {Cursor to right of marked block}
  110.           Move(Txt^[ColTo], WorkBuf[ColFrom], ColPos-ColTo);
  111.           Move(Txt^[ColFrom], WorkBuf[ColFrom+ColPos-ColTo], ColTo-ColFrom);
  112.           NewColFrom := ColFrom+ColPos-ColTo;
  113.           NewColTo := ColPos;
  114.  
  115.         end;
  116.  
  117.         {Copy buffer to current}
  118.         Move(WorkBuf[1], Txt^[1], Bufflen);
  119.  
  120.       end;
  121.  
  122.       {Save new block pointers}
  123.       Blockfrom.Col := NewColFrom;
  124.       Blockto.Col := NewColTo;
  125.  
  126.       {Fix up text markers}
  127.       if EdFlagSet(Cline, InMark) then
  128.         for M := 0 to MaxMarker do
  129.           with Marker[M] do
  130.             if Line = Cline then
  131.               if ColPos < ColFrom then begin
  132.                 if (Col >= ColPos) and (Col < ColFrom) then
  133.                   Col := Col+ColTo-ColFrom
  134.                 else if (Col >= ColFrom) and (Col < ColTo) then
  135.                   Col := Col-ColFrom+ColPos;
  136.               end else begin
  137.                 if (Col >= ColFrom) and (Col < ColTo) then
  138.                   Col := Col+ColPos-ColTo
  139.                 else if (Col >= ColTo) and (Col < ColPos) then
  140.                   Col := Col+ColFrom-ColTo;
  141.               end;
  142.  
  143.     end else begin
  144.  
  145.       {Move from one line to another}
  146.  
  147.       {Store temporary markers}
  148.       F := Blockfrom;
  149.       T := Blockto;
  150.       with C, CurWin^ do begin
  151.         Line := CurLine;
  152.         Col := ColNo;
  153.       end;
  154.  
  155.       {Determine whether all of any window topline or curline is in marked block}
  156.       WindFrom := EdFindWindow(Blockfrom.Line);
  157.       WindFrom^.Modified := True;
  158.       EdFixBaseLine(WindFrom);
  159.  
  160.       {Insert line breaks at the three markers}
  161.       {ORDER is IMPORTANT}
  162.       if C.Line = T.Line then
  163.         EdInsertLinePrimitive(C, Cright);
  164.       EdInsertLinePrimitive(T, Tright);
  165.       EdInsertLinePrimitive(F, fRight);
  166.       if C.Line <> T.Line then
  167.         EdInsertLinePrimitive(C, Cright);
  168.  
  169.       {Splice}
  170.       if T.Line = F.Line then begin
  171.         {Block contained within single line}
  172.         fRight^.FwdLink := Cright;
  173.         EdJoinLinePrimitive(fRight, T.Col-F.Col);
  174.       end else begin
  175.         {Multiline block}
  176.         T.Line^.FwdLink := Cright;
  177.         EdJoinLinePrimitive(T.Line, Pred(T.Col));
  178.       end;
  179.  
  180.       if T.Line = C.Line then begin
  181.         {Cursor on same line as end of block}
  182.         Tright^.FwdLink := fRight;
  183.         EdJoinLinePrimitive(Tright, C.Col-T.Col);
  184.       end else begin
  185.         C.Line^.FwdLink := fRight;
  186.         EdJoinLinePrimitive(C.Line, Pred(C.Col));
  187.       end;
  188.  
  189.       if F.Line = C.Line then begin
  190.         {Cursor on same line as begin of block}
  191.         T.Line^.FwdLink := Tright;
  192.         EdJoinLinePrimitive(T.Line, Pred(T.Col+F.Col-C.Col));
  193.       end else begin
  194.         F.Line^.FwdLink := Tright;
  195.         EdJoinLinePrimitive(F.Line, Pred(F.Col));
  196.       end;
  197.  
  198.       {Set block markers again}
  199.       if T.Line = C.Line then begin
  200.         Blockfrom.Line := F.Line;
  201.         Blockfrom.Col := F.Col+C.Col-T.Col;
  202.       end else
  203.         Blockfrom := C;
  204.  
  205.       if F.Line = T.Line then begin
  206.         Blockto.Line := C.Line;
  207.         Blockto.Col := C.Col+T.Col-F.Col;
  208.       end else
  209.         Blockto := T;
  210.  
  211.     end;
  212.  
  213.     EdBlockCleanup;
  214.  
  215.   end;                       {EdBlockMove}
  216.  
  217.   {***}
  218.   procedure EdBlockCopy;
  219.     {-Process copy block command}
  220.   var
  221.     C : BlockMarker;
  222.     Cline, Cright, P, Q, B, F, T : PlineDesc;
  223.     M, ColPos, ColFrom, ColTo, Blen : Integer;
  224.     Done : Boolean;
  225.  
  226.   begin                      {EdBlockCopy}
  227.  
  228.     {A block must be defined and visible}
  229.     if EdNoBlock then
  230.       Exit;
  231.  
  232.     {Don't allow cursor within block}
  233.     if EdCursorInBlock(CurWin^.CurLine, CurWin^.ColNo, True) then
  234.       Exit;
  235.  
  236.     Cline := CurWin^.CurLine;
  237.     ColPos := CurWin^.ColNo;
  238.     with C do begin
  239.       Line := Cline;
  240.       Col := ColPos;
  241.     end;
  242.     ColFrom := Blockfrom.Col;
  243.     ColTo := Blockto.Col;
  244.     F := Blockfrom.Line;
  245.     T := Blockto.Line;
  246.  
  247.     if (F = T) and (Cline = F) then begin
  248.  
  249.       {Copy within a single line is special case}
  250.       with Cline^ do begin
  251.  
  252.         {Size up current line}
  253.         if ColPos > Bufflen then
  254.           Blen := ColPos
  255.         else
  256.           Blen := Bufflen;
  257.  
  258.         if not(EdSizeline(Cline, Succ(Blen+ColTo-ColFrom), True)) then
  259.           Exit;
  260.  
  261.         {Initialize buffer}
  262.         Move(Txt^[1], WorkBuf[1], Bufflen);
  263.  
  264.         {Copy the appropriate text}
  265.         Move(Txt^[ColFrom], WorkBuf[ColPos], ColTo-ColFrom);
  266.         if Blen <> ColPos then
  267.           Move(Txt^[ColPos], WorkBuf[ColPos+ColTo-ColFrom], Succ(Blen-ColPos));
  268.  
  269.         {Copy buffer to current}
  270.         Move(WorkBuf[1], Txt^[1], Bufflen);
  271.  
  272.       end;
  273.  
  274.       {Save new block markers}
  275.       Blockfrom.Col := ColPos;
  276.       Blockto.Col := ColPos+ColTo-ColFrom;
  277.  
  278.       {Fix up text markers}
  279.       if EdFlagSet(Cline, InMark) then
  280.         for M := 0 to MaxMarker do
  281.           with Marker[M] do
  282.             if Line = Cline then
  283.               if (Col >= ColPos) then
  284.                 Col := Col+ColTo-ColFrom;
  285.  
  286.     end else begin
  287.  
  288.       {Reduce available memory so we have something left to link with}
  289.       FreeListSpace := FreeListPerm+(MaxLineLength shl 1);
  290.  
  291.       {Break at the cursor position}
  292.       EdInsertLinePrimitive(C, Cright);
  293.       if GotError then begin
  294.         FreeListSpace := FreeListPerm;
  295.         Exit;
  296.       end;
  297.  
  298.       {P will track the source text}
  299.       if Cline = Blockfrom.Line then
  300.         P := Cright
  301.       else
  302.         P := Blockfrom.Line;
  303.  
  304.       {Q will track the destination text}
  305.       Q := Cline;
  306.  
  307.       Done := False;
  308.  
  309.       repeat
  310.  
  311.         if (P = F) then begin
  312.  
  313.           if (P = T) then begin
  314.  
  315.             {Current source line contains begin and end of block}
  316.             Blen := ColTo-ColFrom;
  317.             B := EdMaktextdesc(Blen);
  318.             if EdPtrNotNil(B) then begin
  319.               {Copy text into buffer}
  320.               Move(P^.Txt^[ColFrom], B^.Txt^[1], Blen);
  321.               {Force exit for last line of block}
  322.               Done := True;
  323.             end;
  324.  
  325.           end else begin
  326.  
  327.             {First line of block}
  328.             Blen := Succ(P^.Bufflen-ColFrom);
  329.             B := EdMaktextdesc(Blen);
  330.             if EdPtrNotNil(B) then begin
  331.               {Copy text into buffer}
  332.               Move(P^.Txt^[ColFrom], B^.Txt^[1], Blen);
  333.               EdFwdPtr(P);
  334.             end;
  335.  
  336.           end;
  337.  
  338.         end else if (P = T) then begin
  339.  
  340.           {Last line of block}
  341.           Blen := Pred(ColTo);
  342.           B := EdMaktextdesc(Blen);
  343.           if EdPtrNotNil(B) then begin
  344.             {Copy text into buffer}
  345.             if Blen > 0 then
  346.               Move(P^.Txt^[1], B^.Txt^[1], Blen);
  347.             {Force exit}
  348.             Done := True;
  349.           end;
  350.  
  351.         end else begin
  352.  
  353.           {Middle of block}
  354.           Blen := P^.Bufflen;
  355.           B := EdMaktextdesc(Blen);
  356.           if EdPtrNotNil(B) then begin
  357.             {Copy text into buffer}
  358.             Move(P^.Txt^[1], B^.Txt^[1], Blen);
  359.             EdFwdPtr(P);
  360.           end;
  361.  
  362.         end;
  363.  
  364.         if EdPtrIsNil(B) then begin
  365.  
  366.           {Out of memory error already reported}
  367.           {Move b back to previous success and go on to the relink step}
  368.           B := Q;
  369.           Blen := Succ(EdTextLength(B));
  370.           {Correct blockto marker for as far as we got}
  371.           Blockto.Col := Blen;
  372.           Done := True;
  373.           GotError := False;
  374.  
  375.         end else begin
  376.  
  377.           {Insert buffer between current q and cright}
  378.           Q^.FwdLink := B;
  379.           B^.Backlink := Q;
  380.           B^.FwdLink := Cright;
  381.           Cright^.Backlink := B;
  382.  
  383.           {Move q forward to b so that next line is inserted after b}
  384.           Q := B;
  385.  
  386.         end;
  387.  
  388.       until Done;            {Loop through all lines of block}
  389.  
  390.       {Get stack space back so we have room to link up}
  391.       FreeListSpace := FreeListPerm;
  392.  
  393.       {Join at begin and end}
  394.  
  395.       {Join right part of original current line to last buffer}
  396.       EdJoinLinePrimitive(B, Blen);
  397.       if GotError then begin
  398.         EdBlockCleanup;
  399.         Exit;
  400.       end;
  401.  
  402.       {Join first buffer to left part of current line}
  403.       EdJoinLinePrimitive(Cline, Pred(ColPos));
  404.       if GotError then begin
  405.         EdBlockCleanup;
  406.         Exit;
  407.       end;
  408.  
  409.       {Set block markers}
  410.       if F = T then begin
  411.         {Original block contained in a single line}
  412.         Blockto.Line := Cline;
  413.         Blockto.Col := ColPos+Blen;
  414.       end else
  415.         Blockto.Line := B;
  416.       Blockfrom.Line := Cline;
  417.       Blockfrom.Col := ColPos;
  418.  
  419.     end;
  420.  
  421.     EdBlockCleanup;
  422.  
  423.   end;                       {EdBlockCopy}
  424.  
  425.   {***}
  426.   procedure EdBlockDelete;
  427.     {-Process delete block command}
  428.   var
  429.     WindFrom : PwinDesc;
  430.     P, Q, Tright, fRight : PlineDesc;
  431.     C : BlockMarker;
  432.     M, ColFrom, ColTo, Blen : Integer;
  433.  
  434.   begin                      {EdBlockDelete}
  435.  
  436.     {A block must be defined and not hidden}
  437.     if EdNoBlock then
  438.       Exit;
  439.  
  440.     ColFrom := Blockfrom.Col;
  441.     ColTo := Blockto.Col;
  442.     WindFrom := EdFindWindow(Blockfrom.Line);
  443.  
  444.     {Determine whether all of any window topline or curline is in marked block}
  445.     EdFixBaseLine(WindFrom);
  446.  
  447.     {Special case when block is within a single line}
  448.     if (Blockfrom.Line = Blockto.Line) then begin
  449.  
  450.       P := Blockfrom.Line;
  451.       Blen := EdTextLength(P);
  452.  
  453.       with P^ do begin
  454.  
  455.         {Initialize buffer}
  456.         Move(Txt^[1], WorkBuf[1], Bufflen);
  457.  
  458.         {Remove characters and right pad with blanks}
  459.         if ColTo <= Blen then
  460.           Move(Txt^[ColTo], WorkBuf[ColFrom], Succ(Blen-ColTo));
  461.         FillChar(WorkBuf[ColFrom+Succ(Blen-ColTo)], (ColTo-ColFrom), Blank);
  462.  
  463.         {Copy buffer to current}
  464.         Move(WorkBuf[1], Txt^[1], Bufflen);
  465.  
  466.       end;
  467.  
  468.       {Correct cursor}
  469.       if CurWin^.CurLine = Blockfrom.Line then
  470.         CurWin^.ColNo := Blockfrom.Col;
  471.  
  472.       {Fix up text markers}
  473.       if EdFlagSet(P, InMark) then
  474.         for M := 0 to MaxMarker do
  475.           with Marker[M] do
  476.             if Line = P then
  477.               if (Col >= ColTo) then
  478.                 Col := Col-ColTo+ColFrom
  479.               else if (Col >= ColFrom) then
  480.                 EdSetPtrNil(Line);
  481.  
  482.     end else begin
  483.  
  484.       {Store temporary marker}
  485.       with C do begin
  486.         Line := CurWin^.CurLine;
  487.         Col := CurWin^.ColNo;
  488.       end;
  489.  
  490.       {Provide some memory margin to get started deleting}
  491.       FreeListSpace := FreeListPerm-(MaxLineLength shl 1);
  492.  
  493.       {Inserting line breaks before and after block}
  494.       EdInsertLinePrimitive(Blockfrom, fRight);
  495.       if GotError then begin
  496.         FreeListSpace := FreeListPerm;
  497.         Exit;
  498.       end;
  499.       EdInsertLinePrimitive(Blockto, Tright);
  500.       if GotError then begin
  501.         FreeListSpace := FreeListPerm;
  502.         Exit;
  503.       end;
  504.  
  505.       {Now scan and delete all lines in the block}
  506.       P := fRight;
  507.       repeat
  508.  
  509.         {Get the forward link now. push to undo destroys it}
  510.         Q := P^.FwdLink;
  511.  
  512.         {Put line on undo stack if possible}
  513.         EdPushUndo(P);
  514.  
  515.         P := Q;
  516.  
  517.       until P = Tright;
  518.  
  519.       {Splice blockfrom to tright}
  520.       Blockfrom.Line^.FwdLink := Tright;
  521.       EdJoinLinePrimitive(Blockfrom.Line, Pred(Blockfrom.Col));
  522.  
  523.       FreeListSpace := FreeListPerm;
  524.       EdRealign;
  525.       EdJumpMarker(C);
  526.  
  527.     end;
  528.  
  529.     WindFrom^.Modified := True;
  530.     {Indicate that markers are gone}
  531.     EdSetPtrNil(Blockto.Line);
  532.     EdOffblock;
  533.     Blockhide := True;
  534.  
  535.   end;                       {EdBlockDelete}
  536.  
  537. end.
  538.