editor.mod 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. MODULE editor1;
  2. (* based on the kilo editor building course*)
  3. (* Step 28 *)
  4. (******************** INCLUDES ******************)
  5. IMPORT IO, Strings, ASCII, NumberIO, termios, FIO, Delay, SplitV1, STextIO;
  6. IMPORT libc, SYSTEM, Storage, MemUtils;
  7. (******************** DATA ******************)
  8. TYPE
  9. abufType = RECORD
  10. b : SYSTEM.ADDRESS;
  11. len : CARDINAL;
  12. END;
  13. abufTypePtr = POINTER TO abufType;
  14. VAR
  15. editorConfig : RECORD
  16. screenrows : CARDINAL;
  17. screencols : CARDINAL;
  18. theTermios : termios.TERMIOS;
  19. END;
  20. TCSAFLUSH : INTEGER;
  21. theStructure : SplitV1.Structure;
  22. cursorposStr : ARRAY [0..15] OF CHAR;
  23. clearScreenStr : ARRAY[0..6] OF CHAR;
  24. cursorHomeStr : ARRAY[0..2] OF CHAR;
  25. requestCursorPosStr : ARRAY[0..15] OF CHAR;
  26. resultStr : ARRAY [0..15] OF CHAR;
  27. tmpString : ARRAY[0..15] OF CHAR;
  28. tmpString1 : ARRAY[0..15] OF CHAR;
  29. tmpString2 : Strings.String1;
  30. cc : Strings.String1;
  31. i : CARDINAL;
  32. str : ARRAY [0..15] OF CHAR;
  33. abuf : abufType;
  34. abufInit : abufType;
  35. (******************** Utilities *****************)
  36. PROCEDURE Card2Str ( x : CARDINAL; VAR str : ARRAY OF CHAR);
  37. BEGIN
  38. IF x < 10 THEN
  39. NumberIO.CardToStr(x,1,str);
  40. ELSIF x < 100 THEN
  41. NumberIO.CardToStr(x,2,str);
  42. ELSE
  43. NumberIO.CardToStr(x,3,str);
  44. END;
  45. END Card2Str;
  46. (******************** TERMINAL ******************)
  47. PROCEDURE CtrlKey(c: CHAR) : CARDINAL;
  48. (* return a value < ORD(" ") for the control keys *)
  49. VAR
  50. n : BITSET;
  51. BEGIN
  52. n := BITSET(ORD(c));
  53. n := n * BITSET(1FH);
  54. RETURN CARDINAL(n)
  55. END CtrlKey;
  56. PROCEDURE die (s : ARRAY OF CHAR);
  57. BEGIN
  58. libc.perror(s);
  59. FOR i := 0 TO Strings.Length(s) DO
  60. IO.Write(s[i])
  61. END;
  62. HALT
  63. END die;
  64. PROCEDURE disablerawMode() : INTEGER;
  65. VAR
  66. result : INTEGER;
  67. BEGIN
  68. IO.BufferedMode(0,TRUE);
  69. IO.BufferedMode(1,TRUE);
  70. result := termios.tcsetattr(FIO.StdIn, TCSAFLUSH, editorConfig.theTermios);
  71. IF result = -1 THEN
  72. die("tcsetattr")
  73. ELSE
  74. RETURN result
  75. END;
  76. END disablerawMode;
  77. PROCEDURE enablerawMode;
  78. BEGIN
  79. libc.atexit(disablerawMode);
  80. editorConfig.theTermios := termios.InitTermios();
  81. (* raw := termios.InitTermios(); *)
  82. IF termios.tcgetattr(FIO.StdIn, editorConfig.theTermios) = -1 THEN
  83. die("tcgetattr")
  84. END;
  85. IO.UnBufferedMode(0,TRUE);
  86. IO.UnBufferedMode(1,TRUE);
  87. END enablerawMode;
  88. PROCEDURE editorReadKey() : CHAR;
  89. VAR
  90. c : CHAR;
  91. BEGIN
  92. IO.Read(c);
  93. RETURN c
  94. END editorReadKey;
  95. (******************** Buffer ******************)
  96. PROCEDURE abAppend (ptr : abufTypePtr; str: ARRAY OF CHAR; len : CARDINAL);
  97. BEGIN
  98. (*
  99. REALLOCATE - attempts to reallocate storage. The address,
  100. a, should either be NIL in which case ALLOCATE
  101. is called, or alternatively it should have already
  102. been initialized by ALLOCATE. The allocated storage
  103. is resized accordingly.
  104. *)
  105. (* PROCEDURE REALLOCATE (VAR a: ADDRESS; Size: CARDINAL) ; *)
  106. Storage.REALLOCATE( ptr^.b,ptr^.len + len);
  107. (* PROCEDURE MemCopy (from: ADDRESS; length: CARDINAL; to: ADDRESS) ; *)
  108. IF ptr^.b <> NIL THEN
  109. MemUtils.MemCopy(SYSTEM.ADR(str),len, ptr^.b);
  110. ptr^.len := ptr^.len + len;
  111. END;
  112. END abAppend;
  113. PROCEDURE abFree (ptr : abufTypePtr);
  114. BEGIN
  115. (* PROCEDURE DEALLOCATE (VAR a: ADDRESS ; Size: CARDINAL) ; *)
  116. Storage.DEALLOCATE(ptr^.b, ptr^.len);
  117. ptr^.len := 0;
  118. END abFree;
  119. (******************** output ******************)
  120. PROCEDURE editorDrawRows;
  121. VAR
  122. y : CARDINAL;
  123. str : ARRAY [0..15] OF CHAR;
  124. BEGIN
  125. str[0] := "~";
  126. str[1] := CHR(13);
  127. str[2] := CHR(10);
  128. str[3] := CHR(0);
  129. FOR y := 1 TO editorConfig.screenrows -1 DO
  130. (* IO.Write("~");
  131. IO.Write(CHR(13));
  132. IO.Write(CHR(10)); *)
  133. libc.write(FIO.StdOut,SYSTEM.ADR(str),3);
  134. END;
  135. IO.Write("~");
  136. END editorDrawRows;
  137. PROCEDURE editorRefreshScreen;
  138. BEGIN
  139. (* modif using libc write procedure *)
  140. libc.write(FIO.StdOut,SYSTEM.ADR(clearScreenStr),3);
  141. libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr),3);
  142. editorDrawRows;
  143. libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr),3);
  144. (* WriteString(clearScreenStr);
  145. WriteString(cursorHomeStr); *)
  146. (* FOR i := 0 TO 3 DO
  147. IO.Write(clearScreenStr[i])
  148. END; *)
  149. (* FOR i := 0 TO 3 DO
  150. IO.Write(cursorHomeStr[i])
  151. END; *)
  152. (* editorDrawRows; *)
  153. (* WriteString(cursorHomeStr); *)
  154. (* FOR i := 0 TO 3 DO
  155. IO.Write(cursorHomeStr[i])
  156. END; *)
  157. END editorRefreshScreen;
  158. PROCEDURE requestCursorPosition(VAR x,y : CARDINAL);
  159. VAR
  160. c : CHAR;
  161. BEGIN
  162. str := "";
  163. SplitV1.InitStructure(theStructure);
  164. Strings.Concat(str,ASCII.esc,str);
  165. Strings.Concat(str,"[6n", str);
  166. (* sending request *)
  167. (* FOR i := 0 TO 3 DO
  168. IO.Write(str[i])
  169. END; *)
  170. libc.write(FIO.StdOut,SYSTEM.ADR(str),4);
  171. (* getting answer *)
  172. str := "";
  173. REPEAT
  174. IO.Read(c);
  175. cc[0] := c;
  176. Strings.Concat(str,cc,str);
  177. UNTIL c = "R";
  178. (* displaying the retour , changing the escape to ? *)
  179. (* str[0] := "?"; *)
  180. (* FOR i := 0 TO Strings.Length(str) DO
  181. IO.Write(str[i])
  182. END; *)
  183. (* libc.write(FIO.StdOut,SYSTEM.ADR(str),Length(str)); *)
  184. (* extracting the coordinates *)
  185. Strings.Delete(str,0,2);
  186. Strings.Delete(str,Strings.Length(str) -1 ,1);
  187. SplitV1.SplitStr(str, ";", theStructure);
  188. NumberIO.StrToCard(theStructure[0].element,x);
  189. NumberIO.StrToCard(theStructure[1].element,y);
  190. (* NumberIO.WriteCard(x, 5);
  191. NumberIO.WriteCard(y, 5); *)
  192. END requestCursorPosition;
  193. PROCEDURE cursorpos(x,y : CARDINAL);
  194. BEGIN
  195. cursorposStr := "";
  196. Strings.Concat(cursorposStr, ASCII.esc,cursorposStr);
  197. Strings.Concat(cursorposStr, "[",cursorposStr);
  198. tmpString := "";
  199. Strings.Concat(tmpString,cursorposStr, tmpString);
  200. tmpString1 := "";
  201. Card2Str(y,tmpString1);
  202. Strings.Concat(tmpString,tmpString1, tmpString);
  203. tmpString2[0] := ";";
  204. Strings.Concat(tmpString, tmpString2,tmpString);
  205. tmpString1 := "";
  206. Card2Str(x,tmpString1);
  207. Strings.Concat(tmpString,tmpString1, tmpString);
  208. tmpString2[0] := "H";
  209. Strings.Concat(tmpString, tmpString2,tmpString);
  210. (* FOR i := 0 TO Strings.Length(tmpString) DO
  211. IO.Write(tmpString[i])
  212. END; *)
  213. libc.write(FIO.StdOut,SYSTEM.ADR(tmpString),Strings.Length(tmpString));
  214. END cursorpos;
  215. PROCEDURE getWindowSize(VAR y : CARDINAL; VAR x: CARDINAL);
  216. BEGIN
  217. cursorpos(999,999);
  218. requestCursorPosition(x,y);
  219. END getWindowSize;
  220. (******************** input ******************)
  221. PROCEDURE editorProcessKeypress;
  222. VAR
  223. c : CHAR;
  224. b : BOOLEAN;
  225. BEGIN
  226. c := editorReadKey();
  227. CASE ORD(c) OF
  228. 17 : HALT;
  229. END
  230. END editorProcessKeypress;
  231. (******************** INIT ******************)
  232. PROCEDURE InitScreenEscapes;
  233. VAR temp : ARRAY[0..10] OF CHAR;
  234. BEGIN
  235. cursorHomeStr := "";
  236. Strings.Concat(cursorHomeStr,ASCII.esc,cursorHomeStr);
  237. Strings.Concat(cursorHomeStr,"[H",cursorHomeStr);
  238. clearScreenStr := "";
  239. Strings.Concat(clearScreenStr,ASCII.esc,clearScreenStr);
  240. Strings.Concat(clearScreenStr,"[2J",clearScreenStr);
  241. cursorposStr := "";
  242. Strings.Concat(cursorposStr,ASCII.esc,cursorposStr);
  243. Strings.Concat(cursorposStr,"[",cursorposStr);
  244. requestCursorPosStr := "";
  245. Strings.Concat(requestCursorPosStr,ASCII.esc,requestCursorPosStr);
  246. Strings.Concat(requestCursorPosStr,"[6n",requestCursorPosStr);
  247. END InitScreenEscapes;
  248. PROCEDURE InitEditor;
  249. BEGIN
  250. TCSAFLUSH := termios.tcsflush ();
  251. InitScreenEscapes;
  252. getWindowSize(editorConfig.screenrows, editorConfig.screencols);
  253. abufInit.len := 0;
  254. abufInit.b := NIL;
  255. END InitEditor;
  256. BEGIN
  257. enablerawMode;
  258. InitEditor;
  259. LOOP
  260. editorRefreshScreen;
  261. editorProcessKeypress;
  262. editorRefreshScreen;
  263. END;
  264. (* Delay.Delay(2000); *)
  265. IF disablerawMode() = -1 THEN
  266. HALT
  267. END;
  268. NumberIO.WriteCard(editorConfig.screencols, 5);
  269. NumberIO.WriteCard(editorConfig.screenrows, 5);
  270. END editor1.