mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-16 13:57:07 +09:00
196 lines
5.3 KiB
D
196 lines
5.3 KiB
D
import termbox;
|
|
import buffer;
|
|
import clipboard;
|
|
import cursor;
|
|
import statusline;
|
|
|
|
import std.conv: to;
|
|
import std.utf: count;
|
|
|
|
class View {
|
|
uint topline;
|
|
|
|
uint width;
|
|
uint height;
|
|
|
|
Buffer buf;
|
|
Cursor cursor;
|
|
StatusLine sl;
|
|
|
|
this(Buffer buf, Cursor cursor, uint topline = 0, uint width = termbox.width(), uint height = termbox.height() - 2) {
|
|
this.topline = topline;
|
|
this.width = width;
|
|
this.height = height;
|
|
|
|
this.buf = buf;
|
|
this.cursor = cursor;
|
|
this.sl = new StatusLine(this);
|
|
}
|
|
|
|
uint toCharNumber(int x, int y) {
|
|
int loc;
|
|
foreach (i; 0 .. y) {
|
|
loc += buf.lines[i].count + 1;
|
|
}
|
|
loc += x;
|
|
return loc;
|
|
}
|
|
|
|
int[] fromCharNumber(uint value) {
|
|
int x, y;
|
|
int loc;
|
|
foreach (lineNum, l; buf.lines) {
|
|
if (loc + l.count+1 > value) {
|
|
y = cast(int) lineNum;
|
|
x = value - loc;
|
|
return [x, y];
|
|
} else {
|
|
loc += l.count+1;
|
|
}
|
|
}
|
|
return [-1, -1];
|
|
}
|
|
|
|
uint cursorLoc() {
|
|
return toCharNumber(cursor.x, cursor.y);
|
|
}
|
|
|
|
void setCursorLoc(uint charNum) {
|
|
int[] xy = fromCharNumber(charNum);
|
|
cursor.x = xy[0];
|
|
cursor.y = xy[1];
|
|
}
|
|
|
|
void cursorUp() {
|
|
if (cursor.y > 0) {
|
|
cursor.y--;
|
|
cursor.x = cursor.lastX;
|
|
if (cursor.x > buf.lines[cursor.y].length) {
|
|
cursor.x = cast(int) buf.lines[cursor.y].length;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cursorDown() {
|
|
if (cursor.y < buf.lines.length - 1) {
|
|
cursor.y++;
|
|
cursor.x = cursor.lastX;
|
|
if (cursor.x > buf.lines[cursor.y].length) {
|
|
cursor.x = cast(int) buf.lines[cursor.y].length;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cursorRight() {
|
|
if (cursor.x < buf.lines[cursor.y].length) {
|
|
cursor.x++;
|
|
cursor.lastX = cursor.x;
|
|
}
|
|
}
|
|
|
|
void cursorLeft() {
|
|
if (cursor.x > 0) {
|
|
cursor.x--;
|
|
cursor.lastX = cursor.x;
|
|
}
|
|
}
|
|
|
|
void update(Event e) {
|
|
uint cloc = cursorLoc();
|
|
if (e.key == Key.mouseWheelUp) {
|
|
if (topline > 0)
|
|
topline--;
|
|
} else if (e.key == Key.mouseWheelDown) {
|
|
if (buf.lines.length > height && topline < buf.lines.length - height)
|
|
topline++;
|
|
} else {
|
|
if (e.key == Key.arrowUp) {
|
|
cursorUp();
|
|
} else if (e.key == Key.arrowDown) {
|
|
cursorDown();
|
|
} else if (e.key == Key.arrowRight) {
|
|
cursorRight();
|
|
} else if (e.key == Key.arrowLeft) {
|
|
cursorLeft();
|
|
} else if (e.key == Key.mouseLeft) {
|
|
cursor.x = e.x;
|
|
cursor.y = e.y + topline;
|
|
if (cursor.y - topline > height-1) {
|
|
cursor.y = height + topline-1;
|
|
}
|
|
if (cursor.y > buf.lines.length) {
|
|
cursor.y = cast(int) buf.lines.length-1;
|
|
}
|
|
cursor.lastX = cursor.x;
|
|
if (cursor.x > buf.lines[cursor.y].length) {
|
|
cursor.x = cast(int) buf.lines[cursor.y].length;
|
|
}
|
|
} else if (e.key == Key.ctrlS) {
|
|
if (buf.path != "") {
|
|
buf.save();
|
|
}
|
|
} else if (e.key == Key.ctrlV) {
|
|
if (Clipboard.supported) {
|
|
buf.insert(cloc, Clipboard.read());
|
|
}
|
|
} else {
|
|
if (e.ch != 0) {
|
|
buf.insert(cloc, to!string(to!dchar(e.ch)));
|
|
cursorRight();
|
|
} else if (e.key == Key.space) {
|
|
buf.insert(cursorLoc(), " ");
|
|
cursorRight();
|
|
} else if (e.key == Key.enter) {
|
|
buf.insert(cloc, "\n");
|
|
cursorDown();
|
|
cursor.x = 0;
|
|
cursor.lastX = cursor.x;
|
|
} else if (e.key == Key.backspace2) {
|
|
if (cloc > 0) {
|
|
buf.remove(cloc-1, cloc);
|
|
setCursorLoc(cloc - 1);
|
|
cursor.lastX = cursor.x;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cursor.y < topline) {
|
|
topline = cursor.y;
|
|
}
|
|
|
|
if (cursor.y > topline + height-1) {
|
|
topline = cursor.y - height-1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void display(bool drawCursor = true) {
|
|
uint x, y;
|
|
|
|
string[] lines;
|
|
if (topline + height > buf.lines.length) {
|
|
lines = buf.lines[topline .. $];
|
|
} else {
|
|
lines = buf.lines[topline .. topline + height];
|
|
}
|
|
|
|
foreach (i, line; lines) {
|
|
foreach (dchar ch; line) {
|
|
setCell(x++, y, ch, Color.basic, Color.basic);
|
|
}
|
|
y++;
|
|
x = 0;
|
|
}
|
|
|
|
if (drawCursor) {
|
|
if (cursor.y - topline < 0 || cursor.y - topline > height-1) {
|
|
hideCursor();
|
|
} else {
|
|
setCursor(cursor.x, cursor.y - topline);
|
|
}
|
|
}
|
|
|
|
sl.display();
|
|
}
|
|
}
|