if Far.Cfg_Get("System","WindowMode")=="false" then return end
local NumPad={Num9="PgUp",Num3="PgDn",Num8="Up",Num2="Down",Num7="Home",Num1="End"}
local MaxBufH = 10000 --условный максимальный размер консольного буфера
local offset = {Up =-1, Down=1,
PgUp=-Far.Height, PgDn=Far.Height,
Home=-MaxBufH, End =MaxBufH}
local function far_in_window()
local f = far.AdvControl(far.Flags.ACTL_GETFARRECT)
local w = win.GetConsoleScreenBufferInfo()
local yDelta = f.Top-w.WindowTop
return yDelta==0, yDelta
end
local allPanels = "Shell QView Tree Info Search ShellAutoCompletion"
----------------------------------------------------
local ffi = require("ffi")
local C = ffi.C
ffi.cdef[[
//http://msdn.microsoft.com/library/ms683231
HANDLE GetStdHandle( //WINAPI
DWORD nStdHandle
);
//http://msdn.microsoft.com/library/ms684969
BOOL ReadConsoleOutputCharacterW( //WINAPI
HANDLE hConsoleOutput, //_In_
LPTSTR lpCharacter, //_Out_
DWORD nLength, //_In_
COORD dwReadCoord, //_In_
LPDWORD lpNumberOfCharsRead //_Out_
);
]]
local STD_OUTPUT_HANDLE = ffi.new("DWORD",-11)
local INVALID_HANDLE_VALUE = ffi.cast("HANDLE",-1)
local hConsoleOutput = C.GetStdHandle(STD_OUTPUT_HANDLE)
if hConsoleOutput==INVALID_HANDLE_VALUE then return end
local function ReadConsoleOutputCharacter(x,y,nLength)
local dwReadCoord = ffi.new("COORD",x,y);
local lpNumberOfCharsRead = ffi.new("DWORD[1]")
local lpCharacter = ffi.new("wchar_t[?]",nLength)
local res = C.ReadConsoleOutputCharacterW(hConsoleOutput,lpCharacter,nLength,dwReadCoord,lpNumberOfCharsRead)
if res>0 then
return win.Utf16ToUtf8(ffi.string(lpCharacter,lpNumberOfCharsRead[0]*ffi.sizeof"wchar_t"))
end
far.Message(debug.getinfo(2).currentline,nil,nil,"ewl")
end
local prompt= "^%a:%\\.->" --regexp for far prompt search
local limit=10000;
local function seekBuffer(str,dir)
local info = win.GetConsoleScreenBufferInfo ()
local max_y=info.SizeY-(info.WindowBottom-info.WindowTop)-1
local from,to,step
str = str or prompt
if dir and dir<0 then from,to,step = info.WindowTop-1, 0 ,-1 --CtrlUp
else from,to,step = info.WindowTop+1, info.SizeY-3, 1
end
if (from-to)*-step>limit then to=from+limit*step end
local y
for i=from, to, step do
local line = ReadConsoleOutputCharacter(0,i,info.SizeX)
if line:match(str) then y=i; break end
end
if not y then y=from; mf.beep() end
local yDelta = info.WindowTop-y
Far.Window_Scroll(-yDelta)
end
Macro { description="Seek prompt in buffer [Up or Down]";
area="Common"; key="CtrlUp CtrlDown"; priority=50;
condition=function()
return allPanels:find(Area.Current) and not APanel.Visible or not far_in_window()
end;
action=function()
seekBuffer(prompt,akey(1)=="CtrlUp" and -1 or 1)
end;
}
--------------------------------------------------------------------
Macro { description="Autohide panels when scrolling up with CtrlAlt<Key>";
area=allPanels; key="/^LCtrlLAlt(Num[789]|Up|PgUp|Home)$/"; priority=60;
condition=function() return APanel.Visible and far_in_window() end;
action=function() Keys("CtrlO") end;
}
Macro { description="Autoshow panels when scrolling down with CtrlAlt<Key>";
area=allPanels; key="/^LCtrlLAlt(Num[123]|Down|PgDn|End)$/"; priority=60;
condition=function() return not APanel.Visible and far_in_window() end;
action=function() Keys("CtrlO") end;
}
-------------------------------------------------------------------------------
NoMacro { description="Scroll Console Buffer in Editor (steals CtrlAlt<Keys>)";
area="Editor"; key="/^LCtrlLAlt(Num[123789]|Up|Down|PgUp|PgDn|Home|End)$/";
condition=far_in_window;
action=function()
local key = akey(1):match("CtrlAlt(.+)")
offset.PgUp=-Far.Height; offset.PgDn=Far.Height
Far.Window_Scroll(offset[NumPad[key]] or offset[key])
end;
}
Macro { description="Scroll Console Buffer when Panels is hidden";
area="Common"; key="/^(LCtrlLAlt)?(Num[123789]|Up|Down|PgUp|PgDn|Home|End)$/"; priority=50;
condition=function() --reserve some keys for cmdline
return (allPanels:find(Area.Current) and not APanel.Visible and CmdLine.Empty) or not far_in_window()
end;
action=function()
local key = akey(1):match("CtrlAlt(.+)") or akey(1)
offset.PgUp=-Far.Height; offset.PgDn=Far.Height
Far.Window_Scroll(offset[NumPad[key]] or offset[key])
end;
}
Macro { description="Scroll Console Buffer in UserScreen";
area="Editor Viewer Help Dialog DialogAutoCompletion Disks FindFolder Menu MainMenu UserMenu";
key="CtrlO";
action=function()
offset.PgUp=-Far.Height; offset.PgDn=Far.Height
panel.GetUserScreen()
local BreakKey = {CtrlO=true, Esc=true, Break=true}
local key
while not BreakKey[key] do
key=mf.waitkey()
if key=="CtrlUp" or key=="CtrlDown" then
seekBuffer(prompt,key=="CtrlUp" and -1 or 1)
else
key=key:match("CtrlAlt(.+)") or key
Far.Window_Scroll(offset[NumPad[key]] or offset[key])
end
end
far.AdvControl (far.Flags.ACTL_REDRAWALL)
end;
}
Macro { description="Esc - scroll buffer to Far window";
area="Common"; key="Esc"; priority=60;
condition=function()
local in_window,yDelta = far_in_window()
if not in_window then
Far.Window_Scroll(yDelta)
return true
end
end;
action=function() end;
}