}\r
\r
\r
+static Handle<Value> WriteTTY(const Arguments& args) {\r
+ HandleScope scope;\r
+ int fd, len;\r
+ DWORD written;\r
+ HANDLE handle;\r
+\r
+ if (!args[0]->IsNumber())\r
+ THROW_BAD_ARGS\r
+\r
+ fd = args[0]->IntegerValue();\r
+ handle = (HANDLE)_get_osfhandle(fd);\r
+\r
+ Handle<String> data = args[1]->ToString();\r
+ String::Value buf(data);\r
+ len = data->Length();\r
+\r
+ if (!WriteConsoleW(handle, reinterpret_cast<void*>(*buf), len, &written, NULL))\r
+ return ThrowException(ErrnoException(GetLastError(), "WriteConsole"));\r
+\r
+ return scope.Close(Integer::New(written));\r
+}\r
+\r
+\r
+static Handle<Value> CloseTTY(const Arguments& args) {\r
+ HandleScope scope;\r
+\r
+ int fd = args[0]->IntegerValue();\r
+ if (close(fd) < 0)\r
+ return ThrowException(ErrnoException(errno, "close"));\r
+\r
+ return Undefined();\r
+}\r
+\r
+\r
// process.binding('stdio').getWindowSize(fd);\r
// returns [row, col]\r
static Handle<Value> GetWindowSize (const Arguments& args) {\r
}\r
\r
\r
+/* moveCursor(fd, dx, dy) */\r
+/* cursorTo(fd, x, y) */\r
+template<bool relative>\r
+static Handle<Value> SetCursor(const Arguments& args) {\r
+ HandleScope scope;\r
+ int fd;\r
+ COORD size, pos;\r
+ HANDLE handle;\r
+ CONSOLE_SCREEN_BUFFER_INFO info;\r
+\r
+ if (!args[0]->IsNumber())\r
+ THROW_BAD_ARGS\r
+ fd = args[0]->IntegerValue();\r
+ handle = (HANDLE)_get_osfhandle(fd);\r
+\r
+ if (!GetConsoleScreenBufferInfo(handle, &info))\r
+ return ThrowException(ErrnoException(GetLastError(), "GetConsoleScreenBufferInfo"));\r
+\r
+ pos = info.dwCursorPosition;\r
+ if (relative) {\r
+ if (args[1]->IsNumber())\r
+ pos.X += static_cast<short>(args[1]->Int32Value());\r
+ if (args[2]->IsNumber())\r
+ pos.Y += static_cast<short>(args[2]->Int32Value());\r
+ } else {\r
+ if (args[1]->IsNumber())\r
+ pos.X = static_cast<short>(args[1]->Int32Value());\r
+ if (args[2]->IsNumber())\r
+ pos.Y = static_cast<short>(args[2]->Int32Value());\r
+ }\r
+\r
+ size = info.dwSize;\r
+ if (pos.X >= size.X) pos.X = size.X - 1;\r
+ if (pos.X < 0) pos.X = 0;\r
+ if (pos.Y >= size.Y) pos.Y = size.Y - 1;\r
+ if (pos.Y < 0) pos.Y = 0;\r
+\r
+ if (!SetConsoleCursorPosition(handle, pos))\r
+ return ThrowException(ErrnoException(GetLastError(), "SetConsoleCursorPosition"));\r
+\r
+ return Undefined();\r
+}\r
+\r
+\r
+/*\r
+ * ClearLine(fd, direction)\r
+ * direction:\r
+ * -1: from cursor leftward\r
+ * 0: entire line\r
+ * 1: from cursor to right\r
+ */\r
+static Handle<Value> ClearLine(const Arguments& args) {\r
+ HandleScope scope;\r
+ int fd, dir;\r
+ short x1, x2, count;\r
+ WCHAR *buf;\r
+ COORD pos;\r
+ HANDLE handle;\r
+ CONSOLE_SCREEN_BUFFER_INFO info;\r
+ DWORD res, written, mode, oldmode;\r
+\r
+ if (!args[0]->IsNumber())\r
+ THROW_BAD_ARGS\r
+ fd = args[0]->IntegerValue();\r
+ handle = (HANDLE)_get_osfhandle(fd);\r
+\r
+ if (args[1]->IsNumber())\r
+ dir = args[1]->IntegerValue();\r
+\r
+ if (!GetConsoleScreenBufferInfo(handle, &info))\r
+ return ThrowException(ErrnoException(GetLastError(), "GetConsoleScreenBufferInfo"));\r
+\r
+ x1 = dir <= 0 ? 0 : info.dwCursorPosition.X;\r
+ x2 = dir >= 0 ? info.dwSize.X - 1: info.dwCursorPosition.X;\r
+ count = x2 - x1 + 1;\r
+\r
+ if (x1 != info.dwCursorPosition.X) {\r
+ pos.Y = info.dwCursorPosition.Y;\r
+ pos.X = x1;\r
+ if (!SetConsoleCursorPosition(handle, pos))\r
+ return ThrowException(ErrnoException(GetLastError(), "SetConsoleCursorPosition"));\r
+ }\r
+\r
+ if (!GetConsoleMode(handle, &oldmode))\r
+ return ThrowException(ErrnoException(GetLastError(), "GetConsoleMode"));\r
+\r
+ // Disable wrapping at eol because otherwise windows scrolls the console\r
+ // when clearing the last line of the console\r
+ mode = oldmode & ~ENABLE_WRAP_AT_EOL_OUTPUT;\r
+ if (!SetConsoleMode(handle, mode))\r
+ return ThrowException(ErrnoException(GetLastError(), "SetConsoleMode"));\r
+\r
+ buf = new WCHAR[count];\r
+ for (short i = 0; i < count; i++) {\r
+ buf[i] = L' ';\r
+ }\r
+\r
+ res = WriteConsoleW(handle, buf, count, &written, NULL);\r
+\r
+ delete[] buf;\r
+\r
+ if (!res)\r
+ return ThrowException(ErrnoException(GetLastError(), "WriteConsole"));\r
+\r
+ if (!SetConsoleCursorPosition(handle, info.dwCursorPosition))\r
+ return ThrowException(ErrnoException(GetLastError(), "SetConsoleCursorPosition"));\r
+\r
+ if (!SetConsoleMode(handle, oldmode))\r
+ return ThrowException(ErrnoException(GetLastError(), "SetConsoleMode"));\r
+\r
+ return Undefined();\r
+}\r
+\r
+\r
/* TTY watcher data */\r
bool tty_watcher_initialized = false;\r
HANDLE tty_handle;\r
NODE_SET_METHOD(target, "isStdinBlocking", IsStdinBlocking);\r
NODE_SET_METHOD(target, "setRawMode", SetRawMode);\r
NODE_SET_METHOD(target, "openStdin", OpenStdin);\r
+ NODE_SET_METHOD(target, "writeTTY", WriteTTY);\r
+ NODE_SET_METHOD(target, "closeTTY", CloseTTY);\r
+ NODE_SET_METHOD(target, "moveCursor", SetCursor<true>);\r
+ NODE_SET_METHOD(target, "cursorTo", SetCursor<false>);\r
+ NODE_SET_METHOD(target, "clearLine", ClearLine);\r
NODE_SET_METHOD(target, "getWindowSize", GetWindowSize);\r
NODE_SET_METHOD(target, "initTTYWatcher", InitTTYWatcher);\r
NODE_SET_METHOD(target, "destroyTTYWatcher", DestroyTTYWatcher);\r