moved code from header to source files
This commit is contained in:
170
src/windows.c
Executable file
170
src/windows.c
Executable file
@@ -0,0 +1,170 @@
|
||||
#include "tim.h"
|
||||
|
||||
#ifdef TIM_WINDOWS
|
||||
|
||||
i64 tim_time_usec(void) {
|
||||
LARGE_INTEGER ticks = {0};
|
||||
LARGE_INTEGER freq = {0};
|
||||
QueryPerformanceCounter(&ticks);
|
||||
QueryPerformanceFrequency(&freq);
|
||||
return 1000000 * ticks.QuadPart / freq.QuadPart;
|
||||
}
|
||||
|
||||
void tim_write_str(cstr s, i32 size) {
|
||||
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
WriteFile(h, s, size, NULL, NULL);
|
||||
FlushFileBuffers(h);
|
||||
}
|
||||
|
||||
void tim_update_screen_size(void) {
|
||||
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
|
||||
if (GetConsoleScreenBufferInfo(hout, &csbi) == 0) {
|
||||
printf("ERROR: can't get console buffer size\n");
|
||||
exit(1);
|
||||
}
|
||||
i32 w = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
i32 h = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
tim.resized = (u32)(w * h) <= TIM_MAX_CELLS && (w != tim.w || h != tim.h);
|
||||
if (tim.resized) {
|
||||
tim.w = tim.scopes[0].w = w;
|
||||
tim.h = tim.scopes[0].h = h;
|
||||
tim.window = csbi.srWindow;
|
||||
}
|
||||
}
|
||||
|
||||
void tim_init_terminal(void) {
|
||||
DWORD mode = 0;
|
||||
HANDLE hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
GetConsoleMode(hin, &tim.mode_in); // get current input mode
|
||||
mode = tim.mode_in; //
|
||||
mode &= ~ENABLE_ECHO_INPUT; // disable echo
|
||||
mode &= ~ENABLE_LINE_INPUT; // disable line buffer
|
||||
// TODO: enable ctrl-c again
|
||||
mode &= ~ENABLE_PROCESSED_INPUT; // disable ctrl-c
|
||||
mode |= ENABLE_WINDOW_INPUT; // enable resize event
|
||||
mode |= ENABLE_MOUSE_INPUT; // enable mouse event
|
||||
mode |= ENABLE_EXTENDED_FLAGS; // for ENABLE_QUICK_EDIT
|
||||
mode &= ~ENABLE_QUICK_EDIT_MODE; // disable select mode
|
||||
SetConsoleMode(hin, mode); // set input mode
|
||||
//
|
||||
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); //
|
||||
GetConsoleMode(hout, &tim.mode_out); // get current output mode
|
||||
mode = tim.mode_out; //
|
||||
mode |= ENABLE_PROCESSED_OUTPUT; // enable ascii sequences
|
||||
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; // enable vt sequences
|
||||
SetConsoleMode(hout, mode); // set output mode
|
||||
//
|
||||
tim.cp_in = GetConsoleCP(); // get current code page
|
||||
tim.cp_out = GetConsoleOutputCP(); //
|
||||
SetConsoleCP(CP_UTF8); // set utf8 in/out code page
|
||||
SetConsoleOutputCP(CP_UTF8); //
|
||||
tim_write_str(S("\33[?1049h")); // use alternate buffer
|
||||
tim_update_screen_size(); //
|
||||
}
|
||||
|
||||
void tim_reset_terminal(void) {
|
||||
tim_write_str(S("\33[m")); // reset colors
|
||||
tim_write_str(S("\33[?25h")); // show cursor
|
||||
tim_write_str(S("\33[?1049l")); // exit alternate buffer
|
||||
HANDLE hin = GetStdHandle(STD_INPUT_HANDLE); //
|
||||
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); //
|
||||
SetConsoleMode(hin, tim.mode_in); // set original mode
|
||||
SetConsoleMode(hout, tim.mode_out); //
|
||||
SetConsoleCP(tim.cp_in); // set original code page
|
||||
SetConsoleOutputCP(tim.cp_out); //
|
||||
}
|
||||
|
||||
void tim_read_event(i32 timeout_ms) {
|
||||
TimEvent* e = &tim.event;
|
||||
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
||||
const i8 key_table[256] = {
|
||||
[VK_BACK] = TimKey_Backspace,
|
||||
[VK_TAB] = TimKey_Tab,
|
||||
[VK_RETURN] = TimKey_Enter,
|
||||
[VK_ESCAPE] = TimKey_Escape,
|
||||
[VK_PRIOR] = TimKey_PageUp,
|
||||
[VK_NEXT] = TimKey_PageDown,
|
||||
[VK_END] = TimKey_End,
|
||||
[VK_HOME] = TimKey_Home,
|
||||
[VK_LEFT] = TimKey_Left,
|
||||
[VK_UP] = TimKey_Up,
|
||||
[VK_RIGHT] = TimKey_Right,
|
||||
[VK_DOWN] = TimKey_Down,
|
||||
[VK_INSERT] = TimKey_Insert,
|
||||
[VK_DELETE] = TimKey_Delete,
|
||||
};
|
||||
|
||||
while (true) {
|
||||
memset(e, 0, sizeof(*e));
|
||||
// In cmd.exe the cursor somtimes reappears. This reliably hides it.
|
||||
tim_write_str(S("\33[?25l"));
|
||||
|
||||
DWORD r = WaitForSingleObject(h, timeout_ms);
|
||||
if (r == WAIT_TIMEOUT) {
|
||||
e->type = TimEvent_Draw;
|
||||
tim_update_screen_size(); // workaround, see WINDOW_BUFFER_SIZE_EVENT
|
||||
return;
|
||||
} else if (r != WAIT_OBJECT_0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// received input
|
||||
INPUT_RECORD rec = {0};
|
||||
DWORD n = 0;
|
||||
ReadConsoleInput(h, &rec, 1, &n);
|
||||
|
||||
switch (rec.EventType) {
|
||||
case KEY_EVENT: {
|
||||
if (!rec.Event.KeyEvent.bKeyDown) {
|
||||
// only interested in key press
|
||||
continue;
|
||||
}
|
||||
i32 key = key_table[(u8)rec.Event.KeyEvent.wVirtualKeyCode];
|
||||
WCHAR chr = rec.Event.KeyEvent.uChar.UnicodeChar;
|
||||
if (!key && chr < ' ') {
|
||||
// non printable key
|
||||
continue;
|
||||
}
|
||||
tim_update_screen_size(); // workaround, see WINDOW_BUFFER_SIZE_EVENT
|
||||
e->type = TimEvent_Key;
|
||||
if (key) {
|
||||
e->key = key;
|
||||
return;
|
||||
}
|
||||
e->key = chr;
|
||||
WideCharToMultiByte(CP_UTF8, 0, &chr, 1, e->s, sizeof(e->s),
|
||||
NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
case MOUSE_EVENT: {
|
||||
bool move = rec.Event.MouseEvent.dwEventFlags & ~DOUBLE_CLICK;
|
||||
bool left = rec.Event.MouseEvent.dwButtonState &
|
||||
FROM_LEFT_1ST_BUTTON_PRESSED;
|
||||
if (move || !left) {
|
||||
// ignore move events and buttons other than left
|
||||
continue;
|
||||
}
|
||||
tim_update_screen_size(); // workaround, see WINDOW_BUFFER_SIZE_EVENT
|
||||
e->type = TimEvent_Mouse;
|
||||
e->key = TimKey_MouseButtonLeft;
|
||||
e->x = rec.Event.MouseEvent.dwMousePosition.X - tim.window.Left;
|
||||
e->y = rec.Event.MouseEvent.dwMousePosition.Y - tim.window.Top;
|
||||
return;
|
||||
}
|
||||
|
||||
case WINDOW_BUFFER_SIZE_EVENT:
|
||||
e->type = TimEvent_Draw;
|
||||
// cmd.exe screen buffer and window size are separate, making this
|
||||
// event a bit unreliable. Effectively it is only emitted when the
|
||||
// terminal width changes and not for the height. As a workaround
|
||||
// the screen size is updated every time an event is emitted.
|
||||
tim_update_screen_size();
|
||||
return;
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
#endif // TIM_WINDOWS
|
||||
Reference in New Issue
Block a user