editor.mod 3.7 KB

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