REM @author Philippe Prados philippe.prados@atosorigin.com REM @author Romain Pelisse romain.pelisse@atosorigin.com REM @author Manuel Odesser modesser@linagora.com REM @author Laurent Godard Option Explicit REM REM Data for the service layer REM Private Const USE_ON_ERROR = true ' Hide some errors Private Const selectWord = true ' Select current word to update Private Const defaultStartup = true REM data for the functionnality part Private results as Object ' Array of results from the last search for foreign term Private result as Object ' Current result to manage Private currentResult as Integer ' index of the current row in the results table Private oldViewCursor as Object ' Cursor on the current selection Private cursor as Object ' Cursor on the current selection Global IgnoreTermArray(0) as String Private ignoreIdx as integer ' Focus current words to ignore ' Lors de l'analyse du document ou d'une selection, le focus est à -1 ' Sinon, il permet de selectionner depuis les candidats, que ceux incluant le focus ' Cela permet d'éviter d'avoir à ignorer plusieurs fois, des mots avant ou après le focus Private exitCode as integer ' OK or Cancel Global maxwords as Long ' Max number of world to analyse, before and after cursor Private ReplaceArray(0) as String Private ReplacementArray(0) as String Private posCurrent as Integer ' Cursor position in relation to selection Private withInsecable as boolean ' true if plugin insecable is present REM REM data for the HMI layer REM Dim mainDialog as Object ' Current dialog objet Private Const dialogueLibraryName = "terminologie" Private Const sDialogName = "dialogues" Private Const REMPLACEMENT_FIELD_NAME = "remplacement" Private Const TITLE = "Correcteur terminologique" REM Retreives the running OOO version REM http://www.oooforum.org/forum/viewtopic.phtml?t=10003&highlight=getsolarversion REM @author : Romain PELISSE REM @author : Laurent Godard REM Global OOoVersion_ as String Function OOoVersion() As String If ( OOoVersion_ = "" ) Then Dim aSettings, aConfigProvider Dim aParams2(0) As new com.sun.star.beans.PropertyValue Dim sProvider$, sAccess$ sProvider = "com.sun.star.configuration.ConfigurationProvider" sAccess = "com.sun.star.configuration.ConfigurationAccess" aConfigProvider = createUnoService(sProvider) aParams2(0).Name = "nodepath" aParams2(0).Value = "/org.openoffice.Setup/Product" aSettings = aConfigProvider.createInstanceWithArguments(sAccess, aParams2()) _OOoVersion = aSettings.getByName("ooSetupVersion") End If OOOVersion = _OOoVersion End Function REM REM Retrieve and build the Uno Service associated with this plugin, if and REM only if the service as not already be fetched. REM REM @author Romain PELISSE romain.pelisse@atosorigin.com REM Global terminologieService_ as Object ' Singleton Function terminologieService() as Object if isNull(terminologieService_) then terminologieService_ = createUnoService( "org.atosorigin.ctOO.comp.CtOO3" ) maxwords = terminologieService_.maxwords end if if (isnull(terminologieService_)) then msgbox("Java module not found",0,TITLE) end if terminologieService=terminologieService_ End Function REM ********************************************************************************************** REM ********************************************************************************************** REM FUNCTIONNALITY METHODS REM ********************************************************************************************** REM ********************************************************************************************** ' Manage current selection Sub ManageSelection() Dim viewCursor as object Dim theText as Object Dim theCursor as Object Dim abort as boolean Redim IgnoreTermArray(0) Redim ReplaceArray(0) Redim ReplacementArray(0) viewCursor=ThisComponent.currentController.viewCursor if not isEmpty(viewCursor.Cell) then theText=viewCursor.Cell else theText=viewCursor.Text endif oldViewCursor=theText.createTextCursorByRange(viewCursor) theCursor=theText.createTextCursorByRange(viewCursor) poscurrent=-1 abort=ManageMixedCursor(theText,theCursor) oldViewCursor.collapseToEnd() viewCursor.gotoRange(oldViewCursor,FALSE) if not abort then msgbox "La vérification de la sélection a été effectuée.",0,TITLE end if end sub ' Manage all document Sub ManageDocument() Dim viewCursor as object Dim listParagraph as Object Dim paraCursor as Object Dim elementText as Object if USE_ON_ERROR then on error goto Ignore ' Trap to all errors endif Redim IgnoreTermArray(0) Redim ReplaceArray(0) Redim ReplacementArray(0) Dim abort as boolean abort=false viewCursor=ThisComponent.currentController.viewCursor oldViewCursor=viewCursor.Text.createTextCursorByRange(viewCursor) poscurrent=-1 ' Paragraphes abort=manageParagraphs(nothing,ThisComponent.text,ThisComponent.text.createEnumeration()) ' Header & footer if (not abort) then Dim pagesStyles as Object Dim pageStyle as Object Dim i as Integer Dim headerCursor Dim footerCursor pagesStyles=ThisComponent.StyleFamilies.getByName("PageStyles") for i = 0 to pagesStyles.count-1 pageStyle=pagesStyles.getByIndex(i) if pageStyle.headerIsOn then headerCursor=pageStyle.headerText.createTextCursor headerCursor.gotoStart(false) headerCursor.gotoEnd(true) cursor=headerCursor if (not ManageCursor) then abort=true exit for end if end if if pageStyle.footerIsOn then footerCursor=pageStyle.footerText.createTextCursor footerCursor.gotoStart(false) footerCursor.gotoEnd(true) cursor=footerCursor if (not ManageCursor) then abort=true exit for end if end if next end if ' End Ignore: if USE_ON_ERROR then on error goto EndFn ' Trap to all errors endif oldViewCursor.collapseToEnd() viewCursor.gotoRange(oldViewCursor,FALSE) if not abort then msgbox "La vérification du document a été effectuée.",0,TITLE end if EndFn: End sub REM REM Handles the event 'key pressed by user'. REM @author Romain PELISSE REM @author Manuel Odesser modesser@linagora.com REM Global count as Integer Function ManageKeyPressedEvent(keyEvent As Object) As Boolean ManageKeyPressedEvent = True REM whatever happen, let the event propagate to other event handler If ( isWordBoundary(keyEvent) ) Then Dim viewCursor as Object Dim contextCursor as Object Dim theText as Object if USE_ON_ERROR then on error goto Ignore endif viewCursor = ThisComponent.currentController.viewCursor if not isEmpty(viewCursor.Cell) then theText=viewCursor.Cell else theText=viewCursor.Text endif oldViewCursor = theText.createTextCursorByRange(viewCursor) contextCursor = theText.createTextCursorByRange(oldViewCursor) contextCursor = selectPart(contextCursor.getText(),maxwords) REM We keep running the dialog until we end Redim IgnoreTermArray(0) ' Remove last cr ' poscurrent=poscurrent-1 poscurrent=poscurrent-2 ' REM Recule encore de 1 pour gérer l'espace insécable ManageMixedCursor(theText,contextCursor) ThisComponent.CurrentController.select(oldViewCursor) ' if ThisComponent.currentSelection.supportsService("com.sun.star.text.TextTableCursor") then ' viewCursor.collapseToEnd() ' viewCursor.goRight(1,false) ' else ' viewCursor.gotoRange(oldViewCursor,FALSE) ' Selection toute la ligne d'un tableau lors d'un changement de cellule ' endif End If Ignore: End Function ' Execute engine for the cursor variable function ManageMixedCursor(theText as Object,contextCursor as Object) as boolean Dim abort as boolean if USE_ON_ERROR then on error goto Ignore ' Trap to all errors endif if ThisComponent.currentSelection.supportsService("com.sun.star.text.TextRanges") then abort=ManageParagraphs(contextCursor,theText,contextCursor.createEnumeration()) elseif ThisComponent.currentSelection.supportsService("com.sun.star.text.TextTableCursor") then ' Selection dans un tableau Dim table as object table = ThisComponent.TextTables.getByName(ThisComponent.currentController.viewCursor.TextTable.Name) ' Patch temporaire abort=ManageArray(table) end if ManageMixedCursor=abort Ignore: End Function ' ------------------------------------------------------- ' Manage all paragraph and table Function ManageParagraphs(theCursor as Object,theText as Object, listParagraph as Object) as boolean dim elementText as object dim paraCursor as object dim newParaCursor as object if USE_ON_ERROR then on error goto Ignore ' Trap to all errors endif ' Paragraphes newParaCursor=theText.createTextCursor() do while listParagraph.hasMoreElements elementText = listParagraph.nextElement if (elementText.supportsService("com.sun.star.text.Paragraph")) then paraCursor=theText.createTextCursorByRange(elementText,true) dim l as integer l=len(getOnlyText(paraCursor))+1 ' Ajuste the begin and end to the cursor if not isNull(theCursor) then on error goto IgnoreAdjuste if (theText.compareRegionStarts(paraCursor.start,theCursor.start) > 0) then newParaCursor.gotoRange(theCursor.start,false) newParaCursor.gotoRange(paraCursor.end,true) paraCursor=newParaCursor endif if (theText.compareRegionStarts(paraCursor.end,theCursor.end) < 0) then newParaCursor.gotoRange(paraCursor.start,false) newParaCursor.gotoRange(theCursor.end,true) paraCursor=newParaCursor endif IgnoreAdjuste: endif cursor=paraCursor if (not isNull(paraCursor)) then if (not ManageCursor) then ManageParagraphs=true exit do end if end if if (poscurrent <> -1) then poscurrent=poscurrent - l end if elseif elementText.supportsService("com.sun.star.text.TextTable") Then ManageParagraphs=ManageArray(elementText) end if if (ManageParagraphs) then exit do end if loop Ignore: end function Function ManageCursor() as boolean exitCode=com.sun.star.ui.dialogs.ExecutableDialogResults.CANCEL results=nothing ignoreIdx=0 REM We keep running the dialog until we end if ( getWorkload() ) Then mainDialog.execute() if (exitCode = com.sun.star.ui.dialogs.ExecutableDialogResults.OK) then ManageCursor=true end if else ManageCursor=true end if End Function Function ManageArray(array as object) Dim cell as Object dim index as integer for index = LBound(array.CellNames) to UBound(array.CellNames) cell=array.getCellByName(array.CellNames(index)) if not isNull(cell) then cursor=cell.createTextCursor() cursor.gotoStart(false) cursor.gotoEnd(true) if (not ManageCursor) then ManageArray=true exit for end if end if next end function ' ----------------------------------------------------- ' Iterator in text Sub Iterator_init() currentResult=-1 End Sub Function Iterator_next() as Integer currentResult = currentResult + 1 Iterator_next=currentResult End Function Function Iterator_HasNext() as boolean if isNull(results) then Iterator_HasNext=false elseif UBound(results)=-1 then Iterator_HasNext=false else Dim i as Integer i = UBound(results) dim b as boolean b=(currentResult < UBound(results)) Iterator_HasNext=b end if End Function Function Iterator_cur() as Integer Iterator_cur=currentResult End Function ' ----------------------------------------------------- ' Engine to find next words to manage, and auto ignore/replace or ask user Function getWorkload() as Boolean Dim replaceCursor as Object Dim continue as boolean Dim breakloop as boolean Dim remplacement as String getWorkload = true if isNull(results) then results=checkSelection(cursor) Iterator_init() currentResult = currentResult + ignoreIdx end if do breakloop=false if isArray(results) then do continue=false if (poscurrent=-1) then Iterator_next() else ' Filtre sur les candidats incluant le focus do Iterator_next() if (Iterator_cur() > UBound(results) ) then exit do end if result=results(Iterator_cur) loop while not (result.start<=poscurrent and poscurrent <= result.start+result.len ) currentResult = currentResult + ignoreIdx end if if isArray(results) then if Iterator_cur() <= UBound(results) then result=results(Iterator_cur) remplacement = getReplacementTerm(result) if (remplacement<> "") then replaceCursor = createCursorPartOfText(cursor,result) REM Case where replace by himself if checkRecurs(replaceCursor.String,remplacement) then ignoreIdx= IgnoreIdx + 1 end if replaceCursor.String = remplacement results=checkSelection(cursor) Iterator_init() currentResult = currentResult + ignoreIdx continue=true elseif ( NOT isIgnoreTerm(result)) then breakloop=true else ignoreIdx= IgnoreIdx + 1 continue=true end if end if end if loop while continue if (breakloop) then exit do end if end if loop while Iterator_HasNext() if isArray(results) then if Iterator_cur > UBound(results) then REM Iterator_cur = -1 or Iterator_cur > UBound(results) then Dialog_Close() getWorkload = false ' It's necessary to open the dialog Else if (selectWord) then ThisComponent.CurrentController.select(createCursorPartOfText(cursor,result)) else createCursorPartOfText(cursor,result) endif Dialog_set(result) end if else Dialog_Close() getWorkload = false ' It's necessary to open the dialog end if End Function REM Return true if the term must be ignored Function IsIgnoreTerm(result as object) as boolean IsIgnoreTerm=false REM Check ignore term Dim word as string word = getPartOfText(cursor,result) 'FIXME: renv. string dans result if not isNull(IgnoreTermArray) then Dim index as Integer for index = LBound(IgnoreTermArray) to UBound(IgnoreTermArray) if StrComp(IgnoreTermArray(index),word,0)=0 then IsIgnoreTerm=true exit for end if next end if End Function REM Return empty string or the replacement term Function getReplacementTerm(result as object) as string getReplacementTerm = "" ' Check ignore term Dim word as string word = getPartOfText(cursor,result) 'FIXME: renv. string dans result if not isNull(ReplaceArray) then Dim index as Integer for index = LBound(ReplaceArray) to UBound(ReplaceArray) Dim word2 as string word2=ReplaceArray(index) if StrComp(word2,word,0)=0 then getReplacementTerm=ReplacementArray(index) end if next end if End Function REM Finite state machine for dialog function Dialog_FSM(event as String) as boolean Dim replaceCursor as Object Dim remplacement as String Dim foreignTerm as String Dim l as Integer Dialog_FSM = true select case event case "ignore" REM if there is still results to be dealt with... ignoreIdx = ignoreIdx + 1 getWorkload() case "ignoreall" foreignTerm = mainDialog.getModel().getByName("anglicisme").getPropertyValue("Text") REM ' Resize ignore term array if (isNull(IgnoreTermArray)) then l=0 else l=UBound(IgnoreTermArray)+1 end if ReDim preserve IgnoreTermArray(l) ' Add to array IgnoreTermArray(UBound(IgnoreTermArray)) = getPartOfText(cursor,result) Dialog_FSM("ignore") case "replace" replaceCursor = createCursorPartOfText(cursor,result) remplacement = mainDialog.getModel().getByName("remplacement").getPropertyValue("Text") REM Case where replace by himself on error goto here if (replaceCursor.Text.compareRegionStarts(replaceCursor,oldViewCursor) > 0) then oldViewCursor.gotoRange(replaceCursor.start,true) end if Here: if checkRecurs(replaceCursor.String,remplacement) then ignoreIdx= IgnoreIdx + 1 end if replaceCursor.String = remplacement REM We modify the target's text, we need to recheck it REM so back to square one... except for the already ignore term results = nothing getWorkload() case "replaceall" foreignTerm = mainDialog.getModel().getByName("anglicisme").getPropertyValue("Text") remplacement = mainDialog.getModel().getByName("remplacement").getPropertyValue("Text") REM ' Resize ignore term array if (isNull(ReplaceArray)) then l=0 else l=UBound(ReplaceArray)+1 end if ReDim preserve ReplaceArray(l) ReDim preserve ReplacementArray(l) ' Add to array ReplaceArray(UBound(ReplaceArray)) = getPartOfText(cursor,result) ReplacementArray(UBound(ReplacementArray)) = remplacement Dialog_FSM("replace") end select End function ' Selection d'une portion limité à n mots avant et après la selection, ' bornée au paragraphe courant. Function selectPart(theText as Object,maxwords as Integer) as Object Dim viewCursor as Object Dim portionCursor as Object Dim wordCursor as Object Dim paragraphCursor as Object Dim nbCharacter as integer viewCursor=ThisComponent.currentController.viewCursor wordCursor = theText.createTextCursorByRange(viewCursor) paragraphCursor = theText.createTextCursorByRange(viewCursor) portionCursor = theText.createTextCursorByRange(viewCursor) paragraphCursor.gotoEndOfParagraph(true) paragraphCursor.gotoStartOfParagraph(true) paragraphCursor.gotoPreviousParagraph(true) wordCursor.gotoStartOfWord(false) for nbCharacter = 1 to maxwords wordCursor.gotoPreviousWord(false) next wordCursor.gotoRange(viewCursor.start,true) REM calcul la position courant par rapport à la selection portionCursor = theText.createTextCursorByRange(viewCursor) if (theText.compareRegionStarts(wordCursor.start,paragraphCursor.start) < 0) then portionCursor.gotoRange(wordCursor.start,true) else portionCursor.gotoRange(paragraphCursor.start,true) end if ' Calculate cursor position poscurrent=0 Dim listParagraph as Object Dim elementText as Object Dim paraCursor as Object listParagraph=portionCursor.createEnumeration() do while listParagraph.hasMoreElements elementText = listParagraph.nextElement if listParagraph.hasMoreElements then if (elementText.supportsService("com.sun.star.text.Paragraph")) then paraCursor=theText.createTextCursorByRange(elementText,true) poscurrent=poscurrent + len(getOnlyText(paraCursor)) + 1 ' for CR end if end if loop Dim partialLineCursor as Object partialLineCursor = theText.createTextCursorByRange(viewCursor) if not isEmpty(elementText.Cell) then partialLineCursor=paragraphCursor poscurrent=0 elseif (theText.compareRegionStarts(elementText.start,portionCursor)> 0) then partialLineCursor.gotoRange(portionCursor.start,true) else partialLineCursor.gotoRange(elementText.start,true) end if poscurrent = poscurrent + len(getOnlyText(partialLineCursor)) for nbCharacter = 1 to maxwords - 1 wordCursor.gotoNextWord(true) next wordCursor.gotoEndOfWord(true) if (theText.compareRegionStarts(wordCursor.end,paragraphCursor.end) > 0) then portionCursor.gotoRange(wordCursor.end,true) else portionCursor.gotoRange(paragraphCursor.end,true) end if 'viewCursor.gotoRange(portionCursor,false) selectPart=portionCursor End Function function checkRecurs(orig as String,remplacement as String) as boolean dim pos as integer if (StrComp(remplacement,orig,1)=0) then checkRecurs=true endif pos=InStr(1,remplacement,orig,1) if (pos <> 0) then if (mid(remplacement,pos+len(orig),1) = " ") then checkRecurs=true end if end if if (pos>1) then if (mid(remplacement,pos-1,1) = " ") then checkRecurs=true end if end if end function REM ***************************************************************************************************** REM Events call back REM REM REM ***************************************************************************************************** Sub ActivateReplaceButton() End Sub Sub Ignore() Dialog_FSM("ignore") End Sub Sub ReplaceAnglicisme() Dialog_FSM("replace") End Sub Sub ReplaceAllAnglicisme() Dialog_FSM("replaceall") End Sub Sub IgnoreAll() Dialog_FSM("ignoreall") End Sub REM ***************************************************************************************************** REM REM Routines related to the "at start" activation (or not) of the extension REM REM ***************************************************************************************************** Const packageName = "org.atosorigin.ctOO.terminologie" Const keyName = packageName & ".noActivationAtStart" Sub checkForDefaultActivation Dim vMyKey as Object terminologieService ' Init java wrapper vMyKey = getRegistry().getRootKey().openKey(keyName) ' Wait a half second before open or create the document ' because, some time, the current doc is not good, ' and it's impossible to register the key event ' Wait 50 initInsecable() ' Whatever is defined, we record the key Handler If NOT isNull(vMyKey) Then REM if the value is not "yes", we also activate... Dim str As String str = vMyKey.getStringValue if ( vMyKey.getStringValue = "yes" ) Then activate() else desactivate() End if else if (defaultStartup = true) Then activate() else desactivate() End if End if End Sub Sub initInsecable() on error goto no BasicLibraries.LoadLibrary("starxpert_insecable") withInsecable=true no: End sub Function getRegistry() As Object Dim vRegistry as Object Dim pathSubstitutionService as Object Dim fileURL as String vRegistry = createUnoService("com.sun.star.registry.SimpleRegistry") pathSubstitutionService = createUnoService("com.sun.star.util.PathSubstitution") fileURL = pathSubstitutionService.getSubstituteVariableValue("$(user)") & packageName & "terminologie.rdb" vRegistry.open(convertToURL(fileURL), FALSE, TRUE ) getRegistry = vRegistry End Function Sub setDefaultActivationToTrue setDefaultActivation("yes","La correction terminologique automatique au démarrage a été activée.") End Sub Sub setDefaultActivationToFalse setDefaultActivation( "no","La correction terminologique automatique au démarrage a été désactivée.") End Sub sub setDefaultActivation(state as String, mssg as String) Dim vRegistry as Object Dim vRootKey as Object Dim vMyKey as Object vRegistry = getRegistry() vRootKey = vRegistry.getRootKey() vMyKey = vRootKey.openKey(keyName) If IsNull (vMyKey) Then REM Key is missing, we add it vMyKey = vRootKey.createKey( keyName ,TRUE) End If vMyKey.setStringValue(state) msgbox(mssg,0,TITLE) If ( state = "yes" ) Then activate() Else desactivate() End If vMyKey.closeKey() vRegistry.close() 'msgbox("keyHandlerEnable:" & keyHandlerEnable,"debug") end sub REM ***************************************************************************************************** REM REM Routines related to the "cheking while typing" functionnality REM REM ***************************************************************************************************** REM REM Automatically called by OOo at close. REM WARN: Do not modify method name. REM REM @author Romain PELISSE REM @author Manuel Odesser modesser@linagora.com REM Global keyHandlerEnable as boolean ' true if on Global TerminologieKeyHandler As Object ' Singleton Sub activate Dim doc As Object doc = StarDesktop.CurrentComponent If IsNull(TerminologieKeyHandler) Then TerminologieKeyHandler = CreateUnoListener("KeyHandler_","com.sun.star.awt.XKeyHandler") End If REM can't use thisComponent here, operation would be call on any open files, REM including the librairies, which is far away from what we need. if HasUnoInterfaces(doc, "com.sun.star.frame.XModel") Then If doc.supportsService("com.sun.star.text.TextDocument") Then doc.currentController.addKeyHandler(TerminologieKeyHandler) keyHandlerEnable=true else if USE_ON_ERROR = false then msgbox("ERROR addKeyHandler for " & doc.Title,"debug") End If else if USE_ON_ERROR = false then msgbox("ERROR HasUnoInterfaces for " & doc.Title,"debug") end if End Sub REM REM Automatically called by OOo at close. REM WARN: Do not modify method name. REM REM @author Romain PELISSE REM @author Manuel Odesser modesser@linagora.com REM Sub desactivate ON ERROR RESUME NEXT REM If this procedure is launched by the quick start, no document has been defined if keyHandlerEnable then StarDesktop.CurrentComponent.currentController.removeKeyHandler(TerminologieKeyHandler) keyHandlerEnable = false end if End Sub REM REM Automatically called by OOo at close. REM WARN: Do not modify method name. REM REM @author Romain PELISSE REM @author Manuel Odesser modesser@linagora.com REM Sub KeyHandler_disposing removeHook End Sub REM REM Automatically called by OOo REM WARN: Do not modify method name. REM REM @author Romain PELISSE REM @author Manuel Odesser modesser@linagora.com REM dim reentrant as boolean Sub KeyHandler_keyReleased(keyEvent As New com.sun.star.awt.KeyHandler) As Boolean if not reentrant then ' evite une double boite de dialogue reentrant=true ManageKeyPressedEvent(keyEvent) reentrant=false endif KeyHandler_keyReleased = false End Sub REM REM Automatically called by OOo REM WARN: Do not modify method name. REM REM @author Romain PELISSE REM @author Manuel Odesser modesser@linagora.com REM Global insecable as object Function KeyHandler_keyPressed(keyEvent As New com.sun.star.awt.KeyHandler) As Boolean ' Ne fonctionne pas, car le mot n'est pas délimité par un espace à ce moment là. ' if ( keyHandlerEnable ) Then ' if not reentrant then ' reentrant=true ' ManageKeyPressedEvent(keyEvent) ' reentrant=false ' endif ' End if ' Hook for insecable space if isNull(insecable) then insecable = array(":", ";", "?", "!") end if KeyHandler_keyPressed=false if withInsecable then dim count as integer for count=Lbound(insecable) to Ubound(insecable) if (insecable(count) = keyEvent.keyChar) then KeyHandler_keyPressed=true endif next end if End Function REM REM Manually written Mutex... far from being safe REM WARN: - won't support multi-proc REM REM @author Manuel Odesser modesser@linagora.com REM Function keyMutex(operation As String, Optional state As Boolean) Static mutex As Boolean If operation = "set" Then If state = True Then While mutex Wait 100 Wend End If REM WARN: Here is a gap in this mutex mutex = state keyMutex = True End If If operation = "get" Then keyMutex = mutex End If End Function REM REM Does the character is a word boundary ? REM REM @return boolean REM @author Manuel Odesser modesser@linagora.com REM Global oCharacterClassification as Object Function isWordBoundary(keyEvent as Object) as Boolean dim oCharacterClassification as Object, nUnicodeType as integer Select Case keyEvent.KeyCode Case com.sun.star.awt.Key.RETURN isWordBoundary = true exit function Case com.sun.star.awt.Key.TAB isWordBoundary = true exit function ' Case com.sun.star.awt.Key.DELETE ' Case com.sun.star.awt.Key.ESCAPE ' Case com.sun.star.awt.Key.DOWN ' Case com.sun.star.awt.Key.UP ' Case com.sun.star.awt.Key.LEFT ' Case com.sun.star.awt.Key.RIGHT End Select if (isNull(oCharacterClassification)) then oCharacterClassification = CreateUnoService("com.sun.star.i18n.CharacterClassification") end if nUnicodeType = oCharacterClassification.getType(keyEvent.KeyChar,0) If _ nUnicodeType = com.sun.star.i18n.UnicodeType.SPACE_SEPARATOR Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.LINE_SEPARATOR Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.PARAGRAPH_SEPARATOR Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.INITIAL_PUNCTUATION Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.FINAL_PUNCTUATION Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.CONNECTOR_PUNCTUATION Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.OTHER_PUNCTUATION Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.START_PUNCTUATION Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.END_PUNCTUATION Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.MATH_SYMBOL Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.CURRENCY_SYMBOL Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.MODIFIER_SYMBOL Or _ nUnicodeType = com.sun.star.i18n.UnicodeType.OTHER_SYMBOL Then isWordBoundary = true Else isWordBoundary = false Endif End Function REM REM Retrieve and build the Uno Service CharacterClassification REM only if the service as not already be fetched. REM REM @author Romain PELISSE romain.pelisse@atosorigin.com REM Dim characterClassificationService_ as Object Function characterClassificationService() as Object Dim service as String service = "com.sun.star.i18n.CharacterClassification" if isNull(characterClassificationService_) then characterClassificationService_ = CreateUnoService(service) end if if (isnull(characterClassificationService_)) then msgbox("Problème: service " & service & " introuvable",0,TITLE) end if REM ... characterClassificationService=characterClassificationService_ End Function REM ********************************************************************************************** REM ********************************************************************************************** REM IHM METHODS REM ********************************************************************************************** REM ********************************************************************************************** REM REM This routine display the main dialog. REM REM @author Romain PELISSE romain.pelisse@atosorigin.com REM REM @arg : an identified foreignTerm with its metadata REM Sub Dialog_set(result as Object) if IsNull(mainDialog) then mainDialog = Dialog_ctr() end if Dim domains as Object Dim term as String domains = result.foreignTerm.domaines term = getPartOfText(cursor,result) Dim DialogModel As Object Dim ControlModel As Object DialogModel = mainDialog.getModel() ControlModel = DialogModel.getByName("anglicisme") ControlModel.setPropertyValue("Text", term) ControlModel = DialogModel.getByName("ForeignTermInContext") ControlModel.setPropertyValue("Text", selectSentence(cursor,result,20)) ControlModel = DialogModel.getByName("Domaines") ' Building the domains list from results Dim domainsList(UBound(domains) - LBound(domains)) As String Dim indexDomain As Integer for indexDomain = LBound(domains) to UBound(domains) domainsList(indexDomain) = domains(indexDomain).name next ControlModel.StringItemList = domainsList() ' Preselection of the first item definePreselectedItem(ControlModel) UpdateTermsList() End Sub REM REM Handy routine to preselect the appropriate term of any list box REM TODO: Is this necessary ? Aren't there any other (better) way to do this ? REM Sub definePreselectedItem(ControlModel as Object) ' FUTURE: add this param "index as Integer' Dim preselectionItems(1) As Integer preselectionItems(0) = 0 ControlModel.SelectedItems = preselectionItems() End Sub REM REM Retrieve dialog descriptor and build it REM REM @author Romain PELISSE romain.pelisse@atosorigin.com REM @author Manuel Odesser modesser@linagora.com REM Function Dialog_ctr Dim oLibContainer As Object Dim oInputStreamProvider As Object Dim oLib As Object ' retrieving from lib, the dialog descriptor DialogLibraries.loadLibrary(dialogueLibraryName) ' Let's build the dialog box oInputStreamProvider = DialogLibraries.getByName(dialogueLibraryName).getByName(sDialogName) Dialog_ctr = CreateUnoDialog(oInputStreamProvider) End Function REM REM Update synonyms list on the main dialog REM REM @author Manuel Odesser modesser@linagora.com REM @author Romain Pelisse romain.pelisse@atosorigin.com REM Sub UpdateTermsList() Dim DialogModel As Object Dim ControlModel As Object Dim meaning as String Dim synonyms As Variant Dim domains as Object domains = result.foreignTerm.domaines If IsNull(mainDialog) OR isNull(domains) Then ' Should never happens... Exit Sub End If ' Getting back the selected 'domain' ControlModel = mainDialog.getModel().getByName("Domaines") on error goto noSelectedMeaning meaning = ControlModel.StringItemList(ControlModel.SelectedItems(0)) noSelectedMeaningNext: on error resume next ' updating the list ControlModel = mainDialog.getModel().getByName("Termes") Dim indexDomain as Integer if ( NOT IsNull(domains) ) Then For indexDomain = LBound(domains) To UBound(domains) ' Does this meaning match with the one we're looking for ? If meaning = domains(indexDomain).name Then ControlModel.StringItemList = domains(indexDomain).synonymes Exit For EndIf Next End If definePreselectedItem(ControlModel) UpdateSelectedTerm Exit Sub noSelectedMeaning: meaning = 0 goto noSelectedMeaningNext End Sub REM REM Display a text box REM REM @author Manuel Odesser modesser@linagora.com REM @author Romain Pelisse romain.pelisse@atosorigin.com REM Sub ShowTextDialog(dialog as String) TextDialog_ctr(dialog).execute() End Sub REM REM Display the help text REM REM @author Romain Pelisse romain.pelisse@atosorigin.com REM Sub Help ShowTextDialog("help_text") End Sub REM REM Display the about text REM REM @author Romain Pelisse romain.pelisse@atosorigin.com REM Sub About ShowTextDialog("help_dialog") End Sub REM REM Buid a text dialog REM REM @author Manuel Odesser modesser@linagora.com REM @author Roamin Pelisse romain.pelisse@atosorigin.com REM Function TextDialog_ctr(sDialogName as String) Dim inputStreamProvider As Object Dim dialog As Object ' récupération de la librairie dans laquelle est définie la boîte DialogLibraries.loadLibrary(dialogueLibraryName) dialog = DialogLibraries.getByName(dialogueLibraryName) ' crée la boîte proprement dite TextDialog_ctr = CreateUnoDialog(dialog.getByName(sDialogName)) End Function REM REM Close the mainDialog box REM REM @author Manuel Odesser modesser@linagora.com REM Sub Dialog_Close exitCode=com.sun.star.ui.dialogs.ExecutableDialogResults.OK if (not isNull(mainDialog)) then mainDialog.endExecute(com.sun.star.ui.dialogs.ExecutableDialogResults.OK) endif End Sub REM Update the displayed term with the appropriate value REM REM @author Manuel Odesser modesser@linagora.com REM @author Romain Pelisse romain.pelisse@atosorigin.com REM Sub UpdateSelectedTerm() Dim ControlModel As Object Dim term as String ' on récupère le terme cliqué ControlModel = mainDialog.getModel().getByName("Termes") on error goto noSelectedWord term = ControlModel.StringItemList(ControlModel.SelectedItems(0)) noSelectedWordNext: on error resume next ' et on met à jour la liste des synonymes ControlModel = mainDialog.getModel().getByName(REMPLACEMENT_FIELD_NAME) ControlModel.setPropertyValue("Text",term) Exit Sub noSelectedWord: term = "" goto noSelectedWordNext End Sub REM REM Open the appropriate URL from the mainDialog REM REM @author Laurent Godard http://www.indesko.com/telechargements/ooowikipedia REM Sub OpenExternalDatasourceURL() Dim objlancer as Object Dim handleErrors as Object Dim adress as String Dim term As String Dim httpValidTerm As String ' on error resume next term = mainDialog.getModel().getByName(REMPLACEMENT_FIELD_NAME).getPropertyValue("Text") ' FUTURE: When FranceTerme handle properly accentued character passed by Get ' this next call should be removed httpValidTerm = replaceNotHttpSupportedCharacter(term) ' building the appropriate URL adress = ConvertToURL("http://franceterme.culture.fr/FranceTerme/recherche.html?TERME=" + httpValidTerm) ' calling the external service objlancer = CreateUnoService("com.sun.star.system.SystemShellExecute") objlancer.execute(adress, "", 0) End Sub REM REM This fonction replace special character that could mess REM up with an http link syntax. REM REM @author Romain PELISSE, romain.pelisse@atosorigin.com REM Function replaceNotHttpSupportedCharacter(maChaine As String) Dim RechRemp(1,6) As String Dim i, j, place As Integer Dim arg(0) As String : arg(0) = maChaine ' Caractères à remplacer. rechRemp(0, 0) = "áâãäåæ": rechRemp(1, 0) = "a" rechRemp(0, 1) = "èéêë;" : rechRemp(1, 1) = "e" rechRemp(0, 2) = "ìíîï" : rechRemp(1, 2) = "i" rechRemp(0, 3) = "óôõöø" : rechRemp(1, 3) = "o" rechRemp(0, 4) = "ùúûü" : rechRemp(1, 4) = "u" rechRemp(0, 5) = "ç" : rechRemp(1, 5) = "c" rechRemp(0, 6) = "ñ" : rechRemp(1, 6) = "n" ' TODO: add the uppercase version if any ? ' Moulinette sur les chaînes de caractères. For i = 0 to 6 For j = 0 to (Len(rechRemp(0, i)) - 1) While InStr(maChaine, mid(rechRemp(0, i), (j + 1), 1)) <> 0 place = InStr(maChaine, mid(rechRemp(0, i), (j + 1), 1)) maChaine = Left(maChaine, (place - 1)) & rechRemp(1, i) & Right(maChaine, (Len(maChaine) - place)) Wend Next j Next i Dim str As String str = StrSubstitute(maChaine,"œ","oe") replaceNotHttpSupportedCharacter = str End Function REM REM The original string, cString, is modified by this function and then returned. REM All occurences of cFindStr are replaced by cReplaceStr. REM cFindStr and cReplaceStr do not need to be the same length. REM REM @author DannyB (http://www.oooforum.org/forum/viewtopic.phtml?t=5374) REM Function StrSubstitute( ByVal cString As String,_ ByVal cFindStr As String, ByVal cReplaceStr As String ) As String Dim cResult As String Dim nPos As Integer cResult = "" If Len( cFindStr ) > 0 Then Do nPos = Instr( 1, cString, cFindStr, 0 ) If nPos > 0 Then cResult = cResult & Left( cString, nPos-1 ) cResult = cResult & cReplaceStr cString = Mid( cString, nPos+Len(cFindStr) ) Else ' Append the rest of the original string. cResult = cResult & cString EndIf Loop Until nPos = 0 EndIf StrSubstitute() = cResult End Function REM Select part of the text Function createCursorPartOfText(cursor as Object,result as Object) as Object Dim selectionCursor as Object If not IsNull(cursor) AND not IsNull(result) then selectionCursor = cursor.Text.createTextCursorByRange(cursor) selectionCursor.collapseToStart() dim l as integer ' l=LenNumber(cursor) ' No ajust paragraph number l=0 if (result.start > l ) then selectionCursor.goRight(result.start-l,false) end if selectionCursor.goRight(result.len,true) createCursorPartOfText = selectionCursor Else createCursorPartOfText = cursor End If End Function REM Select part of the text Function getPartOfText(cursor as Object,result as Object) as String getPartOfText=mid(cursor.string,result.start + LenNumber(cursor) + 1,result.len) End Function REM Select part of the text Function getOnlyText(cursor as Object) as String getOnlyText=mid(cursor.string,LenNumber(cursor)+1) End Function REM Selection d'une portion limité à n mots avant et après la selection, ' bornée au paragraphe courant. Function selectSentence(cursor as Object, result as Object, offset as Integer) as String Dim selectionCursor as Object Dim start as Integer Dim prefix as String Dim suffix as String prefix = "" suffix = "" start = result.start - offset If start <= 0 Then start = 0 Else prefix = "..." End If If not IsNull(cursor) AND not IsNull(result) then selectionCursor = cursor.Text.createTextCursorByRange(cursor) selectionCursor.collapseToStart() selectionCursor.goRight(start,false) If ( NOT (selectionCursor.goRight(result.len + (offset *2) ,true) ) ) Then selectionCursor = cursor.Text.createTextCursorByRange(cursor) selectionCursor.collapseToStart() selectionCursor.goRight(start,false) selectionCursor.gotoEndOfParagraph(true) Else suffix = "..." End if selectSentence = prefix + selectionCursor.String + suffix Else selectSentence = cursor.String End If End Function ' This routine is a wrapper for java component Function CheckSelection(cursor as Object) as Object Dim selectedText as String ' msgbox "cursor=" & cursor.string selectedText = getOnlyText(cursor) If NOT isNull(selectedText) AND selectedText <> "" Then dim a as object results = terminologieService.search(selectedText) currentResult = -1 CheckSelection=results end if End Function ' Hack function. ' Calculate the length of number if present Function LenNumber(cursor as Object) as Integer dim hackCursor as object hackCursor=cursor.Text.createTextCursorByRange(cursor,false) hackCursor.collapseToStart() hackCursor.goRight(1,false) hackCursor.goLeft(1,true) LenNumber=len(hackCursor.string) - 1 if (LenNumber < 0) then LenNumber = 0 end if End Function