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.
    • Alan KilbornA
      Alan Kilborn
      last edited by

      Hello all,

      Is there a way to tell if clipboard has column-block in it without actually pasting? I’m speaking in a Pythonscript context…can I tell before I do an editor.paste() function call if what I will be pasting is something that was a column-block selection at the point it was copied to the clipboard?

      Thanks!

      Claudia FrankC CoisesC 2 Replies Last reply Reply Quote 0
      • 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