| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- MODULE editor1;
- (* based on the kilo editor building course*)
- (* Step 39 *)
- (******************** INCLUDES ******************)
- IMPORT IO, Strings, ASCII, NumberIO, termios, FIO, Delay, SplitV1, STextIO;
- IMPORT libc, SYSTEM, Storage, MemUtils;
- (******************** DATA ******************)
- CONST
- KILO_VERSION = "0.0.1";
- TYPE
- abufType = RECORD
- b : SYSTEM.ADDRESS;
- len : CARDINAL;
- END;
- abufTypePtr = POINTER TO abufType;
- VAR
- editorConfig : RECORD
- screenrows : CARDINAL;
- screencols : CARDINAL;
- theTermios : termios.TERMIOS;
- posX, posY : CARDINAL;
- 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;
- cursorOnStr : ARRAY[0..6] OF CHAR;
- cursorOffStr : ARRAY[0..6] OF CHAR;
- tildeStr : ARRAY[0..3] OF CHAR;
- eraseLineStr : ARRAY[0..2] 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;
-
- (******************** 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();
- 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;
- str : ARRAY [0..2] OF CHAR;
- BEGIN
- IO.Read(c);
- IF c = ASCII.esc THEN
- IO.Read(c);
- IF c = "[" THEN
- IO.Read(c);
- (*
- Arrow Keys:
- Reset Set
- ----- ---
- up ^[A ^[OA
- down ^[B ^[OB
- right ^[C ^[OC
- left ^[D ^[OD
- *)
- CASE c OF
- "A" : c := "e"; |
- "B" : c := "x" |
- "C" : c := "d" |
- "D" : c := "s"
- END;
- END;
- END;
- RETURN c
- END editorReadKey;
- (******************** Buffer ******************)
- PROCEDURE abufInit( VAR ptr : abufTypePtr);
- BEGIN
- Storage.ALLOCATE(ptr,SYSTEM.TSIZE(abufType) );
- ptr^.b := NIL;
- ptr^.len := 0;
- END abufInit;
- PROCEDURE abAppend (VAR ptr : abufTypePtr; str: ARRAY OF CHAR );
- VAR
- llen : CARDINAL;
- BEGIN
- llen := Strings.Length(str);
- IF ptr <> NIL THEN
- IF ptr^.b = NIL THEN
- Storage.ALLOCATE(ptr^.b,llen);
- ELSE
- Storage.REALLOCATE( ptr^.b,ptr^.len + llen);
- END;
- MemUtils.MemCopy(SYSTEM.ADR(str),llen, SYSTEM.ADDADR(ptr^.b,ptr^.len));
- ptr^.len := ptr^.len + llen;
- END;
- END abAppend;
- PROCEDURE abFree (VAR ptr : abufTypePtr);
- BEGIN
- Storage.DEALLOCATE(ptr^.b, ptr^.len);
- Storage.DEALLOCATE(ptr,SYSTEM.TSIZE(abufType));
- END abFree;
- (******************** output ******************)
- PROCEDURE editorDrawRows(VAR ptr : abufTypePtr);
- VAR
- y : CARDINAL;
- str : ARRAY [0..3] OF CHAR;
- welcome : ARRAY [0..79] OF CHAR;
- welcomeLen : CARDINAL;
- blanks : CARDINAL;
- blanksStr : ARRAY[0..79] OF CHAR;
- template : ARRAY[0..79] OF CHAR;
- i : CARDINAL;
- string1 : Strings.String1;
- BEGIN
- (* template := " "; *)
- welcome := "Kilo editor -- version ";
- Strings.Concat(welcome,KILO_VERSION,welcome);
- welcomeLen := Strings.Length(welcome);
- cc[0] := CHR(13);
- Strings.Concat(welcome,cc,welcome);
- cc[0] := CHR(10);
- Strings.Concat(welcome,cc,welcome);
- blanks := (editorConfig.screencols - welcomeLen) /2;
- blanksStr := "";
- (*
- Copy - copy at most, length, characters in, substr, to, str,
- starting at position, index.
- *)
- (* PROCEDURE Copy (str: ARRAY OF CHAR; index, length: CARDINAL; VAR result: ARRAY OF CHAR) ; *)
- (* Strings.Copy(template,0,blanks,blanksStr); doesn't work !*)
- (* a workaround *)
- string1[0] := " ";
- FOR i := 0 TO blanks DO
- Strings.Concat(blanksStr,string1,blanksStr);
- END;
- FOR y := 1 TO editorConfig.screenrows -1 DO
- IF ((y = (editorConfig.screenrows / 3)) AND (editorConfig.screencols > welcomeLen)) THEN
- abAppend(ptr,blanksStr);
- abAppend(ptr,welcome);
- ELSE
- abAppend(ptr,tildeStr);
- END;
- abAppend(ptr,eraseLineStr)
- END;
- abAppend(ptr,"~");
- END editorDrawRows;
- PROCEDURE editorRefreshScreen;
- VAR
- ptr : abufTypePtr;
- BEGIN
- abufInit(ptr);
- abAppend(ptr,cursorOffStr);
- abAppend(ptr,cursorHomeStr);
- editorDrawRows(ptr);
- cursorpos(editorConfig.posX,editorConfig.posY,FALSE);
- abAppend(ptr,cursorposStr);
- abAppend(ptr,cursorOnStr);
- libc.write(FIO.StdOut,ptr^.b,ptr^.len);
- abFree(ptr);
- 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);
- 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";
- (* 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,y);
- NumberIO.StrToCard(theStructure[1].element,x);
- END requestCursorPosition;
- PROCEDURE cursorpos(x,y : CARDINAL; emit : BOOLEAN);
- 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);
- cursorposStr := tmpString;
- editorConfig.posX := x;
- editorConfig.posY := y;
- libc.write(FIO.StdOut,SYSTEM.ADR(tmpString),Strings.Length(tmpString));
- END cursorpos;
- PROCEDURE getWindowSize(VAR y : CARDINAL; VAR x: CARDINAL);
-
- BEGIN
- cursorpos(999,999,TRUE);
- requestCursorPosition(x,y);
- END getWindowSize;
- (******************** input ******************)
- PROCEDURE editorProcessKeypress;
- VAR
- c : CHAR;
- b : BOOLEAN;
- BEGIN
- c := editorReadKey();
- WITH editorConfig DO
- CASE ORD(c) OF
- 17 : HALT; |
- ORD("e") : IF posY > 1 THEN DEC(posY) END; |
- ORD("x") : IF posY < (screenrows - 1) THEN INC(posY) END; |
- ORD("s") : IF posX > 1 THEN DEC(posX) END; |
- ORD("d") : IF posX < (screencols - 1) THEN INC(posX) END;
- END
- 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);
-
- cursorOnStr := "";
- Strings.Concat(cursorOnStr,ASCII.esc,cursorOnStr);
- Strings.Concat(cursorOnStr,"[?25h",cursorOnStr);
-
- cursorOffStr := "";
- Strings.Concat(cursorOffStr,ASCII.esc,cursorOffStr);
- Strings.Concat(cursorOffStr,"[?25l",cursorOffStr);
-
- tildeStr := "~";
- cc[0] := CHR(13);
- Strings.Concat(tildeStr,cc,tildeStr);
- cc[0] := CHR(10);
- Strings.Concat(tildeStr,cc,tildeStr);
- eraseLineStr := "";
- Strings.Concat(eraseLineStr,ASCII.esc,eraseLineStr);
- Strings.Concat(eraseLineStr,"[K",eraseLineStr);
- END InitScreenEscapes;
- PROCEDURE InitEditor;
- BEGIN
- TCSAFLUSH := termios.tcsflush ();
- InitScreenEscapes;
- editorConfig.posX := 1;
- editorConfig.posY := 1;
- getWindowSize(editorConfig.screenrows, editorConfig.screencols);
- editorConfig.posX := 1;
- editorConfig.posY := 1;
- libc.write(FIO.StdOut,SYSTEM.ADR(clearScreenStr),4);
- (* NumberIO.WriteCard(editorConfig.screencols,5);
- NumberIO.WriteCard(editorConfig.screenrows,5);
- Delay.Delay(2000) *)
- END InitEditor;
- BEGIN
- enablerawMode;
- InitEditor;
- LOOP
- editorRefreshScreen;
- editorProcessKeypress;
- (* editorRefreshScreen; *)
- END;
- IF disablerawMode() = -1 THEN
- HALT
- END;
- NumberIO.WriteCard(editorConfig.screencols, 5);
- NumberIO.WriteCard(editorConfig.screenrows, 5);
- END editor1.
|