Introduction
Reading CodeProject and seeing some of the cool VC++ plug-ins out there has almost convinced me to move my primary editor to VC++, away from (gasp! my friends at college would kill me!) Emacs. But I've been missing some stuff, the kill-ring with multi-yank being one of them.
The following is inspired by Emacs' kill-ring behavior and owes its existence to the code published by Michael Pelts in Multiple Clipboard Macros. That project showed me enough of VC++, VBScript to convince me to try this out. The current implementation addresses the two major issues I had with Mr. Pelts' code: incompatibility with "Virtual Space" mode, and incompatibility with the standard Windows clipboard. I believe that these issues are solved by the code below.
Description
Basically, this adds multiple clipboard functionality (a stack of past copy/cuts) to VC++ in a very clean manner. The only difference from normal usage is that if one does Shift + Paste (default key-binding), then past clipboard entries (well, ones from VC++, anyways) are available via subsequent Shift + Pastes. The extended-functionality via "Shift" is done so as not to interfere with normal pastes, which do not leave the pasted text selected. Note, just to emphasize: when text is added to the clipboard from an external application, it _is_ available to be Shift + Pasted.
MClipboardCut
MClipboardCopy
MClipboardPaste
MClipboardClear
MClipboardDefaultBindings
Notes
Two known issues (so far): The first is interaction with a column-mode selection (Alt + Mouse_drag). This does not MClipboardPaste the same way that standard Paste does. The second known issue occurs when doing a series of MClipboardPastes. If during the middle of this series, another application is used to add something to the clipboard, this clipboard text is not made available to the MClipboard ring. This shouldn't be a major issue, as the typical usage scenario is to do a series of MClipboardPastes and then move on.
The code has been roughly tested on VC++ 6.0 (and only VC++ 6.0). It might work on prior versions as well, although I don't have enough VBScript experience (this is my first go at it) to hazard a guess, and I don't have a prior version of VC++ to test with. Let me know if it does, however. =)
Have at it, folks, and enjoy!
Dim nRingMaxSize
Dim nMaxValidExtract
Dim nRingInsertionPos
Dim nRingExtractionPos
Dim curCol
Dim curLine
Dim lastPaste
Dim lastPasteCol
Dim lastPasteLine
nRingMaxSize = 10
Dim Ring(9) nMaxValidExtract = 0 nRingInsertionPos = -1
nRingExtractionPos = 0
curCol = 0
curLine = 0
lastPaste = ""
lastPasteCol = 0
lastPasteLine = 0
Private Sub GetSelIntoRing()
If (nRingInsertionPos <> -1) Then
If (ActiveDocument.Selection = Ring(nRingInsertionPos)) Then
Exit Sub
End If
End If
nRingInsertionPos = (nRingInsertionPos + 1) Mod nRingMaxSize
Ring(nRingInsertionPos) = ActiveDocument.Selection
If (nMaxValidExtract < nRingMaxSize) Then
nMaxValidExtract = nMaxValidExtract + 1
End If
End Sub
Private Sub SetNextExtractionPos()
If (nMaxValidExtract = 0) Then
nRingExtractionPos = 0
Exit Sub
End If
If (nRingExtractionPos = 0) Then
nRingExtractionPos = nMaxValidExtract - 1
Exit Sub
End If
nRingExtractionPos = nRingExtractionPos - 1
End Sub
Private Sub GetSelOnRecentYankAndUpdateLasts
Dim col
Dim line
col = ActiveDocument.Selection.CurrentColumn
line = ActiveDocument.Selection.CurrentLine
ActiveDocument.Selection.MoveTo curLine, curCol
ActiveDocument.Selection.MoveTo line, col, dsExtend
lastPaste = ActiveDocument.Selection
lastPasteCol = curCol
lastPasteLine = curLine
End Sub
Sub MClipboardCopy ()
If (ActiveDocument Is Nothing) Then
Exit Sub
ElseIf (ActiveDocument.Type <> "Text") Then
Exit Sub
ElseIf (Len(ActiveDocument.Selection) = 0) Then
Exit Sub
End If
GetSelIntoRing()
nRingExtractionPos = nRingInsertionPos
ActiveDocument.Selection.Copy
End Sub
Sub MClipboardCut ()
If (ActiveDocument Is Nothing) Then
Exit Sub
ElseIf (ActiveDocument.Type <> "Text") Then
Exit Sub
ElseIf (Len(ActiveDocument.Selection) = 0) Then
Exit Sub
End If
GetSelIntoRing()
nRingExtractionPos = nRingInsertionPos
ActiveDocument.Selection.Cut
End Sub
Sub MClipboardPaste ()
If (ActiveDocument Is Nothing) Then
Exit Sub
ElseIf (ActiveDocument.Type <> "Text") Then
Exit Sub
End If
Dim currentSel
currentSel = ActiveDocument.Selection
ActiveDocument.Selection = ""
curCol = ActiveDocument.Selection.CurrentColumn
curLine = ActiveDocument.Selection.CurrentLine
If (nMaxValidExtract = 0) Then
ActiveDocument.Selection.Paste
GetSelOnRecentYankAndUpdateLasts
GetSelIntoRing
Exit Sub
End If
If (currentSel = lastPaste) Then
If (curCol = lastPasteCol) Then
If (curLine = lastPasteLine) Then
ActiveDocument.Selection = Ring(nRingExtractionPos)
GetSelOnRecentYankAndUpdateLasts
SetNextExtractionPos
Exit Sub
End If
End If
End If
ActiveDocument.Selection.Paste
GetSelOnRecentYankAndUpdateLasts
If (lastPaste <> Ring(nRingInsertionPos)) Then
GetSelIntoRing
Else
SetNextExtractionPos
End If
End Sub
Sub MClipboardClear ()
nMaxValidExtract = 0
nRingInsertionPos = -1
nRingExtractionPos = 0
curCol = 0
curLine = 0
lastPaste = ""
lastPasteCol = 0
lastPasteLine = 0
Dim i
i = 0
Do Until (i = nRingMaxSize)
Ring(i) = ""
i = i + 1
Loop
End Sub
Sub MClipboardDefaultBindings ()
AddKeyBinding "CTRL+X", "MClipboardCut", "Text"
AddKeyBinding "SHIFT+DEL", "MClipboardCut", "Text"
AddKeyBinding "CTRL+C", "MClipboardCopy", "Text"
AddKeyBinding "CTRL+INS", "MClipboardCopy", "Text"
AddKeyBinding "CTRL+SHIFT+V", "MClipboardPaste", "Text"
AddKeyBinding "CTRL+SHIFT+INS", "MClipboardPaste", "Text"
AddKeyBinding "CTRL+SHIFT+X", "MClipboardClear", "Text"
AddKeyBinding "CTRL+SHIFT+DEL", "MClipboardClear", "Text"
End Sub