MODULE editor1; (* based on the kilo editor building course*) (* Step 28 *) (******************** INCLUDES ******************) IMPORT IO, Strings, ASCII, NumberIO, termios, FIO, Delay, SplitV1, STextIO; IMPORT libc, SYSTEM, Storage, MemUtils; (******************** DATA ******************) TYPE abufType = RECORD b : SYSTEM.ADDRESS; len : CARDINAL; END; abufTypePtr = POINTER TO abufType; VAR editorConfig : RECORD screenrows : CARDINAL; screencols : CARDINAL; theTermios : termios.TERMIOS; END; TCSAFLUSH : INTEGER; theStructure : SplitV1.Structure; cursorposStr : ARRAY [0..15] OF CHAR; clearScreenStr : ARRAY[0..6] OF CHAR; cursorHomeStr : ARRAY[0..2] OF CHAR; requestCursorPosStr : ARRAY[0..15] OF CHAR; resultStr : ARRAY [0..15] OF CHAR; tmpString : ARRAY[0..15] OF CHAR; tmpString1 : ARRAY[0..15] OF CHAR; tmpString2 : Strings.String1; cc : Strings.String1; i : CARDINAL; str : ARRAY [0..15] OF CHAR; abuf : abufType; abufInit : abufType; (******************** Utilities *****************) PROCEDURE Card2Str ( x : CARDINAL; VAR str : ARRAY OF CHAR); BEGIN IF x < 10 THEN NumberIO.CardToStr(x,1,str); ELSIF x < 100 THEN NumberIO.CardToStr(x,2,str); ELSE NumberIO.CardToStr(x,3,str); END; END Card2Str; (******************** TERMINAL ******************) PROCEDURE CtrlKey(c: CHAR) : CARDINAL; (* return a value < ORD(" ") for the control keys *) VAR n : BITSET; BEGIN n := BITSET(ORD(c)); n := n * BITSET(1FH); RETURN CARDINAL(n) END CtrlKey; PROCEDURE die (s : ARRAY OF CHAR); BEGIN libc.perror(s); FOR i := 0 TO Strings.Length(s) DO IO.Write(s[i]) END; HALT END die; PROCEDURE disablerawMode() : INTEGER; VAR result : INTEGER; BEGIN IO.BufferedMode(0,TRUE); IO.BufferedMode(1,TRUE); result := termios.tcsetattr(FIO.StdIn, TCSAFLUSH, editorConfig.theTermios); IF result = -1 THEN die("tcsetattr") ELSE RETURN result END; END disablerawMode; PROCEDURE enablerawMode; BEGIN libc.atexit(disablerawMode); editorConfig.theTermios := termios.InitTermios(); (* raw := termios.InitTermios(); *) IF termios.tcgetattr(FIO.StdIn, editorConfig.theTermios) = -1 THEN die("tcgetattr") END; IO.UnBufferedMode(0,TRUE); IO.UnBufferedMode(1,TRUE); END enablerawMode; PROCEDURE editorReadKey() : CHAR; VAR c : CHAR; BEGIN IO.Read(c); RETURN c END editorReadKey; (******************** Buffer ******************) PROCEDURE abAppend (ptr : abufTypePtr; str: ARRAY OF CHAR; len : CARDINAL); BEGIN (* REALLOCATE - attempts to reallocate storage. The address, a, should either be NIL in which case ALLOCATE is called, or alternatively it should have already been initialized by ALLOCATE. The allocated storage is resized accordingly. *) (* PROCEDURE REALLOCATE (VAR a: ADDRESS; Size: CARDINAL) ; *) Storage.REALLOCATE( ptr^.b,ptr^.len + len); (* PROCEDURE MemCopy (from: ADDRESS; length: CARDINAL; to: ADDRESS) ; *) IF ptr^.b <> NIL THEN MemUtils.MemCopy(SYSTEM.ADR(str),len, ptr^.b); ptr^.len := ptr^.len + len; END; END abAppend; PROCEDURE abFree (ptr : abufTypePtr); BEGIN (* PROCEDURE DEALLOCATE (VAR a: ADDRESS ; Size: CARDINAL) ; *) Storage.DEALLOCATE(ptr^.b, ptr^.len); ptr^.len := 0; END abFree; (******************** output ******************) PROCEDURE editorDrawRows; VAR y : CARDINAL; str : ARRAY [0..15] OF CHAR; BEGIN str[0] := "~"; str[1] := CHR(13); str[2] := CHR(10); str[3] := CHR(0); FOR y := 1 TO editorConfig.screenrows -1 DO (* IO.Write("~"); IO.Write(CHR(13)); IO.Write(CHR(10)); *) libc.write(FIO.StdOut,SYSTEM.ADR(str),3); END; IO.Write("~"); END editorDrawRows; PROCEDURE editorRefreshScreen; BEGIN (* modif using libc write procedure *) libc.write(FIO.StdOut,SYSTEM.ADR(clearScreenStr),3); libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr),3); editorDrawRows; libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr),3); (* WriteString(clearScreenStr); WriteString(cursorHomeStr); *) (* FOR i := 0 TO 3 DO IO.Write(clearScreenStr[i]) END; *) (* FOR i := 0 TO 3 DO IO.Write(cursorHomeStr[i]) END; *) (* editorDrawRows; *) (* WriteString(cursorHomeStr); *) (* FOR i := 0 TO 3 DO IO.Write(cursorHomeStr[i]) END; *) END editorRefreshScreen; PROCEDURE requestCursorPosition(VAR x,y : CARDINAL); VAR c : CHAR; BEGIN str := ""; SplitV1.InitStructure(theStructure); Strings.Concat(str,ASCII.esc,str); Strings.Concat(str,"[6n", str); (* sending request *) (* FOR i := 0 TO 3 DO IO.Write(str[i]) END; *) libc.write(FIO.StdOut,SYSTEM.ADR(str),4); (* getting answer *) str := ""; REPEAT IO.Read(c); cc[0] := c; Strings.Concat(str,cc,str); UNTIL c = "R"; (* displaying the retour , changing the escape to ? *) (* str[0] := "?"; *) (* FOR i := 0 TO Strings.Length(str) DO IO.Write(str[i]) END; *) (* libc.write(FIO.StdOut,SYSTEM.ADR(str),Length(str)); *) (* extracting the coordinates *) Strings.Delete(str,0,2); Strings.Delete(str,Strings.Length(str) -1 ,1); SplitV1.SplitStr(str, ";", theStructure); NumberIO.StrToCard(theStructure[0].element,x); NumberIO.StrToCard(theStructure[1].element,y); (* NumberIO.WriteCard(x, 5); NumberIO.WriteCard(y, 5); *) END requestCursorPosition; PROCEDURE cursorpos(x,y : CARDINAL); BEGIN cursorposStr := ""; Strings.Concat(cursorposStr, ASCII.esc,cursorposStr); Strings.Concat(cursorposStr, "[",cursorposStr); tmpString := ""; Strings.Concat(tmpString,cursorposStr, tmpString); tmpString1 := ""; Card2Str(y,tmpString1); Strings.Concat(tmpString,tmpString1, tmpString); tmpString2[0] := ";"; Strings.Concat(tmpString, tmpString2,tmpString); tmpString1 := ""; Card2Str(x,tmpString1); Strings.Concat(tmpString,tmpString1, tmpString); tmpString2[0] := "H"; Strings.Concat(tmpString, tmpString2,tmpString); (* FOR i := 0 TO Strings.Length(tmpString) DO IO.Write(tmpString[i]) END; *) libc.write(FIO.StdOut,SYSTEM.ADR(tmpString),Strings.Length(tmpString)); END cursorpos; PROCEDURE getWindowSize(VAR y : CARDINAL; VAR x: CARDINAL); BEGIN cursorpos(999,999); requestCursorPosition(x,y); END getWindowSize; (******************** input ******************) PROCEDURE editorProcessKeypress; VAR c : CHAR; b : BOOLEAN; BEGIN c := editorReadKey(); CASE ORD(c) OF 17 : HALT; END END editorProcessKeypress; (******************** INIT ******************) PROCEDURE InitScreenEscapes; VAR temp : ARRAY[0..10] OF CHAR; BEGIN cursorHomeStr := ""; Strings.Concat(cursorHomeStr,ASCII.esc,cursorHomeStr); Strings.Concat(cursorHomeStr,"[H",cursorHomeStr); clearScreenStr := ""; Strings.Concat(clearScreenStr,ASCII.esc,clearScreenStr); Strings.Concat(clearScreenStr,"[2J",clearScreenStr); cursorposStr := ""; Strings.Concat(cursorposStr,ASCII.esc,cursorposStr); Strings.Concat(cursorposStr,"[",cursorposStr); requestCursorPosStr := ""; Strings.Concat(requestCursorPosStr,ASCII.esc,requestCursorPosStr); Strings.Concat(requestCursorPosStr,"[6n",requestCursorPosStr); END InitScreenEscapes; PROCEDURE InitEditor; BEGIN TCSAFLUSH := termios.tcsflush (); InitScreenEscapes; getWindowSize(editorConfig.screenrows, editorConfig.screencols); abufInit.len := 0; abufInit.b := NIL; END InitEditor; BEGIN enablerawMode; InitEditor; LOOP editorRefreshScreen; editorProcessKeypress; editorRefreshScreen; END; (* Delay.Delay(2000); *) IF disablerawMode() = -1 THEN HALT END; NumberIO.WriteCard(editorConfig.screencols, 5); NumberIO.WriteCard(editorConfig.screenrows, 5); END editor1.