Пример #1
0
        /// <summary>
        /// Compares this string with a string that possibly contains wildcard characters.
        /// Returns true if the strings match.
        /// </summary>
        /// <param name="t">This string. If null, returns false. If "", returns true if pattern is "" or "*".</param>
        /// <param name="pattern">String that possibly contains wildcard characters. Cannot be null. If "", returns true if this string is "". If "*", always returns true except when this string is null.</param>
        /// <param name="ignoreCase">Case-insensitive.</param>
        /// <remarks>
        /// Wildcard characters:
        ///
        /// Character | Will match | Examples
        /// | - | - | - |
        /// | * | Zero or more of any characters. | <c>"start*"</c>, <c>"*end"</c>, <c>"*middle*"</c>
        /// | ? | Any single character. | <c>"date ????-??-??"</c>
        ///
        /// There are no escape sequences for * and ? characters.
        ///
        /// Uses ordinal comparison, ie does not depend on current culture.
        ///
        /// Much faster than regular expression.
        ///
        /// See also: [](xref:wildcard_expression).
        /// </remarks>
        /// <example>
        /// <code><![CDATA[
        /// string s = @"C:\abc\mno.xyz";
        /// if(s.Like(@"C:\abc\mno.xyz")) AOutput.Write("matches whole text (no wildcard characters)");
        /// if(s.Like(@"C:\abc\*")) AOutput.Write("starts with");
        /// if(s.Like(@"*.xyz")) AOutput.Write("ends with");
        /// if(s.Like(@"*mno*")) AOutput.Write("contains");
        /// if(s.Like(@"C:\*.xyz")) AOutput.Write("starts and ends with");
        /// if(s.Like(@"?:*")) AOutput.Write("any character, : and possibly more text");
        /// ]]></code>
        /// </example>
        /// <seealso cref="AWildex"/>
#if false //somehow speed depends on dll version. With some versions same as C# code, with some slower. Also depends on string. With shortest strings 50% slower.
        public static bool Like(this string t, string pattern, bool ignoreCase = false)
        {
            if (t == null)
            {
                return(false);

                fixed(char *pt = t, pw = pattern)
                return(Cpp.Cpp_StringLike(pt, t.Length, pw, pattern.Length, ignoreCase));
        }
Пример #2
0
        //#region IReflect

        //FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) => null;
        //FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) => null;
        //MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) => null;
        //MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) => null;
        //MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) => null;
        //MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) => null;
        //MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) => null;
        //PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) => null;
        //PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) => null;
        //PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) => null;
        //object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) => null;
        //Type IReflect.UnderlyingSystemType => null;

        //#endregion

        /// <summary>
        /// Call in hook wndproc on WM_GETOBJECT like this: <c>handled = true; return (_acc ??= new _Accessible(this)).WmGetobject(wParam, lParam);</c>.
        /// If lParam is EObjid.CLIENT, calls API LresultFromObject(this), else calls API DefWindowProc.
        /// </summary>
        public nint WmGetobject(nint wParam, nint lParam)
        {
            var oid = (EObjid)lParam;

            //print.it(oid);
            if (oid != EObjid.CLIENT)
            {
                return(Api.DefWindowProc(_w, Api.WM_GETOBJECT, wParam, lParam));
            }

            return(Cpp.Cpp_AccWorkaround(this, wParam, ref _accWorkaround));

            //cannot use this because of .NET bug: then calls our IAccessible implementation methods in other thread.
            //var accIP = Marshal.GetIUnknownForObject(this);
            ////var accIP=Marshal.GetIDispatchForObject(this);
            //var r = Api.LresultFromObject(typeof(IAccessible).GUID, wParam, accIP);
            ////Marshal.AddRef(accIP); print.it(Marshal.Release(accIP));
            //Marshal.Release(accIP);
            //return r;
        }
Пример #3
0
        public bool InsideString(bool charJustAdded, int position) //need to refactor this out too.
        {
            Cpp style = (Cpp)GetStyleAt(position - (charJustAdded ? 2 : 1));

            if (style == Cpp.String)
            {
                return(true);
            }

            int    lineNumber = LineFromPosition(position);
            int    lineStart  = PositionFromLine(lineNumber);
            string curLine    = GetLine(lineNumber);

            if (curLine.Length > 0)
            {
                int length = position - lineStart;
                if (length >= curLine.Length)
                {
                    length = curLine.Length - 1;
                }
                curLine = curLine.Substring(0, length);
            }
            if (curLine.IndexOf('"') >= 0)
            {
                int curIndex       = 0;
                int numSpeechMarks = 0;
                while ((curIndex = curLine.IndexOf('"', curIndex)) >= 0)
                {
                    numSpeechMarks++;
                    curIndex++;
                }
                if (numSpeechMarks % 2 == 1)
                {
                    // in a string literal
                    return(true);
                }
            }

            return(false);
        }
Пример #4
0
        wnd _wTargetControl;         //control or window from mouse

        int _InvokeDropTarget(wnd w, DDEvent ev, int effect, int keyState, POINT pt)
        {
            nint prop = w.Prop["OleDropTargetInterface"];

            if (prop == 0 && w != _wWindow)               //if w is of a HwndHost that does not register drop target, use that of the main window
            {
                w    = _wWindow;
                prop = w.Prop["OleDropTargetInterface"];
            }
            if (prop == 0)
            {
                return(0);
            }

            var data = ev == DDEvent.Enter || ev == DDEvent.Drop ? _data : null;
            int hr   = Cpp.Cpp_CallIDroptarget(prop, (int)ev, data, keyState, pt, ref effect);

            if (hr != 0)
            {
                effect = 0;
            }
            return(effect);
            //working with COM in C# often is difficult. Cannot call IDropTarget methods.
        }
Пример #5
0
        /// <summary>
        /// Runs/opens a program, document, directory (folder), URL, new email, Control Panel item etc.
        /// The returned <see cref="RResult"/> variable contains some process info - process id etc.
        /// </summary>
        /// <param name="file">
        /// Examples:
        /// - <c>@"C:\file.txt"</c>
        /// - <c>folders.Documents</c>
        /// - <c>folders.System + "notepad.exe"</c>
        /// - <c>@"%folders.System%\notepad.exe"</c>
        /// - <c>@"%TMP%\file.txt"</c>
        /// - <c>"notepad.exe"</c>
        /// - <c>@"..\folder\x.exe"</c>
        /// - <c>"http://a.b.c/d"</c>
        /// - <c>"file:///path"</c>
        /// - <c>"mailto:[email protected]"</c>
        /// - <c>":: ITEMIDLIST"</c>
        /// - <c>@"shell:::{CLSID}"</c>
        /// - <c>@"shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"</c>.
        /// More info in Remarks.
        /// </param>
        /// <param name="args">
        /// Command line arguments.
        /// This function expands environment variables if starts with <c>"%"</c> or <c>"\"%"</c>.
        /// </param>
        /// <param name="flags"></param>
        /// <param name="dirEtc">
        /// Allows to specify more parameters: current directory, verb, etc.
        /// If string, it sets initial current directory for the new process. If "", gets it from <i>file</i>. More info: <see cref="ROptions.CurrentDirectory"/>.
        /// </param>
        /// <exception cref="ArgumentException">Used both <b>ROptions.Verb</b> and <b>RFlags.Admin</b> and this process isn't admin.</exception>
        /// <exception cref="AuException">Failed. For example, the file does not exist.</exception>
        /// <remarks>
        /// It works like when you double-click a file icon. It may start new process or not. For example it may just activate window if the program is already running.
        /// Uses API <msdn>ShellExecuteEx</msdn>.
        /// Similar to <see cref="Process.Start(string, string)"/>.
        ///
        /// The <i>file</i> parameter can be:
        /// - Full path of a file or directory. Examples: <c>@"C:\file.txt"</c>, <c>folders.Documents</c>, <c>folders.System + "notepad.exe"</c>, <c>@"%folders.System%\notepad.exe"</c>.
        /// - Filename of a file or directory, like <c>"notepad.exe"</c>. The function calls <see cref="filesystem.searchPath"/>.
        /// - Path relative to <see cref="folders.ThisApp"/>. Examples: <c>"x.exe"</c>, <c>@"subfolder\x.exe"</c>, <c>@".\subfolder\x.exe"</c>, <c>@"..\another folder\x.exe"</c>.
        /// - URL. Examples: <c>"https://www.example.com"</c>, <c>"file:///path"</c>.
        /// - Email, like <c>"mailto:[email protected]"</c>. Subject, body etc also can be specified, and Google knows how.
        /// - Shell object's ITEMIDLIST like <c>":: ITEMIDLIST"</c>. See <see cref="Pidl.ToHexString"/>, <see cref="folders.shell"/>. Can be used to open virtual folders and items like Control Panel.
        /// - Shell object's parsing name, like <c>@"shell:::{CLSID}"</c> or <c>@"::{CLSID}"</c>. See <see cref="Pidl.ToShellString"/>. Can be used to open virtual folders and items like Control Panel.
        /// - To run a Windows Store App, use <c>@"shell:AppsFolder\WinStoreAppId"</c> format. Examples: <c>@"shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"</c>, <c>@"shell:AppsFolder\windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel"</c>. To discover the string use hotkey Ctrl+Shift+Q or function <see cref="WndUtil.GetWindowsStoreAppId"/> or Google.
        ///
        /// Supports environment variables, like <c>@"%TMP%\file.txt"</c>. See <see cref="pathname.expand"/>.
        /// </remarks>
        /// <seealso cref="wnd.find"/>
        /// <seealso cref="wnd.findOrRun"/>
        /// <seealso cref="wnd.runAndFind"/>
        /// <example>
        /// Run Notepad and wait for an active Notepad window.
        /// <code><![CDATA[
        /// run.it("notepad.exe");
        /// 1.s();
        /// wnd w = wnd.wait(10, true, "*- Notepad", "Notepad");
        /// ]]></code>
        /// Run Notepad or activate a Notepad window.
        /// <code><![CDATA[
        /// wnd w = wnd.findOrRun("*- Notepad", run: () => run.it("notepad.exe"));
        /// ]]></code>
        /// Run File Explorer and wait for new folder window. Ignores matching windows that already existed.
        /// <code><![CDATA[
        /// var w = wnd.runAndFind(
        ///     () => run.it(@"explorer.exe"),
        ///     10, cn: "CabinetWClass");
        /// ]]></code>
        /// </example>
        public static RResult it(string file, string args = null, RFlags flags = 0, ROptions dirEtc = null)
        {
            Api.SHELLEXECUTEINFO x = default;
            x.cbSize = Api.SizeOf(x);
            x.fMask  = Api.SEE_MASK_NOZONECHECKS | Api.SEE_MASK_NOASYNC | Api.SEE_MASK_CONNECTNETDRV | Api.SEE_MASK_UNICODE;
            x.nShow  = Api.SW_SHOWNORMAL;

            bool curDirFromFile = false;
            var  more           = dirEtc;

            if (more != null)
            {
                x.lpVerb = more.Verb;
                if (x.lpVerb != null)
                {
                    x.fMask |= Api.SEE_MASK_INVOKEIDLIST;                                   //makes slower. But verbs are rarely used.
                }
                if (more.CurrentDirectory is string cd)
                {
                    if (cd.Length == 0)
                    {
                        curDirFromFile = true;
                    }
                    else
                    {
                        cd = pathname.expand(cd);
                    }
                    x.lpDirectory = cd;
                }

                if (!more.OwnerWindow.IsEmpty)
                {
                    x.hwnd = more.OwnerWindow.Hwnd.Window;
                }

                switch (more.WindowState)
                {
                case ProcessWindowStyle.Hidden: x.nShow = Api.SW_HIDE; break;

                case ProcessWindowStyle.Minimized: x.nShow = Api.SW_SHOWMINIMIZED; break;

                case ProcessWindowStyle.Maximized: x.nShow = Api.SW_SHOWMAXIMIZED; break;
                }

                x.fMask &= ~more.FlagsRemove;
                x.fMask |= more.FlagsAdd;
            }

            if (flags.Has(RFlags.Admin))
            {
                if (x.lpVerb == null || x.lpVerb.Eqi("runas"))
                {
                    x.lpVerb = "runas";
                }
                else if (!uacInfo.isAdmin)
                {
                    throw new ArgumentException("Cannot use Verb with flag Admin, unless this process is admin");
                }
            }

            file = _NormalizeFile(false, file, out bool isFullPath, out bool isShellPath);
            Pidl pidl = null;

            if (isShellPath)                  //":: ITEMIDLIST" or "::{CLSID}..." (we convert it too because the API does not support many)
            {
                pidl = Pidl.FromString(file); //does not throw
                if (pidl != null)
                {
                    x.lpIDList = pidl.UnsafePtr;
                    x.fMask   |= Api.SEE_MASK_INVOKEIDLIST;
                }
                else
                {
                    x.lpFile = file;
                }
            }
            else
            {
                x.lpFile = file;

                if (curDirFromFile && isFullPath)
                {
                    x.lpDirectory = pathname.getDirectory(file);
                }
            }
            x.lpDirectory ??= Directory.GetCurrentDirectory();
            if (!args.NE())
            {
                x.lpParameters = pathname.expand(args);
            }

            if (0 == (flags & RFlags.ShowErrorUI))
            {
                x.fMask |= Api.SEE_MASK_FLAG_NO_UI;
            }
            if (0 == (flags & RFlags.WaitForExit))
            {
                x.fMask |= Api.SEE_MASK_NO_CONSOLE;
            }
            if (0 != (flags & RFlags.MostUsed))
            {
                x.fMask |= Api.SEE_MASK_FLAG_LOG_USAGE;
            }
            x.fMask |= Api.SEE_MASK_NOCLOSEPROCESS;

            WndUtil.EnableActivate(-1);

            bool waitForExit = 0 != (flags & RFlags.WaitForExit);
            bool needHandle  = flags.Has(RFlags.NeedProcessHandle);

            bool ok = false; int pid = 0, errorCode = 0;
            bool asUser = !flags.HasAny(RFlags.Admin | RFlags.InheritAdmin) && uacInfo.isAdmin;             //info: new process does not inherit uiAccess

            if (asUser)
            {
                ok = Cpp.Cpp_ShellExec(x, out pid, out int injectError, out int execError);
                if (!ok)
                {
                    if (injectError != 0)
                    {
                        print.warning("Failed to run as non-admin.");
                        asUser = false;
                    }
                    else
                    {
                        errorCode = execError;
                    }
                }
            }
            if (!asUser)
            {
                ok = Api.ShellExecuteEx(ref x);
                if (!ok)
                {
                    errorCode = lastError.code;
                }
            }
            pidl?.Dispose();
            if (!ok)
            {
                throw new AuException(errorCode, $"*run '{file}'");
            }

            var         R  = new RResult();
            WaitHandle_ ph = null;

            if (needHandle || waitForExit)
            {
                if (pid != 0)
                {
                    x.hProcess = Handle_.OpenProcess(pid, Api.PROCESS_ALL_ACCESS);
                }
                if (!x.hProcess.Is0)
                {
                    ph = new WaitHandle_(x.hProcess, true);
                }
            }

            if (!waitForExit)
            {
                if (pid != 0)
                {
                    R.ProcessId = pid;
                }
                else if (!x.hProcess.Is0)
                {
                    R.ProcessId = process.processIdFromHandle(x.hProcess);
                }
            }

            try {
                Api.AllowSetForegroundWindow();

                if (x.lpVerb != null && Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
                {
                    Thread.CurrentThread.Join(50);                     //need min 5-10 for file Properties. And not Sleep.
                }
                if (ph != null)
                {
                    if (waitForExit)
                    {
                        ph.WaitOne();
                        if (Api.GetExitCodeProcess(x.hProcess, out var exitCode))
                        {
                            R.ProcessExitCode = exitCode;
                        }
                    }
                    if (needHandle)
                    {
                        R.ProcessHandle = ph;
                    }
                }
            }
            finally {
                if (R.ProcessHandle == null)
                {
                    if (ph != null)
                    {
                        ph.Dispose();
                    }
                    else
                    {
                        x.hProcess.Dispose();
                    }
                }
            }

            return(R);

            //tested: works well in MTA thread.
            //rejected: in QM2, run also has a 'window' parameter. However it just makes limited, unclear etc, and therefore rarely used. Instead use wnd.findOrRun or Find/Run/Wait like in the examples.
            //rejected: in QM2, run also has 'autodelay'. Better don't add such hidden things. Let the script decide what to do.
        }
Пример #6
0
        private void Style(int linenum, int end)
        {
            int line_length = SendMessageDirect(Constants.SCI_LINELENGTH, linenum);
            int start_pos   = SendMessageDirect(Constants.SCI_POSITIONFROMLINE, linenum);
            int laststyle   = start_pos;

            Cpp stylingMode;

            if (start_pos > 0)
            {
                stylingMode = (Cpp)GetStyleAt(start_pos - 1);
            }
            else
            {
                stylingMode = Cpp.Default;
            }
            bool onNewLine    = true;
            bool onScriptLine = false;
            int  i;

            SendMessageDirect(Constants.SCI_STARTSTYLING, start_pos, 0x1f);

            for (i = start_pos; i <= end; i++)
            {
                char c = (char)GetCharAt(i);

                if (!Char.IsLetterOrDigit(c) && (stylingMode != Cpp.Comment || stylingMode != Cpp.CommentLine || stylingMode != Cpp.String))
                {
                    string lastword = previousWordFrom(i);
                    if (lastword.Length != 0)
                    {
                        Cpp newMode = stylingMode;
                        if (onScriptLine && Keywords.Contains(lastword.Trim()))
                        {
                            newMode = Cpp.Word;
                        }
                        if (!onScriptLine && stylingMode == Cpp.Word2) // before colon
                        {
                            if (lastword.Trim() == "return" || lastword.Trim() == "stop")
                            {
                                newMode = Cpp.Word;
                            }
                        }


                        if (newMode != stylingMode)
                        {
                            SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle - lastword.Length, (int)stylingMode);
                            SendMessageDirect(Constants.SCI_SETSTYLING, lastword.Length, (int)newMode);
                            laststyle = i;
                        }
                    }
                }

                if (c == '\n')
                {
                    onNewLine    = true;
                    onScriptLine = false;
                    if (stylingMode != Cpp.Comment && stylingMode != Cpp.String)
                    {
                        if (laststyle < i)
                        {
                            SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
                            laststyle = i;
                        }
                        stylingMode = Cpp.Default;
                    }
                    continue;
                }

                if (onNewLine)
                {
                    if (c == ' ')
                    {
                        onScriptLine = true;
                        onNewLine    = false;
                        continue;
                    }
                }

                if (onScriptLine)
                {
                    if (isOperator(c))
                    {
                        if (stylingMode != Cpp.String && stylingMode != Cpp.Comment && stylingMode != Cpp.CommentLine)
                        {
                            SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
                            SendMessageDirect(Constants.SCI_SETSTYLING, 1, (int)Cpp.Operator);
                            stylingMode = Cpp.Default;
                            laststyle   = i + 1;
                        }
                    }

                    else if (isNumeric(c))
                    {
                        if (stylingMode != Cpp.String && stylingMode != Cpp.Comment && stylingMode != Cpp.CommentLine)
                        {
                            SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
                            SendMessageDirect(Constants.SCI_SETSTYLING, 1, (int)Cpp.Number);
                            stylingMode = Cpp.Default;
                            laststyle   = i + 1;
                        }
                    }
                    else if (c == '"')
                    {
                        if (stylingMode == Cpp.String)
                        {
                            SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle + 1, (int)stylingMode);
                            laststyle   = i + 1;
                            stylingMode = Cpp.Default;
                        }
                        else
                        {
                            stylingMode = Cpp.String;
                        }
                    }
                }
                else
                {
                    if (onNewLine && stylingMode != Cpp.Comment)
                    {
                        SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
                        stylingMode = Cpp.Word2;
                        laststyle   = i;
                    }
                    if (c == ':' && stylingMode != Cpp.Comment && stylingMode != Cpp.CommentLine)
                    {
                        SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle + 1, (int)stylingMode);
                        laststyle   = i + 1;
                        stylingMode = Cpp.Number;
                    }
                    if (c == '@' && stylingMode == Cpp.Word2)
                    {
                        SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
                        stylingMode = Cpp.Number;
                        laststyle   = i;
                    }
                }

                if (c == '/')
                {
                    if (stylingMode == Cpp.Comment && GetCharAt(i - 1) == '*')
                    {
                        SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle + 1, (int)stylingMode);
                        stylingMode = Cpp.Default;
                        laststyle   = i + 1;
                    }
                    else if (GetCharAt(i + 1) == '*' && onScriptLine)
                    {
                        SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
                        stylingMode = Cpp.Comment;
                        laststyle   = i;
                    }
                    else if (GetCharAt(i + 1) == '/')
                    {
                        SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
                        stylingMode = Cpp.CommentLine;
                        laststyle   = i;
                    }
                }

                onNewLine = false;
            }



            SendMessageDirect(Constants.SCI_SETSTYLING, i - laststyle, (int)stylingMode);
        }