mirror of
https://github.com/Rayerd/dfl.git
synced 2025-04-26 04:59:55 +03:00
Fixed SharedControl class, Control.invoke method and Control.delayInvoke method
This commit is contained in:
parent
bdd8449947
commit
bf168783ef
3 changed files with 228 additions and 166 deletions
|
@ -1866,20 +1866,18 @@ extern(Windows) LRESULT dflWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
|
|||
{
|
||||
switch(wparam)
|
||||
{
|
||||
case WPARAM_DFL_INVOKE:
|
||||
case WPARAM_DFL_INVOKE_PARAMS:
|
||||
{
|
||||
InvokeData* pinv;
|
||||
pinv = cast(InvokeData*)lparam;
|
||||
DflInvokeParam* p = cast(DflInvokeParam*)lparam;
|
||||
try
|
||||
{
|
||||
pinv.result = pinv.dg(pinv.args);
|
||||
p.fp(Application.lookupHwnd(hwnd), p.params.ptr[0 .. p.nparams]);
|
||||
}
|
||||
catch(DThrowable e)
|
||||
{
|
||||
//Application.onThreadException(e);
|
||||
try
|
||||
{
|
||||
pinv.exception = e;
|
||||
p.exception = e;
|
||||
}
|
||||
catch(DThrowable e2)
|
||||
{
|
||||
|
@ -1889,20 +1887,18 @@ extern(Windows) LRESULT dflWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
|
|||
}
|
||||
return LRESULT_DFL_INVOKE;
|
||||
|
||||
case WPARAM_DFL_INVOKE_SIMPLE:
|
||||
case WPARAM_DFL_INVOKE_NOPARAMS:
|
||||
{
|
||||
InvokeSimpleData* pinv;
|
||||
pinv = cast(InvokeSimpleData*)lparam;
|
||||
DflInvokeParam* p = cast(DflInvokeParam*)lparam;
|
||||
try
|
||||
{
|
||||
pinv.dg();
|
||||
p.fp(Application.lookupHwnd(hwnd), p.params);
|
||||
}
|
||||
catch(DThrowable e)
|
||||
{
|
||||
//Application.onThreadException(e);
|
||||
try
|
||||
{
|
||||
pinv.exception = e;
|
||||
p.exception = e;
|
||||
}
|
||||
catch(DThrowable e2)
|
||||
{
|
||||
|
@ -1912,21 +1908,24 @@ extern(Windows) LRESULT dflWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
|
|||
}
|
||||
return LRESULT_DFL_INVOKE;
|
||||
|
||||
case WPARAM_DFL_DELAY_INVOKE:
|
||||
try
|
||||
case WPARAM_DFL_DELAY_INVOKE_NOPARAMS:
|
||||
{
|
||||
(cast(void function())lparam)();
|
||||
}
|
||||
catch(DThrowable e)
|
||||
{
|
||||
Application.onThreadException(e);
|
||||
DflInvokeParam* p = cast(DflInvokeParam*)lparam;
|
||||
try
|
||||
{
|
||||
p.fp(Application.lookupHwnd(hwnd), p.params);
|
||||
}
|
||||
catch(DThrowable e)
|
||||
{
|
||||
Application.onThreadException(e);
|
||||
}
|
||||
dfl.internal.clib.free(p);
|
||||
}
|
||||
break;
|
||||
|
||||
case WPARAM_DFL_DELAY_INVOKE_PARAMS:
|
||||
{
|
||||
DflInvokeParam* p;
|
||||
p = cast(DflInvokeParam*)lparam;
|
||||
DflInvokeParam* p = cast(DflInvokeParam*)lparam;
|
||||
try
|
||||
{
|
||||
p.fp(Application.lookupHwnd(hwnd), p.params.ptr[0 .. p.nparams]);
|
||||
|
@ -2044,36 +2043,20 @@ else
|
|||
|
||||
enum LRESULT LRESULT_DFL_INVOKE = 0x95FADF; // Magic number.
|
||||
|
||||
|
||||
struct InvokeData
|
||||
{
|
||||
Object delegate(Object[]) dg;
|
||||
Object[] args;
|
||||
Object result;
|
||||
DThrowable exception = null;
|
||||
}
|
||||
|
||||
|
||||
struct InvokeSimpleData
|
||||
{
|
||||
void delegate() dg;
|
||||
DThrowable exception = null;
|
||||
}
|
||||
|
||||
|
||||
UINT wmDfl;
|
||||
|
||||
enum: WPARAM
|
||||
{
|
||||
WPARAM_DFL_INVOKE = 78,
|
||||
WPARAM_DFL_DELAY_INVOKE = 79,
|
||||
WPARAM_DFL_INVOKE_PARAMS = 78,
|
||||
WPARAM_DFL_DELAY_INVOKE_NOPARAMS = 79,
|
||||
WPARAM_DFL_DELAY_INVOKE_PARAMS = 80,
|
||||
WPARAM_DFL_INVOKE_SIMPLE = 81,
|
||||
WPARAM_DFL_INVOKE_NOPARAMS = 81,
|
||||
}
|
||||
|
||||
struct DflInvokeParam
|
||||
{
|
||||
void function(Control, size_t[]) fp;
|
||||
DThrowable exception;
|
||||
size_t nparams;
|
||||
size_t[1] params;
|
||||
}
|
||||
|
|
|
@ -3614,16 +3614,37 @@ class Control: DObject, IWindow // docmain
|
|||
if(!hwnd)
|
||||
badInvokeHandle();
|
||||
|
||||
InvokeData inv;
|
||||
inv.dg = dg;
|
||||
inv.args = args;
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
if(LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE, cast(LRESULT)&inv))
|
||||
static struct DelegateInvokeParam
|
||||
{
|
||||
Object delegate(Object[]) dg;
|
||||
Object result;
|
||||
Object[] args;
|
||||
}
|
||||
|
||||
static void funcEntry(Control c, size_t[] p)
|
||||
{
|
||||
auto dip = cast(DelegateInvokeParam*)p[0];
|
||||
dip.result = dip.dg(dip.args);
|
||||
}
|
||||
|
||||
DelegateInvokeParam dip;
|
||||
dip.dg = dg;
|
||||
dip.args = args;
|
||||
|
||||
DflInvokeParam dflInvokeParam;
|
||||
dflInvokeParam.fp = &funcEntry;
|
||||
dflInvokeParam.exception = null;
|
||||
dflInvokeParam.nparams = args.length;
|
||||
dflInvokeParam.params[0] = cast(size_t)&dip;
|
||||
|
||||
if(LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE_PARAMS, cast(LPARAM)&dflInvokeParam))
|
||||
throw new DflException("Invoke failure");
|
||||
if(inv.exception)
|
||||
throw inv.exception;
|
||||
if(dflInvokeParam.exception)
|
||||
throw dflInvokeParam.exception;
|
||||
|
||||
return inv.result;
|
||||
return dip.result;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
|
@ -3632,13 +3653,32 @@ class Control: DObject, IWindow // docmain
|
|||
if(!hwnd)
|
||||
badInvokeHandle();
|
||||
|
||||
InvokeSimpleData inv;
|
||||
inv.dg = dg;
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
static struct DelegateInvokeParam
|
||||
{
|
||||
void delegate() dg;
|
||||
}
|
||||
|
||||
static void funcEntry(Control c, size_t[] p)
|
||||
{
|
||||
auto dip = cast(DelegateInvokeParam*)p[0];
|
||||
dip.dg();
|
||||
}
|
||||
|
||||
DelegateInvokeParam dip;
|
||||
dip.dg = dg;
|
||||
|
||||
DflInvokeParam dflInvokeParam;
|
||||
dflInvokeParam.fp = &funcEntry;
|
||||
dflInvokeParam.exception = null;
|
||||
dflInvokeParam.nparams = 0;
|
||||
dflInvokeParam.params[0] = cast(size_t)&dip;
|
||||
|
||||
if(LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE_SIMPLE, cast(LRESULT)&inv))
|
||||
if(LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE_NOPARAMS, cast(LPARAM)&dflInvokeParam))
|
||||
throw new DflException("Invoke failure");
|
||||
if(inv.exception)
|
||||
throw inv.exception;
|
||||
if(dflInvokeParam.exception)
|
||||
throw dflInvokeParam.exception;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3654,10 +3694,24 @@ class Control: DObject, IWindow // docmain
|
|||
if(!hwnd)
|
||||
badInvokeHandle();
|
||||
|
||||
assert(!invokeRequired);
|
||||
|
||||
static assert(fn.sizeof <= LPARAM.sizeof);
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE, cast(LPARAM)fn);
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
static void funcEntry(Control c, size_t[] p)
|
||||
{
|
||||
auto func = cast(void function())p[0];
|
||||
func();
|
||||
}
|
||||
|
||||
DflInvokeParam* dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
|
||||
if(!dflInvokeParam)
|
||||
throw new OomException();
|
||||
|
||||
dflInvokeParam.fp = &funcEntry;
|
||||
dflInvokeParam.exception = null;
|
||||
dflInvokeParam.nparams = 0;
|
||||
dflInvokeParam.params[0] = cast(size_t)fn;
|
||||
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_NOPARAMS, cast(LPARAM)dflInvokeParam);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
|
@ -3671,22 +3725,19 @@ class Control: DObject, IWindow // docmain
|
|||
if(!hwnd)
|
||||
badInvokeHandle();
|
||||
|
||||
assert(!invokeRequired);
|
||||
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
DflInvokeParam* p;
|
||||
p = cast(DflInvokeParam*)dfl.internal.clib.malloc(
|
||||
(DflInvokeParam.sizeof - size_t.sizeof)
|
||||
+ params.length * size_t.sizeof);
|
||||
if(!p)
|
||||
DflInvokeParam* dflInvokeParams = cast(DflInvokeParam*)malloc(
|
||||
DflInvokeParam.sizeof - size_t.sizeof + params.length * size_t.sizeof);
|
||||
if(!dflInvokeParams)
|
||||
throw new OomException();
|
||||
|
||||
p.fp = fn;
|
||||
p.nparams = params.length;
|
||||
p.params.ptr[0 .. params.length] = params[];
|
||||
dflInvokeParams.fp = fn;
|
||||
dflInvokeParams.exception = null;
|
||||
dflInvokeParams.nparams = params.length;
|
||||
dflInvokeParams.params.ptr[0 .. params.length] = params[];
|
||||
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, cast(LPARAM)p);
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, cast(LPARAM)dflInvokeParams);
|
||||
}
|
||||
|
||||
deprecated alias beginInvoke = delayInvoke;
|
||||
|
@ -8323,15 +8374,3 @@ class ContainerControl: ScrollableControl, IContainerControl // docmain
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private template hasLocalAliasing(T...)
|
||||
{
|
||||
import std.traits, std.typecons;
|
||||
|
||||
static if( !T.length )
|
||||
enum hasLocalAliasing = false;
|
||||
else
|
||||
enum hasLocalAliasing = std.traits.hasLocalAliasing!(T[0]) ||
|
||||
dfl.control.hasLocalAliasing!(T[1 .. $]);
|
||||
}
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
///
|
||||
module dfl.sharedcontrol;
|
||||
|
||||
private import dfl.base;
|
||||
private import dfl.control;
|
||||
private import dfl.application;
|
||||
|
||||
private import dfl.internal.winapi;
|
||||
private import dfl.internal.dlib;
|
||||
private import dfl.internal.clib;
|
||||
private import dfl.internal.clib : malloc, free;
|
||||
|
||||
///
|
||||
shared class SharedControl
|
||||
|
@ -18,72 +19,49 @@ shared class SharedControl
|
|||
private:
|
||||
Control _ctrl;
|
||||
|
||||
LPARAM makeParam(ARGS...)(void function(Control, ARGS) fn, Tuple!(ARGS)* args)
|
||||
void makeParam(ARGS...)(void function(Control, ARGS) func, ARGS args, DflInvokeParam* dflInvokeParam)
|
||||
if (ARGS.length)
|
||||
{
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
static struct InvokeParam
|
||||
static struct FunctionInvokeParam
|
||||
{
|
||||
void function(Control, ARGS) fn;
|
||||
void function(Control, ARGS) func;
|
||||
ARGS args;
|
||||
}
|
||||
alias malloc = dfl.internal.clib.malloc;
|
||||
alias free = dfl.internal.clib.free;
|
||||
|
||||
auto param = cast(InvokeParam*)malloc(InvokeParam.sizeof);
|
||||
param.fn = fn;
|
||||
param.args = args.field;
|
||||
|
||||
if (!param)
|
||||
|
||||
auto invokeParam = cast(FunctionInvokeParam*)malloc(FunctionInvokeParam.sizeof);
|
||||
if (!invokeParam)
|
||||
throw new OomException();
|
||||
invokeParam.func = func;
|
||||
invokeParam.args = args;
|
||||
|
||||
auto p = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
|
||||
|
||||
if (!p)
|
||||
throw new OomException();
|
||||
|
||||
|
||||
static void fnentry(Control c, size_t[] p)
|
||||
static void funcEntry(Control c, size_t[] p)
|
||||
{
|
||||
auto param = cast(InvokeParam*)p[0];
|
||||
param.fn(c, param.args);
|
||||
auto param = cast(FunctionInvokeParam*)p[0];
|
||||
param.func(c, param.args);
|
||||
free(param);
|
||||
}
|
||||
|
||||
p.fp = &fnentry;
|
||||
p.nparams = 1;
|
||||
p.params[0] = cast(size_t)param;
|
||||
|
||||
return cast(LPARAM)p;
|
||||
dflInvokeParam.fp = &funcEntry;
|
||||
dflInvokeParam.exception = null;
|
||||
dflInvokeParam.nparams = 1;
|
||||
dflInvokeParam.params[0] = cast(size_t)invokeParam;
|
||||
}
|
||||
|
||||
|
||||
LPARAM makeParamNoneArgs(void function(Control) fn)
|
||||
void makeParamNoneArgs(void function(Control) func, DflInvokeParam* dflInvokeParam)
|
||||
{
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
alias malloc = dfl.internal.clib.malloc;
|
||||
alias free = dfl.internal.clib.free;
|
||||
|
||||
auto p = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
|
||||
|
||||
if (!p)
|
||||
throw new OomException();
|
||||
|
||||
static void fnentry(Control c, size_t[] p)
|
||||
static void funcEntry(Control c, size_t[] p)
|
||||
{
|
||||
auto fn = cast(void function(Control))p[0];
|
||||
fn(c);
|
||||
auto func = cast(void function(Control))p[0];
|
||||
func(c);
|
||||
}
|
||||
|
||||
p.fp = &fnentry;
|
||||
p.nparams = 1;
|
||||
p.params[0] = cast(size_t)fn;
|
||||
|
||||
return cast(LPARAM)p;
|
||||
dflInvokeParam.fp = &funcEntry;
|
||||
dflInvokeParam.exception = null;
|
||||
dflInvokeParam.nparams = 0;
|
||||
dflInvokeParam.params[0] = cast(size_t)func;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
///
|
||||
this(Control ctrl)
|
||||
|
@ -91,62 +69,124 @@ public:
|
|||
assert(ctrl);
|
||||
_ctrl = cast(shared)ctrl;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
void invoke(ARGS...)(void function(Control, ARGS) fn, ARGS args)
|
||||
void invoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
|
||||
if (ARGS.length && !hasLocalAliasing!(ARGS))
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
Control.badInvokeHandle();
|
||||
|
||||
auto t = tuple(args);
|
||||
auto p = makeParam(fn, &t);
|
||||
SendMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, p);
|
||||
synchronized
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
|
||||
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
|
||||
if (!dflInvokeParam)
|
||||
throw new OomException();
|
||||
|
||||
makeParam(func, args, dflInvokeParam);
|
||||
scope(exit)
|
||||
{
|
||||
free(dflInvokeParam);
|
||||
}
|
||||
|
||||
if (LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE_PARAMS, cast(LPARAM)dflInvokeParam))
|
||||
throw new DflException("Invoke failure");
|
||||
|
||||
if (dflInvokeParam.exception)
|
||||
throw dflInvokeParam.exception;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
void invoke(ARGS...)(void function(Control, ARGS) fn, ARGS args)
|
||||
void invoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
|
||||
if (!ARGS.length)
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
Control.badInvokeHandle();
|
||||
|
||||
auto p = makeParamNoneArgs(fn);
|
||||
SendMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, p);
|
||||
synchronized
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
|
||||
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof);
|
||||
if (!dflInvokeParam)
|
||||
throw new OomException();
|
||||
|
||||
makeParamNoneArgs(func, dflInvokeParam);
|
||||
scope(exit)
|
||||
{
|
||||
free(dflInvokeParam);
|
||||
}
|
||||
|
||||
if (LRESULT_DFL_INVOKE != SendMessageA(hwnd, wmDfl, WPARAM_DFL_INVOKE_NOPARAMS, cast(LPARAM)dflInvokeParam))
|
||||
throw new DflException("Invoke failure");
|
||||
|
||||
if (dflInvokeParam.exception)
|
||||
throw dflInvokeParam.exception;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
void delayInvoke(ARGS...)(void function(Control, ARGS) fn, ARGS args)
|
||||
void delayInvoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
|
||||
if (ARGS.length && !hasLocalAliasing!(ARGS))
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
Control.badInvokeHandle();
|
||||
|
||||
auto t = tuple(args);
|
||||
auto p = makeParam(fn, &t);
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, p);
|
||||
synchronized
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
|
||||
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof); // NOTE: You must free memory in window procedure.
|
||||
if (!dflInvokeParam)
|
||||
throw new OomException();
|
||||
|
||||
makeParam(func, args, dflInvokeParam);
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, cast(LPARAM)dflInvokeParam);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
void delayInvoke(ARGS...)(void function(Control, ARGS) fn, ARGS args)
|
||||
void delayInvoke(ARGS...)(void function(Control, ARGS) func, ARGS args)
|
||||
if (!ARGS.length)
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
Control.badInvokeHandle();
|
||||
|
||||
auto p = makeParamNoneArgs(fn);
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_PARAMS, p);
|
||||
synchronized
|
||||
{
|
||||
auto ctrl = cast(Control)_ctrl;
|
||||
auto hwnd = ctrl.handle;
|
||||
|
||||
if(!hwnd)
|
||||
throw new DflException("Must invoke with created handle"); // Control.badInvokeHandle();
|
||||
|
||||
static assert((DflInvokeParam*).sizeof <= LPARAM.sizeof);
|
||||
|
||||
auto dflInvokeParam = cast(DflInvokeParam*)malloc(DflInvokeParam.sizeof); // NOTE: You must free memory in window procedure.
|
||||
if (!dflInvokeParam)
|
||||
throw new OomException();
|
||||
|
||||
makeParamNoneArgs(func, dflInvokeParam);
|
||||
PostMessageA(hwnd, wmDfl, WPARAM_DFL_DELAY_INVOKE_NOPARAMS, cast(LPARAM)dflInvokeParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private template hasLocalAliasing(T...)
|
||||
{
|
||||
import std.traits : hasUnsharedAliasing;
|
||||
|
||||
static if (!T.length)
|
||||
enum hasLocalAliasing = false;
|
||||
else
|
||||
enum hasLocalAliasing = std.traits.hasUnsharedAliasing!(T[0]) || dfl.sharedcontrol.hasLocalAliasing!(T[1 .. $]);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue