Community
    • Login

    Way to tell if clipboard has column-block in it before pasting?

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    11 Posts 5 Posters 4.5k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Claudia FrankC
      Claudia Frank @Alan Kilborn
      last edited by

      @Alan-Kilborn

      more or less - depends what exactly should be done.
      What comes first into my mind is using editor.selectionIsRectangle.
      If it returns True it is column mode but this of course means the selection is
      still active.

      If this doesn’t answer your question you may provide more infos how your script
      should work exactly.

      Cheers
      Claudia

      Alan KilbornA 1 Reply Last reply Reply Quote 0
      • Alan KilbornA
        Alan Kilborn @Claudia Frank
        last edited by

        @Claudia-Frank

        Thank you for your reply. I was thinking in terms of possibly the selection being made some time ago, i.e., not currently active, maybe there is another selection currently active for drag-and-drop movement purpose…the point is, nothing has been copied to the clipboard since the column block was. So the column block is still there, and N++ knows it…but can I also know it from my script somehow?

        Claudia FrankC 1 Reply Last reply Reply Quote 0
        • Claudia FrankC
          Claudia Frank @Alan Kilborn
          last edited by

          @Alan-Kilborn

          actually I think npp doesn’t know it but scintilla does.

          In theory you should be able to do it

          1. Install a clipboard watcher (ctypes and windows api required)
          2. whenever clipboard data changes, check if selection was rectangle

          But I still don’t get the point why it is necessary to do it as scintilla is handling it for you.

          Cheers
          Claudia

          Alan KilbornA 1 Reply Last reply Reply Quote 0
          • Alan KilbornA
            Alan Kilborn @Claudia Frank
            last edited by

            @Claudia-Frank

            Hi Claudia, I forgot about this for a while. :(

            But now I’m interested again.

            I looked up how to install a clipboard viewer in the chain using C and the Windows API, and I am a little familiar with Python’s ctypes, but I don’t really see how to put it all together. The first thing I’m confused on is the hwnd I would use…but I’m sure there’s more. Can you possibly show me how to do this? TIA…

            Claudia FrankC 1 Reply Last reply Reply Quote 0
            • Claudia FrankC
              Claudia Frank @Alan Kilborn
              last edited by Claudia Frank

              @Alan-Kilborn

              Hi Alan,

              I guess it is the hwnd from npp which you can get by using FindWindow API call.
              and in order to receive the WM_CHANGECBCHAIN and WM_DRAWCLIPBOARD messages
              you need to register a hook like I did here.

              Don’t forget to pass the message to the next viewer in chain like described in this example.

              Note, there is also an win32clipboard module available which could make it more easy just make sure
              it is installed in a directory which is resolved by sys.path.

              I’m kinda unsure how a “linux” clipboard would act but let me know if I should give it a try.

              Cheers
              Claudia

              1 Reply Last reply Reply Quote 0
              • Scott SumnerS
                Scott Sumner
                last edited by

                @Alan-Kilborn & @Claudia-Frank ,

                Here’s HookForClipboardUpdate.py that provides the desired functionality.

                import ctypes, os
                from ctypes.wintypes import LONG, HWND, UINT, WPARAM, LPARAM
                
                SetWindowLong = ctypes.windll.user32.SetWindowLongA
                CallWindowProc = ctypes.windll.user32.CallWindowProcA
                FindWindow = ctypes.windll.user32.FindWindowA
                AddClipboardFormatListener = ctypes.windll.user32.AddClipboardFormatListener
                RemoveClipboardFormatListener = ctypes.windll.user32.RemoveClipboardFormatListener
                IsClipboardFormatAvailable = ctypes.windll.user32.IsClipboardFormatAvailable
                
                WndProcType = ctypes.WINFUNCTYPE(LONG, HWND, UINT, WPARAM, LPARAM)
                
                GWL_WNDPROC = -4
                WM_CLIPBOARDUPDATE = 0x31D
                CF_TEXT = 1
                CF_UNICODETEXT = 13
                
                class Hook():
                
                    def __init__(self):
                        self.nppHandle = FindWindow('Notepad++', None)
                
                    def register(self):
                        self.newWndProc = WndProcType(self.MyWndProc)
                        self.oldWndProc = SetWindowLong(self.nppHandle, GWL_WNDPROC, self.newWndProc)
                        console.editor.setProperty('oldWndProc', self.oldWndProc)
                        AddClipboardFormatListener(self.nppHandle)
                        print "registered"
                
                    def unregister(self):
                        self.prevWndProc = console.editor.getProperty('oldWndProc')
                        dummy = SetWindowLong(self.nppHandle, GWL_WNDPROC, int(self.prevWndProc))
                        RemoveClipboardFormatListener(self.nppHandle)
                        print "unregistered"
                
                    def MyWndProc(self, hWnd, msg, wParam, lParam):
                        if msg == WM_CLIPBOARDUPDATE:
                            self.clipboardUpdate()
                        return CallWindowProc(self.oldWndProc, hWnd, msg, wParam, lParam)
                
                    def clipboardUpdate(self):
                        print "got clipboard update"
                        if IsClipboardFormatAvailable(CF_TEXT) or IsClipboardFormatAvailable(CF_UNICODETEXT):
                            print "clipboard contains text"
                            print "selection is {}rectangular".format('' if editor.selectionIsRectangle() else 'NOT ')
                
                _hook = Hook()
                
                if console.editor.getProperty('Hookstatus') != '1':
                    console.editor.setProperty('Hookstatus', '1')
                    _hook.register()
                else:
                    console.editor.setProperty('Hookstatus', '0')
                    _hook.unregister()
                

                @Alan-Kilborn , at the point where the above program prints whether or not the clipboard text is rectangular or not, set a global variable that reflects the setting, that your other script(s) can then query.

                If this (or ANY) posting was useful, don’t post a “thanks”, just upvote ( click the ^ in the ^ 0 v area on the right ).

                Claudia FrankC 1 Reply Last reply Reply Quote 3
                • Pritika SrivastavP
                  Pritika Srivastav Banned
                  last edited by

                  This post is deleted!
                  1 Reply Last reply Reply Quote -1
                  • Claudia FrankC
                    Claudia Frank @Scott Sumner
                    last edited by

                    @Scott-Sumner

                    and this works under linux/wine as well. :-)
                    Another nice one.

                    Cheers
                    Claudia

                    1 Reply Last reply Reply Quote 0
                    • CoisesC
                      Coises @Alan Kilborn
                      last edited by Coises

                      @Alan-Kilborn said in Way to tell if clipboard has column-block in it before pasting?:

                      Is there a way to tell if clipboard has column-block in it without actually pasting?

                      I came across this question while searching for an answer to the same question (though for C++, not python).

                      I knew the notion that Scintilla just remembers what was last copied had to be wrong — it’s stored in the clipboard somehow. Two simple tests demonstrate this:

                      1. Select and copy a rectangular selection in Notepad++. Close Notepad++. Open it again, open a file with multiple lines of text already in it and paste. The paste is rectangular.

                      2. Select and copy a column selection in Visual Studio. Open Notepad++, open a file with multiple lines of text already in it and paste. The paste is rectangular.

                      The answer is that both Scintilla and Visual Studio indicate a column selection by registering an additional clipboard format as a signal.

                      This code hasn’t been tested thoroughly yet and probably is missing an error check or two, but roughly, it works this way:

                          CLIPFORMAT cfColumnSelect = static_cast<CLIPFORMAT>(RegisterClipboardFormat(L"MSDEVColumnSelect"));
                          if (IsClipboardFormatAvailable(cfColumnSelect) && OpenClipboard(0)) {
                              HANDLE clipboardHandle = GetClipboardData(CF_UNICODETEXT);
                              wchar_t* clipboardData = static_cast<wchar_t*>(GlobalLock(clipboardHandle));
                              std::wstring clipboardString(clipboardData);
                              GlobalUnlock(clipboardHandle);
                              CloseClipboard();
                              // clipboard data is in clipboardString; examine here as needed
                          }
                      

                      Notepad++ does this here.

                      Alan KilbornA 1 Reply Last reply Reply Quote 3
                      • Alan KilbornA
                        Alan Kilborn @Coises
                        last edited by

                        @Coises said:

                        Curiously, because this current topic is really focused on “Way to tell if clipboard has column-block in it before pasting?” (from its title), it doesn’t, until @Coises posted, reference MSDEVColumnSelect.

                        However, these topics do:

                        • https://community.notepad-plus-plus.org/topic/17272 Mar 11, 2019, 1:28 PM posting
                        • https://community.notepad-plus-plus.org/topic/19643 Jul 9, 2020, 1:56 PM (in script listing)

                        And, Scintilla code discusses it, too, HERE.

                        1 Reply Last reply Reply Quote 2
                        • First post
                          Last post
                        The Community of users of the Notepad++ text editor.
                        Powered by NodeBB | Contributors