| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- MODULE editor;
- (* based on the kilo editor building course*)
- (* Step 28 *)
- (******************** INCLUDES ******************)
- IMPORT FIO, IO, SYSTEM, termios, NumberIO;
- IMPORT CharClass, libc, ASCII;
- IMPORT errno;
- IMPORT VT100;
- FROM Strings IMPORT Concat, String1, Length, Delete;
- IMPORT SplitV1;
- IMPORT Delay;
- (******************** DATA ******************)
- VAR
- c : CHAR;
- p : POINTER TO CHAR;
-
- result : INTEGER;
- number : CARDINAL;
- editorConfig : RECORD
- screenrows : CARDINAL;
- screencols : CARDINAL;
- theTermios : termios.TERMIOS;
- raw : termios.TERMIOS;
- END;
- (* testing *)
- test : BOOLEAN;
- clearScreenStr : ARRAY[0..6] OF CHAR;
- cursorHomeStr : ARRAY[0..2] OF CHAR;
- cursorposStr : ARRAY[0..9] OF CHAR;
- requestCursorPosStr : ARRAY[0..15] OF CHAR;
- adresse : SYSTEM.ADDRESS;
- X,Y : CARDINAL;
- (******************** Utilities *****************)
- PROCEDURE WriteString( str : ARRAY OF CHAR);
- (* IO procedures : direct to libc in unbuffered mode *)
- VAR
- i : CARDINAL;
- BEGIN
- FOR i := 1 TO Length(str) DO
- IO.Write(str[i])
- END;
- END WriteString;
- (******************** 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);
- WriteString(clearScreenStr);
- HALT
- END die;
- PROCEDURE disablerawMode() : INTEGER;
- VAR
- TCSAFLUSH : INTEGER;
- result : INTEGER;
-
- BEGIN
- IO.BufferedMode(0,TRUE);
- IO.BufferedMode(1,TRUE);
- TCSAFLUSH := termios.tcsflush ();
- IF termios.tcsetattr(FIO.StdIn, TCSAFLUSH, editorConfig.theTermios) = -1 THEN
- die("tcsetattr")
- END;
- RETURN 1
- END disablerawMode;
- PROCEDURE enablerawMode;
- VAR
- TCSAFLUSH : INTEGER;
- result : INTEGER;
- bresult : BOOLEAN;
- BEGIN
- TCSAFLUSH := termios.tcsflush ();
- libc.atexit(disablerawMode);
-
- bresult := termios.SetFlag(editorConfig.raw,termios.cs8, TRUE);
- IF termios.tcsetattr(FIO.StdIn, TCSAFLUSH, editorConfig.raw) = -1 THEN
- die("tcsetattr")
- 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;
- BEGIN
- FOR y := 1 TO 24 DO
- IO.Write("~");
- IO.Write(CHR(13));
- IO.Write(CHR(10));
- END;
- END editorDrawRows;
- PROCEDURE editorRefreshScreen;
- VAR
- i : CARDINAL;
- BEGIN
- (* modif *)
- (* 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 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;
- PROCEDURE requestCursorPosition(VAR x,y : CARDINAL);
- (* ESC[6n request cursor position (reports as ESC[#;#R) *)
- VAR
- str : ARRAY [0..15] OF CHAR;
- theStructure : SplitV1.Structure;
- c : CHAR;
- cc : String1;
- i : CARDINAL;
- BEGIN
- str := "";
- SplitV1.InitStructure(theStructure);
- (* sending the request *)
- (* WriteString(requestCursorPosStr); *)
- Concat(str,ASCII.esc,str);
- Concat(str,"[6n", str);
- FOR i := 0 TO Length(str) DO
- IO.Write(str[i])
- END;
- (* quering the answer *)
- str := "";
- REPEAT
- IO.Read(c);
- cc[0] := c;
- Concat(str,cc,str);
- UNTIL c = "R";
- (* extracting coodinates from the answer *)
- Delete(str,0,2);
- Delete(str,Length(str) -1 ,1);
- SplitV1.SplitStr(str, ";", theStructure);
- NumberIO.StrToCard(theStructure[0].element,x);
- NumberIO.StrToCard(theStructure[1].element,y);
- END requestCursorPosition;
- PROCEDURE cursorpos(x,y : CARDINAL);
- VAR
- tmpString : ARRAY[0..15] OF CHAR;
- tmpString1: ARRAY[0..15] OF CHAR;
- tmpString2: String1;
- i : CARDINAL;
- BEGIN
- cursorposStr := "";
- Concat(cursorposStr, ASCII.esc,cursorposStr);
- Concat(cursorposStr, "[",cursorposStr);
- tmpString := "";
- Concat(tmpString,cursorposStr, tmpString);
- tmpString1 := "";
- Card2Str(y,tmpString1);
- Concat(tmpString,tmpString1, tmpString);
- tmpString2[0] := ";";
- Concat(tmpString, tmpString2,tmpString);
- tmpString1 := "";
- Card2Str(x,tmpString1);
- Concat(tmpString,tmpString1, tmpString);
- tmpString2[0] := "H";
- Concat(tmpString, tmpString2,tmpString);
- FOR i := 0 TO Length(tmpString) DO
- IO.Write(tmpString[i])
- END;
- END cursorpos;
- PROCEDURE getWindowSize(VAR y : CARDINAL; 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 := "";
- Concat(cursorHomeStr,ASCII.esc,cursorHomeStr);
- Concat(cursorHomeStr,"[H",cursorHomeStr);
- clearScreenStr := "";
- Concat(clearScreenStr,ASCII.esc,clearScreenStr);
- Concat(clearScreenStr,"[2J",clearScreenStr);
- cursorposStr := "";
- Concat(cursorposStr,ASCII.esc,cursorposStr);
- Concat(cursorposStr,"[",cursorposStr);
-
- requestCursorPosStr := "";
- Concat(requestCursorPosStr,ASCII.esc,requestCursorPosStr);
- Concat(requestCursorPosStr,"[6n",requestCursorPosStr);
- END InitScreenEscapes;
- PROCEDURE InitEditor;
- BEGIN
- getWindowSize(editorConfig.screenrows, editorConfig.screencols)
- END InitEditor;
- BEGIN
- InitScreenEscapes;
- (* termios state saved *)
- editorConfig.theTermios := termios.InitTermios();
- (* a copy of it *)
- editorConfig.raw := termios.InitTermios();
- IF termios.tcgetattr(FIO.StdIn, editorConfig.theTermios) = -1 THEN
- die("tcgetattr")
- END;
- IF termios.tcgetattr(FIO.StdIn, editorConfig.raw) = -1 THEN
- die("tcgetattr")
- END;
- (* end termios *)
- (* enablerawMode;
- InitEditor;
- LOOP
- editorRefreshScreen;
- editorProcessKeypress;
- editorRefreshScreen;
- END; *)
- cursorpos(30,30);
- requestCursorPosition(X,Y);
- result := disablerawMode();
- NumberIO.WriteCard(X, 5);
- NumberIO.WriteCard(Y, 5);
- (* cleaning ...*)
- adresse := termios.KillTermios(editorConfig.raw);
- END editor.
|