home *** CD-ROM | disk | FTP | other *** search
- {$B+} {Boolean complete evaluation on}
- {$I+} {I/O checking on}
- {$N-} {No numeric coprocessor}
- {$R-} {Range checking off}
- {$S+} {Stack checking on}
- {$V-} {Var String checking off}
-
- Program Note;
-
- {************************************************************************}
- {* Copyright (c) Steve Edwards, TurboWorks Software, 1988 *}
- {* Released to the public domain for personal , non-commercial use only *}
- {************************************************************************}
-
- {*********************** --- IBM PC SPECIFIC --- ************************}
- {* Written 9/12/88, Steve Edwards, 501-575-6814 *}
- {* Updated 10/13/88 for faster video writes. *}
- {* *}
- {* NOTE is a full screen editor which is designed to function as a *}
- {* programmer's editor for MS-DOS. Most of the keyboard commands *}
- {* are similar to WordStar , with some special extensions for this *}
- {* editor. Requires Turbo Pascal Ver 4.0 to compile as it stands. *}
- {* *}
- {* FEATURES: *}
- {* Filenames may include drive and path *}
- {* size of files limited to available memory *}
- {* full cursory key usage *}
- {* full forward and reverse scrolling at high speed *}
- {* horizontal scrolling *}
- {* on-line help ( press F1 for help ) *}
- {* search for strings ( forward mode only ) *}
- {* search & replace strings ( forward mode only ) *}
- {* block commands -- copy, move, delete, write *}
- {* *}
- {************************************************************************}
-
- Uses Crt,
- Dos,
- Printer;
-
- Const
- MaxWidth = 128;
- RtMrg : Integer = 76;
- LeftM : Integer = 1;
- Wrap : Boolean = True;
- InSrt : Boolean = True;
- GoodColorCard : Boolean = True; {set false for IBM CGA}
-
- Type
- Line = String[MaxWidth];
- LPtr = ^LineRec;
- LineRec = Record
- Last : LPtr;
- Data : Line;
- Next : LPtr;
- End;
- ScreenLine = String[80];
- String80 = String[80];
- Word = String[24];
-
- Var
- LWord : ScreenLine; { left margin spacer }
- Find ,Repl ,
- InPut,OutPut : Word;
- Fore , Back, Attr : Byte; { text colors for Write}
- BaseOfScreen,Mode : LongInt; { used by FASTWRITE }
- WaitforRetrace : Boolean; { " " " }
- VidStatPort, VidModePort : LongInt; { " " " }
- ModePortData : Byte Absolute $40 : $65; { }
- SearchString,
- Replacement : ScreenLine;
- TextLine ,BlankLine : ScreenLine;
- FileFound,
- Finished ,Changed : Boolean;
- TabSet : Array [1..MaxWidth] Of Boolean;
- TextFile : Text;
- WorkFile : Text;
- Ln,LastLn,NextLn,
- FirstLn,EndLn : LPtr;
- MaxLines : Integer ;
- IBeg , IEnd : Integer ;
- BlockBeg, BlockEnd : LPtr;
- I , J, {cursor position: i = line, j = column}
- Len, {length of current line}
- NLines, {length of file}
- NBl, {number of buffer lines}
- Top, {first line on screen}
- Offset, K, N : Integer;
- Choice, Ch : Char;
-
- (*-------------------------------------------------------------------*)
-
- Function YN: Boolean;
- Begin
- Repeat
- Ch := ReadKey
- Until Ch In['y','Y','n','N'];
- If UpCase(Ch) = 'Y' Then
- YN := True
- Else YN := False;
- End;
-
- Procedure Beep;
- Begin
- Sound(800);
- Delay(400);
- NoSound;
- Delay(1000);
- End;
-
- Procedure Capitalize(var fname:word);
- Begin
- For J := 1 To Length(FName) Do
- FName[J] := UpCase(FName[J]);
- End;
-
- Procedure ReadFile;
- Var OvFlw : Boolean;
- InputLine : String[255];
- Begin
- If ParamStr(1) = '' Then
- Begin
- Write('File to edit: ');
- ReadLn(Input);
- End
- Else
- InPut := ParamStr(1);
- Capitalize(Input);
- New(Ln);
- Ln^.Data := '';
- FirstLn := Ln;
- EndLn := Ln;
- Assign(WorkFile,Input);
- {$I-} ReSet(WorkFile); {I+}
- If IoResult = 0 Then
- Begin
- OvFlw := False;
- MaxLines := MemAvail Div 12;
- If MaxLines < 0 Then
- MaxLines := 2730;
- NLines := 0;
- Write(' Reading file ');
- While Not (Eof(WorkFile) Or OvFlw) Do
- Begin
- ReadLn(WorkFile,InputLine);
- If Length(InputLine) > MaxWidth Then
- Begin
- WriteLn('File is too fat for this editor');
- OvFlw := True; Delay(1000);
- End
- Else
- Begin
- Ln^.Data := InputLine;
- LastLn := Ln;
- New(Ln);
- Ln^.data := '';
- Ln^.last := LastLn;
- LastLn^.Next := Ln;
- NLines := NLines + 1;
- If NLines > MaxLines Then
- Begin
- WriteLn('File is too long. Not enough memory');
- OvFlw := True; Delay(1000);
- End;
- End;
- End; {not EOF}
- EndLn := Ln;
- If Not OvFlw Then
- FileFound := True;
- End {IOresult = 0}
- Else
- Begin
- Write('Can''t find this file. Is this a new file?');
- If YN Then
- Begin
- FileFound := True;
- NLines := 1;
- New(Ln);
- Ln^.Data := '';
- FirstLn^.Next := Ln;
- Ln^.Last := FirstLn;
- EndLn := Ln;
- End
- Else
- FileFound := False;
- End;
- Close(WorkFile);
- End;
-
- Procedure WriteFile; { save changes to file }
- Begin
- GotoXY(1,1); For J := 1 To 45 Do Write(' ');
- GotoXY(1,1); Write('Text was changed. Save? ');
- If YN Then
- Begin
- Write('as: '); ReadLn(OutPut);
- If OutPut = '' Then
- OutPut := Input;
- Capitalize(OutPut);
- GotoXY(40,1); WriteLn(' Writing to disk as ',OutPut);
- Assign(WorkFile,OutPut);
- ReWrite(WorkFile);
- Ln := EndLn^.Next;
- Repeat
- WriteLn(WorkFile,Ln^.Data);
- Ln := Ln^.Next
- Until Ln = EndLn;
- Close(WorkFile);
- End;
- End;
-
- {------------------------- FastWrite Routines -------------------------}
-
- Function Attribute(Foreground, Background : Byte) : Byte;
- {-Translates foreground and background colors into video attributes.
- "And 127" masks out the blink bit. Add 128 to the result to set it.}
- Begin
- Attribute := ((Background Shl 4) + Foreground) And 127;
- End;
-
- Function EgaInstalled : Boolean;
- {-Test for presence of the EGA. I have little idea how this works, but
- it does.}
- Begin
- Inline(
- $B8/$00/$12 { MOV AX,$1200}
- /$BB/$10/$00 { MOV BX,$10}
- /$B9/$FF/$FF { MOV CX,$FFFF}
- /$CD/$10 { INT $10}
- /$31/$C0 { XOR AX,AX}
- /$81/$F9/$FF/$FF { CMP CX,$FFFF}
- /$74/$01 { JE DONE}
- /$40 { INC AX}
- /$88/$46/$04 {DONE: MOV [BP+$04],AL}
- );
- End;
-
- Procedure GetVideoMode;
- {-Video mode of 7 indicates mono display; all other modes are for color
- displays. This routine MUST be called before any of the screen writing
- routines are used!}
- Var
- Mode : Integer;
- Vid : Integer Absolute $40 : $63;
- Begin
- Inline(
- $B4/$0F {MOV AH,$F}
- /$CD/$10 {INT $10}
- /$30/$E4 {XOR AH,AH}
- /$89/$46/<Mode {MOV [BP+<Mode],AX}
- );
- If Mode = 6 Then Mode := 7;
- If Mode = 7 Then BaseOfScreen := $B000 { Mono }
- Else BaseOfScreen := $B800; { Color }
- VidStatPort := Vid + 6; {video status port for either card}
- VidModePort := Vid + 4; {video mode port for either card}
- WaitForRetrace := (BaseOfScreen = $B800) And Not EgaInstalled;
- { *VERY IMPORTANT* WaitForRetrace MUST be false if BaseOfScreen = $B000. }
- End;
-
- Procedure VideoOff;
- {-avoid snow writing full screen to c/g card}
- Begin
- {clear video enable bit}
- Port[VidModePort] := ModePortData And 247;
- End;
-
- Procedure VideoOn;
- {-reenable video}
- Begin
- {set video enable bit}
- Port[VidModePort] := ModePortData Or 8;
- End;
-
- Procedure FastWrite( St : String80; Row, Col, Attr : Byte );
- {-Write St directly to video memory, without snow.}
- Begin
- Inline(
- $1E { PUSH DS ;Save DS}
- /$31/$C0 { XOR AX,AX ;AX = 0}
- /$88/$C1 { MOV CL,AL ;CL = 0}
- /$8A/$AE/>Row { MOV CH,[BP+>Row] ;CX = Row * 256}
- /$FE/$CD { DEC CH ;Row to 0..24 range}
- /$D1/$E9 { SHR CX,1 ;CX = Row * 128}
- /$89/$CF { MOV DI,CX ;Store in DI}
- /$D1/$EF { SHR DI,1 ;DI = Row * 64}
- /$D1/$EF { SHR DI,1 ;DI = Row * 32}
- /$01/$CF { ADD DI,CX ;DI = (Row * 160)}
- /$8B/$8E/>Col { MOV CX,[BP+>Col] ;CX = Column}
- /$49 { DEC CX ;Col to 0..79 range}
- /$D1/$E1 { SHL CX,1 ;Account for attribute bytes}
- /$01/$CF { ADD DI,CX ;DI = (Row * 160) + (Col * 2)}
- /$8E/$06/>BaseOfScreen { MOV ES,[>BaseOfScreen] ;ES:DI points to Base:Row,Col}
- /$8A/$0E/>WaitForRetrace{ MOV CL,[>WaitForRetrace] ;Grab this before changing DS}
- /$8C/$D2 { MOV DX,SS ;Move SS...}
- /$8E/$DA { MOV DS,DX ; into DS}
- /$8D/$B6/>St { LEA SI,[BP+>St] ;DS:SI points to St[0]}
- /$FC { CLD ;Set direction to forward}
- /$AC { LODSB ;AX = Length(St); DS:SI -> St[1]}
- /$91 { XCHG AX,CX ;CX = Length; AL = Wait}
- /$E3/$29 { JCXZ Exit ;If string empty, Exit}
- /$8A/$A6/>Attr { MOV AH,[BP+>Attr] ;AH = Attribute}
- /$D0/$D8 { RCR AL,1 ;If WaitForRetrace is False...}
- /$73/$1D { JNC NoWait ; use NoWait routine}
- /$BA/$DA/$03 { MOV DX,$03DA ;Point DX to CGA status port}
- /$AC {Next: LODSB ;Load next character into AL}
- { ; AH already has Attr}
- /$89/$C3 { MOV BX,AX ;Store video word in BX}
- /$FA { CLI ;No interrupts now}
- /$EC {WaitNoH: IN AL,DX ;Get 6845 status}
- /$A8/$08 { TEST AL,8 ;Check for vertical retrace}
- /$75/$09 { JNZ Store ; In progress? go}
- /$D0/$D8 { RCR AL,1 ;Else, wait for end of}
- /$72/$F7 { JC WaitNoH ; horizontal retrace}
- /$EC {WaitH: IN AL,DX ;Get 6845 status again}
- /$D0/$D8 { RCR AL,1 ;Wait for horizontal}
- /$73/$FB { JNC WaitH ; retrace}
- /$89/$D8 {Store: MOV AX,BX ;Move word back to AX...}
- /$AB { STOSW ; and then to screen}
- /$FB { STI ;Allow interrupts}
- /$E2/$E8 { LOOP Next ;Get next character}
- /$EB/$04 { JMP SHORT Exit ;Done}
- /$AC {NoWait: LODSB ;Load next character into AL}
- { ; AH already has Attr}
- /$AB { STOSW ;Move video word into place}
- /$E2/$FC { LOOP NoWait ;Get next character}
- /$1F {Exit: POP DS ;Restore DS}
- );
- End;
-
- Procedure FastWriteV( Var St; Row, Col, Attr : Byte );
- {-Works with string variables ONLY. (I made St an untyped parameter
- only to make this easier to use when type checking is on.) This is
- just FastWrite optimized for use with string Variables, for times
- when speed really matters.}
- Begin
- Inline(
- $1E { PUSH DS}
- /$31/$C0 { XOR AX,AX}
- /$88/$C1 { MOV CL,AL}
- /$8A/$6E/<Row { MOV CH,[BP+<Row]}
- /$FE/$CD { DEC CH}
- /$D1/$E9 { SHR CX,1}
- /$89/$CF { MOV DI,CX}
- /$D1/$EF { SHR DI,1}
- /$D1/$EF { SHR DI,1}
- /$01/$CF { ADD DI,CX}
- /$8B/$4E/<Col { MOV CX,[BP+<Col]}
- /$49 { DEC CX}
- /$D1/$E1 { SHL CX,1}
- /$01/$CF { ADD DI,CX}
- /$8E/$06/>BaseOfScreen { MOV ES,[>BaseOfScreen]}
- /$8A/$0E/>WaitForRetrace{ MOV CL,[>WaitForRetrace]}
- /$C5/$76/<St { LDS SI,[BP+<St] ;DS:SI points to St[0]}
- /$FC { CLD}
- /$AC { LODSB}
- /$91 { XCHG AX,CX}
- /$E3/$28 { JCXZ Exit}
- /$8A/$66/<Attr { MOV AH,[BP+<Attr]}
- /$D0/$D8 { RCR AL,1}
- /$73/$1D { JNC NoWait}
- /$BA/$DA/$03 { MOV DX,$03DA}
- /$AC {Next: LODSB}
- /$89/$C3 { MOV BX,AX}
- /$FA { CLI}
- /$EC {WaitNoH: IN AL,DX}
- /$A8/$08 { TEST AL,8}
- /$75/$09 { JNZ Store}
- /$D0/$D8 { RCR AL,1}
- /$72/$F7 { JC WaitNoH}
- /$EC {WaitH: IN AL,DX}
- /$D0/$D8 { RCR AL,1}
- /$73/$FB { JNC WaitH}
- /$89/$D8 {Store: MOV AX,BX}
- /$AB { STOSW}
- /$FB { STI}
- /$E2/$E8 { LOOP Next}
- /$EB/$04 { JMP SHORT Exit}
- /$AC {NoWait: LODSB}
- /$AB { STOSW}
- /$E2/$FC { LOOP NoWait}
- /$1F {Exit: POP DS}
- );
- End;
-
- {------------------------- FastWrite Routines -------------------------}
-
- Procedure RulerLine;
- Var
- C , J : Byte;
- Begin
- TextLine := BlankLine;
- For J := 1 To 79 Do
- Begin
- If J Mod 5 = 0 Then
- TextLine[J] := '+'
- Else
- TextLine[J] := '-';
- C := 48 + ((J + Offset) Div 10) Mod 10 ;
- If J Mod 10 = 0 Then
- TextLine[J] := Chr(C);
- End;
- FastWriteV(TextLine,2,1, Attr);
- If (Wrap) Then { put margin markers on ruler }
- Begin
- Textcolor(14);
- TextBackGround(Green);
- if LeftM >= Offset Then
- Begin
- GotoXY(LeftM - Offset + 1, 2);
- Write('|');
- End;
- If RtMrg >= Offset Then
- Begin
- GotoXY(RtMrg - Offset + 1, 2);
- Write('|');
- End;
- TextColor( Fore );
- TextBackGround( Back );
- End;
- End;
-
- Procedure StatusLine;
- Begin
- Textline := BlankLine;
- Insert(' Line: Column:',TextLine,1);
- If Insrt Then Insert('Insert ',TextLine,26)
- Else Insert('OverWrite ',TextLine,25);
- If Wrap Then Insert(' WordWrap',TextLine,35)
- Else Insert(' NoWrap ',TextLine,35);
- Insert(' Workfile:',TextLine,47);
- Insert(Input,TextLine,58);
- FastWriteV(TextLine,1,1,Attr);
- RulerLine;
- End;
-
- Procedure WriteLine(Row,Attr:Byte); { direct write to screen }
- Var Len : Byte; { writes blanks where there is no text}
- Contents : ScreenLine;
- Begin
- TextLine := BlankLine;
- Contents := Copy(Ln^.Data,Offset,80);
- Len := Ord(Contents[0]);
- Insert(Contents,TextLine,1);
- If Len = 80 Then TextLine[80] := '+'
- Else If Len > 0 Then TextLine[80] := '<';
- FastWriteV(TextLine,Row,1,Attr);
- End;
-
- Procedure Screen; { rewrites the bottom 23 lines }
- Var Row : Byte;
- TopLn : LPtr;
- Begin { makes sure i and ln are in register }
- Ln := EndLn^.Next;
- If Top > 1 Then
- For K := 2 To Top Do
- Ln := Ln^.Next;
- TopLn := Ln;
- For Row := 3 to 25 do
- Begin
- WriteLine(Row,Attr);
- If Ln <> EndLn Then
- Ln := Ln^.Next;
- End;
- Ln := TopLn;
- Row := I - Top;
- While Row > 0 do
- Begin
- Ln := Ln^.Next;
- Row := Row - 1;
- End;
- End;
-
- Procedure Help;
- Begin
- Window(1, 1, 80, 25);
- ClrScr; GetVideoMode;
- FastWrite('╔══════════════════════════════════════════════════════════════════════════════╗', 1, 1, Attr ); GetVideoMode ;
- FastWrite('║ Window Editor -- by TurboWorks Software ║', 2, 1, Attr ); GetVideoMode ;
- FastWrite('║ ┌───────────────────────┐ ┌───────────────────────┐ ┌──────────────────────┐ ║', 3, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^X line up │ │ ^S column left │ │ Alt-A Ascii │ ║', 4, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^E line down │ │ ^D column right │ │ Alt-B Back Color │ ║', 5, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^C page up │ │ ^PgUp file home │ │ Alt-C Copy Block │ ║', 6, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^R page down │ │ ^PgDn file end │ │ Alt-D Del Block │ ║', 7, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^K quit │ │ ^N insert line │ │ Alt-F Fore Color │ ║', 8, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^P set margins │ │ ^Y delete line │ │ Alt-G Goto Block │ ║', 9, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^BkSp delete word │ │ BkSp delete char │ │ Alt-M Move Block │ ║',10, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^V toggle ins │ │ Ins toggle insert │ │ Alt-N Clr Marks │ ║',11, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^W window dn │ │ │ │ Alt-S Beg Block │ ║',12, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^Z window up │ │ Del delete char │ │ Alt-T End Block │ ║',13, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^Home erase bol │ │ Home beg of line │ │ │ ║',14, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^End erase eol │ │ End end of line │ │ │ ║',15, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^F next word │ │ Tab next tab stop │ │ │ ║',16, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ ^A prev word │ │ BTab last tab stop │ │ │ ║',17, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ F1 help │ │ F6 replace │ │ │ ║',18, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ F2 clear marks │ │ F7 page up │ │ │ ║',19, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ F3 quit │ │ F8 page down │ │ │ ║',20, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ F4 set margins │ │ F9 prev word │ │ │ ║',21, 1, Attr ); GetVideoMode ;
- FastWrite('║ │ F5 search │ │ F10 next word │ │ │ ║',22, 1, Attr ); GetVideoMode ;
- FastWrite('║ └───────────────────────┘ └───────────────────────┘ └──────────────────────┘ ║',23, 1, Attr ); GetVideoMode ;
- FastWrite('║ Press any key to return to your editing..... ║',24, 1, Attr ); GetVideoMode ;
- FastWrite('╚══════════════════════════════════════════════════════════════════════════════╝',25, 1, Attr ); GetVideoMode ;
- Repeat
- Until KeyPressed;
- Ch := ReadKey;
- StatusLine;
- Screen;
- End;
-
- Procedure PageUp;
- Begin
- If Top > 22 Then Begin
- Top := Top - 22; I := I - 22; End
- Else Begin
- I := I - Top + 1; Top := 1; End;
- Screen;
- End;
-
- Procedure PageDown;
- begin
- If Top <= (NLines - 44) Then
- Begin
- Top := Top + 22;
- I := I + 22;
- End
- Else If NLines > 22 Then
- Begin
- I := I - Top + NLines - 22;
- Top := NLines - 22;
- End;
- Screen;
- End;
-
- Procedure Cursor; { make sure the cursor is visible on the screen }
- Var ii,jj,chgd : Word;
- Shifted : Boolean;
- Begin
- Shifted := False;
- If I < 1 Then
- Begin
- I := 1;
- Ln := EndLn^.Next;
- End;
- If I > NLines Then
- Begin
- I := NLines;
- Ln := EndLn^.Last;
- End;
- If J < 1 Then
- J := 1;
- If J > MaxWidth Then
- J := MaxWidth;
- Len := Ord(Ln^.Data[0]);
- If ( J > Offset + 77 ) Then
- Begin
- Offset := 10 * ( J Div 10 ) - 59;
- Shifted := True;
- End;
- If J < Offset Then
- Begin
- Offset := 10 * ( ( J - 10 ) Div 10 ) + 1;
- Shifted := True;
- End;
- If I < Top Then
- Begin
- Top := I;
- Shifted := True;
- End;
- If I > Top + 22 Then
- Begin
- Top := I - 22;
- Shifted := True;
- End;
- If Shifted Then
- Begin
- RulerLine;
- Screen;
- End;
- Str(i:4,ii);
- Str(j:3,jj);
- If Changed Then Chgd := ' * '
- Else Chgd := ' ';
- FastWriteV(ii,1,7,Attr); GetVideoMode;
- FastWriteV(jj,1,20,Attr); GetVideoMode;
- FastWriteV(Chgd,1,76,Attr); GetVideoMode;
- GotoXY( J - Offset + 1, i - top + 3);
- End;
-
- Procedure CursorLeft;
- Begin
- J := J - 1;
- If J < 1 Then
- Begin
- I := I - 1;
- If I < 1 Then
- Begin
- I := 1;
- J := 1;
- Ln := EndLn^.Next ;
- Exit;
- End;
- J := Length(Ln^.Last^.Data) + 1 ;
- Ln := Ln^.Last ;
- End
- End;
-
- Procedure CursorRight;
- Begin
- j := j + 1;
- if j > MaxWidth then
- Begin
- i := i + 1;
- If I > NLines then
- Begin
- I := NLines;
- Ln := EndLn^.Last ;
- End
- Else If I < NLines Then
- Ln := Ln^.Next ;
- J := 1;
- End;
- End;
-
- Procedure ParaForm; { set margins, wordwrap on/off }
- Begin
- GotoXY(1,1); ClrEol;
- Write('WordWrap? ');
- If YN Then
- Wrap := True
- Else
- Begin
- Wrap := False;
- LeftM := 1;
- LWord := '';
- End;
- If Wrap Then
- Begin
- GotoXY(15,1); Write('Left margin: ');
- ReadLn(LeftM);
- LWord := '';
- While Length(LWord) < LeftM - 1 Do
- LWord := LWord + ' ';
- RulerLine;
- Repeat
- GotoXY(35,1); Write('Right margin: ');
- ReadLn(RtMrg);
- Until RtMrg > LeftM + 24;
- End;
- ClrScr;
- StatusLine;
- Screen;
- End; { ParaForm }
-
- Procedure InsertLn(contents:line); {insert after current line}
- Begin
- New(NextLn);
- NextLn^.Data := Contents;
- NextLn^.Last := Ln;
- NextLn^.Next := Ln^.Next;
- Ln^.Next^.Last := NextLn;
- Ln^.Next := NextLn;
- NLines := NLines + 1;
- End;
-
- Procedure CutLine; { start new line after <CR> }
- Var
- More : Line;
- Begin
- More := Copy(Ln^.Data,J,Len-J+1);
- Delete(Ln^.Data,J,Len-J+1);
- InsertLn(LWord + More);
- i := i + 1;
- j := LeftM;
- Screen;
- End;
-
- Procedure WordWrap;
- Begin
- N := 0;
- Repeat
- J := J - 1;
- N := N + 1;
- Until (Ln^.Data[J] = ' ') Or (J = 1);
- J := J + 1;
- Len := Len + 1;
- CutLine;
- J := LeftM + N - 1 ;
- end;
-
- Procedure StackLine; { put current line on top of previous line }
- begin
- j := length(ln^.last^.data)+1;
- ln^.last^.data := ln^.last^.data + ln^.data;
- ln^.last^.next := ln^.next; { isolate current line }
- ln^.next^.last := ln^.last;
- Dispose(Ln); { and zap it}
- I := I - 1;
- NLines := NLines - 1;
- Screen;
- End;
-
- Procedure DeleteLine;
- Begin
- Ln^.Last^.Next := Ln^.Next; { isolate current line }
- Ln^.Next^.Last := Ln^.Last;
- Dispose(Ln); { and zap it}
- J := 1 ; I := I - 1;
- NLines := NLines - 1;
- Changed := True;
- StatusLine;
- Screen;
- End;
-
- Procedure DeleteEOL;
- Begin
- If J < MaxWidth Then
- Begin
- Ln^.Data := Copy ( Ln^.Data, 1 , J - 1 ) ;
- Changed := True;
- End;
- If J > 1 Then
- J := J - 1;
- StatusLine ;
- Screen ;
- End;
-
- Procedure DeleteBOL;
- Begin
- If J > 1 Then
- Begin
- Ln^.Data := Copy ( BlankLine, 1, J ) + Copy ( Ln^.Data, J + 1 , MaxWidth ) ;
- Changed := True;
- End;
- If J < MaxWidth Then
- J := J + 1;
- StatusLine ;
- Screen ;
- End;
-
- Procedure DeleteWord;
- Var
- EndW : Byte;
- Begin
- While (( Copy(Ln^.Data,J,1) <> ' ' ) And ( J > 0 )) Do
- J := J - 1 ;
- If J = 0 Then
- J := 1 ;
- EndW := J + 1;
- While (( Copy(Ln^.Data,EndW,1) <> ' ' ) And ( EndW < MaxWidth )) Do
- EndW := EndW + 1 ;
- If J = 1 Then
- Ln^.Data := Copy ( Ln^.Data , EndW + 1, MaxWidth )
- Else
- Ln^.Data := Copy ( Ln^.Data, 1, J ) + Copy ( Ln^.Data , EndW + 1, MaxWidth ) ;
- Changed := True ;
- StatusLine ;
- Screen ;
- End;
-
- Procedure PrevWord;
- Begin
- (* if i am in a word then skip to the space *)
- While (Not ((Ln^.Data[j] = ' ') Or ( j >= Length(Ln^.Data) ))) And
- (( i <> 1 ) Or ( j <> 1 )) Do
- CursorLeft;
- (* find end of previous word *)
- While ((Ln^.Data[j] = ' ') Or ( j >= Length(Ln^.Data) )) And
- (( i <> 1 ) Or ( j <> 1 )) Do
- CursorLeft;
- (* find start of previous word *)
- While (Not ((Ln^.Data[j] = ' ') Or ( j >= Length(Ln^.Data) ))) And
- (( i <> 1 ) Or ( j <> 1 )) do
- CursorLeft;
- CursorRight;
- End;
-
- Procedure NextWord;
- Begin
- (* if i am in a word, then move to the whitespace *)
- while (not ((Ln^.Data[j] = ' ') or ( j >= length(Ln^.Data)))) and
- ( i < NLines ) do
- CursorRight;
- (* skip over the space to the other word *)
- while ((Ln^.Data[j] = ' ') or ( j >= Length(Ln^.Data))) and
- ( i < NLines ) do
- CursorRight;
- End;
-
- Procedure Tab;
- Begin
- If J < MaxWidth Then
- Begin
- Repeat
- J := J + 1;
- Until ( TabSet [J]= True ) Or ( J = MaxWidth );
- End;
- End;
-
- Procedure BackTab;
- Begin
- If J > 1 Then
- Begin
- Repeat
- J := J - 1;
- Until ( TabSet [J]= True ) Or ( J = 1 );
- End;
- End;
-
- Procedure Search;
- var
- Temp : ScreenLine;
- Pointer, Position : Integer;
- LocPtr , Location : Integer;
- TmpPtr : LPtr;
- Begin
- Window(1, 1, 80, 25);
- GotoXY(1, 1); ClrEol;
- Write('Search: Enter string: <',SearchString,'> ');
- Temp := '';
- ReadLn(Temp);
- If Temp <> '' Then
- SearchString := Temp;
- If Length( SearchString ) = 0 Then
- Begin
- StatusLine;
- Screen;
- Exit;
- End;
- GotoXY(1,1); ClrEol;
- Write('Searching...');
- NextWord;
- TmpPtr := Ln;
- LocPtr := J;
- For Location := I + 1 To NLines Do
- begin
- (* look for matches on this line *)
- Pointer := Pos (SearchString, Copy(Ln^.Data,LocPtr,MaxWidth));
- (* if there was a match then get ready to print it *)
- If (Pointer > 0) Then
- Begin
- I := Location - 1 ;
- J := Pointer;
- StatusLine;
- Screen;
- Exit;
- End
- Else If Location <> NLines Then
- Begin
- Ln := Ln^.Next ;
- LocPtr := 1 ;
- End
- End;
- Window(1, 1, 80, 25);
- GotoXY(1, 1); ClrEol;
- Write('Search string not found. Press any key to exit...');
- Repeat
- Until KeyPressed;
- Ch := ReadKey;
- Ln := TmpPtr ;
- StatusLine;
- Screen;
- End;
-
- Procedure Replace;
- Var
- Temp : ScreenLine;
- Pointer , Position : Integer;
- Location, Len : Integer;
- Begin
- Window(1, 1, 80, 25);
- GotoXY(1, 1); ClrEol;
- Write('Replace: Enter search string: <',SearchString,'> ');
- Temp := '';
- ReadLn(Temp);
- If Temp <> '' Then
- SearchString := Temp;
- If Length(SearchString) = 0 Then
- Begin
- StatusLine;
- Screen;
- Exit;
- End;
- GotoXY(1, 1); ClrEol;
- Write('Replace: Enter replacement string: <',replacement,'> ');
- Temp := '';
- ReadLn(Temp);
- if Temp <> '' Then
- Replacement := Temp;
- Len := Length (Replacement);
- Ln := EndLn^.Next ;
- I := 1 ; J := 1 ;
- GotoXY(1, 1); ClrEol;
- Write('Searching...');
- For Location := 1 to NLines Do
- Begin
- (* look for matches on this line *)
- Position := Pos (SearchString, Ln^.Data );
- (* if there was a match then get ready to print it *)
- While (Position > 0) Do
- Begin
- I := Location ;
- J := Position ;
- If Location > 8 Then
- Top := Location - 8
- Else
- Top := 1 ;
- Screen ;
- TextColor( Back );
- TextBackGround( Fore );
- GotoXY( J - Offset + 1, I - Top + 3 );
- Write ( SearchString );
- TextColor( Fore );
- TextBackGround( Back );
- GotoXY(1, 1); ClrEol;
- Write('Replace (Y/N/ESC)? ');
- Ch := ReadKey;
- If Ord (Ch)= 27 Then
- Begin
- I := 1;
- J := 1;
- Ln := EndLn^.Next ;
- StatusLine;
- Screen;
- Exit;
- End;
- If Ch In ['y','Y'] Then
- Begin
- Ln^.Data := Copy (Ln^.Data, 1, Position - 1) + Replacement +
- Copy (Ln^.Data, Position + Length (SearchString), MaxWidth);
- Position := Pos (SearchString, Copy (Ln^.Data, Position + Len + 1,MaxWidth)) ;
- End
- Else
- Position := Pos (SearchString, Copy (Ln^.Data, Position + Length(SearchString) + 1,MaxWidth)) ;
- End;
- Ln := Ln^.Next ;
- GotoXY(1, 1); ClrEol;
- Write('Searching...');
- End;
- Window(1, 1, 80, 25);
- GotoXY(1, 1); ClrEol;
- Write('End of replace. Press any key to exit...');
- Repeat
- Until KeyPressed;
- Ch := ReadKey;
- Ln := EndLn^.Next ;
- I := 1 ;
- J := 1 ;
- StatusLine;
- Screen;
- End;
-
- Procedure ClearMarks ;
- Begin
- IBeg := 0 ;
- IEnd := 0 ;
- BlockBeg := Nil ;
- BlockEnd := Nil ;
- End;
-
- Procedure InsertMark( Mark : Char );
- Begin
- If Mark = 'B' Then
- Begin
- If BlockBeg = Nil Then
- Begin
- BlockBeg := Ln ;
- IBeg := I ;
- End
- Else { BlockBeg Already Defined }
- Write(#7);
- End;
- If Mark = 'E' Then
- Begin
- If BlockEnd = Nil Then
- Begin
- BlockEnd := Ln ;
- IEnd := I ;
- End
- Else { BlockEnd Already Defined }
- Write(#7);
- End;
- End;
-
- Procedure GotoBlock ;
- Begin
- If BlockBeg <> Nil Then
- Begin
- Ln := BlockBeg ;
- I := IBeg;
- J := 1 ;
- If ( I >= 12 ) Then
- Top := I - 8;
- StatusLine ;
- Screen ;
- End;
- End;
-
- Procedure DeleteBlock;
- Var
- TPtr : LPtr;
- Begin
- If IEnd < IBeg Then
- Exit;
- Ln := BlockEnd ;
- I := IEnd ;
- Repeat
- TPtr := Ln^.Last; { save location of previous line }
- Ln^.Last^.Next := Ln^.Next; { isolate current line }
- Ln^.Next^.Last := Ln^.Last;
- Dispose(Ln); { and zap it}
- J := 1 ; I := I - 1;
- NLines := NLines - 1;
- Ln := TPtr;
- Until Ln = BlockBeg^.Last ;
- If I >= 12 Then
- Top := I - 8
- Else
- Top := 1 ;
- Changed := True;
- ClearMarks;
- StatusLine;
- Screen;
- End;
-
- Procedure CopyBlock;
- var
- TPtr : LPtr ;
- Size : Integer;
- Begin
- If IEnd < IBeg then
- Exit;
- If (IBeg < I) And (I <= IEnd) Then
- Exit;
- Size := IEnd - IBeg - 1; { exclude markers }
- If Size = 0 Then
- Exit;
- If NLines + Size <= MaxLines Then
- Begin
- Repeat
- InsertLn (BlockEnd^.Data) ;
- BlockEnd := BlockEnd^.Last ;
- NLines := NLines + 1 ;
- Until BlockEnd = BlockBeg^.Last ;
- End
- Else
- Write(#7);
- Changed := True;
- ClearMarks;
- StatusLine;
- Screen;
- End;
-
- Procedure MoveBlock;
- Var
- Size : Integer;
- TPtr : LPtr;
- Begin
- If IEnd < IBeg Then
- Exit;
- If (IBeg <= I) And (I <= IEnd + 1) Then
- Exit;
- Size := IEnd - IBeg + 1;
- If NLines + Size <= MaxLines Then
- Begin
- TPtr := Ln^.Next ;
- BlockBeg^.Last^.Next := BlockEnd^.Next ;
- BlockEnd^.Next^.Last := BlockBeg^.Last ;
- Ln^.Next := BlockBeg ;
- TPtr^.Last := BlockEnd ;
- BlockBeg^.Last := Ln ;
- BlockEnd^.Next := TPtr ;
- End
- Else
- Write(#7);
- Changed := True;
- ClearMarks;
- StatusLine;
- Screen;
- End;
-
- Procedure WriteBlock ;
- Var
- TPtr : LPtr ;
- Begin
- If ((BlockBeg = Nil) Or (BlockEnd = Nil)) Then
- Exit ;
- If IBeg + 1 < IEnd Then
- Begin
- GotoXY(1,1); For J := 1 To 45 Do Write(' ');
- GotoXY(1,1); Write('Write Block To Disk ? ');
- If YN Then
- Begin
- Write('as: '); ReadLn(OutPut);
- If OutPut = '' Then
- OutPut := Input;
- Capitalize(OutPut);
- GotoXY(40,1); WriteLn(' Writing to disk as ',OutPut);
- Assign(WorkFile,OutPut);
- ReWrite(WorkFile);
- TPtr := BlockBeg;
- Repeat
- WriteLn(WorkFile,TPtr^.Data);
- TPtr := TPtr^.Next
- Until TPtr = BlockEnd;
- Close(WorkFile);
- End;
- End
- Else
- Write(#7);
- StatusLine ;
- Screen ;
- End;
-
- Procedure AddChar; { keyboard entry }
- begin
- Changed := True;
- While J > Len + 1 Do
- Begin
- Ln^.Data := Ln^.Data + ' ' ;
- Len := Len + 1 ;
- End;
- If J = Len + 1 Then
- Ln^.Data := Ln^.Data + Ch
- Else If InSrt Then
- Insert(Ch,Ln^.Data,J)
- Else
- Ln^.Data[J] := Ch;
- J := J + 1;
- WriteLine( I - Top + 3,Attr);
- If (J > RtMrg + 2) And Wrap Then
- WordWrap;
- End;
-
- Procedure Ascii;
- Var
- AscNo, Repeats, R : Integer;
- AsciiLine : ScreenLine;
- Begin
- AsciiLine := '';
- GotoXY( 1, 1); ClrEol;
- Write('Enter ASCII code number: --- ');
- GotoXY(26,1);
- Readln(AscNo);
- GotoXY(1,1);
- Write('Enter number of repeats: -- ');
- GotoXY(26,1);
- ReadLn(Repeats);
- If Not(Repeats In [1..79]) Then
- Repeats := 1;
- If (AscNo > 0) And (AscNo < 256) Then
- Begin
- For R := 1 To Repeats Do
- Begin
- Ch := Chr(AscNo);
- AsciiLine := AsciiLine + Ch ;
- End;
- End;
- While J > Length(Ln^.Data) + 1 Do
- Begin
- Ln^.Data := Ln^.Data + ' ' ;
- Len := Len + 1 ;
- End;
- J := J - 1;
- If J = Length(Ln^.Data) + 1 Then
- Ln^.Data := Ln^.Data + AsciiLine
- Else If InSrt Then
- Insert(AsciiLine,Ln^.Data,J)
- Else
- Ln^.Data := Copy(Ln^.Data,1,J) + AsciiLine + Copy(Ln^.Data,J + Length(AsciiLine),128);
- Changed := True;
- StatusLine;
- Screen;
- End;
-
- Procedure Leave;
- Var
- Trash : Char;
- Begin
- VideoOff;
- Repeat
- Until KeyPressed;
- Trash := ReadKey;
- If (Trash = #0) And (KeyPressed) Then
- Trash := ReadKey;
- VideoOn;
- End;
-
- Procedure Colors;
- Begin
- Case Ch Of
- #48 : Back := (Back + 1) Mod 8;
- #33 : Fore := (Fore + 1) Mod 16;
- End;
- Attr := Attribute( Fore, Back );
- StatusLine;
- Screen;
- End;
-
- Procedure Command;
- Begin
- If Ch = #0 Then
- If KeyPressed Then Ch := ReadKey; { keypad input }
- Case Ch Of
- {alt A} #30 : Ascii;
- {alt B, alt F} #48,#33 : If Mode <> 7 Then Colors;
- {alt C} #46 : CopyBlock;
- {alt D} #32 : DeleteBlock;
- {alt G} #34 : GotoBlock;
- {alt H} #35 : Help;
- {alt K} #37 : ;
- {alt L} #38 : Leave;
- {alt M} #50 : MoveBlock;
- {alt N} #49 : ClearMarks;
- {alt S} #31 : InsertMark('B');
- {alt T} #20 : InsertMark('E');
- {alt W} #17 : WriteBlock;
- {alt X} #45 : Finished := True;
- {tab} #9 : Tab;
- {bktab} #15 : BackTab;
- {F1} #59 : Help;
- {F2} #60 : ClearMarks;
- {F3} #61 : Finished := True;
- {F4} #62 : ParaForm ;
- {F5} #63 : Search ;
- {F6} #64 : Replace;
- {F7} #65 : PageUp ;
- {F8} #66 : PageDown;
- {F9} #67 : PrevWord;
- {F10} #68 : NextWord;
- {home} #71 : J := LeftM;
- {end } #79 : J := Len + 1;
- {^home} #119 : DeleteBOL;
- {^end } #117 : DeleteEOL;
- {^A} #116,#1 : PrevWord;
- {^D} #77, #4 : J := J + 1;
- {^S} #75,#19 : If J > 1 Then
- J := J - 1;
- {^E} #72, #5 : If I > 1 Then
- Begin
- I := I - 1;
- Ln := Ln^.Last;
- End;
- {^F} #115,#6 : NextWord;
- {^X} #80,#24 : If I < NLines Then
- Begin
- I := I + 1;
- Ln := Ln^.Next;
- End;
- {del}#83, #7 : Begin
- Delete(Ln^.Data,J,1);
- WriteLine(I - Top + 3,Attr);
- End;
- { <-- } #8 : If J = 1 Then
- StackLine
- Else
- Begin
- J := J - 1;
- Delete(Ln^.Data,J,1);
- Cursor;
- WriteLine(i - Top + 3,Attr);
- End;
- {^<--} #127 : DeleteWord;
- {Enter} #13 : Begin
- If InSrt Then
- Begin
- If J = Len Then
- J := J + 1;
- CutLine;
- End
- Else
- Begin
- I := I + 1 ;
- J := 1 ;
- Ln^ := Ln^.Next^
- End;
- End;
- {^R} #73,#18 : PageUp;
- {^C} #81, #3 : PageDown;
- {^PgUp} #132 : Begin
- I := 1;
- Top := 1;
- Ln := FirstLn;
- Screen;
- End;
- {^PgDn} #118 : Begin
- I := NLines;
- Top := NLines - 22;
- Ln := EndLn;
- Screen;
- End;
- {^Y} #25 : DeleteLine;
- {^N} #14 : Begin
- Ln := Ln^.Last;
- InsertLn('');
- Screen;
- End;
- {Ins}#22,#82 : Begin
- If InSrt Then
- InSrt := False
- Else
- InSrt := True;
- StatusLine;
- End;
- {^P} #16 : ParaForm;
- {^W} #23 : If Top > 1 Then
- Begin
- Top := Top - 1;
- I := I - 1;
- Screen;
- End;
- {^Z} #26 : If Top < NLines + 22 Then
- Begin
- Top := Top + 1;
- I := I + 1;
- Screen;
- End;
- {^K} #11 : Finished := True;
- Else Begin
- GotoXY(1,1); WriteLn('****** COMMAND NOT RECOGNIZED ****** ');
- Beep; StatusLine;
- End;
- End; {case}
- End;
-
- Begin {Main}
- CheckBreak := False;
- DirectVideo := True;
- ClearMarks ;
- GetVideoMode;
- IF BaseOfScreen = $B000 Then Begin
- Fore := White;
- Back := Black;
- End
- Else Begin
- Fore := Yellow; { make these whatever you want }
- Back := Blue;
- End;
- Attr := Attribute( Fore, Back );
- TextColor( Fore );
- TextBackground( Back );
- ClrScr;
- BlankLine := '';
- For J := 1 To 80 Do
- BlankLine := BlankLine + ' ';
- For I := 1 To MaxWidth Do
- TabSet[I]:=( I Mod 8 ) = 1;
- FileFound := False;
- ReadFile;
- If FileFound Then Begin
- FirstLn^.Last := EndLn ;
- EndLn^.Next := FirstLn ; { close chain, endless loop }
- J := 1; I := 1 ;
- Top := 1; Offset := 1 ;
- Find := '.'; Repl := '';
- Nbl := 0; Lword := '';
- SearchString := ''; Finished := False;
- Replacement := ''; Changed := False;
- ClrScr;
- StatusLine;
- Screen;
- Repeat
- Cursor;
- Ch := ReadKey;
- Case Ch Of
- #0..#31,#127 : Command;
- Else AddChar;
- End;
- Until Finished;
- If Changed Then WriteFile;
- End; {FileFound}
- GetVideoMode;
- IF BaseOfScreen = $B000 Then Begin
- Fore := White;
- Back := Black;
- End
- Else Begin
- Fore := Blue; { make these whatever you want }
- Back := Black;
- End;
- NormVideo;
- TextColor( Fore );
- TextBackGround( Back );
- ClrScr;
- End.
-