editorC.mod 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. MODULE editorC;
  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 (VAR ptr : abufTypePtr; sourcePtr : SYSTEM.ADDRESS; len : CARDINAL );
  97. VAR
  98. llen : CARDINAL;
  99. BEGIN
  100. (*
  101. REALLOCATE - attempts to reallocate storage. The address,
  102. a, should either be NIL in which case ALLOCATE
  103. is called, or alternatively it should have already
  104. been initialized by ALLOCATE. The allocated storage
  105. is resized accordingly.
  106. *)
  107. (* PROCEDURE REALLOCATE (VAR a: ADDRESS; Size: CARDINAL) ; *)
  108. IF ptr <> NIL THEN
  109. IF ptr^.b = NIL THEN
  110. Storage.ALLOCATE(ptr^.b,len);
  111. ELSE
  112. Storage.REALLOCATE( ptr^.b,ptr^.len + len);
  113. END;
  114. MemUtils.MemCopy(SYSTEM.ADR(str),len, SYSTEM.ADDADR(ptr^.b,ptr^.len));
  115. ptr^.len := ptr^.len + llen;
  116. END;
  117. END abAppend;
  118. PROCEDURE abFree (ptr : abufTypePtr);
  119. BEGIN
  120. (* PROCEDURE DEALLOCATE (VAR a: ADDRESS ; Size: CARDINAL) ; *)
  121. Storage.DEALLOCATE(ptr^.b, ptr^.len);
  122. ptr^.len := 0;
  123. END abFree;
  124. (******************** output ******************)
  125. PROCEDURE editorDrawRows;
  126. VAR
  127. y : CARDINAL;
  128. str : ARRAY [0..15] OF CHAR;
  129. BEGIN
  130. str[0] := "~";
  131. str[1] := CHR(13);
  132. str[2] := CHR(10);
  133. str[3] := CHR(0);
  134. FOR y := 1 TO editorConfig.screenrows -1 DO
  135. (* IO.Write("~");
  136. IO.Write(CHR(13));
  137. IO.Write(CHR(10)); *)
  138. libc.write(FIO.StdOut,SYSTEM.ADR(str),3);
  139. END;
  140. IO.Write("~");
  141. END editorDrawRows;
  142. PROCEDURE editorRefreshScreen;
  143. BEGIN
  144. (* modif using libc write procedure *)
  145. libc.write(FIO.StdOut,SYSTEM.ADR(clearScreenStr),3);
  146. libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr),3);
  147. editorDrawRows;
  148. libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr),3);
  149. (* WriteString(clearScreenStr);
  150. WriteString(cursorHomeStr); *)
  151. (* FOR i := 0 TO 3 DO
  152. IO.Write(clearScreenStr[i])
  153. END; *)
  154. (* FOR i := 0 TO 3 DO
  155. IO.Write(cursorHomeStr[i])
  156. END; *)
  157. (* editorDrawRows; *)
  158. (* WriteString(cursorHomeStr); *)
  159. (* FOR i := 0 TO 3 DO
  160. IO.Write(cursorHomeStr[i])
  161. END; *)
  162. END editorRefreshScreen;
  163. PROCEDURE requestCursorPosition(VAR x,y : CARDINAL);
  164. VAR
  165. c : CHAR;
  166. BEGIN
  167. str := "";
  168. SplitV1.InitStructure(theStructure);
  169. Strings.Concat(str,ASCII.esc,str);
  170. Strings.Concat(str,"[6n", str);
  171. (* sending request *)
  172. (* FOR i := 0 TO 3 DO
  173. IO.Write(str[i])
  174. END; *)
  175. libc.write(FIO.StdOut,SYSTEM.ADR(str),4);
  176. (* getting answer *)
  177. str := "";
  178. REPEAT
  179. IO.Read(c);
  180. cc[0] := c;
  181. Strings.Concat(str,cc,str);
  182. UNTIL c = "R";
  183. (* displaying the retour , changing the escape to ? *)
  184. (* str[0] := "?"; *)
  185. (* FOR i := 0 TO Strings.Length(str) DO
  186. IO.Write(str[i])
  187. END; *)
  188. (* libc.write(FIO.StdOut,SYSTEM.ADR(str),Length(str)); *)
  189. (* extracting the coordinates *)
  190. Strings.Delete(str,0,2);
  191. Strings.Delete(str,Strings.Length(str) -1 ,1);
  192. SplitV1.SplitStr(str, ";", theStructure);
  193. NumberIO.StrToCard(theStructure[0].element,x);
  194. NumberIO.StrToCard(theStructure[1].element,y);
  195. (* NumberIO.WriteCard(x, 5);
  196. NumberIO.WriteCard(y, 5); *)
  197. END requestCursorPosition;
  198. PROCEDURE cursorpos(x,y : CARDINAL);
  199. BEGIN
  200. cursorposStr := "";
  201. Strings.Concat(cursorposStr, ASCII.esc,cursorposStr);
  202. Strings.Concat(cursorposStr, "[",cursorposStr);
  203. tmpString := "";
  204. Strings.Concat(tmpString,cursorposStr, tmpString);
  205. tmpString1 := "";
  206. Card2Str(y,tmpString1);
  207. Strings.Concat(tmpString,tmpString1, tmpString);
  208. tmpString2[0] := ";";
  209. Strings.Concat(tmpString, tmpString2,tmpString);
  210. tmpString1 := "";
  211. Card2Str(x,tmpString1);
  212. Strings.Concat(tmpString,tmpString1, tmpString);
  213. tmpString2[0] := "H";
  214. Strings.Concat(tmpString, tmpString2,tmpString);
  215. (* FOR i := 0 TO Strings.Length(tmpString) DO
  216. IO.Write(tmpString[i])
  217. END; *)
  218. libc.write(FIO.StdOut,SYSTEM.ADR(tmpString),Strings.Length(tmpString));
  219. END cursorpos;
  220. PROCEDURE getWindowSize(VAR y : CARDINAL; VAR x: CARDINAL);
  221. BEGIN
  222. cursorpos(999,999);
  223. requestCursorPosition(x,y);
  224. END getWindowSize;
  225. (******************** input ******************)
  226. PROCEDURE editorProcessKeypress;
  227. VAR
  228. c : CHAR;
  229. b : BOOLEAN;
  230. BEGIN
  231. c := editorReadKey();
  232. CASE ORD(c) OF
  233. 17 : HALT;
  234. END
  235. END editorProcessKeypress;
  236. (******************** INIT ******************)
  237. PROCEDURE InitScreenEscapes;
  238. VAR temp : ARRAY[0..10] OF CHAR;
  239. BEGIN
  240. cursorHomeStr := "";
  241. Strings.Concat(cursorHomeStr,ASCII.esc,cursorHomeStr);
  242. Strings.Concat(cursorHomeStr,"[H",cursorHomeStr);
  243. clearScreenStr := "";
  244. Strings.Concat(clearScreenStr,ASCII.esc,clearScreenStr);
  245. Strings.Concat(clearScreenStr,"[2J",clearScreenStr);
  246. cursorposStr := "";
  247. Strings.Concat(cursorposStr,ASCII.esc,cursorposStr);
  248. Strings.Concat(cursorposStr,"[",cursorposStr);
  249. requestCursorPosStr := "";
  250. Strings.Concat(requestCursorPosStr,ASCII.esc,requestCursorPosStr);
  251. Strings.Concat(requestCursorPosStr,"[6n",requestCursorPosStr);
  252. END InitScreenEscapes;
  253. PROCEDURE InitEditor;
  254. BEGIN
  255. TCSAFLUSH := termios.tcsflush ();
  256. InitScreenEscapes;
  257. getWindowSize(editorConfig.screenrows, editorConfig.screencols);
  258. abufInit.len := 0;
  259. abufInit.b := NIL;
  260. END InitEditor;
  261. BEGIN
  262. enablerawMode;
  263. InitEditor;
  264. LOOP
  265. editorRefreshScreen;
  266. editorProcessKeypress;
  267. editorRefreshScreen;
  268. END;
  269. (* Delay.Delay(2000); *)
  270. IF disablerawMode() = -1 THEN
  271. HALT
  272. END;
  273. NumberIO.WriteCard(editorConfig.screencols, 5);
  274. NumberIO.WriteCard(editorConfig.screenrows, 5);
  275. END editorC.