Files
loongoffice/scripting/workben/bindings/ScriptBinding.xba
2002-11-22 09:11:53 +00:00

987 lines
31 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="ScriptBinding" script:language="StarBasic">REM ***** BASIC *****
REM ----- Global Variables -----
&apos;bindingDialog can refer to either KeyBinding or MenuBinding dialog
private bindingDialog as object
private helpDialog as object
&apos;Array to store lines from the xml file
private xmlFile() as string
&apos;Name of the xml file [writer/calc][menubar/keybindings].xml
private xmlFileName as string
&apos;Number of lines in the xml file
private numberOfLines as integer
&apos;Parallel arrays to store all top-level menu names and line positions
private menuItems() as string
private menuItemLinePosition() as integer
&apos;Counter for the number of top-level menus
private menuCount as integer
&apos;Parallel arrays to store all sub-menu names and line positions for a particular top-level menu
private subMenuItems() as string
private subMenuItemLinePosition() as integer
&apos;Counter for the number of sub-menus
private subMenuCount as integer
&apos;Parallel arrays to store all script names and line positions
private scriptNames() as string
private scriptLinePosition() as integer
&apos;Counter for the number of scripts
private scriptCount as integer
&apos;Array to store all combinations of key bindings
private allKeyBindings() as string
REM ------ Storage Refresh Function ------
sub RefreshUserScripts()
smgr = getProcessServiceManager()
context = smgr.getPropertyValue( &quot;DefaultContext&quot; )
scriptstoragemgr = context.getValueByName( &quot;/singletons/drafts.com.sun.star.script.framework.storage.theScriptStorageManager&quot; )
storage = scriptstoragemgr.getScriptStorage( 1 )
storage.refresh()
end sub
REM ----- Launch Functions -----
Sub ExecuteKeyBinding()
xmlFileName = GetDocumentType( &quot;Key&quot; )
if not (ReadXMLToArray( &quot;Key&quot; )) then
Exit Sub
endif
bindingDialog = LoadDialog( &quot;ScriptBindingLibrary&quot;, &quot;KeyBinding&quot; )
PopulateScriptList()
CreateAllKeyBindings()
PopulateTopLevelKeyBindingList()
PopulateKeyBindingList( 1, 11 )
bindingDialog.execute()
end Sub
Sub ExecuteMenuBinding()
xmlFileName = GetDocumentType( &quot;Menu&quot; )
if not (ReadXMLToArray( &quot;Menu&quot; )) then
Exit Sub
endif
bindingDialog = LoadDialog( &quot;ScriptBindingLibrary&quot;, &quot;MenuBinding&quot; )
PopulateScriptList()
PopulateMenuCombo()
PopulateSubMenuList( 1 )
MenuLabelBoxListener()
bindingDialog.execute()
end Sub
REM ----- Initialising functions -----
function LoadDialog( libName as string, dialogName as string ) as object
dim library as object
dim libDialog as object
dim runtimeDialog as object
libContainer = DialogLibraries
libContainer.LoadLibrary( libName )
library = libContainer.getByName( libname )
libDialog = library.getByName( dialogName )
runtimeDialog = CreateUnoDialog( libDialog )
LoadDialog() = runtimeDialog
end function
function GetDocumentType( bindingType as string ) as string
document = StarDesktop.ActiveFrame.Controller.Model
Dim errornumber As Integer
errornumber = 111
Error errornumber
if document.SupportsService(&quot;com.sun.star.sheet.SpreadsheetDocument&quot;) then
if bindingType = &quot;Key&quot; then
GetDocumentType() = &quot;calckeybinding.xml&quot;
else
if bindingType = &quot;Menu&quot; then
GetDocumentType() = &quot;calcmenubar.xml&quot;
end if
end if
else
if document.SupportsService(&quot;com.sun.star.text.TextDocument&quot;) then
if bindingType = &quot;Key&quot; then
GetDocumentType() = &quot;writerkeybinding.xml&quot;
else
if bindingType = &quot;Menu&quot; then
GetDocumentType() = &quot;writermenubar.xml&quot;
end if
end if
else
msgbox &quot;Couldn&apos;t determine file type&quot;
end if
end if
end function
function GetOfficePath() as string
REM Error check and prompt user to manually input Office Path
settings = CreateUnoService( &quot;com.sun.star.frame.Settings&quot; )
path = settings.getByName( &quot;PathSettings&quot; )
unformattedOfficePath = path.getPropertyValue( &quot;UserPath&quot; )
dim officePath as string
const removeFromEnd = &quot;/user&quot;
const removeFromEndWindows = &quot;\user&quot;
REM If Solaris or Linux
if not ( instr( unformattedOfficePath, removeFromEnd ) = 0 ) then
endPosition = instr( unformattedOfficePath, removeFromEnd )
officePath = mid( unformattedOfficePath, 1, endPosition )
REM If Windows
else if not ( instr( unformattedOfficePath, removeFromEndWindows ) = 0 ) then
endPosition = instr( unformattedOfficePath, removeFromEndWindows )
officePath = mid( unformattedOfficePath, 1, endPosition )
while instr( officePath, &quot;\&quot; ) &gt; 0
backSlash = instr( officePath, &quot;\&quot; )
startPath = mid( officePath, 1, backSlash - 1 )
endPath = mid( officePath, backslash + 1, len( officePath ) - backSlash )
officePath = startPath + &quot;/&quot; + endPath
wend
else
msgbox &quot;Office path not found&quot;
REM Prompt user
end if
end if
GetOfficePath() = officePath
end function
REM ----- File I/O functions -----
function ReadXMLToArray( bindingType as string ) as boolean
On Error Goto ErrorHandler
simplefileaccess = CreateUnoService( &quot;com.sun.star.ucb.SimpleFileAccess&quot; )
filestream = simplefileaccess.openFileRead( &quot;file://&quot; + GetOfficePath() + &quot;user/config/soffice.cfg/&quot; + xmlFileName )
textin = CreateUnoService( &quot;com.sun.star.io.TextInputStream&quot; )
textin.setInputStream( filestream )
redim xmlFile( 400 ) as String
redim menuItems( 30 ) as String
redim menuItemLinePosition( 30 ) as Integer
redim scriptNames( 120 ) as string
redim scriptLinePosition( 120) as integer
lineCount = 1
menuCount = 1
scriptCount = 1
do while not textin.isEOF()
xmlline = textin.readLine()
xmlFile( lineCount ) = xmlline
const menuItemWhiteSpace = 2
const menuXMLTag = &quot;&lt;menu:menu&quot;
&apos;If line read from XML file is a Menu title
if bindingType = &quot;Menu&quot; then
&apos;If the xml line is a top-level menu
if instr( xmlline, menuXMLTag ) = menuItemWhiteSpace then
menuLabel = ExtractLabelFromXMLLine( xmlline )
menuItems( menuCount ) = menuLabel
menuItemLinePosition( menuCount ) = lineCount
menuCount = menuCount + 1
end if
else if bindingType = &quot;Key&quot; then
&apos;If the xml line is a key binding
if instr( xmlFile( lineCount ), &quot;&lt;accel:item&quot; ) &gt; 0 then
scriptName = &quot;&quot;
if instr( xmlFile( lineCount ), &quot;accel:shift=&quot;+chr$(34)+&quot;true&quot;+chr$(34) ) &gt; 0 then
scriptName = scriptName + &quot;SHIFT + &quot;
end if
if instr( xmlFile( lineCount ), &quot;accel:mod1=&quot;+chr$(34)+&quot;true&quot;+chr$(34) ) &gt; 0 then
scriptName = scriptName + &quot;CONTROL + &quot;
end if
scriptName = scriptName + ExtractKeyCodeFromXMLLine( xmlline )
scriptNames( scriptCount ) = scriptName
&apos; msgbox( &quot;scriptNames( &quot; + scriptCount + &quot; ) &quot; + scriptNames( scriptCount ) )
scriptLinePosition( scriptCount ) = lineCount
scriptCount = scriptCount + 1
end if
end if
end if
lineCount = lineCount + 1
loop
&apos;Set global variable numberOfLines (lineCount is one too many at end of the loop)
numberOfLines = lineCount - 1
&apos;Set global variable scriptCount (it is one too many at end of the loop)
scriptCount = scriptCount - 1
&apos;Set global variable menuCount (it is one too many at end of the loop)
menuCount = menuCount - 1
filestream.closeInput()
ReadXMLToArray( ) = true
Exit function
ErrorHandler:
reset
MsgBox (&quot;Error: Unable to read Star Office configuration file - &quot; + xmlFileName + chr$(10) + chr$(10) + &quot;Action: Please reinstall Scripting Framework&quot;,0,&quot;Error&quot; )
ReadXMLToArray( ) = false
end function
Sub WriteXMLFromArray()
On Error Goto ErrorHandler
originalFile = &quot;file:///&quot; + GetOfficePath() + &quot;user/config/soffice.cfg/&quot; + xmlFileName
backupFile = originalFile + &quot;.tmp&quot;
simplefileaccess = CreateUnoService( &quot;com.sun.star.ucb.SimpleFileAccess&quot; )
simplefileaccess.move( originalFile, backupFile )
outfilestream = simplefileaccess.openFileWrite( originalFile )
REM Alternative Debug Lines
&apos;simplefileaccess.kill( &quot;file:///&quot; + GetOfficePath() + &quot;user/config/soffice.cfg/&quot; + xmlFileName + &quot;.temp&quot; )
&apos;outfilestream = simplefileaccess.openFileWrite( &quot;file:///&quot;+ GetOfficePath() + &quot;user/config/soffice.cfg/&quot; + xmlFileName + &quot;.temp&quot; )
textout = CreateUnoService( &quot;com.sun.star.io.TextOutputStream&quot; )
textout.setOutputStream( outfilestream )
for n = 1 to numberOfLines
&apos;If writing the last line then no new line character added
if n = numberOfLines then
textout.writeString( xmlFile(n) )
else
textout.writeString( xmlFile(n) + chr$(10) )
end if
next n
outfilestream.flush()
outfilestream.closeOutput()
if simplefileaccess.exists( backupFile ) then
simplefileaccess.kill( backupFile)
endif
Exit Sub
ErrorHandler:
reset
MsgBox (&quot;Error: Unable to write to Star Office configuration file&quot; + chr$(10) + &quot;/&quot; + GetOfficePath() + &quot;user/config/soffice.cfg/&quot; +xmlFileName + chr$(10) + chr$(10) + &quot;Action: Please make sure you have write access to this file&quot;,0,&quot;Error&quot; )
if simplefileaccess.exists( backupFile ) then
simplefileaccess.move( backupFile, originalFile)
endif
end Sub
REM ----- Array update functions -----
sub AddNewMenuBinding( newScript as string, newMenuLabel as string, newLinePosition as integer )
dim newXmlFile( 400 ) as string
dim newLineInserted as boolean
dim lineCounter as integer
lineCounter = 1
do while lineCounter &lt;= numberOfLines
if not newLineInserted then
REM If the line number is the position at which to insert the new line
if lineCounter = newLinePosition then
if( instr( xmlFile( lineCounter ), &quot;&lt;menu:menupopup&gt;&quot; ) &gt; 0 ) then
msgbox(&quot;It is &lt;menu:menupopup&gt;&quot;)
indent = GetMenuWhiteSpace( xmlFile( newLinePosition + 1 ) )
newXmlFile( lineCounter ) = xmlFile( lineCounter )
newXmlFile( lineCounter + 1 ) = ( indent + &quot;&lt;menu:menuitem menu:id=&quot;+chr$(34)+&quot;script://&quot; + newScript + chr$(34)+&quot; menu:helpid=&quot;+chr$(34)+&quot;1929&quot;+chr$(34)+&quot; menu:label=&quot;+chr$(34)+ newMenuLabel + chr$(34)+&quot;/&gt;&quot; )
else
msgbox(&quot;It is NOT &lt;menu:menupopup&gt;&quot;)
indent = GetMenuWhiteSpace( xmlFile( newLinePosition - 1 ) )
newXmlFile( lineCounter ) = ( indent + &quot;&lt;menu:menuitem menu:id=&quot;+chr$(34)+&quot;script://&quot; + newScript + chr$(34)+&quot; menu:helpid=&quot;+chr$(34)+&quot;1929&quot;+chr$(34)+&quot; menu:label=&quot;+chr$(34)+ newMenuLabel + chr$(34)+&quot;/&gt;&quot; )
newXmlFile( lineCounter + 1 ) = xmlFile( lineCounter )
end if
REM added -1 for debug --&gt;
&apos; indent = GetMenuWhiteSpace( xmlFile( newLinePosition ) )
&apos; newXmlFile( lineCounter ) = ( indent + &quot;&lt;menu:menuitem menu:id=&quot;+chr$(34)+&quot;script://&quot; + newScript + chr$(34)+&quot; menu:helpid=&quot;+chr$(34)+&quot;1929&quot;+chr$(34)+&quot; menu:label=&quot;+chr$(34)+ newMenuLabel + chr$(34)+&quot;/&gt;&quot; )
&apos; newXmlFile( lineCounter + 1 ) = xmlFile( lineCounter )
newLineInserted = true
else
newXmlFile( lineCounter ) = xmlFile( lineCounter )
end if
else
REM if the new line has been inserted the read from one position behind
newXmlFile( lineCounter + 1 ) = xmlFile( lineCounter )
end if
lineCounter = lineCounter + 1
loop
numberOfLines = numberOfLines + 1
REM read the new file into the global array
for n = 1 to numberOfLines
xmlFile( n ) = newXmlFile( n )
next n
end sub
sub AddNewKeyBinding( scriptName as string, shift as boolean, control as boolean, key as string )
dim keyCombo as string
newLine = &quot; &lt;accel:item accel:code=&quot;+chr$(34)+&quot;KEY_&quot; + key +chr$(34)
if shift then
keyCombo = &quot;SHIFT + &quot;
newLine = newLine + &quot; accel:shift=&quot;+chr$(34)+&quot;true&quot;+chr$(34)
end if
if control then
keyCombo = keyCombo + &quot;CONTROL + &quot;
newLine = newLine + &quot; accel:mod1=&quot;+chr$(34)+&quot;true&quot;+chr$(34)
end if
keyCombo = keyCombo + key
newLine = newLine + &quot; xlink:href=&quot;+chr$(34)+&quot;script://&quot; + scriptName
REM For this release of the scripting framework only use application binding
applicationBinding = true
if applicationBinding then
newLine = newLine + &quot;?location=application&quot;+chr$(34)+&quot;/&gt;&quot;
else
newLine = newLine + &quot;?location=document&quot;+chr$(34)+&quot;/&gt;&quot;
end if
scriptNames( scriptCount ) = keyCombo
scriptLinePosition( scriptCount ) = numberOfLines
scriptCount = scriptCount + 1
for n = 1 to numberOfLines
if n = numberOfLines then
xmlFile( n ) = newLine
xmlFile( n + 1 ) = &quot;&lt;/accel:acceleratorlist&gt;&quot;
exit for
else
xmlFile( n ) = xmlFile( n )
end if
next n
numberOfLines = numberOfLines + 1
end sub
sub RemoveBinding( removeLinePosition as integer )
dim newXmlFile( 400 ) as string
dim lineRemoved as boolean
lineRemoved = false
for n = 1 to numberOfLines
if not lineRemoved then
if not( n = removeLinePosition ) then
newXmlFile( n ) = xmlFile( n )
else
newXmlFile( n ) = xmlFile( n + 1 )
lineRemoved = true
end if
else
newXmlFile( n ) = xmlFile( n + 1 )
end if
next n
numberOfLines = numberOfLines - 1
REM read the new file into the global array
for n = 1 to numberOfLines
xmlFile( n ) = newXmlFile( n )
next n
end sub
REM Adds or removes the starting xml line positions for each top-level menu after the menu with the added script
sub UpdateTopLevelMenus( topLevelMenuPosition as integer, addLine as boolean )
for n = topLevelMenuPosition to 8
if addLine then
menuItemLinePosition( n ) = menuItemLinePosition( n ) + 1
else
menuItemLinePosition( n ) = menuItemLinePosition( n ) - 1
end if
next n
end sub
REM Remove scriptNames and scriptLinePosition entries
sub RemoveScriptNameAndPosition( keyComboPosition )
dim updatedScriptNames( 120 ) as string
dim updatedScriptLinePosition( 120 ) as integer
dim removedScript as boolean
removedScript = false
for n = 1 to scriptCount
if not removedScript then
if not( n = keyComboPosition ) then
updatedScriptNames( n ) = scriptNames( n )
else
removedScript = true
end if
else
updatedScriptNames( n - 1 ) = scriptNames( n )
end if
next n
scriptCount = scriptCount - 1
for n = 1 to scriptCount
scriptNames( n ) = updatedScriptNames( n )
next n
end sub
REM ----- Populating Dialog Controls -----
sub PopulateScriptList()
scriptList = bindingDialog.getControl( &quot;ScriptList&quot; )
scriptList.removeItems( 0, scriptList.getItemCount() )
smgr = getProcessServiceManager()
context = smgr.getPropertyValue( &quot;DefaultContext&quot; )
scriptstoragemgr = context.getValueByName( &quot;/singletons/drafts.com.sun.star.script.framework.storage.theScriptStorageManager&quot; )
storage = scriptstoragemgr.getScriptStorage( 1 )
logicalNames() = storage.getScriptLogicalNames()
for n = 1 to ubound( logicalNames() ) + 1
scriptList.addItem( logicalNames( n - 1 ), n )
next n
scriptList.selectItemPos( 0, true )
end sub
sub PopulateMenuCombo()
menuComboBox = bindingDialog.getControl( &quot;MenuCombo&quot; )
menuComboBox.removeItems( 0, menuComboBox.getItemCount() )
for n = 1 to menuCount
menuComboBox.addItem( menuItems( n ), n - 1 )
next n
menuComboBox.setDropDownLineCount( 8 )
menuComboBox.text = menuComboBox.getItem( 0 )
end sub
sub PopulateSubMenuList( menuItemPosition as integer )
redim subMenuItems( 100 ) as string
redim subMenuItemLinePosition( 100 ) as integer
dim lineNumber as integer
const menuItemWhiteSpace = 4
const menuXMLTag = &quot;&lt;menu:menu&quot;
subMenuCount = 1
REM xmlStartLine and xmlEndLine refer to the first and last lines
&apos; menuItemPosition of a top-level menu ( 1=File to 8=Help ) add one line
xmlStartLine = menuItemLinePosition( menuItemPosition ) + 1
REM If last menu item is chosen
if menuItemPosition = menuCount then
xmlEndLine = numberOfLines
else
REM Other wise get the line before the next top-level menu begins
xmlEndLine = menuItemLinePosition( menuItemPosition + 1 ) - 1
end if
for lineNumber = xmlStartLine to xmlEndLine
REM Insert all sub-menus and sub-popupmenus
if not( instr( xmlFile( lineNumber ), menuXMLTag ) = 0 ) and instr( xmlFile( lineNumber ), &quot;menupopup&quot;) = 0 then
subMenuIndent = GetMenuWhiteSpace( xmlFile( lineNumber ) )
if subMenuIndent = &quot; &quot; then
subMenuIndent = &quot;&quot;
else
subMenuIndent = subMenuIndent + subMenuIndent
end if
if not( instr( xmlFile( lineNumber ), &quot;menuseparator&quot; ) = 0 ) then
subMenuItems( subMenuCount ) = subMenuIndent + &quot;----------------&quot;
else
subMenuName = ExtractLabelFromXMLLine( xmlFile( lineNumber ) )
REM Add script Name if there is one bound to menu item
if instr( xmlFile( lineNumber ), &quot;script://&quot; ) &gt; 0 then
script = ExtractScriptIdFromXMLLine( xmlFile( lineNumber ) )
subMenuItems( subMenuCount ) = ( subMenuIndent + subMenuName + &quot; [&quot; + script + &quot;]&quot; )
else
subMenuItems( subMenuCount ) = subMenuIndent + subMenuName
end if
end if
subMenuItemLinePosition( subMenuCount ) = lineNumber
subMenuCount = subMenuCount + 1
end if
next lineNumber
subMenuList = bindingDialog.getControl( &quot;SubMenuList&quot; )
currentPosition = subMenuList.getSelectedItemPos()
subMenuList.removeItems( 0, subMenuList.getItemCount() )
for n = 1 to subMenuCount - 1
subMenuList.addItem( subMenuItems( n ), n - 1 )
next n
subMenuList.selectItemPos( currentPosition, true )
SubMenuListListener()
end sub
sub PopulateTopLevelKeyBindingList()
keyCombo = bindingDialog.getControl( &quot;KeyCombo&quot; )
keyCombo.removeItems( 0, keyCombo.getItemCount() )
keyCombo.addItem( &quot;SHIFT + CONTROL + F keys&quot;, 0 )
keyCombo.addItem( &quot;SHIFT + CONTROL + digits&quot;, 1 )
keyCombo.addItem( &quot;SHIFT + CONTROL + letters&quot;, 2 )
keyCombo.addItem( &quot;CONTROL + F keys&quot;, 3 )
keyCombo.addItem( &quot;CONTROL + digits&quot;, 4 )
keyCombo.addItem( &quot;CONTROL + letters&quot;, 5 )
keyCombo.addItem( &quot;SHIFT + F keys&quot;, 6 )
keyCombo.setDropDownLineCount( 7 )
keyCombo.text = keyCombo.getItem( 0 )
end sub
sub PopulateKeyBindingList( startPosition as integer, endPosition as integer )
dim formattedKeyBinding( 47 ) as string
counter = 1
keyList = bindingDialog.getControl( &quot;KeyList&quot; )
for n = startPosition to endPosition
REM If key combo is a script the value returned is the line position
if IsAllocatedKeyCombo( allKeyBindings( n ) ) &gt; 1 then
formattedKeyBinding( counter ) = ( allKeyBindings( n ) + &quot; [Allocated to &quot; + ExtractScriptIdFromXMLLine( xmlFile( isAllocatedKeyCombo( allKeyBindings( n ) ) ) ) + &quot;]&quot; )
REM If key combo is an Office function 1 is returned
else if IsAllocatedKeyCombo( allKeyBindings( n ) ) = 1 then
formattedKeyBinding( counter ) = ( allKeyBindings( n ) + &quot; [Allocated to Office function]&quot; )
REM If key combo is unallocated 0 is returned
else
formattedKeyBinding( counter ) = allKeyBindings( n )
end if
end if
counter = counter + 1
next n
currentPosition = keyList.getSelectedItemPos()
keyList.removeItems( 0, keyList.getItemCount() )
for n = 1 to counter - 1
keyList.addItem( formattedKeyBinding( n ), n - 1 )
next n
keyList.selectItemPos( currentPosition, true )
KeyListListener()
end sub
sub CreateAllKeyBindings()
reDim allKeyBindings( 105 ) as string
keyBindingPosition = 1
for FKey = 2 to 12
allKeyBindings( keyBindingPosition ) = &quot;SHIFT + CONTROL + F&quot; + FKey
keyBindingPosition = keyBindingPosition + 1
next FKey
for Digit = 0 to 9
allKeyBindings( keyBindingPosition ) = &quot;SHIFT + CONTROL + &quot; + Digit
keyBindingPosition = keyBindingPosition + 1
next Digit
for Alpha = 65 to 90
allKeyBindings( keyBindingPosition ) = &quot;SHIFT + CONTROL + &quot; + chr$( Alpha )
keyBindingPosition = keyBindingPosition + 1
next Alpha
for FKey = 2 to 12
allKeyBindings( keyBindingPosition ) = &quot;CONTROL + F&quot; + FKey
keyBindingPosition = keyBindingPosition + 1
next FKey
for Digit = 0 to 9
allKeyBindings( keyBindingPosition ) = &quot;CONTROL + &quot; + Digit
keyBindingPosition = keyBindingPosition + 1
next Digit
for Alpha = 65 to 90
allKeyBindings( keyBindingPosition ) = &quot;CONTROL + &quot; + chr$( Alpha )
keyBindingPosition = keyBindingPosition + 1
next Alpha
for FKey = 2 to 12
allKeyBindings( keyBindingPosition ) = &quot;SHIFT + F&quot; + FKey
keyBindingPosition = keyBindingPosition + 1
next FKey
end sub
REM ----- Text Handling Functions -----
function ExtractLabelFromXMLLine( XMLLine as string ) as string
labelStart = instr( XMLLine, &quot;label=&quot;+chr$(34)) + 7
labelEnd = instr( XMLLine, chr$(34)+&quot;&gt;&quot; )
if labelEnd = 0 then
labelEnd = instr( XMLLine, chr$(34)+&quot;/&gt;&quot; )
end if
labelLength = labelEnd - labelStart
menuLabelUnformatted = mid( XMLLine, labelStart, labelLength )
tildePosition = instr( menuLabelUnformatted, &quot;~&quot; )
select case tildePosition
case 0
menuLabel = menuLabelUnformatted
case 1
menuLabel = right( menuLabelUnformatted, labelLength - 1 )
case else
menuLabelLeft = left( menuLabelUnformatted, tildePosition - 1 )
menuLabelRight = right( menuLabelUnformatted, labelLength - tildePosition )
menuLabel = menuLabelLeft + menuLabelRight
end select
ExtractLabelFromXMLLine() = menuLabel
end function
function ExtractScriptIdFromXMLLine( XMLLine as string ) as string
idStart = instr( XMLLine, &quot;script://&quot;) + 9
if instr( XMLLine, &quot;&quot;+chr$(34)+&quot; menu:helpid=&quot; ) = 0 then
idEnd = instr( XMLLIne, &quot;?location=&quot; )
else
idEnd = instr( XMLLine, &quot;&quot;+chr$(34)+&quot; menu:helpid=&quot; )
end if
idLength = idEnd - idStart
scriptId = mid( XMLLine, idStart, idLength )
ExtractScriptIdFromXMLLine() = scriptId
end function
function ExtractKeyCodeFromXMLLine( XMLLine as string ) as string
keyStart = instr( XMLLine, &quot;code=&quot;+chr$(34)+&quot;KEY_&quot;) + 10
keyCode = mid( XMLLine, keyStart, ( len( XMLLine ) - keyStart ) )
keyEnd = instr( keyCode, chr$(34) )
keyCode = mid( keyCode, 1, keyEnd - 1 )
ExtractKeyCodeFromXMLLine() = keyCode
end function
function GetMenuWhiteSpace( MenuXMLLine as string ) as string
whiteSpace = &quot;&quot;
numberOfSpaces = instr( MenuXMLLine, &quot;&lt;&quot; ) - 1
for i = 1 to numberOfSpaces
whiteSpace = whiteSpace + &quot; &quot;
next i
GetMenuWhiteSpace() = whiteSpace
end function
function IsAllocatedKeyCombo( script as string ) as integer
const NotAllocated = 0
const AllocatedToOfficeFunction = 1
const AllocatedToScript = 2
dim Allocation as integer
if instr( script, &quot; [Allocated&quot; ) &gt; 0 then
endPosition = instr( script, &quot; [Allocated&quot; ) - 1
script = mid( script, 1, endPosition )
end if
Allocation = NotAllocated
count = 1
while Allocation = NotAllocated and count &lt; scriptCount
linePosition = scriptLinePosition( count )
if strcomp( script, scriptNames( count ) ) = 0 then
if instr( xmlFile( linePosition ), &quot;script://&quot; ) &gt; 0 then
Allocation = linePosition
else
Allocation = AllocatedToOfficeFunction
end if
end if
count = count + 1
wend
msgbox( &quot; IsAllocatedKeyCombo() script: &quot; + script + &quot; Allocation: &quot; + Allocation )
IsAllocatedKeyCombo() = Allocation
end Function
function IsAllocatedMenuItem( script as string ) as boolean
foundMenuItem = false
Allocated = false
count = 0
do
count = count + 1
if strcomp( script, subMenuItems( count ) ) = 0 then
foundMenuItem = true
end if
loop while not( foundMenuItem ) and count &lt; subMenuCount
linePosition = subMenuItemLinePosition( count )
if not( instr( xmlFile( linePosition ), &quot;script://&quot; ) = 0 ) then
Allocated = true
end if
isAllocatedMenuItem() = Allocated
end Function
function HasShiftKey( keyCombo ) as boolean
if instr( keyCombo, &quot;SHIFT&quot; ) = 0 then
hasShift = false
else
hasShift = true
end if
HasShiftKey = hasShift
end function
function HasControlKey( keyCombo ) as boolean
if instr( keyCombo, &quot;CONTROL&quot; ) = 0 then
hasControl = false
else
hasControl = true
end if
HasControlKey = hasControl
end function
function ExtractKeyFromCombo( keyString as string ) as string
while not( instr( keyString, &quot;+&quot; ) = 0 )
removeTo = instr( keyString, &quot;+ &quot; ) + 2
keyString = mid( keyString, removeTo, ( len( keyString ) - removeTo ) + 1 )
wend
ExtractKeyFromCombo() = keyString
end function
REM ------ Event Handling Functions (Listeners) ------
sub KeyListListener()
keyList = bindingDialog.getControl( &quot;KeyList&quot; )
selectedKeyCombo = keyList.getSelectedItem()
if isAllocatedKeyCombo( selectedKeyCombo ) &gt; 1 then
bindingDialog.Model.Delete.enabled = true
bindingDialog.Model.NewButton.enabled = false
else
if isAllocatedKeyCombo( selectedKeyCombo ) = 1 then
bindingDialog.Model.Delete.enabled = false
bindingDialog.Model.NewButton.enabled = false
else
bindingDialog.Model.Delete.enabled = false
bindingDialog.Model.NewButton.enabled = true
end if
end if
end sub
sub SubMenuListListener()
subMenuList = bindingDialog.getControl( &quot;SubMenuList&quot; )
selectedMenuItem = subMenuList.getSelectedItem()
if IsAllocatedMenuItem( selectedMenuItem ) then
bindingDialog.Model.Delete.enabled = true
else
bindingDialog.Model.Delete.enabled = false
end if
end sub
&apos;Populates the SubMenuList with the appropriate menu items from the Top-level menu selected from the combo box
sub MenuComboListener()
combo = bindingDialog.getControl( &quot;MenuCombo&quot; )
newToplevelMenu = combo.text
counter = 0
do
counter = counter + 1
loop while not( newToplevelMenu = menuItems( counter ) )
PopulateSubMenuList( counter )
end sub
&apos;Populates the KeyList with the appropriate key combos from the Top-level key group selected from the combo box
sub KeyComboListener()
combo = bindingDialog.getControl( &quot;KeyCombo&quot; )
itemSelected = combo.text
select case itemSelected
case &quot;SHIFT + CONTROL + F keys&quot;
PopulateKeyBindingList( 1, 11 )
case &quot;SHIFT + CONTROL + digits&quot;
PopulateKeyBindingList( 12, 21 )
case &quot;SHIFT + CONTROL + letters&quot;
PopulateKeyBindingList( 22, 47 )
case &quot;CONTROL + F keys&quot;
PopulateKeyBindingList( 48, 58 )
case &quot;CONTROL + digits&quot;
PopulateKeyBindingList( 59, 68 )
case &quot;CONTROL + letters&quot;
PopulateKeyBindingList( 69, 94 )
case &quot;SHIFT + F keys&quot;
PopulateKeyBindingList( 95, 105 )
case else
msgbox &quot;Error&quot;
end select
end sub
sub MenuLabelBoxListener()
if bindingDialog.Model.MenuLabelBox.text = &quot;&quot; then
bindingDialog.Model.NewButton.enabled = false
else
bindingDialog.Model.NewButton.enabled = true
end if
end sub
REM ------ Event Handling Functions (Buttons) ------
sub MenuOKButton()
msgbox (&quot;Office must be restarted before your changes will take effect.&quot;+ chr$(10)+&quot;Also close the Office QuickStarter (Windows and some Linux)&quot;, 48, &quot;Assign Script (Java) To Menu&quot; )
WriteXMLFromArray()
bindingDialog.endExecute()
end sub
sub MenuCancelButton()
bindingDialog.endExecute()
end sub
sub MenuHelpButton()
helpDialog = LoadDialog( &quot;ScriptBindingLibrary&quot;, &quot;HelpBinding&quot; )
helpDialog.execute()
end sub
sub MenuDeleteButton()
subMenuList = bindingDialog.getControl( &quot;SubMenuList&quot; )
linePos = subMenuItemLinePosition( subMenuList.getSelectedItemPos() + 1 )
RemoveBinding( linePos )
REM Update the top-level menu&apos;s line positions
combo = bindingDialog.getControl( &quot;MenuCombo&quot; )
newToplevelMenu = combo.text
counter = 0
do
counter = counter + 1
loop while not( newToplevelMenu = menuItems( counter ) )
UpdateTopLevelMenus( counter + 1, false )
MenuComboListener()
end sub
sub MenuNewButton()
menuScriptList = bindingDialog.getControl( &quot;ScriptList&quot; )
script = menuScriptList.getSelectedItem()
newMenuLabel = bindingDialog.Model.MenuLabelBox.text
subMenuList = bindingDialog.getControl( &quot;SubMenuList&quot; )
REM Update the top-level menu&apos;s line positions
combo = bindingDialog.getControl( &quot;MenuCombo&quot; )
newToplevelMenu = combo.text
counter = 0
do
counter = counter + 1
loop while not( newToplevelMenu = menuItems( counter ) )
UpdateTopLevelMenus( counter + 1, true )
REM New line position is one ahead of the selected sub menu item
linePos = subMenuItemLinePosition( subMenuList.getSelectedItemPos() + 1 ) + 1
AddNewMenuBinding( script, newMenuLabel, linePos )
MenuComboListener()
end sub
sub KeyOKButton()
msgbox (&quot;Office must be restarted before your changes will take effect.&quot;+ chr$(10)+&quot;Also close the Office QuickStarter (Windows and some Linux)&quot;, 48, &quot;Assign Script (Java) To Key&quot; )
WriteXMLFromArray()
bindingDialog.endExecute()
end sub
sub KeyCancelButton()
bindingDialog.endExecute()
end sub
sub KeyHelpButton()
helpDialog = LoadDialog( &quot;ScriptBindingLibrary&quot;, &quot;HelpBinding&quot; )
helpDialog.execute()
end sub
sub KeyNewButton()
menuScriptList = bindingDialog.getControl( &quot;ScriptList&quot; )
script = menuScriptList.getSelectedItem()
keyList = bindingDialog.getControl( &quot;KeyList&quot; )
keyCombo = keyList.getSelectedItem()
AddNewKeyBinding( script, HasShiftKey( keyCombo ), HasControlKey( keyCombo ), ExtractKeyFromCombo( keyCombo ) )
KeyComboListener()
end sub
sub KeyDeleteButton()
keyList = bindingDialog.getControl( &quot;KeyList&quot; )
REM Check that combo is a script
keyCombo = keyList.getSelectedItem()
if instr( keyCombo, &quot; [Allocated&quot; ) &gt; 0 then
endPosition = instr( keyCombo, &quot; [Allocated&quot; ) - 1
keyCombo = mid( keyCombo, 1, endPosition )
end if
for n = 1 to scriptCount
if strcomp( keyCombo, scriptNames( n ) ) = 0 then
keyComboPosition = n
exit for
end if
next n
linePosition = scriptLinePosition( keyComboPosition )
REM remove scriptNames and scriptLinePosition entries
RemoveScriptNameAndPosition( keyComboPosition )
RemoveBinding( linePosition )
script = ExtractScriptIdFromXMLLine( xmlFile( linePosition ) )
KeyComboListener()
end sub
sub HelpOKButton()
helpDialog.endExecute()
end sub</script:module>