diff --git a/kilo b/kilo index dace6e4..a2e0ad4 100755 --- a/kilo +++ b/kilo @@ -3,7 +3,14 @@ namespace Kilo; -require_once __DIR__ . '/src/constants.php'; +// ----------------------------------------------------------------------------- +// ! App Constants +// ----------------------------------------------------------------------------- +define('KILO_VERSION', '0.0.1'); +define('KILO_TAB_STOP', 4); +define('KILO_QUIT_TIMES', 3); + +require_once __DIR__ . '/src/C.php'; require_once __DIR__ . '/src/functions.php'; require_once __DIR__ . '/src/Editor.php'; diff --git a/src/C.php b/src/C.php new file mode 100644 index 0000000..378cd06 --- /dev/null +++ b/src/C.php @@ -0,0 +1,146 @@ +. */ + + // ------------------------------------------------------------------------ + // ! IOCTL constants + // ------------------------------------------------------------------------ + public const TIOCGWINSZ = 0x5413; +} \ No newline at end of file diff --git a/src/constants.php b/src/constants.php deleted file mode 100644 index 97d576b..0000000 --- a/src/constants.php +++ /dev/null @@ -1,148 +0,0 @@ -. */ - -// ----------------------------------------------------------------------------- -// ! IOCTL constants -// ----------------------------------------------------------------------------- -define('TIOCGWINSZ', 0x5413); \ No newline at end of file diff --git a/src/functions.php b/src/functions.php index dcd9faa..8050c1d 100644 --- a/src/functions.php +++ b/src/functions.php @@ -4,8 +4,8 @@ namespace Kilo; use FFI; -$ffi = FFI::load(__DIR__ . '/ffi.h'); -$original_termios = $ffi->new('struct termios'); +/** @var FFI\CData $original_termios */ +$original_termios = get_ffi()->new('struct termios'); // ---------------------------------------------------------------------------- // ! Raw mode / Terminal size @@ -13,13 +13,15 @@ $original_termios = $ffi->new('struct termios'); function enable_raw_mode(): void { - global $ffi; global $original_termios; + // Make sure to restore normal mode on exit/die/crash register_shutdown_function('Kilo\disable_raw_mode'); + $ffi = get_ffi(); + // Populate the original terminal settings - $res = $ffi->tcgetattr(STDIN_FILENO, FFI::addr($original_termios)); + $res = $ffi->tcgetattr(C::STDIN_FILENO, FFI::addr($original_termios)); if ($res === -1) { die('tcgetattr'); @@ -27,15 +29,15 @@ function enable_raw_mode(): void // So, the only thing that seems to really matter here is that c_oflag is 0... $termios = clone $original_termios; - $termios->c_iflag = 0; //$termios->c_iflag & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - $termios->c_oflag = 0; // $termios->c_oflag && ~(OPOST); - $termios->c_cflag |= (CS8); - $termios->c_lflag = $termios->c_lflag & ~(_ECHO | ICANON | IEXTEN | ISIG); - $termios->c_cc[VMIN] = 0; - $termios->c_cc[VTIME] = 1; + $termios->c_iflag = 0; //$termios->c_iflag & ~(C::BRKINT | C::ICRNL | C::INPCK | C::ISTRIP | C::IXON); + $termios->c_oflag = 0; // $termios->c_oflag && ~(C::OPOST); + $termios->c_cflag |= (C::CS8); + $termios->c_lflag = $termios->c_lflag & ~( C::ECHO | C::ICANON | C::IEXTEN | C::ISIG); + $termios->c_cc[C::VMIN] = 0; + $termios->c_cc[C::VTIME] = 1; // Turn on raw mode - $res = $ffi->tcsetattr(STDIN_FILENO, TCSAFLUSH, FFI::addr($termios)); + $res = $ffi->tcsetattr(C::STDIN_FILENO, C::TCSAFLUSH, FFI::addr($termios)); if ($res === -1) { die('tcsetattr'); @@ -44,10 +46,10 @@ function enable_raw_mode(): void function disable_raw_mode(): void { - global $ffi; global $original_termios; - $res = $ffi->tcsetattr(STDIN_FILENO, TCSAFLUSH, FFI::addr($original_termios)); + $ffi = get_ffi(); + $res = $ffi->tcsetattr(C::STDIN_FILENO, C::TCSAFLUSH, FFI::addr($original_termios)); echo "\n"; @@ -82,10 +84,10 @@ function get_cursor_position() function get_window_size() { - global $ffi; + $ffi = get_ffi(); $ws = $ffi->new('struct winsize'); - $res = $ffi->ioctl(STDOUT_FILENO, TIOCGWINSZ, FFI::addr($ws)); + $res = $ffi->ioctl(C::STDOUT_FILENO, C::TIOCGWINSZ, FFI::addr($ws)); if ($res === -1 || $ws->ws_col === 0) { @@ -95,8 +97,6 @@ function get_window_size() return [$ws->ws_row, $ws->ws_col]; } - - // ---------------------------------------------------------------------------- // ! C function/macro equivalents // ---------------------------------------------------------------------------- @@ -115,11 +115,18 @@ function ctrl_key(string $char): int return -1; } - // b1,100,001 (a) & b0,011,111 = b0,000,001 - // b1,100,010 (b) & b0,011,111 = b0,000,010 + // b1,100,001 (a) & b0,011,111 (0x1f) = b0,000,001 (SOH) + // b1,100,010 (b) & b0,011,111 (0x1f) = b0,000,010 (STX) + // ...and so on return ord($char) & 0x1f; } +/** + * Does the one-character string contain an ascii ordinal value? + * + * @param string $single_char + * @return bool + */ function is_ascii(string $single_char): bool { if (strlen($single_char) > 1) @@ -130,12 +137,24 @@ function is_ascii(string $single_char): bool return ord($single_char) < 0x80; } +/** + * Does the one-character string contain an ascii control character? + * + * @param string $char + * @return bool + */ function is_cntrl(string $char): bool { $c = ord($char); return is_ascii($char) && ( $c < 0x20 || $c === 0x7f ); } +/** + * Does the one-character string contain an ascii number? + * + * @param string $char + * @return bool + */ function is_digit(string $char): bool { $c = ord($char); @@ -146,6 +165,29 @@ function is_digit(string $char): bool // ! Helper functions // ---------------------------------------------------------------------------- +/** + * A 'singleton' function to replace a global variable + * + * @return FFI + */ +function get_ffi(): FFI +{ + static $ffi; + + if ($ffi === NULL) + { + $ffi = FFI::load(__DIR__ . '/ffi.h'); + } + + return $ffi; +} + +/** + * Pull input from the stdin stream. + * + * @param int $len + * @return string + */ function read_stdin(int $len = 128): string { $handle = fopen('php://stdin', 'rb'); @@ -155,6 +197,13 @@ function read_stdin(int $len = 128): string return $input; } +/** + * Write to the stdout stream + * + * @param string $str + * @param int|NULL $len + * @return int + */ function write_stdout(string $str, int $len = NULL): int { $handle = fopen('php://stdout', 'ab'); @@ -177,3 +226,20 @@ function read_stdout(int $len = 128): string return $input; } + +/** + * Replaces a slice of an array with the same value + * + * @param array $array The array to update + * @param int $offset The index of the first location to update + * @param int $length The number of indices to update + * @param mixed $value The value to replace in the range + */ +function array_replace_range(array &$array, int $offset, int $length, $value):void +{ + $end = $offset + $length; + for ($i = $offset; $i < $end; $i++) + { + $array[$i] = $value; + } +}