diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | ProcessUtils.cpp | 155 | ||||
-rw-r--r-- | ProcessUtils.h | 15 | ||||
-rw-r--r-- | RadTerminal.cpp | 690 | ||||
-rw-r--r-- | RadTerminal.sln | 37 | ||||
-rw-r--r-- | RadTerminal.vcxproj | 112 | ||||
-rw-r--r-- | WinUtils.h | 36 | ||||
m--------- | libtsm | 0 | ||||
-rw-r--r-- | tsm.vcxproj | 170 | ||||
-rw-r--r-- | tsm.vcxproj.filters | 44 |
11 files changed, 1267 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a15991d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +Bin/ +Int/ +.vs/ +*.VC.db +*.vcxproj.user diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f4fc4c1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libtsm"] + path = libtsm + url = https://github.com/RadAd/libtsm.git diff --git a/ProcessUtils.cpp b/ProcessUtils.cpp new file mode 100644 index 0000000..8b8aa45 --- /dev/null +++ b/ProcessUtils.cpp @@ -0,0 +1,155 @@ +#include "ProcessUtils.h" +#include <Windows.h> +#include <tchar.h> +#include <vector> + +// TODO +// Support .lnk files + +namespace { + void Clear(SubProcessData* spd) + { + spd->hOutput = NULL; + spd->hInput = NULL; + spd->pi.hThread = NULL; + spd->pi.hProcess = NULL; + spd->hPC = NULL; + } + + SubProcessData CreateSubProcess(LPCTSTR cmd, COORD size, HANDLE hInput, HANDLE hOutput, bool bUseConPty) + { + SubProcessData spd = {}; + + DWORD dwCreationFlags = EXTENDED_STARTUPINFO_PRESENT; + STARTUPINFOEX si = {}; + std::vector<BYTE> attrList; + si.StartupInfo.cb = sizeof(si); + + if (bUseConPty) + { + spd.hr = CreatePseudoConsole( + size, + hInput, + hOutput, + 0, + &spd.hPC); + if (spd.hr != S_OK) + { + CleanupSubProcess(&spd); + Clear(&spd); + return spd; + } + + SIZE_T size = 0; + if (InitializeProcThreadAttributeList(NULL, 1, 0, &size)) + { + spd.hr = HRESULT_FROM_WIN32(GetLastError()); + CleanupSubProcess(&spd); + Clear(&spd); + return spd; + } + + attrList.resize(size); + si.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList.data()); + if (!InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size)) + { + spd.hr = HRESULT_FROM_WIN32(GetLastError()); + CleanupSubProcess(&spd); + Clear(&spd); + return spd; + } + if (!UpdateProcThreadAttribute( + si.lpAttributeList, + 0, + PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, + spd.hPC, sizeof(HPCON), + NULL, + NULL)) + { + spd.hr = HRESULT_FROM_WIN32(GetLastError()); + CleanupSubProcess(&spd); + Clear(&spd); + return spd; + } + } + else + { + si.StartupInfo.dwXSize = size.X; + si.StartupInfo.dwYSize = size.Y; + si.StartupInfo.dwFlags = STARTF_USESIZE | STARTF_USESTDHANDLES; + si.StartupInfo.hStdInput = hInput; + si.StartupInfo.hStdOutput = hOutput; + si.StartupInfo.hStdError = si.StartupInfo.hStdOutput; + dwCreationFlags |= CREATE_NO_WINDOW; + } + + TCHAR localcmd[MAX_PATH]; + wcscpy_s(localcmd, cmd); + if (!CreateProcess(nullptr, localcmd, nullptr, nullptr, FALSE, dwCreationFlags, nullptr, nullptr, &si.StartupInfo, &spd.pi)) + { + spd.hr = HRESULT_FROM_WIN32(GetLastError()); + CleanupSubProcess(&spd); + Clear(&spd); + return spd; + } + + spd.hr = S_OK; + return spd; + } +} + +SubProcessData CreateSubProcess(LPCTSTR cmd, COORD size, bool bUseConPty) +{ + SubProcessData spd = {}; + + HANDLE hReadPipeInput = NULL; + HANDLE hWritePipeInput = NULL; + if (spd.hr == S_OK && !CreatePipe(&hReadPipeInput, &hWritePipeInput, nullptr, 0)) + spd.hr = HRESULT_FROM_WIN32(GetLastError()); + + HANDLE hWritePipeOutput = NULL; + HANDLE hReadPipeOutput = NULL; + if (spd.hr == S_OK && !CreatePipe(&hReadPipeOutput, &hWritePipeOutput, nullptr, 0)) + spd.hr = HRESULT_FROM_WIN32(GetLastError()); + + if (spd.hr == S_OK) + spd = CreateSubProcess(cmd, size, hReadPipeInput, hWritePipeOutput, true); + + if (spd.hr == S_OK) + { + spd.hInput = hWritePipeInput; + spd.hOutput = hReadPipeOutput; + } + else + { + CloseHandle(hWritePipeInput); + CloseHandle(hReadPipeOutput); + } + + CloseHandle(hReadPipeInput); + CloseHandle(hWritePipeOutput); + + return spd; +} + +void CleanupSubProcess(const SubProcessData* spd) +{ + CloseHandle(spd->hOutput); + CloseHandle(spd->hInput); + + TerminateProcess(spd->pi.hProcess, 0xFF); + + CloseHandle(spd->pi.hThread); + CloseHandle(spd->pi.hProcess); + ClosePseudoConsole(spd->hPC); +} + +UINT GetIcon(const SubProcessData* spd, HICON *phIconLarge, HICON *phIconSmall) +{ + TCHAR exe[MAX_PATH]; + DWORD exelen = ARRAYSIZE(exe); + QueryFullProcessImageName(spd->pi.hProcess, 0, exe, &exelen); + + WORD iIcon = 0; + return ExtractIconEx(exe, 0, phIconLarge, phIconSmall, 1); +} diff --git a/ProcessUtils.h b/ProcessUtils.h new file mode 100644 index 0000000..0b6f304 --- /dev/null +++ b/ProcessUtils.h @@ -0,0 +1,15 @@ +#pragma once +#include <Windows.h> + +struct SubProcessData +{ + HRESULT hr; + HPCON hPC; + PROCESS_INFORMATION pi; + HANDLE hInput; + HANDLE hOutput; +}; + +SubProcessData CreateSubProcess(LPCTSTR cmd, COORD zsCon, bool bUseConPty); +void CleanupSubProcess(const SubProcessData* spd); +UINT GetIcon(const SubProcessData* spd, HICON *phIconLarge, HICON *phIconSmall); diff --git a/RadTerminal.cpp b/RadTerminal.cpp new file mode 100644 index 0000000..ff0d61b --- /dev/null +++ b/RadTerminal.cpp @@ -0,0 +1,690 @@ +#include <windows.h> +#include <windowsx.h> +#include <tchar.h> +#include <string> +#include "ProcessUtils.h" +#include "WinUtils.h" +#include "libtsm\src\tsm\libtsm.h" +#include "libtsm\external\xkbcommon\xkbcommon-keysyms.h" + +// TODO +// https://stackoverflow.com/questions/5966903/how-to-get-mousemove-and-mouseclick-in-bash +// scrollback +// remove polling +// unicode/emoji +// selection +// cut/paste +// drop files +// status bar +// flash window on updates + +#ifdef _UNICODE +#define tstring wstring +#else +#define tstring string +#endif + +#define PROJ_NAME TEXT("RadTerminal") + +void ShowError(HWND hWnd, LPCTSTR msg, HRESULT hr) +{ + TCHAR fullmsg[1024]; + _stprintf_s(fullmsg, _T("%s: 0x%x"), msg, hr); + MessageBox(hWnd, fullmsg, PROJ_NAME, MB_ICONERROR); +} + +#define CHECK(x, r) \ + if (!(x)) \ + { \ + ShowError(hWnd, _T(#x), HRESULT_FROM_WIN32(GetLastError())); \ + return (r); \ + } + +LRESULT CALLBACK RadTerminalWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +struct RadTerminalCreate +{ + int iFontHeight; + LPTSTR strFontFace; + LPTSTR strScheme; + COORD szCon; + std::tstring strCmd; +}; + +int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR pCmdLine, int nCmdShow) +{ + HWND hWnd = NULL; + + WNDCLASS wc = {}; + + wc.lpfnWndProc = RadTerminalWindowProc; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + //wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW); + wc.hInstance = hInstance; + wc.lpszClassName = TEXT("RadTerminal"); + + ATOM atom = NULL; + CHECK(atom = RegisterClass(&wc), EXIT_FAILURE); + + RadTerminalCreate rtc = {}; + rtc.iFontHeight = 16; + rtc.strFontFace = _T("Consolas"); + //rtc.strScheme = _T("solarized"); + rtc.szCon = { 80, 25 }; + + bool command = false; + for (int i = 1; i < __argc; ++i) + { + LPCTSTR arg = __targv[i]; + if (command) + { + rtc.strCmd += ' '; + rtc.strCmd += arg; + } + else if (_tcsicmp(arg, _T("-w")) == 0) + rtc.szCon.X = _tstoi(__targv[++i]); + else if (_tcsicmp(arg, _T("-h")) == 0) + rtc.szCon.Y = _tstoi(__targv[++i]); + else if (_tcsicmp(arg, _T("-scheme")) == 0) + rtc.strScheme = __targv[++i]; + else if (_tcsicmp(arg, _T("-font_face")) == 0) + rtc.strFontFace = __targv[++i]; + else if (_tcsicmp(arg, _T("-font_size")) == 0) + rtc.iFontHeight = _tstoi(__targv[++i]); + else + { + rtc.strCmd = arg; + command = true; + } + } + + if (rtc.strCmd.empty()) + //rtc.strCmd = _T("%COMSPEC%"); + rtc.strCmd = _T("cmd"); + + HWND hChildWnd = CreateWindowEx( + 0, + MAKEINTATOM(atom), + PROJ_NAME, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, // Parent window + NULL, // Menu + hInstance, + &rtc + ); + CHECK(hChildWnd, EXIT_FAILURE); + + ShowWindow(hChildWnd, nCmdShow); + + MSG msg = {}; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return EXIT_SUCCESS; +} + +void tsm_log(void *data, + const char *file, + int line, + const char *func, + const char *subs, + unsigned int sev, + const char *format, + va_list args) +{ + char buf[1024]; + sprintf_s(buf, "tsm_log: %s:%d %s %s %d\n", strrchr(file, '\\'), line, func, subs, sev); + OutputDebugStringA(buf); + OutputDebugStringA("tsm_log: "); + vsprintf_s(buf, format, args); + OutputDebugStringA(buf); + OutputDebugStringA("\n"); +} + +struct tsm_screen_draw_info +{ + HFONT hFontNormal; + HFONT hFontBold; + TEXTMETRIC tm; +}; + +struct tsm_screen_draw_data +{ + HDC hdc; + const tsm_screen_draw_info* info; + + POINT p; + HFONT hFont; + std::tstring drawbuf; + COLORREF bg; + COLORREF fg; +}; + +SIZE GetCellSize(const tsm_screen_draw_info* di) +{ + return { di->tm.tmAveCharWidth, di->tm.tmHeight }; +} + +POINT GetScreenPos(const tsm_screen_draw_info* di, COORD pos) +{ + SIZE sz = GetCellSize(di); + return { pos.X * sz.cx, pos.Y * sz.cy }; +} + +void Flush(tsm_screen_draw_data* const draw) +{ + if (!draw->drawbuf.empty()) + { + HFONT hFontOrig = SelectFont(draw->hdc, draw->hFont); + SetBkColor(draw->hdc, draw->bg); + SetTextColor(draw->hdc, draw->fg); + TextOut(draw->hdc, draw->p.x, draw->p.y, draw->drawbuf.c_str(), (int) draw->drawbuf.length()); + draw->drawbuf.clear(); + SelectFont(draw->hdc, hFontOrig); + } +} + +int tsm_screen_draw(struct tsm_screen *con, + uint64_t id, + const uint32_t *ch, + size_t len, + unsigned int width, + unsigned int posx, + unsigned int posy, + const struct tsm_screen_attr *attr, + tsm_age_t age, + void *data) +{ + tsm_screen_draw_data* const draw = (tsm_screen_draw_data*) data; + // TODO Underline, Inverse, Protect, Blink + const COORD pos = { (SHORT) posx, (SHORT) posy }; + const POINT p = GetScreenPos(draw->info, pos); + const HFONT hFont = attr->bold ? draw->info->hFontBold : draw->info->hFontNormal; + const COLORREF bg = RGB(attr->br, attr->bg, attr->bb); + const COLORREF fg = RGB(attr->fr, attr->fg, attr->fb); + if (hFont != draw->hFont || bg != draw->bg || fg != draw->fg || p.y != draw->p.y) + { + Flush(draw); + draw->hFont = hFont; + draw->bg = bg; + draw->fg = fg; + draw->p = p; + } + if (len > 0) + { + for (int i = 0; i < len; ++i) + { + uint32_t chr = ch[i]; + + char buf[4]; + size_t buflen = tsm_ucs4_to_utf8(chr, buf); + + wchar_t bufw[4]; + int bufwlen = MultiByteToWideChar(CP_UTF8, 0, buf, (int) buflen, bufw, ARRAYSIZE(bufw)); + + draw->drawbuf.append(bufw, bufwlen); + } + } + else + draw->drawbuf += ' '; + return 0; +} + +void tsm_vte_write(struct tsm_vte *vte, + const char *u8, + size_t len, + void *data) +{ + const HANDLE hInput = (HANDLE) data; + + while (len > 0) + { + DWORD written = 0; + WriteFile(hInput, u8, (DWORD) len, &written, nullptr); + len -= written; + } + //FlushFileBuffers(hInput); +} + +bool tsm_vte_read(struct tsm_vte *vte, HANDLE hOutput) +{ + DWORD avail = 0; + if (PeekNamedPipe(hOutput, nullptr, 0, nullptr, &avail, nullptr) && avail > 0) + { + while (avail > 0) + { + char buf[1024]; + const DWORD toread = (avail> ARRAYSIZE(buf)) ? ARRAYSIZE(buf) : avail; + DWORD read = 0; + ReadFile(hOutput, buf, toread, &read, nullptr); + tsm_vte_input(vte, buf, read); + avail -= read; + } + return true; + } + else + return false; +} + +void tsm_vte_osc(struct tsm_vte *vte, + const char *u8, + size_t len, + void *data) +{ + if (strncmp(u8, "0;", 2) == 0 || strncmp(u8, "2;", 2) == 0) + { + HWND hWnd = (HWND) data; + SetWindowTextA(hWnd, u8 + 2); + } +} + +struct RadTerminalData +{ + struct tsm_screen *screen; + struct tsm_vte *vte; + tsm_screen_draw_info draw_info; + SubProcessData spd; +}; + +void DrawCursor(HDC hdc, const RadTerminalData* const data) +{ + unsigned int flags = tsm_screen_get_flags(data->screen); + if (!(flags & TSM_SCREEN_HIDE_CURSOR)) + { + const COORD pos = { (SHORT) tsm_screen_get_cursor_x(data->screen), (SHORT) tsm_screen_get_cursor_y(data->screen) }; + RECT rc = Rect(GetScreenPos(&data->draw_info, pos), GetCellSize(&data->draw_info)); + // TODO Different cursor styles + rc.top += (rc.bottom - rc.top) * 8 / 10; + InvertRect(hdc, &rc); + } +} + +BOOL RadTerminalWindowOnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct) +{ + const RadTerminalCreate* const rtc = (RadTerminalCreate*) lpCreateStruct->lpCreateParams; + + RadTerminalData* const data = new RadTerminalData; + ZeroMemory(data, sizeof(RadTerminalData)); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data); + + data->spd = CreateSubProcess(rtc->strCmd.c_str(), rtc->szCon, true); + if (data->spd.hr != S_OK) + { + ShowError(hWnd, _T("CreateSubProcess"), data->spd.hr); + return FALSE; + } + + // TODO Report error + int e = 0; + e = tsm_screen_new(&data->screen, tsm_log, nullptr); + e = tsm_screen_resize(data->screen, rtc->szCon.X, rtc->szCon.Y); + e = tsm_vte_new(&data->vte, data->screen, tsm_vte_write, data->spd.hInput, tsm_log, nullptr); + tsm_vte_set_osc_cb(data->vte, tsm_vte_osc, hWnd); + if (rtc->strScheme != nullptr) + { + char scheme[1024]; + WideCharToMultiByte(CP_UTF8, 0, rtc->strScheme, -1, scheme, ARRAYSIZE(scheme), nullptr, nullptr); + e = tsm_vte_set_palette(data->vte, scheme); + } + + CHECK(data->draw_info.hFontNormal = CreateFont(rtc->strFontFace, rtc->iFontHeight, FW_NORMAL), FALSE); + CHECK(data->draw_info.hFontBold = CreateFont(rtc->strFontFace, rtc->iFontHeight, FW_BOLD), FALSE); + + HDC hdc = GetDC(hWnd); + SelectFont(hdc, data->draw_info.hFontNormal); + GetTextMetrics(hdc, &data->draw_info.tm); + ReleaseDC(hWnd, hdc); + + RECT r = Rect({ 0, 0 }, GetScreenPos(&data->draw_info, rtc->szCon)); + const DWORD style = GetWindowStyle(hWnd); + CHECK(AdjustWindowRect(&r, style, FALSE), FALSE); + CHECK(SetWindowPos(hWnd, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOMOVE | SWP_NOZORDER), FALSE); + + HICON hIconLarge = NULL, hIconSmall = NULL; + UINT count = GetIcon(&data->spd, &hIconLarge, &hIconSmall); + if (count > 0) + { + SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIconLarge); + SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); + } + + CHECK(SetTimer(hWnd, 1, 10, nullptr), FALSE); + CHECK(SetTimer(hWnd, 2, 500, nullptr), FALSE); + + return TRUE; +} + +void RadTerminalWindowOnDestroy(HWND hWnd) +{ + const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA); + + CleanupSubProcess(&data->spd); + + DeleteFont(data->draw_info.hFontNormal); + DeleteFont(data->draw_info.hFontBold); + + tsm_vte_unref(data->vte); + tsm_screen_unref(data->screen); + + delete data; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) nullptr); + PostQuitMessage(0); +} + +void RadTerminalWindowOnPaint(HWND hWnd) +{ + const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA); + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hWnd, &ps); + + HBRUSH hBrush = (HBRUSH) GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND); + if (hBrush != NULL) + FillRect(hdc, &ps.rcPaint, hBrush); + + tsm_screen_draw_data draw = {}; + draw.hdc = hdc; + draw.info = &data->draw_info; + draw.p.y = -1; + tsm_age_t age = tsm_screen_draw(data->screen, tsm_screen_draw, (void*) &draw); + Flush(&draw); + + HWND hActive = GetActiveWindow(); + if (hActive == hWnd) + DrawCursor(hdc, data); + + EndPaint(hWnd, &ps); +} + +void RadTerminalWindowOnKeyDown(HWND hWnd, UINT vk, BOOL fDown, int cRepeat, UINT flags) +{ + const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA); + //uint32_t ascii = MapVirtualKeyA(vk, MAPVK_VK_TO_CHAR); + BYTE KeyState[256]; + GetKeyboardState(KeyState); + + uint32_t keysym = XKB_KEY_NoSymbol; + uint32_t ascii = 0; + uint32_t unicode = ascii; + + unsigned int mods = 0; + if (KeyState[VK_SHIFT] != 0) + mods |= TSM_SHIFT_MASK; + if (KeyState[VK_SCROLL] != 0) + mods |= TSM_LOCK_MASK; + if (KeyState[VK_CONTROL] != 0) + mods |= TSM_CONTROL_MASK; + if (KeyState[VK_MENU] != 0) + mods |= TSM_ALT_MASK; + if (KeyState[VK_LWIN] != 0) + mods |= TSM_LOGO_MASK; + + UINT scan = (cRepeat >> 8); + WORD charsAscii[2] = {}; + if (ToAscii(vk, scan, KeyState, charsAscii, 0) > 0) + { + ascii = charsAscii[0]; + keysym = ascii; + } + WCHAR charsUnicode[4] = {}; + if (ToUnicode(vk, scan, KeyState, charsUnicode, ARRAYSIZE(charsUnicode), 0) > 0) + { + unicode = charsUnicode[0]; + keysym = ascii; + } + + switch (vk) + { + case VK_BACK: keysym = XKB_KEY_BackSpace; break; + case VK_TAB: keysym = XKB_KEY_Tab; break; + //case VK_: keysym = XKB_KEY_Linefeed; break; + case VK_CLEAR: keysym = XKB_KEY_Clear; break; + case VK_RETURN: keysym = XKB_KEY_Return; break; + case VK_PAUSE: keysym = XKB_KEY_Pause; break; + case VK_SCROLL: keysym = XKB_KEY_Scroll_Lock; break; + //case VK_: keysym = XKB_KEY_Sys_Req; break; + case VK_ESCAPE: keysym = XKB_KEY_Escape; break; + case VK_DELETE: keysym = XKB_KEY_Delete; break; + + case VK_HOME: keysym = XKB_KEY_Home; break; + case VK_LEFT: keysym = XKB_KEY_Left; break; + case VK_UP: keysym = XKB_KEY_Up; break; + case VK_RIGHT: keysym = XKB_KEY_Right; break; + case VK_DOWN: keysym = XKB_KEY_Down; break; + //case VK_PRIOR: keysym = XKB_KEY_Prior; break; + case VK_PRIOR: keysym = XKB_KEY_Page_Up; break; + //case VK_NEXT: keysym = XKB_KEY_Next; break; + case VK_NEXT: keysym = XKB_KEY_Page_Down; break; + case VK_END: keysym = XKB_KEY_End; break; + //case VK_: keysym = XKB_KEY_Begin; break; + + case VK_SELECT: keysym = XKB_KEY_Select; break; + case VK_PRINT: keysym = XKB_KEY_Print; break; + case VK_EXECUTE: keysym = XKB_KEY_Execute; break; + case VK_INSERT: keysym = XKB_KEY_Insert; break; + //case VK_: keysym = XKB_KEY_Undo; break; + //case VK_: keysym = XKB_KEY_Redo; break; + //case VK_: keysym = XKB_KEY_Menu; break; + //case VK_: keysym = XKB_KEY_Find; break; + case VK_CANCEL: keysym = XKB_KEY_Cancel; break; + case VK_HELP: keysym = XKB_KEY_Help; break; + //case VK_: keysym = XKB_KEY_Break; break; + //case VK_: keysym = XKB_KEY_Mode_switch; break; + //case VK_: keysym = XKB_KEY_script_switch; break; + case VK_NUMLOCK: keysym = XKB_KEY_Num_Lock; break; + + //case VK_: keysym = XKB_KEY_KP_Space; break; + //case VK_: keysym = XKB_KEY_KP_Tab; break; + //case VK_: keysym = XKB_KEY_KP_Enter; break; + //case VK_: keysym = XKB_KEY_KP_F1; break; + //case VK_: keysym = XKB_KEY_KP_F2; break; + //case VK_: keysym = XKB_KEY_KP_F3; break; + //case VK_: keysym = XKB_KEY_KP_F4; break; + //case VK_: keysym = XKB_KEY_KP_Home; break; + //case VK_: keysym = XKB_KEY_KP_Left; break; + //case VK_: keysym = XKB_KEY_KP_Up; break; + //case VK_: keysym = XKB_KEY_KP_Right; break; + //case VK_: keysym = XKB_KEY_KP_Down; break; + //case VK_: keysym = XKB_KEY_KP_Prior; break; + //case VK_: keysym = XKB_KEY_KP_Page_Up; break; + //case VK_: keysym = XKB_KEY_KP_Next; break; + //case VK_: keysym = XKB_KEY_KP_Page_Down; break; + //case VK_: keysym = XKB_KEY_KP_End 0xff9c + //case VK_: keysym = XKB_KEY_KP_Begin 0xff9d + //case VK_: keysym = XKB_KEY_KP_Insert 0xff9e + //case VK_: keysym = XKB_KEY_KP_Delete 0xff9f + //case VK_: keysym = XKB_KEY_KP_Equal 0xffbd /* Equals */ + //case VK_: keysym = XKB_KEY_KP_Multiply 0xffaa + //case VK_: keysym = XKB_KEY_KP_Add 0xffab + //case VK_: keysym = XKB_KEY_KP_Separator 0xffac /* Separator, often comma */ + //case VK_: keysym = XKB_KEY_KP_Subtract 0xffad + //case VK_: keysym = XKB_KEY_KP_Decimal 0xffae + //case VK_: keysym = XKB_KEY_KP_Divide 0xffaf + + case VK_NUMPAD0: keysym = XKB_KEY_KP_0; break; + case VK_NUMPAD1: keysym = XKB_KEY_KP_1; break; + case VK_NUMPAD2: keysym = XKB_KEY_KP_2; break; + case VK_NUMPAD3: keysym = XKB_KEY_KP_3; break; + case VK_NUMPAD4: keysym = XKB_KEY_KP_4; break; + case VK_NUMPAD5: keysym = XKB_KEY_KP_5; break; + case VK_NUMPAD6: keysym = XKB_KEY_KP_6; break; + case VK_NUMPAD7: keysym = XKB_KEY_KP_7; break; + case VK_NUMPAD8: keysym = XKB_KEY_KP_8; break; + case VK_NUMPAD9: keysym = XKB_KEY_KP_9; break; + + case VK_F1: keysym = XKB_KEY_F1; break; + case VK_F2: keysym = XKB_KEY_F2; break; + case VK_F3: keysym = XKB_KEY_F3; break; + case VK_F4: keysym = XKB_KEY_F4; break; + case VK_F5: keysym = XKB_KEY_F5; break; + case VK_F6: keysym = XKB_KEY_F6; break; + case VK_F7: keysym = XKB_KEY_F7; break; + case VK_F8: keysym = XKB_KEY_F8; break; + case VK_F9: keysym = XKB_KEY_F9; break; + case VK_F10: keysym = XKB_KEY_F10; break; + case VK_F11: keysym = XKB_KEY_F11; break; + //case VK_: keysym = XKB_KEY_L1; break; + case VK_F12: keysym = XKB_KEY_F12; break; + //case VK_: keysym = XKB_KEY_L2; break; + case VK_F13: keysym = XKB_KEY_F13; break; + //case VK_: keysym = XKB_KEY_L3; break; + case VK_F14: keysym = XKB_KEY_F14; break; + //case VK_: keysym = XKB_KEY_L4; break; + case VK_F15: keysym = XKB_KEY_F15; break; + //case VK_: keysym = XKB_KEY_L5; break; + case VK_F16: keysym = XKB_KEY_F16; break; + //case VK_: keysym = XKB_KEY_L6; break; + case VK_F17: keysym = XKB_KEY_F17; break; + //case VK_: keysym = XKB_KEY_L7; break; + case VK_F18: keysym = XKB_KEY_F18; break; + //case VK_: keysym = XKB_KEY_L8; break; + case VK_F19: keysym = XKB_KEY_F19; break; + //case VK_: keysym = XKB_KEY_L9; break; + case VK_F20: keysym = XKB_KEY_F20; break; + //case VK_: keysym = XKB_KEY_L10; break; + case VK_F21: keysym = XKB_KEY_F21; break; + //case VK_: keysym = XKB_KEY_R1; break; + case VK_F22: keysym = XKB_KEY_F22; break; + //case VK_: keysym = XKB_KEY_R2; break; + case VK_F23: keysym = XKB_KEY_F23; break; + //case VK_: keysym = XKB_KEY_R3; break; + case VK_F24: keysym = XKB_KEY_F24; break; + //case VK_: keysym = XKB_KEY_R4; break; + //case VK_: keysym = XKB_KEY_F25; break; + //case VK_: keysym = XKB_KEY_R5; break; + //case VK_: keysym = XKB_KEY_F26; break; + //case VK_: keysym = XKB_KEY_R6; break; + //case VK_: keysym = XKB_KEY_F27; break; + //case VK_: keysym = XKB_KEY_R7; break; + //case VK_: keysym = XKB_KEY_F28; break; + //case VK_: keysym = XKB_KEY_R8; break; + //case VK_: keysym = XKB_KEY_F29; break; + //case VK_: keysym = XKB_KEY_R9; break; + //case VK_: keysym = XKB_KEY_F30; break; + //case VK_: keysym = XKB_KEY_R10; break; + //case VK_: keysym = XKB_KEY_F31; break; + //case VK_: keysym = XKB_KEY_R11; break; + //case VK_: keysym = XKB_KEY_F32; break; + //case VK_: keysym = XKB_KEY_R12; break; + //case VK_: keysym = XKB_KEY_F33; break; + //case VK_: keysym = XKB_KEY_R13; break; + //case VK_: keysym = XKB_KEY_F34; break; + //case VK_: keysym = XKB_KEY_R14; break; + //case VK_: keysym = XKB_KEY_F35; break; + //case VK_: keysym = XKB_KEY_R15; break; + } + + bool b = tsm_vte_handle_keyboard(data->vte, keysym, ascii, mods, unicode); + InvalidateRect(hWnd, nullptr, TRUE); + + FORWARD_WM_KEYDOWN(hWnd, vk, cRepeat, flags, DefWindowProc); +} + +void RadTerminalWindowOnTimer(HWND hWnd, UINT id) +{ + const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA); + switch (id) + { + case 1: + { + if (tsm_vte_read(data->vte, data->spd.hOutput)) + InvalidateRect(hWnd, nullptr, TRUE); + + DWORD exitcode = 0; + if (GetExitCodeProcess(data->spd.pi.hProcess, &exitcode) && exitcode != STILL_ACTIVE) + { + DestroyWindow(hWnd); + } + } + break; + + case 2: + { + HWND hActive = GetActiveWindow(); + if (hActive == hWnd) + { + HDC hdc = GetDC(hWnd); + DrawCursor(hdc, data); + ReleaseDC(hWnd, hdc); + } + } + break; + } +} + +void RadTerminalWindowOnSize(HWND hWnd, UINT state, int cx, int cy) +{ + if (state == SIZE_RESTORED || state == SIZE_MAXIMIZED) + { + const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA); + SIZE sz = GetCellSize(&data->draw_info); + COORD size = { (SHORT) (cx / sz.cx), (SHORT) (cy / sz.cy) }; + int e = tsm_screen_resize(data->screen, size.X, size.Y); + ResizePseudoConsole(data->spd.hPC, size); + } +} + +void RadTerminalWindowOnSizing(HWND hWnd, UINT edge, LPRECT prRect) +{ + const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA); + const DWORD style = GetWindowStyle(hWnd); + UnadjustWindowRect(prRect, style, FALSE); + SIZE sz = GetCellSize(&data->draw_info); + COORD size = { (SHORT) ((prRect->right - prRect->left) / sz.cx), (SHORT) ((prRect->bottom - prRect->top) / sz.cy) }; + + switch (edge) + { + case WMSZ_LEFT: case WMSZ_TOPLEFT: case WMSZ_BOTTOMLEFT: + prRect->left = prRect->right - size.X * sz.cx; + break; + + case WMSZ_RIGHT: case WMSZ_TOPRIGHT: case WMSZ_BOTTOMRIGHT: + prRect->right = prRect->left + size.X * sz.cx; + break; + } + + switch (edge) + { + case WMSZ_TOP: case WMSZ_TOPLEFT: case WMSZ_TOPRIGHT: + prRect->top = prRect->bottom - size.Y * sz.cy; + break; + + case WMSZ_BOTTOM: case WMSZ_BOTTOMLEFT: case WMSZ_BOTTOMRIGHT: + prRect->bottom = prRect->top + size.Y * sz.cy; + break; + } + + AdjustWindowRect(prRect, style, FALSE); +} + +void RadTerminalWindowOnActivate(HWND hWnd, UINT state, HWND hwndActDeact, BOOL fMinimized) +{ + if (state == WA_INACTIVE) + InvalidateRect(hWnd, nullptr, TRUE); +} + +/* void Cls_OnSizing(HWND hwnd, UINT edge, LPRECT prRect) */ +#define HANDLE_WM_SIZING(hwnd, wParam, lParam, fn) \ + ((fn)((hwnd), (UINT)(wParam), (LPRECT)lParam), TRUE) + +LRESULT CALLBACK RadTerminalWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + HANDLE_MSG(hWnd, WM_CREATE, RadTerminalWindowOnCreate); + HANDLE_MSG(hWnd, WM_DESTROY, RadTerminalWindowOnDestroy); + HANDLE_MSG(hWnd, WM_PAINT, RadTerminalWindowOnPaint); + HANDLE_MSG(hWnd, WM_KEYDOWN, RadTerminalWindowOnKeyDown); + HANDLE_MSG(hWnd, WM_TIMER, RadTerminalWindowOnTimer); + HANDLE_MSG(hWnd, WM_SIZE, RadTerminalWindowOnSize); + HANDLE_MSG(hWnd, WM_SIZING, RadTerminalWindowOnSizing); + HANDLE_MSG(hWnd, WM_ACTIVATE, RadTerminalWindowOnActivate); + //case (WM_KEYDOWN): HANDLE_WM_KEYDOWN((hWnd), (wParam), (lParam), (RadTerminalWindowOnKeyDown)); return 1; + //HANDLE_MSG(hWnd, WM_CHAR, RadTerminalWindowOnChar); + default: return DefWindowProc(hWnd, uMsg, wParam, lParam); + } +} diff --git a/RadTerminal.sln b/RadTerminal.sln new file mode 100644 index 0000000..045b096 --- /dev/null +++ b/RadTerminal.sln @@ -0,0 +1,37 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RadTerminal", "RadTerminal.vcxproj", "{5660720B-5A4B-4F82-85C3-AE789F685218}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tsm", "tsm.vcxproj", "{F7508F50-F42C-4091-A87E-227FFE89C038}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5660720B-5A4B-4F82-85C3-AE789F685218}.Debug|x64.ActiveCfg = Debug|x64 + {5660720B-5A4B-4F82-85C3-AE789F685218}.Debug|x64.Build.0 = Debug|x64 + {5660720B-5A4B-4F82-85C3-AE789F685218}.Debug|x86.ActiveCfg = Debug|Win32 + {5660720B-5A4B-4F82-85C3-AE789F685218}.Debug|x86.Build.0 = Debug|Win32 + {5660720B-5A4B-4F82-85C3-AE789F685218}.Release|x64.ActiveCfg = Release|x64 + {5660720B-5A4B-4F82-85C3-AE789F685218}.Release|x64.Build.0 = Release|x64 + {5660720B-5A4B-4F82-85C3-AE789F685218}.Release|x86.ActiveCfg = Release|Win32 + {5660720B-5A4B-4F82-85C3-AE789F685218}.Release|x86.Build.0 = Release|Win32 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Debug|x64.ActiveCfg = Debug|x64 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Debug|x64.Build.0 = Debug|x64 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Debug|x86.ActiveCfg = Debug|Win32 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Debug|x86.Build.0 = Debug|Win32 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Release|x64.ActiveCfg = Release|x64 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Release|x64.Build.0 = Release|x64 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Release|x86.ActiveCfg = Release|Win32 + {F7508F50-F42C-4091-A87E-227FFE89C038}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/RadTerminal.vcxproj b/RadTerminal.vcxproj new file mode 100644 index 0000000..45ec2d8 --- /dev/null +++ b/RadTerminal.vcxproj @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{5660720B-5A4B-4F82-85C3-AE789F685218}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>RadTerminal</RootNamespace> + <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> + <UseDebugLibraries>true</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <OutDir>$(SolutionDir)Bin\$(Platform)$(Configuration)\</OutDir> + <IntDir>Int\$(Platform)$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PreprocessorDefinitions>_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> + <ClCompile> + <PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="ProcessUtils.cpp" /> + <ClCompile Include="RadTerminal.cpp" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="tsm.vcxproj"> + <Project>{f7508f50-f42c-4091-a87e-227ffe89c038}</Project> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <ClInclude Include="ProcessUtils.h" /> + <ClInclude Include="WinUtils.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/WinUtils.h b/WinUtils.h new file mode 100644 index 0000000..a2b630b --- /dev/null +++ b/WinUtils.h @@ -0,0 +1,36 @@ +#pragma once +#include <windows.h> + +inline BOOL UnadjustWindowRect( + LPRECT prc, + DWORD dwStyle, + BOOL fMenu) +{ + RECT rc; + SetRectEmpty(&rc); + BOOL fRc = AdjustWindowRect(&rc, dwStyle, fMenu); + if (fRc) { + prc->left -= rc.left; + prc->top -= rc.top; + prc->right -= rc.right; + prc->bottom -= rc.bottom; + } + return fRc; +} + +inline RECT Rect(POINT p1, POINT p2) +{ + return { p1.x, p1.y, p2.x, p2.y }; +} + +inline RECT Rect(POINT p1, SIZE s2) +{ + return { p1.x, p1.y, p1.x + s2.cx, p1.y + s2.cy }; +} + +inline HFONT CreateFont(LPTSTR pFontFace, int iFontHeight, int cWeight) +{ + return CreateFont(iFontHeight, 0, 0, 0, cWeight, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + DEFAULT_PITCH | FF_DONTCARE, pFontFace); +} diff --git a/libtsm b/libtsm new file mode 160000 +Subproject 9e581863c0cdb7c4055d58eae88a36ce8496d00 diff --git a/tsm.vcxproj b/tsm.vcxproj new file mode 100644 index 0000000..a9008d6 --- /dev/null +++ b/tsm.vcxproj @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <ItemGroup> + <ClInclude Include="libtsm\external\wcwidth\wcwidth.h" /> + <ClInclude Include="libtsm\external\xkbcommon\xkbcommon-keysyms.h" /> + <ClInclude Include="libtsm\src\shared\shl-array.h" /> + <ClInclude Include="libtsm\src\shared\shl-htable.h" /> + <ClInclude Include="libtsm\src\shared\shl-llog.h" /> + <ClInclude Include="libtsm\src\tsm\libtsm-int.h" /> + <ClInclude Include="libtsm\src\tsm\libtsm.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="libtsm\external\wcwidth\wcwidth.c" /> + <ClCompile Include="libtsm\src\shared\shl-htable.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-render.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-screen.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-selection.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-unicode.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-vte-charsets.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-vte.c" /> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{F7508F50-F42C-4091-A87E-227FFE89C038}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>tsm</RootNamespace> + <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <OutDir>$(SolutionDir)Bin\$(Platform)$(Configuration)\</OutDir> + <IntDir>Int\$(Platform)$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <OutDir>$(SolutionDir)Bin\$(Platform)$(Configuration)\</OutDir> + <IntDir>Int\$(Platform)$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(SolutionDir)Bin\$(Platform)$(Configuration)\</OutDir> + <IntDir>Int\$(Platform)$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)Bin\$(Platform)$(Configuration)\</OutDir> + <IntDir>Int\$(Platform)$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>BUILD_ENABLE_DEBUG;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>$(ProjectDir)\libtsm\src\shared;$(ProjectDir)\libtsm\external;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>BUILD_ENABLE_DEBUG;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>$(ProjectDir)\libtsm\src\shared;$(ProjectDir)\libtsm\external;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>$(ProjectDir)\libtsm\src\shared;$(ProjectDir)\libtsm\external;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>$(ProjectDir)\libtsm\src\shared;$(ProjectDir)\libtsm\external;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/tsm.vcxproj.filters b/tsm.vcxproj.filters new file mode 100644 index 0000000..30ff511 --- /dev/null +++ b/tsm.vcxproj.filters @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClInclude Include="libtsm\src\tsm\libtsm.h" /> + <ClInclude Include="libtsm\src\tsm\libtsm-int.h" /> + <ClInclude Include="libtsm\external\wcwidth\wcwidth.h"> + <Filter>external</Filter> + </ClInclude> + <ClInclude Include="libtsm\external\xkbcommon\xkbcommon-keysyms.h"> + <Filter>external</Filter> + </ClInclude> + <ClInclude Include="libtsm\src\shared\shl-array.h"> + <Filter>shared</Filter> + </ClInclude> + <ClInclude Include="libtsm\src\shared\shl-htable.h"> + <Filter>shared</Filter> + </ClInclude> + <ClInclude Include="libtsm\src\shared\shl-llog.h"> + <Filter>shared</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="libtsm\src\tsm\tsm-render.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-screen.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-selection.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-unicode.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-vte.c" /> + <ClCompile Include="libtsm\src\tsm\tsm-vte-charsets.c" /> + <ClCompile Include="libtsm\external\wcwidth\wcwidth.c"> + <Filter>external</Filter> + </ClCompile> + <ClCompile Include="libtsm\src\shared\shl-htable.c"> + <Filter>shared</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Filter Include="external"> + <UniqueIdentifier>{99e2687b-9168-4201-87f1-ff62c9b0680e}</UniqueIdentifier> + </Filter> + <Filter Include="shared"> + <UniqueIdentifier>{a67ec51c-945f-4b13-acf3-4187ec50ebff}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project>
\ No newline at end of file |