editor.mod 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. MODULE editor;
  2. (* based on the kilo editor building course*)
  3. (* Step 26 *)
  4. (*** IMPORTS ***)
  5. IMPORT IO, termios, FIO, libc, CharClass, NumberIO, ASCII ;
  6. IMPORT STextIO, Strings, SYSTEM;
  7. (*** data ***)
  8. CONST
  9. clearScreenStrLen = 4;
  10. cursorHomeStrLen = 3;
  11. tildeStrLen = 3;
  12. VAR
  13. editorConfig : RECORD
  14. theTermios : termios.TERMIOS;
  15. END;
  16. c : CHAR;
  17. TCSAFLUSH : INTEGER;
  18. i : CARDINAL;
  19. (* escape sequences *)
  20. clearScreenStr : ARRAY[0..3] OF CHAR;
  21. cursorHomeStr : ARRAY[0..2] OF CHAR;
  22. tildeStr : ARRAY[0..2] OF CHAR;
  23. (* escape sequences length *)
  24. (*** Terminal ***)
  25. PROCEDURE CtrlKey(c: CHAR) : CARDINAL;
  26. VAR
  27. n : BITSET;
  28. BEGIN
  29. n := BITSET(ORD(c));
  30. n := n * BITSET(1FH);
  31. RETURN CARDINAL(n)
  32. END CtrlKey;
  33. PROCEDURE die (s : ARRAY OF CHAR);
  34. BEGIN
  35. libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr), cursorHomeStrLen);
  36. libc.write(FIO.StdOut,SYSTEM.ADR(clearScreenStr), clearScreenStrLen);
  37. libc.perror(s);
  38. FOR i := 0 TO Strings.Length(s) DO
  39. IO.Write(s[i])
  40. END;
  41. HALT
  42. END die;
  43. PROCEDURE disablerawMode() : INTEGER;
  44. VAR
  45. result : INTEGER;
  46. BEGIN
  47. IO.BufferedMode(0,TRUE);
  48. IO.BufferedMode(1,TRUE);
  49. result := termios.tcsetattr(FIO.StdIn, TCSAFLUSH, editorConfig.theTermios);
  50. IF result = -1 THEN
  51. editorConfig.theTermios := termios.KillTermios(editorConfig.theTermios);
  52. die("tcsetattr")
  53. ELSE
  54. RETURN result
  55. END;
  56. END disablerawMode;
  57. PROCEDURE enablerawMode;
  58. BEGIN
  59. libc.atexit(disablerawMode);
  60. editorConfig.theTermios := termios.InitTermios();
  61. IF termios.tcgetattr(FIO.StdIn, editorConfig.theTermios) = -1 THEN
  62. die("tcgetattr")
  63. END;
  64. IO.UnBufferedMode(0,TRUE);
  65. IO.UnBufferedMode(1,TRUE);
  66. END enablerawMode;
  67. PROCEDURE editorReadKey() : CHAR;
  68. VAR
  69. c : CHAR;
  70. BEGIN
  71. IO.Read(c);
  72. RETURN c
  73. END editorReadKey;
  74. PROCEDURE editorProcessKeypress;
  75. VAR
  76. c : CHAR;
  77. BEGIN
  78. c := editorReadKey();
  79. CASE ORD(c) OF
  80. 17 : libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr), cursorHomeStrLen);
  81. libc.write(FIO.StdOut,SYSTEM.ADR(clearScreenStr), clearScreenStrLen);
  82. HALT;
  83. END
  84. END editorProcessKeypress;
  85. (*** Output ***)
  86. PROCEDURE editorDrawRows;
  87. VAR
  88. y : CARDINAL;
  89. BEGIN
  90. FOR y := 1 TO 24 DO
  91. libc.write(FIO.StdOut,SYSTEM.ADR(tildeStr), tildeStrLen);
  92. END;
  93. END editorDrawRows;
  94. PROCEDURE editorRefreshScreen;
  95. BEGIN
  96. libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr), cursorHomeStrLen);
  97. libc.write(FIO.StdOut,SYSTEM.ADR(clearScreenStr), clearScreenStrLen);
  98. editorDrawRows;
  99. libc.write(FIO.StdOut,SYSTEM.ADR(cursorHomeStr), cursorHomeStrLen);
  100. END editorRefreshScreen;
  101. (*** Input ***)
  102. (*** Init ***)
  103. PROCEDURE InitScreenEscapes;
  104. VAR temp : ARRAY[0..10] OF CHAR;
  105. BEGIN
  106. cursorHomeStr := "";
  107. Strings.Concat(cursorHomeStr,ASCII.esc,cursorHomeStr);
  108. Strings.Concat(cursorHomeStr,"[H",cursorHomeStr);
  109. clearScreenStr := "";
  110. Strings.Concat(clearScreenStr,ASCII.esc,clearScreenStr);
  111. Strings.Concat(clearScreenStr,"[2J",clearScreenStr);
  112. tildeStr[0] := "~";
  113. tildeStr[1] := CHR(13);
  114. tildeStr[2] := CHR(10);
  115. END InitScreenEscapes;
  116. BEGIN
  117. InitScreenEscapes;
  118. TCSAFLUSH := termios.tcsflush ();
  119. enablerawMode;
  120. editorRefreshScreen;
  121. LOOP
  122. editorProcessKeypress;
  123. editorRefreshScreen;
  124. END;
  125. END editor.