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; (******************** DATA ******************) TYPE abufType = RECORD b : SYSTEM.ADDRESS; len : CARDINAL; END; 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; (******************** 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.