editor.mod 9.7 KB

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