home *** CD-ROM | disk | FTP | other *** search
- { MSPTROP.PAS
- MS 4.0
- Copyright (c) 1985, 87 by Borland International, Inc. }
-
- {$I msdirect.inc}
-
- unit MsPtrOp;
- {-Low level pointer operations for the Toolbox architecture}
-
- interface
-
- uses
- Crt, {Basic video operations - standard unit}
- Dos, {DOS interface - standard unit}
- MsVars, {Global types and declarations}
- MsScrn1; {Fast screen writing routines}
-
- {----------- 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 EdChangeStatus(NewVal : Word; var StoreLoc : Word);
- {-Update a status value, setting UpdateScreen if a change has occurred}
-
- function EdGetPageNum(P : PlineDesc) : Integer;
- {-Return the page number of the line}
-
- procedure EdSetPageNum(P : PlineDesc; Num : Integer);
- {-Set the page number of the line}
-
- 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 EdCompress(P : PlineDesc; Lmargin : Integer; var Col, Len : Integer);
- {-Remove excess spaces internal to a line}
-
- procedure EdUpdateFont(C : PrintCommandtype; var FontByte : Byte);
- {-Toggle appropriate bit of packed font byte}
-
- procedure EdCloneAttrFlags(P, Q : PlineDesc; Col : Integer);
- {-Set font attribute flag for line q based on contents of p up to col}
-
- function EdComputeEffectiveColNo(Attribs : Boolean; P : PlineDesc; Col : Integer) : Integer;
- {-When attributes are displayed, correct column number for invisible characters}
-
- function EdAdjustColno(P, Q : PlineDesc; Col : Integer) : Integer;
- {-Adjust returned colno so effcol(p,col)=effcol(q,col)}
-
- {----------- Window oriented operations}
-
- procedure EdWindowGoto(Wno : Byte);
- {-Move cursor into window Wno, counted from top of screen}
-
- 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 EdResetTempMargin(W : Pwindesc; FullReset : Boolean);
- {-Set temp margin back to fixed left margin when appropriate}
-
- procedure EdResetPageLine(W : Pwindesc);
- {-Reset the accurate pagination line after an edit operation occurs}
-
- procedure EdZoomWindow(FixCurline : Boolean);
- {-Make the current window fill the entire screen}
-
- procedure EdWindowUp;
- {-Process up window command}
-
- procedure EdWindowDown;
- {-Process down window command}
-
- procedure EdRealignOne(W : Pwindesc);
- {-Realign one window}
-
- 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}
-
- procedure EdResetWindowPrimitive(W : Pwindesc);
- {-Low level routine for resetting window}
-
- function EdNewstream : Word;
- {-Return unique text stream identifier}
-
- procedure EdChangeStreamName(Fname : Filepath);
- {-Change name of current stream to fname}
-
- procedure EdSetEvenTabs(var Tabs : TabArray);
- {-Set the tab array to even tabs on the current default spacing}
-
- 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 MSPTROP}
- {$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;
- 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 EdResetTempMargin(W : Pwindesc; FullReset : Boolean);
- {-Set temp margin back to fixed left margin when appropriate}
- var
- P : PlineDesc;
- FoundMarginline, FoundBlankline : Boolean;
-
- procedure EdClearTempMargin(W : Pwindesc);
- {-Clear the temporary margin}
-
- begin {EdClearTempMargin}
- with W^ do begin
- Wmargin := Lmargin;
- EdSetPtrNil(WmarginLine);
- end;
- end; {EdClearTempMargin}
-
- begin {EdResetTempMargin}
-
- with W^ do
- if FullReset then
-
- {Reset temp margin independent of conditions}
- EdClearTempMargin(W)
-
- else if EdPtrIsNil(WmarginLine) then
-
- {Original marginline was deleted, reset the temp margin}
- Wmargin := Lmargin
-
- else if Wmargin <> Lmargin then begin
-
- {Scan backward from current line}
- P := Curline;
- FoundBlankline := False;
- FoundMarginline := False;
-
- while EdPtrNotNil(P) and not(FoundMarginline) do begin
- if (P^.Txt^[1] = FormatChar) or (EdTextLength(P) = 0) then
- FoundBlankline := True;
- if P = WmarginLine then
- FoundMarginline := True;
- EdBackPtr(P);
- end;
-
- if FoundMarginline then begin
- if FoundBlankline then
- EdClearTempMargin(W);
- Exit;
- end;
-
- {Scan forward from current line}
- P := Curline;
- FoundBlankline := False;
- FoundMarginline := False;
-
- while EdPtrNotNil(P) and not(FoundMarginline) do begin
- if (P^.Txt^[1] = FormatChar) or (EdTextLength(P) = 0) then
- FoundBlankline := True;
- if P = WmarginLine then
- FoundMarginline := True;
- EdFwdPtr(P);
- end;
-
- if FoundMarginline and not(FoundBlankline) then
- {Current line still in same paragraph}
- Exit;
-
- {Marginline disappeared, or blank line found}
- EdClearTempMargin(W);
-
- end;
- end; {EdResetTempMargin}
-
- procedure EdResetPageLine(W : Pwindesc);
- {-Reset the accurate pagination line after an edit operation occurs}
- var
- V : Pwindesc;
- S : Integer;
-
- begin {EdResetPageLine}
- V := W;
- S := V^.Stream;
- repeat
- {Reset for all linked windows}
- with V^ do
- if PA and (Stream = S) then begin
- PaginationDone := False;
- EdSetPtrNil(PageLine);
- end;
- EdFwdPtr(V);
- until V = W;
- end; {EdResetPageLine}
-
- procedure EdZoomWindow(FixCurline : Boolean);
- {-Make the current window fill the entire screen}
-
- procedure EdBackupAllCurline;
- {-Assure curline is in visible region for all windows}
- var
- W : Pwindesc;
-
- begin {EdBackupAllCurline}
- W := Curwin;
- repeat
- EdBackupCurline(W);
- EdFwdPtr(W);
- until W = Curwin;
- end; {EdBackupAllCurline}
-
- procedure EdSetVisible(On : Boolean);
- {-Set the visible flags for all windows}
- var
- W : Pwindesc;
- begin {EdSetVisible}
- W := Curwin;
- repeat
- W^.Visible := On;
- EdFwdPtr(W);
- until W = Curwin;
- end; {EdSetVisible}
-
- begin {EdZoomWindow}
- with Curwin^ do
- if Zoomed then begin
- {Undo the previous zoom}
- Firstlineno := ZoomWin.Firstlineno;
- Lastlineno := ZoomWin.Lastlineno;
- EdSetTextNo(Curwin);
- if FixCurline then
- EdBackupAllCurline;
- EdSetVisible(True);
- end else begin
- {Save current window screen position}
- ZoomWin.Firstlineno := Firstlineno;
- ZoomWin.Lastlineno := Lastlineno;
- {Set window to fill full screen}
- Firstlineno := LogtopScr;
- Lastlineno := PhyscrRows;
- EdSetTextNo(Curwin);
- {Turn off visibility of all other windows}
- EdSetVisible(False);
- Visible := True;
- end;
- Zoomed := not(Zoomed);
- end; {EdZoomWindow}
-
- procedure EdWindowUp;
- {-Process up window command}
- var
- Rezoom : Boolean;
-
- begin {EdWindowUp}
- Rezoom := Zoomed;
- if Rezoom then
- EdZoomWindow(False);
- EdBackPtr(Curwin);
- if Rezoom then
- EdZoomWindow(False);
- {Assure current line is positioned on screen}
- EdBackupCurline(Curwin);
- end; {EdWindowUp}
-
- procedure EdWindowDown;
- {-Process down window command}
- var
- Rezoom : Boolean;
-
- begin {EdWindowDown}
- Rezoom := Zoomed;
- if Rezoom then
- EdZoomWindow(False);
- EdFwdPtr(Curwin);
- if Rezoom then
- EdZoomWindow(False);
- {Assure current line is positioned on screen}
- EdBackupCurline(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 must always be defined!}
- P := TopLine;
- {Account for zoomed windows - each window effectively has full screen}
- if Zoomed then begin
- if TL then
- Size := PhyscrRows-(LogtopScr+2)
- else
- Size := PhyscrRows-Succ(LogtopScr);
- end else
- 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 EdChangeStatus(NewVal : Word; var StoreLoc : Word);
- {-Update a status value, setting UpdateScreen if a change has occurred}
-
- begin {EdChangeStatus}
- if NewVal <> StoreLoc then begin
- UpdateScreen := True;
- StoreLoc := NewVal;
- end;
- end; {EdChangeStatus}
-
- function EdGetPageNum(P : PlineDesc) : Integer;
- {-Return the page number of the line}
-
- begin {EdGetPageNum}
- if EdPtrIsNil(P) then
- EdGetPageNum := 0
- else
- EdGetPageNum := (P^.Flags and MaxPage);
- end; {EdGetPageNum}
-
- procedure EdSetPageNum(P : PlineDesc; Num : Integer);
- {-Set the page number of the line}
-
- begin {EdSetPageNum}
- with P^ do
- Flags := (Flags and not(MaxPage)) or (Num and MaxPage);
- end; {EdSetPageNum}
-
- 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
- if TL then
- Firsttextno := Firstlineno+2
- else
- 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}
- Wstream := W^.Stream;
- V := W^.Fwdlink;
- while V <> W do
- if V^.Stream = Wstream then begin
- EdLinkedWindow := True;
- Exit;
- end else
- EdFwdPtr(V);
- EdLinkedWindow := False;
- 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 EdSetEvenTabs(var Tabs : TabArray);
- {-Set the tab array to even tabs on the current default spacing}
- var
- I, TabPos : Integer;
-
- begin {EdSetEvenTabs}
- for I := 1 to MaxNumTabs do begin
- TabPos := Succ(SaveTabSize*I);
- if TabPos <= Maxlinelength then
- Tabs[I] := TabPos
- else
- Tabs[I] := 0;
- end;
- end; {EdSetEvenTabs}
-
- procedure EdInitWindowSettings(W : Pwindesc);
- {-Set window parameters to defaults}
-
- begin {EdInitWindowSettings}
- with W^ do begin
- Insertflag := SaveInsertMode;
- AI := SaveIndentMode;
- WW := SaveWWmode;
- TL := SaveTabMode;
- JU := SaveJustMode;
- PA := SavePageMode;
- AT := SaveAttrMode;
- FT := SaveFTmode;
- CW := SaveCompressWrap;
- Lmargin := SaveLeftMargin;
- Rmargin := SaveRightMargin;
- PageLen := SavePageLen;
- Tmargin := SaveTopMargin;
- Bmargin := SaveBottomMargin;
- Filename := NoFile;
- Modified := False;
- Visible := True;
- Clineno := 1;
- Crelpos := 00;
- PaginationDone := False;
- EdSetPtrNil(PageLine);
- if PA then
- Leftcol := 2
- else
- Leftcol := 0;
- Leftedge := 1;
- EdSetEvenTabs(Tabs);
- EdResetTempMargin(W, 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 EdUpdateFont(C : PrintCommandtype; var FontByte : Byte);
- {-Toggle appropriate bit of packed font byte}
- var
- Mask : Byte;
-
- begin {EdUpdateFont}
- Mask := 1 shl Ord(C);
- if (FontByte and Mask) = 0 then
- FontByte := FontByte or Mask
- else
- FontByte := FontByte and not(Mask);
- end; {EdUpdateFont}
-
- procedure EdCloneAttrFlags(P, Q : PlineDesc; Col : Integer);
- {-Set font attribute flag for line q based on contents of p up to col}
- var
- FontByte : Byte;
- C : PrintCommandtype;
- I : Integer;
-
- begin {EdCloneAttrFlags}
-
- {Get the font descriptor at start of original line}
- FontByte := P^.Font;
-
- {Scan the line up to the break point}
- with P^ do begin
- if Col > Bufflen then
- Col := Succ(Bufflen);
- for I := 1 to Pred(Col) do begin
- C := PrintMap[Txt^[I]];
- if C <> PrtNone then
- EdUpdateFont(C, FontByte);
- end;
- end;
-
- {Give the font descriptor to the new line}
- Q^.Font := FontByte;
- {Assume font will change in new line, later updated by background process}
- EdSetFlag(Q, NewAttr);
-
- end; {EdCloneAttrFlags}
-
- function EdComputeEffectiveColNo(Attribs : Boolean; P : PlineDesc; Col : Integer) : Integer;
- {-When attributes are displayed, correct column number for invisible characters}
- var
- Ipos, Opos : Integer;
-
- begin {EdComputeEffectiveColNo}
- if Attribs then
- with P^ do begin
-
- Opos := 0;
- for Ipos := 1 to Col do
- if Ipos > Bufflen then
- Inc(Opos)
- else if PrintMap[Txt^[Ipos]] = PrtNone then
- Inc(Opos);
-
- {Correct if cursor is on a control character}
- if Opos = 0 then
- EdComputeEffectiveColNo := 1
- else if (Col > Bufflen) or (PrintMap[Txt^[Col]] = PrtNone) then
- EdComputeEffectiveColNo := Opos
- else
- EdComputeEffectiveColNo := Succ(Opos);
-
- end
- else
- EdComputeEffectiveColNo := Col;
- end; {EdComputeEffectiveColNo}
-
- function EdAdjustColno(P, Q : PlineDesc; Col : Integer) : Integer;
- {-Adjust returned colno so effcol(p,col)=effcol(q,col)}
- var
- EffCol, Ipos, Opos : Integer;
-
- begin {EdAdjustColno}
- {Get the apparent column to match}
- EffCol := EdComputeEffectiveColNo(True, Q, Col);
- {Scan the new line to see what text position corresponds to EffCol}
- with P^ do begin
- Ipos := 0;
- Opos := 0;
- while Opos < EffCol do begin
- Inc(Ipos);
- if Ipos > Bufflen then
- Inc(Opos)
- else if PrintMap[Txt^[Ipos]] = PrtNone then
- Inc(Opos);
- end;
- end;
- EdAdjustColno := Ipos;
- end; {EdAdjustColno}
-
- procedure EdTopScreen;
- {-Move cursor to top of screen}
- var
- P : PlineDesc;
-
- begin {EdTopScreen}
- with Curwin^ do begin
- P := Curline;
- Curline := TopLine;
- Lineno := 1;
- if AT then
- {Adjust current column number to match appearance of previous line}
- Colno := EdAdjustColno(Curline, P, Colno);
- end;
- end; {EdTopScreen}
-
- procedure EdBottomScreen;
- {-Move cursor to bottom of screen}
- var
- P : PlineDesc;
-
- begin {EdBottomScreen}
- with Curwin^ do begin
- P := Curline;
- Curline := TopLine;
- Lineno := 1;
- while EdPtrNotNil(Curline^.Fwdlink) and (Lineno <= Lastlineno-Firsttextno) do begin
- Inc(Lineno);
- EdFwdPtr(Curline);
- end;
- if AT then
- {Adjust current column number to match appearance of previous line}
- Colno := EdAdjustColno(Curline, P, Colno);
- end;
- end; {EdBottomScreen}
-
- procedure EdCompress(P : PlineDesc; Lmargin : Integer; var Col, Len : Integer);
- {-Remove excess spaces internal to a line}
- var
- Lptr, Tptr, OrigCol : Integer;
- Tline : TextLine;
- LastC, C : Char;
-
- begin {EdCompress}
-
- {Get length to last non-blank}
- Len := EdTextLength(P);
-
- {Save column position}
- OrigCol := Col;
-
- if Lmargin >= Len then
- {No compression will occur}
- Exit;
-
- with P^ do
- if Len > 0 then begin
-
- Lptr := 1;
-
- {Pass on leading spaces and characters left of left margin without change}
- while (Txt^[Lptr] = Blank) or (Lptr <= Lmargin) do begin
- Tline[Lptr] := Txt^[Lptr];
- Inc(Lptr);
- end;
- Tptr := Pred(Lptr);
-
- {Output non-blank characters}
- {Initialize lastc to anything but a blank}
- LastC := Period;
- while Lptr <= Len do begin
- C := Txt^[Lptr];
- if C = Blank then begin
- if (LastC <> Blank) then begin
- Inc(Tptr);
- Tline[Tptr] := C;
- end else begin
- if Lptr <= OrigCol then
- {Don't output blank, the cursor column number is pulled one left}
- Dec(Col);
- {Fix up markers}
- EdFixBlockInsertedSpace(P, Succ(Tptr), -1);
- EdCheckNoMarker;
- EdFixMarkInsertedSpace(P, Tptr, -1);
- end;
- end else begin
- {All non-blank characters output}
- Inc(Tptr);
- Tline[Tptr] := C;
- end;
- Inc(Lptr);
- LastC := C;
- end;
-
- {Copy back onto input}
- Move(Tline[1], Txt^[1], Tptr);
- FillChar(Txt^[Succ(Tptr)], Bufflen-Tptr, Blank);
- {Return length}
- Len := Tptr;
-
- end;
- end; {EdCompress}
-
- procedure EdWindowGoto(Wno : Byte);
- {-Move cursor into window Wno, counted from top of screen}
- var
- W : Pwindesc;
- Rezoom : Boolean;
-
- begin {EdWindowGoto}
- W := EdFindWindesc(Wno);
- Rezoom := Zoomed and (W <> Curwin);
- if Rezoom then
- EdZoomWindow(False);
- Curwin := W;
- if Rezoom then
- EdZoomWindow(False);
- 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 : Word;
-
- 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.