local ffi = require("ffi")
local FALSE, C, U, P = 0, ffi.C, ffi.load("user32"), ffi.load("psapi")
local ONLY_CONSOLE = true
ffi.cdef([[
HWND FindWindowExA(HWND Parent, HWND ChildAfter, LPCSTR Class, LPCSTR Title);
UINT GetWindowModuleFileNameA(HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax);
BOOL IsWindowVisible(HWND hWnd);
BOOL IsIconic(HWND hWnd);
BOOL SetForegroundWindow(HWND hWnd);
BOOL ShowWindow(HWND hwnd, int nCmdShow);
DWORD GetCurrentProcessId(void);
UINT GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId);
void ExitProcess(uint32_t uExitCode);
DWORD GetProcessImageFileNameA(HANDLE hProcess, LPSTR lpImageFileName, DWORD nSize);
HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
BOOL CloseHandle(HANDLE handle);
]])
Macro {
description = "Activate already running far instead of starting new one";
area="Shell"; flags="RunAfterFARStart";
action=function()
local SW_SHOW , PROCESS_QUERY_INFORMATION = 5, 0x0400
local console_class = ONLY_CONSOLE and "ConsoleWindowClass\0" or nil
local text_size = 512
local text = ffi.new("char[?]", text_size)
local pid = ffi.new("DWORD[1]")
local this_pid = C.GetCurrentProcessId();
local wnd = nil
repeat
wnd = U.FindWindowExA(nil, wnd, console_class, nil);
if wnd ~= ffi.NULL and U.IsWindowVisible(wnd) ~= FALSE then
local tid = C.GetWindowThreadProcessId(wnd, pid);
if tid > 0 and pid[0] > 0 and pid[0] ~= this_pid then
local n = U.GetWindowModuleFileNameA(wnd, text, text_size);
if n <= 0 then
local hProcess = C.OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid[0]);
if hProcess ~= ffi.NULL then
n = P.GetProcessImageFileNameA(hProcess, text, text_size);
C.CloseHandle(hProcess);
end
end
if n > 8 and ffi.string(text):sub(-8):lower() == "\\far.exe" then
if U.IsIconic(wnd) ~= FALSE then U.ShowWindow(wnd, SW_SHOW); end
U.SetForegroundWindow(wnd);
C.ExitProcess(0);
end
end
end
until wnd == ffi.NULL
end
}