IMPLEMENTATION MODULE Editor; (* * REPERTOIRE * Release 1.6 * By Charles Bradford and Cole Brecheen * (c) Copyright 1985-1992 PMI * Green Bay, Wisconsin * All rights reserved * (414) 468-6040 * * $Header: D:/logfiles/mods/editor.mov 1.7 10 Mar 1991 15:26:46 coleb $ * *) (*$O-*) (*We turn off optimization for the whole module to help avoid bugs in Logitech's LONGINTs.*) (*EntryDiag: IMPORT Diagnostics; :EntryDiag*) IMPORT BigSets; IMPORT ByteFiddler; IMPORT GenLists; IMPORT KbdInput; IMPORT Key; IMPORT ListUtils; IMPORT LowLevel; IMPORT M2Strings; IMPORT MsColors; IMPORT Numbers; IMPORT NumTypes; IMPORT PosUtils; IMPORT ScrnTypes; IMPORT ScrnUtl1; IMPORT Spkr; IMPORT StrConv; IMPORT StrEdit; IMPORT SYSTEM; IMPORT UserOps; IMPORT VEditor; IMPORT VWindows; VAR Initialized : BOOLEAN; CONST LineLeng = 255; DisplayLeng = 80; TYPE LineType = ARRAY [0..LineLeng] OF CHAR; LongAndShort = RECORD CASE : BOOLEAN OF TRUE: longi: LONGINT; | FALSE: locard, hicard: CARDINAL; END; END; VAR DumType: CARDINAL; blank : ARRAY [0..0] OF CHAR; DeleteBuffer : GenLists.GenList; PROCEDURE CountToStr( TheCount: LongAndShort; VAR TheStr: ARRAY OF CHAR); BEGIN IF TheCount.hicard = 0 THEN StrConv.CardinalToStr( TheCount.locard, 1, TheStr); ELSE StrConv.LongIntegerToStr( TheCount.longi, 1, TheStr); END; END CountToStr; PROCEDURE DefaultEditor( VAR TheList: GenLists.GenList; VAR Rec: VEditor.AnEdControlRec ); TYPE WriteToScreenOrNot = (DoWrite, DontWrite); VAR BlankStr : ARRAY [0..DisplayLeng] OF CHAR; Testing, DoExitBox : BOOLEAN; (* Testing is true if want to see internals printed. *) WindowHeight, ColsScrolled, MaxLength, LastLineDeleted, TheRow, RLineCnt, TLine, TheNdx : CARDINAL; RCharCnt, TCharCnt : LongAndShort; (* TheRow = the actual row on the screen where the cursor is*) (* Row1 = first row on screen that is in the editor*) (* TheNdx = the column in the text, not on the screen, where we are. Value starts at 0. TheNdx + Col1 is the actual screen column*) (* RCharCnt, RlineCnt = actual text size in characters and lines*) (* TCharCnt, Tline = cursor position in text (characters & lines)*) dumint: INTEGER; PROCEDURE SetPromptColors( TheFrame: ScrnTypes.DisplayFrame ); BEGIN VWindows.SetForeColor( TheFrame^.WindowHandle, Rec.EdPromptFore ); VWindows.SetBackColor( TheFrame^.WindowHandle, Rec.EdPromptBack ); VWindows.SetMonoAttr( TheFrame^.WindowHandle, Rec.EdPromptAttrib ); END SetPromptColors; PROCEDURE SetAttribOrColor( ForeColor, BackColor: MsColors.AColor; attr: MsColors.AMonoAttribute ); BEGIN VWindows.SetForeColor( Rec.WindowHandle, ForeColor ); VWindows.SetBackColor( Rec.WindowHandle, BackColor ); VWindows.SetMonoAttr( Rec.WindowHandle, attr ); END SetAttribOrColor; PROCEDURE CheckMax(): BOOLEAN; BEGIN IF (Rec.MaxLines = 0) OR (GenLists.ListLength( TheList ) < Rec.MaxLines) THEN RETURN TRUE; ELSE Spkr.Noise( Spkr.Warble, Spkr.Normal, Spkr.Short); RETURN FALSE; END; END CheckMax; PROCEDURE UpdateFrameRec(); VAR FieldRec: ScrnTypes.InputFieldRecord; BEGIN IF Rec.FrameRec # NIL THEN IF GenLists.Initialized( Rec.FrameRec^.FieldList ) AND (Rec.FrameRec^.CurrentField # 0) AND (GenLists.ListLength( Rec.FrameRec^.FieldList ) > 0) THEN IF (Rec.FrameRec^.CurrentField = 0) THEN Rec.FrameRec^.CurrentField := 1; END; ScrnUtl1.GetFieldRec( Rec.FrameRec, Rec.FrameRec^.CurrentField, FieldRec ); IF FieldRec.typ = ScrnTypes.EditorCode THEN (* ?? FieldRec.Col2 := Rec.Col2; FieldRec.Row2 := Rec.Row2; *) FieldRec.TextRow1 := Rec.TextRow1; FieldRec.CursorCol := Rec.CursorCol; FieldRec.CursorRow := Rec.CursorRow; FieldRec.MaxLines := Rec.MaxLines; FieldRec.ChangeMade := Rec.ChangeMade; FieldRec.ReadOnly := Rec.ReadOnly; ScrnUtl1.PutFieldRec( FieldRec, Rec.FrameRec, Rec.FrameRec^.CurrentField ); END; END; END; END UpdateFrameRec; PROCEDURE GetFrameRecData(); VAR FieldRec: ScrnTypes.InputFieldRecord; BEGIN IF Rec.FrameRec # NIL THEN Rec.WindowHandle := Rec.FrameRec^.WindowHandle; IF GenLists.Initialized( Rec.FrameRec^.FieldList ) AND (GenLists.ListLength( Rec.FrameRec^.FieldList ) > 0) THEN IF (Rec.FrameRec^.CurrentField = 0) THEN Rec.FrameRec^.CurrentField := 1; END; ScrnUtl1.GetFieldRec( Rec.FrameRec, Rec.FrameRec^.CurrentField, FieldRec ); IF FieldRec.typ = ScrnTypes.EditorCode THEN (* ?? Rec.Col2 := FieldRec.Col2; Rec.Row2 := FieldRec.Row2; *) Rec.TextRow1 := FieldRec.TextRow1; Rec.CursorCol := FieldRec.CursorCol; Rec.CursorRow := FieldRec.CursorRow; Rec.MaxLines := FieldRec.MaxLines; Rec.ChangeMade := FieldRec.ChangeMade; Rec.ReadOnly := FieldRec.ReadOnly; IF NOT ScrnUtl1.ListFromEdField( Rec.FrameRec, Rec.FrameRec^.CurrentField, TheList ) THEN (*Remember that a user might invoke a help sequence from within the editor, which would require PushFrame/PopFrame to save and restore the frame's lists. Since we're editing one of them, we need to update our pointer, because the saved copy will be in a different place.*) END; END; END; END; END GetFrameRecData; PROCEDURE findindent(str : ARRAY OF CHAR) : CARDINAL; VAR ind, leng : CARDINAL; done : BOOLEAN; BEGIN done := FALSE; ind := 0; leng := M2Strings.Length(str); IF leng#0 THEN DEC(leng); REPEAT IF (str[ind]#blank[0]) THEN done := TRUE; ELSIF (ind>=leng) THEN done := TRUE; ind := HIGH(str) + 1; ELSE INC(ind); END; UNTIL done; ELSE ind := HIGH(str) + 1; END; RETURN (ind); END findindent; PROCEDURE WriteStrings(TextLine, baserow, endrow : CARDINAL); VAR clrstr: ARRAY [0..DisplayLeng] OF CHAR; clrlngth, tmpsize, leng, tmprow : CARDINAL; tmpadr: SYSTEM.ADDRESS; BEGIN LowLevel.Fill( SYSTEM.ADR(clrstr), DisplayLeng + 1, blank); leng := GenLists.ListLength( TheList); M2Strings.Assign(BlankStr, clrstr); tmprow := baserow - 1; WHILE (TextLine <= leng) AND (tmprow < endrow) DO INC( tmprow); GenLists.GetElmtAdr( TheList, TextLine, tmpadr, tmpsize, DumType); tmpsize := LowLevel.ScanEQ( tmpsize, 0C, tmpadr ); IF tmpsize < ColsScrolled THEN clrlngth := MaxLength; tmpsize := 0; (*set tmpsize to 0 because none of the string will show.*) ELSE IF (tmpsize - ColsScrolled) > MaxLength THEN tmpsize := MaxLength; clrlngth := 0; ELSE tmpsize := Numbers.Min( tmpsize - ColsScrolled, MaxLength ); clrlngth := MaxLength - tmpsize; END; IF tmpsize > 0 THEN VWindows.DrawStr( Rec.WindowHandle, Rec.Col1, tmprow, LowLevel.AddAddr(tmpadr, ColsScrolled), tmpsize ); END; END; IF clrlngth > 0 THEN VWindows.DrawStr( Rec.WindowHandle, Rec.Col1 + tmpsize, tmprow, SYSTEM.ADR(clrstr), clrlngth ); END; INC( TextLine); END; IF (tmprow < endrow) AND (endrow = Rec.Row2) THEN VWindows.ClearPart( Rec.WindowHandle, Rec.Col1, tmprow + 1, Rec.Col2, Rec.Row2); END; END WriteStrings; PROCEDURE OvrOrIns( VAR TheStr: ARRAY OF CHAR); BEGIN IF Rec.overwriting THEN StrEdit.AssignStr( 'Overwrite', TheStr); ELSE StrEdit.AssignStr( ' Insert ', TheStr); END; END OvrOrIns; PROCEDURE WriteFooter(); VAR dumstr : ARRAY [0..DisplayLeng] OF CHAR; tmpstr : ARRAY [0..10] OF CHAR; SavedFore, SavedBack : MsColors.AColor; SavedAttr : MsColors.AMonoAttribute; BEGIN IF Rec.FrameRec # NIL THEN SavedFore := VWindows.ForeColor( Rec.WindowHandle ); SavedBack := VWindows.BackColor( Rec.WindowHandle ); SavedAttr := VWindows.MonoAttr( Rec.WindowHandle ); SetPromptColors( Rec.FrameRec ); END; CountToStr(RCharCnt, tmpstr); M2Strings.Concat('TEXT SIZE: chars:', tmpstr, dumstr); StrEdit.LeftJustify( dumstr, 23 ); StrEdit.Append(dumstr, ' lines:'); StrConv.CardinalToStr(RLineCnt, 1, tmpstr); StrEdit.Append(dumstr, tmpstr); StrEdit.LeftJustify( dumstr, 33 ); StrEdit.Append(dumstr, ' POSITION: char:'); CountToStr( TCharCnt, tmpstr); StrEdit.Append(dumstr, tmpstr); StrEdit.LeftJustify( dumstr, 54 ); StrEdit.Append(dumstr, ' line:'); StrConv.CardinalToStr(TLine, 1, tmpstr); StrEdit.Append(dumstr, tmpstr); StrEdit.LeftJustify( dumstr, 65 ); StrEdit.Append(dumstr, 'MODE:'); OvrOrIns( tmpstr); StrEdit.Append(dumstr, tmpstr); VWindows.DrawStr( Rec.WindowHandle,2, Rec.CountRow, SYSTEM.ADR(dumstr), M2Strings.Length(dumstr) ); IF Rec.FrameRec # NIL THEN VWindows.SetForeColor( Rec.WindowHandle, SavedFore ); VWindows.SetBackColor( Rec.WindowHandle, SavedBack ); VWindows.SetMonoAttr( Rec.WindowHandle, SavedAttr ); END; END WriteFooter; PROCEDURE AddCLCount( CharTotalDiff: LONGINT; LineTotalDiff: INTEGER; CharPosDiff: LONGINT; LinePosDiff : INTEGER ); VAR tmpstr : ARRAY [0..20] OF CHAR; TmpLong : LONGINT; SavedFore, SavedBack : MsColors.AColor; SavedAttr : MsColors.AMonoAttribute; BEGIN TLine := INTEGER( INTEGER(TLine) + LinePosDiff ); IF Rec.DoCounting THEN IF Rec.FrameRec # NIL THEN SavedFore := VWindows.ForeColor( Rec.WindowHandle ); SavedBack := VWindows.BackColor( Rec.WindowHandle ); SavedAttr := VWindows.MonoAttr( Rec.WindowHandle ); SetPromptColors( Rec.FrameRec ); END; IF LineTotalDiff # 0 THEN RLineCnt := INTEGER(INTEGER(RLineCnt) + LineTotalDiff); StrConv.CardinalToStr(RLineCnt, 1, tmpstr); StrEdit.Append(tmpstr, ' '); StrEdit.SetLength(tmpstr, 4); VWindows.DrawStr( Rec.WindowHandle, 31, Rec.CountRow, SYSTEM.ADR(tmpstr), 4); END; IF LinePosDiff#0 THEN StrConv.CardinalToStr(TLine, 1, tmpstr); StrEdit.Append(tmpstr, ' '); StrEdit.SetLength(tmpstr, 4); VWindows.DrawStr( Rec.WindowHandle,62, Rec.CountRow, SYSTEM.ADR(tmpstr), 4); END; IF CharTotalDiff # NumTypes.L0 THEN TmpLong := CharTotalDiff; RCharCnt.longi := RCharCnt.longi + TmpLong; CountToStr( RCharCnt, tmpstr); StrEdit.Append(tmpstr, ' '); StrEdit.SetLength(tmpstr, 5); VWindows.DrawStr( Rec.WindowHandle,19, Rec.CountRow, SYSTEM.ADR(tmpstr), 5); END; IF CharPosDiff # NumTypes.L0 THEN TmpLong := CharPosDiff; TCharCnt.longi := TCharCnt.longi + TmpLong; CountToStr( TCharCnt, tmpstr); StrEdit.Append(tmpstr, ' '); StrEdit.SetLength(tmpstr, 5); VWindows.DrawStr( Rec.WindowHandle,51, Rec.CountRow, SYSTEM.ADR(tmpstr), 5); END; IF Rec.FrameRec # NIL THEN VWindows.SetForeColor( Rec.WindowHandle, SavedFore ); VWindows.SetBackColor( Rec.WindowHandle, SavedBack ); VWindows.SetMonoAttr( Rec.WindowHandle, SavedAttr ); END; END; VWindows.GotoXY( Rec.WindowHandle, Rec.Col1 + TheNdx - ColsScrolled, TheRow); END AddCLCount; PROCEDURE CountChars(Rtmptr : CARDINAL; VAR Rchars : LONGINT; VAR Rlines : CARDINAL; Ttmptr : CARDINAL; VAR Tchars : LONGINT); VAR leng : CARDINAL; BEGIN IF NOT Rec.DoCounting THEN Rchars := NumTypes.L1; Rlines := 1; Tchars := NumTypes.L1; (*Added 25 May 87 to prevent uninitialized values*) RETURN; END; leng := GenLists.ListLength( TheList); (*count all chars starting WITH Rtmptr*) Rlines := 0; Rchars := NumTypes.L1; (*put 1+ chars and lines before Ttmptr in Tchars and Tlines*) Tchars := NumTypes.L1; WHILE Rtmptr <= leng DO Rlines := Rlines + 1; IF Rtmptr=Ttmptr THEN Tchars := Rchars; END; Rchars := Rchars + Numbers.Lc( ListUtils.ElmtSize(TheList,Rtmptr) + 2 ); INC( Rtmptr); END; END CountChars; PROCEDURE TheLength(): CARDINAL; (* Returns length of current line *) BEGIN RETURN ListUtils.ElmtSize( TheList, TLine); END TheLength; PROCEDURE MoveAcrossTo(NewNdx : INTEGER); VAR charsmoved : INTEGER; redraw : BOOLEAN; lngth : CARDINAL; BEGIN lngth := TheLength(); IF (CARDINAL(NewNdx) >= lngth) AND (TheNdx >= lngth) THEN charsmoved := 0; ELSE IF (CARDINAL(NewNdx) >= lngth) AND (TheNdx < lngth) THEN (*We've crossed over to the right of the trailing CR/LF.*) charsmoved := (lngth - TheNdx) + 2; ELSIF (CARDINAL(NewNdx) < lngth) AND (TheNdx >= lngth) THEN (*We've crossed over to the left of the trailing CR/LF.*) charsmoved := (NewNdx - INTEGER(lngth)) - 2; ELSE charsmoved := NewNdx - INTEGER(TheNdx); IF (charsmoved = 0) THEN RETURN; END; END; END; TheNdx := NewNdx; IF (TheNdx < ColsScrolled) THEN ColsScrolled := TheNdx; redraw := TRUE; ELSIF (TheNdx > (ColsScrolled + MaxLength - 1)) THEN ColsScrolled := TheNdx - MaxLength + 1; redraw := TRUE; ELSE redraw := FALSE; END; AddCLCount( NumTypes.L0, 0, Numbers.Li(charsmoved), 0); IF redraw THEN WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); END; END MoveAcrossTo; PROCEDURE MoveVerticallyTo( NewTLine: CARDINAL ); VAR TmpSize, ColNow, RowNow, LstLngth, TmpLineCount : CARDINAL; TmpL, BytesSkipped : LONGINT; redrawing, MovingUp : BOOLEAN; addrow, addchar, dist : INTEGER; BEGIN LstLngth := GenLists.ListLength( TheList ); addrow := 0; addchar := 0; IF NewTLine > LstLngth THEN (*We'll add a line if the line we're on is the last line and it isn't blank.*) IF (TLine = LstLngth) AND (ListUtils.ElmtSize(TheList, TLine) > 0) THEN IF CheckMax() THEN GenLists.ListInsert( '', DumType, TheList, TLine + 1); addrow := 1; addchar := 2; INC( LstLngth ); END; END; (*otherwise we don't let them move past last line*) NewTLine := LstLngth; ELSIF NewTLine < 1 THEN NewTLine := 1; END; IF TLine > NewTLine THEN MovingUp := TRUE; ELSIF TLine < NewTLine THEN MovingUp := FALSE; ELSE RETURN; END; (*Now we count the bytes we will be skipping.*) TmpLineCount := TLine; BytesSkipped := NumTypes.L0; IF MovingUp THEN WHILE (TmpLineCount >= NewTLine) DO IF TmpLineCount > LstLngth THEN (*This can happen if we've just deleted the last line and we're moving up to what is now the new last line.*) TmpL := NumTypes.L0; ELSE TmpL := Numbers.Lc( ListUtils.ElmtSize( TheList, TmpLineCount )); (*Workaround for a Logitech LONGINT bug.*) END; BytesSkipped := BytesSkipped + TmpL + NumTypes.L2; DEC( TmpLineCount ); END; (*Adjust BytesSkipped because we may not have actually skipped over some of the bytes on the line we were on. It depends on whether the cursor was beyond the end of the line at the time.*) IF TLine > LstLngth THEN TmpSize := 0; ELSE TmpSize := ListUtils.ElmtSize( TheList, TLine ); END; IF TheNdx < TmpSize THEN TmpSize := TmpSize - TheNdx + 2; (*Otherwise the cursor was beyond the end of the line, so we did skip over the full length of the line plus the CR/LF at the end of it. We don't have to subtract anything*) BytesSkipped := BytesSkipped - Numbers.Lc(TmpSize); END; TmpSize := ListUtils.ElmtSize( TheList, NewTLine ); (*Now determine whether we have skipped over all of the line we're moving to. If we don't adjust BytesSkipped, it tells AddCLCount that we have skipped over the whole thing.*) IF TheNdx < TmpSize THEN BytesSkipped := BytesSkipped - Numbers.Lc(TheNdx); ELSE TmpSize := TmpSize + 2; BytesSkipped := BytesSkipped - Numbers.Lc(TmpSize); END; BytesSkipped := -BytesSkipped; ELSE WHILE (TmpLineCount <= NewTLine) DO TmpL := Numbers.Lc( ListUtils.ElmtSize( TheList, TmpLineCount )); (*Workaround for a Logitech LONGINT bug.*) BytesSkipped := BytesSkipped + TmpL + NumTypes.L2; INC( TmpLineCount ); END; (*Now we subtract the part of the line we're on that we didn't actually skip.*) IF TLine <= LstLngth THEN TmpL := Numbers.Lc( Numbers.Min(TheNdx, TheLength() ) ); IF Numbers.C(TmpL) >= ListUtils.ElmtSize(TheList, TLine) THEN TmpL := TmpL + NumTypes.L2; END; BytesSkipped := BytesSkipped - TmpL; END; (*And now we subtract the part of the new line that we haven't yet skipped.*) TmpSize := ListUtils.ElmtSize(TheList, NewTLine); IF TheNdx < TmpSize THEN TmpSize := TmpSize - TheNdx + 2; BytesSkipped := BytesSkipped - Numbers.Lc(TmpSize); END; END; dist := INTEGER(NewTLine) - INTEGER(TLine); (*Now determine whether we can get by with just moving the cursor instead of redrawing some or all of the window.*) IF MovingUp THEN redrawing := (INTEGER(TheRow) + dist) < INTEGER(Rec.Row1); ELSE redrawing := (INTEGER(TheRow) + dist) > INTEGER(Rec.Row2); END; IF NOT redrawing THEN TheRow := INTEGER(INTEGER(TheRow) + dist); VWindows.GetCursorCoords( Rec.WindowHandle, ColNow, RowNow ); VWindows.GotoXY( Rec.WindowHandle, ColNow, CARDINAL(INTEGER(RowNow) + dist) ); AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); RETURN; END; (*We know we have to redraw at least some of the window. The next easy case is redrawing the whole thing.*) IF ABS(dist) >= INTEGER(WindowHeight) THEN IF (NewTLine > (TheRow - Rec.Row1)) AND (NOT (NewTLine = LstLngth)) THEN WriteStrings( NewTLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); ELSE (*We're moving more than a page's length, so we'll position the cursor to the top of the window unless we're going to the very end--in that case we position it to the bottom.*) VWindows.GetCursorCoords( Rec.WindowHandle, ColNow, RowNow ); IF (NewTLine = LstLngth) AND (NewTLine >= WindowHeight) THEN WriteStrings( NewTLine - WindowHeight + 1, Rec.Row1, Rec.Row2 ); TheRow := Rec.Row2; VWindows.GotoXY( Rec.WindowHandle, ColNow, Rec.Row2 ); ELSE WriteStrings( NewTLine, Rec.Row1, Rec.Row2 ); TheRow := Rec.Row1; VWindows.GotoXY( Rec.WindowHandle, ColNow, Rec.Row1 ); END; END; AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); RETURN; END; (*Looks like we'll have to scroll part of the window and redraw the rest of it.*) IF NOT VWindows.ScrollVertically( Rec.WindowHandle, Rec.Col1, Rec.Row1, Rec.Col2, Rec.Row2, dist ) THEN (*The window manager they've chosen doesn't support a fast vertical scroll, so we can redraw the whole thing and leave.*) WriteStrings( NewTLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); RETURN; END; IF MovingUp THEN (*We have to redraw the top of the window.*) WriteStrings( NewTLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row1 + CARDINAL(ABS(dist)) - 1 ); ELSE (*We have to redraw the bottom of the window.*) WriteStrings( NewTLine - CARDINAL(ABS(dist)) + 1, Rec.Row2 - CARDINAL(ABS(dist)) + 1, Rec.Row2 ); END; AddCLCount( Numbers.Li(addchar), addrow, BytesSkipped, dist ); END MoveVerticallyTo; PROCEDURE PageUp(); BEGIN IF (TheRow > Rec.Row1) OR (TLine = 1) THEN MoveVerticallyTo( TLine - (TheRow - Rec.Row1) ); ELSIF WindowHeight >= TLine THEN MoveVerticallyTo( 1 ); ELSE MoveVerticallyTo( TLine - WindowHeight ); END; END PageUp; PROCEDURE PageDown(); BEGIN IF (TheRow < Rec.Row2) OR (TLine = GenLists.ListLength(TheList)) THEN MoveVerticallyTo( TLine + (Rec.Row2 - TheRow) ); ELSE MoveVerticallyTo( TLine + WindowHeight ); END; END PageDown; PROCEDURE DeleteAChar( spacesback : CARDINAL); VAR tmpadr: SYSTEM.ADDRESS; null: CHAR; tmpsize, NewNdx: CARDINAL; BEGIN null := 0C; IF TheNdx > TheLength() THEN MoveAcrossTo( TheLength() ); END; NewNdx := TheNdx - spacesback; MoveAcrossTo( NewNdx ); (*This changes the value of TheNdx. We have to do it before the ShiftArrayLeft because MoveAcrossTo won't update our character position if it thinks we're moving around in the void beyond the end of the line.*) GenLists.GetElmtAdr( TheList, TLine, tmpadr, tmpsize, DumType); LowLevel.ShiftArrayLeft( LowLevel.AddAddr(tmpadr, NewNdx), tmpsize - NewNdx, 1 ); (*Now we have to make sure we've truncated the line, because the ShiftArrayLeft will only do so if it moves a trailing null with the rest of the string.*) IF tmpsize > 0 THEN ListUtils.OverwriteElmt( TheList, TLine, SYSTEM.ADR(null), 1, tmpsize - 1 ); END; WriteStrings( TLine, TheRow, TheRow ); IF NewNdx >= TheLength() THEN (*We have to increment the character position by 2 if we wound up beyond the line length--the MoveAcrossTo didn't know what the ending line length would be.*) AddCLCount( Numbers.Li(-1), 0, NumTypes.L2, 0); ELSE AddCLCount( Numbers.Li(-1), 0, NumTypes.L0, 0); END; END DeleteAChar; PROCEDURE NewLink(VAR oldptr : CARDINAL; curind : CARDINAL); VAR newline : LineType; BEGIN (*We don't have to check MaxLines here because NewLink is only called in BumpWord, which we don't call if we're close to the limit.*) LowLevel.Fill( SYSTEM.ADR( newline), curind, blank); StrEdit.SetLength( newline, curind); GenLists.ListInsert( newline, GenLists.StrCode, TheList, oldptr + 1); END NewLink; PROCEDURE ReplaceWith(TheChr : CHAR); VAR LinesAdded, CharsAdded : INTEGER; StartLine, CursorLine, CursorCol: CARDINAL; RoomOnThisLine, BeyondEnd : BOOLEAN; BEGIN (* First we'll put the character into the list. Then we'll worry about whether we have to wrap or scroll to display it. *) CharsAdded := 0; BeyondEnd := (TheNdx >= ListUtils.ElmtSize(TheList, TLine)); IF BeyondEnd THEN WHILE (TheNdx > ListUtils.ElmtSize(TheList, TLine)) DO ListUtils.InsertIntoElmt( TheList, TLine, SYSTEM.ADR(blank), 1, 65535 ); (*pad with blanks out to TheNdx, if necessary*) INC(CharsAdded); END; TCharCnt.longi := TCharCnt.longi - NumTypes.L2; (*We do this to compensate for the fact that MoveAcrossTo will think we've crossed over a CR/LF.*) ListUtils.InsertIntoElmt( TheList, TLine, SYSTEM.ADR(TheChr), 1, 65535 ); (*append TheChr to the string at position TLine*) INC(CharsAdded); ELSE IF Rec.overwriting THEN ListUtils.OverwriteElmt( TheList, TLine, SYSTEM.ADR(TheChr), 1, TheNdx ); CharsAdded := 0; ELSE ListUtils.InsertIntoElmt( TheList, TLine, SYSTEM.ADR(TheChr), 1, TheNdx ); CharsAdded := 1; END; END; RoomOnThisLine := (NOT Rec.Wrapping) OR (ListUtils.ElmtSize(TheList, TLine) < MaxLength); IF RoomOnThisLine THEN MoveAcrossTo( TheNdx + 1 ); WriteStrings( TLine, TheRow, TheRow ); AddCLCount(Numbers.Li(CharsAdded), 0, NumTypes.L0, 0); ELSE StartLine := TLine; CursorLine := TLine; CursorCol := TheNdx; ListUtils.ReformPara( TheList, ListUtils.IndentationAt(TheList, TLine), MaxLength, StartLine, CursorLine, CursorCol, LinesAdded, CharsAdded, TCharCnt.longi ); AddCLCount( Numbers.Li(CharsAdded), LinesAdded, NumTypes.L0, 0 ); MoveAcrossTo( 0 ); (*Makes sure part of the current word isn't scrolled out of the window. *) MoveAcrossTo( CursorCol + 1 ); MoveVerticallyTo( CursorLine ); WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); END; END ReplaceWith; PROCEDURE ScrollRegion( row1, row2 : CARDINAL; dist: INTEGER ); VAR NewTopLine: INTEGER; BEGIN NewTopLine := INTEGER(TLine - (TheRow - Rec.Row1)) + INTEGER(row1 - Rec.Row1) + dist; IF NOT VWindows.ScrollVertically( Rec.WindowHandle, Rec.Col1, row1, Rec.Col2, row2, dist ) THEN NewTopLine := Numbers.Min( NewTopLine, 1 ); WriteStrings( NewTopLine, row1, row2 ); RETURN; END; IF NewTopLine < 1 THEN (*They want to move down by more lines than we have to fill with.*) NewTopLine := 1 + ABS(dist); INC( row1, CARDINAL(ABS(dist)) ); END; IF dist > 0 THEN WriteStrings( CARDINAL(NewTopLine) + (row2 - row1) - CARDINAL(dist), Rec.Row2 - CARDINAL(dist) + 1, Rec.Row2 ); ELSE WriteStrings( CARDINAL(NewTopLine) + CARDINAL(ABS(dist)), row1, CARDINAL(INTEGER(row1) + ABS(dist) - 1) ); END; END ScrollRegion; PROCEDURE Reformat(); VAR LinesAdded, CharsAdded: INTEGER; StartLine, CursorLine, CursorCol: CARDINAL; BEGIN StartLine := TLine; CursorLine := TLine; CursorCol := TheNdx; ListUtils.ReformPara( TheList, ListUtils.IndentationAt(TheList, StartLine), MaxLength, StartLine, CursorLine, CursorCol, LinesAdded, CharsAdded, TCharCnt.longi ); AddCLCount( Numbers.Li(CharsAdded), LinesAdded, NumTypes.L0, 0 ); MoveAcrossTo( CursorCol ); MoveVerticallyTo( CursorLine ); WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); END Reformat; PROCEDURE InsertDeleteBuffer(); VAR BufLngth: CARDINAL; CharsAdded, tmpl: LONGINT; BEGIN BufLngth := GenLists.ListLength( DeleteBuffer ); IF BufLngth = 0 THEN RETURN; END; ListUtils.InsertElmtsOf( DeleteBuffer, 1, BufLngth, TheList, TLine ); tmpl := ListUtils.CharCount( DeleteBuffer, 1, 65535 ); IF tmpl > NumTypes.L65535 THEN (*If they try to copy more than 64K at once, we throw up our hands; the text gets inserted correctly, but we don't bother to position the cursor after it. We just go to the top and let them figure out where they were.*) RCharCnt.longi := RCharCnt.longi + tmpl; RLineCnt := RLineCnt + BufLngth; MoveVerticallyTo( 1 ); MoveAcrossTo( 0 ); CharsAdded := tmpl; AddCLCount( CharsAdded, BufLngth, NumTypes.L0, 0 ); END; CharsAdded := tmpl; AddCLCount( CharsAdded, BufLngth, NumTypes.L0, 0 ); WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); MoveVerticallyTo( TLine + BufLngth ); END InsertDeleteBuffer; PROCEDURE DeleteALine(); VAR delsize : INTEGER; BEGIN delsize := 2 + ListUtils.ElmtSize( TheList, TLine ); IF TLine # LastLineDeleted THEN IF GenLists.Initialized( DeleteBuffer ) THEN GenLists.DisposeList( DeleteBuffer ); END; GenLists.NewList( DeleteBuffer ); LastLineDeleted := TLine; END; ListUtils.InsertElmtsOf( TheList, TLine, 1, DeleteBuffer, 65535 ); GenLists.ListDelete( TheList, TLine, 1); IF TLine <= GenLists.ListLength( TheList) THEN (*this isn't the last line*) WriteStrings( TLine, TheRow, Rec.Row2 ); AddCLCount( Numbers.Li(-delsize), -1, NumTypes.L0, 0); ELSIF TLine # 1 THEN (*this is the last line of many*) VWindows.ClearPart( Rec.WindowHandle, Rec.Col1, TheRow, Rec.Col2, TheRow); AddCLCount( Numbers.Li(-delsize), -1, NumTypes.L0, 0); MoveVerticallyTo( TLine - 1 ); ELSE (*This is the only line *) GenLists.ListInsert( '', GenLists.StrCode, TheList, 1); VWindows.ClearPart( Rec.WindowHandle, Rec.Col1, TheRow, Rec.Col2, TheRow); MoveAcrossTo( 0 ); AddCLCount( Numbers.Li(2 - delsize), 0, Numbers.Li(1 - INTEGER( TCharCnt.locard)), 0); END; END DeleteALine; PROCEDURE JoinLines(); (* joins this line to the previous one (caused by a BSP in the first column or a del at the end) *) VAR addedtoend, firstleng : INTEGER; tmpsize: CARDINAL; tmpadr: SYSTEM.ADDRESS; OnBlankLine : BOOLEAN; BEGIN IF TLine = 1 THEN (* if this isn't the first line *) RETURN; END; OnBlankLine := TheLength() = 0; MoveAcrossTo( 0 ); GenLists.GetElmtAdr( TheList, TLine - 1, tmpadr, tmpsize, DumType); firstleng := ListUtils.ElmtSize( TheList, TLine - 1 ); IF (firstleng # 0) AND (ByteFiddler.PeekChar(LowLevel.AddAddr(tmpadr, firstleng - 1)) # blank[0]) THEN (* if need a space at end of prior line to separate *) ListUtils.InsertIntoElmt( TheList, TLine - 1, SYSTEM.ADR(blank), 1, 65535 ); (*append a blank to end of previous line*) addedtoend := 1; ELSE addedtoend := 0; END; AddCLCount( Numbers.Li(addedtoend), 0, Numbers.Li(addedtoend), 0 ); (*update char counts so that MoveTo procedures will count correctly as line boundary is crossed.*) MoveVerticallyTo( TLine - 1 ); (*This changes TLine.*) MoveAcrossTo( TheLength() ); IF NOT OnBlankLine THEN GenLists.GetElmtAdr( TheList, TLine + 1, tmpadr, tmpsize, DumType ); ListUtils.InsertIntoElmt( TheList, TLine, tmpadr, tmpsize, 65535 ); AddCLCount( -NumTypes.L2, -1, -NumTypes.L2, 0 ); (*account for deletion of CR/LF and TLine*) ELSE AddCLCount( -NumTypes.L2, -1, NumTypes.L0, 0 ); (*We've lost a line, but we're past the CR/LF on the line above*) END; GenLists.ListDelete( TheList, TLine + 1, 1); WriteStrings( TLine, TheRow, TheRow ); ScrollRegion( TheRow + 1, Rec.Row2, 1 ); END JoinLines; PROCEDURE NewLine(); VAR prvadr: SYSTEM.ADDRESS; OldNdx, prvsize : CARDINAL; BEGIN IF NOT CheckMax() THEN RETURN; END; OldNdx := TheNdx; MoveAcrossTo( 0 ); GenLists.GetElmtAdr( TheList, TLine, prvadr, prvsize, DumType); prvsize := ListUtils.ElmtSize( TheList, TLine ); (*Reduces prvsize to number of bytes before the 0C.*) GenLists.ListInsert( '', GenLists.StrCode, TheList, TLine + 1 ); IF OldNdx = 0 THEN AddCLCount( NumTypes.L2, 1, NumTypes.L2, 0 ); (*Increment char total for the new CR/LF, and increment the char position because MoveVerticallyTo won't count the trailing CR/LF in this case--it thinks we've already skipped it.*) ELSE AddCLCount( NumTypes.L2, 1, NumTypes.L0, 0 ); (*Increment char total for the new CR/LF.*) END; IF OldNdx < prvsize THEN ListUtils.InsertIntoElmt( TheList, TLine + 1, LowLevel.AddAddr(prvadr, OldNdx), prvsize - OldNdx, 0 ); ByteFiddler.PokeChar( 0C, LowLevel.AddAddr(prvadr, OldNdx) ); END; WriteStrings( TLine, TheRow, TheRow ); IF TheRow < Rec.Row2 THEN ScrollRegion( TheRow + 1, Rec.Row2, -1 ); END; MoveVerticallyTo( TLine + 1 ); END NewLine; PROCEDURE NextWord(); VAR tmpcol, leng : INTEGER; tmpsize: CARDINAL; txtadr, tmpadr: SYSTEM.ADDRESS; BEGIN leng := ListUtils.ElmtSize( TheList, TLine ); IF TheNdx + 1 >= CARDINAL(leng) THEN MoveVerticallyTo( TLine + 1 ); GenLists.GetElmtAdr( TheList, TLine, txtadr, tmpsize, DumType); MoveAcrossTo(0); IF ByteFiddler.PeekChar(txtadr) # blank[0] THEN RETURN; END; END; GenLists.GetElmtAdr( TheList, TLine, txtadr, tmpsize, DumType); tmpcol := TheNdx; LOOP tmpadr := LowLevel.AddAddr( txtadr, tmpcol ); IF tmpcol + 1 < leng THEN IF ByteFiddler.PeekChar(tmpadr) = blank[0] THEN LowLevel.IncAddr( tmpadr, 1 ); dumint := LowLevel.ScanNE(leng - tmpcol - 1, blank, tmpadr); MoveAcrossTo(tmpcol + 1 + dumint); RETURN; ELSE INC(tmpcol); END; ELSE MoveAcrossTo(leng); RETURN; END; END; END NextWord; PROCEDURE LastWord(); VAR tmpcol : INTEGER; tmpsize: CARDINAL; txtadr, tmpadr: SYSTEM.ADDRESS; BEGIN tmpcol := TheNdx; GenLists.GetElmtAdr( TheList, TLine, txtadr, tmpsize, DumType); LOOP IF tmpcol > 0 THEN tmpadr := LowLevel.AddAddr(txtadr, tmpcol - 1); IF ByteFiddler.PeekChar(tmpadr) # blank[0] THEN dumint := LowLevel.ScanEQ(-tmpcol,blank,tmpadr); (* last is + since scan returns neg.*) MoveAcrossTo( tmpcol + dumint); EXIT; ELSE DEC( tmpcol); END; ELSE MoveVerticallyTo( TLine - 1 ); MoveAcrossTo( TheLength() ); EXIT; END; END; END LastWord; PROCEDURE KeyResponse(); VAR OvrStr : ARRAY [0..10] OF CHAR; SavedFore, SavedBack : MsColors.AColor; SavedAttr : MsColors.AMonoAttribute; BEGIN LOOP Rec.EdLastKey := KbdInput.KeyHit( KbdInput.AnyKeyNum ); IF Rec.FrameRec # NIL THEN UpdateFrameRec(); UserOps.TheKeyHandler( Rec.FrameRec, Rec.EdLastKey, Rec.NextFrame ); IF Rec.overwriting THEN VWindows.SetCursorHeight( Rec.WindowHandle, 2); ELSE VWindows.SetCursorHeight( Rec.WindowHandle, 4); END; SetAttribOrColor( Rec.EntryForeColor, Rec.EntryBackColor, Rec.EntryAttrib ); GetFrameRecData(); END; IF (Rec.EdLastKey = UserOps.SubmitKey) OR (Rec.EdLastKey = UserOps.BackupKey) OR (Rec.EdLastKey = UserOps.ExitKey) THEN EXIT; END; CASE Rec.EdLastKey OF Key.Up : (*up arrow*) IF (TLine = 1) AND BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN (*We're letting the user exit from the editor window by pressing the up arrow on the top line of the file.*) EXIT; ELSE MoveVerticallyTo( TLine - 1 ); END; | Key.Down : (*down arrow*) IF (TLine = GenLists.ListLength(TheList)) AND BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN (*We're letting the user exit from the editor window by pressing the down arrow on the bottom line of the file.*) EXIT; ELSE MoveVerticallyTo( TLine + 1 ); END; | Key.Left: (*left arrow*) IF TheNdx>0 THEN MoveAcrossTo(TheNdx - 1); ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN (*We're letting the user exit from the editor window by pressing the left arrow on the left edge of the window.*) EXIT; ELSIF (TheRow # Rec.Row1) THEN MoveVerticallyTo( TLine - 1 ); MoveAcrossTo( TheLength()); END; | Key.Right: (*right arrow*) IF TheNdx < TheLength() THEN MoveAcrossTo( TheNdx + 1); ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN (*We're letting the user exit from the editor window by pressing the right arrow at the end of the current line.*) EXIT; ELSIF (TLine # GenLists.ListLength( TheList)) THEN MoveVerticallyTo( TLine + 1 ); MoveAcrossTo(0); END; | Key.Tab, Key.CtrlRight: (*Tab and Ctrl-RightArrow*) IF TheNdx < TheLength() THEN NextWord(); ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN (*We're letting the user exit from the editor window by pressing the Tab or Ctrl-RightArrow if they're in the FieldExitKeySet.*) EXIT; ELSE NextWord(); END; | Key.BackTab, Key.CtrlLeft: (*BackTab and Ctrl-LeftArrow*) IF TheNdx>0 THEN LastWord(); ELSIF BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN EXIT; ELSE LastWord(); END; | Key.F4 : NextWord(); | Key.Ins : IF NOT Rec.ReadOnly THEN Rec.overwriting := NOT Rec.overwriting; IF Rec.overwriting THEN VWindows.SetCursorHeight( Rec.WindowHandle, 2 ); ELSE VWindows.SetCursorHeight( Rec.WindowHandle, 4 ); END; IF Rec.FrameRec # NIL THEN SavedFore := VWindows.ForeColor( Rec.WindowHandle ); SavedBack := VWindows.BackColor( Rec.WindowHandle ); SavedAttr := VWindows.MonoAttr( Rec.WindowHandle ); SetPromptColors( Rec.FrameRec ); END; IF Rec.DoCounting THEN OvrOrIns( OvrStr); VWindows.DrawStr( Rec.WindowHandle, 71, Rec.CountRow, SYSTEM.ADR(OvrStr), M2Strings.Length(OvrStr) ); END; IF Rec.FrameRec # NIL THEN VWindows.SetForeColor( Rec.WindowHandle, SavedFore ); VWindows.SetBackColor( Rec.WindowHandle, SavedBack ); VWindows.SetMonoAttr( Rec.WindowHandle, SavedAttr ); END; VWindows.GotoXY( Rec.WindowHandle, Rec.Col1 + TheNdx - ColsScrolled, TheRow); END; | Key.Del : IF NOT Rec.ReadOnly THEN Rec.ChangeMade := TRUE; IF TheNdx < TheLength() THEN DeleteAChar(0); ELSE MoveVerticallyTo( TLine + 1 ); MoveAcrossTo( 0 ); JoinLines(); END; END; | Key.Home: (* go to start of current line*) MoveAcrossTo(0); | Key.AltD : IF NOT Rec.ReadOnly THEN Rec.ChangeMade := TRUE; DeleteALine(); END; | Key.AltI, Key.AltU : IF NOT Rec.ReadOnly THEN Rec.ChangeMade := TRUE; InsertDeleteBuffer(); END; | Key.End: (*End*) (* go to end of current line*) MoveAcrossTo( TheLength()); | Key.PgUp: (*PgUp*) IF (TLine = 1) AND BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN (*We're letting the user exit from the editor window by pressing PgUp on the top line of the file.*) EXIT; ELSE PageUp(); (* go up one page *) END; | Key.PgDn: (*PgDn*) IF (TLine = GenLists.ListLength(TheList)) AND BigSets.InSet( UserOps.FieldExitKeySet, Rec.EdLastKey ) THEN (*We're letting the user exit from the editor window by pressing the PgDn key on the bottom line of the file.*) EXIT; ELSE PageDown(); (* go down one page *) END; | Key.CtrlPgUp: (* go to top of file *) MoveVerticallyTo( 1 ); | Key.CtrlPgDn: (* go to end of text file *) MoveVerticallyTo( GenLists.ListLength(TheList) ); MoveAcrossTo( TheLength() ); | Key.F7: (* pack paragraphs starting at current line and going down until indentation changes *) IF (Rec.Wrapping) AND (NOT Rec.ReadOnly) THEN Rec.ChangeMade := TRUE; Reformat(); END; | Key.F7 + Key.FShift: (*ShiftF7 toggles between wrapping and not wrapping.*) Rec.Wrapping := NOT Rec.Wrapping; IF Rec.Wrapping AND (NOT Rec.ReadOnly) THEN Rec.ChangeMade := TRUE; Reformat(); END; | Key.F8: Testing := NOT Testing; | Key.BackSpace : IF NOT Rec.ReadOnly THEN Rec.ChangeMade := TRUE; IF TheNdx>0 THEN DeleteAChar(1); ELSE JoinLines(); END; END; | Key.Return : IF NOT Rec.ReadOnly THEN Rec.ChangeMade := TRUE; NewLine(); END; ELSE IF (NOT Rec.ReadOnly) AND (Rec.EdLastKey # 0) AND (Rec.EdLastKey < KbdInput.Extended) THEN Rec.ChangeMade := TRUE; ReplaceWith( CHR(Rec.EdLastKey) ); END; END; END; END KeyResponse; VAR SavedHeight, BxCol1, BxCol2, BxRow1, BxRow2 : CARDINAL; BEGIN (*DefaultEditor*) GetFrameRecData(); Rec.ChangeMade := FALSE; IF Rec.Col2 < Rec.Col1 THEN INC(Rec.Col2, Rec.Col1); END; ColsScrolled := 0; LastLineDeleted := 0; Rec.Col1 := Numbers.Between(1, Rec.Col1, DisplayLeng); Rec.Row1 := Numbers.Between(1, Rec.Row1, Rec.Row2); Rec.Row2 := Numbers.Between(Rec.Row1, Rec.Row2, VWindows.EndRow(Rec.WindowHandle)); Rec.Col2 := Numbers.Between(Rec.Col1, Rec.Col2, DisplayLeng); BxCol1 := Rec.Col1; BxCol2 := Rec.Col2; BxRow1 := Rec.Row1; BxRow2 := Rec.Row2; IF Rec.FrameRec # NIL THEN SavedHeight := VWindows.GetCursorHeight( Rec.FrameRec^.WindowHandle ); END; SetAttribOrColor( Rec.EntryForeBox, Rec.EntryBackBox, Rec.EntryAttrib ); CASE Rec.EntryBox OF (* Draw Entry Box *) 2: VWindows.DrawBox( Rec.WindowHandle, VWindows.DoubleBox, Rec.Col1, Rec.Row1, Rec.Col2, Rec.Row2); | 1: VWindows.DrawBox( Rec.WindowHandle, VWindows.SingleBox, Rec.Col1, Rec.Row1, Rec.Col2, Rec.Row2); ELSE (*do nothing*); END; IF (Rec.EntryBox # 0) OR (Rec.ExitBox # 0) THEN (* Correct coordinates to the area inside the box *) INC(Rec.Col1); INC(Rec.Row1); DEC(Rec.Row2); DEC(Rec.Col2); END; IF Rec.DoCounting AND (Rec.Row2 >= Rec.CountRow) THEN Rec.Row2 := Numbers.Min( Rec.Row2, Rec.CountRow - 1 ); (*This makes sure Row2 doesn't interfere with the prompt line.*) END; WindowHeight := Rec.Row2 - Rec.Row1 + 1; Rec.TextRow1 := Numbers.Between(1, Rec.TextRow1, GenLists.ListLength(TheList)); Rec.CursorCol := Numbers.Between(1, Rec.CursorCol, (Rec.Col2 - Rec.Col1) + 1 ); Rec.CursorRow := Numbers.Between(1, Rec.CursorRow, WindowHeight ); Rec.CursorRow := Numbers.Between(1, Rec.CursorRow, GenLists.ListLength(TheList) + 1 - Rec.TextRow1 ); (*We correct Rec.CursorRow again to prevent it from falling below the bottom of TheList. Added 16 Nov 86.*) SetAttribOrColor( Rec.EntryForeColor, Rec.EntryBackColor, Rec.EntryAttrib ); MaxLength := (Rec.Col2 - Rec.Col1) + 1; LowLevel.Fill( SYSTEM.ADR(BlankStr), DisplayLeng + 1, blank); Testing := FALSE; IF GenLists.ListLength( TheList) # 0 THEN WriteStrings( Rec.TextRow1, Rec.Row1, Rec.Row2); TLine := Rec.TextRow1 + Rec.CursorRow - 1; ELSE (* set counter to line one and clear window *) GenLists.ListInsert( '', GenLists.StrCode, TheList, 1); TLine := 1; VWindows.ClearPart( Rec.WindowHandle, Rec.Col1, Rec.Row1, Rec.Col2, Rec.Row2); END; TheRow := Rec.CursorRow + Rec.Row1 - 1; TheNdx := Rec.CursorCol - 1; CountChars( 1, RCharCnt.longi, RLineCnt, TLine, TCharCnt.longi); TCharCnt.longi := TCharCnt.longi + Numbers.Lc( TheNdx ); IF Rec.DoCounting THEN WriteFooter(); ELSE RCharCnt.longi := NumTypes.L1; RLineCnt := 1; TCharCnt.longi := NumTypes.L1; END; VWindows.GotoXY( Rec.WindowHandle, Rec.Col1 + TheNdx - ColsScrolled, TheRow); IF Rec.overwriting THEN VWindows.SetCursorHeight( Rec.WindowHandle, 2); ELSE VWindows.SetCursorHeight( Rec.WindowHandle, 4); END; KeyResponse(); Rec.CursorRow := (TheRow + 1) - Rec.Row1; Rec.CursorCol := 1 + TheNdx; Rec.TextRow1 := TLine + 1 - Rec.CursorRow; DoExitBox := ( Rec.ExitBox # Rec.EntryBox) OR ( Rec.ExitForeBox # Rec.EntryForeBox) OR ( Rec.ExitBackBox # Rec.EntryBackBox) OR ( Rec.ExitAttrib # Rec.EntryAttrib); (* whether the exit box differs from the entry, and so must be re-drawn *) IF DoExitBox THEN SetAttribOrColor( Rec.ExitForeBox, Rec.ExitBackBox, Rec.ExitAttrib ); CASE Rec.ExitBox OF 2: VWindows.DrawBox( Rec.WindowHandle, VWindows.DoubleBox, BxCol1, BxRow1, BxCol2, BxRow2); | 1: VWindows.DrawBox( Rec.WindowHandle, VWindows.SingleBox, BxCol1, BxRow1, BxCol2, BxRow2); ELSE VWindows.ClearPart( Rec.WindowHandle, BxCol1, BxRow1, BxCol2, BxRow2); END; END; SetAttribOrColor( Rec.ExitForeColor, Rec.ExitBackColor, Rec.ExitAttrib ); IF (Rec.EntryForeColor # Rec.ExitForeColor) OR (Rec.EntryBackColor # Rec.ExitBackColor) OR (Rec.EntryAttrib # Rec.ExitAttrib) OR (DoExitBox AND ( Rec.ExitBox = 0)) THEN WriteStrings( TLine - (TheRow - Rec.Row1), Rec.Row1, Rec.Row2); (* Rewrite the current screen *) END; IF (Rec.EntryBox # 0) OR (Rec.ExitBox # 0) THEN (* Set coordinates back to area that includes box *) DEC(Rec.Col1); DEC(Rec.Row1); INC(Rec.Row2); INC(Rec.Col2); END; UpdateFrameRec(); IF Rec.FrameRec # NIL THEN VWindows.SetCursorHeight( Rec.FrameRec^.WindowHandle, SavedHeight ); END; END DefaultEditor; PROCEDURE SetGlobals( VAR Rec: VEditor.AnEdControlRec ); BEGIN overwriting := Rec.overwriting; DoCounting := Rec.DoCounting; MaxLines := Rec.MaxLines; EdLastKey := Rec.EdLastKey; ExitBox := Rec.ExitBox; EntryBox := Rec.EntryBox; CountRow := Rec.CountRow; EdPromptFore := Rec.EdPromptFore; EdPromptBack := Rec.EdPromptBack; EdPromptAttrib := Rec.EdPromptAttrib; EntryAttrib := Rec.EntryAttrib; ExitAttrib := Rec.ExitAttrib; EntryForeColor := Rec.EntryForeColor; EntryBackColor := Rec.EntryBackColor; ExitForeColor := Rec.ExitForeColor; ExitBackColor := Rec.ExitBackColor; EntryForeBox := Rec.EntryForeBox; EntryBackBox := Rec.EntryBackBox; ExitForeBox := Rec.ExitForeBox; ExitBackBox := Rec.ExitBackBox; END SetGlobals; PROCEDURE GetGlobals( VAR Rec: VEditor.AnEdControlRec ); BEGIN Rec.overwriting := overwriting; Rec.DoCounting := DoCounting; Rec.MaxLines := MaxLines; Rec.ExitBox := ExitBox; Rec.EntryBox := EntryBox; Rec.CountRow := CountRow; Rec.EdPromptFore := EdPromptFore; Rec.EdPromptBack := EdPromptBack; Rec.EdPromptAttrib := EdPromptAttrib; Rec.EntryAttrib := EntryAttrib; Rec.ExitAttrib := ExitAttrib; Rec.EntryForeColor := EntryForeColor; Rec.EntryBackColor := EntryBackColor; Rec.ExitForeColor := ExitForeColor; Rec.ExitBackColor := ExitBackColor; Rec.EntryForeBox := EntryForeBox; Rec.EntryBackBox := EntryBackBox; Rec.ExitForeBox := ExitForeBox; Rec.ExitBackBox := ExitBackBox; END GetGlobals; VAR GlobalEdRec: VEditor.AnEdControlRec; PROCEDURE ScrnEdit(Col1, Row1, Col2, Row2 : CARDINAL; VAR TheList : GenLists.GenList; VAR TextRow1, CursorCol, CursorRow: CARDINAL; VAR ChangeMade: BOOLEAN; ReadOnly: BOOLEAN; VAR FrameRec: ScrnTypes.DisplayFrame): INTEGER; VAR LocalRec : VEditor.AnEdControlRec; tmpint: INTEGER; BEGIN VEditor.InitEdRec( LocalRec ); GetGlobals( LocalRec ); LocalRec.Wrapping := FALSE; LocalRec.NextFrame := ''; LocalRec.Col1 := Col1; LocalRec.Row1 := Row1; LocalRec.Col2 := Col2; LocalRec.Row2 := Row2; LocalRec.TextRow1 := TextRow1; LocalRec.CursorCol := CursorCol; LocalRec.CursorRow := CursorRow; LocalRec.ChangeMade := ChangeMade; LocalRec.ReadOnly := ReadOnly; LocalRec.FrameRec := FrameRec; DefaultEditor( TheList, LocalRec ); TextRow1 := LocalRec.TextRow1; CursorCol := LocalRec.CursorCol; CursorRow := LocalRec.CursorRow; ChangeMade := LocalRec.ChangeMade; IF StrConv.StrToInteger( LocalRec.NextFrame, 0, tmpint ) THEN RETURN tmpint; ELSE RETURN 0; END; END ScrnEdit; PROCEDURE Init(); BEGIN IF Initialized THEN RETURN; ELSE Initialized := TRUE; END; (*EntryDiag: Diagnostics.Init(); :EntryDiag*) BigSets.Init(); ByteFiddler.Init(); GenLists.Init(); KbdInput.Init(); Key.Init(); ListUtils.Init(); LowLevel.Init(); M2Strings.Init(); MsColors.Init(); Numbers.Init(); NumTypes.Init(); PosUtils.Init(); ScrnTypes.Init(); ScrnUtl1.Init(); Spkr.Init(); StrConv.Init(); StrEdit.Init(); UserOps.Init(); VEditor.Init(); VWindows.Init(); (*EntryDiag: Diagnostics.diagS( 'Entering Editor', '' ); :EntryDiag*) VEditor.InitEdRec( GlobalEdRec ); SetGlobals( GlobalEdRec ); blank[0] := ' '; GenLists.NilList( DeleteBuffer ); (*EntryDiag: Diagnostics.diagS( 'Exiting Editor', '' ); :EntryDiag*) END Init; BEGIN Initialized := FALSE; Init(); END Editor.