Category : Word Processors
Archive   : AE170.ZIP
Filename : AE1.PAS

 
Output of file : AE1.PAS contained in archive : AE170.ZIP
UNIT AE1 ;

{$R-}
{$B-}
{$I-}
{$S+}
{$V-}

{-----------------------------------------------------------------------------}
{ This unit contains all basic procedures }
{-----------------------------------------------------------------------------}

INTERFACE

USES Crt, Dos, AE0 ;

FUNCTION UpperCase (S : STRING) : STRING ;
FUNCTION WordToString (Num : WORD ; Len : INTEGER) : STRING ;
FUNCTION Wildcarded (Name : PathStr) : BOOLEAN ;
FUNCTION Exists (FileName : PathStr) : BOOLEAN ;
PROCEDURE MoveToScreen (VAR Source, Dest ; Len : WORD) ;
PROCEDURE MoveFromScreen (VAR Source, Dest ; Len : WORD) ;
PROCEDURE SaveArea (X1, Y1, X2, Y2 : WORD ; VAR MemPtr : ScreenBlockPtr) ;
PROCEDURE RestoreArea (X1, Y1, X2, Y2 : WORD ; VAR MemPtr : ScreenBlockPtr) ;
FUNCTION Grow (Index : WORD ; Chars : WORD) : BOOLEAN ;
PROCEDURE Shrink (Index : WORD ; Chars : WORD) ;
FUNCTION GetCursor : BYTE ;
PROCEDURE SetCursor (Cursor : BYTE) ;
PROCEDURE CursorTo (X, Y : BYTE) ;
PROCEDURE WarningBeep ;
FUNCTION ReadKeyNr : WORD ;
PROCEDURE SetBottomLine (LineText : STRING) ;
PROCEDURE Message (Contents : STRING) ;
PROCEDURE ErrorMessage (ErrorNr : BYTE) ;
PROCEDURE Pause ;
PROCEDURE CheckDiskError ;
PROCEDURE PutFrame (X1, Y1, X2, Y2 : BYTE ; Border : STRING) ;
PROCEDURE ClearArea (X1, Y1, X2, Y2 : BYTE) ;
PROCEDURE ClearCurrentWs ;
PROCEDURE ClearKeyBuffer ;
PROCEDURE CheckEsc ;
PROCEDURE CreateHistory (VAR Hp : HistPtr ; LineLen : BYTE) ;
PROCEDURE AddToHistory (Hp : HistPtr ; S : STRING) ;
FUNCTION CurrentHistLine (Hp : HistPtr) : STRING ;
FUNCTION NextHistLine (Hp : HistPtr) : STRING ;
FUNCTION PrevHistLine (Hp : HistPtr) : STRING ;
FUNCTION LeftMargin (VAR P : Position) : WORD ;
{$IFDEF DEVELOP }
PROCEDURE GetMem (VAR P : pointer ; Size : WORD ) ;
{$ENDIF }

IMPLEMENTATION

{-----------------------------------------------------------------------------}
{ Converts all lower case letters in a string to upper case. }
{-----------------------------------------------------------------------------}

FUNCTION UpperCase (S : STRING) : STRING ;

VAR Counter : WORD ;

BEGIN
FOR Counter := 1 TO LENGTH (S) DO S [Counter] := UPCASE (S [Counter]) ;
UpperCase := S ;
END ;

{-----------------------------------------------------------------------------}
{ Converts an expression of type word to a string }
{ if Len < 0 then string is adjusted to the left; string length is }
{ if Len > 0 then string is adjusted to the right; string length is <-Len> }
{ if Len = 0 then string is not adjusted; string has minimum length }
{-----------------------------------------------------------------------------}

FUNCTION WordToString (Num : WORD ; Len : INTEGER) : STRING ;

VAR S : STRING [5] ;

BEGIN
IF Len > 0
THEN STR (Num : Len, S)
ELSE BEGIN
STR (Num, S) ;
Len := - Len ;
IF (Len > 0) AND (LENGTH (S) < Len)
THEN BEGIN
FILLCHAR (S [LENGTH (S) + 1], Len - LENGTH (S), ' ') ;
S [0] := CHR (Len) ;
END ;
END ;
WordToString := S ;
END ;

{-----------------------------------------------------------------------------}
{ Deletes all spaces on the left of a string. }
{-----------------------------------------------------------------------------}

FUNCTION TrimLeft (S : STRING) : STRING ;

BEGIN
WHILE (LENGTH (S) > 0) AND (S [1] = ' ') DO DELETE (S, 1, 1) ;
TrimLeft := S ;
END ;

{-----------------------------------------------------------------------------}
{ Indicates whether a filename contains wildcard characters }
{-----------------------------------------------------------------------------}

FUNCTION Wildcarded (Name : PathStr) : BOOLEAN ;

BEGIN
Wildcarded := (POS ('*', Name) <> 0) OR (POS ('?', Name) <> 0) ;
END ;

{-----------------------------------------------------------------------------}
{ Returns True if the file exists, False otherwise. }
{-----------------------------------------------------------------------------}

FUNCTION Exists (FileName : PathStr) : BOOLEAN ;

VAR SR : SearchRec ;

BEGIN
FINDFIRST (FileName, ReadOnly + Hidden + SysFile, SR) ;
Exists := (DosError = 0) AND (NOT Wildcarded (Filename) ) ;
END ;

{-----------------------------------------------------------------------------}
{ Moves bytes of memory to screen memory. }
{ From the TCALC spreadsheet program delivered with every copy of Turbo }
{ Pascal 5.5 }
{-----------------------------------------------------------------------------}

PROCEDURE MoveToScreen (VAR Source, Dest ; Len : WORD) ;

EXTERNAL ;

{-----------------------------------------------------------------------------}
{ Moves bytes of screen memory to memory. }
{ From the TCALC spreadsheet program delivered with every copy of Turbo }
{ Pascal 5.5 }
{-----------------------------------------------------------------------------}

PROCEDURE MoveFromScreen (VAR Source, Dest ; Len : WORD) ;

EXTERNAL ;

{$L TCMVSMEM.OBJ }

{-----------------------------------------------------------------------------}
{ Saves the contents of a rectangular part of the screen to memory. }
{ Upper left corner is (X1,Y1), lower right is (X2,Y2) }
{ Also claims the amount of memory needed. }
{-----------------------------------------------------------------------------}

PROCEDURE SaveArea (X1, Y1, X2, Y2 : WORD ; VAR MemPtr : ScreenBlockPtr) ;

VAR LineLen : BYTE;
Index : WORD;
Counter : BYTE;

BEGIN
LineLen := X2 - X1 + 1;
GETMEM (POINTER(MemPtr), LineLen * (Y2 - Y1 + 1) * 2) ;
Index := 1 ;
FOR Counter := Y1 TO Y2 DO
BEGIN
MoveFromScreen (DisplayPtr^ [Counter, X1], MemPtr^ [Index], LineLen * 2);
INC (Index, LineLen)
END;
END;

{-----------------------------------------------------------------------------}
{ Reverse of SaveArea }
{-----------------------------------------------------------------------------}

PROCEDURE RestoreArea (X1, Y1, X2, Y2 : WORD ; VAR MemPtr : ScreenBlockPtr) ;

VAR LineLen : BYTE;
Index : WORD;
Counter : BYTE;

BEGIN
LineLen := X2 - X1 + 1;
Index := 1;
FOR Counter := Y1 TO Y2 DO
BEGIN
MoveToScreen (MemPtr^ [Index], DisplayPtr^ [Counter, X1], LineLen * 2);
INC (Index, LineLen)
END;
FREEMEM (MemPtr, LineLen * (Y2 - Y1 + 1) * 2) ;
END;

{-----------------------------------------------------------------------------}
{ Expands the text in the buffer of the current workspace at position }
{ by characters. Function result is False if there is not }
{ enough space left, True otherwise. }
{ Index values of Mark and in position stack are adapted }
{-----------------------------------------------------------------------------}

FUNCTION Grow (Index : WORD ; Chars : WORD) : BOOLEAN ;

VAR Counter : BYTE ;

BEGIN
WITH CurrentWs DO
IF Chars > (WsBufSize - BufferSize)
THEN BEGIN
{ not enough space }
ErrorMessage (1) ;
Grow := FALSE ;
END
ELSE BEGIN
{ move rest of text forward }
MOVE (Buffer^ [Index], Buffer^ [Index + Chars], BufferSize - Index + 1) ;
INC (BufferSize, Chars) ;
{ adapt Mark and position stack }
IF MARK >= Index THEN INC (MARK, Chars) ;
FOR Counter := 1 TO PosStackpointer DO
BEGIN
IF PosStack [Counter] >= Index
THEN INC (PosStack [Counter], Chars) ;
END ;
ChangesMade := TRUE ;
Grow := TRUE ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Deletes characters from the buffer in the current workspace, }
{ starting on position . }
{ Index values of Mark and in position stack are adapted }
{-----------------------------------------------------------------------------}

PROCEDURE Shrink (Index : WORD ; Chars : WORD) ;

VAR Counter : WORD ;

BEGIN
WITH CurrentWs DO
BEGIN
{ move rest of text backward }
MOVE (Buffer^ [Index + Chars], Buffer^ [Index], BufferSize - (Index + Chars) + 1) ;
DEC (BufferSize, Chars) ;
{ adapt Mark }
IF (MARK >= Index)
THEN BEGIN
IF (MARK < (Index + Chars) )
THEN MARK := Inactive
ELSE DEC (MARK, Chars) ;
END ;
{ adapt position stack }
FOR Counter := 1 TO PosStackpointer DO
IF (PosStack [Counter] >= Index)
THEN BEGIN
IF (PosStack [Counter] < (Index + Chars) )
THEN PosStack [Counter] := Index
ELSE DEC (PosStack [Counter], Chars) ;
END ;
ChangesMade := TRUE ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Returns the current cursor type }
{-----------------------------------------------------------------------------}

FUNCTION GetCursor : BYTE ;

VAR Reg : REGISTERS ;

BEGIN
WITH Reg DO
BEGIN
AH := 3 ;
BH := 0 ;
{ call BIOS interrupt }
INTR ($10, Reg) ;
CASE CX OF
$0607, $0B0C : GetCursor := UnderLineCursor ;
$0507, $090C : GetCursor := HalfBlockCursor ;
$0807, $0D0C : GetCursor := BlockCursor ;
$2000 : GetCursor := Inactive ;
$2001 : GetCursor := NoBlinkCursor ;
ELSE GetCursor := UnderLineCursor ;
END ; { of case }
END ; { of with }
END ;

{-----------------------------------------------------------------------------}
{ Sets a new cursor }
{-----------------------------------------------------------------------------}

PROCEDURE SetCursor (Cursor : BYTE) ;

VAR Reg : REGISTERS ;
ScrEl : ScreenElement ;

BEGIN
WITH Reg DO
BEGIN
AH := 1 ;
BH := 0 ;
{ monochrome and color cards require different settings for cursor shape }
CASE Cursor OF
Inactive : CX := $2000 ;
UnderLineCursor : IF Colorcard THEN CX := $0607 ELSE CX := $0B0C ;
HalfBlockCursor : IF Colorcard THEN CX := $0507 ELSE CX := $090C;
BlockCursor : IF Colorcard THEN CX := $0807 ELSE CX := $0D0C ;
NoBlinkCursor : CX := $2001 ;
END ; { of case }
{ call BIOS interrupt }
INTR ($10, Reg) ;
END ; { with }
IF Cursor = NoBlinkCursor
THEN BEGIN
{ put NoBlinkCursor on new position }
ScrEl := ScreenElement (DisplayPtr^ [WHEREY, WHEREX]) ;
{ set cursor attribute }
WITH ScreenColorArray [Config.Setup.ScreenColors] DO
IF WHEREY = LinesOnScreen
THEN ScrEl.Attribute := CursorAttr
ELSE ScrEl.Attribute := StatusCursorAttr ;
DisplayPtr^ [WHEREY, WHEREX] := WORD (ScrEl) ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Positions the cursor at (X,Y) }
{-----------------------------------------------------------------------------}

PROCEDURE CursorTo (X, Y : BYTE) ;

VAR ScrEl : ScreenElement ;

BEGIN
GOTOXY (X, Y) ;
IF Config.Setup.CursorType = NoBlinkCursor
THEN BEGIN
{ put NoBlinkCursor on new position }
ScrEl := ScreenElement (DisplayPtr^ [Y, X]) ;
{ set cursor attribute }
WITH ScreenColorArray [Config.Setup.ScreenColors] DO
IF WHEREY = LinesOnScreen
THEN ScrEl.Attribute := StatusCursorAttr
ELSE ScrEl.Attribute := CursorAttr ;
DisplayPtr^ [Y, X] := WORD (ScrEl) ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Produces a low beep trough the speaker, unless inhibited by Setup }
{-----------------------------------------------------------------------------}

PROCEDURE WarningBeep ;

BEGIN
IF Config.Setup.SoundBell
THEN BEGIN
SOUND (110) ;
DELAY (100) ;
NOSOUND ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Waits until a key on the keyboard is pressed and returns its key number. }
{ Control keys (cursor keys, function keys etc.) are translated to numbers }
{ above 255. }
{-----------------------------------------------------------------------------}

FUNCTION ReadKeyNr : WORD ;

VAR Regs : REGISTERS ;

BEGIN
WITH Regs DO
BEGIN
AH := 0 ;
INTR ($16, Regs) ;
{ AL now contains the ASCII value of the key, AH the scan code }
CASE AL OF
0 : IF AH = 3 THEN ReadKeyNr := 0 { ^@ }
ELSE ReadKeyNr := 256 + AH ;
8 : IF AH = 14 THEN ReadKeyNr := BkspKey
ELSE ReadKeyNr := 8 ; { ^H }
9 : IF AH = 15 THEN ReadKeyNr := TabKey
ELSE ReadKeyNr := 9 ; { ^I }
10 : IF AH = 28 THEN ReadKeyNr := CtrlReturnKey
ELSE ReadKeyNr := 10 ; { ^J }
13 : IF AH = 28 THEN ReadKeyNr := ReturnKey
ELSE ReadKeyNr := 13 ; { ^M }
27 : IF AH = 1 THEN ReadKeyNr := EscapeKey
ELSE ReadKeyNr := 27 ; { ^[ }
ELSE ReadKeyNr := AL ;
END ; { of case }
END ; { of with }
END ;

{-----------------------------------------------------------------------------}
{ Puts a line of text on the last line of the screen. }
{ Writes directly into video memory. }
{-----------------------------------------------------------------------------}

PROCEDURE SetBottomLine (LineText : STRING) ;

VAR ScrEl : ScreenElement ;
ScrElPtr : ScreenElementPtr ;
Col : BYTE ;

BEGIN
ScrElPtr := ScreenElementPtr (StatusLinePtr) ;
{ set attribute }
ScrEl.Attribute := ScreenColorArray [Config.Setup.ScreenColors].StatusAttr ;
{ fill first part of status line with LineText }
FOR Col := 1 TO LENGTH (LineText) DO
BEGIN
ScrEl.Contents := LineText [Col] ;
ScrElPtr.Ref^ := ScrEl ;
INC (ScrElPtr.OFS, 2) ;
END ;
{ fill rest of status line with spaces }
ScrEl.Contents := ' ' ;
FOR Col := (LENGTH (LineText) + 1) TO ColsOnScreen DO
BEGIN
ScrElPtr.Ref^ := ScrEl ;
INC (ScrElPtr.OFS, 2) ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Produces a message on the last line of the screen and sets MessageRead }
{-----------------------------------------------------------------------------}

PROCEDURE Message (Contents : STRING) ;

BEGIN
SetBottomLine (Contents) ;
MessageRead := (LENGTH (Contents) = 0) ;
END ;

{-----------------------------------------------------------------------------}
{ Produces an error beep (if allowed by Setup), writes an error message }
{ corresponding to the error number, on the last screen line and waits }
{ until the Escape key is pressed. }
{ If any macros are running, they are canceled. }
{-----------------------------------------------------------------------------}

PROCEDURE ErrorMessage (ErrorNr : BYTE) ;

VAR ErrorText : STRING [ColsOnScreen] ;

BEGIN
IF Config.Setup.SoundBell
THEN BEGIN
SOUND (880) ;
DELAY (100) ;
NOSOUND ;
END ;
CASE ErrorNr OF
1 : ErrorText := 'Not enough memory' ;
4 : ErrorText := 'Block too large for paste buffer' ;
5 : ErrorText := 'No block defined' ;
6 : ErrorText := 'Maximum macro length reached. End of define mode' ;
7 : ErrorText := 'File too large. Only partially read' ;
8 : ErrorText := 'File not found' ;
9 : ErrorText := 'Cyclic macro definition. Key ignored' ;
10 : ErrorText := 'Too many macros nested. Execution canceled' ;
11 : ErrorText := 'Word wrap mode must be on to do this' ;
12 : ErrorText := 'Position stack full' ;
13 : ErrorText := 'Position stack empty' ;
14 : CASE DosError OF
2 : ErrorText := 'Can not find COMMAND.COM ' ;
8 : ErrorText := 'Not enough memory to execute DOS command' ;
ELSE ErrorText := 'DOS error ' + WordToString (DosError, 2) ;
END ; { of case }
15 : ErrorText := 'String not found' ;
16 : ErrorText := 'Illegal file name' ;
17 : CASE DiskError OF
2 : ErrorText := 'File not found' ;
3 : ErrorText := 'Path not found' ;
5 : ErrorText := 'File access denied' ;
100 : ErrorText := 'Disk read error' ;
101 : ErrorText := 'Disk write error' ;
103 : ErrorText := 'File not open' ;
150 : ErrorText := 'Disk is write-protected' ;
152 : ErrorText := 'Drive not ready' ;
159 : ErrorText := 'Printer out of paper' ;
160 : ErrorText := 'Device write fault' ;
ELSE ErrorText := 'I/O error ' + WordToString (DiskError, 0) ;
END ; { of case }
18 : ErrorText := 'Macro execution interrupted' ;
19 : ErrorText := 'Bad or incompatible configuration file. Using default' ;
20 : ErrorText := 'Please enter a number' ;
21 : ErrorText := 'Number is too low' ;
22 : ErrorText := 'Number is too high' ;
23 : ErrorText := 'Bad or incompatible work file' ;
END ; { of case }
SetBottomLine (ErrorText + ' (press Esc)') ;
REPEAT UNTIL ReadKeyNr = EscapeKey ;
IF MacroStackpointer <> Inactive
THEN BEGIN
MacroStackpointer := Inactive ;
Message ('Macro execution canceled') ;
END
ELSE Message ('') ;
END ;

{-----------------------------------------------------------------------------}
{ Like the DOS batch command, Pause displays the message 'Press any key to }
{ continue' and then waits until a key is pressed. }
{-----------------------------------------------------------------------------}

PROCEDURE Pause ;

VAR DummyKey : WORD ;

BEGIN
SetBottomLine ('Press any key to continue') ;
DummyKey := ReadKeyNr ;
EscPressed := (DummyKey = EscapeKey) ;
SetBottomLine ('') ;
END ;

{-----------------------------------------------------------------------------}
{ Reads the result of the last I/O operation into the DiskError variable }
{ and produces an error message if an error has occurred. }
{-----------------------------------------------------------------------------}

PROCEDURE CheckDiskError ;

BEGIN
DiskError := IORESULT ;
IF DiskError <> 0 THEN ErrorMessage (17) ;
END ;

{-----------------------------------------------------------------------------}
{ Draws a frame on the text screen between (X1,Y1) and (X2,Y2) }
{-----------------------------------------------------------------------------}

PROCEDURE PutFrame (X1, Y1, X2, Y2 : BYTE ; Border : STRING) ;

VAR i : BYTE ;

BEGIN
CursorTo (X1, Y1) ; WRITE (Border [1]) ; { upper left corner }
FOR i := SUCC (X1) TO PRED (X2) DO WRITE (Border [2]) ; { upper side }
WRITE (Border [3]) ; { upper right corner }
FOR i := SUCC (Y1) TO PRED (Y2) DO
BEGIN
CursorTo (X1, i) ; WRITE (Border [8]) ; { left side }
CursorTo (X2, i) ; WRITE (Border [4]) ; { right side }
END ;
CursorTo (X1, Y2) ; WRITE (Border [7]) ; { lower right corner }
FOR i := SUCC (X1) TO PRED (X2) DO WRITE (Border [6]) ; { lower side }
WRITE (Border [5]) ; { lower left corner }
END ;

{-----------------------------------------------------------------------------}
{ Clears a rectangular screen area between (X1,Y1) and (X2,Y2). }
{-----------------------------------------------------------------------------}

PROCEDURE ClearArea (X1, Y1, X2, Y2 : BYTE) ;

VAR OldWindMax, OldWindMin : WORD ;

BEGIN
OldWindMax := WindMax ;
OldWindMin := WindMin ;
WINDOW (X1, Y1, X2, Y2) ;
CLRSCR ;
WINDOW (LO (OldWindMin) + 1, HI (OldWindMin) + 1,
LO (OldWindMax) + 1, HI (OldWindMax) + 1) ;
END ;

{-----------------------------------------------------------------------------}
{ Clears the current workspace, resetting all variables. }
{-----------------------------------------------------------------------------}

PROCEDURE ClearCurrentWs ;

BEGIN
WITH Workspace [CurrentWsnr] DO
BEGIN
Name := '' ;
ChangesMade := FALSE ;
GETTIME (LastTimeSaved [1], LastTimeSaved [2],
LastTimeSaved [3], LastTimeSaved [4]) ;
CurPos.Index := 1 ;
CurPos.Linenr := 1 ;
CurPos.Colnr := 1 ;
MARK := Inactive ;
FirstVisibleLine := CurPos ;
FirstScreenCol := 1 ;
VirtualColnr := 1 ;
Buffer^ [1] := EF ;
Buffersize := 1 ;
PosStackPointer := Inactive ;
END ;
{ make copy of current workspace equal to original }
CurrentWs := Workspace [CurrentWsnr] ;
END ;

{-----------------------------------------------------------------------------}
{ Clears the keys in the keyboard buffer. }
{-----------------------------------------------------------------------------}

PROCEDURE ClearKeyBuffer ;

VAR DummyKey : CHAR ;

BEGIN
WHILE KEYPRESSED DO DummyKey := READKEY ;
END ;


{-----------------------------------------------------------------------------}
{ Checks if the Escape key has been pressed }
{-----------------------------------------------------------------------------}

PROCEDURE CheckEsc ;

BEGIN
EscPressed := FALSE ;
WHILE KEYPRESSED DO
IF READKEY = ESC THEN EscPressed := TRUE ;
END ;

{-----------------------------------------------------------------------------}
{ Creates an empty history with lines of chars long }
{-----------------------------------------------------------------------------}

PROCEDURE CreateHistory (VAR Hp : HistPtr ; LineLen : BYTE) ;

VAR i : BYTE ;

BEGIN
NEW (Hp) ;
FOR i := 1 TO MaxHistLength DO
GETMEM (POINTER(Hp^.LINE [i]), LineLen + 1) ;
Hp^.MaxLineLen := LineLen ;
Hp^.Len := 0 ;
Hp^.CurLine := 0 ;
END ;

{-----------------------------------------------------------------------------}
{ Adds a new string to a history, unless already present }
{-----------------------------------------------------------------------------}

PROCEDURE AddToHistory (Hp : HistPtr ; S : STRING) ;

VAR i,j : BYTE ;

BEGIN
WITH Hp^ DO
BEGIN
{ check if line already present in history }
i := 1 ;
WHILE (i < Len ) AND (S <> LINE [i]^) DO
INC (i) ;
IF (Len > 0) AND (S = LINE[i]^)
THEN BEGIN
{ move this line to top of history }
FOR j := i TO (Len-1) DO
LINE[j]^ := LINE[j+1]^ ;
LINE[Len]^ := S ;
END
ELSE BEGIN
{ add line to end of history }
IF Len < MaxHistLength
THEN { expand history }
INC (Len)
ELSE { history full: shift lines, losing the oldest one }
FOR i := 1 TO (Len - 1) DO
LINE [i]^ := LINE [i + 1]^ ;
LINE [Len]^ := COPY (S, 1, MaxLineLen) ;
END ;
{ set current line so that next PrevHistLine returns this line }
CurLine := 0 ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Returns the current history line }
{-----------------------------------------------------------------------------}

FUNCTION CurrentHistLine (Hp : HistPtr) : STRING ;

BEGIN
WITH Hp^ DO
IF (Len = 0) OR (CurLine = 0)
THEN CurrentHistLine := ''
ELSE CurrentHistLine := LINE [CurLine]^ ;
END ;

{-----------------------------------------------------------------------------}
{ Returns the history line above the current one }
{-----------------------------------------------------------------------------}

FUNCTION NextHistLine (Hp : HistPtr) : STRING ;

BEGIN
WITH Hp^ DO
BEGIN
IF CurLine = Len
THEN CurLine := 0
ELSE INC (CurLine) ;
NextHistLine := CurrentHistLine (Hp) ;
END ;

END ;

{-----------------------------------------------------------------------------}
{ Returns the history line below the current one }
{-----------------------------------------------------------------------------}

FUNCTION PrevHistLine (Hp : HistPtr) : STRING ;

BEGIN
WITH Hp^ DO
BEGIN
IF CurLine = 0
THEN CurLine := Len
ELSE DEC (CurLine) ;
PrevHistLine := CurrentHistLine (Hp) ;
END ;
END ;

{-----------------------------------------------------------------------------}
{ Determines the left margin of the current line. Position P must be after }
{ the first non-space, otherwise the result is 1. }
{-----------------------------------------------------------------------------}

FUNCTION LeftMargin (VAR P : Position) : WORD ;

VAR Counter : WORD ;

BEGIN
WITH CurrentWs DO
BEGIN
{ look for first non-space on current line }
Counter := 1 ;
WHILE (Buffer^ [P.Index - P.Colnr + Counter] = ' ') AND
(Counter <= P.Colnr) DO
INC (Counter) ;
IF (Counter > P.Colnr)
THEN LeftMargin := 1
ELSE LeftMargin := Counter ;
END ; { of with }
END ;

{-----------------------------------------------------------------------------}
{ GetMem is redirected, to keep track of available memory. }
{-----------------------------------------------------------------------------}

{$IFDEF DEVELOP }
PROCEDURE GetMem (VAR P : pointer ; Size : WORD ) ;

BEGIN
System.GetMem (P, Size) ;
IF MEMAVAIL < MinMemAvail
THEN MinMemAvail := MEMAVAIL ;
END ;
{$ENDIF }

{-----------------------------------------------------------------------------}

END.


  3 Responses to “Category : Word Processors
Archive   : AE170.ZIP
Filename : AE1.PAS

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/