Code:
; Clipser
; Copyright (c) 2005 by Decarlo L.
; this program may only be used under the 110 SGPL License
; v1.2.4
; fixed clip menu reset issues: item compounding, OnClipboardChange buffer effect
; v1.2.3
; added restore of system clipboard after Clipser paste
; fixed first item duplicate-checking to allow subsets
; added ability for consecutive Paste, supporting Space, Backspace, Enter, Comma
; added skip of filepath/URL caching for items over 99 lines to improve speed
; fixed bug of Undo when clip menu appears
; v1.2.2 description:
; multiclipboard utility.
; menu view (Shift.Ctrl.v.c),
; cycling view (Shift.Ctrl.v, hold modifiers, then v/c for forward/back),
; efficient clipboard switching (double-press LCtrl, then tap/hold),
; composite text clipboard simultaneous with any selected clipboard,
; automatic caching of any copied (or cut) texts,
; automatic checking of duplicate items,
; item-copied indicator,
; alphabetic/chronological clip menu listing,
; automatic saving of clipboards on exit of program or changing of clip ring,
; view/edit all items (toggle Shift.Ctrl.c),
; delete selected items/replace list (Shift.Ctrl.c, hold, then right-click in dialog),
; automatic caching of copied files 10 Mb or less,
; automatic caching of filepathNames and website URL's to specified clipboard,
; support for configurable cut, copy, paste hotkeys
; clipboard naming and other configurable settings (hold Ctrl.C or Alt.L)
; help dialog (right-click dialog after holding Shift.Ctrl.c / Ctrl.C / Alt.L)
; add: auto-capture to specified clipboard when window/program is foreground/open
; add: support for pictures and other non-text objects
; add: option for automatic-advance in multiple Paste
; add: ListBox mode to DeleteSelect
; history, recent topmost:
; added limit setting for automatic delete in file cache
; added option to normalize filecache names from source-naming default
; added support for configurable hotkey option for cut, copy, paste
; added auto-capture of filepathNames and website URL's to specified clipboard
; added ability to backward wrap for in-text scrolling of clip list
; fixed some array handling due to clipboard switching
; added clip# indicator when switching clipboards
; completed remaining list routines to handle clipboard switching
; added updating of clip# index when clipboard is switched
; added automatic saving of clipboards prior to loading new clipboard ring
; fixed issues related to empty clipboard ring
; fixed item checking for last item stored
; fixed item checking regarding subsets of copied items
; fixed item checking on initial entry after clipboard is switched
; modified item checking to handle when custom clipboard is not <composite>
; fixed list handling when max clip limit is reached
; fixed duplicate-item checking of initial element
; fixed menu display issues of item sorting, initial item, and reverse indexing
; added automatic save/load of last clipboard ring
; added settings gui and .ini file for clipboard names and other settings
Download Clipser (67 K)Here are the functions used (included in the download).
Code:
RunW(app, secToWait=30) ; Run,WinWait,WinActivate,WinWaitActive
{
Run, %app%,,, appPID ; must be PID, not ID
WinWait ahk_pid %appPID%,, %secToWait%
WinActivate
WinWaitActive,,, %secToWait% ; default 30 sec maximum
ifWinNotActive ahk_pid %appPID%
Msgbox, Target application window did not activate within %secToWait% sec.`n`nThe originating thread may cause problems if it continues.
return
}
SplashText(title="", timeout="", width="", height="", text="") ; default timeout 700
{
SplashTextOn, %Width%, %Height%, %Title%, %Text%
if timeout =
sleep 700
else if timeout = 0 ; leave on until replaced or turned off later
RETURN
else
sleep %timeout%
SplashTextOff
return
}
StringR(in, charsToKeep, charsToTrim="")
{
StringRight, out, in, %charsToKeep%
if charsToTrim
StringTrimRight, out, out, %charsToTrim%
return out
}
StringM(in, StartChar, Count, L="")
{
if L = L
StringMid, Out, in, %StartChar%, %Count%, L
else
StringMid, Out, in, %StartChar%, %Count%
return out
}
StringL(in, charsToKeep, charsToTrim="", trimInitialWhitespace="")
{
global recurse_StringL_out
StringLeft, out, in, %charsToKeep%
if charsToTrim
StringTrimLeft, out, out, %charsToTrim%
if trimInitialWhitespace
{
recurse_StringL_out = %out%
Loop % StrLen(out)
{
if Contains( StringL(recurse_StringL_out, 1), A_Space . "," . A_Tab . ",`n,`r,`v,`f" ) ; if first char is space
recurse_StringL_out := StringL(recurse_StringL_out, StrLen(recurse_StringL_out), 1) ; trim first char
else
BREAK
}
}
if trimInitialWhitespace
return recurse_StringL_out
else
return out
}
In( a, b ) ; If a in b list. For b, use "var1 [, var2, ...]"
{
Loop, Parse, b, `,, %A_Space%%A_Tab%
if a = %A_LoopField%
Return 1
}
Contains( a, b ) ; If a contains any element in b list "var1[,var2,...]" do not use spaces/tabs.
; modifying this to handle spaces/tabs in b list, will make it incompatible with StringL whitespace-trim.
{
Loop, Parse, b, `, ;, %A_Space%%A_Tab%
ifInString, a, %A_LoopField%
Return 1
}
GuiControlGet(Subcommand="", ControlID="", Param4="") ; use prefix 2:, 37:, etc in first param if needed
{
GuiControlGet, OutputVar, %Subcommand%, ControlID, Param4
return OutputVar
}
NotInString(a,b)
{
IfNotInString, a, %b% ; 2nd param of IfInString defaults to a literal
return 1
}
KeyWait(str, hotkey="") ; default is string, not hotkey label
; this accepts strings and hotkey labels. do not use commas; spaces/tabs optional
{
str_orig := str
if hotkey ; parse hotkey label
{
StringReplace, str, str, ^, Ctrl`,
StringReplace, str, str, #, LWin`,RWin`,
StringReplace, str, str, !, Alt`,
StringReplace, str, str, +, Shift`,
StringReplace, str, str, %A_Space%&%A_Space%, `,
if StringR(str, 2) = ",,"
{
StringTrimRight, str, str, 1
str := str . "`,"
}
; msgbox,,, %str_orig% =`n`n%str%, 2
Loop, Parse, str, `,, %A_Space%%A_Tab%
Keywait % A_LoopField
}
else
Loop, Parse, str,, %A_Space%%A_Tab%
Keywait % A_LoopField
}
HotkeyStrCode(str, codeToString = "")
{
if codeToString
{
StringReplace, str, str, +, % " Shift ", all
StringReplace, str, str, ^, % " Ctrl ", all
StringReplace, str, str, #, % " Win ", all
StringReplace, str, str, !, % " Alt ", all
}
else
{
StringReplace, str, str, LShift, +, all
StringReplace, str, str, RShift, +, all
StringReplace, str, str, Shift, +, all
StringReplace, str, str, LCtrl, ^, all
StringReplace, str, str, RCtrl, ^, all
StringReplace, str, str, Ctrl, ^, all
StringReplace, str, str, LWin, #, all
StringReplace, str, str, RWin, #, all
StringReplace, str, str, Win, #, all
StringReplace, str, str, LAlt, !, all
StringReplace, str, str, RAlt, !, all
StringReplace, str, str, Alt, !, all
}
return str
}
Sort(ByRef varName, options="", separator="") ; option DØ = ability to sort on every char
{
if separator =
separator = ¤
ifInString, options, DØ
{
StringReplace, options, options, DØ
varNameLength := StrLen(varName)
Loop, Parse, varName
{
ifNotInString, notRepeated, %A_LoopField%
{
notRepeated = %notRepeated%%A_LoopField%
if (A_Index = varNameLength)
varName1 = %varName1%%A_LoopField%
else
varName1 = %varName1%%A_LoopField%%separator%
}
}
if StringR(varName1, 1) = "¤"
varName1 := StringR(varName1, 260, 1)
Sort varName1, D%separator%
Sort varName1, options
StringReplace, varName1, varName1, ¤,, all
varName = %varName1% ; ByRef changes original
}
else
Sort, varName, options
return varName
}