editor.mod 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. MODULE editor;
  2. (* based on the kilo editor building course*)
  3. (* Step 27 *)
  4. (******************** INCLUDES ******************)
  5. IMPORT FIO, IO, SYSTEM, termios, NumberIO;
  6. IMPORT CharClass, libc, ASCII;
  7. IMPORT errno;
  8. IMPORT VT100;
  9. FROM Strings IMPORT Concat, String1, Length, Delete;
  10. IMPORT SplitV1;
  11. IMPORT Delay;
  12. (******************** DATA ******************)
  13. VAR
  14. c : CHAR;
  15. p : POINTER TO CHAR;
  16. result : INTEGER;
  17. number : CARDINAL;
  18. editorConfig : RECORD
  19. theTermios : termios.TERMIOS;
  20. raw : termios.TERMIOS;
  21. END;
  22. (* testing *)
  23. test : BOOLEAN;
  24. clearScreenStr : ARRAY[0..6] OF CHAR;
  25. cursorHomeStr : ARRAY[0..2] OF CHAR;
  26. cursorposStr : ARRAY[0..9] OF CHAR;
  27. requestCursorPosStr : ARRAY[0..9] OF CHAR;
  28. coordX, coordY : CARDINAL;
  29. adresse : SYSTEM.ADDRESS;
  30. (******************** Utilities *****************)
  31. PROCEDURE WriteString( str : ARRAY OF CHAR);
  32. (* IO procedures : direct to libc in unbuffered mode *)
  33. VAR
  34. i : CARDINAL;
  35. BEGIN
  36. FOR i := 1 TO Length(str) DO
  37. IO.Write(str[i])
  38. END;
  39. END WriteString;
  40. (******************** TERMINAL ******************)
  41. PROCEDURE CtrlKey(c: CHAR) : CARDINAL;
  42. (* return a value < ORD(" ") for the control keys *)
  43. VAR
  44. n : BITSET;
  45. BEGIN
  46. n := BITSET(ORD(c));
  47. n := n * BITSET(1FH);
  48. RETURN CARDINAL(n)
  49. END CtrlKey;
  50. PROCEDURE die (s : ARRAY OF CHAR);
  51. BEGIN
  52. libc.perror(s);
  53. WriteString(clearScreenStr);
  54. HALT
  55. END die;
  56. PROCEDURE disablerawMode() : INTEGER;
  57. VAR
  58. TCSAFLUSH : INTEGER;
  59. result : INTEGER;
  60. BEGIN
  61. IO.BufferedMode(0,TRUE);
  62. IO.BufferedMode(1,TRUE);
  63. TCSAFLUSH := termios.tcsflush ();
  64. IF termios.tcsetattr(FIO.StdIn, TCSAFLUSH, editorConfig.theTermios) = -1 THEN
  65. die("tcsetattr")
  66. END;
  67. RETURN 1
  68. END disablerawMode;
  69. PROCEDURE enablerawMode;
  70. VAR
  71. TCSAFLUSH : INTEGER;
  72. result : INTEGER;
  73. bresult : BOOLEAN;
  74. BEGIN
  75. TCSAFLUSH := termios.tcsflush ();
  76. libc.atexit(disablerawMode);
  77. bresult := termios.SetFlag(editorConfig.raw,termios.cs8, TRUE);
  78. IF termios.tcsetattr(FIO.StdIn, TCSAFLUSH, editorConfig.raw) = -1 THEN
  79. die("tcsetattr")
  80. END;
  81. IO.UnBufferedMode(0,TRUE);
  82. IO.UnBufferedMode(1,TRUE);
  83. END enablerawMode;
  84. PROCEDURE editorReadKey() : CHAR;
  85. VAR
  86. c : CHAR;
  87. BEGIN
  88. IO.Read(c);
  89. RETURN c
  90. END editorReadKey;
  91. (******************** output ******************)
  92. PROCEDURE editorDrawRows;
  93. VAR
  94. y : CARDINAL;
  95. BEGIN
  96. FOR y := 1 TO 24 DO
  97. IO.Write("~");
  98. IO.Write(CHR(13));
  99. IO.Write(CHR(10));
  100. END;
  101. END editorDrawRows;
  102. PROCEDURE editorRefreshScreen;
  103. VAR
  104. i : CARDINAL;
  105. BEGIN
  106. (* modif *)
  107. (* WriteString(clearScreenStr);
  108. WriteString(cursorHomeStr); *)
  109. FOR i := 0 TO 3 DO
  110. IO.Write(clearScreenStr[i])
  111. END;
  112. FOR i := 0 TO 3 DO
  113. IO.Write(cursorHomeStr[i])
  114. END;
  115. editorDrawRows;
  116. (* WriteString(cursorHomeStr); *)
  117. FOR i := 0 TO 3 DO
  118. IO.Write(cursorHomeStr[i])
  119. END;
  120. END editorRefreshScreen;
  121. PROCEDURE Card2Str ( x : CARDINAL; VAR str : ARRAY OF CHAR);
  122. BEGIN
  123. IF x < 10 THEN
  124. NumberIO.CardToStr(x,1,str);
  125. ELSIF x < 100 THEN
  126. NumberIO.CardToStr(x,2,str);
  127. ELSE
  128. NumberIO.CardToStr(x,3,str);
  129. END;
  130. END Card2Str;
  131. PROCEDURE requestCursorPosition(VAR x,y : CARDINAL);
  132. (* ESC[6n request cursor position (reports as ESC[#;#R) *)
  133. VAR
  134. str : ARRAY [0..15] OF CHAR;
  135. theStructure : SplitV1.Structure;
  136. c : CHAR;
  137. cc : String1;
  138. BEGIN
  139. str := "";
  140. SplitV1.InitStructure(theStructure);
  141. (* sending the request *)
  142. WriteString(requestCursorPosStr);
  143. (* quering the answer *)
  144. REPEAT
  145. IO.Read(c);
  146. cc[0] := c;
  147. Concat(str,cc,str);
  148. UNTIL c = "R";
  149. (* extracting coodinates from the answer *)
  150. Delete(str,0,2);
  151. Delete(str,Length(str) -1 ,1);
  152. SplitV1.SplitStr(str, ";", theStructure);
  153. NumberIO.StrToCard(theStructure[0].element,x);
  154. NumberIO.StrToCard(theStructure[1].element,y);
  155. END requestCursorPosition;
  156. PROCEDURE cursorpos(x,y : CARDINAL);
  157. VAR
  158. tmpString : ARRAY[0..10] OF CHAR;
  159. tmpString1: ARRAY[0..5] OF CHAR;
  160. tmpString2: String1;
  161. BEGIN
  162. tmpString := "";
  163. Concat(tmpString,cursorposStr, tmpString);
  164. tmpString1 := "";
  165. Card2Str(y,tmpString1);
  166. Concat(tmpString,tmpString1, tmpString);
  167. tmpString2[0] := ";";
  168. Concat(tmpString, tmpString2,tmpString);
  169. tmpString1 := "";
  170. Card2Str(x,tmpString1);
  171. Concat(tmpString,tmpString1, tmpString);
  172. tmpString2[0] := "H";
  173. Concat(tmpString, tmpString2,tmpString);
  174. WriteString(tmpString);
  175. END cursorpos;
  176. PROCEDURE getWindowSize(VAR y : CARDINAL; x: CARDINAL);
  177. BEGIN
  178. cursorpos(999,999);
  179. requestCursorPosition(x,y);
  180. END getWindowSize;
  181. (******************** input ******************)
  182. PROCEDURE editorProcessKeypress;
  183. VAR
  184. c : CHAR;
  185. b : BOOLEAN;
  186. BEGIN
  187. c := editorReadKey();
  188. CASE ORD(c) OF
  189. 17 : HALT;
  190. END
  191. END editorProcessKeypress;
  192. (******************** INIT ******************)
  193. PROCEDURE InitScreenEscapes;
  194. VAR temp : ARRAY[0..10] OF CHAR;
  195. BEGIN
  196. cursorHomeStr := "";
  197. Concat(cursorHomeStr,ASCII.esc,cursorHomeStr);
  198. Concat(cursorHomeStr,"[H",cursorHomeStr);
  199. clearScreenStr := "";
  200. Concat(clearScreenStr,ASCII.esc,clearScreenStr);
  201. Concat(clearScreenStr,"[2J",clearScreenStr);
  202. cursorposStr := "";
  203. Concat(cursorposStr,ASCII.esc,cursorposStr);
  204. Concat(cursorposStr,"[",cursorposStr);
  205. requestCursorPosStr := "";
  206. Concat(requestCursorPosStr,ASCII.esc,requestCursorPosStr);
  207. Concat(requestCursorPosStr,"[6n",requestCursorPosStr);
  208. END InitScreenEscapes;
  209. BEGIN
  210. InitScreenEscapes;
  211. (* termios state saved *)
  212. editorConfig.theTermios := termios.InitTermios();
  213. (* a copy of it *)
  214. editorConfig.raw := termios.InitTermios();
  215. IF termios.tcgetattr(FIO.StdIn, editorConfig.theTermios) = -1 THEN
  216. die("tcgetattr")
  217. END;
  218. IF termios.tcgetattr(FIO.StdIn, editorConfig.raw) = -1 THEN
  219. die("tcgetattr")
  220. END;
  221. (* end termios *)
  222. enablerawMode;
  223. LOOP
  224. editorRefreshScreen;
  225. editorProcessKeypress;
  226. editorRefreshScreen;
  227. END;
  228. (* cleaning ...*)
  229. adresse := termios.KillTermios(editorConfig.raw);
  230. END editor.