mirror of https://github.com/adamdruppe/arsd.git
lots of cool stuff
This commit is contained in:
parent
f95927b193
commit
c2b29d1e21
277
terminal.d
277
terminal.d
|
@ -955,6 +955,10 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
||||||
|
|
||||||
version(Windows)
|
version(Windows)
|
||||||
~this() {
|
~this() {
|
||||||
|
if(_suppressDestruction) {
|
||||||
|
flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
flush(); // make sure user data is all flushed before resetting
|
flush(); // make sure user data is all flushed before resetting
|
||||||
reset();
|
reset();
|
||||||
showCursor();
|
showCursor();
|
||||||
|
@ -1411,7 +1415,8 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
||||||
// assert(s.indexOf("\033") == -1);
|
// assert(s.indexOf("\033") == -1);
|
||||||
|
|
||||||
// tracking cursor position
|
// tracking cursor position
|
||||||
foreach(ch; s) {
|
// FIXME: by grapheme?
|
||||||
|
foreach(dchar ch; s) {
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case '\n':
|
case '\n':
|
||||||
_cursorX = 0;
|
_cursorX = 0;
|
||||||
|
@ -1425,8 +1430,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
||||||
_cursorX += _cursorX % 8; // FIXME: get the actual tabstop, if possible
|
_cursorX += _cursorX % 8; // FIXME: get the actual tabstop, if possible
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(ch <= 127) // way of only advancing once per dchar instead of per code unit
|
_cursorX++;
|
||||||
_cursorX++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_wrapAround && _cursorX > width) {
|
if(_wrapAround && _cursorX > width) {
|
||||||
|
@ -1760,7 +1764,12 @@ struct RealTimeConsoleInput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _suppressDestruction;
|
||||||
|
|
||||||
~this() {
|
~this() {
|
||||||
|
if(_suppressDestruction)
|
||||||
|
return;
|
||||||
|
|
||||||
// the delegate thing doesn't actually work for this... for some reason
|
// the delegate thing doesn't actually work for this... for some reason
|
||||||
version(Posix)
|
version(Posix)
|
||||||
if(fdIn != -1)
|
if(fdIn != -1)
|
||||||
|
@ -2198,6 +2207,23 @@ struct RealTimeConsoleInput {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputEvent[] keyPressAndRelease2(dchar c, uint modifiers = 0) {
|
||||||
|
if((flags & ConsoleInputFlags.releasedKeys))
|
||||||
|
return [
|
||||||
|
InputEvent(KeyboardEvent(true, c, modifiers), terminal),
|
||||||
|
InputEvent(KeyboardEvent(false, c, modifiers), terminal),
|
||||||
|
// old style event
|
||||||
|
InputEvent(CharacterEvent(CharacterEvent.Type.Pressed, c, modifiers), terminal),
|
||||||
|
InputEvent(CharacterEvent(CharacterEvent.Type.Released, c, modifiers), terminal),
|
||||||
|
];
|
||||||
|
else return [
|
||||||
|
InputEvent(KeyboardEvent(true, c, modifiers), terminal),
|
||||||
|
// old style event
|
||||||
|
InputEvent(CharacterEvent(CharacterEvent.Type.Pressed, c, modifiers), terminal)
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
char[30] sequenceBuffer;
|
char[30] sequenceBuffer;
|
||||||
|
|
||||||
// this assumes you just read "\033["
|
// this assumes you just read "\033["
|
||||||
|
@ -2285,7 +2311,7 @@ struct RealTimeConsoleInput {
|
||||||
default:
|
default:
|
||||||
// don't know it, just ignore
|
// don't know it, just ignore
|
||||||
//import std.stdio;
|
//import std.stdio;
|
||||||
//writeln(cap);
|
//terminal.writeln(cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -2388,92 +2414,110 @@ struct RealTimeConsoleInput {
|
||||||
|
|
||||||
return [InputEvent(m, terminal)];
|
return [InputEvent(m, terminal)];
|
||||||
default:
|
default:
|
||||||
// look it up in the termcap key database
|
// screen doesn't actually do the modifiers, but
|
||||||
auto cap = terminal.findSequenceInTermcap(sequence);
|
// it uses the same format so this branch still works fine.
|
||||||
if(cap !is null) {
|
if(terminal.terminalInFamily("xterm", "screen")) {
|
||||||
return translateTermcapName(cap);
|
import std.conv, std.string;
|
||||||
} else {
|
auto terminator = sequence[$ - 1];
|
||||||
if(terminal.terminalInFamily("xterm")) {
|
auto parts = sequence[2 .. $ - 1].split(";");
|
||||||
import std.conv, std.string;
|
// parts[0] and terminator tells us the key
|
||||||
auto terminator = sequence[$ - 1];
|
// parts[1] tells us the modifierState
|
||||||
auto parts = sequence[2 .. $ - 1].split(";");
|
|
||||||
// parts[0] and terminator tells us the key
|
|
||||||
// parts[1] tells us the modifierState
|
|
||||||
|
|
||||||
uint modifierState;
|
uint modifierState;
|
||||||
|
|
||||||
int modGot;
|
int modGot;
|
||||||
if(parts.length > 1)
|
if(parts.length > 1)
|
||||||
modGot = to!int(parts[1]);
|
modGot = to!int(parts[1]);
|
||||||
mod_switch: switch(modGot) {
|
mod_switch: switch(modGot) {
|
||||||
case 2: modifierState |= ModifierState.shift; break;
|
case 2: modifierState |= ModifierState.shift; break;
|
||||||
case 3: modifierState |= ModifierState.alt; break;
|
case 3: modifierState |= ModifierState.alt; break;
|
||||||
case 4: modifierState |= ModifierState.shift | ModifierState.alt; break;
|
case 4: modifierState |= ModifierState.shift | ModifierState.alt; break;
|
||||||
case 5: modifierState |= ModifierState.control; break;
|
case 5: modifierState |= ModifierState.control; break;
|
||||||
case 6: modifierState |= ModifierState.shift | ModifierState.control; break;
|
case 6: modifierState |= ModifierState.shift | ModifierState.control; break;
|
||||||
case 7: modifierState |= ModifierState.alt | ModifierState.control; break;
|
case 7: modifierState |= ModifierState.alt | ModifierState.control; break;
|
||||||
case 8: modifierState |= ModifierState.shift | ModifierState.alt | ModifierState.control; break;
|
case 8: modifierState |= ModifierState.shift | ModifierState.alt | ModifierState.control; break;
|
||||||
case 9:
|
case 9:
|
||||||
..
|
..
|
||||||
case 16:
|
case 16:
|
||||||
modifierState |= ModifierState.meta;
|
modifierState |= ModifierState.meta;
|
||||||
if(modGot != 9) {
|
if(modGot != 9) {
|
||||||
modGot -= 8;
|
modGot -= 8;
|
||||||
goto mod_switch;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// this is an extension in my own terminal emulator
|
|
||||||
case 20:
|
|
||||||
..
|
|
||||||
case 36:
|
|
||||||
modifierState |= ModifierState.windows;
|
|
||||||
modGot -= 20;
|
|
||||||
goto mod_switch;
|
goto mod_switch;
|
||||||
default:
|
}
|
||||||
}
|
break;
|
||||||
|
|
||||||
switch(terminator) {
|
// this is an extension in my own terminal emulator
|
||||||
case 'A': return keyPressAndRelease(NonCharacterKeyEvent.Key.UpArrow, modifierState);
|
case 20:
|
||||||
case 'B': return keyPressAndRelease(NonCharacterKeyEvent.Key.DownArrow, modifierState);
|
..
|
||||||
case 'C': return keyPressAndRelease(NonCharacterKeyEvent.Key.RightArrow, modifierState);
|
case 36:
|
||||||
case 'D': return keyPressAndRelease(NonCharacterKeyEvent.Key.LeftArrow, modifierState);
|
modifierState |= ModifierState.windows;
|
||||||
|
modGot -= 20;
|
||||||
|
goto mod_switch;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
case 'H': return keyPressAndRelease(NonCharacterKeyEvent.Key.Home, modifierState);
|
switch(terminator) {
|
||||||
case 'F': return keyPressAndRelease(NonCharacterKeyEvent.Key.End, modifierState);
|
case 'A': return keyPressAndRelease(NonCharacterKeyEvent.Key.UpArrow, modifierState);
|
||||||
|
case 'B': return keyPressAndRelease(NonCharacterKeyEvent.Key.DownArrow, modifierState);
|
||||||
|
case 'C': return keyPressAndRelease(NonCharacterKeyEvent.Key.RightArrow, modifierState);
|
||||||
|
case 'D': return keyPressAndRelease(NonCharacterKeyEvent.Key.LeftArrow, modifierState);
|
||||||
|
|
||||||
case 'P': return keyPressAndRelease(NonCharacterKeyEvent.Key.F1, modifierState);
|
case 'H': return keyPressAndRelease(NonCharacterKeyEvent.Key.Home, modifierState);
|
||||||
case 'Q': return keyPressAndRelease(NonCharacterKeyEvent.Key.F2, modifierState);
|
case 'F': return keyPressAndRelease(NonCharacterKeyEvent.Key.End, modifierState);
|
||||||
case 'R': return keyPressAndRelease(NonCharacterKeyEvent.Key.F3, modifierState);
|
|
||||||
case 'S': return keyPressAndRelease(NonCharacterKeyEvent.Key.F4, modifierState);
|
|
||||||
|
|
||||||
case '~': // others
|
case 'P': return keyPressAndRelease(NonCharacterKeyEvent.Key.F1, modifierState);
|
||||||
switch(parts[0]) {
|
case 'Q': return keyPressAndRelease(NonCharacterKeyEvent.Key.F2, modifierState);
|
||||||
case "5": return keyPressAndRelease(NonCharacterKeyEvent.Key.PageUp, modifierState);
|
case 'R': return keyPressAndRelease(NonCharacterKeyEvent.Key.F3, modifierState);
|
||||||
case "6": return keyPressAndRelease(NonCharacterKeyEvent.Key.PageDown, modifierState);
|
case 'S': return keyPressAndRelease(NonCharacterKeyEvent.Key.F4, modifierState);
|
||||||
case "2": return keyPressAndRelease(NonCharacterKeyEvent.Key.Insert, modifierState);
|
|
||||||
case "3": return keyPressAndRelease(NonCharacterKeyEvent.Key.Delete, modifierState);
|
|
||||||
|
|
||||||
case "15": return keyPressAndRelease(NonCharacterKeyEvent.Key.F5, modifierState);
|
case '~': // others
|
||||||
case "17": return keyPressAndRelease(NonCharacterKeyEvent.Key.F6, modifierState);
|
switch(parts[0]) {
|
||||||
case "18": return keyPressAndRelease(NonCharacterKeyEvent.Key.F7, modifierState);
|
case "1": return keyPressAndRelease(NonCharacterKeyEvent.Key.Home, modifierState);
|
||||||
case "19": return keyPressAndRelease(NonCharacterKeyEvent.Key.F8, modifierState);
|
case "4": return keyPressAndRelease(NonCharacterKeyEvent.Key.End, modifierState);
|
||||||
case "20": return keyPressAndRelease(NonCharacterKeyEvent.Key.F9, modifierState);
|
case "5": return keyPressAndRelease(NonCharacterKeyEvent.Key.PageUp, modifierState);
|
||||||
case "21": return keyPressAndRelease(NonCharacterKeyEvent.Key.F10, modifierState);
|
case "6": return keyPressAndRelease(NonCharacterKeyEvent.Key.PageDown, modifierState);
|
||||||
case "23": return keyPressAndRelease(NonCharacterKeyEvent.Key.F11, modifierState);
|
case "2": return keyPressAndRelease(NonCharacterKeyEvent.Key.Insert, modifierState);
|
||||||
case "24": return keyPressAndRelease(NonCharacterKeyEvent.Key.F12, modifierState);
|
case "3": return keyPressAndRelease(NonCharacterKeyEvent.Key.Delete, modifierState);
|
||||||
default:
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
case "15": return keyPressAndRelease(NonCharacterKeyEvent.Key.F5, modifierState);
|
||||||
}
|
case "17": return keyPressAndRelease(NonCharacterKeyEvent.Key.F6, modifierState);
|
||||||
} else if(terminal.terminalInFamily("rxvt")) {
|
case "18": return keyPressAndRelease(NonCharacterKeyEvent.Key.F7, modifierState);
|
||||||
// FIXME: figure these out. rxvt seems to just change the terminator while keeping the rest the same
|
case "19": return keyPressAndRelease(NonCharacterKeyEvent.Key.F8, modifierState);
|
||||||
// though it isn't consistent. ugh.
|
case "20": return keyPressAndRelease(NonCharacterKeyEvent.Key.F9, modifierState);
|
||||||
} else {
|
case "21": return keyPressAndRelease(NonCharacterKeyEvent.Key.F10, modifierState);
|
||||||
// maybe we could do more terminals, but linux doesn't even send it and screen just seems to pass through, so i don't think so; xterm prolly covers most them anyway
|
case "23": return keyPressAndRelease(NonCharacterKeyEvent.Key.F11, modifierState);
|
||||||
// so this space is semi-intentionally left blank
|
case "24": return keyPressAndRelease(NonCharacterKeyEvent.Key.F12, modifierState);
|
||||||
|
|
||||||
|
// starting at 70 i do some magic for like shift+enter etc.
|
||||||
|
// this only happens on my own terminal emulator.
|
||||||
|
case "78": return keyPressAndRelease2('\b', modifierState);
|
||||||
|
case "79": return keyPressAndRelease2('\t', modifierState);
|
||||||
|
case "83": return keyPressAndRelease2('\n', modifierState);
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
} else if(terminal.terminalInFamily("rxvt")) {
|
||||||
|
// look it up in the termcap key database
|
||||||
|
string cap = terminal.findSequenceInTermcap(sequence);
|
||||||
|
if(cap !is null) {
|
||||||
|
//terminal.writeln("found in termcap " ~ cap);
|
||||||
|
return translateTermcapName(cap);
|
||||||
|
}
|
||||||
|
// FIXME: figure these out. rxvt seems to just change the terminator while keeping the rest the same
|
||||||
|
// though it isn't consistent. ugh.
|
||||||
|
} else {
|
||||||
|
// maybe we could do more terminals, but linux doesn't even send it and screen just seems to pass through, so i don't think so; xterm prolly covers most them anyway
|
||||||
|
// so this space is semi-intentionally left blank
|
||||||
|
//terminal.writeln("wtf ", sequence[1..$]);
|
||||||
|
|
||||||
|
// look it up in the termcap key database
|
||||||
|
string cap = terminal.findSequenceInTermcap(sequence);
|
||||||
|
if(cap !is null) {
|
||||||
|
//terminal.writeln("found in termcap " ~ cap);
|
||||||
|
return translateTermcapName(cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3067,7 +3111,21 @@ class LineGetter {
|
||||||
//bool reverseVideo;
|
//bool reverseVideo;
|
||||||
|
|
||||||
/// Set this if you want a prompt to be drawn with the line. It does NOT support color in string.
|
/// Set this if you want a prompt to be drawn with the line. It does NOT support color in string.
|
||||||
string prompt;
|
@property void prompt(string p) {
|
||||||
|
this.prompt_ = p;
|
||||||
|
|
||||||
|
promptLength = 0;
|
||||||
|
foreach(dchar c; p)
|
||||||
|
promptLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
@property string prompt() {
|
||||||
|
return this.prompt_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string prompt_;
|
||||||
|
private int promptLength;
|
||||||
|
|
||||||
/// Turn on auto suggest if you want a greyed thing of what tab
|
/// Turn on auto suggest if you want a greyed thing of what tab
|
||||||
/// would be able to fill in as you type.
|
/// would be able to fill in as you type.
|
||||||
|
@ -3316,7 +3374,7 @@ class LineGetter {
|
||||||
}
|
}
|
||||||
|
|
||||||
int availableLineLength() {
|
int availableLineLength() {
|
||||||
return terminal.width - startOfLineX - cast(int) prompt.length - 1;
|
return terminal.width - startOfLineX - promptLength - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int lastDrawLength = 0;
|
private int lastDrawLength = 0;
|
||||||
|
@ -3340,7 +3398,7 @@ class LineGetter {
|
||||||
auto cursorPositionToDrawX = cursorPosition - horizontalScrollPosition;
|
auto cursorPositionToDrawX = cursorPosition - horizontalScrollPosition;
|
||||||
auto cursorPositionToDrawY = 0;
|
auto cursorPositionToDrawY = 0;
|
||||||
|
|
||||||
int written = cast(int) prompt.length;
|
int written = promptLength;
|
||||||
|
|
||||||
void specialChar(char c) {
|
void specialChar(char c) {
|
||||||
terminal.color(regularForeground, specialCharBackground);
|
terminal.color(regularForeground, specialCharBackground);
|
||||||
|
@ -3395,14 +3453,14 @@ class LineGetter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: graphemes and utf-8 on suggestion/prompt
|
// FIXME: graphemes
|
||||||
|
|
||||||
if(written < lastDrawLength)
|
if(written < lastDrawLength)
|
||||||
foreach(i; written .. lastDrawLength)
|
foreach(i; written .. lastDrawLength)
|
||||||
terminal.write(" ");
|
terminal.write(" ");
|
||||||
lastDrawLength = written;
|
lastDrawLength = written;
|
||||||
|
|
||||||
terminal.moveTo(startOfLineX + cursorPositionToDrawX + cast(int) prompt.length, startOfLineY + cursorPositionToDrawY);
|
terminal.moveTo(startOfLineX + cursorPositionToDrawX + promptLength, startOfLineY + cursorPositionToDrawY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Starts getting a new line. Call workOnLine and finishGettingLine afterward.
|
/// Starts getting a new line. Call workOnLine and finishGettingLine afterward.
|
||||||
|
@ -3436,13 +3494,21 @@ class LineGetter {
|
||||||
horizontalScrollPosition = cursorPosition;
|
horizontalScrollPosition = cursorPosition;
|
||||||
horizontalScrollPosition -= terminal.width / 2;
|
horizontalScrollPosition -= terminal.width / 2;
|
||||||
// align on a code point boundary
|
// align on a code point boundary
|
||||||
while(horizontalScrollPosition > 0 && (line[horizontalScrollPosition] & 0x80))
|
aligned(horizontalScrollPosition, -1);
|
||||||
horizontalScrollPosition--;
|
|
||||||
if(horizontalScrollPosition < 0)
|
if(horizontalScrollPosition < 0)
|
||||||
horizontalScrollPosition = 0;
|
horizontalScrollPosition = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void aligned(ref int what, int direction) {
|
||||||
|
// whereas line is right now dchar[] no need for this
|
||||||
|
// at least until we go by grapheme...
|
||||||
|
/*
|
||||||
|
while(what > 0 && what < line.length && ((line[what] & 0b1100_0000) == 0b1000_0000))
|
||||||
|
what += direction;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
private void initializeWithSize(bool firstEver = false) {
|
private void initializeWithSize(bool firstEver = false) {
|
||||||
auto x = startOfLineX;
|
auto x = startOfLineX;
|
||||||
|
|
||||||
|
@ -3454,6 +3520,8 @@ class LineGetter {
|
||||||
}
|
}
|
||||||
|
|
||||||
lastDrawLength = terminal.width;
|
lastDrawLength = terminal.width;
|
||||||
|
version(Win32Console)
|
||||||
|
lastDrawLength -= 1; // I don't like this but Windows resizing is different anyway and it is liable to scroll if i go over..
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
@ -3518,9 +3586,17 @@ class LineGetter {
|
||||||
}
|
}
|
||||||
throw new Exception("Couldn't get cursor position to initialize get line " ~ to!string(len) ~ " " ~ to!string(errno));
|
throw new Exception("Couldn't get cursor position to initialize get line " ~ to!string(len) ~ " " ~ to!string(errno));
|
||||||
}
|
}
|
||||||
|
regot:
|
||||||
auto got = buffer[0 .. len];
|
auto got = buffer[0 .. len];
|
||||||
if(got.length < 6)
|
if(got.length < 6) {
|
||||||
throw new Exception("not enough cursor reply answer");
|
auto len2 = read(terminal.fdIn, &buffer[len], buffer.length - len);
|
||||||
|
if(len2 <= 0)
|
||||||
|
throw new Exception("not enough cursor reply answer");
|
||||||
|
else {
|
||||||
|
len += len2;
|
||||||
|
goto regot;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(got[0] != '\033' || got[1] != '[' || got[$-1] != 'R') {
|
if(got[0] != '\033' || got[1] != '[' || got[$-1] != 'R') {
|
||||||
retries--;
|
retries--;
|
||||||
if(retries > 0)
|
if(retries > 0)
|
||||||
|
@ -3637,9 +3713,12 @@ class LineGetter {
|
||||||
while(cursorPosition && line[cursorPosition - 1] != ' ')
|
while(cursorPosition && line[cursorPosition - 1] != ' ')
|
||||||
cursorPosition--;
|
cursorPosition--;
|
||||||
}
|
}
|
||||||
|
aligned(cursorPosition, -1);
|
||||||
if(!multiLineMode) {
|
if(!multiLineMode) {
|
||||||
if(cursorPosition < horizontalScrollPosition)
|
if(cursorPosition < horizontalScrollPosition) {
|
||||||
horizontalScrollPosition--;
|
horizontalScrollPosition--;
|
||||||
|
aligned(horizontalScrollPosition, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
@ -3656,9 +3735,12 @@ class LineGetter {
|
||||||
if(cursorPosition > line.length)
|
if(cursorPosition > line.length)
|
||||||
cursorPosition = cast(int) line.length;
|
cursorPosition = cast(int) line.length;
|
||||||
}
|
}
|
||||||
|
aligned(cursorPosition, 1);
|
||||||
if(!multiLineMode) {
|
if(!multiLineMode) {
|
||||||
if(cursorPosition >= horizontalScrollPosition + availableLineLength())
|
if(cursorPosition >= horizontalScrollPosition + availableLineLength()) {
|
||||||
horizontalScrollPosition++;
|
horizontalScrollPosition++;
|
||||||
|
aligned(horizontalScrollPosition, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
@ -3705,12 +3787,8 @@ class LineGetter {
|
||||||
// shift+insert = request paste
|
// shift+insert = request paste
|
||||||
// ctrl+insert = request copy. but that needs a selection
|
// ctrl+insert = request copy. but that needs a selection
|
||||||
|
|
||||||
// those work on Windows!!!!o
|
// those work on Windows!!!! and many linux TEs too.
|
||||||
|
// but if it does make it here, we'll attempt it at this level
|
||||||
/*
|
|
||||||
change cursor capabilitiy
|
|
||||||
*/
|
|
||||||
|
|
||||||
} else if(ev.modifierState & ModifierState.control) {
|
} else if(ev.modifierState & ModifierState.control) {
|
||||||
// copy
|
// copy
|
||||||
} else {
|
} else {
|
||||||
|
@ -3758,8 +3836,7 @@ class LineGetter {
|
||||||
if(me.eventType == MouseEvent.Type.Pressed) {
|
if(me.eventType == MouseEvent.Type.Pressed) {
|
||||||
if(me.buttons & MouseEvent.Button.Left) {
|
if(me.buttons & MouseEvent.Button.Left) {
|
||||||
if(me.y == startOfLineY) {
|
if(me.y == startOfLineY) {
|
||||||
// FIXME: prompt.length should be graphemes or at least code poitns
|
int p = me.x - startOfLineX - promptLength + horizontalScrollPosition;
|
||||||
int p = me.x - startOfLineX - cast(int) prompt.length + horizontalScrollPosition;
|
|
||||||
if(p >= 0 && p < line.length) {
|
if(p >= 0 && p < line.length) {
|
||||||
justHitTab = false;
|
justHitTab = false;
|
||||||
cursorPosition = p;
|
cursorPosition = p;
|
||||||
|
|
Loading…
Reference in New Issue