Обновил тут Far 3 с build 5210 до 5888, пока полёт нормальный, редактор стал сильно быстрее, но не понравилось вот что:
начиная с версии build 5287 выкинули опцию "Highlight column separators", а я к ней привык.
Сразу захотелось вернуть как было, по-домашнему. Разумеется, скриптом на Lua.
Ловить отрисовку панелей чтоб перекрашивать как надо не вышло, нет API: https://bugs.farmanager.com/view.php?id=2826
Пришлось использовать адский приём перезаписи кода Far'а в памяти.
Code: Select all
--[[
By Grom PE, 30 Jan 2022, public domain.
This script tries to revert "Highlight column separators" removed in the build 5287:
https://github.com/FarGroup/FarManager/commit/4cdb38e0aefb7cf70ed7b96382b963dcd9e32fd3#diff-6384e9562f170aece91803dbf0cf14f0af8a68d7e1646d1ee389cdb23ef78026
drkns 14.10.2018 13:21:57 +0100 - build 5287
1. Убраны добавленные в 2145 опции "Highlight column separators" и "Double stripe separators".
Разделители всегда используют цвет Panel.Box и удваиваются между полосами.
filelist.cpp
void FileList::HighlightBorder(int Level, int ListPos) const
{
if (Level == m_ColumnsInStripe)
{
SetColor(COL_PANELBOX);
}
else
{
const auto FileColor = GetShowColor(ListPos, true);
auto Color = colors::PaletteColorToFarColor(COL_PANELBOX);
Color.BackgroundColor = FileColor.BackgroundColor;
Color.SetBg4Bit(FileColor.IsBg4Bit());
SetColor(Color); // Need to change this to SetColor(FileColor);
}
}
]]
local _, _, _, build = far.AdvControl("ACTL_GETFARMANAGERVERSION", true)
local ffi = require("ffi")
ffi.cdef[[
BOOL VirtualProtect(
LPVOID lpAddress, // address of region of committed pages
SIZE_T dwSize, // size of the region
DWORD flNewProtect, // desired access protection
PDWORD lpflOldProtect // address of variable to get old protection
);
HMODULE GetModuleHandleW(
LPCTSTR lpModuleName // address of module name to return handle for
);
]]
local PAGE_READWRITE = 4
local PAGE_EXECUTE_READWRITE = 0x40
local HB_funcname = {
["x86"] = "?HighlightBorder@FileList@@ABEXHH@Z",
["x64"] = "?HighlightBorder@FileList@@AEBAXHH@Z",
}
HB_funcname = HB_funcname[jit.arch]
function get_HB_offset_from_Farmap()
local mapfn = win.GetEnv("FARHOME") .. "\\Far.map"
if mf.fexist(mapfn) then
for line in io.lines(mapfn) do
if string.find(line, HB_funcname) then
local s = string.gsub(line, " %w+:%w+ +%S+ (%w+) f +.+", "%1")
if #s == 8 then
return tonumber(s, 16)
else -- handle 64-bit number as tonumber(?, 16) is limited to 32 bits
local lower = tonumber(s:sub(#s-8+1), 16)
local upper = tonumber(s:sub(1,#s-8), 16)
return lower + upper * 256^4
end
end
end
end
end
function writemem(ptr, str)
local b = ffi.cast("char*", ptr)
for i = 1,#str do
b[i-1] = string.byte(str, i)
end
end
function patch_x86()
local HB_offsets = {[5300] = 0x594f30, [5888] = 0x5b7690}
if not HB_offsets[build] then
HB_offsets[build] = get_HB_offset_from_Farmap()
end
if not HB_offsets[build] then return end
local farAddress = tonumber(ffi.cast("SIZE_T", ffi.C.GetModuleHandleW(nil)))
-- assuming image base is 0x400000
local HighlightBorder_addr = farAddress + HB_offsets[build] - 0x400000
local HighlightBorder_caddr = ffi.cast("void*", HighlightBorder_addr)
local size = 232
local p1 = ffi.cast("void*", HighlightBorder_addr + 0x9F)
local p2 = ffi.cast("void*", HighlightBorder_addr + 0xE2)
--[[
FileColor.ForegroundColor = [esp+0x18]
CurColor.ForegroundColor = edi
+0x9F: 8B 79 08 -> EB 41 90
mov edi,[ecx+8] -> jmps free_space; nop
+0xE2: CC CC CC CC CC CC -> 8B 7C 24 18 EB BA
int 3 -> mov edi, [esp+0x18]; jmps continue
]]
if ffi.string(p1, 3) ~= "\x8B\x79\x08" or ffi.string(p2, 6) ~= string.rep("\xCC", 6) then return end
local oldProtect = ffi.new("DWORD[?]", 1)
local res = ffi.C.VirtualProtect(HighlightBorder_caddr, size, PAGE_EXECUTE_READWRITE, oldProtect) -- replace with PAGE_READWRITE if this causes error
if res == 0 then return end
writemem(p1, "\xEB\x41\x90")
writemem(p2, "\x8B\x7c\x24\x18\xEB\xBA")
res = ffi.C.VirtualProtect(HighlightBorder_caddr, size, oldProtect[0], oldProtect)
if res == 0 then
-- error
end
end
function patch_x64()
local HB_offsets = {[5300] = 0x1401efcf0, [5888] = 0x140220e90}
if not HB_offsets[build] then
HB_offsets[build] = get_HB_offset_from_Farmap()
end
if not HB_offsets[build] then return end
local farAddress = tonumber(ffi.cast("SIZE_T", ffi.C.GetModuleHandleW(nil)))
-- assuming image base is 0x140000000
local HighlightBorder_addr = farAddress + HB_offsets[build] - 0x140000000
local HighlightBorder_caddr = ffi.cast("void*", HighlightBorder_addr)
local size = 192
local p1 = ffi.cast("void*", HighlightBorder_addr + 0x87)
local p2 = ffi.cast("void*", HighlightBorder_addr + 0xB4)
--[[
FileColor.ForegroundColor = [rsp+0x40]
CurColor.ForegroundColor = [rsp+0x28]
+0x87: D0 E8 -> EB 2B
shr al,1 -> jmps free_space
+0xB4: CC CC CC CC CC CC CC CC CC CC CC CC -> 8B 54 24 40 89 54 24 28 D0 E8 EB C9
int 3 -> mov edx, [rsp+0x40]; mov [rsp+0x28], edx; shr al,1; jmps continue
]]
if ffi.string(p1, 2) ~= "\xD0\xE8" or ffi.string(p2, 12) ~= string.rep("\xCC", 12) then return end
local oldProtect = ffi.new("DWORD[?]", 1)
local res = ffi.C.VirtualProtect(HighlightBorder_caddr, size, PAGE_EXECUTE_READWRITE, oldProtect) -- replace with PAGE_READWRITE if this causes error
if res == 0 then return end
writemem(p1, "\xEB\x2B")
writemem(p2, "\x8B\x54\x24\x40\x89\x54\x24\x28\xD0\xE8\xEB\xC9")
res = ffi.C.VirtualProtect(HighlightBorder_caddr, size, oldProtect[0], oldProtect)
if res == 0 then
-- error
end
end
if build >= 5287 then
if jit.arch == "x86" then
patch_x86()
elseif jit.arch == "x64" then
patch_x64()
end
end
- Panels_revert_5287_Highlight.lua
- (5.42 KiB) Downloaded 119 times
Как использовать: закинуть в папку
%FARPROFILE%\Macros\scripts
, перезапустить Far.Проверялось на Windows 7 x64, Far 3 x86, x64; build 5300, build 5888, build 5957.