home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
tptools.zip
/
FIRSTED.ZIP
/
EDPTROP.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-12-21
|
34KB
|
1,183 lines
{ EDPTROP.PAS
ED 4.0
Copyright (c) 1985, 87 by Borland International, Inc. }
{$I eddirect.inc}
unit EdPtrOp;
{-Low level pointer operations for the Toolbox architecture}
interface
uses
Dos, {DOS calls - standard unit}
Errors, {Runtime error handler}
EdVars; {Global types and declarations}
{----------- Primitive operations}
function EdMemAvail(Size, Margin : Word) : Boolean;
{-Return true if enough contiguous memory exists on heap}
procedure EdFwdPtr(var P);
{-Change p (Plinedesc or Pwindesc) to its forward link}
procedure EdBackPtr(var P);
{-Change p (Plinedesc or Pwindesc) to its backward link}
function EdPtrIsNil(var P) : Boolean;
{-Return true if pointer p is nil}
function EdPtrNotNil(var P) : Boolean;
{-Return true if pointer p is not nil}
procedure EdSetPtrNil(var P);
{-Initialize pointer p to nil}
procedure EdToggleBoolean(var B : Boolean);
{-Toggle a boolean}
{----------- Line oriented operations}
function EdTopofStream(W : PwinDesc) : PlineDesc;
{-Return pointer to first line in stream}
function EdTextLength(P : PlineDesc) : Integer;
{-Return the length of line text, 0 if all blank}
function EdLineIndent(P : PlineDesc) : Integer;
{-Return the indent of the specified line, 0 if line is empty}
procedure EdClrFlag(P : PlineDesc; Mask : Word);
{-Clear the line flag}
procedure EdSetFlag(P : PlineDesc; Mask : Word);
{-Set the line flag}
function EdFlagSet(P : PlineDesc; Mask : Word) : Boolean;
{-Return True if the mask flag is set for line p}
procedure EdChangeFlag(P : PlineDesc; FlagVal : Boolean; FlagPos : Word);
{-Change a line flag, setting UpdateScreen if change encountered}
procedure EdToggleTextMarker;
{-Toggle visibility of text markers}
procedure EdFixBlockInsertedSpace(P : PlineDesc; Start : Integer; Num : Integer);
{-Fix up block markers after blank space is inserted}
procedure EdFixMarkInsertedSpace(P : PlineDesc; Start : Integer; Num : Integer);
{-Fix up text markers after space is inserted in a line}
procedure EdFixBlockInsertedLine(ThisL, NextL : PlineDesc;
BreakCol : Integer;
Delta : Integer);
{-Fix up block markers after a line is inserted}
procedure EdFixMarkInsertedLine(ThisL, NextL : PlineDesc;
BreakCol : Integer;
Delta : Integer);
{-Fix up text markers after a new line is inserted}
procedure EdLinkbuffer(P, Q : PlineDesc);
{-Link line q after line p}
procedure EdBufferCurrentLine;
{-Keep an extra image of current line to allow restore via ^QL}
procedure EdBackupCurline(W : PwinDesc);
{-Move up curline as needed to fit into smaller window}
procedure EdMoveCursorIntoLine;
{-Set current column within line buffer}
procedure EdGotoColumn(Cno : Integer);
{-Go to column cno on current line}
procedure EdGotoLine(Lno : Integer);
{-Go to line lno of current window}
procedure EdWindowTopFile;
{-Go to top of window}
procedure EdTopScreen;
{-Move cursor to top of screen}
procedure EdBottomScreen;
{-Move cursor to bottom of screen}
procedure EdWindowGoto(Wno : Byte);
{-Move cursor into window Wno, counted from top of screen}
{----------- Window oriented operations}
function EdFindWindow(T : PlineDesc) : PwinDesc;
{-Return the window containing the designated line}
function EdFindWindesc(Wno : Byte) : PwinDesc;
{-return a window descriptor for a window number}
function EdWindowNumber : Byte;
{-Return the window number of the current window}
function EdGetWindowToDivide : Byte;
{-Return best window number to split in order to create a new window}
procedure EdWindowUp;
{-Process up window command}
procedure EdWindowDown;
{-Process down window command}
procedure EdRealign;
{-Realign windows over text streams}
procedure EdFixUpWindowSpan(P : PlineDesc);
{-When p is to be deleted, first fix up any other structures pointing to p}
procedure EdSetTextNo(W : PwinDesc);
{-Set the FirstTextNo of a window}
function EdLinkedWindow(W : PwinDesc) : Boolean;
{-return true if a window is linked to any others}
function EdNewstream : Word;
{-Return unique text stream identifier}
procedure EdChangeStreamName(Fname : Filepath);
{-Change name of current stream to fname}
procedure EdInitWindowSettings(W : PwinDesc);
{-Set window parameters to defaults}
{----------- Block oriented operations}
function EdCursorInBlock(Q : PlineDesc; C : Integer; EndMarkOk : Boolean) : Boolean;
{-Return true if position q:c is in block}
function EdNoBlock : Boolean;
{-Return True if no block is marked and visible}
procedure EdOffblock;
{-Turn off Inblock bits for every text line in the system}
procedure EdCheckNoMarker;
{-If deletion operation has deleted all marked text, remove block markers altogether}
procedure EdBlockHide;
{-Toggle block display}
procedure EdFixBaseLine(WindFrom : PwinDesc);
{-Redefine window Topline and Curline before a block operation deletes them}
procedure EdBlockBegin;
{-Set block begin marker}
procedure EdBlockEnd;
{-Set block end marker}
procedure EdBlockWord;
{-Mark the current word as a block}
{==========================================================================}
implementation
var
NextStream : Word; {Next stream ID to be assigned}
{$L EDPTROP}
{$F+}
function EdGetEol(var Buf; C : Integer) : Integer; external;
{-Find end of a text buffer. Local to the unit, but called FAR.}
{$F-}
function EdPtrDiff(HighPt, LowPt : Pointer) : LongInt;
{-Return the number of bytes between point highpt^ and point lowpt^}
var
HighVal, LowVal : LongInt;
begin {EdPtrDiff}
HighVal := LongInt(Seg(HighPt^)) shl 4+LongInt(Ofs(HighPt^));
LowVal := LongInt(Seg(LowPt^)) shl 4+LongInt(Ofs(LowPt^));
EdPtrDiff := HighVal-LowVal;
end; {EdPtrDiff}
function EdHeapEnd : Pointer;
{-Return the last available location for the heap in a normalized pointer}
begin {EdHeapEnd}
if Ofs(FreePtr^) = 0 then
{Free list is empty}
EdHeapEnd := Ptr(Seg(FreePtr^)+$1000, 0)
else
EdHeapEnd := Ptr(Seg(FreePtr^)+Ofs(FreePtr^) shr 4, 0);
end; {EdHeapEnd}
function EdMemAvail(Size, Margin : Word) : Boolean;
{-Return true if enough contiguous memory exists on heap}
var
HighestHeapEnd, SaveHeapPtr : Pointer;
begin {EdMemAvail}
{Compute highest heap end based on current freelist buffer size}
HighestHeapEnd := Ptr(Seg(FreePtr^)+$1000-Succ(Margin shr 4), 0);
{Compare to actual freelist size}
if EdPtrDiff(HighestHeapEnd, EdHeapEnd) > 0 then
{Actual free list is bigger than buffer we guarantee}
HighestHeapEnd := EdHeapEnd;
if EdPtrDiff(HighestHeapEnd, HeapPtr) > Size then
{There is space at the top of the heap for the request}
EdMemAvail := True
else begin
{Temporarily ignore whatever space is at the top of heap}
SaveHeapPtr := HeapPtr;
HeapPtr := EdHeapEnd;
{Check the largest piece in the fragmented heap}
EdMemAvail := (Size < MaxAvail);
HeapPtr := SaveHeapPtr;
end;
end; {EdMemAvail}
procedure EdFwdPtr(var P);
{-Change p (Plinedesc or Pwindesc) to its forward link}
var
Pl : PlineDesc absolute P;
begin {EdFwdPtr}
Pl := Pl^.FwdLink;
end; {EdFwdPtr}
procedure EdBackPtr(var P);
{-Change p (Plinedesc or Pwindesc) to its backward link}
var
Pl : PlineDesc absolute P;
begin {EdBackPtr}
Pl := Pl^.Backlink;
end; {EdBackPtr}
function EdPtrIsNil(var P) : Boolean;
{-Return true if pointer p is nil}
var
Pl : PlineDesc absolute P;
begin {EdPtrIsNil}
EdPtrIsNil := (Pl = nil);
end; {EdPtrIsNil}
function EdPtrNotNil(var P) : Boolean;
{-Return true if pointer p is not nil}
var
Pl : PlineDesc absolute P;
begin {EdPtrNotNil}
EdPtrNotNil := (Pl <> nil);
end; {EdPtrNotNil}
procedure EdSetPtrNil(var P);
{-Initialize pointer p to nil}
var
Pl : PlineDesc absolute P;
begin {EdSetPtrNil}
Pl := nil;
end; {EdSetPtrNil}
procedure EdToggleBoolean(var B : Boolean);
{-Toggle a boolean}
begin {EdToggleBoolean}
B := not(B);
end; {EdToggleBoolean}
function EdTopofStream(W : PwinDesc) : PlineDesc;
{-Return pointer to first line in stream}
var
P : PlineDesc;
begin {EdTopofStream}
with W^ do
P := TopLine;
while EdPtrNotNil(P^.Backlink) do
EdBackPtr(P);
EdTopofStream := P;
end; {EdTopofStream}
function EdFindWindow(T : PlineDesc) : PwinDesc;
{-Return the window containing the designated line}
var
P : PlineDesc;
W : PwinDesc;
Found : Boolean;
function EdSearchBack(T, P : PlineDesc) : Boolean;
{-Starting at line p, search to top of stream for target line t}
begin {EdSearchBack}
EdSearchBack := False;
while EdPtrNotNil(P) do
if P = T then begin
{Found target line}
EdSearchBack := True;
Exit;
end else
EdBackPtr(P);
end; {EdSearchBack}
function EdSearchFwd(T, P : PlineDesc) : Boolean;
{-Starting at line p, search to bottom of stream for target line t}
begin {EdSearchFwd}
EdSearchFwd := False;
while EdPtrNotNil(P) do
if P = T then begin
{Found target line}
EdSearchFwd := True;
Exit;
end else
EdFwdPtr(P);
end; {EdSearchFwd}
begin {EdFindWindow}
W := CurWin;
repeat
P := W^.TopLine;
Found := EdSearchFwd(T, P);
if not(Found) then
Found := EdSearchBack(T, P);
if Found then begin
EdFindWindow := W;
Exit;
end;
EdFwdPtr(W);
until W = CurWin;
{Window not found}
EdFindWindow := nil;
end; {EdFindWindow}
function EdFindWindesc(Wno : Byte) : PwinDesc;
{-return a window descriptor for a window number}
var
W : PwinDesc;
I : Integer;
begin {EdFindWindesc}
W := Window1;
I := 1;
while I < Wno do begin
EdFwdPtr(W);
Inc(I);
end;
EdFindWindesc := W;
end; {EdFindWindesc}
function EdWindowNumber : Byte;
{-Return the window number of the current window}
var
W : PwinDesc;
I : Integer;
begin {EdWindowNumber}
W := Window1;
I := 1;
while W <> CurWin do begin
EdFwdPtr(W);
Inc(I);
end;
EdWindowNumber := I;
end; {EdWindowNumber}
function EdGetWindowToDivide : Byte;
{-Return best window number to split in order to create a new window}
var
W : PwinDesc;
Wno : Integer;
begin {EdGetWindowToDivide}
{Assume current window by default}
EdGetWindowToDivide := EdWindowNumber;
{See if current window is OK to divide}
with CurWin^ do
if (LastLineNo-FirstLineNo) > (MinWindowLines shl 1) then
Exit;
{Start at top of screen and try the other windows}
W := Window1;
Wno := 1;
repeat
with W^ do
if (LastLineNo-FirstLineNo) > (MinWindowLines shl 1) then begin
EdGetWindowToDivide := Wno;
Exit;
end;
EdFwdPtr(W);
Inc(Wno);
until W = Window1;
end; {EdGetWindowToDivide}
{***}
procedure EdWindowUp;
{-Process up window command}
begin {EdWindowUp}
EdBackPtr(CurWin);
end; {EdWindowUp}
{***}
procedure EdWindowDown;
{-Process down window command}
begin {EdWindowDown}
EdFwdPtr(CurWin);
end; {EdWindowDown}
function EdCursorInBlock(Q : PlineDesc; C : Integer; EndMarkOk : Boolean) : Boolean;
{-Return true if position q:c is in block}
var
P : PlineDesc;
F, T : Integer;
MnOk : Boolean;
begin {EdCursorInBlock}
EdCursorInBlock := False;
P := Blockfrom.Line;
T := Blockto.Col;
F := Blockfrom.Col;
MnOk := not(EndMarkOk);
while EdPtrNotNil(P) do begin
if P = Q then begin
if P = Blockfrom.Line then
if P = Blockto.Line then
EdCursorInBlock := ((C > F) and (C < T)) or (MnOk and ((C = F) or (C = T)))
else
EdCursorInBlock := (C > F) or (MnOk and (C = F))
else if (P = Blockto.Line) then
EdCursorInBlock := (C < T) or (MnOk and (C = T))
else
EdCursorInBlock := True;
Exit;
end;
if P = Blockto.Line then
{Exit loop}
EdSetPtrNil(P)
else
EdFwdPtr(P);
end;
end; {EdCursorInBlock}
function EdNoBlock : Boolean;
{-Return True if no block is marked and visible}
begin {EdNoBlock}
EdNoBlock := Blockhide or
EdPtrIsNil(Blockfrom.Line) or EdPtrIsNil(Blockto.Line) or
((Blockfrom.Line = Blockto.Line) and (Blockfrom.Col >= Blockto.Col));
end; {EdNoBlock}
function EdTextLength(P : PlineDesc) : Integer;
{-Return the length of line text, 0 if all blank}
begin {EdTextLength}
with P^ do
EdTextLength := EdGetEol(Txt^, Bufflen);
end; {EdTextLength}
{***}
procedure EdRealignOne(W : PwinDesc);
{-Realign one window}
var
P : PlineDesc;
Size : Integer;
begin {EdRealignOne}
with W^ do begin
{Realign this window}
LineNo := 1;
{Topline should always be defined!}
P := TopLine;
Size := LastLineNo-FirstTextNo;
{Curline must always be equal to or forward from Topline!}
while (P <> CurLine) and EdPtrNotNil(P) do begin
{Scan until we find the current line}
EdFwdPtr(P);
if LineNo > Size then
EdFwdPtr(TopLine)
else
Inc(LineNo);
end;
end;
end; {EdRealignOne}
procedure EdRealign;
{-Realign windows over text streams}
var
W : PwinDesc;
begin {EdRealign}
W := Window1;
repeat
EdRealignOne(W);
EdFwdPtr(W);
until W = Window1;
end; {EdRealign}
function EdLineIndent(P : PlineDesc) : Integer;
{-Return the indent of the specified line, 0 if line is empty}
var
I : Integer;
begin {EdLineIndent}
with P^ do begin
I := 1;
while (I < Bufflen) and (Txt^[I] = Blank) do
Inc(I);
if I = Bufflen then
{Line is all blank}
I := 0;
end;
EdLineIndent := I;
end; {EdLineIndent}
procedure EdClrFlag(P : PlineDesc; Mask : Word);
{-Clear the line flag}
begin {EdClrFlag}
P^.Flags := P^.Flags and not(Mask);
end; {EdClrFlag}
procedure EdSetFlag(P : PlineDesc; Mask : Word);
{-Set the line flag}
begin {EdSetFlag}
P^.Flags := P^.Flags or Mask;
end; {EdSetFlag}
function EdFlagSet(P : PlineDesc; Mask : Word) : Boolean;
{-Return True if the mask flag is set for line p}
begin {EdFlagSet}
EdFlagSet := (P^.Flags and Mask) <> 0;
end; {EdFlagSet}
procedure EdChangeFlag(P : PlineDesc; FlagVal : Boolean; FlagPos : Word);
{-Change a line flag, setting UpdateScreen if change encountered}
begin {EdChangeFlag}
if FlagVal then begin
{Setting a flag}
if not(EdFlagSet(P, FlagPos)) then begin
UpdateScreen := True;
EdSetFlag(P, FlagPos);
end;
end else if EdFlagSet(P, FlagPos) then begin
{Clearing a flag}
UpdateScreen := True;
EdClrFlag(P, FlagPos);
end;
end; {EdChangeFlag}
procedure EdToggleTextMarker;
{-Toggle visibility of text markers}
var
M : Integer;
begin {EdToggleTextMarker}
MarkHide := not(MarkHide);
{Set line flags}
for M := 0 to MaxMarker do
with Marker[M] do
if EdPtrNotNil(Line) then
if MarkHide then
EdClrFlag(Line, InMark)
else
EdSetFlag(Line, InMark);
end; {EdToggleTextMarker}
procedure EdFixUpWindowSpan(P : PlineDesc);
{-When p is to be deleted, first fix up any other structures pointing to p}
var
W : PwinDesc;
T : PlineDesc;
begin {EdFixUpWindowSpan}
{Check window Toplines, Curlines, and shortening window's span}
W := Window1;
repeat
with W^ do begin
if P = TopLine then begin
{Deleting the top line of a window}
if EdPtrIsNil(P^.Backlink) then begin
if EdPtrIsNil(P^.FwdLink) then begin
{Deleting only line in file, must be linked windows}
CurLine := CurWin^.CurLine;
TopLine := CurLine;
end else begin
{Deleting first line of file}
if P = CurLine then begin
EdFwdPtr(CurLine);
LineNo := 1;
end else
Dec(LineNo);
EdFwdPtr(TopLine);
end;
end else begin
{Somewhere in middle or end of file}
if P = CurLine then begin
EdBackPtr(CurLine);
LineNo := 1;
end;
EdBackPtr(TopLine);
end;
end else if P = CurLine then begin
{Deleting the current line of a window}
if EdPtrIsNil(P^.FwdLink) then begin
{Last line in file}
EdBackPtr(CurLine);
Dec(LineNo);
end else
EdFwdPtr(CurLine);
end else begin
{Check for line in the middle of window}
T := TopLine;
while T <> CurLine do
if T = P then begin
{Try to advance curline}
if EdPtrIsNil(CurLine^.FwdLink) then
Dec(LineNo)
else
EdFwdPtr(CurLine);
{Force exit}
T := CurLine;
end else
EdFwdPtr(T);
end;
end;
EdFwdPtr(W);
until W = Window1;
end; {EdFixUpWindowSpan}
procedure EdFixBlockInsertedSpace(P : PlineDesc; Start : Integer; Num : Integer);
{-Fix up block markers after blank space is inserted}
begin {EdFixBlockInsertedSpace}
if (P = Blockfrom.Line) then
if (Start < Blockfrom.Col) then
Blockfrom.Col := Blockfrom.Col+Num;
if (P = Blockto.Line) then
if (Start < Blockto.Col) then
Blockto.Col := Blockto.Col+Num;
end; {EdFixBlockInsertedSpace}
procedure EdFixMarkInsertedSpace(P : PlineDesc; Start : Integer; Num : Integer);
{-Fix up text markers after space is inserted in a line}
var
M : Integer;
begin {EdFixMarkInsertedSpace}
if EdFlagSet(P, InMark) then
for M := 0 to MaxMarker do
with Marker[M] do
if (Line = P) then
if (Col >= Start) then begin
Col := Col+Num;
if Col < 1 then
Col := 1;
end;
end; {EdFixMarkInsertedSpace}
procedure EdFixBlockInsertedLine(ThisL, NextL : PlineDesc;
BreakCol : Integer;
Delta : Integer);
{-Fix up block markers after a line is inserted}
begin {EdFixBlockInsertedLine}
if not(Blockhide) and EdFlagSet(ThisL, InBlock) then
EdSetFlag(NextL, InBlock);
if (ThisL = Blockfrom.Line) then
if (BreakCol <= Blockfrom.Col) then begin
Blockfrom.Line := NextL;
Blockfrom.Col := Blockfrom.Col-Delta;
EdClrFlag(ThisL, InBlock);
end;
if (ThisL = Blockto.Line) then
if (BreakCol < Blockto.Col) then begin
Blockto.Line := NextL;
Blockto.Col := Blockto.Col-Delta;
end else
EdClrFlag(NextL, InBlock);
end; {EdFixBlockInsertedLine}
procedure EdFixMarkInsertedLine(ThisL, NextL : PlineDesc;
BreakCol : Integer;
Delta : Integer);
{-Fix up text markers after a new line is inserted}
var
MarkGone : Boolean;
M : Integer;
begin {EdFixMarkInsertedLine}
MarkGone := True;
for M := 0 to MaxMarker do
with Marker[M] do
if (Line = ThisL) then
if (Col >= BreakCol) then begin
Col := Succ(Col-Delta);
Line := NextL;
EdSetFlag(NextL, InMark);
end else
MarkGone := False;
if MarkGone then
EdClrFlag(ThisL, InMark);
end; {EdFixMarkInsertedLine}
procedure EdOffblock;
{-Turn off Inblock bits for every text line in the system}
var
W : PwinDesc;
P, Q : PlineDesc;
begin {EdOffblock}
{Start with current window}
W := CurWin;
repeat
{Do this to every window}
P := W^.TopLine;
Q := P;
while EdPtrNotNil(P) do begin
EdClrFlag(P, InBlock);
EdBackPtr(P);
end;
while EdPtrNotNil(Q) do begin
EdClrFlag(Q, InBlock);
EdFwdPtr(Q);
end;
EdFwdPtr(W);
until W = CurWin;
end; {EdOffblock}
{***}
procedure EdSetTextNo(W : PwinDesc);
{-Set the FirstTextNo of a window}
begin {EdSetTextNo}
with W^ do
FirstTextNo := Succ(FirstLineNo);
end; {EdSetTextNo}
function EdLinkedWindow(W : PwinDesc) : Boolean;
{-Return true if a window is linked to any others}
var
V : PwinDesc;
Wstream : Word;
begin {EdLinkedWindow}
EdLinkedWindow := False;
Wstream := W^.Stream;
V := W^.FwdLink;
while V <> W do
if V^.Stream = Wstream then begin
EdLinkedWindow := True;
Exit;
end else
EdFwdPtr(V);
end; {EdLinkedWindow}
function EdBlockDiscontinuous : Boolean;
{-Return true if block is not within a continuous text stream}
var
P : PlineDesc;
begin {EdBlockDiscontinuous}
EdBlockDiscontinuous := True;
P := Blockfrom.Line;
while EdPtrNotNil(P) do
if P = Blockto.Line then begin
{Block is continuous if columns are legal}
EdBlockDiscontinuous := (Blockfrom.Line = Blockto.Line) and (Blockfrom.Col >= Blockto.Col);
Exit;
end else
EdFwdPtr(P);
end; {EdBlockDiscontinuous}
procedure EdResetWindowPrimitive(W : PwinDesc);
{-Low level routine for resetting window}
begin {EdResetWindowPrimitive}
with W^ do begin
CurLine := TopLine;
Clineno := 1;
LineNo := 1;
ColNo := 1;
LeftEdge := 1;
end;
end; {EdResetWindowPrimitive}
function EdNewstream : Word;
{-Return unique text stream identifier}
begin {EdNewstream}
EdNewstream := NextStream;
NextStream := Succ(NextStream) mod MaxInt;
end; {EdNewstream}
procedure EdChangeStreamName(Fname : Filepath);
{-Change name of current stream to fname}
var
W : PwinDesc;
S : Word;
begin {EdChangeStreamName}
S := CurWin^.Stream;
W := CurWin;
repeat
if W^.Stream = S then
W^.Filename := Fname;
EdFwdPtr(W);
until W = CurWin;
end; {EdChangeStreamName}
procedure EdCheckNoMarker;
{-If deletion operation has deleted all marked text, remove block markers altogether}
begin {EdChecknomarker}
{Get out fast if no block now}
if EdPtrIsNil(Blockfrom.Line) or (Blockfrom.Line <> Blockto.Line) then
Exit;
if Blockfrom.Col >= Blockto.Col then begin
EdSetPtrNil(Blockfrom.Line);
EdSetPtrNil(Blockto.Line);
EdOffblock;
end;
end; {EdChecknomarker}
{***}
procedure EdInitWindowSettings(W : PwinDesc);
{-Set window parameters to defaults}
begin {EdInitWindowSettings}
with W^ do begin
InsertFlag := SaveInsertMode;
AI := SaveIndentMode;
Filename := NoFile;
Modified := False;
Clineno := 1;
LeftCol := 0;
LeftEdge := 1;
TcharNo := 0;
{The rest of these aren't used in FirstEd}
{Initialize to harmless values}
WW := False;
TL := False;
JU := False;
PA := False;
AT := False;
FT := False;
Lmargin := 1;
Wmargin := 1;
Rmargin := MaxLineLength;
PageLen := MaxInt;
Tmargin := 0;
Bmargin := 0;
Visible := True;
end;
end; {EdInitWindowSettings}
procedure EdLinkbuffer(P, Q : PlineDesc);
{-Link line q after line p}
begin {EdLinkbuffer}
Q^.Backlink := P;
Q^.FwdLink := P^.FwdLink;
P^.FwdLink := Q;
if EdPtrNotNil(Q^.FwdLink) then
Q^.FwdLink^.Backlink := Q;
end; {EdLinkbuffer}
procedure EdBufferCurrentLine;
{-Keep an extra image of current line to allow restore via ^QL}
var
Len : Integer;
begin {EdBufferCurrentLine}
with CurWin^ do begin
Len := CurLine^.Bufflen;
{Store the text and flags of the current line}
with CurLineBuf^ do begin
Bufflen := Len;
Flags := CurLine^.Flags;
Move(CurLine^.Txt^[1], Txt^[1], Len);
end;
{Store the current column number}
CurLineCol := ColNo;
{Store block columns and lines}
if CurLine = Blockfrom.Line then
CurLineFrom.Col := Blockfrom.Col;
CurLineFrom.Line := Blockfrom.Line;
if CurLine = Blockto.Line then
CurLineTo.Col := Blockto.Col;
CurLineTo.Line := Blockto.Line;
end;
end; {EdBufferCurrentLine}
procedure EdBackupCurline(W : PwinDesc);
{-Move curline up as needed to fit into smaller window}
begin {EdBackupCurline}
with W^ do
while LineNo > Succ(LastLineNo-FirstTextNo) do begin
{Fix up the pointers}
EdFwdPtr(TopLine);
{Alternate behavior, replace previous line with --> EdBackPtr(Curline);}
Dec(LineNo);
end;
end; {EdBackupCurline}
procedure EdMoveCursorIntoLine;
{-Set current column within line buffer}
begin {EdMoveCursorIntoLine}
with CurWin^ do
if ColNo > CurLine^.Bufflen then
ColNo := CurLine^.Bufflen;
end; {EdMoveCursorIntoLine}
procedure EdGotoColumn(Cno : Integer);
{-Go to column cno on current line}
begin {EdGotoColumn}
CurWin^.ColNo := Cno;
end; {EdGotoColumn}
procedure EdGotoLine(Lno : Integer);
{-Go to line Lno of current window}
var
P : PlineDesc;
I : Integer;
begin {EdGotoLine}
with CurWin^ do begin
{Go to first line of file}
P := EdTopofStream(CurWin);
I := 1;
{Count lines to the right one}
while (I < Lno) and EdPtrNotNil(P^.FwdLink) do begin
Inc(I);
EdFwdPtr(P);
end;
CurLine := P;
TopLine := P;
LineNo := 1;
Clineno := I;
end;
end; {EdGotoLine}
procedure EdWindowTopFile;
{-Go to top of file}
var
P : PlineDesc;
begin {EdWindowTopFile}
P := EdTopofStream(CurWin);
CurWin^.TopLine := P;
EdResetWindowPrimitive(CurWin);
end; {EdWindowTopFile}
{***}
procedure EdTopScreen;
{-Go to top of screen}
begin {EdTopScreen}
with CurWin^ do begin
CurLine := TopLine;
LineNo := 1;
end;
end; {EdTopScreen}
{***}
procedure EdBottomScreen;
{-Move cursor to bottom of screen}
begin {EdBottomScreen}
with CurWin^ do begin
CurLine := TopLine;
LineNo := 1;
while (LineNo <= LastLineNo-FirstTextNo) and EdPtrNotNil(CurLine^.FwdLink) do begin
Inc(LineNo);
EdFwdPtr(CurLine);
end;
end;
end; {EdBottomScreen}
procedure EdWindowGoto(Wno : Byte);
{-Move cursor into window Wno, counted from top of screen}
begin {EdWindowGoto}
CurWin := EdFindWindesc(Wno);
end; {EdWindowGoto}
procedure EdBlockHide;
{-Toggle block display}
begin {EdBlockHide}
if Blockhide then
{Turn off blockhide only if From and To markers form a continuous stream}
Blockhide := EdBlockDiscontinuous
else begin
{Turn off block display}
Blockhide := True;
{Reset block flags everywhere}
EdOffblock;
end;
end; {EdBlockHide}
procedure EdFixBaseLine(WindFrom : PwinDesc);
{-Redefine window Topline and Curline before a block operation deletes them}
var
W : PwinDesc;
begin {EdFixBaseLine}
W := WindFrom;
repeat
{Check all windows sharing the text stream including windfrom itself}
if W^.Stream = WindFrom^.Stream then
with W^ do begin
if EdCursorInBlock(TopLine, 1, False) or (TopLine = Blockto.Line) then
TopLine := Blockfrom.Line;
if EdCursorInBlock(CurLine, ColNo, False) or (CurLine = Blockto.Line) then begin
CurLine := Blockfrom.Line;
ColNo := Blockfrom.Col;
end;
end;
EdFwdPtr(W);
until (W = WindFrom);
end; {EdFixBaseLine}
procedure EdSetupBlock(var MarkA, MarkB : BlockMarker);
{-Check for a contiguous block, and set marks and blockhide accordingly}
var
Len : Integer;
begin {EdSetupBlock}
{Turn off all lines in blocks}
EdOffblock;
{Repoint one end of the block}
with CurWin^, MarkA do begin
Line := CurLine;
Col := ColNo;
{Assure block stays within text buffer}
Len := EdTextLength(CurLine);
if Col > Len then
Col := Succ(Len);
end;
{Assure complete block defined}
if EdPtrIsNil(MarkB.Line) then begin
{Only one end defined}
Blockhide := True;
Exit;
end;
Blockhide := EdBlockDiscontinuous;
if Blockhide then begin
EdSetPtrNil(MarkB.Line);
MarkB.Col := 0;
end;
end; {EdSetupBlock}
procedure EdBlockBegin;
{-Set block begin marker}
begin {EdBlockBegin}
EdSetupBlock(Blockfrom, Blockto);
end; {EdBlockBegin}
procedure EdBlockEnd;
{-Set block end marker}
begin {EdBlockEnd}
EdSetupBlock(Blockto, Blockfrom);
end; {EdBlockEnd}
procedure EdBlockWord;
{-Mark the current word as a block}
var
C, Len : Integer;
begin {EdBlockWord}
with CurWin^ do begin
Len := EdTextLength(CurLine);
if Len = 0 then
{Line is empty, don't change anything}
Exit;
{Set marker to this line}
Blockto.Line := CurLine;
Blockfrom.Line := CurLine;
C := ColNo;
with CurLine^ do begin
if C > Len then
{Cursor past end of line, mark word to left}
C := Len;
if (Txt^[C] in Alphas) then begin
{In a word, scan to left edge of word}
while (C > 0) and (Txt^[C] in Alphas) do
Dec(C);
Inc(C);
end else
{In white space, scan right to next word}
while not(Txt^[C] in Alphas) do
Inc(C);
{From marker starts at left edge of word}
Blockfrom.Col := C;
{Scan right past end of word}
while (C <= Len) and (Txt^[C] in Alphas) do
Inc(C);
{To marker is just past right edge of word}
Blockto.Col := C;
end;
end;
EdOffblock;
Blockhide := False;
end; {EdBlockWord}
begin
NextStream := 0; {Initialize text stream identifier}
end.