diff --git a/demos/colors/source/colors.d b/demos/colors/source/colors.d index db0665d..94eea2e 100644 --- a/demos/colors/source/colors.d +++ b/demos/colors/source/colors.d @@ -33,7 +33,7 @@ class ColorBoxes bool done; Screen s; - bool flip() + bool flip() @safe { return (rng.uniform!ubyte() & 0x1) != 0; } @@ -50,7 +50,7 @@ class ColorBoxes s = scr; } - void makeBox() + void makeBox() @safe { Coord wsz = s.size(); dchar dc = ' '; @@ -122,7 +122,7 @@ class ColorBoxes s.show(); } - void handleEvent(Event ev) + void handleEvent(Event ev) @safe { switch (ev.type) { @@ -156,7 +156,7 @@ class ColorBoxes } } - void run() + void run() @safe { s.start(); scope (exit) diff --git a/demos/hello/dub.json b/demos/hello/dub.json index 927a1de..68ac802 100644 --- a/demos/hello/dub.json +++ b/demos/hello/dub.json @@ -1,12 +1,12 @@ { - "copyright": "Copyright 2022 Garrett D'Amore", - "description": "Hello World in Dcell", - "name": "hello", - "targetType": "executable", - "targetName": "hello", - "targetPath": "bin", - "mainSourceFile": "source/hello.d", - "dependencies": { - "dcell" : { "path": "../.." } - } + "copyright": "Copyright 2025 Garrett D'Amore", + "description": "Hello World in Dcell", + "name": "hello", + "targetType": "executable", + "targetName": "hello", + "targetPath": "bin", + "mainSourceFile": "source/hello.d", + "dependencies": { + "dcell": { "path": "../.." } + } } diff --git a/demos/mouse/dub.json b/demos/mouse/dub.json index c4b0dac..0a81dd1 100644 --- a/demos/mouse/dub.json +++ b/demos/mouse/dub.json @@ -1,12 +1,12 @@ { - "copyright": "Copyright 2022 Garrett D'Amore", - "description": "Mouse demo in Dcell", - "name": "mouse", - "targetType": "executable", - "targetName": "mouse", - "targetPath": "bin", - "mainSourceFile": "source/mouse.d", - "dependencies": { - "dcell" : { "path": "../../" } - } + "copyright": "Copyright 2025 Garrett D'Amore", + "description": "Mouse demo in Dcell", + "name": "mouse", + "targetType": "executable", + "targetName": "mouse", + "targetPath": "bin", + "mainSourceFile": "source/mouse.d", + "dependencies": { + "dcell": { "path": "../../" } + } } diff --git a/source/dcell/common.d b/source/dcell/common.d index a74c599..d5f39ca 100644 --- a/source/dcell/common.d +++ b/source/dcell/common.d @@ -1,7 +1,7 @@ /** * Common module for dcell, it contains some package wide definitions. * - * Copyright: Copyright 2022 Garrett D'Amore + * Copyright: Copyright 2025 Garrett D'Amore * Authors: Garrett D'Amore * License: * Distributed under the Boost Software License, Version 1.0. diff --git a/source/dcell/cursor.d b/source/dcell/cursor.d index b839d32..7b4bd2c 100644 --- a/source/dcell/cursor.d +++ b/source/dcell/cursor.d @@ -1,7 +1,7 @@ /** * Cursor module for dcell. * - * Copyright: Copyright 2022 Garrett D'Amore + * Copyright: Copyright 2025 Garrett D'Amore * Authors: Garrett D'Amore * License: * Distributed under the Boost Software License, Version 1.0. diff --git a/source/dcell/event.d b/source/dcell/event.d index e28ea8f..13c6ec2 100644 --- a/source/dcell/event.d +++ b/source/dcell/event.d @@ -79,7 +79,7 @@ struct FocusEvent class EventQ { - void put(Event ev) + void put(Event ev) @safe nothrow { events ~= ev; } diff --git a/source/dcell/parser.d b/source/dcell/parser.d index c7eb351..7426cb6 100644 --- a/source/dcell/parser.d +++ b/source/dcell/parser.d @@ -310,7 +310,7 @@ immutable KeyCode[int] winKeys = [ class Parser { - Event[] events() pure + Event[] events() pure @safe @nogc { auto res = evs; evs = null; @@ -318,14 +318,14 @@ class Parser } // Parse the supplied content, returns true if data is fully parsed. - bool parse(string b) + bool parse(string b) @safe { buf ~= b; scan(); return parseState == ParseState.ini; } - bool empty() const pure + bool empty() const pure @safe { return buf.length == 0; } @@ -368,7 +368,7 @@ private: bool pasting; dstring pasteBuf; - void postKey(Key k, dchar dch, Modifiers mod) + void postKey(Key k, dchar dch, Modifiers mod) nothrow @safe { if (pasting) { @@ -383,7 +383,7 @@ private: } } - void scan() + void scan() @trusted { while (!buf.empty) { @@ -674,7 +674,7 @@ private: parseState = ParseState.ini; } - void handleCsi(ubyte mode, string params, string interm) + void handleCsi(ubyte mode, string params, string interm) @safe { parseState = ParseState.ini; @@ -865,7 +865,7 @@ private: } } - void handleMouse(ubyte mode, int p0, int p1, int p2) + void handleMouse(ubyte mode, int p0, int p1, int p2) nothrow @safe { // XTerm mouse events only report at most one button at a time, // which may include a wheel button. Wheel motion events are @@ -954,7 +954,7 @@ private: evs ~= newMouseEvent(x, y, button, mod); } - void handleWinKey(int p0, int p1, int p2, int p3, int p4, int p5) + void handleWinKey(int p0, int p1, int p2, int p3, int p4, int p5) @safe { // win32-input-mode // ^[ [ Vk ; Sc ; Uc ; Kd ; Cs ; Rc _ @@ -1056,7 +1056,7 @@ private: } // calculate the modifiers from the CSI modifier parameter. - Modifiers calcModifier(int n) + Modifiers calcModifier(int n) pure nothrow @safe @nogc { n--; Modifiers m; @@ -1091,7 +1091,7 @@ private: return m; } - Event newFocusEvent(bool focused) + Event newFocusEvent(bool focused) nothrow @safe { Event ev = { @@ -1102,7 +1102,7 @@ private: return ev; } - Event newKeyEvent(Key k, dchar dch = 0, Modifiers mod = Modifiers.none) + Event newKeyEvent(Key k, dchar dch = 0, Modifiers mod = Modifiers.none) nothrow @safe { if (escaped) { @@ -1147,7 +1147,7 @@ private: return ev; } - Event newMouseEvent(int x, int y, Buttons btn, Modifiers mod) + Event newMouseEvent(int x, int y, Buttons btn, Modifiers mod) nothrow @safe { Event ev = { type: EventType.mouse, when: MonoTime.currTime, mouse: { @@ -1162,7 +1162,7 @@ private: // NB: it is possible for x and y to be outside the current coordinates // (happens for click drag for example). Consumer of the event should clip // the coordinates as needed. - Event newMouseEvent(int x, int y, int btn) + Event newMouseEvent(int x, int y, int btn) nothrow @safe { Event ev = { type: EventType.mouse, when: MonoTime.currTime, mouse: { @@ -1207,7 +1207,7 @@ private: return ev; } - Event newPasteEvent(dstring buffer) + Event newPasteEvent(dstring buffer) nothrow @safe { Event ev = { type: EventType.paste, when: MonoTime.currTime(), paste: { @@ -1217,20 +1217,6 @@ private: return ev; } - bool parseSequence(string seq) - { - if (startsWith(buf, seq)) - { - buf = buf[seq.length .. $]; // yank the sequence - return true; - } - if (startsWith(seq, buf)) - { - partial = true; - } - return false; - } - unittest { import core.thread; diff --git a/source/dcell/screen.d b/source/dcell/screen.d index 29e828c..825ee46 100644 --- a/source/dcell/screen.d +++ b/source/dcell/screen.d @@ -28,17 +28,17 @@ interface Screen * Clears the screen. This doesn't take effect until * the show function is called. */ - void clear(); + void clear() @safe; /** * Retrieve the contents for a given address. This is taken from * the backing draw buffer, and won't necessarily reflect what is * displayed to the user until show is called. */ - ref Cell opIndex(size_t x, size_t y); + ref Cell opIndex(size_t x, size_t y) @safe; /** Convenience for indexing */ - final ref Cell opIndex(Coord pos) + final ref Cell opIndex(Coord pos) @safe { return this[pos.x, pos.y]; } @@ -47,16 +47,16 @@ interface Screen * Set the content for for a given location. This won't necessarily * take effect until the show function is called. */ - void opIndexAssign(Cell, size_t x, size_t y); + void opIndexAssign(Cell, size_t x, size_t y) @safe; /** Convenience for indexing. */ - final void opIndexAssign(Cell c, Coord pos) + final void opIndexAssign(Cell c, Coord pos) @safe { this[pos.x, pos.y] = c; } /** Support $ operation in indices. */ - size_t opDollar(size_t dim)() + size_t opDollar(size_t dim)() nothrow @safe { static if (dim == 0) { @@ -71,7 +71,7 @@ interface Screen /** * Show the cursor at its current location. */ - void showCursor(Cursor); + void showCursor(Cursor) @safe; /** * Move the cursor to the given location, and show @@ -81,7 +81,7 @@ interface Screen * pos = position of the cursor * cur = cursor style */ - void showCursor(Coord pos, Cursor cur = Cursor.current); + void showCursor(Coord pos, Cursor cur = Cursor.current) @safe; /** * Obtain the terminal window size. @@ -90,7 +90,7 @@ interface Screen * * Returns: terminal dimensions */ - Coord size(); + Coord size() @safe; /** * Wait for at least one event to be posted, for up to the given time. @@ -101,7 +101,7 @@ interface Screen * * Returns: true if at least one event is available, false otherwise. */ - bool waitForEvent(Duration timeout, ref Duration resched); + bool waitForEvent(Duration timeout, ref Duration resched) @safe; /** * Wait for at least one event to be posted. @@ -113,7 +113,7 @@ interface Screen * * Returns: True if at least one event is available, false otherwise. */ - final bool waitForEvent(Duration timeout = Duration.max) + final bool waitForEvent(Duration timeout = Duration.max) @safe { Duration resched; return waitForEvent(timeout, resched); @@ -133,7 +133,7 @@ interface Screen * Params: * b = true to enable bracketed paste, false for disable */ - void enablePaste(bool b); + void enablePaste(bool b) @safe; /** * Enable mouse mode. This can cause terminals/emulators @@ -143,7 +143,7 @@ interface Screen * Params: * en = mouse events to report (mask) */ - void enableMouse(MouseEnable en); + void enableMouse(MouseEnable en) @safe; /** * Enable typical mouse features. This enables tracking, but @@ -151,7 +151,7 @@ interface Screen * use of copy-paste at the OS level, which many users tend to * find frustrating. */ - final void enableMouse() + final void enableMouse() @safe { enableMouse(MouseEnable.buttons | MouseEnable.motion); } @@ -159,7 +159,7 @@ interface Screen /** * Disable all mouse handling/capture. */ - final void disableMouse() + final void disableMouse() @safe { enableMouse(MouseEnable.disable); } @@ -171,7 +171,7 @@ interface Screen * It can be disabled by setting DCELL_ALTSCREEN=disable in the * environment. */ - void enableAlternateScreen(bool on); + void enableAlternateScreen(bool on) @safe; /** * Set the title of the window. This only works for emulators running @@ -180,7 +180,7 @@ interface Screen * a specific default, but it may also leave it empty - it depends * on the specific terminal implementation. */ - void setTitle(string); + void setTitle(string) @safe; /** * If the terminal supports color, this returns the @@ -188,52 +188,52 @@ interface Screen * * Returns: the number of colors supported (max 256), or 0 if monochrome */ - int colors(); + int colors() nothrow @safe; /** * Show content on the screen, doing so efficiently. */ - void show(); + void show() @safe; /** * Update the screen, writing every cell. This should be done * to repair screen damage, for example. */ - void sync(); + void sync() @safe; /** * Emit a beep or bell. This is done immediately. */ - void beep(); + void beep() @safe; /** * Attempt to resize the terminal. YMMV. */ - void setSize(Coord); + void setSize(Coord) @safe; /** * Fill the entire screen with the given content and style. * Content is not drawn until the show() or sync() functions are called. */ - void fill(string s, Style style); + void fill(string s, Style style) @safe; /** * Fill the entire screen with the given content, but preserve the style. */ - void fill(string s); + void fill(string s) @safe; /** * Applications should call this in response to receiving * a resize event. (This can't be done automatically to * avoid thread safety issues.) */ - void resize(); + void resize() @safe; /** * Start sets up the terminal. This changes terminal * settings to put the input stream into raw mode, etc. */ - void start(); + void start() @safe; /** * Stop is called to stop processing on the screen. The terminal @@ -242,7 +242,7 @@ interface Screen * This should be called when the program is exited, or if suspending * (to run a sub-shell process interactively for example). */ - void stop(); + void stop() @safe; /** * The style property is used when writing content to the screen diff --git a/source/dcell/termio.d b/source/dcell/termio.d index 0f804f3..e468bc7 100644 --- a/source/dcell/termio.d +++ b/source/dcell/termio.d @@ -56,7 +56,7 @@ import std.stdio; class PosixTty : Tty { /// Create a Tty device on a given device path. The usual path is "/dev/tty". - this(string dev) + this(string dev) nothrow @safe { path = dev; } @@ -73,14 +73,14 @@ class PosixTty : Tty * For more advanced use cases, consider implementing the tty interface * directly. */ - this(File f) + this(File f) @safe { enforce(f.isOpen, "file is not open"); file = f; fd = file.fileno(); } - void start() + void start() @safe { if (!file.isOpen) { @@ -91,7 +91,7 @@ class PosixTty : Tty watchResize(fd); } - void stop() + void stop() @safe { if (file.isOpen()) { @@ -100,7 +100,7 @@ class PosixTty : Tty } } - void close() + void close() @safe { if (file.isOpen) { @@ -110,24 +110,24 @@ class PosixTty : Tty } } - void save() + void save() @trusted { if (!isatty(fd)) throw new Exception("not a tty device"); enforce(tcgetattr(fd, &saved) >= 0, "failed to get termio state"); } - void restore() + void restore() @trusted { enforce(tcsetattr(fd, TCSAFLUSH, &saved) >= 0, "failed to set termio state"); } - void flush() + void flush() @safe { file.flush(); } - void raw() + void raw() @trusted { termios tio; enforce(tcgetattr(fd, &tio) >= 0, "failed to get termio state"); @@ -141,7 +141,7 @@ class PosixTty : Tty enforce(tcsetattr(fd, TCSANOW, &tio) >= 0, "failed to set termios"); } - Coord windowSize() + Coord windowSize() @trusted { // If cores.sys.posix.sys.ioctl had more complete and accurate data... // this structure is fairly consistent amongst all POSIX variants @@ -198,7 +198,7 @@ class PosixTty : Tty // On macOS, we have to use a select() based implementation because poll() // does not work reasonably on /dev/tty. (This was very astonishing when first // we discovered it -- POLLNVAL for device files.) - version (UseSelect) string read(Duration dur = Duration.zero) + version (UseSelect) string read(Duration dur = Duration.zero) @trusted { // this has to use the underlying read system call import unistd = core.sys.posix.unistd; @@ -253,7 +253,7 @@ class PosixTty : Tty return result; } - version (UsePoll) string read(Duration dur = Duration.zero) + version (UsePoll) string read(Duration dur = Duration.zero) @trusted { // this has to use the underlying read system call import unistd = core.sys.posix.unistd; @@ -306,18 +306,18 @@ class PosixTty : Tty return result; } - void write(string s) + void write(string s) @safe { file.write(s); } - bool resized() + bool resized() nothrow @safe @nogc { // NB: resized is edge triggered. return wasResized(fd); } - void wakeUp() nothrow + void wakeUp() nothrow @trusted { import unistd = core.sys.posix.unistd; @@ -385,7 +385,7 @@ else version (AIX) else static assert(0, "no version"); -void watchResize(int fd) +void watchResize(int fd) @trusted { import std.process; import core.sys.posix.fcntl; @@ -406,7 +406,7 @@ void watchResize(int fd) } } -void ignoreResize(int fd) +void ignoreResize(int fd) @trusted { if (atomicLoad(sigFd) == fd) { @@ -418,7 +418,7 @@ void ignoreResize(int fd) } } -bool wasResized(int fd) +bool wasResized(int fd) nothrow @trusted @nogc { if (fd == atomicLoad(sigFd) && fd != -1) { diff --git a/source/dcell/tty.d b/source/dcell/tty.d index 331690c..e1cdb85 100644 --- a/source/dcell/tty.d +++ b/source/dcell/tty.d @@ -27,12 +27,12 @@ interface Tty * Save current tty settings. These can be subsequently * restored using restore. */ - void save(); + void save() @trusted; /** * Restore tty settings saved with save(). */ - void restore(); + void restore() @trusted; /** * Make the terminal suitable for raw mode input. @@ -42,43 +42,43 @@ interface Tty * will block until one character is presented. (Same * effect as 'blocking(true)'. */ - void raw(); + void raw() @trusted; /** * Read input. May return an empty slice if no data * is present and blocking is disabled. */ - string read(Duration dur = Duration.zero); + string read(Duration dur = Duration.zero) @trusted; /** * Write output. */ - void write(string s); + void write(string s) @trusted; /** * Flush output. */ - void flush(); + void flush() @trusted; /** * Get window size. */ - Coord windowSize(); + Coord windowSize() @trusted; /** * Stop input scanning. */ - void stop(); + void stop() @trusted; /** * Close the tty device. */ - void close(); + void close() @trusted; /** * Start termio. This will open the device. */ - void start(); + void start() @trusted; /** * Resized returns true if the window was resized since last checked. @@ -86,10 +86,10 @@ interface Tty * that the caller can see the resize in a timely fashion. * This is edge triggered (reading it will clear the value.) */ - bool resized(); + bool resized() nothrow @nogc @safe; /** * Wake up any reader blocked in read(). */ - void wakeUp(); + void wakeUp() nothrow @trusted; } diff --git a/source/dcell/ttyscreen.d b/source/dcell/ttyscreen.d index cf4dcb4..a1d5582 100644 --- a/source/dcell/ttyscreen.d +++ b/source/dcell/ttyscreen.d @@ -313,7 +313,7 @@ class TtyScreen : Screen started = false; } - void clear() + void clear() @safe { // save the style currently in effect, so when // we later send the clear, we can use it. @@ -326,12 +326,12 @@ class TtyScreen : Screen cells.setAllDirty(false); } - void fill(string s, Style style) + void fill(string s, Style style) @safe { cells.fill(s, style); } - void fill(string s) + void fill(string s) @safe { fill(s, this.style); } @@ -354,7 +354,7 @@ class TtyScreen : Screen return (cells.size()); } - void resize() + void resize() @safe { auto phys = ti.windowSize(); if (phys != cells.size()) @@ -364,34 +364,34 @@ class TtyScreen : Screen } } - ref Cell opIndex(size_t x, size_t y) + ref Cell opIndex(size_t x, size_t y) @safe { return (cells[x, y]); } - void opIndexAssign(Cell c, size_t x, size_t y) + void opIndexAssign(Cell c, size_t x, size_t y) @safe { cells[x, y] = c; } - void enablePaste(bool b) + void enablePaste(bool b) @safe { pasteEn = b; sendPasteEnable(b); } - int colors() const pure + int colors() const pure nothrow @safe { return vt.numColors; } - void show() + void show() @safe { resize(); draw(); } - void sync() + void sync() @safe { pos_ = Coord(-1, -1); resize(); @@ -400,13 +400,13 @@ class TtyScreen : Screen draw(); } - void beep() + void beep() @safe { puts("\x07"); flush(); } - void setSize(Coord size) + void setSize(Coord size) @safe { if (vt.setWindowSize != "") { @@ -417,7 +417,7 @@ class TtyScreen : Screen } } - void enableMouse(MouseEnable en) + void enableMouse(MouseEnable en) @safe { // we rely on the fact that all known implementations adhere // to the de-facto standard from XTerm. This is necessary as @@ -427,7 +427,7 @@ class TtyScreen : Screen sendMouseEnable(en); } - void enableAlternateScreen(bool enabled) + void enableAlternateScreen(bool enabled) @safe { altScrEn = enabled; if (environment.get("DCELL_ALTSCREEN") == "disable") @@ -436,7 +436,7 @@ class TtyScreen : Screen } } - void setTitle(string title) + void setTitle(string title) @safe { this.title = title; if (started && !vt.setTitle.empty) @@ -446,7 +446,7 @@ class TtyScreen : Screen } } - bool waitForEvent(Duration timeout, ref Duration resched) + bool waitForEvent(Duration timeout, ref Duration resched) @safe { // expire for a time when we will timeout, safeguard against obvious overflow. MonoTime expire = (timeout == Duration.max) ? MonoTime.max : MonoTime.currTime() + timeout; @@ -556,7 +556,7 @@ private: class TtyEventQ : EventQ { - override void put(Event ev) + override void put(Event ev) @safe { super.put(ev); ti.wakeUp(); @@ -567,14 +567,14 @@ private: // when adding events that have already come from the tty. // It is significant that this method (indeed the entire class) // is private, so it should not be accessible by external consumers. - void opOpAssign(string op : "~")(Event rhs) + void opOpAssign(string op : "~")(Event rhs) nothrow @safe { super.put(rhs); } // Permit appending a list of events read from the parser directly, but // without waking up the reader. - void opOpAssign(string op : "~")(Event[] rhs) + void opOpAssign(string op : "~")(Event[] rhs) nothrow @safe { foreach (ev; rhs) { @@ -602,13 +602,13 @@ private: string title; TtyEventQ evq; - void puts(string s) + void puts(string s) @safe { ob.write(s); } // flush queued output - void flush() + void flush() @safe { ti.write(ob.toString()); ti.flush(); @@ -616,7 +616,7 @@ private: } // sendColors sends just the colors for a given style - void sendColors(Style style) + void sendColors(Style style) @safe { auto fg = style.fg; auto bg = style.bg; @@ -691,7 +691,7 @@ private: } } - void sendAttrs(Style style) + void sendAttrs(Style style) @safe { auto attr = style.attr; if (attr & Attr.bold) @@ -732,7 +732,7 @@ private: } } - void clearScreen() + void clearScreen() @safe { if (clear_) { @@ -752,7 +752,7 @@ private: } } - void goTo(Coord pos) + void goTo(Coord pos) @safe { if (pos != pos_) { @@ -762,7 +762,7 @@ private: } // sendCursor sends the current cursor location - void sendCursor() + void sendCursor() @safe { if (!cells.isLegal(cursorPos) || (cursorShape == Cursor.hidden)) { @@ -805,7 +805,7 @@ private: } // drawCell draws one cell. It returns the width drawn (1 or 2). - int drawCell(Coord pos) + int drawCell(Coord pos) @safe { Cell c = cells[pos]; auto insert = false; @@ -875,7 +875,7 @@ private: return c.width; } - void draw() + void draw() @safe { puts(vt.startSyncOut); puts(vt.hideCursor); // hide the cursor while we draw @@ -904,7 +904,7 @@ private: flush(); } - void sendMouseEnable(MouseEnable en) + void sendMouseEnable(MouseEnable en) @safe { // we rely on the fact that all known implementations adhere // to the de-facto standard from XTerm. This is necessary as @@ -933,7 +933,7 @@ private: flush(); } - void sendPasteEnable(bool b) + void sendPasteEnable(bool b) @safe { puts(b ? Vt.enablePaste : Vt.disablePaste); flush(); diff --git a/source/dcell/wintty.d b/source/dcell/wintty.d index 84fba8f..6d37f37 100644 --- a/source/dcell/wintty.d +++ b/source/dcell/wintty.d @@ -47,9 +47,6 @@ extern (Windows) @nogc nothrow BOOL CloseHandle(HANDLE hObject); } -@nogc: -nothrow: - /** * WinTty impleements the Tty using the VT input mode and the Win32 ReadConsoleInput and WriteConsole APIs. * We use this instead of ReadFile/WriteFile in order to obtain resize events, and access to the screen size. @@ -57,32 +54,31 @@ nothrow: */ class WinTty : Tty { - /** * Default constructor. * This expects the terminal to be connected to STD_INPUT_HANDLE and STD_OUTPUT_HANDLE. */ - this() + this() @trusted { input = GetStdHandle(STD_INPUT_HANDLE); output = GetStdHandle(STD_OUTPUT_HANDLE); eventH = CreateEventW(null, true, false, null); } - void save() + void save() @trusted { GetConsoleMode(output, &omode); GetConsoleMode(input, &imode); } - void restore() + void restore() @trusted { SetConsoleMode(output, omode); SetConsoleMode(input, imode); } - void start() + void start() @trusted { save(); if (!started) @@ -92,29 +88,29 @@ class WinTty : Tty } } - void stop() + void stop() @trusted { SetEvent(eventH); } - void close() + void close() @trusted { // NB: We do not close the standard input and output handles. CloseHandle(eventH); } - void raw() + void raw() @trusted { SetConsoleMode(input, ENABLE_VIRTUAL_TERMINAL_INPUT | ENABLE_WINDOW_INPUT | ENABLE_EXTENDED_FLAGS); SetConsoleMode(output, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN); } - void flush() + void flush() @safe { } - string read(Duration dur = Duration.zero) + string read(Duration dur = Duration.zero) @trusted { HANDLE[2] handles; handles[0] = input; @@ -170,7 +166,7 @@ class WinTty : Tty } // Write output - void write(string s) @nogc nothrow + void write(string s) @trusted { import std.utf; @@ -191,7 +187,7 @@ class WinTty : Tty } } - Coord windowSize() + Coord windowSize() @trusted { CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(output, &info); @@ -199,14 +195,14 @@ class WinTty : Tty info.srWindow.Bottom - info.srWindow.Top + 1); } - bool resized() + bool resized() @safe { bool result = wasResized; wasResized = false; return result; } - void wakeUp() + void wakeUp() @trusted { SetEvent(eventH); }