mirror of https://github.com/adamdruppe/arsd.git
dark bg, clipboard, and vt on windows beginning factor
This commit is contained in:
parent
944abf3c72
commit
c911434c8b
250
terminal.d
250
terminal.d
|
@ -1,4 +1,6 @@
|
|||
// for optional dependency
|
||||
// for VT on Windows P s = 1 8 → Report the size of the text area in characters as CSI 8 ; height ; width t
|
||||
// could be used to have the TE volunteer the size
|
||||
/++
|
||||
Module for interacting with the user's terminal, including color output, cursor manipulation, and full-featured real-time mouse and keyboard input. Also includes high-level convenience methods, like [Terminal.getline], which gives the user a line editor with history, completion, etc. See the [#examples].
|
||||
|
||||
|
@ -17,8 +19,8 @@
|
|||
|
||||
As a user, if you have to forcibly kill your program and the event doesn't work, there's still ctrl+\
|
||||
|
||||
On Mac Terminal btw, a lot of hacks are needed and mouse support doesn't work. Most functions basically
|
||||
work now though.
|
||||
On old Mac Terminal btw, a lot of hacks are needed and mouse support doesn't work. Most functions basically
|
||||
work now with newer Mac OS versions though.
|
||||
|
||||
Future_Roadmap:
|
||||
$(LIST
|
||||
|
@ -185,8 +187,10 @@ version(Posix) {
|
|||
// capabilities.
|
||||
//version = Demo
|
||||
|
||||
version(Windows)
|
||||
version(Windows) {
|
||||
version(VtEscapeCodes) {} // cool
|
||||
version=Win32Console;
|
||||
}
|
||||
|
||||
version(Win32Console) {
|
||||
import core.sys.windows.windows;
|
||||
|
@ -198,27 +202,30 @@ version(Win32Console) {
|
|||
}
|
||||
|
||||
version(Posix) {
|
||||
|
||||
version=VtEscapeCodes;
|
||||
|
||||
import core.sys.posix.termios;
|
||||
import core.sys.posix.unistd;
|
||||
import unix = core.sys.posix.unistd;
|
||||
import core.sys.posix.sys.types;
|
||||
import core.sys.posix.sys.time;
|
||||
import core.stdc.stdio;
|
||||
|
||||
import core.sys.posix.sys.ioctl;
|
||||
}
|
||||
|
||||
version(VtEscapeCodes) {
|
||||
|
||||
enum UseVtSequences = true;
|
||||
|
||||
version(Windows) {} else
|
||||
private {
|
||||
enum RED_BIT = 1;
|
||||
enum GREEN_BIT = 2;
|
||||
enum BLUE_BIT = 4;
|
||||
}
|
||||
|
||||
version(linux) {
|
||||
extern(C) int ioctl(int, int, ...);
|
||||
enum int TIOCGWINSZ = 0x5413;
|
||||
} else version(OSX) {
|
||||
import core.stdc.config;
|
||||
extern(C) int ioctl(int, c_ulong, ...);
|
||||
enum TIOCGWINSZ = 1074295912;
|
||||
} else static assert(0, "confirm the value of tiocgwinsz");
|
||||
|
||||
struct winsize {
|
||||
ushort ws_row;
|
||||
ushort ws_col;
|
||||
|
@ -373,6 +380,8 @@ an|ansi|ansi-bbs|ANSI terminals (emulators):\
|
|||
:tc=vt-generic:
|
||||
|
||||
`;
|
||||
} else {
|
||||
enum UseVtSequences = false;
|
||||
}
|
||||
|
||||
/// A modifier for [Color]
|
||||
|
@ -543,7 +552,6 @@ struct Terminal {
|
|||
void delegate(in void[]) _writeDelegate; // used to override the unix write() system call, set it magically
|
||||
}
|
||||
|
||||
version(Posix) {
|
||||
bool terminalInFamily(string[] terms...) {
|
||||
import std.process;
|
||||
import std.string;
|
||||
|
@ -555,6 +563,7 @@ struct Terminal {
|
|||
return false;
|
||||
}
|
||||
|
||||
version(Posix) {
|
||||
// This is a filthy hack because Terminal.app and OS X are garbage who don't
|
||||
// work the way they're advertised. I just have to best-guess hack and hope it
|
||||
// doesn't break anything else. (If you know a better way, let me know!)
|
||||
|
@ -566,6 +575,7 @@ struct Terminal {
|
|||
auto term = environment.get("TERM");
|
||||
return term == "xterm-256color";
|
||||
}
|
||||
}
|
||||
|
||||
static string[string] termcapDatabase;
|
||||
static void readTermcapFile(bool useBuiltinTermcap = false) {
|
||||
|
@ -610,6 +620,7 @@ struct Terminal {
|
|||
}
|
||||
|
||||
if(useBuiltinTermcap) {
|
||||
version(VtEscapeCodes)
|
||||
foreach(line; splitLines(builtinTermcap)) {
|
||||
handleTermcapLine(line);
|
||||
}
|
||||
|
@ -839,7 +850,6 @@ struct Terminal {
|
|||
writeStringRaw(buffer[0 .. bufferPos]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint tcaps;
|
||||
|
||||
|
@ -847,7 +857,8 @@ struct Terminal {
|
|||
return (tcaps & TerminalCapabilities.arsdImage) ? true : false;
|
||||
}
|
||||
bool clipboardSupported() {
|
||||
return (tcaps & TerminalCapabilities.arsdImage) ? true : false;
|
||||
version(Win32Console) return true;
|
||||
else return (tcaps & TerminalCapabilities.arsdImage) ? true : false;
|
||||
}
|
||||
|
||||
// only supported on my custom terminal emulator. guarded behind if(inlineImagesSupported)
|
||||
|
@ -918,7 +929,7 @@ struct Terminal {
|
|||
}
|
||||
}
|
||||
|
||||
// stubs that are dependent on tcaps
|
||||
// dependent on tcaps...
|
||||
void displayInlineImage()(ubyte[] imageData) {
|
||||
if(inlineImagesSupported) {
|
||||
import std.base64;
|
||||
|
@ -934,7 +945,7 @@ struct Terminal {
|
|||
}
|
||||
|
||||
void demandUserAttention() {
|
||||
version(Posix) {
|
||||
if(UseVtSequences) {
|
||||
if(!terminalInFamily("linux"))
|
||||
writeStringRaw("\033]5001;1\007");
|
||||
}
|
||||
|
@ -947,12 +958,6 @@ struct Terminal {
|
|||
}
|
||||
}
|
||||
|
||||
void requestPasteFromClipboard() {
|
||||
if(clipboardSupported) {
|
||||
writeStringRaw("\033]52;c;?\007");
|
||||
}
|
||||
}
|
||||
|
||||
void requestCopyToPrimary(string text) {
|
||||
if(clipboardSupported) {
|
||||
import std.base64;
|
||||
|
@ -960,9 +965,16 @@ struct Terminal {
|
|||
}
|
||||
}
|
||||
|
||||
void requestPasteFromPrimary() {
|
||||
if(clipboardSupported) {
|
||||
writeStringRaw("\033]52;p;?\007");
|
||||
bool hasDefaultDarkBackground() {
|
||||
version(Win32Console) {
|
||||
return !(defaultBackgroundColor & 0xf0);
|
||||
} else {
|
||||
// FIXME: there is probably a better way to do this
|
||||
// but like idk how reliable it is.
|
||||
if(terminalInFamily("linux"))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -982,8 +994,6 @@ struct Terminal {
|
|||
this.getSizeOverride = getSizeOverride;
|
||||
this.type = type;
|
||||
|
||||
readTermcap();
|
||||
|
||||
if(type == ConsoleOutputType.minimalProcessing) {
|
||||
_suppressDestruction = true;
|
||||
return;
|
||||
|
@ -992,6 +1002,12 @@ struct Terminal {
|
|||
tcaps = getTerminalCapabilities(fdIn, fdOut);
|
||||
//writeln(tcaps);
|
||||
|
||||
initializeVt();
|
||||
}
|
||||
|
||||
void initializeVt() {
|
||||
readTermcap();
|
||||
|
||||
if(type == ConsoleOutputType.cellular) {
|
||||
doTermcap("ti");
|
||||
clear();
|
||||
|
@ -1001,6 +1017,7 @@ struct Terminal {
|
|||
if(terminalInFamily("xterm", "rxvt", "screen", "tmux")) {
|
||||
writeStringRaw("\033[22;0t"); // save window title on a stack (support seems spotty, but it doesn't hurt to have it)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// EXPERIMENTAL do not use yet
|
||||
|
@ -1019,6 +1036,10 @@ struct Terminal {
|
|||
version(Win32Console)
|
||||
/// ditto
|
||||
this(ConsoleOutputType type) {
|
||||
if(UseVtSequences) {
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
initializeVt();
|
||||
} else {
|
||||
if(type == ConsoleOutputType.cellular) {
|
||||
hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, null, CONSOLE_TEXTMODE_BUFFER, null);
|
||||
if(hConsole == INVALID_HANDLE_VALUE) {
|
||||
|
@ -1068,6 +1089,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
SetConsoleCP(65001); // UTF-8
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
version(Win32Console) {
|
||||
private Color defaultBackgroundColor = Color.black;
|
||||
|
@ -1079,12 +1101,13 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
// only use this if you are sure you know what you want, since the terminal is a shared resource you generally really want to reset it to normal when you leave...
|
||||
bool _suppressDestruction;
|
||||
|
||||
version(Posix)
|
||||
~this() {
|
||||
if(_suppressDestruction) {
|
||||
flush();
|
||||
return;
|
||||
}
|
||||
|
||||
if(UseVtSequences) {
|
||||
if(type == ConsoleOutputType.cellular) {
|
||||
doTermcap("te");
|
||||
}
|
||||
|
@ -1098,14 +1121,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
if(lineGetter !is null)
|
||||
lineGetter.dispose();
|
||||
}
|
||||
|
||||
version(Windows)
|
||||
~this() {
|
||||
if(_suppressDestruction) {
|
||||
flush();
|
||||
return;
|
||||
}
|
||||
} else version(Windows) {
|
||||
flush(); // make sure user data is all flushed before resetting
|
||||
reset();
|
||||
showCursor();
|
||||
|
@ -1121,6 +1137,8 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
SetConsoleActiveScreenBuffer(stdo);
|
||||
if(hConsole !is stdo)
|
||||
CloseHandle(hConsole);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// lazily initialized and preserved between calls to getline for a bit of efficiency (only a bit)
|
||||
|
@ -1285,7 +1303,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
void underline(bool set, ForceOption force = ForceOption.automatic) {
|
||||
if(set == _underlined && force != ForceOption.alwaysSend)
|
||||
return;
|
||||
version(Posix) {
|
||||
if(UseVtSequences) {
|
||||
if(set)
|
||||
writeStringRaw("\033[4m");
|
||||
else
|
||||
|
@ -1329,14 +1347,14 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
void moveTo(int x, int y, ForceOption force = ForceOption.automatic) {
|
||||
if(force != ForceOption.neverSend && (force == ForceOption.alwaysSend || x != _cursorX || y != _cursorY)) {
|
||||
executeAutoHideCursor();
|
||||
version(Posix) {
|
||||
if(UseVtSequences) {
|
||||
doTermcap("cm", y, x);
|
||||
} else version(Win32Console) {
|
||||
|
||||
flush(); // if we don't do this now, the buffering can screw up the position
|
||||
COORD coord = {cast(short) x, cast(short) y};
|
||||
SetConsoleCursorPosition(hConsole, coord);
|
||||
} else static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
_cursorX = x;
|
||||
|
@ -1345,9 +1363,9 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
/// shows the cursor
|
||||
void showCursor() {
|
||||
version(Posix)
|
||||
if(UseVtSequences)
|
||||
doTermcap("ve");
|
||||
else {
|
||||
else version(Win32Console) {
|
||||
CONSOLE_CURSOR_INFO info;
|
||||
GetConsoleCursorInfo(hConsole, &info);
|
||||
info.bVisible = true;
|
||||
|
@ -1357,9 +1375,9 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
/// hides the cursor
|
||||
void hideCursor() {
|
||||
version(Posix) {
|
||||
if(UseVtSequences) {
|
||||
doTermcap("vi");
|
||||
} else {
|
||||
} else version(Win32Console) {
|
||||
CONSOLE_CURSOR_INFO info;
|
||||
GetConsoleCursorInfo(hConsole, &info);
|
||||
info.bVisible = false;
|
||||
|
@ -1466,7 +1484,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
}
|
||||
|
||||
int[] getSize() {
|
||||
version(Win32Console) {
|
||||
version(Windows) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo( hConsole, &info );
|
||||
|
||||
|
@ -1615,17 +1633,12 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
// you really, really shouldn't use this unless you know what you are doing
|
||||
/*private*/ void writeStringRaw(in char[] s) {
|
||||
// FIXME: make sure all the data is sent, check for errors
|
||||
version(Posix) {
|
||||
writeBuffer ~= s; // buffer it to do everything at once in flush() calls
|
||||
} else version(Win32Console) {
|
||||
writeBuffer ~= s;
|
||||
} else static assert(0);
|
||||
}
|
||||
|
||||
/// Clears the screen.
|
||||
void clear() {
|
||||
version(Posix) {
|
||||
if(UseVtSequences) {
|
||||
doTermcap("cl");
|
||||
} else version(Win32Console) {
|
||||
// http://support.microsoft.com/kb/99261
|
||||
|
@ -1705,6 +1718,64 @@ struct RealTimeConsoleInput {
|
|||
@disable this();
|
||||
@disable this(this);
|
||||
|
||||
/++
|
||||
Requests the system to send paste data as a [PasteEvent] to this stream, if possible.
|
||||
|
||||
See_Also:
|
||||
[Terminal.requestCopyToPrimary]
|
||||
[Terminal.requestCopyToClipboard]
|
||||
[Terminal.clipboardSupported]
|
||||
|
||||
History:
|
||||
Added February 17, 2020.
|
||||
|
||||
It was in Terminal briefly during an undocumented period, but it had to be moved here to have the context needed to send the real time paste event.
|
||||
+/
|
||||
void requestPasteFromClipboard() {
|
||||
version(Win32Console) {
|
||||
HWND hwndOwner = null;
|
||||
if(OpenClipboard(hwndOwner) == 0)
|
||||
throw new Exception("OpenClipboard");
|
||||
scope(exit)
|
||||
CloseClipboard();
|
||||
if(auto dataHandle = GetClipboardData(CF_UNICODETEXT)) {
|
||||
|
||||
if(auto data = cast(wchar*) GlobalLock(dataHandle)) {
|
||||
scope(exit)
|
||||
GlobalUnlock(dataHandle);
|
||||
|
||||
int len = 0;
|
||||
auto d = data;
|
||||
while(*d) {
|
||||
d++;
|
||||
len++;
|
||||
}
|
||||
string s;
|
||||
s.reserve(len);
|
||||
foreach(idx, dchar ch; data[0 .. len]) {
|
||||
// CR/LF -> LF
|
||||
if(ch == '\r' && idx + 1 < len && data[idx + 1] == '\n')
|
||||
continue;
|
||||
s ~= ch;
|
||||
}
|
||||
|
||||
injectEvent(InputEvent(PasteEvent(s), terminal), InjectionPosition.tail);
|
||||
}
|
||||
}
|
||||
} else
|
||||
if(terminal.clipboardSupported) {
|
||||
terminal.writeStringRaw("\033]52;c;?\007");
|
||||
}
|
||||
}
|
||||
|
||||
/// ditto
|
||||
void requestPasteFromPrimary() {
|
||||
if(terminal.clipboardSupported) {
|
||||
terminal.writeStringRaw("\033]52;p;?\007");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
version(Posix) {
|
||||
private int fdOut;
|
||||
private int fdIn;
|
||||
|
@ -1739,7 +1810,7 @@ struct RealTimeConsoleInput {
|
|||
GetConsoleMode(inputHandle, &oldInput);
|
||||
|
||||
DWORD mode = 0;
|
||||
mode |= ENABLE_PROCESSED_INPUT /* 0x01 */; // this gives Ctrl+C which we probably want to be similar to linux
|
||||
//mode |= ENABLE_PROCESSED_INPUT /* 0x01 */; // this gives Ctrl+C and automatic paste... which we probably want to be similar to linux
|
||||
//if(flags & ConsoleInputFlags.size)
|
||||
mode |= ENABLE_WINDOW_INPUT /* 0208 */; // gives size etc
|
||||
if(flags & ConsoleInputFlags.echo)
|
||||
|
@ -1980,7 +2051,7 @@ struct RealTimeConsoleInput {
|
|||
|
||||
bool timedCheckForInput_bypassingBuffer(int milliseconds) {
|
||||
version(Win32Console) {
|
||||
auto response = WaitForSingleObject(terminal.hConsole, milliseconds);
|
||||
auto response = WaitForSingleObject(inputHandle, milliseconds);
|
||||
if(response == 0)
|
||||
return true; // the object is ready
|
||||
return false;
|
||||
|
@ -2039,8 +2110,8 @@ struct RealTimeConsoleInput {
|
|||
|
||||
//char[128] inputBuffer;
|
||||
//int inputBufferPosition;
|
||||
version(Posix)
|
||||
int nextRaw(bool interruptable = false) {
|
||||
version(Posix) {
|
||||
if(fdIn == -1)
|
||||
return 0;
|
||||
|
||||
|
@ -2067,12 +2138,20 @@ struct RealTimeConsoleInput {
|
|||
return inputPrefilter ? inputPrefilter(buf[0]) : buf[0];
|
||||
else
|
||||
assert(0); // read too much, should be impossible
|
||||
} else version(Windows) {
|
||||
char[8] buf;
|
||||
DWORD d;
|
||||
import std.conv;
|
||||
if(!ReadFile(inputHandle, buf.ptr, cast(int) buf.length, &d, null))
|
||||
throw new Exception("ReadFile " ~ to!string(GetLastError()));
|
||||
return buf[0];
|
||||
}
|
||||
}
|
||||
|
||||
version(Posix)
|
||||
int delegate(char) inputPrefilter;
|
||||
|
||||
version(Posix)
|
||||
// for VT
|
||||
dchar nextChar(int starting) {
|
||||
if(starting <= 127)
|
||||
return cast(dchar) starting;
|
||||
|
@ -2176,8 +2255,17 @@ struct RealTimeConsoleInput {
|
|||
|
||||
InputEvent[] inputQueue;
|
||||
|
||||
version(Win32Console)
|
||||
InputEvent[] readNextEvents() {
|
||||
if(UseVtSequences)
|
||||
return readNextEventsVt();
|
||||
else version(Windows)
|
||||
return readNextEventsWin32();
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
version(Windows)
|
||||
InputEvent[] readNextEventsWin32() {
|
||||
terminal.flush(); // make sure all output is sent out before waiting for anything
|
||||
|
||||
INPUT_RECORD[32] buffer;
|
||||
|
@ -2219,12 +2307,26 @@ struct RealTimeConsoleInput {
|
|||
|
||||
if(ev.UnicodeChar) {
|
||||
// new style event goes first
|
||||
|
||||
if(ev.UnicodeChar == 3) {
|
||||
// handling this internally for linux compat too
|
||||
newEvents ~= InputEvent(UserInterruptionEvent(), terminal);
|
||||
} else if(ev.UnicodeChar == '\r') {
|
||||
// translating \r to \n for same result as linux...
|
||||
ke.which = cast(dchar) cast(wchar) '\n';
|
||||
newEvents ~= InputEvent(ke, terminal);
|
||||
|
||||
// old style event then follows as the fallback
|
||||
e.character = cast(dchar) cast(wchar) '\n';
|
||||
newEvents ~= InputEvent(e, terminal);
|
||||
} else {
|
||||
ke.which = cast(dchar) cast(wchar) ev.UnicodeChar;
|
||||
newEvents ~= InputEvent(ke, terminal);
|
||||
|
||||
// old style event then follows as the fallback
|
||||
e.character = cast(dchar) cast(wchar) ev.UnicodeChar;
|
||||
newEvents ~= InputEvent(e, terminal);
|
||||
}
|
||||
} else {
|
||||
// old style event
|
||||
ne.key = cast(NonCharacterKeyEvent.Key) ev.wVirtualKeyCode;
|
||||
|
@ -2302,8 +2404,8 @@ struct RealTimeConsoleInput {
|
|||
return newEvents;
|
||||
}
|
||||
|
||||
version(Posix)
|
||||
InputEvent[] readNextEvents() {
|
||||
// for UseVtSequences....
|
||||
InputEvent[] readNextEventsVt() {
|
||||
terminal.flush(); // make sure all output is sent out before we try to get input
|
||||
|
||||
// we want to starve the read, especially if we're called from an edge-triggered
|
||||
|
@ -2327,7 +2429,7 @@ struct RealTimeConsoleInput {
|
|||
}
|
||||
|
||||
// The helper reads just one actual event from the pipe...
|
||||
version(Posix)
|
||||
// for UseVtSequences....
|
||||
InputEvent[] readNextEventsHelper() {
|
||||
InputEvent[] charPressAndRelease(dchar character) {
|
||||
if((flags & ConsoleInputFlags.releasedKeys))
|
||||
|
@ -3711,11 +3813,11 @@ class LineGetter {
|
|||
auto i = RealTimeConsoleInput(terminal, ConsoleInputFlags.raw | ConsoleInputFlags.allInputEvents | ConsoleInputFlags.noEolWrap);
|
||||
//rtci = &i;
|
||||
//scope(exit) rtci = null;
|
||||
while(workOnLine(i.nextEvent())) {}
|
||||
while(workOnLine(i.nextEvent(), &i)) {}
|
||||
} else {
|
||||
//rtci = input;
|
||||
//scope(exit) rtci = null;
|
||||
while(workOnLine(input.nextEvent())) {}
|
||||
while(workOnLine(input.nextEvent(), input)) {}
|
||||
}
|
||||
return finishGettingLine();
|
||||
}
|
||||
|
@ -4118,12 +4220,19 @@ class LineGetter {
|
|||
|
||||
private bool maintainBuffer;
|
||||
|
||||
/// for integrating into another event loop
|
||||
/// you can pass individual events to this and
|
||||
/// the line getter will work on it
|
||||
///
|
||||
/// returns false when there's nothing more to do
|
||||
bool workOnLine(InputEvent e) {
|
||||
/++
|
||||
for integrating into another event loop
|
||||
you can pass individual events to this and
|
||||
the line getter will work on it
|
||||
|
||||
returns false when there's nothing more to do
|
||||
|
||||
History:
|
||||
On February 17, 2020, it was changed to take
|
||||
a new argument which should be the input source
|
||||
where the event came from.
|
||||
+/
|
||||
bool workOnLine(InputEvent e, RealTimeConsoleInput* rtti = null) {
|
||||
switch(e.type) {
|
||||
case InputEvent.Type.EndOfFileEvent:
|
||||
justHitTab = false;
|
||||
|
@ -4309,6 +4418,10 @@ class LineGetter {
|
|||
scrollToEnd();
|
||||
redraw();
|
||||
break;
|
||||
case ('v' - 'a' + 1):
|
||||
if(rtti)
|
||||
rtti.requestPasteFromClipboard();
|
||||
break;
|
||||
case KeyboardEvent.Key.Insert:
|
||||
justHitTab = false;
|
||||
if(ev.modifierState & ModifierState.shift) {
|
||||
|
@ -4319,8 +4432,11 @@ class LineGetter {
|
|||
|
||||
// those work on Windows!!!! and many linux TEs too.
|
||||
// but if it does make it here, we'll attempt it at this level
|
||||
if(rtti)
|
||||
rtti.requestPasteFromClipboard();
|
||||
} else if(ev.modifierState & ModifierState.control) {
|
||||
// copy
|
||||
// FIXME
|
||||
} else {
|
||||
insertMode = !insertMode;
|
||||
|
||||
|
|
Loading…
Reference in New Issue