pax_global_header00006660000000000000000000000064122550174770014524gustar00rootroot0000000000000052 comment=a2f9985a496ac139d416f83e92af2bcbf8b42fac accessodf-0.1.1~b/000077500000000000000000000000001225501747700140155ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/000077500000000000000000000000001225501747700170325ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/pom.xml000066400000000000000000000100551225501747700203500ustar00rootroot00000000000000 4.0.0 be.docarch accessodf 0.1.0-SNAPSHOT accessodf-addon 0.1.0-SNAPSHOT oxt accessodf :: Addon be.docarch accessodf-api org.libreoffice juh org.libreoffice jurt org.libreoffice ridl org.libreoffice unoil src/main/resources be/docarch/accessodf/ooo/l10n target/l10n/bundles/checks be/docarch/accessodf/ooo/toolpanel/l10n target/l10n/bundles/toolpanel be.docarch l10n-maven-plugin checks.ods toolpanel.ods maven-dependency-plugin copy-dependencies prepare-package copy-dependencies target/oxt/lib runtime be.docarch oxt-maven-plugin be.docarch.accessodf.ooo.AccessODFAddOn be.docarch.accessodf.ooo.toolpanel.ToolPanelFactory be.docarch.accessodf.ooo.optionspage.DialogEventHandler lib/*.jar src/main/oxt description.xml META-INF/manifest.xml src/main/oxt description.xml META-INF/manifest.xml true target/oxt debian maven-dependency-plugin 2.8 copy-dependencies none build-classpath prepare-package build-classpath classpath : runtime be.docarch oxt-maven-plugin ${classpath} accessodf-0.1.1~b/accessodf-addon/src/000077500000000000000000000000001225501747700176215ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/000077500000000000000000000000001225501747700205455ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/000077500000000000000000000000001225501747700214665ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/000077500000000000000000000000001225501747700220545ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/000077500000000000000000000000001225501747700234575ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/000077500000000000000000000000001225501747700254115ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/000077500000000000000000000000001225501747700262055ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/AccessODFAddOn.java000066400000000000000000000176341225501747700315230ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.io.File; import java.util.logging.Logger; import java.util.logging.Level; import java.util.logging.Handler; import java.util.logging.FileHandler; import java.util.logging.SimpleFormatter; import com.sun.star.beans.XPropertySet; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; import com.sun.star.frame.XModel; import com.sun.star.frame.XFrame; import com.sun.star.frame.XLayoutManager; import com.sun.star.frame.XDesktop; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lang.XComponent; import com.sun.star.lang.XSingleComponentFactory; import com.sun.star.registry.XRegistryKey; import com.sun.star.lib.uno.helper.WeakBase; import com.sun.star.lib.uno.helper.Factory; import be.docarch.accessodf.Constants; public final class AccessODFAddOn extends WeakBase implements com.sun.star.lang.XInitialization, com.sun.star.frame.XDispatch, com.sun.star.lang.XServiceInfo, com.sun.star.frame.XDispatchProvider { private final XComponentContext m_xContext; private com.sun.star.frame.XFrame m_xFrame; private static final String m_implementationName = AccessODFAddOn.class.getName(); private static final String[] m_serviceNames = { "com.sun.star.frame.ProtocolHandler" }; private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); private static final String TMP_NAME = Constants.TMP_PREFIX; private static final File TMP_DIR = Constants.getTmpDirectory(); private Handler fh = null; private File logFile = null; private int counter = 0; public AccessODFAddOn( XComponentContext context ) { m_xContext = context; try { logFile = File.createTempFile(TMP_NAME, ".log", TMP_DIR); fh = new FileHandler(logFile.getAbsolutePath()); fh.setFormatter(new SimpleFormatter()); Logger.getLogger("").addHandler(fh); Logger.getLogger("").setLevel(Level.FINEST); } catch (java.io.IOException ex) { logger.log(Level.SEVERE, null, ex); } catch (RuntimeException ex) { logger.log(Level.SEVERE, null, ex); } }; public static XSingleComponentFactory __getComponentFactory( String sImplementationName ) { XSingleComponentFactory xFactory = null; if ( sImplementationName.equals( m_implementationName ) ) xFactory = Factory.createComponentFactory(AccessODFAddOn.class, m_serviceNames); return xFactory; } public static boolean __writeRegistryServiceInfo( XRegistryKey xRegistryKey ) { return Factory.writeRegistryServiceInfo(m_implementationName, m_serviceNames, xRegistryKey); } // com.sun.star.lang.XInitialization: public void initialize( Object[] object ) throws com.sun.star.uno.Exception { if ( object.length > 0 ) { m_xFrame = (com.sun.star.frame.XFrame)UnoRuntime.queryInterface( com.sun.star.frame.XFrame.class, object[0]); } } // com.sun.star.frame.XDispatch: public void dispatch( com.sun.star.util.URL aURL, com.sun.star.beans.PropertyValue[] aArguments ) { logger.info(String.valueOf(counter++)); if ( aURL.Protocol.startsWith("be.docarch.accessodf.ooo.accessodfaddon")) { if ( aURL.Path.compareTo("TaskPanelCommand") == 0 ) { try { XMultiComponentFactory xMCF = (XMultiComponentFactory) UnoRuntime.queryInterface( XMultiComponentFactory.class, m_xContext.getServiceManager()); Object desktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", m_xContext); XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, desktop); XComponent doc = (XComponent)xDesktop.getCurrentComponent(); XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, doc); XFrame xFrame = xModel.getCurrentController().getFrame(); XPropertySet xPropertySet = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xFrame); XLayoutManager xLayoutManager = (XLayoutManager) UnoRuntime.queryInterface( XLayoutManager.class, xPropertySet.getPropertyValue("LayoutManager")); String toolPanel = "private:resource/toolpanel/be.docarch.accessibility.ooo.toolpanel"; if (xLayoutManager.isElementVisible(toolPanel)) { // geeft altijd false xLayoutManager.hideElement(toolPanel); } else { xLayoutManager.showElement(toolPanel); } } catch (Exception e) { logger.log(Level.SEVERE, null, e); } return; } } } public void addStatusListener( com.sun.star.frame.XStatusListener xControl, com.sun.star.util.URL aURL ) { // add your own code here } public void removeStatusListener( com.sun.star.frame.XStatusListener xControl, com.sun.star.util.URL aURL ) { // add your own code here } // com.sun.star.lang.XServiceInfo: public String getImplementationName() { return m_implementationName; } public boolean supportsService( String sService ) { int len = m_serviceNames.length; for( int i=0; i < len; i++) { if (sService.equals(m_serviceNames[i])) return true; } return false; } public String[] getSupportedServiceNames() { return m_serviceNames; } // com.sun.star.frame.XDispatchProvider: public com.sun.star.frame.XDispatch queryDispatch( com.sun.star.util.URL aURL, String sTargetFrameName, int iSearchFlags ) { if ( aURL.Protocol.startsWith("be.docarch.accessodf.ooo.accessodfaddon")) { if ( aURL.Path.compareTo("TaskPanelCommand") == 0 ) return this; } return null; } // com.sun.star.frame.XDispatchProvider: public com.sun.star.frame.XDispatch[] queryDispatches( com.sun.star.frame.DispatchDescriptor[] seqDescriptors ) { int nCount = seqDescriptors.length; com.sun.star.frame.XDispatch[] seqDispatcher = new com.sun.star.frame.XDispatch[seqDescriptors.length]; for( int i=0; i < nCount; ++i ) { seqDispatcher[i] = queryDispatch(seqDescriptors[i].FeatureURL, seqDescriptors[i].FrameName, seqDescriptors[i].SearchFlags ); } return seqDispatcher; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/CheckerProvider.java000066400000000000000000000044701225501747700321340ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import be.docarch.accessodf.Constants; import be.docarch.accessodf.Checker; import be.docarch.accessodf.Provider; import java.util.Collection; import java.util.Map; import java.util.HashMap; import java.util.Iterator; import java.util.logging.Logger; import java.util.logging.Level; import javax.imageio.spi.ServiceRegistry; /** * * @author Bert Frees */ public class CheckerProvider implements Provider { private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); private final Map checkers; public CheckerProvider(ClassLoader classLoader, Document document) { checkers = new HashMap(); Checker checker; Iterator i = ServiceRegistry.lookupProviders(Checker.class, classLoader); while (i.hasNext()) { checker = i.next(); checkers.put(checker.getIdentifier(), checker); logger.info(checker.getIdentifier() + " loaded"); } try { Checker mainChecker = new MainChecker(document); checkers.put(mainChecker.getIdentifier(), mainChecker); logger.info(mainChecker.getIdentifier() + " loaded"); } catch (Exception e) { logger.log(Level.SEVERE, null, e); } } public Collection list() { return checkers.values(); } public Checker get(String identifier) { return checkers.get(identifier); } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/Comment.java000066400000000000000000000054311225501747700304550ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.UnoRuntime; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.beans.XPropertySet; import com.sun.star.text.XTextContent; import com.sun.star.text.XTextCursor; import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.beans.UnknownPropertyException; import com.sun.star.beans.PropertyVetoException; /** * * @author Bert Frees */ public class Comment { XTextContent annotation = null; XPropertySet annotationProps = null; public Comment(XMultiServiceFactory xMSF) throws UnknownPropertyException, WrappedTargetException, IllegalArgumentException, PropertyVetoException, com.sun.star.uno.Exception { annotation = (XTextContent)UnoRuntime.queryInterface( XTextContent.class, xMSF.createInstance("com.sun.star.text.textfield.Annotation")); annotationProps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, annotation); setAuthor("Accessibility checker"); } public void setAuthor(String author) throws UnknownPropertyException, PropertyVetoException, WrappedTargetException, IllegalArgumentException { annotationProps.setPropertyValue("Author", author); } public void setContent(String content) throws UnknownPropertyException, PropertyVetoException, WrappedTargetException, IllegalArgumentException { annotationProps.setPropertyValue("Content", content); } public void insertCommentAtCursor(XTextCursor cursor) throws IllegalArgumentException{ cursor.getText().insertTextContent(cursor.getStart(), annotation, true); } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/ConfigurationAccess.java000066400000000000000000000055301225501747700330040ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.beans.PropertyState; import com.sun.star.beans.PropertyValue; import com.sun.star.container.XNameAccess; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; /** * Provides generic factory methods around configuration access. * @author Christian Lins (christian.lins@sun.com) */ public class ConfigurationAccess { /** * Creates a XNameAccess instance for read and write access to the * configuration at the given node path. * @param context * @param path * @return */ public static XNameAccess createUpdateAccess(XComponentContext context, String path) { XNameAccess access; // Create the com.sun.star.configuration.ConfigurationUpdateAccess // for the registry node which contains the data for our option // pages. XMultiServiceFactory xConfig; try { xConfig = (XMultiServiceFactory) UnoRuntime.queryInterface( XMultiServiceFactory.class, context.getServiceManager().createInstanceWithContext( "com.sun.star.configuration.ConfigurationProvider", context)); } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); return null; } // One argument for creating the ConfigurationUpdateAccess is the "nodepath". // Our nodepath point to the node of which the direct subnodes represent the // different options pages. Object[] args = new Object[1]; args[0] = new PropertyValue("nodepath", 0, path,PropertyState.DIRECT_VALUE); // We get the com.sun.star.container.XNameAccess from the instance of // ConfigurationUpdateAccess and save it for later use. try { access = (XNameAccess) UnoRuntime.queryInterface( XNameAccess.class, xConfig.createInstanceWithArguments( "com.sun.star.configuration.ConfigurationUpdateAccess", args)); } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); return null; } return access; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/DaisyCheck.java000066400000000000000000000064641225501747700310710ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.util.Locale; import java.util.ResourceBundle; import java.util.MissingResourceException; import be.docarch.accessodf.Check; /** * * @author Bert Frees */ public class DaisyCheck extends Check { private static final String L10N_BUNDLE = "be/docarch/accessodf/ooo/l10n/checks"; public static enum ID { E_UnsupportedImageFormat, A_EmptyTitleField, A_BodyMatterStartSectionNested, A_RearMatterStartSectionNested } private ID identifier; public DaisyCheck(ID identifier) { this.identifier = identifier; } public String getIdentifier() { return identifier.name(); } public Status getStatus() { if (identifier.name().startsWith("E_")) { return Status.ERROR; } else if (identifier.name().startsWith("A_")) { return Status.ALERT; } else { return null; } } public String getName(Locale locale) { if (identifier == null) { return null; } try { ResourceBundle bundle = ResourceBundle.getBundle(L10N_BUNDLE, locale); return bundle.getString("name_" + identifier.name()); } catch (MissingResourceException e) { return identifier.name(); } } public String getDescription(Locale locale) { if (identifier == null) { return null; } try { ResourceBundle bundle = ResourceBundle.getBundle(L10N_BUNDLE, locale); return bundle.getString("description_" + identifier.name()); } catch (MissingResourceException e) { switch (identifier) { case A_BodyMatterStartSectionNested: return "The section \"BodyMatterStart\" is placed inside another section. odt2daisy will not recognize it."; case A_RearMatterStartSectionNested: return "The section \"RearMatterStart\" is placed inside another section. odt2daisy will not recognize it."; default: return ""; } } } public String getSuggestion(Locale locale) { if (identifier == null) { return null; } try { ResourceBundle bundle = ResourceBundle.getBundle(L10N_BUNDLE, locale); return bundle.getString("suggestion_" + identifier.name()); } catch (MissingResourceException e) { return ""; } } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/Document.java000066400000000000000000000374731225501747700306440ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.io.File; import java.util.logging.Logger; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.AnyConverter; import com.sun.star.util.XModifiable; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lang.XComponent; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.lang.XServiceInfo; import com.sun.star.frame.XComponentLoader; import com.sun.star.frame.XModel; import com.sun.star.frame.XStorable; import com.sun.star.frame.XDesktop; import com.sun.star.document.XDocumentPropertiesSupplier; import com.sun.star.document.XDocumentProperties; import com.sun.star.beans.XPropertySet; import com.sun.star.beans.PropertyValue; import com.sun.star.container.XEnumerationAccess; import com.sun.star.container.XEnumeration; import com.sun.star.container.XNameAccess; import com.sun.star.container.XNameContainer; import com.sun.star.container.XIndexAccess; import com.sun.star.table.XCell; import com.sun.star.text.XTextDocument; import com.sun.star.text.XTextContent; import com.sun.star.text.XTextFramesSupplier; import com.sun.star.text.XTextFrame; import com.sun.star.text.XTextTable; import com.sun.star.text.XTextTablesSupplier; import com.sun.star.text.XTextGraphicObjectsSupplier; import com.sun.star.text.XTextEmbeddedObjectsSupplier; import com.sun.star.text.XTextViewCursor; import com.sun.star.text.XTextViewCursorSupplier; import com.sun.star.view.XSelectionSupplier; import com.sun.star.style.XStyleFamiliesSupplier; import com.sun.star.rdf.XDocumentMetadataAccess; import com.sun.star.rdf.XRepository; import com.sun.star.rdf.XURI; import com.sun.star.rdf.URI; import com.sun.star.rdf.XMetadatable; import java.io.IOException; import java.net.MalformedURLException; import com.sun.star.beans.PropertyVetoException; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.lang.IndexOutOfBoundsException; import com.sun.star.lang.WrappedTargetException; import com.sun.star.datatransfer.UnsupportedFlavorException; import com.sun.star.container.ElementExistException; import com.sun.star.container.NoSuchElementException; import com.sun.star.rdf.ParseException; import com.sun.star.rdf.RepositoryException; import be.docarch.accessodf.Constants; /** * * @author Bert Frees */ public class Document { private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); public XComponentContext xContext = null; public XMultiServiceFactory xMSF = null; public XMultiComponentFactory xMCF = null; public XDocumentMetadataAccess xDMA = null; public XRepository xRepository = null; public XModel xModel = null; public XComponent doc = null; public XNameContainer paragraphStyles = null; public XNameContainer characterStyles = null; public XNameAccess tables = null; public XNameAccess embeddedObjects = null; public XNameAccess graphicObjects = null; public XSelectionSupplier selectionSupplier = null; public XTextViewCursor viewCursor = null; public XDocumentProperties docProperties = null; public XPropertySet docPropertySet = null; public XURI metaFolderURI = null; public XTextDocument textDocument = null; public String metaFolder = "meta/"; private PropertyValue[] conversionProperties = null; private XStorable storable = null; private XModifiable xModifiable = null; private XTextContent firstParagraph = null; private boolean readOnly = false; public Document(XComponentContext xContext) throws com.sun.star.uno.Exception { logger.entering("Document", ""); this.xContext = xContext; xMCF = (XMultiComponentFactory) UnoRuntime.queryInterface( XMultiComponentFactory.class, xContext.getServiceManager()); Object desktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext); XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, desktop); doc = (XComponent)xDesktop.getCurrentComponent(); initDocument(); logger.exiting("Document", ""); } public Document(String unoUrl, XComponentContext xContext) throws com.sun.star.uno.Exception { logger.entering("Document", ""); this.xContext = xContext; xMCF = (XMultiComponentFactory) UnoRuntime.queryInterface( XMultiComponentFactory.class, xContext.getServiceManager()); Object desktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext); XComponentLoader loader = (XComponentLoader)UnoRuntime.queryInterface( XComponentLoader.class, desktop); PropertyValue[] loadProps = new PropertyValue[1]; loadProps[0] = new PropertyValue(); loadProps[0].Name = "ReadOnly"; loadProps[0].Value = new Boolean(false); doc = loader.loadComponentFromURL(unoUrl, "_blank", 0, loadProps); initDocument(); logger.exiting("Document", ""); } private void initDocument() throws com.sun.star.uno.Exception { URIs.init(xContext); textDocument = (XTextDocument)UnoRuntime.queryInterface(XTextDocument.class, doc); xMSF = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, textDocument); xModel = (XModel) UnoRuntime.queryInterface(XModel.class, textDocument); xDMA = (XDocumentMetadataAccess)UnoRuntime.queryInterface(XDocumentMetadataAccess.class, xModel); xRepository = xDMA.getRDFRepository(); metaFolderURI = URI.create(xContext, xDMA.getNamespace() + metaFolder); XStyleFamiliesSupplier xSupplier = (XStyleFamiliesSupplier)UnoRuntime.queryInterface( XStyleFamiliesSupplier.class, textDocument); XNameAccess xFamilies = (XNameAccess)UnoRuntime.queryInterface ( XNameAccess.class, xSupplier.getStyleFamilies()); paragraphStyles = (XNameContainer)UnoRuntime.queryInterface( XNameContainer.class, xFamilies.getByName("ParagraphStyles")); characterStyles = (XNameContainer)UnoRuntime.queryInterface( XNameContainer.class, xFamilies.getByName("CharacterStyles")); XTextTablesSupplier tablesSupplier = (XTextTablesSupplier)UnoRuntime.queryInterface( XTextTablesSupplier.class, doc); tables = tablesSupplier.getTextTables(); XTextGraphicObjectsSupplier textGraphicObjectsSupplier = (XTextGraphicObjectsSupplier)UnoRuntime.queryInterface( XTextGraphicObjectsSupplier.class, doc); XTextEmbeddedObjectsSupplier textEmbeddedObjectsSupplier = (XTextEmbeddedObjectsSupplier)UnoRuntime.queryInterface( XTextEmbeddedObjectsSupplier.class, doc); embeddedObjects = textEmbeddedObjectsSupplier.getEmbeddedObjects(); graphicObjects = textGraphicObjectsSupplier.getGraphicObjects(); selectionSupplier = (XSelectionSupplier)UnoRuntime.queryInterface( XSelectionSupplier.class, xModel.getCurrentController()); XTextViewCursorSupplier xViewCursorSupplier = (XTextViewCursorSupplier)UnoRuntime.queryInterface( XTextViewCursorSupplier.class, xModel.getCurrentController()); viewCursor = xViewCursorSupplier.getViewCursor(); XDocumentPropertiesSupplier xDocPropSuppl = (XDocumentPropertiesSupplier) UnoRuntime.queryInterface( XDocumentPropertiesSupplier.class, textDocument); docProperties = xDocPropSuppl.getDocumentProperties(); docPropertySet = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, doc); Object desktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext); XDesktop xDesktop = (XDesktop)UnoRuntime.queryInterface(XDesktop.class, desktop); xModifiable = (XModifiable)UnoRuntime.queryInterface(XModifiable.class, xDesktop.getCurrentComponent()); conversionProperties = new PropertyValue[1]; conversionProperties[0] = new PropertyValue(); conversionProperties[0].Name = "FilterName"; conversionProperties[0].Value = "writer8"; storable = (XStorable) UnoRuntime.queryInterface(XStorable.class, xModel); for (PropertyValue prop: xModel.getArgs()) { if (prop.Name.equals("ReadOnly")) { readOnly = (Boolean)AnyConverter.toBoolean(prop.Value); break; } } } public void storeToFile(File output) throws MalformedURLException, com.sun.star.io.IOException { logger.entering("Document", "storeToFile"); String outputUnoUrl = UnoUtils.createUnoFileURL(output.getAbsolutePath(), xContext); storable.storeToURL(outputUnoUrl, conversionProperties); logger.exiting("Document", "storeToFile"); } public void removeAccessibilityData(String checkerID) { try { XURI type = URI.create(xContext, checkerID); for (XURI graph : xDMA.getMetadataGraphsWithType(type)) { xDMA.removeMetadataFile(graph); } } catch (IllegalArgumentException e) { } catch (NoSuchElementException e) { } } public void importAccessibilityData(File earlReport, String checkerID, String graphName) throws IOException, IllegalArgumentException, UnsupportedFlavorException, ParseException, NoSuchElementException, WrappedTargetException, RepositoryException, com.sun.star.io.IOException { logger.entering("Document", "importAccessibilityData"); InputStream inputStream = InputStream.newInstance(earlReport); XURI[] types = new XURI[]{ URI.create(xContext, checkerID) }; XURI graphURI = null; try { graphURI = xDMA.importMetadataFile((short)0, inputStream, metaFolder + graphName, metaFolderURI, types); } catch (ElementExistException ex) { graphURI = URI.create(xContext, metaFolderURI.getStringValue() + graphName); xDMA.removeMetadataFile(graphURI); try { xDMA.importMetadataFile((short)0, inputStream, metaFolder + graphName, metaFolderURI, types); } catch (ElementExistException e) { } } logger.exiting("Document", "importAccessibilityData"); } public void ensureMetadataReferences() throws NoSuchElementException, WrappedTargetException, IndexOutOfBoundsException { XEnumerationAccess enumerationAccess = (XEnumerationAccess)UnoRuntime.queryInterface( XEnumerationAccess.class, textDocument.getText()); XEnumeration paragraphs = enumerationAccess.createEnumeration(); while (paragraphs.hasMoreElements()) { ensureMetadataReferences(paragraphs.nextElement()); } XTextFramesSupplier xTextFramesSupplier = (XTextFramesSupplier) UnoRuntime.queryInterface( XTextFramesSupplier.class, doc); XIndexAccess textFrames = (XIndexAccess) UnoRuntime.queryInterface( XIndexAccess.class, xTextFramesSupplier.getTextFrames()); XTextFrame frame = null; XEnumeration paragraphsInFrame = null; for (int i=0; i. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.UnoRuntime; import com.sun.star.container.XNamed; import com.sun.star.container.NoSuchElementException; import com.sun.star.lang.IllegalArgumentException; /** * * @author Bert Frees */ public class DrawObject extends FocusableElement { private final Document doc; private XNamed xNamed = null; public DrawObject(String name, Document doc) throws Exception { if (name == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; Object o = null; try { o = doc.embeddedObjects.getByName(name); } catch (NoSuchElementException e) { try { o = doc.graphicObjects.getByName(name); } catch (NoSuchElementException ee) { } } if (o == null) { throw new Exception("No object found with name " + name); } xNamed = (XNamed)UnoRuntime.queryInterface(XNamed.class, o); } public DrawObject(XNamed xNamed, Document doc) throws IllegalArgumentException { if (xNamed == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; this.xNamed = xNamed; } public XNamed getXNamed() { return xNamed; } public String toString() { return xNamed.getName(); } public int hashCode() { final int PRIME = 31; int hash = 1; hash = hash * PRIME + toString().hashCode(); return hash; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final DrawObject that = (DrawObject)obj; return (this.toString().equals(that.toString())); } @Override public boolean focus() { try { if (xNamed != null) { return doc.selectionSupplier.select(xNamed); } } catch (IllegalArgumentException e) { } return false; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/FocusableElement.java000066400000000000000000000022521225501747700322660ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.util.logging.Logger; import be.docarch.accessodf.Constants; import be.docarch.accessodf.Element; /** * * @author Bert Frees */ public abstract class FocusableElement extends Element { protected static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); public abstract boolean focus(); } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/GeneralCheck.java000066400000000000000000000100601225501747700313600ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.util.Locale; import java.util.ResourceBundle; import java.util.MissingResourceException; import be.docarch.accessodf.Check; /** * * @author Bert Frees */ public class GeneralCheck extends Check { private static final String L10N_BUNDLE = "be/docarch/accessodf/ooo/l10n/checks"; public static enum ID { E_ManyTitles, E_EmptyTitle, E_EmptyHeading, E_HeadingSkip, E_HeadingInFrame, E_NoLanguage, E_NoDefaultLanguage, E_NoHyperlinkLanguage, E_ImageAnchorFloat, A_NoTitle, A_NoHeadings, A_NoSubtitle, A_AlternateLevel, A_FakeUnorderedList, // *** A_FakeOrderedList, // *** A_FakeTable, A_FakeText, A_FakeQuote, // *** paragraaf met marges aan beide kanten A_FakeHeading, A_LinkedImage, A_ImageWithoutAlt, A_FormulaWithoutAlt, A_ObjectWithoutAlt, A_MergedCells, // niet 100% betrouwbaar => nieuwe checker mbv xpath? A_NestedTable, A_NoTableHeading, A_BreakRows, A_BigTable, A_CaptionBelowBigTable, A_UnidentifiedLanguage, A_LowContrast, A_JustifiedText, A_SmallText, A_AllCaps, // voorlopig genegeerd A_LongUnderline, A_LongItalic, A_HasForms, A_NoHyperlinkText, A_FakeLine, A_FlashText } private ID identifier; public GeneralCheck(ID identifier) { this.identifier = identifier; } public String getIdentifier() { return identifier.name(); } public Status getStatus() { if (identifier.name().startsWith("E_")) { return Status.ERROR; } else if (identifier == ID.A_ImageWithoutAlt) { return Status.ERROR; } else if (identifier == ID.A_LowContrast) { return Status.ERROR; } else if (identifier.name().startsWith("A_")) { return Status.ALERT; } else { return null; } } public String getName(Locale locale) { if (identifier == null) { return null; } try { ResourceBundle bundle = ResourceBundle.getBundle(L10N_BUNDLE, locale); return bundle.getString("name_" + identifier.name()); } catch (MissingResourceException e) { return identifier.name(); } } public String getDescription(Locale locale) { if (identifier == null) { return null; } try { ResourceBundle bundle = ResourceBundle.getBundle(L10N_BUNDLE, locale); return bundle.getString("description_" + identifier.name()); } catch (MissingResourceException e) { return ""; } } public String getSuggestion(Locale locale) { if (identifier == null) { return null; } try { ResourceBundle bundle = ResourceBundle.getBundle(L10N_BUNDLE, locale); return bundle.getString("suggestion_" + identifier.name()); } catch (MissingResourceException e) { return ""; } } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/InputStream.java000066400000000000000000000106211225501747700313230ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.io.File; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import com.sun.star.io.XInputStream; import com.sun.star.io.XSeekable; import java.io.IOException; import java.io.FileNotFoundException; import com.sun.star.io.BufferSizeExceededException; import com.sun.star.io.NotConnectedException; /** * From the thread OOo-Java: Using XInputStream... */ public class InputStream extends ByteArrayInputStream implements XInputStream, XSeekable { public static InputStream newInstance(File input) throws IOException, FileNotFoundException { java.io.InputStream inputFile = new BufferedInputStream(new FileInputStream(input)); ByteArrayOutputStream bytes = new ByteArrayOutputStream(); byte[] byteBuffer = new byte[4096]; int byteBufferLength = 0; while ((byteBufferLength = inputFile.read(byteBuffer)) > 0) { bytes.write(byteBuffer,0,byteBufferLength); } inputFile.close(); return new InputStream(bytes.toByteArray()); } public InputStream(byte[] buf) { super(buf); } public int readBytes(byte[][] buffer, int bufferSize) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException { int numberOfReadBytes; try { byte[] bytes = new byte[bufferSize]; numberOfReadBytes = super.read(bytes); if(numberOfReadBytes > 0) { if(numberOfReadBytes < bufferSize) { byte[] smallerBuffer = new byte[numberOfReadBytes]; System.arraycopy(bytes, 0, smallerBuffer, 0, numberOfReadBytes); bytes = smallerBuffer; } } else { bytes = new byte[0]; numberOfReadBytes = 0; } buffer[0]=bytes; return numberOfReadBytes; } catch (IOException e) { throw new com.sun.star.io.IOException(e.getMessage(),this); } } public int readSomeBytes(byte[][] buffer, int bufferSize) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException { return readBytes(buffer, bufferSize); } public void skipBytes(int skipLength) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException { skip(skipLength); } public void closeInput() throws NotConnectedException, com.sun.star.io.IOException { try { close(); } catch (java.io.IOException e) { throw new com.sun.star.io.IOException(e.getMessage(), this); } } public long getLength() throws com.sun.star.io.IOException { return count; } public long getPosition() throws com.sun.star.io.IOException { return pos; } public void seek(long position) throws IllegalArgumentException, com.sun.star.io.IOException { pos = (int) position; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/IssueManager.java000066400000000000000000000346351225501747700314460ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.io.File; import java.util.Date; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.Collection; import java.util.Collections; import java.util.logging.Logger; import java.util.logging.Level; import java.text.ParseException; import java.io.IOException; import com.sun.star.lang.EventObject; import com.sun.star.container.XEnumeration; import com.sun.star.rdf.Statement; import com.sun.star.rdf.XURI; import com.sun.star.rdf.URI; import com.sun.star.rdf.XResource; import com.sun.star.rdf.XRepository; import com.sun.star.rdf.XNamedGraph; import com.sun.star.container.NoSuchElementException; import com.sun.star.rdf.RepositoryException; import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.beans.UnknownPropertyException; import com.sun.star.beans.PropertyVetoException; import be.docarch.accessodf.Check; import be.docarch.accessodf.DummyCheck; import be.docarch.accessodf.Checker; import be.docarch.accessodf.Provider; import be.docarch.accessodf.RunnableChecker; import be.docarch.accessodf.RemoteRunnableChecker; import be.docarch.accessodf.Constants; import be.docarch.accessodf.Report; import be.docarch.accessodf.Issue; import be.docarch.accessodf.FilterSorter; import be.docarch.accessodf.Repairer; import be.docarch.accessodf.Repairer.RepairMode; import be.docarch.accessodf.ooo.rdf.*; /** * * @author Bert Frees */ public class IssueManager { private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); private static final String TMP_NAME = Constants.TMP_PREFIX; private static final File TMP_DIR = Constants.getTmpDirectory(); public static enum Status { ALERT, ERROR, REPAIRED, IGNORED }; private final Document document; private final Settings settings; private final Provider checkers; private final Provider repairers; private final List allIssues; private FilterSorter filterSorter = null; private Issue selectedIssue = null; private Check selectedCheck = null; private Map> check2IssuesMap = null; //private Map check2repairerMap = null; public IssueManager(Document document, Provider checkers, Provider repairers) throws IllegalArgumentException, NoSuchElementException, RepositoryException, PropertyVetoException, WrappedTargetException, ParseException, com.sun.star.uno.Exception { logger.entering("IssueManager", ""); this.document = document; this.checkers = checkers; this.repairers = repairers; //Provider checks = new CheckProvider(checkers); settings = new Settings(document.xContext); //check2repairerMap = new HashMap(); check2IssuesMap = new HashMap>(); filterSorter = new FilterSorter(); filterSorter.setOrderPriority(FilterSorter.NAME, true); filterSorter.setOrderPriority(FilterSorter.CHECKID, true); allIssues = new ArrayList(); // Load accessibility issues from metadata loadMetadata(); logger.exiting("IssueManager", ""); } public void refresh() throws IllegalArgumentException, RepositoryException, UnknownPropertyException, NoSuchElementException, WrappedTargetException, PropertyVetoException, ParseException, IOException, com.sun.star.uno.Exception { settings.loadData(); File odtFile = null; for (Checker checker : checkers.list()) { if (checker instanceof RemoteRunnableChecker) { if (!settings.brailleChecks() && checker.getIdentifier().equals("http://docarch.be/odt2braille/checker/BrailleChecker")) { break; } if (odtFile == null) { odtFile = File.createTempFile(TMP_NAME, ".odt", TMP_DIR); odtFile.deleteOnExit(); document.ensureMetadataReferences(); document.storeToFile(odtFile); } RemoteRunnableChecker remoteChecker = (RemoteRunnableChecker)checker; remoteChecker.setOdtFile(odtFile); if (remoteChecker.run()) { document.removeAccessibilityData(remoteChecker.getIdentifier()); Report report = remoteChecker.getAccessibilityReport(); if (report != null) { document.importAccessibilityData(report.getFile(), remoteChecker.getIdentifier(), report.getName()); } } } else if (checker instanceof RunnableChecker) { ((RunnableChecker)checker).run(); } } // Load accessibility issues from metadata loadMetadata(); } public void clear() throws IllegalArgumentException, RepositoryException, PropertyVetoException, NoSuchElementException { Collection accessibilityDataGraphs = getAccessibilityDataGraphs(); for (XNamedGraph accessibilityDataGraph : accessibilityDataGraphs) { document.xDMA.removeMetadataFile(accessibilityDataGraph.getName()); } if (allIssues.size() > 0) { document.setModified(); allIssues.clear(); } check2IssuesMap.clear(); select(null); } private Collection getAccessibilityDataGraphs() throws IllegalArgumentException, RepositoryException { Collection accessibilityDataGraphs = new ArrayList(); XRepository xRepository = document.xDMA.getRDFRepository(); for (Checker checker : checkers.list()) { XURI type = URI.create(document.xContext, checker.getIdentifier()); XURI[] graphNames = document.xDMA.getMetadataGraphsWithType(type); for (int i=0; i accessibilityDataGraphs = getAccessibilityDataGraphs(); Map checkerDates = new HashMap(); Date longAgo = new Date(0); for (Checker checker : checkers.list()) { checkerDates.put(checker.getIdentifier(), longAgo); } allIssues.clear(); Issue issue, sameIssue; for (XNamedGraph graph : accessibilityDataGraphs) { Assertions assertions = new Assertions(graph, document); XEnumeration assertionEnum = graph.getStatements(null, URIs.RDF_TYPE, URIs.EARL_ASSERTION); XResource assertion = null; while (assertionEnum.hasMoreElements()) { assertion = ((Statement)assertionEnum.nextElement()).Subject; try { issue = assertions.read(assertion, checkers).getIssue(); } catch (Exception e) { logger.log(Level.SEVERE, null, e); continue; } if (issue.getCheck() instanceof DummyCheck) { checkerDates.put(issue.getChecker().getIdentifier(), issue.getCheckDate()); break; } if (allIssues.contains(issue)) { sameIssue = allIssues.remove(allIssues.indexOf(issue)); if (issue.getCheckDate().before(sameIssue.getCheckDate())) { if (issue.ignored()) { sameIssue.ignored(true); } issue.remove(); issue = sameIssue; } else { if (sameIssue.ignored()) { issue.ignored(true); } sameIssue.remove(); } } allIssues.add(issue); } } for (Issue i : allIssues) { String checker = i.getChecker().getIdentifier(); if (i.getCheckDate().after(checkerDates.get(checker))) { checkerDates.put(checker, i.getCheckDate()); } } for (Issue i : allIssues) { if (i.getCheckDate().before(checkerDates.get(i.getChecker().getIdentifier()))) { i.repaired(true); } } arrangeIssues(); logger.exiting("IssueManager", "loadMetadata"); } public void select(Object o) { selectedCheck = null; selectedIssue = null; if (o != null) { if (o instanceof Check) { Check check = (Check)o; for (Check c : getChecks()) { if (c.equals(check)) { selectedCheck = c; } } } else if (o instanceof Issue) { Issue issue = (Issue)o; for (Issue i : allIssues) { if (issue.equals(i)) { selectedIssue = i; selectedCheck = selectedIssue.getCheck(); } } } } } public boolean repair(Issue issue) throws IllegalArgumentException, RepositoryException, PropertyVetoException, NoSuchElementException { if (issue == null) { return false; } for (Repairer repairer : repairers.list()) { try { if (repairer.repair(issue)) { issue.repaired(true); return true; } } catch (Exception e) { } } return false; } public boolean repairable(Issue issue) { for (Repairer repairer : repairers.list()) { if (repairer.supports(issue)) { return true; } } return false; } public RepairMode getRepairMode(Issue issue) throws java.lang.IllegalArgumentException { for (Repairer repairer : repairers.list()) { if (repairer.supports(issue)) { return repairer.getRepairMode(issue); } } throw new java.lang.IllegalArgumentException(); } private void arrangeIssues() { Collections.sort(allIssues, filterSorter); check2IssuesMap.clear(); Check prevCheck = null; ArrayList issueList = null; for (Issue issue : allIssues) { Check check = issue.getCheck(); if (!check.equals(prevCheck)) { issueList = new ArrayList(); check2IssuesMap.put(check, issueList); } issueList.add(issue); prevCheck = check; } } public Collection getChecks() { return check2IssuesMap.keySet(); } public List getIssuesByCheck(Check check) { return check2IssuesMap.get(check); } public Status getStatus(Object o) { if (o != null) { if (o instanceof Check) { Check check = (Check)o; boolean alert = (check.getStatus() == Check.Status.ALERT); boolean allRepaired = true; boolean allIgnored = true; for (Issue issue : check2IssuesMap.get(check)) { if (!issue.ignored()) { allIgnored = false; } if (!issue.repaired()) { allRepaired = false; } } return (allRepaired? Status.REPAIRED: allIgnored? Status.IGNORED: alert? Status.ALERT: Status.ERROR); } else if (o instanceof Issue) { Issue issue = (Issue)o; boolean alert = (issue.getCheck().getStatus() == Check.Status.ALERT); return (issue.repaired()? Status.REPAIRED: issue.ignored()? Status.IGNORED: alert? Status.ALERT: Status.ERROR); } } return null; } public Issue selectedIssue() { return selectedIssue; } public Check selectedCheck() { return selectedCheck; } public void disposing(EventObject event) {} } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/MainChecker.java000066400000000000000000001543071225501747700312330ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.util.Date; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.HashSet; import java.util.ArrayList; import java.util.logging.Logger; import java.util.logging.Level; import java.text.SimpleDateFormat; import java.awt.Color; import com.sun.star.uno.AnyConverter; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.UnoRuntime; import com.sun.star.lang.XServiceInfo; import com.sun.star.lang.Locale; import com.sun.star.beans.XPropertySet; import com.sun.star.container.XEnumerationAccess; import com.sun.star.container.XEnumeration; import com.sun.star.container.XIndexAccess; import com.sun.star.container.XNamed; import com.sun.star.graphic.XGraphic; import com.sun.star.text.XTextFramesSupplier; import com.sun.star.text.XTextGraphicObjectsSupplier; import com.sun.star.text.XTextEmbeddedObjectsSupplier; import com.sun.star.text.XTextSectionsSupplier; import com.sun.star.text.XTextSection; import com.sun.star.text.XTextFrame; import com.sun.star.text.XTextRange; import com.sun.star.text.XTextContent; import com.sun.star.text.XTextTable; import com.sun.star.text.XTextCursor; import com.sun.star.text.XPageCursor; import com.sun.star.text.XWordCursor; import com.sun.star.text.TextContentAnchorType; import com.sun.star.table.XCell; import com.sun.star.table.XTableRows; import com.sun.star.table.XTableColumns; import com.sun.star.awt.FontUnderline; import com.sun.star.awt.FontSlant; import com.sun.star.style.ParagraphAdjust; import com.sun.star.style.XStyle; import com.sun.star.rdf.XURI; import com.sun.star.rdf.URI; import com.sun.star.rdf.XNamedGraph; import com.sun.star.drawing.XDrawPage; import com.sun.star.drawing.XDrawPageSupplier; import com.sun.star.form.XFormsSupplier2; import com.sun.star.linguistic2.XLanguageGuessing; import com.sun.star.beans.UnknownPropertyException; import com.sun.star.lang.IndexOutOfBoundsException; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.lang.WrappedTargetException; import com.sun.star.container.ElementExistException; import com.sun.star.container.NoSuchElementException; import com.sun.star.rdf.RepositoryException; import be.docarch.accessodf.Constants; import be.docarch.accessodf.Check; import be.docarch.accessodf.DummyCheck; import be.docarch.accessodf.Issue; import be.docarch.accessodf.RunnableChecker; import be.docarch.accessodf.ooo.rdf.Assertions; /** * * @author Bert Frees */ public class MainChecker implements RunnableChecker { private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); private static final boolean IS_MAC_OS = System.getProperty("os.name").toLowerCase().contains("mac os"); private final Document document; private final Settings settings; private final Collection fakeFonts; private final XLanguageGuessing languageGuesser; private final Map checks; private final Check dummyCheck = new DummyCheck(); private boolean daisyChecks = false; private Collection metadata = null; private int numberOfTitles = 0; private int numberOfHeadings = 0; private XPageCursor pageCursor = null; private String reportName = null; private Locale docLocale = null; private Map textMetaMap; private Collection detectedIssues; private Map detectedChecks; private Date date = new Date(); public MainChecker(Document document) throws IllegalArgumentException, com.sun.star.uno.Exception { this.document = document; XComponentContext xContext = document.xContext; settings = new Settings(xContext); textMetaMap = new HashMap(); detectedIssues = new ArrayList(); detectedChecks = new HashMap(); checks = new HashMap(); checks.put(dummyCheck.getIdentifier(), dummyCheck); for (GeneralCheck.ID id : GeneralCheck.ID.values()) { checks.put(id.name(), new GeneralCheck(id)); } for (DaisyCheck.ID id : DaisyCheck.ID.values()) { checks.put(id.name(), new DaisyCheck(id)); } fakeFonts = new HashSet(); fakeFonts.add("Bookshelf Symbol 7"); fakeFonts.add("Dingbats"); fakeFonts.add("Marlett"); fakeFonts.add("MS Reference Speciality"); fakeFonts.add("MT Extra"); fakeFonts.add("OpenSymbol"); fakeFonts.add("Symbol"); fakeFonts.add("Webdings"); fakeFonts.add("Wingdings"); fakeFonts.add("Wingdings 2"); fakeFonts.add("Wingdings 3"); languageGuesser = (XLanguageGuessing)UnoRuntime.queryInterface( XLanguageGuessing.class, document.xMCF.createInstanceWithContext( "com.sun.star.linguistic2.LanguageGuessing", document.xContext)); } public String getIdentifier() { return "http://docarch.be/accessodf/ooo/InternalChecker"; } public Collection list() { return checks.values(); } public Check get(String identifier) { return checks.get(identifier); } @Override public String toString() { return getIdentifier(); } public boolean run(){ //document.removeAccessibilityData(getIdentifier()); date = new Date(); reportName = MainChecker.class.getCanonicalName() + "/" + new SimpleDateFormat("yyyy-MM-dd'T'HH.mm.ss").format(new Date()) + ".rdf"; try { settings.loadData(); daisyChecks = settings.daisyChecks(); detectedIssues.clear(); detectedChecks.clear(); textMetaMap.clear(); // Traverse document traverseDocument(); // Save detected issues in RDF XURI[] types = new XURI[]{ URI.create(document.xContext, getIdentifier()) }; XURI graphURI = null; try { graphURI = document.xDMA.addMetadataFile(document.metaFolder + reportName, types); } catch (ElementExistException e) { graphURI = URI.create(document.xContext, document.metaFolderURI.getStringValue() + reportName); } XNamedGraph graph = document.xRepository.getGraph(graphURI); Assertions assertions = new Assertions(graph, document); if (detectedIssues.isEmpty()) { // Create dummy assertion to indicate that the document is validated assertions.create(new Issue(null, dummyCheck, this, date)).write(); } for (Issue i : detectedIssues) { if (detectedChecks.get(i.getCheck()) <= 10) { assertions.create(i).write(); } } for (Check c : detectedChecks.keySet()) { if (detectedChecks.get(c) > 10) { assertions.create(new Issue(null, c, this, date, detectedChecks.get(c))).write(); } } document.setModified(); return true; } catch (Exception e) { logger.log(Level.SEVERE, null, e); } return false; } private void traverseDocument() throws IllegalArgumentException, WrappedTargetException, RepositoryException, NoSuchElementException, IndexOutOfBoundsException, UnknownPropertyException, com.sun.star.uno.Exception, Exception { document.selectionSupplier.select(document.getFirstParagraph().getAnchor()); pageCursor = (XPageCursor)UnoRuntime.queryInterface(XPageCursor.class, document.viewCursor); metadata = new ArrayList(); numberOfTitles = 0; numberOfHeadings = 0; // Language docLocale = (Locale)AnyConverter.toObject(Locale.class, document.docPropertySet.getPropertyValue("CharLocale")); // Traverse all toplevel paragraphs and tables XEnumerationAccess enumerationAccess = (XEnumerationAccess)UnoRuntime.queryInterface( XEnumerationAccess.class, document.textDocument.getText()); XEnumeration paragraphs = enumerationAccess.createEnumeration(); traverseParagraphs(paragraphs, false, false); // Traverse all text frames XTextFramesSupplier xTextFramesSupplier = (XTextFramesSupplier) UnoRuntime.queryInterface( XTextFramesSupplier.class, document.doc); XIndexAccess textFrames = (XIndexAccess) UnoRuntime.queryInterface( XIndexAccess.class, xTextFramesSupplier.getTextFrames()); traverseTextFrames(textFrames); // Traverse all graphic objects XTextGraphicObjectsSupplier xTextGraphicObjectsSupplier = (XTextGraphicObjectsSupplier) UnoRuntime.queryInterface( XTextGraphicObjectsSupplier.class, document.doc); XIndexAccess graphicObjects = (XIndexAccess) UnoRuntime.queryInterface( XIndexAccess.class, xTextGraphicObjectsSupplier.getGraphicObjects()); traverseGraphicObjects(graphicObjects); // Traverse all other embedded objects XTextEmbeddedObjectsSupplier xTextEmbeddedObjectsSupplier = (XTextEmbeddedObjectsSupplier) UnoRuntime.queryInterface( XTextEmbeddedObjectsSupplier.class, document.doc); XIndexAccess embeddedObjects = (XIndexAccess) UnoRuntime.queryInterface( XIndexAccess.class, xTextEmbeddedObjectsSupplier.getEmbeddedObjects()); traverseEmbeddedObjects(embeddedObjects); // Traverse sections XTextSectionsSupplier xTextSectionsSupplier = (XTextSectionsSupplier) UnoRuntime.queryInterface( XTextSectionsSupplier.class, document.doc); XIndexAccess indexAccess = (XIndexAccess) UnoRuntime.queryInterface( XIndexAccess.class, xTextSectionsSupplier.getTextSections()); for (int i=0; i 0) { for (String id : metadata) { addIssue(new Issue(null, get(id), this)); } metadata.clear(); } } /* private void traverseFormComponents(XNameAccess formComponentContainer) throws Exception { String aNames[] = formComponentContainer.getElementNames(); for (int i=0; i fakeTableSpans = new ArrayList(); int fakeTableColumns = 0; int fakeTableRows = 0; while (paragraphs.hasMoreElements()) { element = paragraphs.nextElement(); serviceInfo = (XServiceInfo)UnoRuntime.queryInterface(XServiceInfo.class, element); textContent = (XTextContent)UnoRuntime.queryInterface(XTextContent.class, element); properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, serviceInfo); if (serviceInfo.supportsService("com.sun.star.text.TextTable")) { textTable = (XTextTable)UnoRuntime.queryInterface(XTextTable.class, element); tablePages = traverseTextTable(textTable, inFrame, inTable); keepWithTableBefore = AnyConverter.toBoolean(properties.getPropertyValue("KeepTogether")); bigTable = (tablePages > 1); afterTable = (caption == null); caption = null; fakeTable = null; fakeTableRows = 0; fakeTableColumns = 0; } else if (serviceInfo.supportsService("com.sun.star.text.Paragraph")) { Paragraph paragraph = new Paragraph(textContent); textRange = textContent.getAnchor(); text = textRange.getString(); keepWithNext = AnyConverter.toBoolean(properties.getPropertyValue("ParaKeepTogether")); newLevel = AnyConverter.toShort(properties.getPropertyValue("OutlineLevel")); alignment = AnyConverter.toInt(properties.getPropertyValue("ParaAdjust")); styleName = AnyConverter.toString(properties.getPropertyValue("ParaStyleName")); //numberingStyleName = AnyConverter.toString(properties.getPropertyValue("NumberingStyleName")); if (caption != null && captionAfterTable && bigTable) { addIssue(new Issue(new be.docarch.accessodf.ooo.Paragraph(textContent, document), get(GeneralCheck.ID.A_CaptionBelowBigTable.name()), this)); } caption = null; String style = styleName; do { if (style.equals("Table")) { caption = paragraph; break; } style = ((XStyle)UnoRuntime.queryInterface( XStyle.class, document.paragraphStyles.getByName(style))).getParentStyle(); } while (style.length() > 0); if (text.length() > 0) { if (alignment == ParagraphAdjust.BLOCK_value || alignment == ParagraphAdjust.STRETCH_value) { metadata.add(GeneralCheck.ID.A_JustifiedText.name()); } } if (!inFrame && styleName.equals("Title")) { if (text.length() == 0) { metadata.add(GeneralCheck.ID.E_EmptyTitle.name()); } else { numberOfTitles++; if (numberOfTitles > 1) { metadata.add(GeneralCheck.ID.E_ManyTitles.name()); } } } else if (inFrame && newLevel > 0) { metadata.add(GeneralCheck.ID.E_HeadingInFrame.name()); currentLevel = newLevel; } else if (newLevel > 0 && text.length() == 0) { metadata.add(GeneralCheck.ID.E_EmptyHeading.name()); } else if (newLevel > currentLevel + 1) { metadata.add(GeneralCheck.ID.E_HeadingSkip.name()); numberOfHeadings ++; currentLevel = newLevel; } else if (!alternateLevel && newLevel > 6) { alternateLevel = true; metadata.add(GeneralCheck.ID.A_AlternateLevel.name()); numberOfHeadings ++; currentLevel = newLevel; } else if (newLevel > 0) { numberOfHeadings ++; currentLevel = newLevel; } if (text.length() > 0) { int columns = getNumberOfColumns(text); if (columns > 1) { if (fakeTable != null && columns == fakeTableColumns) { fakeTable.add(paragraph.getEndPoint(), text); fakeTableRows++; if (fakeTableRows == 2) { fakeTableSpans.add(fakeTable); } } else { fakeTable = new Span(paragraph.getStartPoint(), paragraph.getEndPoint(), text); fakeTableColumns = columns; fakeTableRows = 1; } } else { fakeTable = null; fakeTableColumns = 0; fakeTableRows = 0; } if (text.matches("([\\.\\-\\+\\*\\#\\=\\_])\\1{10,}")) { metadata.add(GeneralCheck.ID.A_FakeLine.name()); } if (caption != null && afterTable && bigTable) { if (keepWithTableBefore || !keepWithNext) { addIssue(new Issue(new be.docarch.accessodf.ooo.Paragraph(textContent, document), get(GeneralCheck.ID.A_CaptionBelowBigTable.name()), this)); caption = null; } else { captionAfterTable = true; } } else { captionAfterTable = false; } boolean fakeSubtitle = newLevel == 0 && !styleName.equals("Title") && !styleName.equals("Subtitle") && afterTitle && alignment == ParagraphAdjust.CENTER_value && titleCentered; if (fakeSubtitle) { metadata.add(GeneralCheck.ID.A_NoSubtitle.name()); } boolean checkFakeSubtitle = newLevel == 0 && !styleName.equals("Title") && !styleName.equals("Subtitle") && afterTitle && alignment != ParagraphAdjust.CENTER_value && !titleCentered; boolean checkFakeHeading = newLevel == 0 && !styleName.equals("Title") && !styleName.equals("Subtitle") && !checkFakeSubtitle && !inTable; traverseTextPortions(paragraph, checkFakeSubtitle, checkFakeHeading); if (styleName.equals("Title")) { afterTitle = true; titleCentered = (alignment == ParagraphAdjust.CENTER_value); } else if (afterTitle) { afterTitle = false; } } if (metadata.size() > 0) { be.docarch.accessodf.ooo.Paragraph p = new be.docarch.accessodf.ooo.Paragraph(textContent, document); for (String id : metadata) { addIssue(new Issue(p, get(id), this)); } metadata.clear(); } afterTable = false; } else { fakeTable = null; fakeTableRows = 0; fakeTableColumns = 0; } } for (Span span : fakeTableSpans) { addMetadataToSpan(span, GeneralCheck.ID.A_FakeTable.name()); } if (caption != null && captionAfterTable) { addIssue(new Issue(new be.docarch.accessodf.ooo.Paragraph(textContent, document), get(GeneralCheck.ID.A_CaptionBelowBigTable.name()), this)); } if (textRange != null) { XTextCursor cursor = textRange.getText().createTextCursorByRange(textRange); cursor.gotoStart(false); if (inTable) { int[] pageRange = new int[2]; document.viewCursor.gotoRange(cursor, false); pageRange[0] = pageCursor.getPage(); cursor.gotoEnd(false); document.viewCursor.gotoRange(cursor, false); pageRange[1] = pageCursor.getPage(); return pageRange; } } return null; //traverseWords((XWordCursor)UnoRuntime.queryInterface(XWordCursor.class, cursor)); } private void traverseTextPortions(Paragraph paragraph, boolean checkNoSubtitle, boolean checkFakeHeading) throws UnknownPropertyException, WrappedTargetException, IllegalArgumentException, RepositoryException, NoSuchElementException, com.sun.star.uno.Exception, Exception { float charHeight = 0; float charWeight = 0; short underline = 0; double contrast; Locale locale; Locale guessedLocale; String fontName; FontSlant italic = null; boolean flash = false; String hyperlinkURL = ""; Span smallText = null; Span underlinedText = null; Span italicText = null; Span lowContrastText = null; Span fakeText = null; Span flashText = null; Hyperlink hyperlink = null; LocalizedSpan localizedText = null; int maxUnderlineLength = 250; int maxItalicLength = 250; int minLocaleGuessingLength = 100; boolean allBig = true; boolean allBold = true; Collection smallTextSpans = new ArrayList(); Collection underlinedTextSpans = new ArrayList(); Collection italicTextSpans = new ArrayList(); Collection lowContrastTextSpans = new ArrayList(); Collection fakeTextSpans = new ArrayList(); Collection localizedTextSpans = new ArrayList(); Collection hyperlinks = new ArrayList(); Collection flashTextSpans = new ArrayList(); for (TextPortion textPortion : paragraph.getTextPortions()) { XPropertySet properties = textPortion.properties; String text = textPortion.text; XTextRange start = textPortion.startPoint; XTextRange end = textPortion.endPoint; fontName = AnyConverter.toString(properties.getPropertyValue("CharFontName")); charHeight = AnyConverter.toFloat(properties.getPropertyValue("CharHeight")); charWeight = AnyConverter.toFloat(properties.getPropertyValue("CharWeight")); underline = AnyConverter.toShort(properties.getPropertyValue("CharUnderline")); italic = (FontSlant)AnyConverter.toObject(FontSlant.class, properties.getPropertyValue("CharPosture")); flash = AnyConverter.toBoolean(properties.getPropertyValue("CharFlash")); locale = (Locale)AnyConverter.toObject(Locale.class, properties.getPropertyValue("CharLocale")); try { hyperlinkURL = AnyConverter.toString(properties.getPropertyValue("HyperLinkURL")); } catch (UnknownPropertyException e) { hyperlinkURL = ""; } // Mac OS: "Apple AWT Java VM was loaded on first thread -- can't start AWT" (https://issues.apache.org/ooo/show_bug.cgi?id=47888) if (!IS_MAC_OS) { Color charColor = convertColor(AnyConverter.toInt(properties.getPropertyValue("CharColor"))); Color charBackColor = convertColor(AnyConverter.toInt(properties.getPropertyValue("CharBackColor"))); Color paraBackColor = convertColor(AnyConverter.toInt(properties.getPropertyValue("ParaBackColor"))); Color foreground = (charColor.getAlpha() == 0) ? Color.BLACK : charColor; Color background = (charBackColor.getAlpha() == 0) ? paraBackColor : charBackColor; contrast = contrastRatio(foreground, background); if (contrast < 4.5d) { if (lowContrastText == null) { lowContrastText = new Span(start, end, text); lowContrastTextSpans.add(lowContrastText); } else { lowContrastText.add(end, text); } } else { lowContrastText = null; } } if (fakeFonts.contains(fontName)) { if (fakeText == null) { fakeText = new Span(start, end, text); fakeTextSpans.add(fakeText); } else { fakeText.add(end, text); } } else { fakeText = null; } if (charHeight < 10) { if (smallText == null) { smallText = new Span(start, end, text); smallTextSpans.add(smallText); } else { smallText.add(end, text); } } else { smallText = null; } if (flash) { if (flashText == null) { flashText = new Span(start, end, text); flashTextSpans.add(flashText); } else { flashText.add(end, text); } } else { flashText = null; } if (underline != FontUnderline.NONE) { if (underlinedText == null) { underlinedText = new Span(start, end, text); underlinedTextSpans.add(underlinedText); } else { underlinedText.add(end, text); } } else { underlinedText = null; } if (italic == FontSlant.OBLIQUE || italic == FontSlant.ITALIC || italic == FontSlant.REVERSE_OBLIQUE || italic == FontSlant.REVERSE_ITALIC) { if (italicText == null) { italicText = new Span(start, end, text); italicTextSpans.add(italicText); } else { italicText.add(end, text); } } else { italicText = null; } if (localizedText != null && localizedText.locale().Language.equals(locale.Language) && localizedText.locale().Country.equals(locale.Country)) { localizedText.add(end, text); } else { localizedText = new LocalizedSpan(start, end, text, locale); localizedTextSpans.add(localizedText); } if (hyperlinkURL.length() > 0) { if (hyperlink == null) { hyperlink = new Hyperlink(start, end, text, hyperlinkURL); hyperlinks.add(hyperlink); } else { hyperlink.add(end, text); } } else { hyperlink = null; } allBig = allBig && (charHeight > 13); allBold = allBold && (charWeight > 100); } for (Span span : smallTextSpans) { addMetadataToSpan(span, GeneralCheck.ID.A_SmallText.name()); } for (Span span : flashTextSpans) { addMetadataToSpan(span, GeneralCheck.ID.A_FlashText.name()); } for (Span span : underlinedTextSpans) { if (span.getText().length() > maxUnderlineLength) { addMetadataToSpan(span, GeneralCheck.ID.A_LongUnderline.name()); } } for (Span span : italicTextSpans) { if (span.getText().length() > maxItalicLength) { addMetadataToSpan(span, GeneralCheck.ID.A_LongItalic.name()); } } for (Span span : lowContrastTextSpans) { addMetadataToSpan(span, GeneralCheck.ID.A_LowContrast.name()); } for (Span span : fakeTextSpans) { addMetadataToSpan(span, GeneralCheck.ID.A_FakeText.name()); } for (LocalizedSpan span : localizedTextSpans) { if (span.locale().Language.equals("zxx") && !(docLocale.Language.equals("zxx"))) { if (hyperlinks.contains(span)) { addMetadataToSpan(span, GeneralCheck.ID.E_NoHyperlinkLanguage.name()); } else { addMetadataToSpan(span, GeneralCheck.ID.E_NoLanguage.name()); } } else if (!span.locale().Language.equals("zxx") && span.locale().Language.equals(docLocale.Language) && span.locale().Country.equals(docLocale.Country) && span.getText().length() > minLocaleGuessingLength) { guessedLocale = languageGuesser.guessPrimaryLanguage(span.getText(), 0, span.getText().length()); if (!span.locale().Language.equals(guessedLocale.Language) && guessedLocale.Language.length() > 0) { addMetadataToSpan(span, GeneralCheck.ID.A_UnidentifiedLanguage.name()); } } } for (Hyperlink span : hyperlinks) { if (span.getText().equals(span.url())) { addMetadataToSpan(span, GeneralCheck.ID.A_NoHyperlinkText.name()); } } if (checkNoSubtitle && (allBig || allBold)) { metadata.add(GeneralCheck.ID.A_NoSubtitle.name()); } if (checkFakeHeading && (allBig || allBold)) { metadata.add(GeneralCheck.ID.A_FakeHeading.name()); } } private void traverseWords(XWordCursor cursor) throws IllegalArgumentException, RepositoryException, NoSuchElementException, com.sun.star.uno.Exception { String word = null; XTextRange startRange = null; XTextRange startCaps = null; XTextRange endCaps = null; String capsSample = ""; int numberOfWordsInCaps = 0; do { cursor.gotoEndOfWord(true); startRange = cursor.getStart(); word = cursor.getString(); if (word.length() > 0) { if (word.equals(word.toUpperCase()) && !word.matches("[0-9]+")) { if (startCaps == null) { startCaps = startRange; numberOfWordsInCaps = 0; capsSample = ""; } numberOfWordsInCaps++; capsSample += (word + " "); endCaps = cursor.getEnd(); } else { if (startCaps != null && numberOfWordsInCaps >= 3) { //addMetadataToSpan(startCaps, endCaps, checkURIs.get(GeneralCheck.ID.A_AllCaps), capsSample); } startCaps = null; } } } while (cursor.gotoNextWord(false)); if (startCaps != null && numberOfWordsInCaps >= 3) { //addMetadataToSpan(startCaps, endCaps, checkURIs.get(GeneralCheck.ID.A_AllCaps), capsSample); } } private int traverseTextTable(XTextTable table, boolean inFrame, boolean inTable) throws UnknownPropertyException, IllegalArgumentException, RepositoryException, IndexOutOfBoundsException, NoSuchElementException, WrappedTargetException, com.sun.star.uno.Exception, Exception { XPropertySet properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, table); XPropertySet rowProperties = null; XCell tableCell = null; XEnumerationAccess enumerationAccess = null; XEnumeration paragraphsInTableCell = null; boolean repeatTableHeading = AnyConverter.toBoolean(properties.getPropertyValue("RepeatHeadline")); //boolean keepTableTogether = !AnyConverter.toBoolean(properties.getPropertyValue("Split")); boolean keepTableRowsTogether = true; int[] pageRange = null; int[] cellPageRange = null; String[] cellNames = table.getCellNames(); XTableRows tableRows = table.getRows(); XTableColumns tableColumns = table.getColumns(); for (int i=0; i pageRange[0] + 1) { metadata.add(GeneralCheck.ID.A_BigTable.name()); } if (tableRows.getCount() * tableColumns.getCount() != cellNames.length) { // Dit is geen waterdichte oplossing ! metadata.add(GeneralCheck.ID.A_MergedCells.name()); } if (metadata.size() > 0) { be.docarch.accessodf.ooo.Table t = new be.docarch.accessodf.ooo.Table(table, document); for (String id : metadata) { addIssue(new Issue(t, get(id), this)); } metadata.clear(); } return pageRange[1] - pageRange[0] + 1; } private void traverseTextFrames(XIndexAccess textFrames) throws IndexOutOfBoundsException, UnknownPropertyException, WrappedTargetException, NoSuchElementException, RepositoryException, IllegalArgumentException, com.sun.star.uno.Exception, Exception { XTextFrame textFrame = null; for (int i=0; i 0 && daisyChecks) { String name = ((XNamed)UnoRuntime.queryInterface(XNamed.class, section)).getName(); if (name.equals("BodyMatterStart")) { metadata.add(DaisyCheck.ID.A_BodyMatterStartSectionNested.name()); } else if (name.equals("RearMatterStart")) { metadata.add(DaisyCheck.ID.A_RearMatterStartSectionNested.name()); } if (metadata.size() > 0) { for (String id : metadata) { addIssue(new Issue(null, get(id), this)); } metadata.clear(); } } for (XTextSection childSection : section.getChildSections()) { traverseTextSection(childSection, level+1); } } private void traverseGraphicObjects(XIndexAccess graphicObjects) throws IndexOutOfBoundsException, UnknownPropertyException, WrappedTargetException, RepositoryException, IllegalArgumentException, NoSuchElementException, Exception { Object graphicObject = null; XPropertySet properties = null; XGraphic graphic = null; XPropertySet mediaProperties = null; String title = null; String description = null; String url = null; String fileExtension = null; String mimeType = null; Collection graphicMetadata = new ArrayList(); for (int i=0; i 0) { XNamed namedGraphic = (XNamed)UnoRuntime.queryInterface(XNamed.class, graphicObject); DrawObject o = new DrawObject(namedGraphic, document); for (String id : graphicMetadata) { addIssue(new Issue(o, get(id), this)); } graphicMetadata.clear(); } } } private void traverseEmbeddedObjects(XIndexAccess embeddedObjects) throws IndexOutOfBoundsException, UnknownPropertyException, WrappedTargetException, RepositoryException, IllegalArgumentException, NoSuchElementException, com.sun.star.uno.Exception, Exception { Object embeddedObject = null; XPropertySet properties = null; String title = null; String description = null; for (int i=0; i textPortions; public Paragraph(XTextContent textContent) { textPortions = new ArrayList(); XEnumerationAccess enumerationAccess = (XEnumerationAccess)UnoRuntime.queryInterface( XEnumerationAccess.class, textContent); XEnumeration enumeration = enumerationAccess.createEnumeration(); try { XTextContent textMeta = null; TextPortion portion = null; while (enumeration.hasMoreElements()) { XTextRange range = (XTextRange)UnoRuntime.queryInterface(XTextRange.class, enumeration.nextElement()); XPropertySet propertySet = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, range); String textPortionType = AnyConverter.toString(propertySet.getPropertyValue("TextPortionType")); if (textPortionType.equals("InContentMetadata")) { textMeta = (XTextContent)AnyConverter.toObject( XTextContent.class, propertySet.getPropertyValue("InContentMetadata")); if (portion != null && !textMetaMap.containsKey(portion.endPoint)) { setTextMeta(portion.endPoint, textMeta); } } else if (textPortionType.equals("Text")) { if (range.getString().length() > 0) { portion = new TextPortion(range); if (textMeta != null) { setTextMeta(portion.startPoint, textMeta); } textMeta = null; textPortions.add(portion); } } else if (textPortionType.equals("SoftPageBreak")) { portion = null; } } } catch (Exception e) { } if (textPortions.size() > 0) { startPoint = textPortions.get(0).startPoint; endPoint = textPortions.get(textPortions.size()-1).endPoint; } else { startPoint = textContent.getAnchor().getStart(); endPoint = textContent.getAnchor().getEnd(); } } public List getTextPortions() { return textPortions; } public XTextRange getStartPoint() { return startPoint; } public XTextRange getEndPoint() { return endPoint; } } private class TextPortion { public final String text; public final XTextRange startPoint; public final XTextRange endPoint; public final XPropertySet properties; public TextPortion(XTextRange range) { text = range.getString(); startPoint = range.getStart(); endPoint = range.getEnd(); properties = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, range); } } private class Span { // TODO: samenvoegen met be.docarch.accessodf.ooo.Span ? private String text; private XTextRange startPoint; private XTextRange endPoint; public Span(XTextRange start, XTextRange end, String text) { startPoint = start; endPoint = end; this.text = text; } public void add(XTextRange end, String text) { endPoint = end; this.text += text; } public XTextRange getStartPoint() { return startPoint; } public XTextRange getEndPoint() { return endPoint; } public String getText() { return text; } @Override public boolean equals(Object object) { if (this == object) { return true; } if (!(object instanceof Span)) { return false; } try { Span that = (Span)object; return this.startPoint == that.startPoint && this.endPoint == that.endPoint; } catch (ClassCastException e) { return false; } } @Override public int hashCode() { int hash = 7; hash = 11 * hash + startPoint.hashCode(); hash = 11 * hash + endPoint.hashCode(); return hash; } } private class LocalizedSpan extends Span { private final Locale locale; public LocalizedSpan(XTextRange start, XTextRange end, String text, Locale locale) { super(start, end, text); this.locale = locale; } public Locale locale() { return locale; } } private class Hyperlink extends Span { private final String url; public Hyperlink(XTextRange start, XTextRange end, String text, String url) { super(start, end, text); this.url = url; } public String url() { return url; } } public void setTextMeta(XTextRange range, XTextContent textMeta) { textMetaMap.put(range, textMeta); } public XTextContent getTextMeta(XTextRange range) { XTextContent textMeta = textMetaMap.get(range); if (textMeta == null) { try { textMeta = (XTextContent)UnoRuntime.queryInterface( XTextContent.class, document.xMSF.createInstance("com.sun.star.text.InContentMetadata")); range.getText().insertTextContent(range, textMeta, true); } catch (Exception e) { } } return textMeta; } private static int getNumberOfColumns(String paragraph) { paragraph = paragraph.replaceAll("[\\x20]{5,}", "\t"); paragraph = paragraph.replaceAll("[\\x20]+", ""); paragraph = paragraph.replaceAll("[\\t]+", "\t"); paragraph = paragraph.trim(); if (paragraph.length() == 0) { return 0; } return countOccurrences(paragraph, '\t') + 1; } public static int countOccurrences(String haystack, char needle) { int count = 0; for (int i=0; i < haystack.length(); i++) { if (haystack.charAt(i) == needle) { count++; } } return count; } /* * Convert com.sun.star.util.Color to java.awt.Color */ private static Color convertColor(int comSunStarUtilColor) { Color c = new Color(comSunStarUtilColor, true); int invertedAlpha = 0xFF - c.getAlpha(); return new Color(c.getRed(), c.getGreen(), c.getBlue(), invertedAlpha); } /* * Relative luminance of a color as defined at http://www.w3.org/TR/WCAG20/#contrast-ratiodef: * The relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white */ private static double relativeLuminance(Color color) { double R, G, B; double RsRGB, GsRGB, BsRGB; RsRGB = (double)(color.getRed()) / 0xFF; GsRGB = (double)(color.getGreen()) / 0xFF; BsRGB = (double)(color.getBlue()) / 0xFF; R = (RsRGB <= 0.03928) ? RsRGB / 12.92 : Math.pow((RsRGB + 0.055) / 1.055, 2.4); G = (GsRGB <= 0.03928) ? GsRGB / 12.92 : Math.pow((GsRGB + 0.055) / 1.055, 2.4); B = (BsRGB <= 0.03928) ? BsRGB / 12.92 : Math.pow((BsRGB + 0.055) / 1.055, 2.4); return 0.2126*R + 0.7152*G + 0.0722*B; } /* * Contrast ratio of two colors as defined at http://www.w3.org/TR/WCAG20/#contrast-ratiodef */ private static double contrastRatio(Color color1, Color color2) { double L1 = relativeLuminance(color1); double L2 = relativeLuminance(color2); return (Math.max(L1, L2) + 0.05)/(Math.min(L1, L2) + 0.05); } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/MainRepairer.java000066400000000000000000000400741225501747700314330ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import be.docarch.accessodf.Repairer; import java.util.HashSet; import java.util.Collection; import com.sun.star.beans.PropertyValue; import com.sun.star.beans.XPropertySet; import com.sun.star.frame.XDispatchHelper; import com.sun.star.frame.XDispatchProvider; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.AnyConverter; import com.sun.star.lang.Locale; import com.sun.star.style.ParagraphAdjust; import com.sun.star.style.XStyle; import com.sun.star.table.XTableRows; import com.sun.star.text.TextContentAnchorType; import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.beans.UnknownPropertyException; import com.sun.star.container.NoSuchElementException; import com.sun.star.beans.PropertyVetoException; import be.docarch.accessodf.Check; import be.docarch.accessodf.Issue; import be.docarch.accessodf.Element; /** * * @author Bert Frees */ public class MainRepairer implements Repairer { private Collection supportedGeneralChecks; private Collection supportedElementSpecificChecks; private Document document; private static XDispatchHelper dispatcher; private static XDispatchProvider dispatchProvider; public MainRepairer(Document document) throws com.sun.star.uno.Exception { this.document = document; XComponentContext xContext = document.xContext; dispatcher = (XDispatchHelper)UnoRuntime.queryInterface( XDispatchHelper.class, document.xMCF.createInstanceWithContext( "com.sun.star.frame.DispatchHelper", xContext)); dispatchProvider = (XDispatchProvider)UnoRuntime.queryInterface( XDispatchProvider.class, document.xModel.getCurrentController().getFrame()); supportedElementSpecificChecks = new HashSet(); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_ImageWithoutAlt)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_FormulaWithoutAlt)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_ObjectWithoutAlt)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_LinkedImage)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.E_NoHyperlinkLanguage)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_NoHyperlinkText)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_NoTableHeading)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_JustifiedText)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_NoSubtitle)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_BreakRows)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.E_EmptyTitle)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.E_EmptyHeading)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_FlashText)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.A_SmallText)); supportedElementSpecificChecks.add(new GeneralCheck(GeneralCheck.ID.E_ImageAnchorFloat)); supportedGeneralChecks = new HashSet(); supportedGeneralChecks.add(new GeneralCheck(GeneralCheck.ID.E_NoDefaultLanguage)); supportedGeneralChecks.add(new DaisyCheck(DaisyCheck.ID.A_EmptyTitleField)); } public String getIdentifier() { return "be.docarch.accessodf.ooo.InternalRepairer"; } public boolean repair(Issue issue) { try { PropertyValue[] dispatchProperties; XPropertySet properties; Check check = issue.getCheck(); Element element = issue.getElement(); if (supports(issue)) { String id = check.getIdentifier(); if (id.equals(GeneralCheck.ID.A_ImageWithoutAlt.name()) || id.equals(GeneralCheck.ID.A_FormulaWithoutAlt.name()) || id.equals(GeneralCheck.ID.A_ObjectWithoutAlt.name())) { dispatchProperties = new PropertyValue[]{}; dispatcher.executeDispatch(dispatchProvider, ".uno:ObjectTitleDescription", "", 0, dispatchProperties); if (element == null) { return false; } try { properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((DrawObject)element).getXNamed()); return (AnyConverter.toString(properties.getPropertyValue("Title")).length() > 0); } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(GeneralCheck.ID.E_ImageAnchorFloat.name())) { try { properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((DrawObject)element).getXNamed()); properties.setPropertyValue("AnchorType", TextContentAnchorType.AS_CHARACTER); return true; } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(DaisyCheck.ID.A_EmptyTitleField.name())) { dispatchProperties = new PropertyValue[]{}; dispatcher.executeDispatch(dispatchProvider, ".uno:SetDocumentProperties", "", 0, dispatchProperties); return (document.docProperties.getTitle().length() > 0); } else if (id.equals(GeneralCheck.ID.A_LinkedImage.name())) { dispatchProperties = new PropertyValue[]{}; dispatcher.executeDispatch(dispatchProvider, ".uno:GraphicDialog", "", 0, dispatchProperties); // TODO: return value } else if (id.equals(GeneralCheck.ID.A_NoTableHeading.name())) { dispatchProperties = new PropertyValue[]{}; dispatcher.executeDispatch(dispatchProvider, ".uno:TableDialog", "", 0, dispatchProperties); if (element == null) { return false; } try { return AnyConverter.toBoolean(((XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((Table)element).getXTextTable())).getPropertyValue("RepeatHeadline")); } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(GeneralCheck.ID.A_NoHyperlinkText.name())) { dispatchProperties = new PropertyValue[]{}; dispatcher.executeDispatch(dispatchProvider, ".uno:EditHyperlink", "", 0, dispatchProperties); // TODO: return value } else if (id.equals(GeneralCheck.ID.E_NoHyperlinkLanguage.name())) { Locale docLocale = (Locale)AnyConverter.toObject(Locale.class, document.docPropertySet.getPropertyValue("CharLocale")); if (!docLocale.Language.equals("zxx")) { try { XStyle hyperlinkStyle = (XStyle)UnoRuntime.queryInterface( XStyle.class, document.characterStyles.getByName("Internet Link")); properties =(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, hyperlinkStyle); properties.setPropertyValue("CharLocale", docLocale); } catch (NoSuchElementException e) { } catch (PropertyVetoException e) { } } // TODO: return value } else if (id.equals(GeneralCheck.ID.E_NoDefaultLanguage.name())) { dispatchProperties = new PropertyValue[1]; dispatchProperties[0] = new PropertyValue(); dispatchProperties[0].Name = "Language"; dispatchProperties[0].Value = "*"; //dispatcher.executeDispatch(dispatchProvider, ".uno:OptionsTreeDialog", "", 0, dispatchProperties); dispatcher.executeDispatch(dispatchProvider, ".uno:LanguageStatus", "", 0, dispatchProperties); return !(((Locale)AnyConverter.toObject( Locale.class, document.docPropertySet.getPropertyValue("CharLocale"))).Language.equals("zxx")); // TODO: return value NIET JUIST ! docPropertySet is op dit moment nog niet aangepast } else if (id.equals(GeneralCheck.ID.A_NoSubtitle.name())) { if (element == null) { return false; } try { properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((Paragraph)element).getXTextContent()); try { document.paragraphStyles.getByName("Subtitle"); properties.setPropertyValue("ParaStyleName", "Subtitle"); return true; } catch (NoSuchElementException e) { } } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(GeneralCheck.ID.A_JustifiedText.name())) { if (element == null) { return false; } try { properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((Paragraph)element).getXTextContent()); properties.setPropertyValue("ParaAdjust", ParagraphAdjust.LEFT_value); properties = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, document.paragraphStyles.getByName( AnyConverter.toString(properties.getPropertyValue("ParaStyleName")))); int paraAdjust = AnyConverter.toInt(properties.getPropertyValue("ParaAdjust")); if (paraAdjust == ParagraphAdjust.BLOCK_value || paraAdjust == ParagraphAdjust.STRETCH_value) { properties.setPropertyValue("ParaAdjust", ParagraphAdjust.LEFT_value); } return true; } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(GeneralCheck.ID.E_EmptyTitle.name()) || id.equals(GeneralCheck.ID.E_EmptyHeading.name())) { if (element == null) { return false; } try { properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((Paragraph)element).getXTextContent()); properties.setPropertyValue("ParaStyleName", "Standard"); return true; } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(GeneralCheck.ID.A_FlashText.name())) { if (element == null) { return false; } try { properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((Span)element).getXTextCursor()); properties.setPropertyValue("CharFlash", false); return true; } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(GeneralCheck.ID.A_SmallText.name())) { if (element == null) { return false; } try { properties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ((Span)element).getXTextCursor()); properties.setPropertyValue("CharHeight", 10); return true; } catch (ClassCastException e) { } catch (Exception e) { } } else if (id.equals(GeneralCheck.ID.A_BreakRows.name())) { if (element == null) { return false; } try { XTableRows tableRows = ((Table)element).getXTextTable().getRows(); XPropertySet rowProperties = null; for (int i=0; i. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.ui.XContextMenuInterceptor; import com.sun.star.ui.ContextMenuInterceptorAction; import com.sun.star.ui.ActionTriggerSeparatorType; import com.sun.star.ui.ContextMenuExecuteEvent; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.beans.XPropertySet; import com.sun.star.container.XIndexContainer; import com.sun.star.uno.UnoRuntime; import com.sun.star.view.XSelectionSupplier; public class MyContextMenuInterceptor implements XContextMenuInterceptor { private Document document = null; public MyContextMenuInterceptor(Document document) { this.document = document; } public ContextMenuInterceptorAction notifyContextMenuExecute(ContextMenuExecuteEvent aEvent) throws RuntimeException { try { XIndexContainer xContextMenu = aEvent.ActionTriggerContainer; XSelectionSupplier selection = aEvent.Selection; XPropertySet xMenuEntry = null; XMultiServiceFactory xMenuElementFactory = (XMultiServiceFactory)UnoRuntime.queryInterface( XMultiServiceFactory.class, xContextMenu); if (xMenuElementFactory != null) { XPropertySet xRootMenuEntry = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTrigger")); XPropertySet xSeparator = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTriggerSeparator") ); XIndexContainer xSubMenuContainer = (XIndexContainer)UnoRuntime.queryInterface( XIndexContainer.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTriggerContainer")); xSeparator.setPropertyValue("SeparatorType", new Short(ActionTriggerSeparatorType.LINE)); xRootMenuEntry.setPropertyValue("Text", new String("Accessiblity")); xRootMenuEntry.setPropertyValue("CommandURL", new String("")); xRootMenuEntry.setPropertyValue("SubContainer", xSubMenuContainer ); xMenuEntry = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTrigger")); xMenuEntry.setPropertyValue("Text", new String("Braille Settings")); xMenuEntry.setPropertyValue("CommandURL", new String("be.docarch.odt2braille.addon.odt2brailleaddon:SettingsCommand")); xSubMenuContainer.insertByIndex(0, xMenuEntry); xMenuEntry = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTrigger")); xMenuEntry.setPropertyValue("Text", new String("Task Pane")); xMenuEntry.setPropertyValue("CommandURL", new String(".uno:TaskPane")); xSubMenuContainer.insertByIndex(1, xMenuEntry); xContextMenu.insertByIndex (0, xSeparator ); xContextMenu.insertByIndex (0, xRootMenuEntry ); return ContextMenuInterceptorAction.EXECUTE_MODIFIED ; } } catch ( com.sun.star.beans.UnknownPropertyException ex ) { // do something useful // we used a unknown property } catch ( com.sun.star.lang.IndexOutOfBoundsException ex ) { // do something useful // we used an invalid index for accessing a container } catch ( com.sun.star.uno.Exception ex ) { // something strange has happend! } catch ( java.lang.Throwable ex ) { // catch java exceptions - do something useful } return ContextMenuInterceptorAction.IGNORED; } }accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/OutputStream.java000066400000000000000000000043371225501747700315330ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import java.io.ByteArrayOutputStream; import com.sun.star.io.BufferSizeExceededException; import com.sun.star.io.NotConnectedException; import com.sun.star.io.XOutputStream; /** * From the thread OOo-Java: Using XInputStream... */ public class OutputStream extends ByteArrayOutputStream implements XOutputStream { public OutputStream() { super(32768); } public void writeBytes(byte[] values) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException { try { this.write(values); } catch (java.io.IOException e) { throw(new com.sun.star.io.IOException(e.getMessage())); } } public void closeOutput() throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException { try { super.flush(); super.close(); } catch (java.io.IOException e) { throw(new com.sun.star.io.IOException(e.getMessage())); } } @Override public void flush() { try { super.flush(); } catch (java.io.IOException e) { } } }accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/Paragraph.java000066400000000000000000000074121225501747700307610ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.UnoRuntime; import com.sun.star.lang.XServiceInfo; import com.sun.star.text.XTextContent; import com.sun.star.rdf.XMetadatable; import com.sun.star.lang.IllegalArgumentException; /** * * @author Bert Frees */ public class Paragraph extends FocusableElement { private final XTextContent xTextContent; private final XMetadatable metadatable; private final Document doc; private String sample = ""; private String id = ""; public Paragraph(XTextContent textContent, Document doc) throws Exception { if (textContent == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; xTextContent = textContent; metadatable = (XMetadatable)UnoRuntime.queryInterface(XMetadatable.class, xTextContent); if (metadatable == null) { throw new Exception("Cannot cast to XMetadatable"); } metadatable.ensureMetadataReference(); init(); } public Paragraph(XMetadatable metadatable, Document doc) throws Exception { if (metadatable == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; this.metadatable = metadatable; metadatable.ensureMetadataReference(); xTextContent = (XTextContent)UnoRuntime.queryInterface(XTextContent.class, metadatable); if (xTextContent == null) { throw new Exception("Cannot cast to XTextContent"); } init(); } private void init() throws Exception { id = metadatable.getMetadataReference().Second; if (!((XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class, xTextContent)).supportsService("com.sun.star.text.Paragraph")) { throw new Exception("Does not support service com.sun.star.text.Paragraph"); } sample = xTextContent.getAnchor().getString(); if (sample.length() > 30) { sample = sample.substring(0, 30) + "\u2026"; } } public XTextContent getXTextContent() { return xTextContent; } public XMetadatable getXMetadatable() { return metadatable; } public String toString() { return sample; } public int hashCode() { final int PRIME = 31; int hash = 1; hash = PRIME + id.hashCode(); return hash; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Paragraph that = (Paragraph)obj; return (this.id.equals(that.id)); } @Override public boolean focus() { try { if (xTextContent != null) { return doc.selectionSupplier.select(xTextContent.getAnchor()); } } catch (IllegalArgumentException e) { } return false; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/RepairerProvider.java000066400000000000000000000037741225501747700323470ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import be.docarch.accessodf.Provider; import be.docarch.accessodf.Repairer; import java.util.Collection; import java.util.Map; import java.util.HashMap; import java.util.Iterator; import javax.imageio.spi.ServiceRegistry; /** * * @author Bert Frees */ public class RepairerProvider implements Provider { private final Map repairers; public RepairerProvider(ClassLoader classLoader, Document document) { repairers = new HashMap(); Repairer repairer; Iterator i = ServiceRegistry.lookupProviders(Repairer.class, classLoader); while (i.hasNext()) { repairer = i.next(); repairers.put(repairer.getIdentifier(), repairer); } try { Repairer mainRepairer = new MainRepairer(document); repairers.put(mainRepairer.getIdentifier(), mainRepairer); } catch (com.sun.star.uno.Exception e) { } } public Collection list() { return repairers.values(); } public Repairer get(String identifier) { return repairers.get(identifier); } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/Settings.java000066400000000000000000000110261225501747700306500ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.UnoRuntime; import com.sun.star.deployment.PackageInformationProvider; import com.sun.star.deployment.XPackageInformationProvider; import com.sun.star.container.XNameAccess; import com.sun.star.beans.XPropertySet; import com.sun.star.util.XChangesBatch; /** * * @author Bert Frees */ public class Settings { private boolean daisyChecks = false; private boolean brailleChecks = false; private final boolean daisyChecksAvailable; private final boolean brailleChecksAvailable; private XNameAccess accessLeaves = null; private XPropertySet xLeaf = null; public Settings(XComponentContext context) { accessLeaves = ConfigurationAccess.createUpdateAccess(context, "/be.docarch.accessodf.ooo.optionspage.Settings/Leaves"); try { xLeaf = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, accessLeaves.getByName("accessibilityChecks")); } catch (com.sun.star.container.NoSuchElementException e) { } catch (com.sun.star.lang.WrappedTargetException e) { } XPackageInformationProvider xPkgInfo = PackageInformationProvider.get(context); daisyChecksAvailable = (xPkgInfo.getPackageLocation("com.versusoft.packages.ooo.odt2daisy.addon.Odt2DaisyAddOn-macosx_x86").length() > 0) || (xPkgInfo.getPackageLocation("com.versusoft.packages.ooo.odt2daisy.addon.Odt2DaisyAddOn-macosx_powerpc").length() > 0) || (xPkgInfo.getPackageLocation("com.versusoft.packages.ooo.odt2daisy.addon.Odt2DaisyAddOn-windows_x86").length() > 0) || (xPkgInfo.getPackageLocation("com.versusoft.packages.ooo.odt2daisy.addon.Odt2DaisyAddOn-linux_x86").length() > 0) || (xPkgInfo.getPackageLocation("com.versusoft.packages.ooo.odt2daisy.addon.Odt2DaisyAddOn-linux_x86_64").length() > 0) || (xPkgInfo.getPackageLocation("com.versusoft.packages.ooo.odt2daisy.addon.Odt2DaisyAddOn-solaris_x86").length() > 0) || (xPkgInfo.getPackageLocation("com.versusoft.packages.ooo.odt2daisy.addon.Odt2DaisyAddOn-solaris_sparc").length() > 0); brailleChecksAvailable = (xPkgInfo.getPackageLocation("be.docarch.odt2braille.ooo.odt2brailleaddon").length() > 0); daisyChecks(true); brailleChecks(true); } public void loadData() throws com.sun.star.uno.Exception { if (xLeaf != null) { daisyChecks(xLeaf.getPropertyValue("daisyChecks").toString().equals("1")); brailleChecks(xLeaf.getPropertyValue("brailleChecks").toString().equals("1")); } } public void saveData() throws com.sun.star.uno.Exception { if (xLeaf != null) { xLeaf.setPropertyValue("daisyChecks", (short)(daisyChecks?1:0)); xLeaf.setPropertyValue("brailleChecks", (short)(brailleChecks?1:0)); XChangesBatch xUpdateCommit = (XChangesBatch)UnoRuntime.queryInterface( XChangesBatch.class, accessLeaves); xUpdateCommit.commitChanges(); } } public boolean daisyChecks() { return daisyChecks; } public boolean brailleChecks() { return brailleChecks; } public void daisyChecks(boolean enable) { daisyChecks = daisyChecksAvailable && enable; } public void brailleChecks(boolean enable) { brailleChecks = brailleChecksAvailable && enable; } public boolean daisyChecksAvailable() { return daisyChecksAvailable; } public boolean brailleChecksAvailable() { return brailleChecksAvailable; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/Span.java000066400000000000000000000116771225501747700277650ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.UnoRuntime; import com.sun.star.lang.XServiceInfo; import com.sun.star.text.XTextContent; import com.sun.star.text.XTextCursor; import com.sun.star.rdf.XMetadatable; /** * * @author Bert Frees */ public class Span extends FocusableElement { private final XTextContent startXTextContent; private final XTextContent endXTextContent; private final Document doc; private final XMetadatable startXMetadatable; private final XMetadatable endXMetadatable; private XTextCursor cursor; private String startId; private String endId = ""; private String sample = ""; public Span(XTextContent start, XTextContent end, Document doc) throws Exception { if (start == null || end == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; startXTextContent = start; endXTextContent = end; startXMetadatable = (XMetadatable)UnoRuntime.queryInterface(XMetadatable.class, startXTextContent); endXMetadatable = (XMetadatable)UnoRuntime.queryInterface(XMetadatable.class, endXTextContent); if (startXMetadatable == null || endXMetadatable == null) { throw new Exception("Cannot cast to XMetadatable"); } startXMetadatable.ensureMetadataReference(); endXMetadatable.ensureMetadataReference(); init(); } public Span(XMetadatable start, XMetadatable end, Document doc) throws Exception { if (start == null || end == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; startXMetadatable = start; endXMetadatable = end; startXMetadatable.ensureMetadataReference(); endXMetadatable.ensureMetadataReference(); startXTextContent = (XTextContent)UnoRuntime.queryInterface(XTextContent.class, startXMetadatable); endXTextContent = (XTextContent)UnoRuntime.queryInterface(XTextContent.class, endXMetadatable); if (startXTextContent == null || endXTextContent == null) { throw new Exception("Cannot cast to XTextContent"); } init(); } private void init() throws Exception { startId = startXMetadatable.getMetadataReference().Second; endId = endXMetadatable.getMetadataReference().Second; if (!((XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class, startXTextContent)).supportsService("com.sun.star.text.InContentMetadata") || !((XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class, endXTextContent)).supportsService("com.sun.star.text.InContentMetadata")) { throw new Exception("Does not support service com.sun.star.text.InContentMetadata"); } cursor = startXTextContent.getAnchor().getEnd().getText().createTextCursorByRange(startXTextContent.getAnchor().getEnd()); cursor.gotoRange(endXTextContent.getAnchor().getStart(), true); sample = cursor.getString(); if (sample.length() > 30) { sample = sample.substring(0, 30) + "\u2026"; } } public XTextCursor getXTextCursor() { return cursor; } public XMetadatable getStartXMetadatable() { return startXMetadatable; } public XMetadatable getEndXMetadatable() { return endXMetadatable; } public String toString() { return sample; } public int hashCode() { final int PRIME = 31; int hash = 1; hash = hash * PRIME + startId.hashCode(); hash = hash * PRIME + endId.hashCode(); return hash; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) {return false; } if (getClass() != obj.getClass()) { return false; } final Span that = (Span)obj; return (this.startId.equals(that.startId) && this.endId.equals(that.endId)); } @Override public boolean focus() { if (cursor != null) { doc.viewCursor.gotoRange(cursor, false); return true; } return false; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/Table.java000066400000000000000000000074031225501747700301030ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.UnoRuntime; import com.sun.star.container.XNamed; import com.sun.star.text.XTextTableCursor; import com.sun.star.text.XTextRange; import com.sun.star.text.XTextTable; import com.sun.star.table.XCellRange; import com.sun.star.lang.IllegalArgumentException; /** * * @author Bert Frees */ public class Table extends FocusableElement { private final Document doc; private final XTextTable xTextTable; private final XNamed xNamed; public Table(String name, Document doc) throws Exception { if (name == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; try { Object o = doc.tables.getByName(name); xTextTable = (XTextTable)UnoRuntime.queryInterface(XTextTable.class, o); xNamed = (XNamed)UnoRuntime.queryInterface(XNamed.class, xTextTable); } catch (Exception e) { throw new Exception("No table found with name " + name); } } public Table(XTextTable xTextTable, Document doc) throws IllegalArgumentException { if (xTextTable == null || doc == null) { throw new IllegalArgumentException(); } this.doc = doc; this.xTextTable = xTextTable; xNamed = (XNamed)UnoRuntime.queryInterface(XNamed.class, xTextTable); } public XTextTable getXTextTable() { return xTextTable; } public XNamed getXNamed() { return xNamed; } public String toString() { return xNamed.getName(); } public int hashCode() { final int PRIME = 31; int hash = 1; hash = hash * PRIME + toString().hashCode(); return hash; } public boolean equals(Object obj) { if (this == obj) {return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Table that = (Table)obj; return (this.toString().equals(that.toString())); } @Override public boolean focus() { try { if (xTextTable != null) { String[] cellNames = xTextTable.getCellNames(); doc.viewCursor.gotoRange((XTextRange)UnoRuntime.queryInterface( XTextRange.class, xTextTable.getCellByName(cellNames[cellNames.length - 1])), false); if (cellNames.length > 1) { XCellRange cellRange = (XCellRange)UnoRuntime.queryInterface(XCellRange.class, xTextTable); XTextTableCursor cursor = xTextTable.createCursorByCellName(cellNames[0]); cursor.gotoCellByName(cellNames[cellNames.length - 1], true); doc.selectionSupplier.select(cellRange.getCellRangeByName(cursor.getRangeName())); } return true; } } catch (IllegalArgumentException e) { } return false; } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/URIs.java000066400000000000000000000114321225501747700276730ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.XComponentContext; import com.sun.star.rdf.URI; import com.sun.star.rdf.XURI; import com.sun.star.lang.IllegalArgumentException; import be.docarch.accessodf.Constants; /** * * @author Bert Frees */ public abstract class URIs { public static XURI RDF_TYPE; public static XURI RDFS_SUBCLASSOF; public static XURI EARL_TESTSUBJECT; public static XURI EARL_TESTRESULT; public static XURI EARL_TESTCASE; public static XURI EARL_ASSERTION; public static XURI EARL_ASSERTOR; public static XURI EARL_OUTCOME; public static XURI EARL_FAILED; public static XURI EARL_PASSED; public static XURI EARL_RESULT; public static XURI EARL_TEST; public static XURI EARL_SUBJECT; public static XURI EARL_ASSERTEDBY; public static XURI EARL_MAINASSERTOR; public static XURI EARL_SOFTWARE; public static XURI FOAF_GROUP; public static XURI FOAF_MEMBER; public static XURI FOAF_PERSON; public static XURI FOAF_NAME; public static XURI DCT_DATE; public static XURI DCT_TITLE; public static XURI DCT_DESCRIPTION; public static XURI A11Y_CHECKER; public static XURI A11Y_START; public static XURI A11Y_END; public static XURI A11Y_DOCUMENT; public static XURI A11Y_PARAGRAPH; public static XURI A11Y_SPAN; public static XURI A11Y_TABLE; public static XURI A11Y_OBJECT; public static XURI A11Y_IGNORE; public static XURI A11Y_COUNT; public static void init(XComponentContext context) { try { RDF_TYPE = URI.createKnown(context, com.sun.star.rdf.URIs.RDF_TYPE); RDFS_SUBCLASSOF = URI.createKnown(context, com.sun.star.rdf.URIs.RDFS_SUBCLASSOF); EARL_TESTSUBJECT = URI.create(context, Constants.EARL_TESTSUBJECT); EARL_TESTRESULT = URI.create(context, Constants.EARL_TESTRESULT); EARL_TESTCASE = URI.create(context, Constants.EARL_TESTCASE); EARL_ASSERTION = URI.create(context, Constants.EARL_ASSERTION); EARL_ASSERTOR = URI.create(context, Constants.EARL_ASSERTOR); EARL_OUTCOME = URI.create(context, Constants.EARL_OUTCOME); EARL_RESULT = URI.create(context, Constants.EARL_RESULT); EARL_TEST = URI.create(context, Constants.EARL_TEST); EARL_SUBJECT = URI.create(context, Constants.EARL_SUBJECT); EARL_ASSERTEDBY = URI.create(context, Constants.EARL_ASSERTEDBY); EARL_FAILED = URI.create(context, Constants.EARL_FAILED); EARL_PASSED = URI.create(context, Constants.EARL_PASSED); EARL_MAINASSERTOR = URI.create(context, Constants.EARL_MAINASSERTOR); EARL_SOFTWARE = URI.create(context, Constants.EARL_SOFTWARE); FOAF_GROUP = URI.create(context, Constants.FOAF_GROUP); FOAF_MEMBER = URI.create(context, Constants.FOAF_MEMBER); FOAF_PERSON = URI.create(context, Constants.FOAF_PERSON); FOAF_NAME = URI.create(context, Constants.FOAF_NAME); DCT_DATE = URI.create(context, Constants.DCT_DATE); DCT_TITLE = URI.create(context, Constants.DCT_TITLE); DCT_DESCRIPTION = URI.create(context, Constants.DCT_DESCRIPTION); A11Y_CHECKER = URI.create(context, Constants.A11Y_CHECKER); A11Y_START = URI.create(context, Constants.A11Y_START); A11Y_END = URI.create(context, Constants.A11Y_END); A11Y_IGNORE = URI.create(context, Constants.A11Y_IGNORE); A11Y_COUNT = URI.create(context, Constants.A11Y_COUNT); A11Y_DOCUMENT = URI.create(context, Constants.A11Y_DOCUMENT); A11Y_PARAGRAPH = URI.create(context, Constants.A11Y_PARAGRAPH); A11Y_SPAN = URI.create(context, Constants.A11Y_SPAN); A11Y_TABLE = URI.create(context, Constants.A11Y_TABLE); A11Y_OBJECT = URI.create(context, Constants.A11Y_OBJECT); } catch (IllegalArgumentException e) { } } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/UnoAwtUtils.java000066400000000000000000000204121225501747700313050ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.awt.MessageBoxButtons; import com.sun.star.awt.Rectangle; import com.sun.star.awt.XMessageBox; import com.sun.star.awt.XMessageBoxFactory; import com.sun.star.awt.XWindowPeer; import com.sun.star.beans.XPropertySet; import com.sun.star.lang.XComponent; import com.sun.star.lang.XInitialization; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.ui.dialogs.XExecutableDialog; import com.sun.star.ui.dialogs.XFilePicker; import com.sun.star.ui.dialogs.XFilterManager; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; /** * This class was taken from com.versusoft.packages.ooo * * @author Vincent Spiewak */ public class UnoAwtUtils { public static String showSaveAsDialog(String filename, String filterName, String filterPattern, XComponentContext m_xContext) { String sStorePath = ""; XComponent xComponent = null; XMultiComponentFactory m_xMCF = m_xContext.getServiceManager(); try { // the filepicker is instantiated with the global Multicomponentfactory... Object oFilePicker = m_xMCF.createInstanceWithContext("com.sun.star.ui.dialogs.FilePicker", m_xContext); XFilePicker xFilePicker = (XFilePicker) UnoRuntime.queryInterface(XFilePicker.class, oFilePicker); // choose the template that defines the capabilities of the filepicker dialog XInitialization xInitialize = (XInitialization) UnoRuntime.queryInterface(XInitialization.class, xFilePicker); Short[] listAny = new Short[]{new Short(com.sun.star.ui.dialogs.TemplateDescription.FILESAVE_AUTOEXTENSION)}; xInitialize.initialize(listAny); // add a control to the dialog to add the extension automatically to the filename... // CRASH ON OOo Beta 3 MACOSX //XFilePickerControlAccess xFilePickerControlAccess = (XFilePickerControlAccess) UnoRuntime.queryInterface(XFilePickerControlAccess.class, xFilePicker); //xFilePickerControlAccess.setValue(com.sun.star.ui.dialogs.ExtendedFilePickerElementIds.CHECKBOX_AUTOEXTENSION, (short) 0, new Boolean(true)); xComponent = (XComponent) UnoRuntime.queryInterface(XComponent.class, xFilePicker); // execute the dialog... XExecutableDialog xExecutable = (XExecutableDialog) UnoRuntime.queryInterface(XExecutableDialog.class, xFilePicker); // set the filters of the dialog. The filternames may be retrieved from // http://wiki.services.openoffice.org/wiki/Framework/Article/Filter XFilterManager xFilterManager = (XFilterManager) UnoRuntime.queryInterface(XFilterManager.class, xFilePicker); xFilterManager.appendFilter(filterName, filterPattern); // set the initial displaydirectory. Object oPathSettings = m_xMCF.createInstanceWithContext("com.sun.star.util.PathSettings", m_xContext); XPropertySet xPropertySet = (XPropertySet) com.sun.star.uno.UnoRuntime.queryInterface(XPropertySet.class, oPathSettings); String sTemplateUrl = (String) xPropertySet.getPropertyValue("Work_writable"); xFilePicker.setDisplayDirectory(sTemplateUrl); //set the initial filename xFilePicker.setDefaultName(filename); short nResult = xExecutable.execute(); // query the resulting path of the dialog... if (nResult == com.sun.star.ui.dialogs.ExecutableDialogResults.OK) { String[] sPathList = xFilePicker.getFiles(); if (sPathList.length > 0) { sStorePath = sPathList[0]; } } } catch (com.sun.star.uno.Exception exception) { exception.printStackTrace(); } finally { //make sure always to dispose the component and free the memory! if (xComponent != null) { xComponent.dispose(); } } return sStorePath; } public static short showMessageBox(XWindowPeer parentWindowPeer, String messageBoxType, int messageBoxButtons, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxType == null || messageBoxTitle == null || message == null) { return 0; } // Initialize the message box factory XMessageBoxFactory messageBoxFactory = (XMessageBoxFactory) UnoRuntime.queryInterface(XMessageBoxFactory.class, parentWindowPeer.getToolkit()); Rectangle messageBoxRectangle = new Rectangle(); XMessageBox box = messageBoxFactory.createMessageBox(parentWindowPeer, messageBoxRectangle, messageBoxType, messageBoxButtons, messageBoxTitle, message); return box.execute(); } public static short showInfoMessageBox(XWindowPeer parentWindowPeer, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxTitle == null || message == null) { return 0; } return showMessageBox(parentWindowPeer, "infobox", MessageBoxButtons.BUTTONS_OK, messageBoxTitle, message); } public static short showErrorMessageBox(XWindowPeer parentWindowPeer, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxTitle == null || message == null) { return 0; } return showMessageBox(parentWindowPeer, "errorbox", MessageBoxButtons.BUTTONS_OK, messageBoxTitle, message); } public static short showYesNoWarningMessageBox(XWindowPeer parentWindowPeer, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxTitle == null || message == null) { return 0; } return showMessageBox(parentWindowPeer, "warningbox", MessageBoxButtons.BUTTONS_YES_NO + MessageBoxButtons.DEFAULT_BUTTON_NO, messageBoxTitle, message); } public static short showOkCancelWarningMessageBox(XWindowPeer parentWindowPeer, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxTitle == null || message == null) { return 0; } return showMessageBox(parentWindowPeer, "warningbox", MessageBoxButtons.BUTTONS_OK_CANCEL + MessageBoxButtons.DEFAULT_BUTTON_OK, messageBoxTitle, message); } public static short showQuestionMessageBox(XWindowPeer parentWindowPeer, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxTitle == null || message == null) { return 0; } return showMessageBox(parentWindowPeer, "querybox", MessageBoxButtons.BUTTONS_YES_NO_CANCEL + MessageBoxButtons.DEFAULT_BUTTON_YES, messageBoxTitle, message); } public static short showAbortRetryIgnoreErrorMessageBox(XWindowPeer parentWindowPeer, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxTitle == null || message == null) { return 0; } return showMessageBox(parentWindowPeer, "errorbox", MessageBoxButtons.BUTTONS_ABORT_IGNORE_RETRY + MessageBoxButtons.DEFAULT_BUTTON_RETRY, messageBoxTitle, message); } public static short showRetryCancelErrorMessageBox(XWindowPeer parentWindowPeer, String messageBoxTitle, String message) { if (parentWindowPeer == null || messageBoxTitle == null || message == null) { return 0; } return showMessageBox(parentWindowPeer, "errorbox", MessageBoxButtons.BUTTONS_RETRY_CANCEL + MessageBoxButtons.DEFAULT_BUTTON_CANCEL, messageBoxTitle, message); } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/UnoGUI.java000066400000000000000000000022131225501747700301540ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.uno.XComponentContext; import com.sun.star.frame.XFrame; /** * * @author Bert Frees */ public class UnoGUI { public UnoGUI(XComponentContext m_xContext, XFrame m_xFrame) {} public void showAccessibilityDialog() {} public void clean() {} } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/UnoUtils.java000066400000000000000000000123041225501747700306320ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo; import com.sun.star.beans.PropertyValue; import com.sun.star.container.XNameAccess; import com.sun.star.frame.XFrame; import com.sun.star.frame.XStorable; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.XInterface; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.util.Locale; /** * This class was taken from com.versusoft.packages.ooo * * @author Vincent Spiewak * minor changes by Bert Frees */ public class UnoUtils { public static void storeToURL(String fileURL, String filter, XFrame xFrame) throws com.sun.star.io.IOException { PropertyValue[] conversionProperties = new PropertyValue[1]; conversionProperties[0] = new PropertyValue(); conversionProperties[0].Name = "FilterName"; conversionProperties[0].Value = filter; XStorable storable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xFrame.getController().getModel()); storable.storeToURL(fileURL, conversionProperties); } public static String UnoURLtoURL(String unoURL, XComponentContext xContext) { try { if (System.getProperty("os.name").contains("Windows")) { unoURL = unoURL.substring(6); } else { if (unoURL.startsWith("file://localhost")) { unoURL = unoURL.replaceFirst("file://localhost", ""); } else { unoURL = unoURL.substring(7); } } return URLDecoder.decode(unoURL, "UTF-8"); } catch (UnsupportedEncodingException uee) { return null; } } public static String createUnoFileURL(String filelocation, XComponentContext xContext) throws MalformedURLException { java.net.URL before; if (System.getProperty("os.name").contains("Windows")) { before = new URL("file:/" + filelocation); } else { before = new URL("file://" + filelocation); } // Create a URL, which can be used by UNO String myUNOFileURL = com.sun.star.uri.ExternalUriReferenceTranslator.create(xContext).translateToInternal(before.toExternalForm()); if (myUNOFileURL.length() == 0 && filelocation.length() > 0) { throw new MalformedURLException(); } return myUNOFileURL; } public static String createUnoTmpFile(String prefix, String suffix, XComponentContext xContext) throws java.io.IOException { String tmpUrl = File.createTempFile( prefix, suffix).getAbsolutePath(); System.out.println("Tmp File=" + tmpUrl); tmpUrl = UnoUtils.createUnoFileURL(tmpUrl, xContext); System.out.println("Uno Tmp File=" + tmpUrl); return tmpUrl; } public static Locale getUILocale(XComponentContext xContext) throws com.sun.star.uno.Exception { XMultiComponentFactory serviceManager = xContext.getServiceManager(); // create the provider String sProviderService = "com.sun.star.configuration.ConfigurationProvider"; XMultiServiceFactory xProvider = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, serviceManager.createInstanceWithContext(sProviderService, xContext)); String sReadOnlyView = "com.sun.star.configuration.ConfigurationUpdateAccess"; PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue(); aPathArgument.Name = "nodepath"; aPathArgument.Value = "org.openoffice.Setup/L10N"; Object[] aArguments = new Object[1]; aArguments[0] = aPathArgument; XInterface xViewRoot = (XInterface) xProvider.createInstanceWithArguments(sReadOnlyView, aArguments); XNameAccess xProperties = (XNameAccess) UnoRuntime.queryInterface(XNameAccess.class, xViewRoot); String ooLocale = (String) xProperties.getByName("ooLocale"); if (ooLocale.contains("-")) { int hyphenIndex = ooLocale.indexOf("-"); return new Locale(ooLocale.substring(0,hyphenIndex), ooLocale.substring(hyphenIndex+1)); } else { return new Locale(ooLocale); } } }accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/optionspage/000077500000000000000000000000001225501747700305355ustar00rootroot00000000000000DialogEventHandler.java000066400000000000000000000304441225501747700350250ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/optionspage/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.optionspage; import com.sun.star.awt.ItemEvent; import com.sun.star.lang.EventObject; import com.sun.star.lib.uno.helper.Factory; import com.sun.star.lib.uno.helper.WeakBase; import com.sun.star.lang.XSingleComponentFactory; import com.sun.star.lang.XServiceInfo; import com.sun.star.lang.WrappedTargetException; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.AnyConverter; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.Exception; import com.sun.star.registry.XRegistryKey; import com.sun.star.awt.XContainerWindowEventHandler; import com.sun.star.awt.XControl; import com.sun.star.awt.XControlModel; import com.sun.star.awt.XControlContainer; import com.sun.star.awt.XCheckBox; import com.sun.star.awt.XItemListener; import com.sun.star.beans.XPropertySet; import be.docarch.accessodf.ooo.Settings; /** * A handler which supports an options page which with different controls. * Can be easily adapted to support multiple options pages. * @author OpenOffice.org */ public class DialogEventHandler { public static class _DialogEventHandler extends WeakBase implements XServiceInfo, XContainerWindowEventHandler,XItemListener { /** * Names of supported options pages. The name derives from the * actual file names of the .xdl files not a XML attribute. */ public static String[] SupportedWindowNames = {"OptionsPage"}; /** * Names of the controls which are supported by this handler. All these * controls must have a "Text" property. */ public static String[] ControlNames = {"CheckBox1", "CheckBox2"}; static private final String __serviceName = "be.docarch.accessodf.ooo.optionspage.DialogEventHandler"; private XComponentContext context; private Settings settings; private XCheckBox brailleCheckBox = null; private XPropertySet brailleCheckBoxProperties = null; private XCheckBox daisyCheckBox = null; private XPropertySet daisyCheckBoxProperties = null; public _DialogEventHandler(XComponentContext xCompContext) { this.context = xCompContext; } /** * This method returns an array of all supported service names. * @return Array of supported service names. */ public String[] getSupportedServiceNames() { return getServiceNames(); } /** * This method is a simple helper function to used in the * static component initialisation functions as well as in * getSupportedServiceNames. */ public static String[] getServiceNames() { String[] sSupportedServiceNames = { __serviceName }; return sSupportedServiceNames; } /** This method returns true, if the given service will be * supported by the component. * @param sServiceName Service name. * @return True, if the given service name will be supported. */ public boolean supportsService( String sServiceName ) { return sServiceName.equals( __serviceName ); } /** * Return the class name of the component. * @return Class name of the component. */ public String getImplementationName() { return _DialogEventHandler.class.getName(); } /** * Is called by the OOo event system. * @param aWindow * @param aEventObject * @param sMethod * @return * @throws com.sun.star.lang.WrappedTargetException */ public boolean callHandlerMethod(com.sun.star.awt.XWindow aWindow, Object aEventObject, String sMethod) throws WrappedTargetException { if (sMethod.equals("external_event") ) { try { return handleExternalEvent(aWindow, aEventObject); } catch (com.sun.star.uno.RuntimeException re) { throw re; } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); throw new WrappedTargetException(sMethod, this, e); } } return false; } /** * @return A String array containing the method names supported by this handler. */ public String[] getSupportedMethodNames() { return new String[] {"external_event"}; } private boolean handleExternalEvent(com.sun.star.awt.XWindow aWindow, Object aEventObject) throws com.sun.star.uno.Exception { try { String sMethod = AnyConverter.toString(aEventObject); if (sMethod.equals("ok")) { saveData(aWindow); } else if (sMethod.equals("back")) { loadData(aWindow); } else if (sMethod.equals("initialize")) { init(aWindow); loadData(aWindow); } } catch (com.sun.star.lang.IllegalArgumentException ex) { ex.printStackTrace(); throw new com.sun.star.lang.IllegalArgumentException( "Method external_event requires a string in the event object argument.", this, (short) -1); } return true; } private void init(com.sun.star.awt.XWindow aWindow) throws com.sun.star.uno.Exception { String sWindowName = getWindowName(aWindow); if (sWindowName == null) { throw new com.sun.star.lang.IllegalArgumentException( "This window is not supported by this handler", this, (short) -1); } if (sWindowName.equals("OptionsPage")) { XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( XControlContainer.class, aWindow); if (xContainer == null) { throw new com.sun.star.uno.Exception( "Could not get XControlContainer from window.", this); } this.settings = new Settings(context); daisyCheckBox = (XCheckBox)UnoRuntime.queryInterface(XCheckBox.class, xContainer.getControl("CheckBox1")); brailleCheckBox = (XCheckBox)UnoRuntime.queryInterface(XCheckBox.class, xContainer.getControl("CheckBox2")); daisyCheckBoxProperties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xContainer.getControl("CheckBox1").getModel()); brailleCheckBoxProperties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xContainer.getControl("CheckBox2").getModel()); } } public void itemStateChanged(ItemEvent event) { } public void disposing(EventObject arg0) { } /** * Saves data from the dialog into the configuration. * @param aWindow * @throws com.sun.star.lang.IllegalArgumentException * @throws com.sun.star.uno.Exception */ private void saveData(com.sun.star.awt.XWindow aWindow) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception { String sWindowName = getWindowName(aWindow); if (sWindowName == null) { throw new com.sun.star.lang.IllegalArgumentException( "This window is not supported by this handler", this, (short) -1); } if (sWindowName.equals("OptionsPage")) { settings.daisyChecks(daisyCheckBox.getState()==(short)1); settings.brailleChecks(brailleCheckBox.getState()==(short)1); settings.saveData(); } } /** * Loads data from the configuration into the dialog. * @param aWindow * @throws com.sun.star.uno.Exception */ private void loadData(com.sun.star.awt.XWindow aWindow) throws com.sun.star.uno.Exception { String sWindowName = getWindowName(aWindow); if (sWindowName == null) { throw new com.sun.star.lang.IllegalArgumentException( "This window is not supported by this handler", this, (short) -1); } if (sWindowName.equals("OptionsPage")) { settings.loadData(); daisyCheckBoxProperties.setPropertyValue("Enabled", settings.daisyChecksAvailable()); brailleCheckBoxProperties.setPropertyValue("Enabled", settings.brailleChecksAvailable()); daisyCheckBox.setState((short)(settings.daisyChecks()?1:0)); brailleCheckBox.setState((short)(settings.brailleChecks()?1:0)); } } // Checks if the name property of the window is one of the supported names and returns // always a valid string or null private String getWindowName(com.sun.star.awt.XWindow aWindow) throws com.sun.star.uno.Exception { if (aWindow == null) new com.sun.star.lang.IllegalArgumentException( "Method external_event requires that a window is passed as argument", this, (short) -1); XControl xControlDlg = (XControl) UnoRuntime.queryInterface( XControl.class, aWindow); if (xControlDlg == null) throw new com.sun.star.uno.Exception( "Cannot obtain XControl from XWindow in method external_event."); XControlModel xModelDlg = xControlDlg.getModel(); if (xModelDlg == null) throw new com.sun.star.uno.Exception( "Cannot obtain XControlModel from XWindow in method external_event.", this); XPropertySet xPropDlg = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xModelDlg); if (xPropDlg == null) throw new com.sun.star.uno.Exception( "Cannot obtain XPropertySet from window in method external_event.", this); Object aWindowName = xPropDlg.getPropertyValue("Name"); String sName = null; try { sName = AnyConverter.toString(aWindowName); } catch (com.sun.star.lang.IllegalArgumentException ex) { ex.printStackTrace(); throw new com.sun.star.uno.Exception( "Name - property of window is not a string.", this); } for (int i = 0; i < SupportedWindowNames.length; i++) { if (SupportedWindowNames[i].equals(sName)) { return sName; } } return null; } } /** * Gives a factory for creating the service. * This method is called by the CentralRegistrationClass. * @return returns a XSingleComponentFactory for creating * the component * @param sImplName the name of the implementation for which a * service is desired * @see com.sun.star.comp.loader.JavaLoader */ public static XSingleComponentFactory __getComponentFactory(String sImplName) { XSingleComponentFactory xFactory = null; if ( sImplName.equals( _DialogEventHandler.class.getName() ) ) xFactory = Factory.createComponentFactory(_DialogEventHandler.class, _DialogEventHandler.getServiceNames()); return xFactory; } /** * Writes the service information into the given registry key. * This method is called by the CentralRegistrationClass. * @return returns true if the operation succeeded * @param regKey the registryKey * @see com.sun.star.comp.loader.JavaLoader */ public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { return Factory.writeRegistryServiceInfo(_DialogEventHandler.class.getName(), _DialogEventHandler.getServiceNames(), regKey); } /** * This method is a member of the interface for initializing an object * directly after its creation. * @param object This array of arbitrary objects will be passed to the * component after its creation. * @throws Exception Every exception will not be handled, but will be * passed to the caller. */ public void initialize( Object[] object ) throws com.sun.star.uno.Exception {} }accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/rdf/000077500000000000000000000000001225501747700267605ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/rdf/Assertions.java000066400000000000000000000236621225501747700317660ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.rdf; import java.text.SimpleDateFormat; import java.text.DateFormat; import java.util.Date; import com.sun.star.container.XEnumeration; import com.sun.star.rdf.Statement; import com.sun.star.rdf.XURI; import com.sun.star.rdf.URI; import com.sun.star.rdf.BlankNode; import com.sun.star.rdf.XResource; import com.sun.star.rdf.XNamedGraph; import com.sun.star.rdf.Literal; import be.docarch.accessodf.Check; import be.docarch.accessodf.Provider; import be.docarch.accessodf.Issue; import be.docarch.accessodf.IssueEvent; import be.docarch.accessodf.IssueListener; import be.docarch.accessodf.Element; import be.docarch.accessodf.Checker; import be.docarch.accessodf.ooo.URIs; import be.docarch.accessodf.ooo.Document; /** * * @author Bert Frees */ public class Assertions { private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); private final XNamedGraph graph; private final Document doc; private final Assertors assertors; private final TestSubjects testSubjects; private final TestCases testCases; public Assertions(XNamedGraph graph, Document doc) { this.graph = graph; this.doc = doc; assertors = new Assertors(graph, doc); testSubjects = new TestSubjects(graph, doc); testCases = new TestCases(graph, doc); } public Assertion create(Issue issue) { return new Assertion(issue); } public Assertion read(XResource assertion, Provider checkers) throws Exception { XResource testresult = null; Checker checker = null; Check check = null; Element element = null; Date checkDate = null; int count = 1; try { if (!graph.getStatements(assertion, URIs.RDF_TYPE, URIs.EARL_ASSERTION).hasMoreElements()) { throw new Exception("Not of type earl:Assertion"); } XEnumeration assertorEnum = graph.getStatements(assertion, URIs.EARL_ASSERTEDBY, null); XEnumeration testSubjectEnum = graph.getStatements(assertion, URIs.EARL_SUBJECT, null); XEnumeration testCaseEnum = graph.getStatements(assertion, URIs.EARL_TEST, null); XEnumeration testResultEnum = graph.getStatements(assertion, URIs.EARL_RESULT, null); if (!assertorEnum.hasMoreElements()) { throw new Exception("No earl:assertedBy statement"); } if (!testSubjectEnum.hasMoreElements()) { throw new Exception("No earl:subject statement"); } if (!testCaseEnum.hasMoreElements()) { throw new Exception("No earl:test statement"); } if (!testResultEnum.hasMoreElements()) { throw new Exception("No earl:result statement"); } XURI assertor = URI.create(doc.xContext, ((Statement)assertorEnum.nextElement()).Object.getStringValue()); checker = assertors.read(assertor, checkers).getChecker(); XURI testcase = URI.create(doc.xContext, ((Statement)testCaseEnum.nextElement()).Object.getStringValue()); check = testCases.read(testcase, checker).getCheck(); XResource testsubject = BlankNode.create(doc.xContext, ((Statement)testSubjectEnum.nextElement()).Object.getStringValue()); element = testSubjects.read(testsubject).getElement(); testresult = BlankNode.create(doc.xContext, ((Statement)testResultEnum.nextElement()).Object.getStringValue()); if (!graph.getStatements(testresult, URIs.EARL_OUTCOME, null).hasMoreElements()) { throw new Exception("No earl:outcome statement"); } if (!graph.getStatements(testresult, URIs.RDF_TYPE, URIs.EARL_TESTRESULT).hasMoreElements()) { throw new Exception("Not of type earl:testResult"); } XEnumeration timestamps = graph.getStatements(testresult, URIs.DCT_DATE, null); if (!timestamps.hasMoreElements()) { throw new Exception("No dct:date statement"); } checkDate = dateFormat.parse(((Statement)timestamps.nextElement()).Object.getStringValue()); XEnumeration counts = graph.getStatements(testresult, URIs.A11Y_COUNT, null); if (counts.hasMoreElements()) { count = Integer.parseInt(((Statement)counts.nextElement()).Object.getStringValue()); } Issue issue = new Issue(element, check, checker, checkDate, count); XEnumeration ignore = graph.getStatements(testresult, URIs.A11Y_IGNORE, null); if (ignore.hasMoreElements()) { if (((Statement)ignore.nextElement()).Object.getStringValue().equals("true")) { issue.ignored(true); } } if (graph.getStatements(testresult, URIs.EARL_OUTCOME, URIs.EARL_PASSED).hasMoreElements()) { issue.repaired(true); } return new Assertion(issue, assertion, testresult); } catch (Exception e) { String message = "Invalid assertion" + "\n[Checker: " + ((checker==null) ? "?" : checker.getIdentifier()) + "]" + "\n[Check: " + ((check==null) ? "?" : check.getIdentifier()) + "]" + "\n[Element: " + ((element==null) ? "?" : element.toString()) + "]" + "\n" + e.toString(); try { graph.removeStatements(assertion, null, null); if (testresult != null) { graph.removeStatements(testresult, null, null); } message += "\nAssertion removed from report."; } catch (Exception ee) { message += "\nCould not remove assertion from report."; } Exception newException = new Exception(message); newException.setStackTrace(e.getStackTrace()); throw newException; } } public class Assertion implements IssueListener { private final Issue issue; private XResource assertion; private XResource testresult; private Assertion(Issue issue) { this.issue = issue; issue.addListener(this); } private Assertion(Issue issue, XResource assertion, XResource testresult) { this(issue); this.assertion = assertion; this.testresult = testresult; } public Issue getIssue() { return issue; } public XResource write() throws Exception { if (assertion == null) { assertion = doc.xRepository.createBlankNode(); testresult = doc.xRepository.createBlankNode(); XURI testcase = testCases.create(issue.getCheck()).write(); XURI assertor = assertors.create(issue.getChecker()).write(); XResource subject = testSubjects.create(issue.getElement()).write(); graph.addStatement(testresult, URIs.RDF_TYPE, URIs.EARL_TESTRESULT); graph.addStatement(testresult, URIs.EARL_OUTCOME, URIs.EARL_FAILED); graph.addStatement(testresult, URIs.DCT_DATE, Literal.create(doc.xContext, dateFormat.format(issue.getCheckDate()))); graph.addStatement(assertion, URIs.RDF_TYPE, URIs.EARL_ASSERTION); graph.addStatement(assertion, URIs.EARL_RESULT, testresult); graph.addStatement(assertion, URIs.EARL_TEST, testcase); graph.addStatement(assertion, URIs.EARL_SUBJECT, subject); graph.addStatement(assertion, URIs.EARL_ASSERTEDBY, assertor); if (issue.getCount()>1) { graph.addStatement(testresult, URIs.A11Y_COUNT, Literal.create(doc.xContext, String.valueOf(issue.getCount()))); } } return assertion; } public void issueUpdated(IssueEvent event) { if (event.getSource() != issue) { return; } try { if (assertion == null) { write(); } switch (event.type) { case IGNORE: graph.removeStatements(testresult, URIs.A11Y_IGNORE, null); if (issue.ignored()) { graph.addStatement(testresult, URIs.A11Y_IGNORE, Literal.create(doc.xContext, "true")); } doc.setModified(); break; case REPAIR: graph.removeStatements(testresult, URIs.EARL_OUTCOME, null); if (issue.repaired()) { graph.addStatement(testresult, URIs.EARL_OUTCOME, URIs.EARL_PASSED); } else { graph.addStatement(testresult, URIs.EARL_OUTCOME, URIs.EARL_FAILED); } doc.setModified(); break; case REMOVE: graph.removeStatements(assertion, null, null); doc.setModified(); break; } } catch (Exception e) { e.printStackTrace(); } } } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/rdf/Assertors.java000066400000000000000000000072261225501747700316170ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.rdf; import java.util.Map; import java.util.HashMap; import java.util.TreeMap; import com.sun.star.rdf.XURI; import com.sun.star.rdf.URI; import com.sun.star.rdf.XNamedGraph; import be.docarch.accessodf.Checker; import be.docarch.accessodf.Provider; import be.docarch.accessodf.ooo.URIs; import be.docarch.accessodf.ooo.Document; /** * * @author Bert Frees */ public class Assertors { private final XNamedGraph graph; private final Document doc; private Map xURIMap = new TreeMap(); private Map checkerMap = new HashMap(); public Assertors(XNamedGraph graph, Document doc) { this.graph = graph; this.doc = doc; } public Assertor create(Checker checker) { Assertor a = checkerMap.get(checker); if (a == null) { a = new Assertor(checker); checkerMap.put(checker, a); } return a; } public Assertor read(XURI assertor, Provider checkers) throws Exception { Assertor a = xURIMap.get(assertor.getStringValue()); if (a == null) { if (!graph.getStatements(assertor, URIs.RDF_TYPE, URIs.EARL_ASSERTOR).hasMoreElements()) { throw new Exception("Not of type earl:Assertor"); } if (!graph.getStatements(assertor, URIs.RDF_TYPE, URIs.A11Y_CHECKER).hasMoreElements()) { throw new Exception("Not of type Checker"); } Checker checker = checkers.get(assertor.getStringValue()); if (checker == null) { throw new Exception("Checker ID not found"); } a = new Assertor(checker, assertor); } xURIMap.put(assertor.getStringValue(), a); return a; } public class Assertor { private final Checker checker; private XURI assertor; private Assertor(Checker checker) { this.checker = checker; } private Assertor(Checker checker, XURI assertor) { this(checker); this.assertor = assertor; } public Checker getChecker() { return checker; } public XURI write() throws Exception { if (assertor == null) { assertor = URI.create(doc.xContext, checker.getIdentifier()); graph.addStatement(assertor, URIs.RDF_TYPE, URIs.EARL_ASSERTOR); //graph.addStatement(URIs.A11Y_CHECKER, URIs.RDFS_SUBCLASSOF, URIs.EARL_ASSERTOR); // in plaats van vorige ? graph.addStatement(assertor, URIs.RDF_TYPE, URIs.A11Y_CHECKER); //graph.addStatement(assertor, URIs.DCT_DATE, Literal.create(xContext, dateFormat.format(lastChecked))); // terug invoeren ! } return assertor; } } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/rdf/TestCases.java000066400000000000000000000065001225501747700315220ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.rdf; import java.util.Map; import java.util.TreeMap; import java.util.HashMap; import com.sun.star.rdf.XURI; import com.sun.star.rdf.URI; import com.sun.star.rdf.XNamedGraph; import be.docarch.accessodf.Check; import be.docarch.accessodf.Constants; import be.docarch.accessodf.Provider; import be.docarch.accessodf.ooo.URIs; import be.docarch.accessodf.ooo.Document; /** * * @author Bert Frees */ public class TestCases { private final XNamedGraph graph; private final Document doc; private Map xURIMap = new TreeMap(); private Map checkMap = new HashMap(); public TestCases(XNamedGraph graph, Document doc) { this.graph = graph; this.doc = doc; } public TestCase create(Check check) { TestCase tc = checkMap.get(check); if (tc == null) { tc = new TestCase(check); checkMap.put(check, tc); } return tc; } public TestCase read(XURI testcase, Provider checks) throws Exception { TestCase tc = xURIMap.get(testcase.getStringValue()); if (tc == null) { if (!graph.getStatements(testcase, URIs.RDF_TYPE, URIs.EARL_TESTCASE).hasMoreElements()) { throw new Exception("Not of type earl:TestCase"); } if (!testcase.getNamespace().equals(Constants.A11Y_CHECKS)) { throw new Exception("Invalid namespace for check"); } Check check = checks.get(testcase.getLocalName()); if (check == null) { throw new Exception("Check ID not found"); } tc = new TestCase(check, testcase); } xURIMap.put(testcase.getStringValue(), tc); return tc; } public class TestCase { private final Check check; private XURI testcase; private TestCase(Check check) { this.check = check; } private TestCase(Check check, XURI testcase) { this(check); this.testcase = testcase; } public Check getCheck() { return check; } public XURI write() throws Exception { if (testcase == null) { testcase = URI.createNS(doc.xContext, Constants.A11Y_CHECKS, check.getIdentifier()); graph.addStatement(testcase, URIs.RDF_TYPE, URIs.EARL_TESTCASE); } return testcase; } } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/rdf/TestSubjects.java000066400000000000000000000237101225501747700322500ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.rdf; import java.util.Map; import java.util.TreeMap; import java.util.HashMap; import com.sun.star.container.XEnumeration; import com.sun.star.rdf.Statement; import com.sun.star.rdf.XMetadatable; import com.sun.star.rdf.XURI; import com.sun.star.rdf.URI; import com.sun.star.rdf.XNamedGraph; import com.sun.star.rdf.XResource; import com.sun.star.rdf.Literal; import be.docarch.accessodf.Constants; import be.docarch.accessodf.ooo.URIs; import be.docarch.accessodf.ooo.Paragraph; import be.docarch.accessodf.ooo.Span; import be.docarch.accessodf.ooo.Table; import be.docarch.accessodf.ooo.DrawObject; import be.docarch.accessodf.ooo.Document; import be.docarch.accessodf.Element; /** * * @author Bert Frees */ public class TestSubjects { private static enum Type { PARAGRAPH, SPAN, TABLE, OBJECT, DOCUMENT }; private final XNamedGraph graph; private final Document doc; private Map xResourceMap = new TreeMap(); private Map elementMap = new HashMap(); private TestSubject documentSubject; public TestSubjects(XNamedGraph graph, Document doc) { this.graph = graph; this.doc = doc; } public TestSubject create(Element element) throws Exception { TestSubject ts = (element==null) ? documentSubject : elementMap.get(element); if (ts == null) { ts = new TestSubject(element); if (element==null) { documentSubject = ts; } else { elementMap.put(element, ts); } } return ts; } public TestSubject read(XResource subject) throws Exception { TestSubject ts = xResourceMap.get(subject.getStringValue()); if (ts == null) { if (!graph.getStatements(subject, URIs.RDF_TYPE, URIs.EARL_TESTSUBJECT).hasMoreElements()) { throw new Exception("Not of type earl:TestSubject"); } XEnumeration types = graph.getStatements(subject, URIs.RDF_TYPE, null); if (!types.hasMoreElements()) { throw new Exception("No rdf:type statement"); } String t = ((Statement)types.nextElement()).Object.getStringValue(); if (t.equals(Constants.A11Y_DOCUMENT)) { ts = new TestSubject(null, subject); } else if (t.equals(Constants.A11Y_PARAGRAPH)) { ts = new TestSubject(readParagraph(subject), subject); } else if (t.equals(Constants.A11Y_SPAN)) { ts = new TestSubject(readSpan(subject), subject); } else if (t.equals(Constants.A11Y_TABLE)) { ts = new TestSubject(readTable(subject), subject); } else if (t.equals(Constants.A11Y_OBJECT)) { ts = new TestSubject(readDrawObject(subject), subject); } else { throw new Exception("Invalid type of TestSubject"); } } xResourceMap.put(subject.getStringValue(), ts); return ts; } private Paragraph readParagraph(XResource subject) throws Exception { XEnumeration paragraphs = graph.getStatements(subject, URIs.A11Y_START, null); if (!paragraphs.hasMoreElements()) { throw new Exception("No start statement"); } XURI paragraph = URI.create(doc.xContext, ((Statement)paragraphs.nextElement()).Object.getStringValue()); XMetadatable metadatable = doc.xDMA.getElementByURI(paragraph); if (metadatable == null) { throw new Exception("Cannot find paragraph"); } return new Paragraph(metadatable, doc); } private Span readSpan(XResource subject) throws Exception { XEnumeration starts = graph.getStatements(subject, URIs.A11Y_START, null); XEnumeration ends = graph.getStatements(subject, URIs.A11Y_END, null); if (!starts.hasMoreElements() || !ends.hasMoreElements()) { throw new Exception("No start or end statement"); } XURI start = URI.create(doc.xContext, ((Statement)starts.nextElement()).Object.getStringValue()); XURI end = URI.create(doc.xContext, ((Statement)ends.nextElement()).Object.getStringValue()); XMetadatable startElement = doc.xDMA.getElementByURI(start); XMetadatable endElement = doc.xDMA.getElementByURI(end); if (startElement == null || endElement == null) { throw new Exception("Cannot find span"); } return new Span(startElement, endElement, doc); } private Table readTable(XResource subject) throws Exception { XEnumeration names = graph.getStatements(subject, URIs.DCT_TITLE, null); if (!names.hasMoreElements()) { throw new Exception("No dct:title statement"); } return new Table(((Statement)names.nextElement()).Object.getStringValue(), doc); } private DrawObject readDrawObject(XResource subject) throws Exception { XEnumeration names = graph.getStatements(subject, URIs.DCT_TITLE, null); if (!names.hasMoreElements()) { throw new Exception("No dct:title statement"); } return new DrawObject(((Statement)names.nextElement()).Object.getStringValue(), doc); } public class TestSubject { private final Element element; private final Type type; private XResource testsubject; private TestSubject(Element element) throws Exception { this.element = element; if (element == null) { type = Type.DOCUMENT; } else if (element instanceof Paragraph) { type = Type.PARAGRAPH; } else if (element instanceof Span) { type = Type.SPAN; } else if (element instanceof Table) { type = Type.TABLE; } else if (element instanceof DrawObject) { type = Type.OBJECT; } else { throw new Exception("Invalid element"); } } private TestSubject(Element element, XResource testsubject) throws Exception { this(element); this.testsubject = testsubject; } public Element getElement() { return element; } public XResource write() throws Exception { if (testsubject == null) { switch (type) { case DOCUMENT: writeDocument(); break; case PARAGRAPH: writeParagraph((Paragraph)element); break; case SPAN: writeSpan((Span)element); break; case TABLE: writeTable((Table)element); break; case OBJECT: writeDrawObject((DrawObject)element); break; } } return testsubject; } private void writeDocument() throws Exception { testsubject = doc.xRepository.createBlankNode(); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.EARL_TESTSUBJECT); //graph.addStatement(URIs.A11Y_DOCUMENT, URIs.RDFS_SUBCLASSOF, URIs.EARL_TESTSUBJECT); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.A11Y_DOCUMENT); } private void writeParagraph(Paragraph paragraph) throws Exception { testsubject = doc.xRepository.createBlankNode(); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.EARL_TESTSUBJECT); //graph.addStatement(URIs.A11Y_PARAGRAPH, URIs.RDFS_SUBCLASSOF, URIs.EARL_TESTSUBJECT); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.A11Y_PARAGRAPH); graph.addStatement(testsubject, URIs.A11Y_START, paragraph.getXMetadatable()); } private void writeSpan(Span span) throws Exception { testsubject = doc.xRepository.createBlankNode(); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.EARL_TESTSUBJECT); //graph.addStatement(URIs.A11Y_SPAN, URIs.RDFS_SUBCLASSOF, URIs.EARL_TESTSUBJECT); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.A11Y_SPAN); graph.addStatement(testsubject, URIs.A11Y_START, span.getStartXMetadatable()); graph.addStatement(testsubject, URIs.A11Y_END, span.getEndXMetadatable()); } private void writeTable(Table table) throws Exception { testsubject = doc.xRepository.createBlankNode(); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.EARL_TESTSUBJECT); //graph.addStatement(URIs.A11Y_TABLE, URIs.RDFS_SUBCLASSOF, URIs.EARL_TESTSUBJECT); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.A11Y_TABLE); graph.addStatement(testsubject, URIs.DCT_TITLE, Literal.create(doc.xContext, table.getXNamed().getName())); } private void writeDrawObject(DrawObject object) throws Exception { testsubject = doc.xRepository.createBlankNode(); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.EARL_TESTSUBJECT); //graph.addStatement(URIs.A11Y_OBJECT, URIs.RDFS_SUBCLASSOF, URIs.EARL_TESTSUBJECT); graph.addStatement(testsubject, URIs.RDF_TYPE, URIs.A11Y_OBJECT); graph.addStatement(testsubject, URIs.DCT_TITLE, Literal.create(doc.xContext, object.getXNamed().getName())); } } } accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/toolpanel/000077500000000000000000000000001225501747700302025ustar00rootroot00000000000000AccessibilityPanel.java000066400000000000000000001762411225501747700345500ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/toolpanel/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.toolpanel; import java.util.logging.Logger; import java.util.logging.Level; import java.util.Locale; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import java.util.SortedMap; import java.util.TreeMap; import java.util.ResourceBundle; import java.net.URLClassLoader; import java.net.URL; import java.net.URLDecoder; import java.io.File; import java.io.FileFilter; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.AnyConverter; import com.sun.star.uno.Any; import com.sun.star.uno.Type; import com.sun.star.beans.XPropertySet; import com.sun.star.beans.XMultiPropertySet; import com.sun.star.lang.EventObject; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lang.XComponent; import com.sun.star.accessibility.XAccessible; import com.sun.star.awt.XControl; import com.sun.star.awt.XControlModel; import com.sun.star.awt.XTextComponent; import com.sun.star.awt.XScrollBar; import com.sun.star.awt.ScrollBarOrientation; import com.sun.star.awt.XButton; import com.sun.star.awt.XWindow; import com.sun.star.awt.XWindowPeer; import com.sun.star.awt.Rectangle; import com.sun.star.awt.WindowClass; import com.sun.star.awt.PosSize; import com.sun.star.awt.WindowDescriptor; import com.sun.star.awt.XToolkit; import com.sun.star.awt.XItemListener; import com.sun.star.awt.ItemEvent; import com.sun.star.awt.XActionListener; import com.sun.star.awt.ActionEvent; import com.sun.star.awt.XFixedText; import com.sun.star.awt.XWindowListener; import com.sun.star.awt.WindowEvent; import com.sun.star.awt.XAdjustmentListener; import com.sun.star.awt.AdjustmentEvent; import com.sun.star.awt.tree.XTreeControl; import com.sun.star.awt.tree.XMutableTreeDataModel; import com.sun.star.awt.tree.XMutableTreeNode; import com.sun.star.ui.XToolPanel; import com.sun.star.deployment.PackageInformationProvider; import com.sun.star.deployment.XPackageInformationProvider; import com.sun.star.text.XTextViewCursor; import com.sun.star.text.XTextViewCursorSupplier; import com.sun.star.view.XSelectionSupplier; import com.sun.star.view.XSelectionChangeListener; import com.sun.star.lib.uno.helper.ComponentBase; import be.docarch.accessodf.*; import be.docarch.accessodf.ooo.*; import java.io.UnsupportedEncodingException; import com.sun.star.rdf.RepositoryException; import com.sun.star.lang.DisposedException; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.IndexOutOfBoundsException; import com.sun.star.container.ElementExistException; import com.sun.star.container.NoSuchElementException; import com.sun.star.beans.UnknownPropertyException; import com.sun.star.beans.PropertyVetoException; import com.sun.star.awt.tree.ExpandVetoException; public class AccessibilityPanel extends ComponentBase implements XToolPanel, XItemListener, XActionListener, XWindowListener, XAdjustmentListener, XSelectionChangeListener { private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); private static final boolean showRepairedIssues = false; private static final boolean showIgnoredIssues = false; private Locale oooLocale; private final String L10N_errors; private final String L10N_warnings; private final String L10N_issue; private final String L10N_description; private final String L10N_suggestions; private final String L10N_clear; private final String L10N_ignore; private final String L10N_ignoreAll; private final String L10N_repair; private final String L10N_repairAll; private final String L10N_recheck; private final String L10N_moreHelp; private final String L10N_congratulations; private final String L10N_noIssuesFound; private final Rectangle[] controlRectangles = new Rectangle[12]; private XWindow window; private XWindow mainWindow; private XWindow rightWindow; private XWindow bottomWindow; private XComponentContext xContext = null; private XWindowPeer docWindowPeer = null; private Document document = null; private IssueManager manager = null; private XButton refreshButton = null; private XButton ignoreButton = null; private XButton clearButton = null; private XButton repairButton = null; //private XButton helpButton = null; private XTextComponent nameField = null; private XTextComponent descriptionField = null; private XTextComponent suggestionField = null; private XTreeControl treeControl = null; private XScrollBar hScrollBar = null; private XScrollBar vScrollBar = null; private XWindow refreshButtonWindow = null; private XWindow ignoreButtonWindow = null; private XWindow clearButtonWindow = null; private XWindow repairButtonWindow = null; //private XWindow helpButtonWindow = null; private XWindow nameFieldWindow = null; private XWindow descriptionFieldWindow = null; private XWindow suggestionFieldWindow = null; private XWindow treeControlWindow = null; private XWindow hScrollBarWindow = null; private XWindow vScrollBarWindow = null; private XWindow nameLabelWindow = null; private XWindow statusImageWindow = null; private XWindow descriptionLabelWindow = null; private XWindow suggestionLabelWindow = null; private XPropertySet repairButtonProperties = null; private XPropertySet ignoreButtonProperties = null; //private XPropertySet helpButtonProperties = null; private XPropertySet treeControlProperties = null; private XPropertySet statusImageControlProperties = null; private String imageDir = null; private int horizontalOffset = 0; private int verticalOffset = 0; private XTextViewCursor viewCursor = null; private XSelectionSupplier selectionSupplier = null; private Issue focusedIssue = null; private XMutableTreeDataModel dataModel = null; private HashMap issue2NodeMap = null; private HashMap check2NodeMap = null; private HashMap node2IssueMap = null; private HashMap node2CheckMap = null; private HashMap child2ParentMap = null; // (XMutableTreeNode)node.getParent(); => randomly results in ClassCastException ? private boolean ignoreSelectionEvent = false; public AccessibilityPanel(XComponentContext xContext, XWindow panelAnchorWindow) { logger.entering("AccessibilityPanel", ""); try { oooLocale = UnoUtils.getUILocale(xContext); } catch (Exception e) { oooLocale = Locale.ENGLISH; } ResourceBundle bundle = ResourceBundle.getBundle("be/docarch/accessodf/ooo/toolpanel/l10n/toolpanel", oooLocale); L10N_errors = bundle.getString("errors"); L10N_warnings = bundle.getString("warnings"); L10N_issue = bundle.getString("issue"); L10N_description = bundle.getString("description"); L10N_suggestions = bundle.getString("suggestions"); L10N_clear = bundle.getString("clear"); L10N_ignore = bundle.getString("ignore"); L10N_ignoreAll = bundle.getString("ignoreAll"); L10N_repair = bundle.getString("repair"); L10N_repairAll = bundle.getString("repairAll"); L10N_recheck = bundle.getString("recheck"); L10N_moreHelp = bundle.getString("moreHelp"); L10N_congratulations = bundle.getString("congratulations"); L10N_noIssuesFound = bundle.getString("noIssuesFound"); try { this.xContext = xContext; XMultiComponentFactory xMCF = (XMultiComponentFactory) UnoRuntime.queryInterface( XMultiComponentFactory.class, xContext.getServiceManager()); XWindowPeer panelAnchorPeer = (XWindowPeer)UnoRuntime.queryInterface(XWindowPeer.class, panelAnchorWindow); docWindowPeer = panelAnchorPeer; if (panelAnchorPeer != null) { Rectangle panelAnchorSize = panelAnchorWindow.getPosSize(); XToolkit toolkit = panelAnchorPeer.getToolkit(); XWindowPeer windowPeer = createWindow(toolkit, panelAnchorPeer); window = (XWindow)UnoRuntime.queryInterface(XWindow.class, windowPeer); if (window != null) { window.setPosSize(0, 0, panelAnchorSize.Width, panelAnchorSize.Height, PosSize.POSSIZE); XWindowPeer mainWindowPeer = createWindow(toolkit, windowPeer); XWindowPeer rightWindowPeer = createWindow(toolkit, windowPeer); XWindowPeer bottomWindowPeer = createWindow(toolkit, windowPeer); mainWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, mainWindowPeer); rightWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, rightWindowPeer); bottomWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, bottomWindowPeer); if (mainWindow != null && rightWindow != null && bottomWindow != null) { for (int i=0; i< controlRectangles.length; i++) { controlRectangles[i] = new Rectangle(); } mainWindow.setVisible(true); rightWindow.setVisible(false); bottomWindow.setVisible(false); rightWindow.setPosSize(panelAnchorSize.Width, 0, 20, panelAnchorSize.Height, PosSize.POSSIZE); bottomWindow.setPosSize(0, panelAnchorSize.Height, panelAnchorSize.Width, 20, PosSize.POSSIZE); Rectangle mainRectangle = window.getPosSize(); Rectangle totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); boolean hScrollBarEnabled = totalRectangle.Width > mainRectangle.Width; boolean vScrollBarEnabled = totalRectangle.Height > mainRectangle.Height; if (hScrollBarEnabled && vScrollBarEnabled) { mainRectangle.Width = mainRectangle.Width - 20; mainRectangle.Height = mainRectangle.Height - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); } else if (hScrollBarEnabled) { mainRectangle.Height = mainRectangle.Height - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); vScrollBarEnabled = totalRectangle.Height > mainRectangle.Height; if (vScrollBarEnabled) { mainRectangle.Width = mainRectangle.Width - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); } } else if (vScrollBarEnabled) { mainRectangle.Width = mainRectangle.Width - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); hScrollBarEnabled = totalRectangle.Width > mainRectangle.Width; if (hScrollBarEnabled) { mainRectangle.Height = mainRectangle.Height - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); } } setWindowPosSize(mainWindow, mainRectangle); XControl treeControlControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.tree.TreeControl", null, null, controlRectangles[0]); XControl nameLabelControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlFixedText", null, null, controlRectangles[1]); XControl statusImageControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlImageControl", null, null, controlRectangles[2]); XControl nameFieldControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlEdit", new String[] {"VScroll"}, new Object[] {false}, controlRectangles[3]); XControl descriptionLabelControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlFixedText", null, null, controlRectangles[4]); XControl descriptionFieldControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlEdit", null, null, controlRectangles[5]); XControl suggestionLabelControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlFixedText", null, null, controlRectangles[6]); XControl suggestionFieldControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlEdit", null, null, controlRectangles[7]); XControl refreshButtonControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlButton", null, null, controlRectangles[8]); XControl clearButtonControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlButton", null, null, controlRectangles[9]); XControl repairButtonControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlButton", null, null, controlRectangles[10]); XControl ignoreButtonControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlButton", null, null, controlRectangles[11]); /* XControl helpButtonControl = createControl(xMCF, xContext, toolkit, mainWindowPeer, "com.sun.star.awt.UnoControlButton", new String[] {"PushButtonType"}, new Object[] {(short)PushButtonType.HELP_value}, controlRectangles[12]); */ XControl hScrollBarControl = createControl(xMCF, xContext, toolkit, bottomWindowPeer, "com.sun.star.awt.UnoControlScrollBar", null, null, bottomWindow.getPosSize()); XControl vScrollBarControl = createControl(xMCF, xContext, toolkit, rightWindowPeer, "com.sun.star.awt.UnoControlScrollBar", null, null, rightWindow.getPosSize()); refreshButton = (XButton)UnoRuntime.queryInterface(XButton.class, refreshButtonControl); repairButton = (XButton)UnoRuntime.queryInterface(XButton.class, repairButtonControl); ignoreButton = (XButton)UnoRuntime.queryInterface(XButton.class, ignoreButtonControl); clearButton = (XButton)UnoRuntime.queryInterface(XButton.class, clearButtonControl); //helpButton = (XButton)UnoRuntime.queryInterface(XButton.class, helpButtonControl); nameField = (XTextComponent)UnoRuntime.queryInterface(XTextComponent.class, nameFieldControl); descriptionField = (XTextComponent)UnoRuntime.queryInterface(XTextComponent.class, descriptionFieldControl); suggestionField = (XTextComponent)UnoRuntime.queryInterface(XTextComponent.class, suggestionFieldControl); treeControl = (XTreeControl)UnoRuntime.queryInterface(XTreeControl.class, treeControlControl); hScrollBar = (XScrollBar)UnoRuntime.queryInterface(XScrollBar.class, hScrollBarControl); vScrollBar = (XScrollBar)UnoRuntime.queryInterface(XScrollBar.class, vScrollBarControl); treeControlWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, treeControlControl); nameLabelWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, nameLabelControl); statusImageWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, statusImageControl); nameFieldWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, nameFieldControl); descriptionLabelWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, descriptionLabelControl); descriptionFieldWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, descriptionFieldControl); suggestionLabelWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, suggestionLabelControl); suggestionFieldWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, suggestionFieldControl); clearButtonWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, clearButtonControl); refreshButtonWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, refreshButtonControl); ignoreButtonWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, ignoreButtonControl); repairButtonWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, repairButtonControl); //helpButtonWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, helpButtonControl); hScrollBarWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, hScrollBarControl); vScrollBarWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, vScrollBarControl); repairButtonProperties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, repairButtonControl.getModel()); ignoreButtonProperties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, ignoreButtonControl.getModel()); //helpButtonProperties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, helpButtonControl.getModel()); treeControlProperties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, treeControlControl.getModel()); statusImageControlProperties = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, statusImageControl.getModel()); XFixedText nameLabel = (XFixedText)UnoRuntime.queryInterface(XFixedText.class, nameLabelControl); XFixedText descriptionLabel = (XFixedText)UnoRuntime.queryInterface(XFixedText.class, descriptionLabelControl); XFixedText suggestionLabel = (XFixedText)UnoRuntime.queryInterface(XFixedText.class, suggestionLabelControl); hScrollBar.setLineIncrement(10); hScrollBar.setBlockIncrement(50); hScrollBar.setOrientation(ScrollBarOrientation.HORIZONTAL); vScrollBar.setLineIncrement(10); vScrollBar.setBlockIncrement(50); vScrollBar.setOrientation(ScrollBarOrientation.VERTICAL); updateScrollBars(hScrollBarEnabled, vScrollBarEnabled, mainRectangle.Width, mainRectangle.Height, totalRectangle.Width, totalRectangle.Height); nameLabel.setText(L10N_issue + ":"); descriptionLabel.setText(L10N_description + ":"); suggestionLabel.setText(L10N_suggestions + ":"); clearButton.setLabel(L10N_clear); refreshButton.setLabel(L10N_recheck); //helpButton.setLabel(L10N_moreHelp); initialize(); } } } } catch (Exception ex) { handleUnexpectedException(ex); } logger.exiting("AccessibilityPanel", ""); } private Rectangle computePosSizes(int visibleWidth, int visibleHeight) { int totalWidth = 0; int totalHeight = 0; int MARGIN = 2*2; int MARGIN2 = 2*6; int SIZE_IMAGE = 2*16; int HEIGHT_LABEL = 2*10; int WIDTH_BUTTON = 2*60; int HEIGHT_BUTTON = 2*13; int MIN_WIDTH = 2*100; int MIN_HEIGHT_TREE = 2*80; totalWidth = Math.max(MIN_WIDTH, visibleWidth); // Tree Control controlRectangles[0].X = MARGIN; controlRectangles[0].Y = MARGIN; controlRectangles[0].Width = totalWidth - controlRectangles[0].X - MARGIN; controlRectangles[0].Height = MIN_HEIGHT_TREE; // Name Label controlRectangles[1].X = MARGIN2; controlRectangles[1].Y = controlRectangles[0].Y + controlRectangles[0].Height + MARGIN2; controlRectangles[1].Width = totalWidth - controlRectangles[1].X - MARGIN; controlRectangles[1].Height = HEIGHT_LABEL; // Status Image controlRectangles[2].X = MARGIN2; controlRectangles[2].Y = controlRectangles[1].Y + controlRectangles[1].Height; controlRectangles[2].Width = SIZE_IMAGE; controlRectangles[2].Height = SIZE_IMAGE; // Name Field controlRectangles[3].X = controlRectangles[2].X + controlRectangles[2].Width + MARGIN2; controlRectangles[3].Y = controlRectangles[2].Y + controlRectangles[2].Height - 24 - 4; controlRectangles[3].Width = totalWidth - controlRectangles[3].X - MARGIN; controlRectangles[3].Height = 24; // Description Label controlRectangles[4].X = MARGIN2; controlRectangles[4].Y = controlRectangles[3].Y + controlRectangles[3].Height + MARGIN2; controlRectangles[4].Width = totalWidth - controlRectangles[4].X - MARGIN; controlRectangles[4].Height = HEIGHT_LABEL; // Description Field controlRectangles[5].X = MARGIN; controlRectangles[5].Y = controlRectangles[4].Y + controlRectangles[4].Height; controlRectangles[5].Width = totalWidth - controlRectangles[5].X - MARGIN; controlRectangles[5].Height = 70; // Suggestion Label controlRectangles[6].X = MARGIN2; controlRectangles[6].Y = controlRectangles[5].Y + controlRectangles[5].Height + MARGIN2; controlRectangles[6].Width = totalWidth - controlRectangles[6].X - MARGIN; controlRectangles[6].Height = HEIGHT_LABEL; // Suggestion Field controlRectangles[7].X = MARGIN; controlRectangles[7].Y = controlRectangles[6].Y + controlRectangles[6].Height; controlRectangles[7].Width = totalWidth - controlRectangles[7].X - MARGIN; controlRectangles[7].Height = 70; // Clear Button controlRectangles[8].X = MARGIN; controlRectangles[8].Y = controlRectangles[7].Y + controlRectangles[7].Height + MARGIN2; controlRectangles[8].Width = WIDTH_BUTTON; controlRectangles[8].Height = HEIGHT_BUTTON; // Refresh Button controlRectangles[9].X = controlRectangles[8].X + controlRectangles[8].Width + MARGIN; controlRectangles[9].Y = controlRectangles[8].Y; controlRectangles[9].Width = WIDTH_BUTTON; controlRectangles[9].Height = HEIGHT_BUTTON; // Ignore Button controlRectangles[10].X = controlRectangles[8].X; controlRectangles[10].Y = controlRectangles[8].Y + controlRectangles[8].Height + MARGIN; controlRectangles[10].Width = WIDTH_BUTTON; controlRectangles[10].Height = HEIGHT_BUTTON; // Repair Button controlRectangles[11].X = controlRectangles[9].X; controlRectangles[11].Y = controlRectangles[10].Y; controlRectangles[11].Width = WIDTH_BUTTON; controlRectangles[11].Height = HEIGHT_BUTTON; // Help Button /* controlRectangles[12].X = controlRectangles[10].X; controlRectangles[12].Y = controlRectangles[10].Y + controlRectangles[10].Height + MARGIN; controlRectangles[12].Width = WIDTH_BUTTON; controlRectangles[12].Height = HEIGHT_BUTTON; */ totalWidth = controlRectangles[0].X + controlRectangles[0].Width; totalHeight = controlRectangles[11].Y + controlRectangles[11].Height; if (totalHeight + MARGIN < visibleHeight) { controlRectangles[0].Height = controlRectangles[0].Height + (visibleHeight - totalHeight - MARGIN); for (int i=1; i urls = new ArrayList(); FileFilter jarFilter = new FileFilter() { public boolean accept(File file) { return file.getAbsolutePath().endsWith(".jar"); }}; String odt2braillePackage = xPkgInfo.getPackageLocation("be.docarch.odt2braille.ooo.odt2brailleaddon"); if (odt2braillePackage.length() > 0) { File dir = new File(unoURLtoURL(odt2braillePackage)); if (dir.exists()) { File[] jars = dir.listFiles(jarFilter); for (File jar : jars) { urls.add(new URL("jar:file://" + jar.toURI().toURL().getPath() + "!/")); break; } File lib = new File(dir.getAbsolutePath() + File.separator + "lib"); // gaat blijkbaar niet automatisch via Class-Path attribuut van de main jar ? jars = lib.listFiles(jarFilter); for (File jar : jars) { urls.add(new URL("jar:file://" + jar.toURI().toURL().getPath() + "!/")); } } else { logger.info(dir.getAbsolutePath() + " is not a directory"); } } URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), this.getClass().getClassLoader()); Provider checkerProvider = new CheckerProvider(classLoader, document); Provider repairerProvider = new RepairerProvider(classLoader, document); manager = new IssueManager(document, checkerProvider, repairerProvider); selectionSupplier = (XSelectionSupplier)UnoRuntime.queryInterface( XSelectionSupplier.class, document.xModel.getCurrentController()); XTextViewCursorSupplier xViewCursorSupplier = (XTextViewCursorSupplier)UnoRuntime.queryInterface( XTextViewCursorSupplier.class, document.xModel.getCurrentController()); viewCursor = xViewCursorSupplier.getViewCursor(); issue2NodeMap = new HashMap(); check2NodeMap = new HashMap(); node2IssueMap = new HashMap(); node2CheckMap = new HashMap(); child2ParentMap = new HashMap(); window.addWindowListener(this); hScrollBar.addAdjustmentListener(this); vScrollBar.addAdjustmentListener(this); refreshButton.addActionListener(this); repairButton.addActionListener(this); clearButton.addActionListener(this); ignoreButton.addActionListener(this); treeControl.addSelectionChangeListener(this); manager.select(null); buildTreeView(); updateDialogFields(); updateFocus(); } catch (Exception ex) { handleUnexpectedException(ex); } logger.exiting("AccessibilityPanel", "initialize"); } private void refresh() throws IllegalArgumentException, ElementExistException, RepositoryException, UnknownPropertyException, NoSuchElementException, WrappedTargetException, PropertyVetoException, ExpandVetoException, java.text.ParseException, java.io.IOException, com.sun.star.uno.Exception { logger.entering("AccessibilityPanel", "refresh"); manager.refresh(); focusedIssue = null; Issue oldIssue = manager.selectedIssue(); Check oldCheck = manager.selectedCheck(); manager.select(null); buildTreeView(); if (selectNode(oldIssue)) { manager.select(oldIssue); } else if (selectNode(oldCheck)) { manager.select(oldCheck); } else { treeControl.clearSelection(); } updateDialogFields(); updateFocus(); if (check2NodeMap.isEmpty()) { showSuccesWindow(); } logger.exiting("AccessibilityPanel", "refresh"); } private boolean selectNode(Object o) { if (o != null) { if (o instanceof Check) { Check check = (Check)o; if (check2NodeMap.containsKey(check)) { ignoreSelectionEvent = true; try { treeControl.makeNodeVisible(check2NodeMap.get(check)); treeControl.select(check2NodeMap.get(check)); } catch (IllegalArgumentException e) { } catch (ExpandVetoException e) { } ignoreSelectionEvent = false; return true; } } else if (o instanceof Issue) { Issue issue = (Issue)o; if (issue2NodeMap.containsKey(issue)) { ignoreSelectionEvent = true; try { treeControl.makeNodeVisible(issue2NodeMap.get(issue)); treeControl.select(issue2NodeMap.get(issue)); } catch (IllegalArgumentException e) { } catch (ExpandVetoException e) { } ignoreSelectionEvent = false; return true; } } } return false; } private void clear() throws IllegalArgumentException, RepositoryException, UnknownPropertyException, NoSuchElementException, WrappedTargetException, PropertyVetoException, com.sun.star.uno.Exception { logger.entering("AccessibilityPanel", "clear"); manager.clear(); manager.select(null); buildTreeView(); updateDialogFields(); updateFocus(); logger.exiting("AccessibilityPanel", "clear"); } private void buildTreeView() throws com.sun.star.uno.Exception { dataModel = (XMutableTreeDataModel)UnoRuntime.queryInterface( XMutableTreeDataModel.class, document.xMCF.createInstanceWithContext( "com.sun.star.awt.tree.MutableTreeDataModel", document.xContext)); issue2NodeMap.clear(); check2NodeMap.clear(); node2IssueMap.clear(); node2CheckMap.clear(); child2ParentMap.clear(); int i = 0; int checkNodeValue; int issueNodeValue; List issueList; XMutableTreeNode issueNode; XMutableTreeNode checkNode; XMutableTreeNode rootNode = dataModel.createNode("root", true); XMutableTreeNode warningsNode = dataModel.createNode(L10N_warnings.toUpperCase(), true); XMutableTreeNode errorsNode = dataModel.createNode(L10N_errors.toUpperCase(), true); dataModel.setRoot(rootNode); for (Check check : manager.getChecks()) { issueList = manager.getIssuesByCheck(check); checkNodeValue = i++; if (issueList.size() == 1 && issueList.get(0).getElement() == null) { checkNode = dataModel.createNode("", false); checkNode.setDataValue(new Any(Type.LONG, checkNodeValue)); node2IssueMap.put(checkNodeValue, issueList.get(0)); issue2NodeMap.put(issueList.get(0), checkNode); check2NodeMap.put(check, checkNode); } else { checkNode = dataModel.createNode("", true); checkNode.setDataValue(new Any(Type.LONG, checkNodeValue)); node2CheckMap.put(checkNodeValue, check); check2NodeMap.put(check, checkNode); for (Issue issue : issueList) { issueNode = dataModel.createNode(issue.getName(), false); issueNodeValue = i++; issueNode.setDataValue(new Any(Type.LONG, issueNodeValue)); node2IssueMap.put(issueNodeValue, issue); issue2NodeMap.put(issue, issueNode); checkNode.appendChild(issueNode); child2ParentMap.put(issueNodeValue, checkNode); updateNode(issue); } } switch (check.getStatus()) { case ERROR: errorsNode.appendChild(checkNode); child2ParentMap.put(checkNodeValue, errorsNode); break; case ALERT: warningsNode.appendChild(checkNode); child2ParentMap.put(checkNodeValue, warningsNode); break; } updateNode(check); } if (errorsNode.getChildCount()>0) { rootNode.appendChild(errorsNode); errorsNode.setNodeGraphicURL(imageDir + "/alert_20x20.gif"); } if (warningsNode.getChildCount()>0) { rootNode.appendChild(warningsNode); warningsNode.setNodeGraphicURL(imageDir + "/warning_20x20.gif"); } treeControlProperties.setPropertyValue("DataModel", dataModel); treeControlProperties.setPropertyValue("RowHeight", 20); treeControlProperties.setPropertyValue("RootDisplayed", false); treeControlProperties.setPropertyValue("ShowsHandles", false); treeControlProperties.setPropertyValue("ShowsRootHandles", false); treeControlProperties.setPropertyValue("SelectionType", com.sun.star.view.SelectionType.SINGLE); if (warningsNode.getChildCount()>0) { treeControl.makeNodeVisible(warningsNode.getChildAt(0)); } if (errorsNode.getChildCount()>0) { treeControl.makeNodeVisible(errorsNode.getChildAt(0)); } } private void updateDialogFields() throws UnknownPropertyException, PropertyVetoException, WrappedTargetException, IllegalArgumentException { Issue selectedIssue = manager.selectedIssue(); Check selectedCheck = manager.selectedCheck(); String image = ""; IssueManager.Status status = null; nameField.setText(""); descriptionField.setText(""); suggestionField.setText(""); statusImageControlProperties.setPropertyValue("ImageURL", ""); if (selectedCheck != null) { nameField.setText(selectedCheck.getName(oooLocale)); descriptionField.setText(selectedCheck.getDescription(oooLocale)); suggestionField.setText(selectedCheck.getSuggestion(oooLocale)); if (selectedIssue != null) { status = manager.getStatus(selectedIssue); } else { status = manager.getStatus(selectedCheck); } switch (status) { case IGNORED: image = "ignored.png"; break; case REPAIRED: image = "repaired.png"; break; case ALERT: image = "warning.png"; break; case ERROR: image = "alert.png"; break; } statusImageControlProperties.setPropertyValue("ImageURL", imageDir + "/" + image); } updateButtons(); } private void updateFocus() { Issue selectedIssue = manager.selectedIssue(); if (selectedIssue == null) { return; } Element selectedElement = selectedIssue.getElement(); if (focusedIssue != null) { Element focusedElement = focusedIssue.getElement(); if (selectedElement != null && focusedElement != null) { if (selectedElement.equals(focusedElement)) { return; } } } try { focus(selectedElement); focusedIssue = selectedIssue; } catch (Exception e) { logger.log(Level.SEVERE, null, e); } } private void updateButtons() throws UnknownPropertyException, PropertyVetoException, WrappedTargetException, IllegalArgumentException { Issue selectedIssue = manager.selectedIssue(); Check selectedCheck = manager.selectedCheck(); boolean repairable = false; boolean ignorable = false; if (selectedIssue != null) { ignoreButton.setLabel(L10N_ignore); repairButton.setLabel(L10N_repair); if (!selectedIssue.repaired() && !selectedIssue.ignored()) { ignorable = true; repairable = manager.repairable(selectedIssue); } } else if (selectedCheck != null) { ignoreButton.setLabel(L10N_ignoreAll); repairButton.setLabel(L10N_repairAll); IssueManager.Status status = manager.getStatus(selectedCheck); if (status != IssueManager.Status.REPAIRED && status != IssueManager.Status.IGNORED) { ignorable = true; for (Issue issue : manager.getIssuesByCheck(selectedCheck)) { if (manager.repairable(issue)) { if (manager.getRepairMode(issue) == Repairer.RepairMode.AUTO) { repairable = true; break; } } } } } else { ignoreButton.setLabel(L10N_ignore); repairButton.setLabel(L10N_repair); } ignoreButtonProperties.setPropertyValue("Enabled", ignorable); repairButtonProperties.setPropertyValue("Enabled", repairable && !document.isReadOnly()); //helpButtonProperties.setPropertyValue("HelpURL", getHelpURL(selectedCheck)); //helpButtonProperties.setPropertyValue("Enabled", false); } private String getHelpURL(Check check) { if (check != null) { return "be.docarch.accessodf.ooo.accessodfaddon:" + check.getIdentifier(); } else { return "be.docarch.accessodf.ooo.accessodfaddon:main"; } } private boolean updateNode(Check check) throws IllegalArgumentException { XMutableTreeNode node = check2NodeMap.get(check); if (node == null) { return false; } Object d = node.getDataValue(); if (d == null || AnyConverter.isVoid(d)) { return false; } XMutableTreeNode parent = child2ParentMap.get(AnyConverter.toInt(d)); if (parent == null) { return false; } //String image = ""; String text = ""; switch (manager.getStatus(check)) { case IGNORED: if (!showIgnoredIssues) { try { check2NodeMap.remove(check); ignoreSelectionEvent = true; parent.removeChildByIndex(parent.getIndex(node)); ignoreSelectionEvent = false; return false; } catch (IndexOutOfBoundsException e) { } } //image = "gray_15x20.png"; //text = "IGNORED"; break; case REPAIRED: if (!showRepairedIssues) { try { check2NodeMap.remove(check); ignoreSelectionEvent = true; parent.removeChildByIndex(parent.getIndex(node)); ignoreSelectionEvent = false; return false; } catch (IndexOutOfBoundsException e) { } } //image = "green_15x20.png"; //text = "REPAIRED"; break; case ALERT: //image = "orange_15x20.png"; //text = "WARNING"; break; case ERROR: //image = "red_15x20.png"; //text = "ERROR"; break; } //text += ": " + check.getName(oooLocale); text = check.getName(oooLocale); int i = 0; for (Issue issue : manager.getIssuesByCheck(check)) { if (!issue.repaired() && !issue.ignored()) { i += issue.getCount(); } } if (i > 1 || node.getChildCount() > 0) { text += " (" + i + ")"; } //node.setNodeGraphicURL(imageDir + "/" + image); node.setDisplayValue(text); return true; } private boolean updateNode(Issue issue) throws IllegalArgumentException { XMutableTreeNode node = issue2NodeMap.get(issue); if (node == null) { return false; } Object d = node.getDataValue(); if (d == null || AnyConverter.isVoid(d)) { return false; } XMutableTreeNode parent = child2ParentMap.get(AnyConverter.toInt(d)); if (parent == null) { return false; } //String image = ""; switch (manager.getStatus(issue)) { case IGNORED: if (!showIgnoredIssues) { try { issue2NodeMap.remove(issue); if (issue.getElement() == null) { check2NodeMap.remove(issue.getCheck()); } ignoreSelectionEvent = true; parent.removeChildByIndex(parent.getIndex(node)); ignoreSelectionEvent = false; return false; } catch (IndexOutOfBoundsException e) { } } //image = "gray_15x20.png"; break; case REPAIRED: if (!showRepairedIssues) { try { issue2NodeMap.remove(issue); if (issue.getElement() == null) { check2NodeMap.remove(issue.getCheck()); } ignoreSelectionEvent = true; parent.removeChildByIndex(parent.getIndex(node)); ignoreSelectionEvent = false; return false; } catch (IndexOutOfBoundsException e) { } } //image = "green_15x20.png"; break; case ALERT: //image = "orange_15x20.png"; break; case ERROR: //image = "red_15x20.png"; break; } //node.setNodeGraphicURL(imageDir + "/" + image); return true; } private boolean focus(Element element) { if (element == null) { removeSelection(); return true; } removeSelection(); if (element instanceof FocusableElement) { return ((FocusableElement)element).focus(); } return false; } private void removeSelection() { try { selectionSupplier.select(document.getFirstParagraph().getAnchor()); viewCursor.gotoStart(false); } catch (IllegalArgumentException e) { } catch (NoSuchElementException e) { } catch (WrappedTargetException e) { } } // XActionListener public void actionPerformed(ActionEvent actionEvent) { Object source = actionEvent.Source; Issue selectedIssue = manager.selectedIssue(); Check selectedCheck = manager.selectedCheck(); try { if (source.equals(refreshButton)) { refresh(); } else if (source.equals(clearButton)) { clear(); } else if (source.equals(ignoreButton)) { if (selectedIssue != null) { selectedIssue.ignored(true); if (!updateNode(selectedIssue)) { manager.select(selectedIssue.getCheck()); selectNode(manager.selectedCheck()); } if (!updateNode(manager.selectedCheck())) { manager.select(null); ignoreSelectionEvent = true; treeControl.clearSelection(); ignoreSelectionEvent = false; } } else if (selectedCheck != null) { for (Issue issue : manager.getIssuesByCheck(selectedCheck)) { issue.ignored(true); updateNode(issue); } if (!updateNode(selectedCheck)) { manager.select(null); ignoreSelectionEvent = true; treeControl.clearSelection(); ignoreSelectionEvent = false; } } updateDialogFields(); updateFocus(); if (check2NodeMap.isEmpty()) { showSuccesWindow(); } } else if (source.equals(repairButton)) { if (selectedIssue != null) { if (manager.repair(selectedIssue)) { if (!updateNode(selectedIssue)) { manager.select(selectedIssue.getCheck()); selectNode(manager.selectedCheck()); } if (!updateNode(manager.selectedCheck())) { manager.select(null); ignoreSelectionEvent = true; treeControl.clearSelection(); ignoreSelectionEvent = false; } } } else if (selectedCheck != null) { boolean repaired = false; for (Issue issue : manager.getIssuesByCheck(selectedCheck)) { if (!issue.repaired() && !issue.ignored()) { if (manager.repair(issue)) { repaired = true; updateNode(issue); } } } if (repaired) { if (!updateNode(selectedCheck)) { manager.select(null); ignoreSelectionEvent = true; treeControl.clearSelection(); ignoreSelectionEvent = false; } } } updateDialogFields(); updateFocus(); if (check2NodeMap.isEmpty()) { showSuccesWindow(); } } } catch (Exception e) { logger.log(Level.SEVERE, null, e); } finally { ignoreSelectionEvent = false; } } // XSelectionChangeListener public void selectionChanged(EventObject event) { if (!ignoreSelectionEvent) { try { Object o = treeControl.getSelection(); if (o != null && !AnyConverter.isVoid(o)) { XMutableTreeNode node = (XMutableTreeNode)AnyConverter.toObject(XMutableTreeNode.class, o); Object d = node.getDataValue(); if (d != null && !AnyConverter.isVoid(d)) { int index = AnyConverter.toInt(d); if (node2IssueMap.containsKey(index)) { manager.select(node2IssueMap.get(index)); } else if (node2CheckMap.containsKey(index)) { manager.select(node2CheckMap.get(index)); } else { manager.select(null); } } else { manager.select(null); } updateDialogFields(); updateFocus(); } } catch (IllegalArgumentException ex) { logger.log(Level.SEVERE, null, ex); } catch (UnknownPropertyException ex) { logger.log(Level.SEVERE, null, ex); } catch (PropertyVetoException ex) { logger.log(Level.SEVERE, null, ex); } catch (WrappedTargetException ex) { logger.log(Level.SEVERE, null, ex); } } } public void disposing() { if (window == null) { return; } window.removeWindowListener(this); hScrollBar.removeAdjustmentListener(this); vScrollBar.removeAdjustmentListener(this); refreshButton.removeActionListener(this); repairButton.removeActionListener(this); clearButton.removeActionListener(this); ignoreButton.removeActionListener(this); treeControl.removeSelectionChangeListener(this); try{ XComponent xWindowComp = (XComponent)UnoRuntime.queryInterface(XComponent.class, window); xWindowComp.dispose(); } catch(Exception ex) { logger.log(Level.SEVERE, null, ex); } } // XItemListener public void itemStateChanged(ItemEvent event) { } // XWindowListener public void windowResized(WindowEvent event) { Rectangle mainRectangle = window.getPosSize(); Rectangle totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); boolean hScrollBarEnabled = totalRectangle.Width > mainRectangle.Width; boolean vScrollBarEnabled = totalRectangle.Height > mainRectangle.Height; if (hScrollBarEnabled && vScrollBarEnabled) { mainRectangle.Width = mainRectangle.Width - 20; mainRectangle.Height = mainRectangle.Height - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); } else if (hScrollBarEnabled) { mainRectangle.Height = mainRectangle.Height - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); vScrollBarEnabled = totalRectangle.Height > mainRectangle.Height; if (vScrollBarEnabled) { mainRectangle.Width = mainRectangle.Width - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); } } else if (vScrollBarEnabled) { mainRectangle.Width = mainRectangle.Width - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); hScrollBarEnabled = totalRectangle.Width > mainRectangle.Width; if (hScrollBarEnabled) { mainRectangle.Height = mainRectangle.Height - 20; totalRectangle = computePosSizes(mainRectangle.Width, mainRectangle.Height); } } setWindowPosSize(treeControlWindow, controlRectangles[0]); setWindowPosSize(nameLabelWindow, controlRectangles[1]); setWindowPosSize(statusImageWindow, controlRectangles[2]); setWindowPosSize(nameFieldWindow, controlRectangles[3]); setWindowPosSize(descriptionLabelWindow, controlRectangles[4]); setWindowPosSize(descriptionFieldWindow, controlRectangles[5]); setWindowPosSize(suggestionLabelWindow, controlRectangles[6]); setWindowPosSize(suggestionFieldWindow, controlRectangles[7]); setWindowPosSize(refreshButtonWindow, controlRectangles[8]); setWindowPosSize(clearButtonWindow, controlRectangles[9]); setWindowPosSize(repairButtonWindow, controlRectangles[10]); setWindowPosSize(ignoreButtonWindow, controlRectangles[11]); //setWindowPosSize(helpButtonWindow, controlRectangles[12]); setWindowPosSize(mainWindow, mainRectangle); updateScrollBars(hScrollBarEnabled, vScrollBarEnabled, mainRectangle.Width, mainRectangle.Height, totalRectangle.Width, totalRectangle.Height); } public void windowMoved(WindowEvent event) { } public void windowShown(EventObject event) { } public void windowHidden(EventObject event) { } // XAdjustmentListener public void adjustmentValueChanged(AdjustmentEvent event) { Object source = event.Source; if (source.equals(hScrollBar) || source.equals(vScrollBar)) { horizontalOffset = hScrollBar.getValue(); verticalOffset = vScrollBar.getValue(); setWindowPosSize(treeControlWindow, controlRectangles[0], horizontalOffset, verticalOffset); setWindowPosSize(nameLabelWindow, controlRectangles[1], horizontalOffset, verticalOffset); setWindowPosSize(statusImageWindow, controlRectangles[2], horizontalOffset, verticalOffset); setWindowPosSize(nameFieldWindow, controlRectangles[3], horizontalOffset, verticalOffset); setWindowPosSize(descriptionLabelWindow, controlRectangles[4], horizontalOffset, verticalOffset); setWindowPosSize(descriptionFieldWindow, controlRectangles[5], horizontalOffset, verticalOffset); setWindowPosSize(suggestionLabelWindow, controlRectangles[6], horizontalOffset, verticalOffset); setWindowPosSize(suggestionFieldWindow, controlRectangles[7], horizontalOffset, verticalOffset); setWindowPosSize(refreshButtonWindow, controlRectangles[8], horizontalOffset, verticalOffset); setWindowPosSize(clearButtonWindow, controlRectangles[9], horizontalOffset, verticalOffset); setWindowPosSize(repairButtonWindow, controlRectangles[10], horizontalOffset, verticalOffset); setWindowPosSize(ignoreButtonWindow, controlRectangles[11], horizontalOffset, verticalOffset); //setWindowPosSize(helpButtonWindow, controlRectangles[12], horizontalOffset, verticalOffset); } } // XEventListener public void disposing(EventObject event) {} XWindowPeer createWindow(XToolkit toolkit, XWindowPeer parentWindow) { try { WindowDescriptor aWindow = new WindowDescriptor(); aWindow.Type = WindowClass.SIMPLE; aWindow.WindowServiceName = "window"; aWindow.Parent = parentWindow; aWindow.WindowAttributes = 0; return toolkit.createWindow(aWindow); } catch (Exception ex) { logger.log(Level.SEVERE, null, ex); } return null; } private XControl createControl(XMultiComponentFactory xMCF, XComponentContext xContext, XToolkit toolkit, XWindowPeer windowPeer, String type, String[] propNames, Object[] propValues, Rectangle rectangle) { try { XControl control = (XControl)UnoRuntime.queryInterface( XControl.class, xMCF.createInstanceWithContext(type, xContext)); XControlModel controlModel = (XControlModel)UnoRuntime.queryInterface( XControlModel.class, xMCF.createInstanceWithContext(type + "Model", xContext)); control.setModel(controlModel); XMultiPropertySet properties = (XMultiPropertySet)UnoRuntime.queryInterface(XMultiPropertySet.class, control.getModel()); SortedMap props = new TreeMap(); if (type.equals("com.sun.star.awt.UnoControlImageControl")) { props.put("Border", (short)0); } else if (type.equals("com.sun.star.awt.UnoControlEdit")){ props.put("MultiLine", true); props.put("ReadOnly", true); props.put("VScroll", true); } if (propNames != null) { for (int i=0; i 0) { properties.setPropertyValues((String[])props.keySet().toArray(new String[props.size()]), (Object[])props.values().toArray(new Object[props.size()])); } control.createPeer(toolkit, windowPeer); XWindow controlWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, control); setWindowPosSize(controlWindow, rectangle); return control; } catch (com.sun.star.uno.Exception ex) { logger.log(Level.SEVERE, null, ex); return null; } } private void setWindowPosSize(XWindow window, Rectangle posSize) { setWindowPosSize(window, posSize, 0, 0); } private void setWindowPosSize(XWindow window, Rectangle posSize, int horizontalOffset, int verticalOffset) { window.setPosSize(posSize.X - horizontalOffset, posSize.Y - verticalOffset, posSize.Width, posSize.Height, PosSize.POSSIZE); } private void handleUnexpectedException(Exception ex) { logger.log(Level.SEVERE, null, ex); UnoAwtUtils.showErrorMessageBox(docWindowPeer, "Unexpected exception","Unexpected exception"); } private void showSuccesWindow() { UnoAwtUtils.showInfoMessageBox(docWindowPeer, L10N_congratulations, L10N_noIssuesFound); } //XToolPanel public XWindow getWindow() { if (window == null) { throw new DisposedException("", this ); } return window; } public XAccessible createAccessible(XAccessible i_rParentAccessible ) { if (window == null) { throw new DisposedException("", this ); } // TODO: the following is wrong, since it doesn't respect i_rParentAccessible. In a real extension, you should // implement this correctly :) return (XAccessible)UnoRuntime.queryInterface(XAccessible.class, getWindow()); } private static String unoURLtoURL(String unoURL) { try { if (System.getProperty("os.name").contains("Windows")) { unoURL = unoURL.substring(6); } else { if (unoURL.startsWith("file://localhost")) { unoURL = unoURL.replaceFirst("file://localhost", ""); } else { unoURL = unoURL.substring(7); } } return URLDecoder.decode(unoURL, "UTF-8"); } catch (UnsupportedEncodingException e) { return null; } } } PanelUIElement.java000066400000000000000000000047511225501747700336040ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/toolpanel/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.toolpanel; import java.util.logging.Logger; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.UnoRuntime; import com.sun.star.awt.XWindow; import com.sun.star.frame.XFrame; import com.sun.star.lang.XComponent; import com.sun.star.ui.XUIElement; import com.sun.star.ui.XToolPanel; import com.sun.star.ui.UIElementType; import com.sun.star.lib.uno.helper.ComponentBase; import com.sun.star.lang.DisposedException; import be.docarch.accessodf.Constants; public class PanelUIElement extends ComponentBase implements XUIElement { private final String m_sResourceURL; private XToolPanel m_xToolPanel; private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); public PanelUIElement(XComponentContext context, XWindow i_rParentWindow, String i_rResourceURL) { logger.entering("PanelUIElement", ""); m_sResourceURL = i_rResourceURL; m_xToolPanel = new AccessibilityPanel(context, i_rParentWindow); } // XUIElement public XFrame getFrame() { // TODO return null; } public String getResourceURL() { return m_sResourceURL; } public short getType() { return UIElementType.TOOLPANEL; } public Object getRealInterface() { if (m_xToolPanel == null) { throw new DisposedException("", this ); } return m_xToolPanel; } public void disposing() { XComponent xPanelComponent = (XComponent)UnoRuntime.queryInterface(XComponent.class, m_xToolPanel); xPanelComponent.dispose(); } } ToolPanelFactory.java000066400000000000000000000132741225501747700342220ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/java/be/docarch/accessodf/ooo/toolpanel/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf.ooo.toolpanel; import java.io.File; import java.util.logging.Logger; import java.util.logging.Level; import java.util.logging.Handler; import java.util.logging.FileHandler; import java.util.logging.SimpleFormatter; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; import com.sun.star.beans.PropertyValue; import com.sun.star.lang.XServiceInfo; import com.sun.star.lang.XSingleComponentFactory; import com.sun.star.lang.XInitialization; import com.sun.star.awt.XWindow; import com.sun.star.ui.XUIElementFactory; import com.sun.star.ui.XUIElement; import com.sun.star.lib.uno.helper.Factory; import com.sun.star.lib.uno.helper.WeakBase; import com.sun.star.registry.XRegistryKey; import com.sun.star.container.NoSuchElementException; import com.sun.star.lang.IllegalArgumentException; import be.docarch.accessodf.Constants; public class ToolPanelFactory { public static class _ToolPanelFactory extends WeakBase implements XUIElementFactory, XServiceInfo, XInitialization { private final XComponentContext m_xContext; private static final String _implementationName = _ToolPanelFactory.class.getName(); private static final String[] _serviceNames = { ToolPanelFactory.class.getName() }; private static final Logger logger = Logger.getLogger(Constants.LOGGER_NAME); private static final String TMP_NAME = Constants.TMP_PREFIX; private static final File TMP_DIR = Constants.getTmpDirectory(); private Handler fh = null; private File logFile = null; public _ToolPanelFactory(XComponentContext context) { m_xContext = context; try { logFile = File.createTempFile(TMP_NAME, ".log", TMP_DIR); fh = new FileHandler(logFile.getAbsolutePath()); fh.setFormatter(new SimpleFormatter()); Logger.getLogger("").addHandler(fh); Logger.getLogger("").setLevel(Level.FINEST); } catch (java.io.IOException ex) { logger.log(Level.SEVERE, null, ex); } catch (RuntimeException ex) { logger.log(Level.SEVERE, null, ex); } } // XUIElementFactory public XUIElement createUIElement(String i_rResourceURL, PropertyValue[] i_rArgs) throws NoSuchElementException, IllegalArgumentException { logger.entering("_ToolPanelFactory", "createUIElement"); if (!i_rResourceURL.startsWith("private:resource/toolpanel/be.docarch.accessodf.ooo.toolpanel")) { throw new NoSuchElementException(i_rResourceURL, this); } // retrieve the parent window XWindow xParentWindow = null; for (int i=0; i freesb1996-10-15T00:33:282012-11-22T16:52:28LibreOffice/3.6$MacOSX_x86 LibreOffice_project/58f22d5-270d05a-e2abed1-ea17a85-9b5702PT2H37M9S14PK~vA settings.xmlíZßSâH~¿¿‚Ê»òCJÙBDåÖU‹ ·»oCÒÀ”“éÔÌDdÿú›°4&’Œu[Ç“’™ùºÓÝóMwON¿¼x¬ò BRägVý°fU€;èR>=³F—'֗Χ8™PÚ.:\HPJO‘½œËv4|f‚·‘H*Ûœx ÛÊi£|½¬ývv{),zòÂ(:³fJùíju>ŸÎQL«õV«U]Ž®§:È'tšUT4û­(D|.ˆ”Y kÔjÇÕè·UY)ùÆ4 «³¶Ãúõ;§+ÑŸªÀ mSY=U;³´Èö3…ù«Õ¬¤uï×£êº÷ …Æoä EŠ:¦ÐcÚ¯ ”dŸ2ôß„ŸÓþ]GÑgX¢ Ÿ¦˜ç(øZß’Ùk ;L£–f1ÜrY|zŽJ¡W¢ë~"z#’천چ „qÔ¥¢'y K¦2ìFðfNíί“÷‘áVG‰’‘n>3Òˆú¶û­_Cg>÷½'è=Aï zOÐÚ~¸ºêÛ%&Òæh:§‘3ÓtÞŠ1M—£ý&-CøÙh:糦 ²*M$ÔϦ錺§is46¼l’dÝYËöIJæ »¦G cc"RÛbÇœ›xf¯a 8@žî„͵´›&Sb.‹˜Ÿ p©¿Ü=¦³àߢ2o#nCQ{ÈPÄ †Û¨Þh5æ šw~5`•k"µêLJ8¿â‚0#Äž(Í6Ðò.PŒr°Þ™´!~ê–"ÄæÄáHqG—±³"à\5ùI‚ÔþNoe×j9(ŸÜ-)oc—>S™ª~Iàe¶z2‚ï¾Pi/¸3Èé/ø¼Œ`uÁ“¥·›L7LvlºŒi߆œö7Ž{„;À~Ó.Å'•øÿÅ6µ0¬~øÜ³šö!lç_PKðÈ&õzJ+PK~vA content.xmlì½ÙsÇ™/ú~ÿŠ N‡±“”-)nâˆu Ò¾3/Šì®ìî$ª«Úµž´’=GrÄÄÜŽëã b4㡇KÀMq3#nŸy^¥WÇ9ÿÇý–ÌZzªÁBu¨ñìîªÊü2+ó÷-ù-?úë›mÇZ“~ <÷Ís3³',éÖ=[¹Í7O\¿vqúô‰¿~ëÿú‘×h¨º|ÃöêQ[ºátÝsCø×‚§Ýà ¾úæ‰ÈwßðD ‚7\Ñ–Áaý ¯#]óÔé»ß ¾ø— Üpr?N7§ŸåÍ0ïÃxoæYQËß3Ýœ~ÚöÅzÞ‡ñ^˜Ôôã /ïÃ7gºáÁ¬·;"T=TÜt”»úæ‰VvÞ8yr}}}f}aÆó›'çΜ9s’®Æ×ãû:‘ïÐ]vý¤t$vœœ›™;iîmËPä¥ïM“äFíšôsOEß[íø2€[`¸¸0ó5”~&³¾Öš¹W×ZsÈ4×[ÂϽÎèæìRY°ó/•;ýl[„­!ï÷ôÉ÷à"ýyïJ²®üvÞ¾ðÞÌTÕ}ÕÉ=L¾;ý¼çy1©øov"w~vvñ$Oݽ¾ëíë¾ ¥Ÿº½¾ëíuáÔã÷Úƒ& î›; wLË5\òñ&‰†<0’/Ç7öЦÿï÷®¬Ô[²-’›ÕÞ7O+7…›ÌŒ/aèH—Nú²ãùa<1üà ok>¦­¶áÐWÍ­Mß¶Þ ä,œM<½¦äú_e°u÷õpæ$Ýo1x} ˜û͘ß4¼Èµy[óàäÍŽô^=öF¦… Ê*阭0¨ uºÀ›€çuÞH=m¿}3_s¸Ê<»ÑÛbÏŽ«ÁB8hb¯ýä$^›Fž¨¬{JñêùoÆÌ18ÿÐ=Ýu9m˺¼õ#Øøg‹¿#Ýož8ë+á̰üÌmålè 'Næxz~èÓVæY¼2Ý”.Ìlå`]Á^ퟎªùj@É•Wî¢ íˆ]˜+¯Ø…™ŒýNRúŽŽ ëÀÖ<‹Û'O×ÖuW\'­÷VPñÑñ‚öÞÈ¿îNÜFÊö«PwM´¼ö ©/dïÿçþÿß/þq@ïñ…Wíýä°©Qà U}šÚ‰·*ýÍÐZ÷æçâÞ4™„Ÿ ±8QÛ=aMÿ8Ýè‘~¨d`5¼7j¾«Ó5 (-bߦE}ûº²QÚX˜YšŸ?­\AŠ ]©›/‹ºù™åSKË#R·Pu§–Fœ»Óe7;súôì©§n±¼©›]:37"uK%Rwj~4âN•GÛÂâÒÂhÄ)MæOÍŽøZçfË£nanqD4™+‰–ÏŒøbçJDâS§—GÜs%"ñÒ©åÅ©+ì–Î,ŒÅs¥ÝÂÌìéåQwÅryÔÍÍ-Š(%‚ñòÂÜ™©+M˜ŸY\ZZ‘ºÒx0ÙÓs£Š¥ñŠù™¹ÅÅçn¾´]17³tziD¼›/mWÌÍ,ÏŸqWÌ—¶+æ@jŸUã)mWÀÜÍžqÝ-”¶+€º3K#r²…Ò$(@ãùÙ‘Öï !Î÷Ö{(ƒ_Òdñ%ü±%U³¢Â5Š4éÝIŽ9íuBÕÎtúñÐä(„ƒÂ}P>7sz™Ð¤$Ê‹›sÀÁ……¥ò("nïƒrºæ—Ë›ó!’øþ–ù쩹Ò&iîk±ÌÏΗGxqkenfva¹<ʇÐöAùÒÌ,Kï%Q>D¥Û×þœ;3_"² Q÷öA9h›ó§J£|ˆÜ¶/d9ÍÆ£’6è™n_tùÌ™7hq˜¸0³|úLyBË0›Ë¾VË©ÙÅò–ù0íi_tùÌbyÐ2ÌÞ°¯u¾°|º¼ZäbYZ8SÞZ)nÆf–N•ȆŠÃÄyX+óË¥Q^ÿDw¹<`Y(NND t©¼)_(R©X(Sw^(YØÆZåE®óÓ³%²þ…"¹Å¹í űþ¹™¹¹Aq¡HáüL‰ŠÜBq|X™öŠÅâÌrȈJ”p‹4ËͳcLI”ijYZ^.΋c¡s3§æÊ”Í‹d¡ËK%,‹d¡s|R塼XÌm„ҟœæ'>€+xíåƇ+×/]º°ríòÕ÷Wz†™"G¾Ø*è8bC¨›G}å6§Ûž M;þtX…öÁ[4'íïŸ}ïÂX¨¼ÈsR}þÂʹŸ\þ`LS^—KÃÜo¤;"w„a^ôEá¼lˆÈ {æà¡þÍÐt6:­iÏW&gz ¯×…›ƒw…çÛ0G5/ 1NĈ¹Nhž£lë¯féÿø>Q_múèþg€žÿ承ªÓÿJm%šž ;¨æL‡pÙõ\Ùw-„Ë=×Ы~Z8ªéN^äcøZCÝ4W}Ù‘"sƒK $´î‹íZôÁÇ/éá8²ö’àË:ßì„>ÝÛ6‡×ÍÎÌ&Ê 7àÇÚÀé0@£§T¸MŒ]pG•%#hùÊ]½é†Ê G÷zìæ}™Æb/å¾nDA¨ÚbwkXA¢ ÓÓê9´Mæ×¢KÑ=ÁW²­ámá7•«§v§kÐ.ÀÍ–tNMõ­JÄÛuåڵ䌭Tzkу^:Ê•ñ4¥.áïÓa d³Å»cÀªêxâWo4ì.k#£_µ ¿Î-vÂÔo¦a¿±fÖ‚–°1^ª¯CØÒ'Ò2$™æÖ5_1í¥hÂÞ§E „khH_¤Ý¯¯x˜ÛÝå1EÓ9òf*ʤ§ûø†!Äׇ“Ð{K¼Ú¢£o‡­lë·B˜¥·ök¯¿ùƒŸG^øCþk޳‘¿ 7á1„ïsÐÐEì&Äo øgŽþ˜gk"иÝ—Aðæ‰“9;7XóF#X„ØW‡ß5áD°¹6:roîg ¡/Ü€g¢ÂéWÅé’¹-жæ¦;q2Vµ«m\mãaÛx˜çnÅ}«m{·mî}1Ìg|âØÛ±5!¤[8Ì›¡2T&ƒÊd08 ™ÉÎu0ŸKúúû³EàöøäÀ´pÔ<šÒÂQÙ/¸JfªMQmŠ ÛËÃb«MQmŠÃ"3Ï÷É̳ 3Ï– 3Ï÷wŸÈ̃ 8Ö2óò°`äJf®°B K5q¦]NÇùä¨Xy+@®¹äÁ€O;.*Í®çi•J“F°±û3TV!Xe”©Œ2ûF°Ê# B°W@°¹FíÔÜâA!X%ƒU¶'‚=ÿØ‘ñ)u½éÊ~S¹•Vn¥•[éh¡j£Ÿ212De£¯dˆ½ qñ ïúR ø¿a.pGbJÚumÿö@3õûeGƒmw•/ã bìÞ€ã#*©á°I •åáHI {&ogD-mûâAç¹™øX胙ֱ»|UnãÇïØ±be+;Ƭì ÔNGF«4¶\‹¢òû̦+¿ŸÊï§òû9~?¹‘î ÝkŽ)ûË=÷c?¿?2\¦Êä]±œÏB ËÙõ,ôºšÎç’úÏ_X9÷“Ëì§”ìâØ½EúaùÕ’– ÚChu;ªˆ|øüµ|#.M`Ù¡Ê^mÌjc–ëáRvÆ®Q”ÄÃVûäàׯØ]*¥¶²›VJl¥Äk%öÔØ ŽO¶ ÁJ-w™]Ú¨–ùÄ/ó æßÇÅé¨ä<°UùK+`;4ÀV9ZVÀ–Ø*÷CdÔ?*¦¢£ ½•LYAo^è=hW÷IŽÚ:øÙ=4>ãc«ÛQ¶ NHÆÀJužàe^¥®T割±ÇbIaBÂñFÄ#°_&Ðq»r=ƒØ½›ÚS¹"U®H¯$ÆT®H#Âòé‰pãß+Þ+ +•.vœ%Ó•·]µÌ'c™ï™$'³ÌGË•szìÞv•€] Ø•€] Ø…عaoB|ñ*;Üq&ŽËIEåY2ªþshœú&^0<ôùò*Ù°’ ¿lxd¹Jo{XÓÛüÚ84‹×>h®]ek¨¸tťdžÄcwY­¸Bâ ‰+$>X[zÓï;(§Õ Ú<¤¿§×í‹u\€«°E‚Pø!Î÷Ö[RØÁ‡ó³ˆÊ}÷À³ÃmçS§Oá‚í¿…W~¼Â膆r õR¿dœFê³ú îŽi€Âõé–~缊{.jJ’í®±ÆØKfÎ,jÀ1WpQoÂA—â¬tæ‘bVrKÙ¶Ìþ8í5 §oyÈ\ßè»^„¸Ó2€Or:©‚ò­‰ú–D Z'F1z¥YVt€¦XïAÚ¹5_ŠÕÞ5>:˜•ࣉ€"xž1ª8ôaºÞ¾P2”õ<ɳ…|Y¹‘Y_ËsWfš†Ý™`œ†Àÿsÿ¿ÿïÿ˜ë¨ÀÌž¹¶Ù2Wô4š çÞ?pLÎÓ_m©^ªãK—ѽ(O¿Ùî´/þ5ëKGÉÆ€¿ð«={ƒ†ÔD u×1Uº"Œ·Sn ¹ÖL ý¶S? gÎ,/Ÿ(hOsG^ ‘ÙÿbÍÍÎþ—ê”ml§l9—O¿sÓn˧4av´åT…—MÊrêw ͉F¶={z¶B£cŽFýç6{£Q%VÒh%%öíÕ“  «º|#¶Âq«Á[?Òjž½ :>Ú'ZR†oýˆ,³ 2;õÈaó (Õ¨k–¹’D ]ÄéµdóòŤÃÈÓŽ¨I'è¹%_6¡yZÞì Iº RR4ßGõ3¼Õ©@¦i†__Åü‰x8 x#Ȧüvš¯)Ë^$£º-4ãòæDÎqÔvôZ÷Nbl¶o³E;sœ_¡Á39\˜¡Á¹ÙÂ[œ+¼ÅùÂ[\(¼ÅÅ¢[6@øFç-eÿè¤þzÎÙÕüb®®¤[^WAi]¹Î«wµ°œ««†_ZW²¼Q5ËëÊ–ÅtµØ,žîÑaÍ-îÝÜ©ej.C0àCNÀXÈ ó³ùÖ;Üþá…ßîÆ5:…ì´¥\=¿8©@R´¨_–çÊëýB*Ç ¬v÷)“X6Ò½FŽg°®òM‚”xj,-¬ø-ÿ‡@• -¯ÓbôÆ’ŽÅ^0UÒáx*‰8Q däV|‚“%ÖdÝ2¯-¡FÒÇëª#Š£ót.:·ÿyûåö3øßÖÎGð÷®µóéέÛÛϬ[Ûà¿gÛ/wn¿:9‹óùÞl²°¤^k°ÀB^`,ó<¸ufÜ:\øt¡Ý  ÊCì2 N%c“µ&êÝ{^ – ØJù„ +²i©$(Ê·Å?ˆÈZS0/B¿Ù~´ýbç‹OÒ¨óIi¨£—N‚4VM8RùGqpÞ‘=2J†œVÙ½ºuQ“›Â6SZÏ„3«^§´íÉà€ØQ2"lß·¶\òdû)üûÙöàƒío¶·JC†sðŽë€B#‚¨a4DÐ`°²ª X¯97Èe·îùè“ålXä^*m%ªJ1>D„KŸ€Å ­XXÊÐXÄŠÊGÑ»^§#]èÙòÜ‘ BØÓžÓDâ YÕyµý¼ð?a¿¿Øþ4“O·Ÿo߃ÏA;\x²ó1(*ƒaç—Û/Êdž õ6ÛèXi^¸(b¹G¸¸ì^ôá‡Ò¶†îÞc@²Õ(µû”,ë&ôI\«-üzyrà‚ƒŒ(hø#ɶpt]Øø dq¸Z¢Äñ? "€Î!E6’-ÐP>…[_ŽA 1Ë£ÀÅq<ñe…]¶Ç‡0AÉ Á"¤®ºË£$…34 cYà+Èwò’b|ð²óùöý±BL«ÐÅq¬pæ}ïŠö*mu™á^kÐÀzÓzßs‹ ߑlj܈y·‡À‘[›Ê³Ã…p¬5á $\’Eœ¹/äó$ —3±ôÝŸê‘ûš|½ïÕ#Ôm­¼@…¢ÃrÊ&ä‚cÙš ùX¹c°§ãùHpöò§dn¤l„V“$›P¸¶¾"•¶÷ø1s»Í¶úyÔ½S}½ýÒBA æ9Yráë7øÁYçs´áûÍ3øò0¶ïÀǼJ“}®fV” ÐíZŠa«ãK[†Òo+´ß]¼:(¸z.£—ñjéâPÜs QÅÉC9²”<úzKAÒuD]ŽS0jÅóR”h4Š| “ÁÞ:QL ic–’¾ Ú‚/_LÁw>¯¼$,G5Å&è^•¼´oºîQD ðr €Û”w…}òOœ%´bj¬Ú†uþìå•¿-SnbBÈð£2å'Läëµ;"TÐ4|tK¦ël£&¥CgsDΔBïŒk B¹6°gê "+'>ðJ1hEÓE¢”~ƒÝ;è×W2MÛ¿F[ÑËw>ƒ¿m¿`zŒX…^3X(Wm?ÝùPl ¿²ÄµsïE¿>¸écxæO€p·Ø@C¯¿—<Œ™å­x% \‰7%‰]0§¼»÷jÒ)t)/Ô#Ø9ëÖ[žÑñJÇ;Ö " î/ýö,€LKø¢¢ô_>ú§ò\eDéÂîWH–#`ݱ‹Û9¯íYuáw¿BÒŠr{úòÖ¤/ÜUéÛš¸³NºÈªt sÇËgÄâ×è2ôÁ¬ðÁ¼ùÝ;2™·¶Ä‰ƒWÚýw_–í0øë Öź%z~ºóK@É­[;¿‚kéþútR”þH'5ˆ¹EM>GcüçðËÇôííûø©D‡Ä³)XÔ˶îù¸la3e×l1Ûé8äYÐKËuŠ~Oîò°Ô^µÒPœ÷|Îè Ô*'Ó:`3tì=žÐÿ@²Úm¦BãˆÁ0á<¶ ¦Þ¬«Êò5:¼S¶Ãáû^ùNŽbdì\PZׄ2«äÒX6‚„Lr~_hm„·7ôŠD÷,ãõXa¨˜°ÕJ<+(½O Øqaq{#`ŽB”/ÊÆ–V¼(˜&ˆ(?Š ¦.ƒfŸ/@zxRz<âD¡¯Bq â¬z&‚¼"׊XÅyµß°%\k„bè9@W¢ÒeŠ÷º_ÑnZ¶\Dpˆù 2G_AMˆˆ:?+[äp¢Ôlˆèæ8f—D<-#DÁo[d<Þù(#©ä:.²?ã¸3`©Ô¤ñçJnÙ/]«òº«©®¨ <{2öl[‘éÛrÊìGŠ~k æ±0›WáZ ùúÿ)æ³¼NàµÛpÁQ7 |ñqZÿýK”3`Ë?ÆªÇæ@ý–6¿¦ü{žaðþX\Ä·FK'ó6+®Ž ƈcÝþM ‹¤Ùn¬Cº÷«¿¿OéJÝòœÐa [9”M‰ ÚÖy„9ì{<©ÊßÿüZ«Ô ûÚøW”»ªýæJ܇Ø';m”ë¶‚‡ŽØ,†Aä5W’1ÁÁxÐØ¤€}™/\‹½<Õ½S"üËÎmv±¥ÿbÉ åËQ6\& t²­d‚Q¡ÖÎÏTØò¢ð¬S¶ƒÙ:wL!v–ÐÆRµV:`ÊÕŽ åÙ'SÞc›tæ¾bÀî )²QÚ¶æ×`\uêuÐÜDÐt™IRNa;Ÿïüý]Ù1ö™"Ÿi‡.º«Ç¬dä äÁ¬žcDWk7d=qÇC¡¨€\¸#kh¼X¤gcÜ8Ds18ôÛ/´A$ãn:©ˆtµv#f&”©ÔóÛ‘#Æ€Jºç–„›Ù¶ ê¾ê”šwæb÷!Ó„…ùf4”V$E]yjO’;Z:&¯þmç & .ºˆ´RmßOòÔ<$ßøÏJÌU“,)€+^N±š&´îxç¶RòÁNXjŸ8Âñä„X¹ª€’ï¥Ò›‘޳ëÞaO÷$\'°`Üz‰.$é3¢—èöˆ9ˆ+OK ¬á¡°ûUÍ;Âq@ñžô›Ò>•ç F+cAC¡\,ñ$XõRi¸"èiAdPºhÑ8]SEåyÍ=Ò¡°št›rÍ“M›(rJtK3øEè¨×ˆ°òžÛ½S¦sÚïz°$‘LL¦™OAªyˆ" ÞÖvç-Ö¶žÁwK ³|h-uï¸8yÂÌ\•1x^õ2ÚÊ]¸Ï±È.ÂUv™gTŒ7:]§p©êRA²LÎs*5&?pÈßË=³êG1 1×A`)t·ªÃ«ýDÿbe—)yßã§K¯TÒ¤G>ä'%ȶ¸¬zŽ×.ÙÞ [¤;vÿRf.¬xìºå‡ó=RÂ/)X) T2±}\ ©R’ö.oûR¬þÄ[/[E‚q‚V[¢î{lbÉA×¶ôÔ•¨0D«-KrK€¶±þ(S¾XëÞ¡‹xO§ûU´¨ÀÚЄ–­Nùê†t)g2’×hÊšï­b$á€Ì"gJLṞƒÉOʃ®‹hµA½JRBOrnbYAä¥êLâëŰ|Dû¦’";0f3§:n/wng L{Sù–—˜j/šå1¦a1Væ‡h_þ”t3BÄe«w„J-]‚ÀÀúy4xõÂʽI+W¹r'/.U“ð«´ÿSéoX°AšcQßÚt.üfy’×ßa#¦@-NoMâ ýî¿4ãåµÝùÒ¢ƒô‡Ûw9þyÌúZÛS4 GX¦:Œ8'èÈúméxë¥ã…îܪaïÿkcÂ+rCº6Jæ5q#.ÞŽ UÞV7‚z‹¿Á^#™¦®ÍxË×ôàoízóü‰·TC'ý$SÓæ`Øâ–J‹–èÞi¤K+ð¢ÀžÆh_'UqÑj}wçÖÎ/M6eíE»ñ(‘WôÉèN"@UÈ·_ä»î*,Ç£JÚ¥—|ˆ ÊÔ[´u^Ï„¢Ò(¹àXuÑ®)N]Ì ²ã„ž†žz™É!0úºº±©šè3ƒ <Γ©f&'0œ£Wë…œb}<%~ÕßÒ•’\Ä”¡oxÁþEI.âÒ0ê\ÿJr‹^DÇ ¤®xëç<Ôâ2ã5aˆhçˆ|:H-µo3XiI )ñKÄeÑ´VùÅ =/ÜÄCoUŒô›³tÞïɶôàå>fÆÜþ–K5 ·âÇ”õ—ä¢3ͼ-ÔM/^ú<¡ˆ•p¬„|á—Òv»YWÂI2“—gv>§{Dƒ­&Ýg„xE˜mGqL4Ýs¦ñbì—™`â%•Ž‚ßè¯úSu?*ѸÓÿ*UqoòxáÀßD+¥‚AÜ+™%ÊÓ $†ÙÜàÎKÕ]®«°)×"‡Êt®–(=à¥r™ªÉo²QXXÄû>J h¦ºÛOCž€,¡}{Ê3 Ó*¸Yè*8V˜±ÒŽS*^`g¨ñ‡žgØ{™fÖ åÄl‹@¡/OGþ<’Ý­m4ÕU¦rœ¸¾0üõ½Œ“ý–iŠí/mùHÛZŸdŒ±ÒùñÎ¥ÉU½<ÈöšYE<>¸rÑA« \Éççú6eDkbAbHNïZZ1áw„-…[Ê×ó»®êPEÌå|õX©£ ·<¨_Amý#Öhƒ¿÷Ñ͸D{(¯åR•ÛPºE`éñгŽsNtJtZ# Ã]ñ\¤ÌŽ=`(2‘BðøEºV[ltŸõÈ)Óq…×jy^ÃvdXŒýf$M††êLƒŸÆ"øÁJ¹oT­vð ‰P®cW<·y°dV‰'( j7†×°"Ó}ÉF‹¾hrÝut_ñŒdOUK|±Q¦UO»­ ŒVÙ ÅQ7 Lr†mã;Áó[Ï'—£XÏ ¼…•"L&#XgóF4º¢î‘{Göý9T)û@ƒË¡pT}ƒ w±Ë™2U4γÈ&âFHC17Z’›wà2ÚtW :ÅÎÇÚã^­–Àx!«-… w4"Ç¢Ÿ‹1*-Ìçß”#.eÀƒ¢•»æ¡Ë ^(Êô“ï=jz°Ì¦¬a»å~ ÊM—ÆBUD¾â|ûw ç {ûÓ9 J!¤¤¢}L¾Þ§èÌ ´ËíÇðqk¦€I]Ì™}ë½lb®`ŒúžFʼnDÝ>0A_ Î/.½"Úô4wjÏæ^ …z©Åd2iRscÔÛ2/-•ŽÇ{ÌÄÜìALÅ™½§¢Øy]ü?o ³£Lñ¡ŸÀ]æòÒârµMMÛgN/Ì.>C‰š›_ÑâXp‹…¿»ùÂßÝ|áï.‡|‘g—ŒÖ癢[\(|5ÀÍ·x:‡FZø0öîôÔòÞëþ<_èíw¨M-· ¼˜Ï6TDB—¥|F–"òŠæíªOÝœ]¹ÉÊÜÑ( ýBήŠH¦˜³«f]Î÷®Šp2É9*·VZW,·¹»š~û'¥õ°2rîbUÞk¥uU/àpét>ós§ˆ]œ¯+Q bW{pïÝì`=å0$-œÊß\‹øÀ“ÛýÕåvGXÌ·òRå8?¼ðá{Âe'ÏØò©|gL×ZÒ²Aµ¥üqx^×ö°¼K =Á]ÉžŸΜZÈë‡`ˆñ,®³Õî~pªSãøW99àd˜LNM®‰ÐjKéS±2qRx¬ÆÅ~ ßCGÙÄyS:ü±<²¯¤^©®WR–xËfzq.Ñ«ÔêÀƒuÕEH1ùhx‚WéÒ~ ˜2pç‹[ôí¥IrÊ»¶_ ÏƒI…z{ç“æõt>Ú¯¦'¼u¿R0§<›¥.Ìó°QÏ{«f×â²lù°$Kªt-Zv‘³ÄæÆëSyDw;–ØæO½‚ûÅÁbzâ¹?>L0—‰#þ>ûÇóǵGÿXá=<Ù4p~p¼»)* <ª ‚ß#/µ'dÁ޽£Ç‡Ï©¥¦cJDhé3 cuê«K!,8éWà<1à\X0Äð¬#’ª¶®G>H¥ŠÚ©jp®—T¶%_¨2wʦ¤PFdrº#?»R–1Õ•)YB¯»Ñõ×ÃJÂi‡º¾Ò¶Yaº<´=›ª‡žt¦šmÙËGI«û[€ž Þò±€D…°£!ln·¬}!¬וUÕ ÀÐ1À°"Ö(ˆ¡Ý>ƵܶP†’k {èÛ§,ϧ ú;&чï¨åAL Lxœ|Çr¼¦ªƒ†uã YpûÁî@8¡@aÇUEŽðgŃ/OÆ¥"eê–i¯žT“ åÚ ý ?ÑRS®l[‹ÚÍÇAw* îW$U.m­œÝ îƒÂˆÉ‡÷×ÝÝñž(ª«îC÷(a>ÍòXAæKóö 쳩ì%õ÷'ö[…/×#/S/(ȾïWUóTÎŒ¹-]§+kz ÄTyo@Ì €-ƒ:ÆŽï{®Îÿ5c­Ô}Dà89¨vœ¢q:ô¦Aõ“Àȯ®“‘J²kÕʼnMw©XµóñjÝsפÒ Ô;&d –Š‘ès/¾|SwÃzðÈS°5‡24ÒiÙsДƒYU¤c[€Î<Ø}êþ壚±®–ƒ2ý¡õÐ …b*•x›v¦ÅtCÀExS B4^ÃZ(9ù–¦¡#€sid 4.V5åê,+°5Ñ&‹ÚI`]ƒ @³•…ÏÒÑç æä]¼ 3c­FÝ3ÖÛʱAÙQ¸ßÙñ½&¨6mm³ï¹q³ï“[j¾ˆ SÄiu›0O¦!¦Ñ}îÓ5þADÞRiMùú.QÙ…0t+T _ß§ß•‹* Ñ3ß,܃åç÷1ò àcí Ÿ÷6I‚Cªëqùw¹ÆÅË ˆç#­O3ÖoRmÀè}¸(nræîX´æmÆ`åj´’´ƒ¿!Ó=À¿N±'Tûð)K¥ iĵ…ðmföÔÓrÉHêb^ÆFu˜SzyÍà|C&æû)IFóÿ¬„px›äô*ǨÆâ^gR'™­îK[Rõ WØÞ®bI”Þíƒå7L6oÑÿ—¾Óû|®WQæ°Vh£ûvÀ¢ÁAŠ•|1ƒ8OÜXZqκÊlÓl€œf¬²ô[ r'ó«ì“h7ˆsÉ·fÄiþ<±ö‚ª+kÁaåæ§”›_wƒˆ¼ë¤}¹ \Ž“[•¦@#CWmâ®AâVª3zÅ”Yµ ëüÙË+ »×u6¬Þ¿D<üo>¸ÄOä–*oÖen/Ïçº+˜L¦šTƒŒÜ88y܆ z ÇT=Šîo\U(IÓ!#Þ} ð—­Úݯ It‡YæÑ®%5 ò€>ÿ&Q¯“ìÐ@S^•ŠùqÂö<ß ñ‚»*À4Î a:i~Xg[!Ü5´L¬pðˆ¹2sC-¤’ˆ6‰Ìï›r¶œ²œ¸ÿcÍ}ãZŽåÕ“ž·K}¼DIáIÒâ=`õx Zd¸Ñi"ïÆÞ_g×-"UOá˽2cÏ⺿)IËM­za·•Nc/ˆO/x\Ô’ön€ãÚ¯cR;”«Ì"ÇÃ\ÒÍ0åýÃȳ†Þ¢6ܳfö,lƒz £±ÈjØ}n†Öº‚…«/g.¸‘O­ÄÁF UÓüSÅ÷òñ½3Ê÷ˆÙuë-Ï¿èx…p¼üFræx‚z7Œ/£»ž ¬s-*ë°¨Š‹ºÍmÓÊøø-À߀5T3ò…-4µçPÊ>'üîWÅÒ››aÜ-€Ýàï& "ÅÃXÍÕlÌL°ƒùäWc5wRÙϹù Ìà—Tƒ8Ê'¶4H=Í(¦È¥¶è²¹}‹ž}ŽÊßç&ìÊe"Xè–:ì÷òÐShaÕÍÂBí­TUê§zYE°ˆ0Š™ð›)æ@".¤¿ÃãXéG_…í¯€íXøcÌù&è$p|‰ƒâƒÈIHD§åf—Èg½’ ‹ãžETIM:M_tàÕŠ5Y·@£^ÒE)“eó¼\ç‚cÎ@aŽÈJ_„ƒªª¤@cu¢ÒL:Àx< N;aBg,CüätâÃ"W¬©¦Àº×0-ü0˜²ê-Ñ õIÒIáµWxÀæ«Øelðç²H…8³J:æYlD¶à0î”M\àˆeSø¤¼£= -qÔ¢Ã{9°6NzìÇí¡™ŠM^…žIç¬X5„ßpÈ3èæ-LërS5[RÙ¤èphäB\1ƒ<ñx m‹ÕU騫hÅo|ñÛ—>·=ò¶q¤;eµ<¯a£ïíª¤HQŽV ñ<Ê7ò³Ä¥tÖÎj',.›lwï UìÜèE:!VMÅ2<¥CŸž ¹lmÿ‘b™¿¥Xf>ÂäwCŽÛ^pD5wm" ÁŒOªn©÷QÂ_§,Ýå] ”{¢ÙJåä£ Š{ºâà€:Ðãc²&ñH׊¡ž}¼–+­ŸI8Ð ×}íÁVƽ¼Ž•UJÊŠR‰!»‹!ñ^w)ÜGÚWTP®Xÿ9~ÀB<Ï\SA$'Ï[ ,G­â–rÐ/¥é{lO²_3°™¼ìF¼#àcìBöÔ>„Šø`Š„.¢?¤ƒ&(®³ë,, µŒ@à£ð Jà° x„ƒ÷ŽU<à4,çs©p™7Õ¤ÁܺêFN¡8À¡$%HJÜK—Ð ð5¼`ƒTA›²æGjUT¡h,è)v¦x}¢Y|6DI¦à)Ëóí?ï{‘©|?óÙ¾4þÔ(M—Ý£‰¡> ˆƒÞeN;\Œ@ÅžÀêøÏííg©VÆYH‰vÅn[¡•Ù x2KdÖ -tïÀÓu<ÛÕ£üÝ0˜oþTŽŽ 2¡€>¦[tíÀŠÚ +q”’u6jlv¿n9À;O"ÖšEÁ&ÆQ$4ŸüÐ5wÍó9ÄàuéV,sB|:e^=L “gYÚG—sÂ%ùi  {>A™’rWÜ´`nºE÷ _'i6öÍb9Gýád±ÙMsymÌWy» ÓÕ¼ùjÅU‹åª‹³ÊU©BWqüt™X,ômŒ„{4vøÓ¸ì™÷å®êîR%¯8xÛ!La¡˜¯ƒ,Ja£5º&ñ¬DÂäÚv1AÚ9«›Å1l&@Û›ð"-_ômÒéE€§–Ê­ûQ€ÆË±èôe=P)“ I<éð¶)Kê*>Ù¨·Mé4ÆLGR2rd[ít3ôA´ ½–ÂÃö âEC û1ð7'ó»ô´»(,-ÿ>B¿©âf„¹—εýhp)-r5} S¨$ÑâT$$ö:¥IÐ*?j›7&KÁmàe·5y‘ÅÁó;ž_êNˆã³Q5kcÙ*ÙN¤XF«n÷y§AYC:ËOÀŠªšxäÅ–¹eGĈ~¦Â–…gqDW›8<ø€ž Ôš´^£Ø@¸q>¡úu<Øê»]ºA„5d@ΧµbÏë5¹ÁùIÂ43•ճĚP™bGzø´Þ€V—¾Kij+é8îT™ÓÔX=˜í÷Ñzfè¦æº;àHŠÞE%Éfjè+ô…P¡I²\8íšB·u[Ï¥ )‚ÃM€Ix.|`݋؈w”_18 Êšçù›ÄÈ´ ñ”ȆõýJ®lÒ= R~¯I:2¼±mÁ\^ô oS®¢ÔÄËSùÓToH»ç­r£jµ† ˆ4«æ`I›=³­ò KSÃ$W¦Õ¢s¥æ{ å Âæ´?ÖåÐQ0ÊJaPzOlè ÌD¢À3²Ø`ȽNù–-ak½¶ýµ‰Ý´0èߘsR€þgÛ÷a±A(O{:©ÝöáëQÙùUl'b÷…ÇìÎð˜2Í}FÙp e³ÉÄðÄA4:Qkv¼)a‡;ý– ’ èqQCIs0nçÛw~Ž GãGqŽ~ K ì.a&“¾m?Oš fš,è™4wÅLÇäD¨D Ä,‚á²»Õ½Wˆ¡ÄsºI¦,cª"÷˵bÍäË&)‡¸œ_…Åw“ŠE=÷âîǨ ç?NAA`5]¹e˜"Nlh€-³Êž¾Š˜‰O_ƒ–³Ì£ÐÿärÂ’¥;e±–_oQB]MÅæÐG;ÔaSÖfÔì~í6¬ÆMãß& ­Îs&AŠÄ¼È‘#Æ$F6¸÷qÉ‘¦ûI$¯Ø,™¾1íÄ4 & 'Ež vŠîž¢ "¡µ)9™í^Òd°ß¢Ì®éÚŽ[¸0@hhUºvѲf9—cñΔe2!Oq2z6.šØ_… JHnzª«*r!F ¤ºo*{hiìÙö}öH6ºB£íû82 ÿ¦§Æ y×¾¦tA©½‹R²(ÛõÝ™â‘åIe\†ÉÃLSL1ƒ<„³ÚfÍž…àc°ÓáG”ÚRØ3c½'xZtï¹6 i„9"Ó^ ’¦LbD îF‹õuÖÀ!0½cÍgõfêå7»÷ Pf<7. ×÷ ÍÁfüxÑÕ>m–›“ž…8n¹MdXØrxÝBQ–íU*äœd¶Â†#{˜y>-B`È2ȘLJ«òQ¡cÓ ®ü¤q6eÁÓ˜¦x$ÜÐ&í[2 PÓ†–8w üü¶/”SL&Ëܦ-–.’Ðgé  ¶_ +¡c Gh¶#9Q™jtïÕ•£³ÚG°}¥ã4V}Å`jœ:G÷†éÌ‚=Å&-œ2×̧ÍF»V¦ç~B \Ô¦ˆnr]ü€Òs±ŽûÂa\~kD¸Ýî2Eÿíßeä¶ÚdSøS,ÔC]°Ôó#øÌaL[,7=Cqd*±õìÜñæ)ÈÏàÞ/S¤wIߟL^$™Ò¶¨ð%ÊKI3øOŠ`²œmå¡EžÇTuIùØ 0õ°ÿHr˜®X¶¸~vmnïí¾Ùð%°´ —hdçŃÈ5e1F6„2©Ý Ft \0e›ÏØhäÁƒ}é„2Ѻ0 ¨>£WŽO¸• dÓG=@¾µ-¦Îô«süI0”¿ï‘ü ‹¥–j+7Õ7èü³¥´-„lã(eÁŸS½÷”e ì,r àÿ8à uÑEuK°^¨VW­ÕîŸ\¬ÎÍ5ºW°Z&J+~To‘º‹QƒX0Óu³Ç\b³)ÜMKD }&A#âäáíÔ/{Áëê)‹tf¸…O=Úæ¬ÂW™³ ­Íu©ô€ªsŠ|çK+)ªæ5l«€—‘¯µD8İ}éc½1·ii'|_6¼^¯ pi˜ðþ"r/|C;Ÿˆ$0´–„›¾ç¡íɲ…Y/s¨nޏÝLò‚þƒï cã}<59•¦€¯g;_›Æ„6ß—x‹úË©3g×Ú<«åâ±ùXG½ÓQø-àÏŸÑa÷ƒòøÚ…7m¿í)Z¬Â‚*œ&±š¶pÑÄ™ø ã‰R`§M&:jÆ”u©#èS®´ðH 6–[&îA|1X—˜q¾ÿ(ž®SňOØÙò9AŸÞ–Ž·>üÆZæœbDaиCy=õ#ê&FÜÜ'jÞåID gìoI§0–Oa "U½?…ñ zÀ¯6f ’ì×’Öºp‰) &Ÿ²! ¿ÛªêXª Ò&³ q®©úlAŸ“z6`Ç^? ÎIV S7ãä±Cp“Ðpnb5" 0E©N[N?c±¦ñµ© ÀC:›VQ#¥é¨Á¢ 1í¸Ð-“¦Ç3ê)°™[;¿ÔzÝÐèŽNþCTPqâÊ‹ñÝqãøà]Ô°vioÐ ¥){Ä)]2^YS\ à:<¼›º+fqÀMHϵj"pÌäà’ÕÛo·ïÑÝ·S©a8ÇÍÝÝ‚0þfç `µOÊL ¿-Øú%j âr•rûò¬@…&“Ð7^Í—‡1f¼âfdg\¾ô`U±—áNq†™ {OÉ‹ȸÆ%ú`9©È ¼AØ(JÅ{ëGzn(ççM³}±ž¹³éÃÒ¯ØãtúÒp%Xk¾±®ì°õ批™¹Å¹åò r5[á›'fgNÍÎÍ›_oÂmgfçN/™_6 ΜY˜=…¿PG˜§;hmÓðÈôìÌüâìü6°“¥3‹Øä[?²ëoP@¬ç¿unåG'S_ñ’ üó­y hznnzöÔµÙÙ7èÿéFº¨×D¿…ëƒ9³`†XÀ@B…˜³ä4b šl ¼aÅlX"X©~â[÷ã1õ½šJ¨ÙM¨9à܉×ÝÄí ȨQÙ5Ý)r?:Á@ù½é‹NËd¨I;Ì­z Ý‹㯠ò…h40÷qÇ÷ÜÈE§9ÜüÀß)³NM¦Z³¨¢‰1ý.wø¼ Hv°yíÑÒ)Ížv×Ó?÷D¦ë@Bº•¢ KM£låµu–› p¾/^ì—qÆ›±V$ÌP]/i?=vü¯cl9BÄÍê°“‰‡ §]{žHfŸ3‹qz òlQ>gmæÙbžDÑË4Ÿu¥Ù˜Âs¥ bN%’‡ßÖÛiÞĆ~E”é!T$ALšCç&DB)⤎±‡:‚ g]ÝØTM,èÿº^:òè£ ß^³Ïï.RaÐñ…X=à:Z*ŽûᎲôÁD¸/ÕþÝøŸ‘Û§,üá™Ä}–K³gÜ àéÀ]ʱCÂ_o†ÅŒžq·K$È}-ÕS6La—Ÿ TGA3$>¢d:±ˆù8Ž×™ïòW”†‰ ž2ëËóN’(g²™Îîq lÇ8çÝ\oTÛ ^ –×yƒbÖé@Èì]ÝJQ@š;…w xgÿê~ÕÔ8êÒ«»Á¥7-c¨LA0ž6dÝ¥ûthJŸ4„f‘SïBð÷ÀKY(ßÚCD:ü €66òŠ·~Îs1SS¹É­ëºSœðì@]ÔW§Iªix~Ó÷Ф‰~z¢£ä„é ×Ñe$öÙ¢8–”tc  ¢(–9m@Ù+c’£“¿Ú´°¦P¾*U”2D£§¦û%‘¬÷]ÃC¥v6jîí€8KmL4¡0c7BkZÅœþ€‚ž èë„ßdù0YÆRwôÓg=~4¨óxÀµÑ!ìrraHœÿ1{¾"ÛÖEx`Õt›‡ª3­ÝÍ?‹Ÿ÷.”¶ÎVxé£ýÆ =úœN¡tPI Ñé8x:¾¾6%gYÀXA¶ ”¨Ä_!ÓŠIo5U’㣘¨00…&D“ãÔM * pŒXô6ƒÁLžZàñ±ÅO2õ”ˆ "ï´ZªçЦ¬y^ˆ¹+%,ðl*„¡c“ððaòVÂ㪎Ք랫3ûN&¯åˆ·øÜç%:û}®µù§¤åÜä¿ó L§kT½äˆ¹Ïè‘ç  ÿ vô±•IÛ·UŸ¡ÊÌnƒäÓøTg†{1¸àByloÐ:Vä;ØPÍîSÌþŠ©§W±O Uu´7^ȉkÍ".zç:ºÝ”Š˜Ólø“õ—þ­b' ¦þM°m½Tž‚¡:qÃô>cÅ„X\¨pbrOkU¶æS’}ÄÏÇÔ>¨ÑK²c‡š¬ Jñܰš¢ƒ©å!꿆•µ1~à†”E^¾ëÇh§G2|¶Fé`cT|-õ«Ö31%-›‘Â(IaM¹íyJ8?#*¶½ê(l~œ:\Íè†Ä4ö¯édújQ¸î½nôeŠfpDÍ/Ó ëº ›r-râ´ó¨>îe¬^Žd'öIz7DW.ØÄ$˜!Ê5*ñºÇ}ä´^; ô±°®BxKèbŒqm]îi]…~¤Úáaˆ6˜¡žÂʵªú 9.UþÑQOÐ#8¥N¿Šë¯ãûØøÎ÷¡Æ“azêStá4@ƒlÐ/L9¤Й)?¤…6?ÖI“uN÷ÑöŸ)bUiöeaixÁÁÚº½ýgÔÒõågÐÛŸá÷_–™ºþj-n¦Ñâjú+—ðiÄ(á¥A¢#d¯‚ ÿÔ&¼<ðêMXÔ>F¡T(ö`™‡Þº|ÀZà HqN¹,›*ºè>²)ãàÅäè yˆ²è ¹;ù¬HéŒEëSù!¶äry°h‹î‰ÊFás{ŽÞ=«ƒcs‘-ã}hµ£ «#a“ÁóåfÑC¾HŽò!ÅH¿‰Ö[åÎXï:¸’pÎÁœq25¾¯ÙÚy0úåÏþ$¥“aÈ€ã3Þ䕨ÁݸÌÝËaö¨Ä}¼ó…)‚ÿ€€JÍ (hœ‡“”ÊÌz5Àîöžpz‘ÅaŽñ-#(­X—؆æ ü3ŽFÏrc·´^Øô»êþNÆ1\mël-á&FÀ¬Fm2ñÓ×; 2OædL\– ´‡VAŒi„8© ë%£ÝÑ{Õ@b[’¼Ìf¬·Í¯h÷§†Aâò˜¨Çǰy} ™9ç [^ 8±œËÞª(UXŠ+@=ôÍ×Ξ?ÿúD:ÙŸG+­~áªN† l„?áIœ¾¶.ýUtуMÊ­Oì@ÕQÍ´§|öDÏÔ¥ƒÁáS4–ÊÉ“þ¹öbÇ?Ϲz+ OŒæÌésÒz¸f©©äEzÚ ïÅAì®óG<„¿÷Y©žôÏ:ú4ôEŸÑÀ§éSìþþ)%XýÔèU)o#tsÿ¹§&—ù{<ì™Ç’”DkßÅl`±;=’û<™T‘÷~®Ó|‘ÛÏΖ6Æ’KV†‚2£­)*M3E#À¡!$QÑÀãâÉ¡Îà….=ìNïeí¨è‘½-æ±Ä=;ÈÒ¢ƒÝbßú>¯{>ÿ|ê؉;N2íî½=à.ê%^»vþì;í‘ÜÁpYN büº$ÏqŽn&\¥Ãzº u5¬ð„Ä)Ÿuœs¢Sf>›^öëùYðuëêR\~„Ü¥.©Ï¨‚‹žK’¡AØâ°5h7}ŠXžŠˆÒõýÏKôC6ÉÐä“_:cf£û4¨cM Ú!ÿ¾5ÌCƒ†™@ŠžÒbÆL‹WeñGy÷}F$ Bñ:ý y0{^ÃÖï Ø>_^Ãܧø\[ˆUvrNUæBO!Š‘³Ñœ:ñ§Ž_ïÁæÓÊa*ãHâ©“Êo¹…vE,¬™–!´Sïã”ÏVɹÐ?Ýù~{ÊþÀÚù6Õê$œUbµ¬‘ýTo—Ô6QÉ6ù ³CnŠÞÒRÚL™¶l–¿Cú8#)¥ZAýñ)9¹p”tO^ò½îïjQ½³R“•v:)ÌñŠç6¯ã‰4†uL‹Œ MöágˆATóÅŸgŽÈüœÉc~¿™®},yp0ÔhŽ—=ø«8\?‡ƒõïpAŽ£ÀÖÐÌJ±Âø:ñ /³®ë_ðvŽ-ƬV~÷ëz+TM®GÏüUYT¢‰Š÷½:ﻂ|RŸ Ƨˆ µyFoE~ ÖÄ‘à|JG6€¥Ù~„6žãÈ?Ò± hñD³éߦÙÅËÿðó=`r«4š™ä#& •ó×]ñ³<üì€O/´;áÆ5:ò¢’Ž]ª# uk5°_v…‘Öy ÷• •¤ðJ‰TÎÀÒ çm¡‚ >œ$ß~³RD¡×äHèl€üØlÂŽB—mîÅ£„^–¼ÙaÇWׯy^!ýó‡UŠvdz®uï…‘ÃæNÐ`•´Ÿa8ñ,PXõî=t:HÆ;Hm öµá6)ž †-}åsL•˜ÂYé~…ÓBŽíºcºp©šïéIAÿQvÒŒ\Ã7øƒŸG^øCXÒáœuÛ’ª)]¬VGEœÐ/™f4©0\6ÓkCŸ§¢ü¬ÛöÚñê0•¬ŽÇĪQ¹z˜¤˜ÍHAÜÍÆtÍ“­’aÁ˜ôà`j/ÓYÊn³)Öâ³É/(«ƒNq°›eö.ùŒ>AÝ4YqÃOh·2‡¼ 1†g§(ÜÒÝèDØôœ>çÜ2Q%©dh¦Êä-ö+ú3e¢HŽw·ÿ—ÿH‰®_–Ÿ#w¬˜ÔfÎld/(Éû¸&Œ®Ìlä`Ð&¾I›8A4>õìÝ¿žÞ¾:óˆÙÄ%rÀ®‹¸ÁþòÑoiçþå£âmëZ̾mpÁ´¤6R@ê0Jíé‰HÎGÉe‰ÛÚú´”ZçÔ XݎǪ°\-ïÐwºòÑR ÛØßŒ [G4«œÏ“áe‹±–¥¦D5jöÄ ÃS_QŒ£VÑ‹@W$/$/BŸ'Á4¿Sßcˆj 0TE“-Éïò Py PKª9bÅ#ð¥¾0%7•ËÏcæÌÕ*X)¦¼î>&k¢ê˜K@vPöé:…Ä4T´yûkø³|Isv­<#–‰ß;¾‡¢ –#Þõ:üaB£Æ‹˜tJ:4#æ²1UpÆ©‹^p¥@¼ˆ‰‘™R‹n™âtFÃx9©æ··Ÿ i¨L¯#ã`Ë›ÀôžM€©|LÅ?,‰Åi°“@%i#Ä·Ua“ÂþlÎÏó±D ÙÇ ðWN§8©ì6‚ Å.œ/O.@êD8€ ˜+9Å`ç @'3ÌÆ¬}O¸”Ϩ, ë ËZÚËÉc´òwEÿâÿQþü•–f÷U¥þ¹h¬ܰ˜ÛØÈg:×.RÔÔ)7È@ˆ—~ :^ðÃÀêD>|SVàáaZüV09Úv+ÐðS®›Eèë?¹bòûÖ=Êáëc~`µ¥pèFä0uEÏ-ç_“ù&Ó„Ðéô®L­IíZ“”dEk^ªÂ[줓y„îǯ’"ì …þꩳ±š zkP3Xò‘Ìw*ü”Q ç󄆦  }Ý&†“¦Ðá6 ;ba®_5pßKŠ©6†¾ÛpéJ©úœÍy:E+†7<ÐLÁäæ§Sµ¸¸ÀÀç§’â9ÈHþ"ß¹·3 Î@® Ƙ·eNöàê·Ø†¹/®PD¦£å‘Ø “sTSlbÌæ:M’‘ZžåÕnÊz¨Ö¨”€¹m .çEåR^NÆ:ø@Рül€@6#E…t ”R —,6BÕ6R“h­k²êŽðu´z!Á…ËrµÓ¯ÊÕz”‹S{ÛÞ–î¹ýk>½#À’®©þ–—aÆòòÈDÅ3·´¼"¸Çtœ9½0»´Ë| ¥jnv~ñ•È*²Ëºpê¸`çÙ EáL³ÌìvÑ2—Bá7e8ícÒòiaÛ¾ ‚7Oœ¿°rî'—?¸vùêû+3gçÞÈ~_^Zš;ce~»ÒsÏåŸÍeo8?Ÿ½áâböú…¥žë§zžï¹~þtöúÛ=ퟛë¹áüéžzo¸2ß;„Åùž>æÎôb¡§ÅÅÞFMÖâB_W= ]êíêRo#—{füÝž ¿Ü3œw{Gs¹—Öwz¹—Ôw{)}{®—Оë½Ý\ÐÍ¥Þn.QÕï¾õ/[J9˜©ÿrá&l¤ÏÁi…8ÿá܇ ©˜'ˆ‹¾yâMÖ¦ùorµ&Þ‰C÷m¿áª¨Ívi¾w:{–é¥ùÙÞ©šõ©š/nª.Íï9U»\ ² —Jƒ’4ˆ•ë—.]X¡.O ÚP,$%…°é€Tñ7âsIè¯í˜ RžÐiª@–RMwºíÙÒ\îå]Ѓ˜¡7kÚ¶lˆÈ yªz˜k?7Ü¥Åù-./ŒÒâBá-NãéÂI\,¼Å¥ô.‚Ôlù¢¶W§çùBo¿Ã¤ ÜŽaK ¹ô U€÷×R¾”¬Ò-¯«‚xsvå:¥uÕðË›ÀòFÕ,¯+»€Ã§¥½õÓùÅüÚóò™(rzÿZÓülnÀÈg Ô>–hÛ½ðá{Âe?Ò"öÛéœUãS¦ åEf2¥Â¯xpçHöüœ±.70ý)¥Û®{íšrɳC®IÌ´bZÀŠjèDjžmP1zc‹±‚Ž£ÂКŋ|?zèÓ·¦~ÒmQ—xÅó­6–'BããQM_}ÍÇúŠ© ·mLœC_Ÿ‚/þ*þÚæŒ9x}E?ZرäR¾ÃÜL[ÂJíÞÃÌÈ.»¦žã?µkEYkóñÔcÉMÌí…‚L”<Õ<(üzK­yS)3˜­ÖÈŒ&sU?`¾aò¸5ê:°<ŽÑ”pÚrœmó+­%#yMPiªã†VùzKŸ|'ñ»ƒ©¨«Žp^O•'~|Æu ¸;9x]‰;,ïýdŠŠlÂÊß5{+ˆø\:d´bhÝ;Ý;膴*ã3›ûyJ9ÛŒe€|¶dbÀ/ƒ¶åYô®¡q×µ­¶”%Gk@Ïæ(ýâ¼¢ßæš'›á(MÑ©6…òù/Kg5yõrÄižOÖbéqýbxaxýÍ4­$BÊŒ—÷(MP¬±n‡ËäŒò4⬤T®xÆ„1wÞêh ˜J…g„QZ`cÁÕxü½àÈ€%yå’œ°³ý >”I6Éuùb׆^ïkû`Bãø@ þ’Gû9`º¬»ºà_O?[:»å=sõ1õñ`ûåŸw=ÚùŒÏ{]&¨°á§º }6•<=´Y‰Ö3Úxüž‰Ý'x]ƒðSòÁÇo/ùM¿è:ˆÙÙë‰!§ÇŸÄϼ–*>ÎÑoÛÜùöš©—¾¤‹éøà_äÒñ1µñ1MÀ½äh/‰ ƒg?ãd¢ÄnZ((ór¾#ºa" ݧ®ª§E#ç =¨4XJÔpQÐè>¡­ÞB_üDб áÅWéöøK¯œAùÀ_9,o¨ áz=RÖK¢ãA_¢ó ÞÞ2ÆÏ#I2ÆAÊ{ê3»áÆé-ù ûÐ[’¸Ò4ÐÐu;ÖÑiÚ#}@B]¯Ù®Õ¢pŠ¢×”‹Œ¹Z‰çb€›ô×$d-ªA€®Š5oë6‹zaˆ7¶0·bÅLãçHµ $<¥ƒ­¾×¦GiD°e|¯3m{ë®å`´ÅF93&á)‘s¢H’÷GÁ%µœñ¼^¹µ0˜[A‰£÷)Ú³ò̵[BÓ æOÇÁÑ¢jâûª&Òò¾/…£'°®P¥ãézÛóýx==…xJ/hº¨rjÇ‘Mº®F­ €tGµ»÷\‰@UÞ‚cÑŒd *.ÈLâ;,6ô͡„°è:×]Àظº/»ÿáK¢V1%"-Ÿ|Ú(úäd"öpéàÊ™vÔ ÌÜnġГ\L)+ÛL–<ÓËʹ°Á\Ù„Ù}b\m8Â-q¸¡ÂOúë šæ²mp±ä»SqÈ›ÉËÍ‘x‘WSšÑ?~¬96Åß=§ZÅ=ÑršXvä¿‹ñò=RÑ»Å-sšQ¾¦‰š2!T¯¤#~WÛ¿¡8}¤î~¯wêò(}¬WC¯BýÜ%Ùå!ç{ã ¿b¿N‡ªKMÿ"–ÇÊ3V21v:Z/Uôx7Ä‘.zç$˜sScN”‚™œÍq¼ýNm|Ùì~U“Nn¢o޲|0àòAaák9-›D½¡¹RÚXa˜rm£MP¹¼ÔšŒóo‡-9oÑÛ¶F¡ñXµ®£ê”+†ÝXuné"]X8=,1g„XSX£‡ŠOH4ªaABÝ{0c]¤õN: ŽžŠf͈þÂZL ¼\_dYe±Â@(ñ%ûàʬ±4‡’ÆIDúê~$hɰÚÕÉñˆ2ç„-ÒQ{¦è¹~&üëÇ$ï—‹¦ë×Ê‚‰lëZç-5&Iލšr°AaeÊ"ÃÛ9•šZ`y;B§˜|¿2ROPäBB(ÁUâé[l;Ÿ7ÛÂEc-Ò¿zˆ¤yõ‚rôjÓ“’CÂKîÖ«`o©ÌÁwß}šÆ“0݇¾_®vÁYåÈÆ¶‡%£=_›ŠÐÔ³.ý»*ûêÆ \,¡p‹l'ë¦t=Ly°—ýñí¤5›úíŒhsÅ¢»&ý&¬ÍÕUrç–lÀ¥‚!r‘Ån9‡ÖYÏßôЩ›üËG{ÔvG™—ë’Ž?ݬ¦Ng „#šjÙøu¢™Åô‘¬Ùès?ŠY&jÓ³ÅHVlÜm£Ü¯A"òãh®ýèSñ£D­œ\“ùo@úv—¸í>ã¹1&ÇFt“tåé„/µyü „¿HnX#¾Ê:×g©B‚ß‚ÖG9Ýî[¦¤¯IåmcªácB$›±‡F‡¡Kòpû>ôñrçK­û½0Éݶ@w~Lõ‰ã2rïáíY¿ÑxßIE•klô·ÁÅ û3Ö|Jj)iõéc‚'Cšá¡jãù=.ôHvw,•…4¥â6·¨4×ÓÑÎ/é}|©‡ÉzP'~‰ùõL¤ÌñÃømÁÉÃs¦œÔ~œÐÁ j[…þÀg 5¤¦ÍøZôI?Ü?W£d(¢hXN› îIž¬ÜîYËŒd„uOËê ëÉê—S²:(üÂAeJ ×£´¼÷?X\OÈë“Ö±DJü0°G ™EQ]õËêZTgIÝë;éȤ[`Ûˆ`±¬ž~ ·IÃëÖåIœ ’Ö++Æ>­Z_YUÒŒçZ¢Rô§Ö鵓V¼äv7 Pij´@4ÈFkÒ PF³< ´¥‚ÓS°ØŒi‚î°æL/ødMê\i£I£÷Þ<\ta”¯°.xAæ $«ÁúsÃlj +{Á5,eFy%¬5àÉ‹/Eà¹õÖùœâÚi8KIÃèÓåÙ&êX?ÖI²êÙèé³i¡©h©Çîh­4ñE”–Í)¾\é·ÔEG2Í)­›¼o4 ·X¨øÂÁû\C‘Xùß·Ÿª¥Õ´}:¥›áÍ»©³a„ µ´ùÜvÈC |T´Ë¼ÈXA`¤A‰OظæTzLC¬šJú€ŒØ¬/6óý†ÑÏO¡œŠ«cqéTê§{'½6"4Oå•‹Âó¦EBÈ$uïðKÁåÒTlºÑ3?¶•¶rÞeåÍ t.eõ«T:ÌjMÖ‰~•M GëŒHD!†‡“%"pÈé=I8‚›TWŸ"ý.VÆç4ãi‹&¬O¡ucÉmÓU6Ï<² šù}‘?¡áfÓCw¬D¥ÄÒó0 ¬öŠb¯æß”«f}Fo%T¸‘ ›[ÆS©ª'¬Z¯éºµSºòCÊÌÌ ¬ôgÅ‘’òg3¤ s^M¸ØK‚ »Â¥¢­0úN=»“yD÷;”‡ŠáÙZB¬ñôy# ‘Âcõ#—×N׎E9äý!¥žf-‡S\"­tŽL,nô[TîÒá\}:Éàäœó`¨,n4¯@ÿ†úŸËˆö½#LÇÚ³Ô'à¤2„£õ´VÆ ôÞ¹ýtFóQ¢Ÿ°ÃÑFeI™ú$¯^k TbAƧœO@ë+¨—r¡D˜jl‡ç‘U‰×âšÈ¨o~2…T|I pO}dCòëSL(i0=j¤Q]’ï ίjªÝgÎ8‡œ½0Ÿ¼<Ðo±¦Fj'ª‹‰ÚÙ»‚â~†4]žšt6«gì- Ó6,ɉ9@gzß‹ú¤€ŒB’ÜAr€Ð\~ðc æw·›bY´GPYEÌ7UJ€æ5ûVƒÄªè5L $`ŸY MsÐñTÌþ‘Ksü5£]¥j¡ê²{чVJ™Ã¥üÁDù³Òëw·‚z”WD8bõö2Á©ù³¤ìãõ½ï]n3ͶÝr¾LfëETä>;þ•6ô"IjÛPÍÏœ@•ÓKƒ€yó¼C›GÑîÁòÞÁOÉΑ<\4V§·NÒ î¸8O6¸ÄmÃh)”Sß&Þ†)”£¤T†>/öºÏw„ Ì뵋ss¯§Æzø\ 6êe7£Ÿ{-˜‘ÖCÏ5ózx„ß &Wú¯ÏXW )=í—Ž×äcyN‰R‡½»ŠÑ +-ÕÿëŹYËsóL^oyUrxæcƺäa@>~‘ŽåEm ¿¹øküöƒø¥cˆÍTïÄïbÌËoP— 4‡÷üòzåëœã§©Ç§t¹ú®ž·C¤¿sþï¬ì`Ç;`\Ú{Âf™jL㦜ä•Ôë€Ý §gm‘Óµo’ë…‚pg… ]µ¨ž!6æÇ› ÚáÑó©«Ù(¸µ¦Ò3‚®»ØÖ”CwöÞCÚ×Âu‰’쪋»‰ÁƒÎ@Ì‚ uä5Wd ûZI޳}ª³ä·#¬:jÕz Öl¼¿^‡fvºŸ|ÿLÝØÄ#æDî3¯à²0q‘{Íì¬ôP?ßÄ‚Q"}Âz­9ÂÔ‡¼{ó÷Z5uƒ— ÏžZ¡,ïšÂŽmIuöâ=™‘}Í:š±VœˆÊFÆoeÀ0LJöU~w’#XÎZ„'Í·Y¦êË/è̲Çc9z%áx8áEÉÈVfÔÉÿ¸o¶ù¨–.ç›zÀûÖs°ù`ŽÎé¼Z»7li¯h:ç+É)xêýôd÷‡‹‰Ò£Õ 8ùN õ+û—ì+GjþòÓý†‰o±³IýæL¶——»ô2eézݽ&îõ·i_xôÃýãA²³‹êdº°`dºúÍïÉ£ÝèÑýc²´cü7T!õ’ó ßúÕ [ÿÕB‘)&H/èþ}ûMò ·oQ‡)׊H¿{BèWòuæEf¦ÆöÏäé¿Å%_3›)¡nèߌ'†q¢Â[0^\Ϩ¹ïâŽJ|iÐÆ¬q[Û¿aøKüL²Ë€&½H Ù…wõÝIÐÛ³fëT5 ô6lbh+þ¼/ËuÜ87×k OÛßô!é¯Z‘hcv²ÎPú;Æ  Ç…y0ññ¬œa½rͨëÞuFž¿|ôÛ+fͰŒìô—þi†ažò¹è/?ÚEÊù²Î\0®ïÚ=^Ø–ÖÅô‚eéÑ“'Jê › t¿jú¢Aϼ†Þ/HdÍ ©¬ :Þü¸pÉzío>¸ôzœ¶ã22põjüd«¦ QoÎ*š(j ¦Æ.ëÍ=LQ˜ ƒ·èˆú :¬ Ëöí÷>˜².]¾Hv‹k—/^dìQ¤3EâI °ÄÔ¤iœZ%]N ³µ*ø Z—¤ô¬:4¶¹ÂØ"üsEÄg¦—rÌ¢C!W@çâJ5no Ô©šèL»<ÁSIHWA7!VgBŸû„‘PÂmÔ½¶—LñO0@(¥.@ú\Uää./í·ì¦”ÙTœ¢Q“ÒAÏ'4t˜R›4£Ô”’'úÌž!ÞÚ¹="ƒ -îQBÊk@æHå…}Äøh^d…"˨¹QyýÀês"…&€š'Ñè5R\©ž–nhÊ–¡V™w8" º„¬kmzX –ð(Ïãr‡§i½£‰D£Eê{Œ?£,¯q0i+àæÞm:¹±â_÷§í‹7aÀC²Ž’ÙàÑÿßÞ·õÆqdiþ•|$±%®¥i»§{hY²½ëÛ¶e7v{¬ª¨bŠYÕ™•¤È'ßÔn²Ænc1ƒ¶fÑ]@«µ²$Ûzà»ôæ—ìùÎ9™•E²d2EÓ~’X™·Œ\û‡ì-;3¿äHæÛ¼,k6G·vGiSãÑ)Y$¨VjŠ~9vXmÀ CðUúý÷þ©ÐÔá61ûÑ CÓrƒ¯T\Ê«QÒœ—xÌC¿ñ–M†<¿^’¶«UÒ€UÁ@Ì…Åõ ³4Þ%FÚ¤†ø”{޲/°å4î éqÑ9#ÜþوDZŠ•„!ðLÐ4¸Ö8ù§Âös†&“–kØ´ÍÒøª!¥5§La§âFXÜ=› 2ì4®àË|ÆÙ0–AÁåC `ó^dx—íß$ià­à¤?07“™@ £ j·î··Ï¨Y¶£b2­Æ%Ia¶°˜-ƒDy*xr} /HÃðUûÂ6–|劖pí¸ÍÇ+±ÁtéKt^-ur™­d&.i Àâý½x¨öUÕ­Œ9w]U·8Ë´³«Òœ¼ïëiÔÖnÜàêb+5ü—s±T;­ßÑ‹hs²Ýñ~Ð-°€5‰sy ëi![··ðìWÇŒ|>£×®t8‘8¥ãËomH¼#)˜‘ R˜Œ6ÄÙÛÓ‰É7yF¯gmÛ ÖdɃàíf@° FæÈ–36(5ì\Ìüë5#Ÿ*Œ‡ØN®‚âà`;Òþ·…Eü$ÑÇÂ÷+ »ÌÓc³Í1p’½oÓº'K[§Ôý‹‘qªB¹4üÙÜ‚ƒÄc©¦Ö€¬dIô=@¾,gÇ/e.Ö¿½«°¾—jf22;€Çvúm¼?Jeu£r…äÌáðô3„×B+fÏ™p.0+…Ñàå“=wLÎG }À2lµìi~l‹Ç6ž«êÃï·t öÆÇ’Apí´÷Ü‹ Tßþök9|#Oà×– ¢¶'¿``5¶ˆaäºúüÇkÑ?Dªýñ}-²Òkì”Q4Mñ‡4¤˜–˜§ZïaÇ¥"ü¾÷M£”5X¬¸íO•ñx¹×»YÛÃn‚º=Œ?WžÖ@É}à·B‰ƒßáö*ž[ôÖæbû>vÚ’@ëÈÌwy½Ooô–™PPžâ9|•ÿîµJDY#ôŸ´¯ùª@²×&öô£.1ÇXF¼+XTs³…Ïu]4õà‘ÓƒƒpT38'ú¯¶×Ô~©;êDŠ×áToÑ~sÚo8Ö ì ýwÿ¯ õ_7Qpºªùª*Â:q°ê‹ãÌìï‰ækòÛa¹àsHÂð&„DX¡)@£ºBÏL=í‚ 2V Q¯+@"d‚7ƒñÇÔw½WÜ”3o+SjçYÀ°bàÆu*šqÆŸ4Ë™£4Ó!²ªwÕjó»ÑYkÂê˜(‚m‹˜Vbÿ†;·l÷o3š­Eï“%Ñs—üxfÇ¿|3´Ý)p\}ÃoRlÙÔóI’=,­ÈSò%`ä“$g»µíivñFÁ%y1¼v"oN"¢ùÌÊûƒŸ:ÈJ c¢áγ6e€~•·@0›Q0i%º{¡¯’B$ÎÆ¤½hÃÚÑÑqh£ò‡gæÑQ9‘éí¦žœƒVµÇŠÃf)Ϲ2³ÒÔ@m\*IIXšÄ*Ë´Ñ,±³“eY?–ΈUêh¹Ë<½Yw™&êd)¤pìk¹l¼¡~©¸8ÃûB™_e{,ªAEÞZf‡ÉxÉÕc‹XÁ¥°i.µpd»ÐxËmAË<˜–E¯ã4š5ÿ˳[ˆ«þ¡ã7yÈ)]ß“GÏAóÞ§8Tqvçóä¶8¹¡ì6Ãç˜L3‡c‚4{'hS™MøÏÃXC\ÖØ1“‡øÚ>oj4ä Ì⥙Cúöséظήôq…¦Å%æü›©Â÷Ä.ý€£OY4å•§¬=ýtÍg- Ž0HÑ=·™¢¼µ‚Õ!+Wù}.(¤Ó×¼D޶ìÁ{ß-÷Љkee –ÙšVVœ%©('¢ð¨BfëcOœ$ÔÄ4YðÈŠX^Æ]iУnz˜Wîaš(Þ:³öãߟ¬ùŠø®éͽ§:™LÌ0¡EJwHÏK±Þ­¼*º¿g¡C¥š!–¦CÚM¦kŸ´äw±+^M™”ú—‡¦_•3uvÐ-ýЇ§å.`óâ-„Àð¿ëŸx,áŠÆ ÕÞf“d¨J"fšÛÄÖêål°ï¶×pÚf‡zlßöÏžf·­¦¼·Áe"ùýŸÅ)eÙ<åv¨·T \šñÐomlá×Ñúžï9ì{9=ýb)?çu>Xu@ÝBſ뽒­ŸRr#Õþ‹q(î‡~H Çcð Ù£ãd¨ë­6o€X¨ËóƒD¾¦jÇý‚–ŒÏ.4(â|§Íò’æ\2ºÓDÜp$j^R"$¸M*ë_áI ØMéëœ'/ ,?3ÄU1Í­œ¢MiÝ‘Àp>v§ç»…Ñ‡× rø¤fü“æ#(e.yÁô]¼RÕèÖÓ°D—G|c²8ù|:4-Ë€ šëIÄA»Ç)Ï—8Æ8Òˆk›ˆ<Úán,ÌÄ=8<û†Q|”,ç%O!wŠzfœY"i™´{$Us3+ï›”"‹•Ó{uÍØO @N’Ùk'º\‡¹ƒÖ}çÖΤaò øÔÍ=HÓR~¥%sVyG°[âÔ{%4Åp.P²Ïèøû‡µV¼é™z穹<îU©d0Ñåíº)>—ÀÆæ·#?ŃJ<>ro9ØQ^jrº,$sJÈg°¹J:úÙ– *¢»oÑ|‹Þ>dbœƒ°}Zî¸ ñÍ<ùÖeùU¼3BýS!ätªJ Ý g‡I ›ü-$ m›4´0<¢,¬=VQx Õ‘ó¿8Iuä2Ið÷2Ë•ìÃ7’¢;Dôv$žàig} s7Ø(Ó)ß°kRÚÉH!A¯°“ TjÎØ’ÍÊ„¥Ð™¨ÿµèMÈ»!³+ç™8ÆffZáÁy†PðEh BñˆŽ¹Fxît:Âo™Ü\X%8Ãÿ‘K¥b¨°ù¢uÑèòõ§Ÿ:Bt…ƒmîsÑ¿aOÃ}‡%èÓ÷ÕÉö´çc  a7ÃCVyîK`?~(Š"öЩ=-.P·Ä7âÊ"v…RûDÕF$k­Æÿ?ù€ý2>[³?\™y4B 6\Êܲ†q‘žtôhÍ»8î·á·™ý50½pͺ ©á"ŸE2nQ4î2Œ˜“Œœ'¿X2†iëuÁX‹4ãµczŒ‚ñG©ô¼}vUy%'¡ò¬HÓô÷êOêOWêÞ§A½Ï™×ƒh¢·qR~ÈêÃóRç߈2ó“òÓ‰ò£b±0?åç¸Åâ)Ô‚Nofý·—&ÓÙÎñ©?‡¬Ã‰¦õ 'ùÞÀÄ¢®éçKè–8ŸƒWÂw@jºé!Ÿ hª¤KŽóxº‘ ¢Q’šh¥ ¦î4©[V…&Dt]I ‡„tM›¥¸y–\ÿ™›'G4ƒ–W{økš›-®èÖQn'¤$ ì„›Êâbœ Í¿Æ@²¦®ú¹ÝT¦•µØõT×QUQ’šjŸéû /!å€Ò“6àöçû_R6Z—qÎuC¼¤É+ÞªÐÂìJÔ0wã<¥Çöf¾€“vGtS·´ÔPì»CêXP‚ܳ:‚+’éÒo ^a,0Äs?”r’Õ[û·²A‰ÿåvf;\æ*´Ø€ÈI2À±ÐNÝE±»Æ*…ÍD¡]7A?Hä±$WÚC }Œ©r¿ð""2ÉaËÚÓkÑÿ°.ôÉAL.Œ:æ›Íè]S—ŒCÄÔ! )]¶ (•`«W»O¥æê¢iO+”ºj¸&Cr›%¹^˜É´ß" HrŒ«thÎÃq÷)†iž¬¥Þ¡k+óÀ›®Éö½â~~ÜRºêï ™6BÑAWHÓ½á*9%k3_¹LZMÆÝãÉþž‰7}Á‘ž¤<«2/<%8v3•gﲆ®È'ßpÐT¨¿bÝÅ,à°­\‚²L¯p ÜòS8ãN3›Ö­HÌDuTÁ“ÈæÄ¥Í§–(¨Å R*kòRÅ冓—!î|(,LIYÖåþC#O‡’²ê©ETVXM1¹«/Q–“È©àðIJÆÇ%%O£bt‚üõë‚Íùëd¶aËÙzÚ!´=Ò£$35ȈXqNK“ 3‡¾9f² :ç274'ÌèeIúÉUÞôz–ïfãiþ„ z¨ Á†ý¯U¾=)zyÖMyÖ1IÌF‚|Ý(hmÅãñÀ;*ÐAÒ[Ž®ò3„¥ÛÐ6x ë! ý£§«säÚ_šÃð ¤ÿ»mŒm ’óeÆlßÞá¨[¨Rqüàéœoü@(Ñ?äP¯]E>ñt{L¢s«â lC0SåËxÌöï}Ÿª«‰Î B7•Œco)Ð:Ä©_Ä&mTΛûÁª /žFz_ü_7µÞ"i-0BÔ'ày†Ÿ0A’Àqjã5Rmhéz3Ä;w` ìÿu±’-k‡дi‡Ä¡òèþª05¤2•ê'±Aãë@¤Žn‚›>¶)ºnq­ÕGpfLçOÔÉ$fÏéö2Y£s3ýæ~¦<&G“ô|zÝ#<@|lêùMà‰Úý#´4oÌ5%_*/ŽÉ WðM’b»5Q>]™H#…D•ÎÅð?æœþòVN»ÑÏEìÒ>[ü§^o?F½”jèÙ­ºûo¼¾~ûYtô|Îêùãs=­: mLV[¼Nó›#)5´Ìëõ¦j’#gÈèƒÅ†u]ÿt`?c®7-l™Æ§ùÄf*?ãó8±µëÓ{dÓêìßÕåi9µOöÐN«Þ»?¶åÕ˜Ó~néîÜþFPð~OÆù‡œ|ކ³xbߟ›åi=«7ê£Ûã:gö¼>Y|ÔH]A[HÍæ\Sñ\ç&Öæd˜ŒhÍYïyx’®E¯ò©ý:§uʦâ ÏÑÅ|–þ‡Ëç/à6­»B*‘ëGr'òqœ%»JñÔt”Ó›*.}“ÝÖ1Ì•UA£qÁ³ð ÅIPºTʹ~)ºxkÑûrŽ¿®‰°X2¬b÷xšQ³/ÎrY3nTJ  p¿²x;ºh3׎ÏãÛÑ5øDg«æ@”%9T‡}Ñ(µíh(a36ò[œ'…á*¨à ÝFë N[Hø|Uö×3ºÍçÂ(æ%Ódú¥³¢Hd‰)·µoξ†Ba8Ky«q6& ÙŒê}ƒŠÞ¦t—’~ iÊ›6µ“Éi­›jž½ç™7|’¦,?pÌ tíû|.g¡„P’¤¬z (Z®pÒS”³)5¦ÖzŠ®á@?8üö§zš,^,=ãF±'ñ®s”^¨ÔF—IUŠÎÜ´z¨¦\1}xué.›ë_4K®è <ÀšÓËåb·æ;wé)eñòt¦I8qVÎI³ý/ûVÄY²@š-f‰f¤ŸÈ'ÉÍEÌ(eHahf¤©H¿"ÎL%ÎI3SI³3«^œ?A÷õß¾iò±^¤&ƒúãÈÕ3(P!mÀJJ/Ú4fªJ††¹PiÍÙ‹l…ñ(#tÜe…ub&´_Y‘-LŒáÊh'1Læ±äæéÁ/£Æ‹(–ԆІøÇNú ’UºJð|¶¨? aê_½¦ HÎÁ#Ujé&.áºÀÇ}RUNÜ}ú)þ@IvPTÁ†ÿ#6Â;Š ¾ñkü‘£"!Õ¯œYøÈõòú7þÓIôl âHWvk꾋×éY/ÑÎZôú(8—† ³múËRáYè-`»ŸÄôõçzruy2ñ¸õÉò*#$«ûSŠÇû뜘Ðjg³êÔâ$ô©¡vh£wy<½O*€?†jŒyÂwHù"MKÛk±Rl¦&ÉìN¦Ói‚ýQåãëC0fFÅS~€X–|5±!¶¤Åƒß1ÝøgŠ úI%£aâ|èSèÚÄz‡ò7ØÊNÿg²çý¿²X÷²7ê{Y…³d2ñn>FÿÆ)Ä~~”ÆhIyó:‹ò(£Ã(ÉI½ÄÌm®Ž>úÄC Ät»Çx6QQæZÇÅ,yx~EXeÂcÁs¢q9öVnE'©.CmŒ|èZÞ™œ W¬ôV»©ºÁ,¥íÀó ¶a`x–_iÊÑåÔnƒ÷Ð ½Ø¯¸¥–AÕØ™ã)Øôr^(´œ]˜i‡ò›ÎšÞ€˜#ls¥)åŒ]‚ÀÁL4"%©hðõñ Ô# ÊŒ÷«€¥àj¦-®h“«J¯\£¯å HÁ6uÝvæH ›ñËšqe¾æÊsŒ‚>¸*MÒKÃ;LÌ0 ¨¹ÿýrZ21‡cðP;“„Á«E7U:Lã‰t4+*ÛHkjé5£C/Ãs¡é0&/lž\]1ÙªÖ¯e©Ì|ŒoÚéÜvÀmׂ[°\Ç.O¡ ˜O„+¦–i¢sd™¼Lâ¿ØÍÀËY¤Ô€–m˜|#ŽÓár”‡($2€}€cœ›HÍ2„ƒ¨ˆRǨj€YyävöC.2»ŽÒ°n½vAζ­Mø[ö%Ù;¡æö­rG JÞ¶ÙÜž=»"÷ÂIŠÜ÷2çø3Ã7èË+»$ øïÊû]‘ž©@ ‘FÆÄHv`»„Kœú;ÑØ øjnËñ?JæI’ÚLŠèе©ú­ÜŒÔ¢fÞõÍÐÞùŽë½Ãjg&úØl”ŒË\@B“ab'±’­•çñÈF–«›[­HÈ?-ÄþÃè5C÷MÔ"˜ÑëÜ {¯`iîß=ìf×i‡ud ·È¢fä2SÒc‡"©ûÁkÔ …ïÐô±! Ä‹i©Lh—Xqm–ÇÎÉ?C÷}†íç=C¼47Å”g¿%ÿsƒZ*L_<Ńr ëÊ— ÃŽã8kÔOãaüçV~îÐÇUÌOîÒAûÓ†ï5µ¨ëfÀ àým Ðæ=VRõˆÏpæûŸAËî—rŽ·8¿8E\ˆÉŸ¡±ù±vèÙ²u‘f½Dƒ<‹óý/Ç"ÑJ©q eˆ5@ç‹P»ÌrŠÅ”ÌR•:¾rÚ;üþªÿ3¬?œ¨Éö†Ý¾h3’;c^!Ól†\ÃkÉÄÕ@t0¶ÈXîÙ0êǃÍ1) Ù°»ì ç¿#wš“™2Ø@E` 7 Ùr8HÇ À½YÎ"6¢ÿŽl6ìóûÜöa{ÁÄò+9+çÁicç`'ƨIÎi)³áfjÊ\ØiBtŒà¹8v×_ŒóÎuæ"ð‘Òq×çûôààRee”NâÜ{òjâáZìÐ˰øÀIøÜ\§˜œý(ŒÇÖïG;·­XÝŒgV>ž,ÿTÐï}ʯØLÔÚY4âÔoR7è.¢2¯L2Î*{«ºˆ„q’§(êÐSÅΤO6R/ú÷þu•‹N§Ó”™/´]úò‡Ø!³‚6×rœN7bÅEÄ?âršÐh^¡Gû±üü.·íÉ‹{¨Ö ˧œ}‘i:€ò@ïY˪ÅÕf9¾GÝdË2G¦ëO:‡#Xƒþ»ü „Ö8è¨æÙU“#wºØ¿…™3ù%Y¬û_ÒZÓïkkk«¤é TÖE£çµ¶ñý¦#,«­µˆoTïXúœ«Eök| h®Ââ©4™ƒpaÕ'è²}$7Ê­¿è´š\‡‡“ð»eP&V¶rc&C÷w/ÚNŠM:äÚβk‘”Àkêø„SýúÆSöòbE´k‘w]-æÈ¯¦CìH2õ9FC²:•NsWuõ3AÏ-göU_‚#Û]Î>“Õ:ýÙ±­ à÷$ ¡àø”Íì¾­°ç+­¿>ùŽhFÔl;dC°Çõk@W|&]ûœS@3TKÁ:j<²*èJ µ{(,ó¬×ðºÃ_²3î:mÏ ‹A=Q‹à‚»/WnןñðÓÏhø~_rîB8JÇÞ,Ç€K祥굑׊î(òF-ÕSê˜~ÌC›ÆÉŸ{Py',Qý Á8ç7ÞC·|poÙl±ÀNËëÒõèÚŽ*°gÉTù†ÍŒ¦ë¢.¶ƒ†a£6žjÈïÒ‹:wðÝ3}]›ü†É{°ø65ñ}fÕ¹“5wÿKYˆ¯¼Sn=ÝŽwHƒS ©\c‘í=®LÆîÇ‘ûûÜ̞㛂÷`AØ·ص\jìþ®L Øõð%‘'›˜û‡Æ];Ÿóu77’«JTýäêP¹WËëêá«Hå&“˜“â* Mrù­œÏz;¥¥”tÛÓj)#Bé܌ן|ÍX.£îŽR˜8Dæ'Æž¯£†‡òf/r,(ßñ*8ìøˆ©.èòÑ\ áùÜiÉõz þú¨mì áý/I†þ®”½[âOlOpJðÖß¹t‰v®{æìÊÛ 'š5ÿ.RÎŽIÖ­ÐúŠeì|lñ8›EE²kzÑŽF+…ý±"Œ”ºi›‡éÏÅ\•[‡ „Yº#µÒmípAš4~|KÊüåª9ÒØI¦®TäåóçW{õúçA™ƒWÚµ&çÁ€ô…ͪȻ§AžèMBE1š‰ËñØ8ê'ô"òjZLÔMηîoâÊsp„Z¤î:ëã³ CíB´n\ïÂÉ+ãâv[†ÖmAÌ`ŸÅ“xO²rÙïESãÖ¨«’!'¶~y¤€³C\ÊbrôÂh™P{ƒ©+ø‰ûz„^âK…x’e»P¿ÓvÅcfÖ6«¯ÖvIM,ã´mÄcRJùí ,³Æ÷íLR€q´Éò˜*l?Û\¶í¹˜ z|ÓÍ "å%ã*‰q˜{nM%£SòîÚVãàõ«Áß +1Pð² ³Ô¤ƒêòNØ×áS鲚C´™ç¶s;«±ª[d¦Š[|r ¢ þ‚zå¶Ð9»B×KnCÔœYn¨ LUPµ-®–Ê0\#ÌÌ8_NãºDÄ=P}—Ô±TàEå!ùù¶:D£ìk’É'eRl¦ #Ê<· ü‘öÔ‹6Qåôkß™+cyÃ{‚8É]vZ6;ÃÅ2ðjªµ¨ÞÏ=r“oÜÐ >S âUí¯ ÃD`‹_}'ÛtÃð˜$ßI¶ŠøudüVe&Ÿh¸Llœ©ö‘”@°¶ÄéçèâêE½U%ò|PæöQZàO¿áÂXÏM }̾—íÜ3´Çîù»Ú‚Iòç.µà_ªçµª¥eؚȡ߅–6ß…Kª‘¨iYͧ™¤ƒë9uýºy·–+ nqé ·tÀŠ™ÛJsçk™Ö=ùW· üÔ¾öNÎU&Á»F*dcO…Ѷ%^ÍÂpÀ«oY„6KI©[€ø›#º/Ü ×>MäÀ%ýsmeܲ6‡ü¬‹Ûm¥”WÀluÀZö¥yW©a¶¦…Ùy%¬¬]öJ„=ŠV5gkX €ÁzlÕ¿&q‹òe›º×È©!¤…„H"cÌÑšè\þQ rIµX¸J‘Y¨yÕVS+h`‡¬]m@öPõëó®&£ã5‹Õ®æqfò&IJãbãxŒò—Ωû_™‰Ýƒ¼7sNF0û;QYàï [0UÏhߦCý/ÒÈËè=•ÇæI?ªöÒ GÅÜB4ÞÍ,™N‘ž3tK¦qÐm|+ªnAÛu`5$Ãg…ý˜´––¯’¬ ¨+&Lýf­ºÜ\¿`A’Û&[bbòÍÓêý²šZùôÁ Ž ß-OŠ, ÔW —òÕ“Û8h]E1«-A¶@}½î[¾œÓ(º;I/¥É$a‰lFÌpÃŒ3.÷e’ú°˜–V¶|_=—VÝ1ŽÙ­>.ù¶Ì\:‘K&âT¢UŸë©ûÄÑçddÊ BœŒP®a>Ã"ú')¢×Óôb<íkdXôÑvž°'E)Š[©Ñ ƒaƒáÿ3šåÈjqì± 5™¡0È=ÄW×"W#‚}ìʪúê‘òß]¬²œ´ƒDý%{ލ¡r$J ‰‰h¥’r=”4Ñþ员ݹ/1n6<õ“¼rV¡¨8ÞÙX J†:”¢hÖŸâ< bÂá·*@U áÉšÙ¡]ܦTŸ€\"Ù…[­€~)e%µ•fþ¼‹>”Œ¿.±)*/—G™¬{Þ*AƒŠÅ7«ÞIyÀ¢7“¬TwqKfµ©{ŠS†èàK £òÁÐÚÑPÒƒ Äœ‘Þ =Í ÏTYÞx“C€_´S!® Úù%= ¨s\åŠ,\ÈÆw¸7E¶¤Ç6ñ¥0.Wy¹üZЛc9Ì>.9¯ è8N)€ùŸÃ]ˆd` í –p;vôžVEì±k Ù6I©ŸÞOo´ôú êpÖö|ë#70¶¹êúGíõ)n¾7½m¯Ù67íC““‘A´'N«½;Æû‹¤Fäÿ¶$HÉ•?‰Â$5°ú*·Á]J¨.<§-Õ§&O·«âþNqâRÕ†0 „*Wþ&TsÛËÔE-¾cC‰š°DÕ¢–ºHÕÓ«ÊE⿱Z³b=h[Í®v•%«ÄœâôÌjS'Ë2ø†ÍÆï‘”#4Ò±N%Æm©½«â#èîã2)6¢Xñ¿"ý9·“È’V“3€äµ¦;œÄ€.Hù”jV¯ÞãæÙ\Ö Íàå« ´M:Q2(P™?Íi»å¹é°¨F¾â¢ìçñNœKÞ…_ˆ<"ÓƒKçq GœÄ¡fy¬ƒpxñƒ£<ãOúºì× ñZtÉMˆ3"v… &r>¤ü¶a¾ø«;ÂÉÖñ°/G"8†ýme·\åíBû¡o¦:6´G!mVÞ,à&bT»¤cäN鱪¦˜ñeÑg֢׌Â<†-ú{¥ÝâÇ%üŠe0£U!%äžVÓ¿U»àÚÉë|˜ßåúI$B=Kþn#Ä%h •ÛoÜ+–ý=Ár»%ÙÁÊ „ƒ[òlïqr•7<—1åà àt& ¨ ¾OÅ]¥Jàž ÷Ø-ñék|c.‹šS’¡ð0<}Ë @{¼¡ã°[¦¦ºSÊ9C]¦k7#G=7 ýEŸå‘§uZn–X­Òaå¿Úéùåøãè lÂl×B=š­ž~4‰¾VIìwÙíù˜]‰8Ÿ+]c?ódMî3ÖŽêL^p§>d@‡½z–ûâÔî:¬C õÄ?ó°nœf_¥âóp5¥>È&cà„¹(âÓŠUL´¡z·x8•ÉÝàä‚ý9+ä5cÏêJ¸6hµ¿/`µÖèÖÖV»SóÞ­²ÝñRúIJ…§ ü¡Ž½JŽ$ ùtÉBÙ›ñþ—}IÔ6>{›Ï–œÃ=8Yp®dõþÝÙÖS¥º{¥b £7Pýá”CÆtvµ×õóByýoeuìuƒ%¿lJä÷›Ez+6¢é ¤ßA*È•ªŠ«‚«h*ÐGŸjˆ,ˆ"ÎÆùþ­Å_-}4¤2b²i£Ô”¶÷Åq•zêp¥jUMmï¹èYô3>RKÿ8_rCÛÁ„ãÙ¼*&u]@­zÎçwÓÜNò@oKÀBEÔã§Ÿâ°Zæ ר¨ 5r—sîHßÊFóc±-ßÊ!GŪs–èÉuvŽ Gw|¼¸üÙñ–}nBêÍæs,/Ž4ˆ7ÝȘøÔ³&JËùA·ÊU¬MpL›kñ„äeUÃð ì·V ŽKK’sŸqfö{¿z£àôl=™rYê"…üª|†m™¼¨*`| .»cŠet®q&Lð!ÿÅØ‹qB§ ^‘G«WbT~M°¥hü£Ÿ>µNð¡ÉühÎJ²fÖä>!hÁ\´¡‹û³£—åõ¥"X&%GÆ®åPã&cÅ–Mæ¨~rÖ]ßàDáŠÎœIq¼GrºMÍAŽºpN%¦¶mv•qæs–iÝwân2ؘõqïÄàìÕ(üØ (*p…æõ„õ¢Í’º+ùæ-z>£7ï*€@Ék•uJíÒ]\òÿºp:ŽÍ@‘éQ´"IÐ ¬¯ˆÝùísZÒØUøç"PªÇ•áÚöÚîšÜǪéyBIÑñ8êÉùÏu2êÅuÂZ¯ 6Œ,ÿüt‡«>T£ßŠØòûøÉƒ§_TìßPý7~7<?eéByxí’PÀ– s/\Îü Ê_?¹'{L냙ãF"7Å>õ)Ùœ_uScÀ9®ÖwiAî <" ¨9¡*dÿB¼0ˆqAõu€%jPú>tŒ‡´kèÆ¸z5ÌÍ»^î‚3ÚÝuÑBAÁœÏ¤Wï­:H3eà“QÊOÜý¶ÿ;/>@6Z;}û}Áƒü–·{6ðò¿m™X §Ç·s4/ÿåx`ñ”&ãxùM3úºiœsAðÐ:PĂ瀕mÊ'ž¡yÚ…šß.PÃÛˆ†ÕÉ—Äœå]øÒãnb§Ô\“ˆ½Xø,ó0š(`E\kQKË©WÕÖèèA‘Ln‡ñtÿ¯>m‹‘n—rµ3Û+û{PÊø½¿ÅÆqaÛèǃÉ,S!pŸŽTN?\¡þpê±þwL"ïûiyõæ~þ¡Í}/íïÅFó µÚ~éÅŸý|™Zèe¤ýa«Dêf׺ð!«ñ‹¿ÿ»^<`9êü ~ö}Fuœ=†¿¸vÑÓðœ¹Æ¨hðŸàI>0âa±a̬ú±o‡;Õ_îË>§~”ÿüÿPKŸG§ÛìŸøPK~vA 1‡‡Thumbnails/thumbnail.png‰PNG  IHDR“8ÓNIDATxœíÍ‹E‡{Ì®¸ÑH"¸¢`{ðâG`õàAÁcÀ¬‡tÿÏzÈÉÿÁCÀ“$7!‚ñDØSð ñ3ñ"l‚eBƬ­MoWuuWWÍt=5¿ç°ÔôÇ[ÕýL÷ÐûÒo­ìîî‚ÆÖÖÖÊØc‘9*šûãÚ—=±ýêFùñÏ.þÓ§^ÙwTÑÉÐÜdeíáûW«wÿæÂWwdÀÝÛ{×÷ŽÓŸ?zÿƒsßyãé[ë'6ÇT|247½ùã•o<ãü×Çß¹òáÉOÞ{ëû±‡4247Y-&³¿.võ¥³gÝwôÍ3§¾¸4{PñÉÐÜ=f“Ž?óØ/·ïÜkß¼qýÐê³c(>š›M§¿ý=}ùôök;;·Þ~ñÂÇŸ|÷õ±Ÿ Í;yúÜS}äð¥OŸ»zmïÌöÎdõ¡±Ÿ ÍMÖ}|m¿qx}ã…õ±G3724·$È••ÍÍ ŸR—]sTdŽŠÌQ‘9*2GEæ¨È?s“Éd6›µ}ìÜ·l4v)—— û¬¢•ûÖwô—ÿÌU§¯:ìz£øÿÌÖWµ,ljóÒìØ€U|Þ:÷ÍU&JIÕ×ټꂋƒ Í¿fgõ€mk;ÃZƒ› #´nƒ¦y·l|gãvæ¸}EéÚ¼"Ãc¦Ã»ea;¼KÜWU€Ö;¤c$;Dfì›ë±Þ¬êÛ.ÙÙ¿´­²þ5ºæØ1§›d…÷S—æð ±vÌ=ÏQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*Ã3«QÒªîUýÃË—_˜Y-j':<­j¦C­9Rë?»½ò«91<³1­ÚøÞ4âÔ».Ú-6IYæTK—YGê °_42«áiUë*ëwȼàúçW­£âšY O«šÌñDɯfƼ2«ïƒEæžç¨È™£"sTdŽŠÌQ‘9*2GEæ¨È• wV­KÜ»—¸ùÕd÷ }guaùUs`u¬)=ëÀŠƒÿææ¦ÑƒÞY-ž²ùåWÛDšVª†#È€a'ÈBßY-¢æÌÝ­·ÜyE eVÍfEôüj£/k~Õ¼+vK}_–ãï¬6"Ì)¿êN‚÷Œ» –¶b®ï¬º7÷‰òóV¡ç9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽJ*µ|q÷k¾áÞsG©ÔfˆX\Á]ÅZ‰Á$¹Ú U#¤¸B£—6»hyiÕfˆR\Á}ÍeC*µ"W0«,X//Ü+ý R©ÍÐ'Zÿâ Ž-û×xHFm†À¾ÐûâÑó™£"sTdŽŠÌQ‘9*2GEæ¨È™£”YM3­jÝ bY­vO$­j†u÷îH̺et‚2«i¦U«8m>}Å9ÙQYhfuiUßÞÝñÓtVa>qsɈiUëZǬtŽ$"dVSK«š1Í£è3Mas̬&›VÍ=ÏQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*Ë•YíÓu²iK‘Yu4Ìc÷=¨±XŠÌj}äÖ.#ñ:¨±XŠÌªy©%å`K‘Y5ך—`½íuPc±,™ÕþaÝítPf•Šžç¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sT‚fëì\nݲlxMó¹„&u2d¶Î˜‹¯m¹µËsvš›¹Û!ÛSðž­³sjLóKÐÀ:1`}ß°hnÖù·sû.o¡³uš]  ç¨÷ŒèÃ!³u6¶µ½æì4§Õ4ÃZZçãl›¹³gLÞ³u¶5Úâ8æì4ׯjÏvÛ7¦ç¡D†<x¶{ãXg°Oœ lÕÑó™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*2GEæ¨È™£"sTdŽŠÌQ‘9*¡¸½ ê(¿]8Kˆ:zÏ©d³•!¸ë‘}‹[+¿Ý6°ÎjßÖUyÔðö®À]5{;Ë`× )¿]íî®±í>àljx/ºwøq¶é¬t÷’G ï!¸E²+"–ß¶vd–„v6¿ÞÞ¸­ßèžE¯;ëa›å·ÁÝk­¡úÕk›Qð~*ˆU~{ô#o€«á­ç9*ÿå*ú»ãY7+IEND®B`‚PK~vAConfigurations2/images/Bitmaps/PK~vAConfigurations2/popupmenu/PK~vAConfigurations2/toolpanel/PK~vAConfigurations2/statusbar/PK~vAConfigurations2/progressbar/PK~vAConfigurations2/toolbar/PK~vAConfigurations2/menubar/PK~vA'Configurations2/accelerator/current.xmlPKPK~vAConfigurations2/floater/PK~vA styles.xmlí]ÝŽÛ6¾ß§0œt‘«±~,Ùr3¤iÚ L‚dŠÅ^ 8e ‘%A’ç§—{Û˾ƢoЗY´ï±¤þ,É’M›”%ËšÉX<ü9‡ß9<<<¢_¾z\Zƒ{èù¦c_… ~8€¶æè¦=¿þ|ó#7¾ºúÛKÇ0L ÎtG[-¡p~ðdA€*Ûþ,*¼®<{æßôg6XBh3Ç…vRi–¥ž…]EOÂÆH«‡ÄÙÚ| H+cÚ\]pGÞsHœ­­{à´2¦E2ÍV7Òʾŧ9Kfa–i½.‚ÀFÒ…ãÍG‚ªª£°4°–Ò¹+Ï ©tm-ˆ;óGÂ…0Jh—0¤ãôÙ!Ù«åôˆE°1«®}D‚ØÅ¸$k(['‡¯û91ºîçbÖÀ#ÆYHœ‡Š¤“CEÒ³u— XTÌïtô†ÿ|x¿Æ•·$í ÓæD¥y¦KÌfD­ï8N:T\!Röp¸"ÏGÑç õÃVòÏ  —!×¶’kÀÒR‰;Ë2¡!:a„(8x!ŸP{˜éÊ–å‘]Ç ÒäÆIGLUu,­jUÅ¥ éÜÓõRR4i„Ô) wo‡g9[¶]þê($J!ĵ6žÞ<5²õH"æà£ =+¬6˵Óß—‚²ß|á2Û`deâe ³ôˆÃ«d1´Æ@ƒœ5Ë¿zÙ‡ôñ úŒw9|í™À†¤» ÅÒ´žâ‚ሠ¶XY{«‹K¸9´‘0ýÓ÷wµÿXæg–t°.¡îb‰Ú¥]$%”]$Â8THY × 4dÐÑHÒõàgÛD^ |øR2Š¿×ñ¿+FO·îÉà’ft7`á,ËDŸÔÙû_¿ÿúç¿•ôžÐö>ªÒÈøyä&£Ô¡VVì&-ÇC M§AË&ä.ðÀÜî‚s=d­¼ÀD>eT„¨Q+ŽË馻—üÅXÓ^ ›’ͪáPs°5œ™ìù ÌÑ3;z !xh\ß¿+rÈ®»z!aÒXB÷Ë")‰[M Þ\o¶Ý >’¶™–/Ìb«iÑ»ëpnJ„~õ2r¾b,7‘L®ùahZš6gÚœ£zº97™å°£’6Ó6´•ç¡-ÃSYW‚0ùÄ'\Ü;ZS°¿x+X5/s ,εØÐiÞ:¼¤tî9+7ܵ„­Òæ1H®)áÇͱ?-ï+i+–„6˜«ÿýç¿i‹…F®J öذ Ý!h-ùÕÏ ƒG?E&¹r&;'ßHn&ó¦PÎ[ƒñŒÃÇ|2!&S<¡›bIhÎúÖáT!~"rð¢=û1 fE2f¹½ä*Ny‡ù†9ÙÚÁŽÉ$úVœ‡8%ÓkwSYSÛU/”~FõÖR#š;·'f7Â'ˆ_BÅÄüvA9eRåÄ ³RP¹1•Ù)¨ÌHAe*%ˆx×åÔ¢€j­+c= fIWFö–fïd¤Ûjcº­²Óm•‘n«4º=&4¼ø¶K÷¿u/¾íÒÄð>‹ïÉØ€±Ô” KÌl@ˆF6 œäí6 0—°\™È+š¿Uýd:CÂË¡åØóâ$ÎÊâC<ôªFc!žœ¢ ÖÖ@9Çæœ{èN#5€åg°¼pVžO6Ø6r«g2ªTYØ1ðm†f²º¯™HMÃÔ¸í¦CØj:¤\)|t¿„@ž£´m¸Ó³:³O[ÅVq!3Ë;Œà”.8>¯Äž±zxx¸ƒà¡L’ëNj—-ó­b«DÈ”i=2ÁyB DÇ ÂñÍI‹Á#P‚§ömy»#y¯my{– ~—Û2Ëì¶Ì2£-³¼{˼mþLÕ©EÿΤNJ¿ˆœXéVcÇM2»ã&™Ñq“LuÜ$äÚt)$ø­yí«ÇO¢à·“iyÒ˜ ˜°3F&`Be:vâ,œ8Ÿ” wðPYnìPYfw¨,3:T–©••=B§¿wU ©€á+)íÉÚbÎP(Ãʯ¸u"ÝëLÃå»p ÁÛL4Øi—§ ߃:í}½M¡|MJ!Íî (^°ê v(ß¿RHÏxÝX‰ˆ3]»È4Wˆ÷%ˆ_F‘?¥±}ƒÂnß 0Ú7(Tû†É>§^§oÚ'ûzu u²Ï¡×é&«MØ«M«M¨ŽÕ&m9VÛ´/ƒ¾p0tì·Þw°ÅÂ)›P:eê—âÛ7ëÊÉ\‹p €P¾}?!ÈÕ=ÊÂÏ Å|Ü&/ñ«iÖ)óq'm9b8ë9·eÎí”`»p,«ÉjO0%Ý4¼J0ä—8Qgßn+=öicû”Ç>eä±O©<ö)õÅ8Œ0‰~XA’4§IdÊ.±îÙkµ6–*3e—*3e”*3¥J•Q©¯-bç#°‚¤JzuQÃ>C~Û”NÃlU»$IewI’Êè’$•ê’$•:2Æöì•ô¤&µœ)»mRrVK¹ÚXâ»Ê.ñ]e”ø®R%¾«¤‰ïÏOÿdZ-x€W/dªŽL•ò:J•ô~‚.€aJ‘ãÒ5ÜÐEMEžôEôƒäÖªtÄ+#ÒÚt§h2iÀ@šˆÝ0P¼€Þ9ÜÐåk‹<ñ•¬§¿ú`f ÓpžŸ~Šæ–pòœM‚걡Bc&;„$ô;„Hü‡îDž8}µ 8yõ0½lUræ–X/O%51Õ˜ê3ËpÈBõircEÔ•û7ôAR óì²ÐôµÃ³àp$" GK Íx¾AXɘ4Å€iŸ…¶Ä·vÖ0µÌÎ×#1ÑL-©ýÑf%dRG–aÅ– £†IeçÆ 2Á¤nû¢^‘䛋ß\»õ[m·-„-ðÚø2c‘æËŒ+\¹Si;{Âï/Þ>=¡å¢LŸï”v]¥ã”y¾e{ÃNÓípŠjnŠö‡è»ç“¦ °4­'44p‡× e­åž>*HߺòÃ_ðâÔ´“¶<'˜ Xæñb;v†Ýâ4Æý£mEÌÓkÏVº ¦ðM€Zûë÷_ÿüã·ÍbÍYº|Lëc™d˜¯–ÄgèoD\âß]"Ä- –^ÍIDKÚ ‰W¶=Ë´aBã;–©W<˜z°¸‚UàTPÄ vþ>LÇðÍù"¸"`ëû G¦`†.é¶7¹¬>6êÌ=à. Ó¾nôr¨¡ŠÐ«Ö€%æ/¨oAqƒarè&3–¨pH“é éÚØs<|•'ä­$Þò·¢|{+ò·þ絆%˜ŽZ7}dzŸâa‰ü7nP ©+Hòw@ûЏ­'zöLC?†1,µ†Ûæ;©Ï‡?9evVVåiÙ¢PŃÂ|‘ #4®›Fô ÂËg‹àJÀe;Zφ)lýÐñ÷2d›.7VE”I{™AáÞ![NF\ZR9jw AØzjÿ+ÚOË«{(’PcVÜÙÃL+ f CU5­ÇlÙRÌJ»1+5`g £ÇlÙ ÌŽwcvÜfUµ÷ zÌV`VÞY¹;Ûc¶Çlf•ݘUŽŽYì¨jÙ³ÇìxŸ¸Á¸Ñ¸Þõv¶Çlf+âã†ãS~Ê÷˜í1»OÜ`ÜhÜ@0î&¸ÇlÙ}âã>nÐc¶­˜­ˆŒôþlÙ-˜­ˆŒð½?ÛcVÙ'n 47àyE¡93Œ(¾Ûc¶“˜­ˆ('7è1ÛiÌVÄ ”“Žô˜í4f+âJ£qƒ)òF{;Ûc¶³q¥Ñ¸$á Ú³=f÷‰( Ç T•&nÐc¶˜m* ¡št—~‚ßñw󺎜L¥‡_¿F6æØö)=üzøõ{ì~ ïß.÷ðk~Mì|¥ßùž=ü¾zУ{iyŒ€ äz'=$mme…wK‚ÿ¬#’`îØÀâî,.ðòs˜–¨ØËÌÞ㡉ÅÈ•ìá]/ƒgøx¼Ê©Œ[ÜïJœÉ‚•Â}xëIM¨/o›%æ÷»³åÍj_qDüMÙùpxH2È–/ïSÁ˜è„p!«H'tg…º„aN)/DD\ö$¤!üX2íúE¦Ñ/ᓺ4©ƒÎË9iÒÛG¤36ï ëÓ S¹>eYªz´ê w&Y2cæRªæÝ™üÝju¸3Õ=ìÎüä8Çw¥éïRQÆ‚Ð1Cx~®t|Ÿ6…©Î1Å î3Îhm¿s‚ÀYb?@P×¾qrÚIí`p4‚ÌÓMÿ`Mê%˜X·^ê6dªŽ»‡/Áó’¤(GT!¹q_B®Õ—(o½>_"£<9׉òÔ}B»My˜íXÏ[y¤Æ•GªUyÊ[?ŠòT$'ÊS÷ùr^yø 5•I^µé•§õÎÛ9íb3ÊS‘…ž(Oͧãîzø4üÞÙîªæ€È–+¾¨mñ1Cïù­KG°~~ûä÷¦ýêÛ#ðÍ1BðEw?3ÏölÄÌ3ŽNuè¼[îN'¿ÎO¯á*ð@ݺU¶î`*UUIêáwúðsØö˜ì?‹>O:Àç!×ÇUЄ“X[~Fr]—“¸>æîˆ…8§ ÑX5‡¶í´—W`XÓÆ5­Xå­×,dRÝMä÷¯ÞMlZ{ÄöÙÞvNÆû_À³ã`ju:PLÔÖT ä…ÌNðüöo neãöcë?âÊþ$¬ÿ)GgT/SIÀŽî|™Wø15»âÞ슧̮´7»Ò)³+¬§˜Ìbìª|òuÂô`Þ‹]ñ”Ù•öfWj»ºfKà}…Þ ü=~ÙÎ󜇺§Ê…eyÎÖ4a²Üý|vo‡ï´ð~ ò‰žë—Ã¥€žq~¶ù_Â8†ajñHü«—ñGüE¿HN¦Æ%‰@æC½£u>71Ü¥0,!*ùºeÓóÑcL}oôåíi¯ÒåúÁ3Ñç9·ttÔ´…|廵?‚yEîs(ñ3Ãqô_~ð7c/⵿Uy»îHÞsTyù|þaìÏžf¶êt9I£êQÅÃib¤ñæbc˜ù!6¦‹`šE²i>™9ÌßÄ‹±šMÉöX÷˜ŸIµÊH`ÂT†Â\"qmfƒÝÓ@T[…ÆßÒ.|‡œÍÓ—„„±ða"íé…¼B ;‡ÆŒ×Dž.-ž‰VÇ3Ñ –[÷5àÂÁ«SI­BòfY<±“ñ´|r“b›ŒÆ…–¹ÀAðü7'c©Ûo¤YÛçñžø‘Zpëýðë:^à3èáÛÃ÷PøÊdîEÉ’Œ 9ªÜòÄKà§M¤¡ø!n)ád{8ØqÉN)’ËÕK œ¹ñÿþˆúêÕ«W/GŇñ·0 Yc±å÷ÂIPv”Ÿ©´÷O˜—øÃ¸WBÒ_æÙÆ’¦rBß:„цw‰ö3ÄÚ¼U²â†d£Oœã£< =…=xÑø°5C}þvC¹žrBÈz×Aðˆ~¹@õ8¤DÜ=°Vß­ r‚À‰ˆSž…y>&¼úÇ ðrwÓ˜(i7Ä…oe6Vgr%Öì–/ÏYchŒ²„Ú9Wªš%Œž5‚ZÌÇü‡§®_xû¥¿ûtóîãõNq•Ñž§Ô¾üüÓOo¿ ­„ô÷õ›ØmW›`Ðu@¬¯A5Ì!ÝÒF”Œ:r¤Ñ ÍVÇØF[ ëŸýúÂtËî¬ÅvUM|óPóù4BÍLÏZgj>'h„IÉ;kxhSGlåE°¼×))e0-X¨%R°‘Ö3Ô 'Vcy(ó`=ØFäqÝgãî%|¡qž_C™°Ÿ!qÁô Æú"–÷ˆëK¾8Ike¬C³²%ç¿7û׃§EG ²8iïúÏgº¿Q¿¾éöPKhkáPK~vA…l9Š..mimetypePK~vA°æÞ^‚‚Tmeta.xmlPK~vAðÈ&õzJ+ üsettings.xmlPK~vAŸG§ÛìŸø °content.xmlPK~vA 1‡‡Õ¨Thumbnails/thumbnail.pngPK~vA’°Configurations2/images/Bitmaps/PK~vAϰConfigurations2/popupmenu/PK~vA±Configurations2/toolpanel/PK~vA?±Configurations2/statusbar/PK~vAw±Configurations2/progressbar/PK~vA±±Configurations2/toolbar/PK~vAç±Configurations2/menubar/PK~vA'²Configurations2/accelerator/current.xmlPK~vAt²Configurations2/floater/PK~vAÐwð¢8Ž ª²styles.xmlPK~vAhkáÅMETA-INF/manifest.xmlPK6pÆaccessodf-0.1.1~b/accessodf-addon/src/main/l10n/toolpanel.ods000066400000000000000000000434421225501747700240320ustar00rootroot00000000000000PKü\ë@…l9Š..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKü\ë@«j$††meta.xml freesb1996-10-15T00:33:282012-07-11T13:39:56.08LibreOffice/3.5$Windows_x86 LibreOffice_project/165a79a-7059095-e13bb37-fef39a4-9503d18PT16M26S13PKü\ë@ settings.xmlíYQsâ6~ï¯`üN „£'p\Ò¤¥ ƒIÚÞ›°ÐDÖz$Âýúʧı/`¬Lo¦O€¥ývYí~Ú]_~~XmBRä]«yÖ°jÀ=ô)_t­‡éuýësï§KœÏ©Ž^Wu Jé-²¦Å¹t’å® î ‘T:œ å9OÅœýÝÎVYòä™QþÔµ–J…Žm¯×ë³õùŠ…Ý¼¸¸°·«éVùœ.U•ìÞW…ˆ/ŠbĘ­²V£Ñ¶“ßVmgäžkZV/õCú÷{—;ÉG*bßÔvcÓº–Vé¬(¬_¼fåɽ–y¤’Îô)†Vº¨6¡^¤\Y½Æ¥ýä(àÌ•ä?©¯–yЭv§ùédø ‹e®é/‡Â×Ö)÷áü¬*XçÒVF‡—Øb0¬oýŒ•R V/އæQ–Æ ;§D;ä=C3"÷÷£qÿîjt@ #!QŒQR¥Sà¯<ÿ\î,_#ÿ‡Ül—ƒ¾AA¿!W„¹!£êô!{K'D9E=SèëSU™¥ûöÀï{Š®`‹>!|QàžV9ðÔÞŠ™+…Ñʉ¸Õ2xŠ:@¥0¨ø+b0Õ(•Ft úHX”EM’¼QÖd1¿~½SÜ]âúWA³Ô=Cd@¸ÕS"‚|䜇û7FÑò–ÚM­-éÜ*/ì~2ûx›Qx“·[%søÿ(û7Êb]Ð<ÄAQÄÍ “!wˆš¯ pk¿<>¤Á¿Ce º\¾‡£‘¡È@3Œ³¨ÙꜷZŸ:œ«¯Ü©M>Áõ _7(F”¸K¥ÉÆú­¼”nêÀÝ3dÒ…ì­[‰—“pŠ"dºŠÌJ€oå®11¦aRŸwa ®Ù­$eáóëðáÝhæÓ•…æWžo|ÙÐIàûÏTºî-rú >® Øu¥ù$¨ÃçɃHø€@ŒøM/ÈÙÆ@h?„>Qp-t-AÈô÷ê`¬‹¢8H@EÙú{F$tÚʉØXöqÓk3êûÀ‡K"ˆ§b>uV0Ò­RDÞvK»ºŽ³’}6F±þÔÁUÉ’Jx–²w¨¹Î|-?€å#Mÿ¥®¸ÿ]ùSÓî=ýýHá0/2¸·òËnŒéê+æËBCe›ÙÚÁ%+xL†²÷|ÈPš»xM^í;nºÓ?JgN§„G‹çPç%§8aÈ6Ä¢ˆ‰ÿïKM#ãˆ{*"9S¨ ‚ª®P8öT\«}HEnº32×/¾ÜôC B2fŸÊg¦›R“S€>cúlcNû gCÂ=`?hçûAmã±-*l6ì7¯=í¢½PKJÙØúRPKü\ë@ content.xmlí\Ýoܸï_!l€¾Éû娵}HrIs€}äéÛ+QÏ)”wݧ¤W´8ôp@QÐ/×·ÈpÓà4‡<ì»ü?íÿÑ¡¾¬]kíF\8Fb`³ËÎü8œr(în4 |ãsAÝiuW:-S‹Ù„º;­÷o™W[íþd›9±ð–ͬ(ÀTš£þ7 7[)u§qºÅ b‹¢‹-im±Ó¼×V™{+Ñ•¶yä×îž0—{K<’u;+Þ‰¾hP_sÂ\îms4¬ÛYñ‚QËÝV·óHø¦ÃÀêAˆ$™B1ò =ØiyR†[íöp8\öWwÛÝÍÍÍvB-[_q?á²­6ö±R&ÚÝ•n;ç °Duñ)Þ2$Ìk›ItfVCްÀp•cÖTî3á_‡nmï:tg˜Ùò¯íg ó¤«ôíú®Ò·Ë}$½ó{µ½ÄäeïÔ¯xPW—â0•ÅIX{˜)w¹?c¬€ª:¤ÁžÀíu:«íôs‰{x.û‰y‰Ý:—ÝB¾UXœUF¾n8L|¨\¾"e1£C¯’ faÏý‹ý½{–‡tÊLÞÎl*$¢§–ájfŽt­Íqȸ, ãÔO¾0[½›'vêPÔœÕå¶]É púmH#Äæ!ÁÃ+¹õ|Øl'L…ãìçQRðfÃÁ£s¢F‚|åf Àhà,Ü*õžÌ¯<Õ§‚ÙδĩఄèË*Ü¿ÛV4S-/@3M¥eµ×ÚÍ×Ð4fD»hp`-5daÓÆ–/v·Ó\X4ég…{§uäw[䩜# þQFhµÏï}ùdÀIE÷SJ¹»¢™.¦`*<1$B¼]ErP¥ŠœòŽ*Ò¡Î2ÁÛÅ—9B"-H®‡ú*O¬£Úx@ l‘°±¯ÅOQÈÄϦÓÖóÁ ‰ƒwAwy,¨2}AЩýÏ~÷ßÿP¡½ ¼«öö¬ˆÉÚQ$a˜’Xf"§¥äu«Åº…² e’‰`í÷£€¶òžåF3„Ì€¹$XÛpŒÌ†$•ê\bÆ>$¶Z·û+Ý~ß ü%8çaë- [oe³³9¶þòì¶¾¾:¶Õ%Îézw>lkKÄÖ™ÓnëËÃÖÛXŸÛÆòb¡×ߘŸ•C8Nƒ–2ª”¤=L\¶•õŽJçŽ6Y(I€|³ÜÛA¾ÀóŸ‘`¾º¶±,àU[_s>¿ÿÙg{w®}zsoj¥¦%¾MDè#%G…pUŠ@o° ï´|nÊÁ~Œg­7Ø/¶,!âêl%ùáÿ;(òå´ŸC§³ÓâúG¡g2Nòس*¢®:3ª ¨MÂ'ôÀ”ÌtÈĈ2½’…“ò)Ë…[š3 _DBç( ´boN„\07•OM¯¼‘&UuRϤ”IiªC€¸KhfÚŽTÇŠµS剨3Ž©¢H šÉÎ-ó©rp%Y$}Bqa¦Iµ›ÒŸt½4@&͖Ȭ`I« ¿„Öîj(Km¹¨Š!7ð­$θ,Dæ † ݹ¸a–Îry%LJ» U9¢9†21‰ôŒZÑ9•{ƒqr\åãQ©6œR_0ÌPÐgC˜f™#ñÍÚÌ~H|(ñ•%|Ht݇D7¢›UÏ™è*=«zr’6cþ²ª¦¼ ŸâȼóÔSçì¬R»‰¬^ˆøiú ÆöÌߌ0`öÑéékEŠ-<ŒåîvºÛW "?ÍlKóy!`!ˆh©€Lpx¯)ñT¡1oúh€}1Å£2Ç.ˆç&©çSêDX”*Ÿ”/yÍúdgyE±’5—í¨ ¡Òù1”ÑxP†Ä¬H”ò°"†¡dÚX¨U(MjU(²*ºBkrh–UHéD¦SW5Ãõeö4ÈÔ³¯A檙kd®k¹‘ËLg¬ÂL7C؆,Þén,ª˜³a…Vud3äUÁSõzþù¬ÉG¡Ê¸¶9®’¡.„»ÄÞngo·ÛÓrkjêÕÒ„éÒ4‰ei¢þ²49|iÖ[ژܥi²q#šÞîëÉò>Çõ»WØuæ‹sÆçôøboj;o€Ö{ J’y3L=¸8Ò`†ø/ñÓøeüƒûj°.ö|¼Pº`Á2Dœªíqãz¨KðµC"4ÌèC„¸°¼H]éÓ7×’Ã!Òky͇Ϸñ«ø_ñ›“Gñx÷ìäËøEüêäWÍÃVÁÔ"HÏDó›ÿBÌu4ç"[Cê'óK­ZºWkmîp]Ôø(RÁ8Xê@ÆÿšŸøñ÷ñëø¸ù‰†³“0Ódý…ŒÁbÌÆéÕ;šOØë—m‘ñóæ…? ÒÇî{eø»øÅÉcX·žÃëñÉoâgšàë±øuíqL°v]‚¨‘ëb¡&ºùþž^Ù˜kÚ™ä¸5j:Mõæä×ñSmÂ{ÑH¡‡¸ÒP¡…ÖeÙZ>FsÖŒ5¤ÞÐ"õ:ãq£ùúÁ÷±0Ô¥m‡ŽºBÌ É"Ù|,ý9>Ž_ÂòôøäëÆ…ï‘ Ô0‹{XeÄK:Ä¥Œk(§4ŠÕ0ŸbÏ{êTÛ ÍË?„õç›÷ÆÂ‰\r©‚2®&1.ÑHåp›i …鲋®¨'vtÇÆÉ£øiü£zû~M‚Úä2èG¤ùdtWŸX¹ó6æBÎû°´Î¶¢ÄÕ±>} !¤ŽÍ_AP=Ž_ž|áôUóþ;i:Ò±GÇ\¢Ò±R¥1¤e¥ÊâHO’Ì‚IßR•G•¦µª2´´¯[y¨i\¸—(è,[Í{ÖüRÏ«î£,9è8WaTræë(¸Æ_%T +ÚßâcØ"Ç/âÇßÇÏO~«a=»‹‰Ð`ðñ_!:B>~í\Šð  ¸ý°q;í«ÒËÓ"yüwa £Ènþ¡ã¾ª»¼Hè;~$ ;ý5BæÓ~þtêäKøûÖ-õé#þgü&~¿Tçê–2˜ “1Ò1±ú lÜ&¾³Ðm‚ j£.G2»òßüsˆšåߤ”ÛƒS-Oû‡ æ÷x·ÆO|,1Ê[ܨwæÖyML?÷ǯ­ƒáø5°¹¹®MYråGÜRßœiþ<ŒȲÔWXÄ'òÈHn- c¨²ƒ£T®èÐ)`ýB4ùYBØc!›avÕ29N!%ˆl¤ÀM®Ægcj¸^$Ã.¢Ø'_x˜Ø"Ã’ÐÆ91,¾›½YM¡®+öý©kÊŠ_ƒPáíÿ¦‡Ä/ÿó·ÿþ_øí·ß¢—*J<òðù‡Ÿ¤C}¦äyMóëχŸžé!‡äñ;üãªn% •ªåç_?}ü+yøÝ?ž?qùüß—ï+ªšDäß|þýÇ?SÙùKÐ9Šæ?~ÿðÍGöðÝ7þõG~kº™/ü¿üòþ—àéÛ¿Í×_±Mþ—¯¾†ÊŸŒüãßýë?ßÿ38ðä²ÒEóÕW_ÿóó¯ß½ã©U¢‹·?þC9})/R"‡ï?=Ÿëñ1ÏÓÓ»?}~ÿþ=yôöí[ø.Ç5ÝÌ»ÿ„J¡W-3 ‘ó9¸Ä!s:£æ|÷ôñùùc>kÈšwñP¿ÿôQ¼õ©Ê·‚ñÈßå¾ÍÑÜC´AÑ Ú¼‰Î‡÷ɽÇ_ð¿ô½ñ}¿ìH;ãOqzÚ:µö‚?lNÝ—Qn8—¹»€U˜h¼YËîXüõIk¼o4ûý¾ñø2·Ã·šM²y}±`Éö7þÜ.5p9ž­#¥°´ÆñÔ*‘Âõ«¯b+7x*ší„ÄDØ 'Û @o9'áZKÕvrxô}¶µZ{ê.áaQzÄ©,Ú5þË%±u¥`âðøg[§¯*’ÂÕ“WjáÞ™M÷ÁGÊ žŸž¢0¶ÎªN–zâY7 ûÅÐcO­Vzà*ÊwÕ8‘B£:)\plÙA‚§¢±GV‹IØùõQ};|‹œžúâ4Fèw+¤~¸d o¤×Eü䨓UuR¸:`yïlzOí*ÏŽ4Æ€üüÂWæìŸyðLy lùIu°ç¾?—ŸÓx rüì•J¤ °òÊ ÁÿIîžbAÑ Ú hmôECnÉɶB×ÁäÚvR™ÓÛÔÚØ¢V™7sÖùYˬü,D´ÊkeGuoèF§›¸>©­ºþèHwf;03º+ê/õzû!»j§7zìcâ&„ÜVív»~¿ÝywUŠõdtz°öÀvWÐo\òÊú`u¡ëz*‹ý¸UkOGGšN‘Yx³1‰v8ÙæÀ•BÓUü›¹)›®•°õ8D4F®Vß:z.X0Ü^“÷GûNµä7D]ÔùÔþvé¯Å÷_ÈZÁèX’õdt,pa»b{ÜÙzÕ MèB,útÆ-̳ðÖO»ÅŽJv;ŸwÁÙÐðaÅßækß:‡Ðè›A5l=óiºÐz8ô-˜¬]rÌ9tÉáÖi!ÕåKbZÍàÖ°ëɨ&Înt²RgÖÈשp¡ÑNÖó0ó–Ö~âÀÞAt€¡k—ü›ziÛ6 vMcwãcÇ®OÚD3`÷$6 nÒè§ÉfÞ kµ!ÐlKô͈ìÛ«î<|T§¬«³€ÎÈz`þY1Yx³•5 ,˜ÇFía½!'ΧžK”.žº¶mC£o9kÕª`ëqø…°=¡¡Ì}âç±äóAô÷Èø+^sH²dÏØ†a—f=ÙAèÑ#ãR/ÁÈS"¶C Ê‘ L;#fúI9TÁ“ ¹ñ–[Ý5÷ÊŸ#‹â@ŸÑES<µ²¸Ÿ‰æN<¥“Ü]ü[`—Ý”þ’‘{3p`‡ ;²L‰DGQ‚Èܰè1óûæÔϘö‹Å®ªŠR e€<ù¯³^Yéñ ­½oW0ÞÃãÆ& ò© €•$ºYè­vøÖ&X,`:…á$/õ@‚©úË!O2µ¨]>&oKe’¬ÀoP)åSDü.¯ŽŒjbéñ/Ú:¿Ô×ë-&ðè3£ÉŽÐŸ™ÅÔ&ŸNè[{ |Zð}º€×f,@±¢QM-é±k±÷ݹ%%oTM,!"~sAâ_cÁï¡Ó­Š¡J‘ äH“ô-Syºñ=3W¯CôºÁ[îº>Ì·Ð:B1DGÉÔ2e+É€ÕЬ ›Í~¿1 üÊ?¾Ç‰â™|O)P¬^ü$›t ¬s”Ì· üÌN¾%Ê󄊆çÀêÖbCt¥j± ŠŒ:<Ðᢰ;­1­%bîÈpÐá㦤/ µ| ˆÁýÐÖiÍ<[2ñ¢¦S^·'ÇÏ"už)g­v®ñg°´SšÍÆc´Ùg#;×ÍþFT±ºµ¹ä€)ƒ@½Ù¡çú/xžçh!œí:c ©ø/´RÑÝôžçcÓc)ì÷{1æüÄéËŽpVü¯ ,‹9Âé36*†¯dÖ¿Ôi¡¨4ˆ=—àoÔBO¹>r-9ÅÝT×8T è‚#\3‡™GÏ1´~‰MgÈ6hôN”¦á˜ó“®·Há„#¼Íj˜÷5·ƒÏhöLiÆFÅðõŽ‘Y.ì-1ˆ}kå3üM¬ÐSª´¸Ë:Åòc) Q!Ú…óô§.+íÎa4òÖ­¿ð9´ùnNKa"~yêà )˜™ ¨¾&`h$fÏŒÖJŽUÉo5 :°w7¤ºcƒØ³ XåMlîB©>r$pF1-nž„°ÆáÅÐäÒ™Fö`5®µY ¢ ŠÑ&!š»M×òì&¡ú)DCˆ«9ër–ÐÅ£ë…Ò’›¼ PõñfÜ¢6Ù̳ëŠ;'â36V!…àØ›ÍhiÕ‰.8Ю^äÔ¯wÔaÏQ`‘§½e‡åº‡F—_=òº-¹½çÖ˜¿˜±± )H³xd/´.ud1aVÁÈ!vzâîCéËÂg<¬µ÷×LwX<¦µŸlÁµøÔ£K‰ÿú Œ E}'êÈòй&‹Wî)îÄ|¤pÆCò¬Ä@Ï` –‘õHîX·«ÐSâ¿bÆÆâ4ô”dÃ1Öy…cV2rˆ&j”Ü¡¸;W©9Ó‰õŠ™+î$fl,x–„4O섊DÎÀ[nD ¢ ŠÑ'j,ƒ» X%:ÒH#ºƒ:=P{ð.ËrßåJ¹™"~^¤)LâõoåmÀÕ³ø„h”ÝR‡o»’»,¿Ø›ñ0$ŠOë½âÁ§u,.7øk® Å¿¦‘ëô’„þR…f<Œ!ŠôÒHv,.Ÿ‹WÐâ¢QjódÔ.ËÊ¢åâ#¢ø›ÍFâÕÔŽÅåmÀ´øÄDÞLªÍ3l¹0,QTµR!5þpty"ødÇâ²Ð ¸zŸ:p™‘ÜÈÝÅwG Oƒhƒ¢A´AÑ ÚÜîKý¥ù÷@ávg†+ù*rËÒÍ9þLæ#Ï“÷ùÛÍ·:µè/]²÷ñzGXêà]äÍÉmŽ0¹ùb#Ï—lð·4À;9KkæÆÂŽð ö¢¿´]ªj^ï{fTv¯PÀ'aƒÏEêNœpyçòxûè{2ïu›#LBêFý¥íâ¶øI^á»Jò¢ÉÜ>¿3á&G˜,ë²a켿ôlÚ(ð—ãõŽpI–ëíŽðaø0s—|ðwpzJÌÒʾ'k²r„£ÆØ% €½ÍŽuð.âÚ,G8ÜäÒ¸ô³´f :ÂeqwG Oƒhƒ¢A´ÑM%ë¥N8×Ùeg¡pÅà5†–Qèõûý>ìqï+Z¾ÔÐ%™ß=ÖtDê„ÓY‡nú}Þ"ºYèxz•©û Ž4Ü2®Ýb±£}–y˜QŠ÷U…¢C ÑŸ‚l÷2Ý Ý´Zã*e¡p·buŸ\4˜kGa˜4ï«E‡ü‡K½Ð䄆¼ÑÍn·{¬PºW«îS¹¦Qf`.xó8®Z¹á ìùfUk ¿‹Ohü¦›Íf»rYè\ºO*[¸q¡wL‡Ìµl«ÞˆFÒU!jL’ð»¼Y#íJ³ä,^0ý§2uŸéwOUè“ w—È]Œ> ¢ ŠÑæFsO-Û+ æ-ŒÍ½üÉØÜ+¼„ï&sÏœU¤lïfs¯è⽠ͽ°„|_´û€:m¹•ðÝbîy³§Š”íÝjî^¼—¡¹”ð¢ЛÕ̃Ôr&û¾̽0œ ”íÝjî^¼W„¹—_ ß«Í=šÝ(¨j ËöJæõæ^YÅ{™{´„œžDµ9/ÕjµüJø^oîÙ‘¡ —í•Àíæ^ÁÅ{›{bóKiHÕ“Ù{¡¹W-î"`ôimP4ÅS+;€ñ/‹F¹¾I£ì:8ˆua1ï `˜µ€ßgo|xu$Þ ÜÁë?þjÒÍ=ÑÛ‘·K|z¨ wñA£¾fsÓœáâ‰ua¥,eôŠ•]FÀpx083°;Ð2Ä6u¡³†É ˜Na8$ÑÙþOÀ7›ð¸„±X˜öS†ö‚U#¾ÁP´ tW0ÞÃãK^zJ7÷†íÝTôeY3»ÉäƒFe*èÝ2kÕÚ+jHåáeb]X¼YZÀRFîaÑ^mJ €i/Ê­ìxCŽ€ öø.´&àûô°€Ü9“`Éív(h¢, ]ðÙ” ä·ZÀ¬¿@§Í=ž”axаL±|J—ßz£ÙÜgž]Vt¬ ËÒJ XÎÈ…Ò†0`*ŽGõÝëÓÝ“ú=‹t’†žy°Ðõa¾îOæZ×—nî5§Ó†ôe :uÇ ‡ö°w 91oúmæ/•²â]X¤žÕ©m€ý§Ì€ÁjgzMC¤Sƒ6;ãÀ:eù¡ Ãð±=R~z ×Fä±¹“í rFË›ts2ˆ¾,'†èÊ}¡d{OzbL±””0 ¢€ xñÅÁë\Îlø.ÕD¤nuá—¨Ÿ16`o¹«Ž1€ªÙ}(D ¢ ЦxüË‹T›×ˆ&òˆ“nqn+-Kéús^ÙË+o‰ÒîBâO˜wm½eÝEm|ÖbyæL{æB6†ÃE4ç߉ù ;±ï öc§5KE ROsÜ‚m®аâ!験b³É¼È j.óJ!pXoêtýî*èƒ.wü ^âÆYM0pѳÿFl¶Æ ¾S.]Ígûó#Í~o-}wM”îû]Çq·‡sóv,Q­H²è(|¨%,Òú‚ª@= ;êVïÀž';]§uìI3ŽÉ¦ßÌóO!°ToºµØ|ò.ï6á@‚è0_P°–'ÙTJWí\|¨Àîuè·÷ºôo É “%‰R]´šàvŠƒ\õNfÇ#HJ½æ©Ž=iN7=ÂC)Ä–êMMê,Ñ#e­%½kÁà –R–{؃ŋ&y}g¥«é×4çç7\¦/ÌO ª¦IÊyEÄ€ÕŒ–p8^Ž?yѽËJ$‹HA X*å슿÷»È¥w7Ðö£4Èf³ßX½(¾€ÒU*š°ZŒáþ°}v~ðºÌHÚÄóåÑY_{1š aÄv™qÍüŒ''£ôŽ©5—9¬D7ˆ[»â]þ·ù¨T42ä¥Û¹Ïå—ý-÷],ž§²)”\Œ‚> ¢ ŠÑ& Ñ$Ç']&¾Œ›“û¤”{¾æë/¦ ȦJè»$.Ì/׆‹ÍÜÁ ÔéÓÂm³õ‚‡lWð¾,¼GKlh1¥IÇGv-6”]&×âãy¹‘:ä‚ÁÉ GëjbåžvZ äÎb·K_„W]6çF¥½Ës¤{ó8kµS6‘V Š #I>ªUN÷ÓíXF´Ð³Æ =É®‰\¾y˜»¼m•ÑøY9Âë pÓó<ÙëX¢ËLíÑ¢ -¦7}KæÚ¨_-¹L0çã]j‚ˆU´h[Ÿ}ÿö˜p´®'Vî¹u)¸ô®C o†øÐè ÉV“p´tP;¥h•§Ðé5‡»Ý™øƒð¤øã§È‘þÉM¤“BlC)µáÎ¥ÙiíX^DñªRv›¶m!c»ïÊ»§;n¸÷ø«ú4ˆ6(D›³¢¹ÁÈŠæ"ÔºzÕ£ú·+­±WÀ%KMÌçÈ[JƒÆl‰·œ_Чf~ á•{) •y¨þ甡Äl¨°Ä¬ÙW¬N¥+sðY1Å¥j¾&ÍÝÐtê$øøºRš(›¡“ú_‰JÅÈ£‹üº00a©©ó9³%B:ƒ ²N¤.[2ü Ýió|Àb›Ç÷{7*8”\;¥+¶ÿÚÈ„ <Ã3Fn`uBãé)æ(²Uø~0kDJCeêÑÍä…ž•Ëë%yL²µ w\ž†]AX’B–W=CñÑæ)óPÿãÁt¶ìæ595¡\Ìæ'“Ú‘¥™’a>^œ%YjЏƒÙ©^Âʺò^ Ø“}­#FÒw£‚Cŵ“Bæà©ó?6Â9ž.¹Às©OžTG1ØGpÅ5zVæ‚$±¤°ÔØÆ‘á³%vÈ>í¨?•èô~¡;íŸ Ø“}BÛ<žª9<ïÚ¥[6¦½ƒyÞÈ ráý²¥U¸|§§“5l7¸RކÒ)ƒËP¾Vµ¶n5 DÍYÉK,žÄÊ•ÕÏçi–¦´l,w[±ÔŸ?ÿ’9;ÐמDe]øÕð ¾ðlÀ1W)æ\Ê;K±û¤×“_#›ƒ³F.«3±òà1ÞrgIE*ëòEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Ú hmP4ˆ6(D ¢ ŠÑEƒhƒ¢A´AÑ Úü?ÈWÝ8œ+IEND®B`‚PKü\ë@Configurations2/images/Bitmaps/PKü\ë@Configurations2/popupmenu/PKü\ë@Configurations2/toolpanel/PKü\ë@Configurations2/statusbar/PKü\ë@Configurations2/progressbar/PKü\ë@Configurations2/toolbar/PKü\ë@Configurations2/menubar/PKü\ë@'Configurations2/accelerator/current.xmlPKPKü\ë@Configurations2/floater/PKü\ë@ styles.xmlí]Ýn㸾ïSžÝb¨býÛÊN2˜ÍÎn˜É f²(z0e #K‚$'™½ìm/ûEß /S´ïQR–dI¦Mʲe%A‹‡äááw¤W¯Ÿ—öèúå:Wcá‚ £»†å̯ƿÝýÂÍÆ¯¯ÿðÊ5MK‡—†«¯–Ð ¹ üfÃ`„*;Áe\x5^ùÎ¥ +¸tÀ—¡~ézÐI+]æ©/£®â+Qc¤Õ#â|í>‡¤•1m¡.x ï9"Î×6|ðDZÓ"™æ«›.iåçÀæL—ÓÝ¥B«Äųm9_¯Æ‹0ô.'“§§§‹'éÂõçAÓ´ITš1¬gtÞÊ·#*CŸ@â΂‰p!LRÚ% )˜6Ï’³Z>@ŸX4 ³êù0@$h¸—d åëðõ8'F×ã¼FÌúøÄ8‹ˆ‹P‘ r¨HF¾î„‹šùM> Âèׇ÷k\ùKÒ¾0mATºoyÄÃŒ©óõ]×ÍXÅbeØy^žÄŸsÔOäO¾B?G®7’ëÀÖ3‰»Ë*¡!:a‚(8øˆ!ŸRûxе-+z®fŒ˜äÆIGÌTu.ízUÅ¥)éÜ7ŒJRÄŽ4Aj‹”†{´àÓ‹‚-k–¿6‰ˆ2HVõq÷y‚Ë8l.‘AH,vn•Ç×é’`ºh909êvpý*Våìò(þŒ…t5~ã[ÀÆ#¤f)ÅÒ²¿%ãIsí`[¾UQ}]’¯ŽË¸9t o!ÜOVlïb‰Ú•]¤%”]ÄC­ÁöæóžêÈ6<TO,I×£ß -ðpôáKžüX&Œ¯63÷-á’†»;°p—U¢Ï ÚìýÿúûÿýŠÞ³ÚÞ'u“\}ª”Kš`e'žVÚrÂR¤Åœm{œ’{Àsx Îó‘âû¡…ܳ¸Q£V\3¬ öÔ+úr-¬è›#F  5ÝK8ó˜£kN|AwWNè#®~z;.WäN%ð"´±”î÷EZ’´šÜÜn¶×i>—ñ‘µ™•/¬r«YÑ»Ûhf*D~ý*öbg¦0±Lnùq‰h”|ZZg9!œ£z†5·Â‰<ꨢͬ }åûÈ÷þVÕ•ÀkŸøt®ü츆þ Ö1Àe-Íy6‚b­B쥥sß]y‘ûµ>ÉšÇ ¹ecˆ>nòþmùàÚi[E°¤´9À\ÿçoÿÌZ,5r]Q°‹ÀÆuèŽ@k»ÈA}aš<ú*’«dïä‹g ¼L=Ê=îG`¯àËþ8¼Ê€<ÏN¤Í€9Ù:WõZ$ÂvhGÂ@c©OóÌð­ÌL£.7·4¬—ÝŽë‡R×,@Mé6{×$#ñ¼ !îo«úˆ‘=rËèiÇÔï?\V…͸Z„L å¼ ¡t`PŽ= %zTZç{c»?Ï%dïåÔîÏ7“yS)çmz‚ó6=ð¾¥ã)žRNñ¬»}ñþ<³PÍýùf2o3Êyë0ž±?Ï'R`2ÅÝ‹RwÖ· § G ò!G/g?F1X‘l°ÜNò§ºÃbÂlpËd’½çNÉtÆÞÞ”@ÖT³êEÒÏ©ÞZjDsGàöÄÂìGø—P1ñxû œSRåÄf¥ ÓÎtÊNA§ŒtJ£ AÄ»-Ï  Dãisel'°@1XÒ•‘½¥Ùð+Ùè¶$t¥Û’ÀL·#2Ðíh‚÷×mÒHãÞ‹ï‘é¾Òúâ{dú¯ì´øžŽ P:³ ; 0²ÊVZKX-È\äÍß*„A:áÕØvyy/«@Ìz]“ ^Ø›fèB utBÎu8÷ú¦ó1M`9,/Ü•1{Œ£f2êTYØÂx“¡ÑÖ¬º…TÑ2-k6B£é ¥ðÙsœÍOž£ÔÀ®ÌŸÕ™½ÌÕ°Êë ™Yn6‚ÑŒÒ â¼{daÿðpÁC™$·t\n´,Õ°ZAeZLpžp¢c†éðæäˆÁ#Q‚§õmù‘-F;mËgé¡ïáCârg[f™Ý–Yf´e–·o™›æ¯ÃTVôàLê¤ô‹øÈ‰•nuvÜ$³;n’7ÉTÇM2A®MŸBÒh¼-¯}íøIãíeDZÖ:3; 12 Pzv⬜8Ÿ’ +=n—ñkgÖ§”ù¸Óc9b8ë9·=eÎí”`»p(«ÉjO0%Ýt¼J0/q¢Î®ÝÖzìÓÎ<ö);}ÊÈcŸRyìSêã0Â$úbIÒ|œ.Uép‰5pÇ^ë°³T™)»T™)£T™)UªÌŒú±Eì|Vœ‘>º¨cŸˆáx)†Ù:;ëì!I3vIš1zHÒŒê!I3êÈ#س[xf¤ÏAêRË™÷˜”œÕR>ë,ñ}Æ.ñ}Æ(ñ}F•ø>#M|ÿîôO¦g%ðúe‡ƒj#SaFù8Jôù=ƒÆSä¸ô 7eÔT#½}/¹×ºV¾ }?0oº“FyºFšˆÝ0PÜ€Þ;ÜPækkÄdíÃêCü<Öïz"§oC¾c” §u¶CÐØí4F;f‡ òÄé«§oÐñ`[ÕË£JŽÃ£%ÖËSICƒêHõcMa¢ú1éU?žáýUŸÔ•û+ XA’4 ϲËRÓ·n Ø`ŽE´¿£%ò¤Ïwè+“¦0í³Ôö/ø©-L-³óõXL4SKêCtX ™Ô‘eØc¹eÓlaR™¹q±ˆ¶MjÓ‹zE’7—ß\ÛøVÛ¦…ð¼¶=^f,Ҽ̸ƕ;E‘¶°³·½¿8®¹9)?Ç/ O›nx5ûúRiÞ<`ÑXù ~*èÙ ä}7x°­9‹ã:¹—:•ô_zW{f·6ÞÅ^ñ>û¨8{'zRË$7øzI|†A³ ’øøaÃyñ§BlwÄ`Tz5¶B$=m/"^9ômË)MàÚ–QCòdáâj V¡[C‘¨RÔiôÿ8ãá ZóEx5F aì*q/ék€”ö¾È,Lê»þ3^l&¦Ã9FPåwå먺i=g`†Ù>%}ºxÆ6êÌ}à-JÓ¾nôj¬£ŠÐ¯×€ %Öï¨oAõÂqrè&3‘¨°—HÓé éÚ8s̾Ɠ3y/‰÷ü½¨Üß‹ü=‡½Ñ±3® +@fù[–È?âF%’°‚$ÿô¯ØÀ;Fªg/tôešãJkØ4ßi}>ú*(³» ±*§HËE*. óEŠŒÈ¸nÑ„—ß—Á%T€Ëq}´Ö3Ø `àéç›®6V1E”i{9¦pï©yÈF“‘”VTŽÛm ˆZÏìMûYy}ejÌŠÛ1»Ÿi¥Á¬ijš®˜0[‰Yi;f¥ì¬i˜0[ƒYy;få0«iƒo0`¶³ÊvÌ*ØÙ³fk0«nǬzpÌbÏ@ÓÌž=få]âr§q¼ìì€ÙÌÖÄ äŽã3~Ƙ0»KÜ@î4n ˜SA0;`v—¸<Ä Ì+fkâr§qƒÁŸ0Û€Ùš¸ÜyÜ€üÙ³ê.qµÓ¸Ï«*Í9˜iÆñݳ½ÄlMÜ@=é¸Á€Ù^c¶&n žtÜ`Àl¯1[7P;Ì7:ØÙ³5˜­‰¨Æ $ gИ0»KÜ@í8n i4qƒ³½ÀlW! }Ѥ» ðëü¿›7 ädªüøu²1ǶOà7ÀoØcðë~Ãvy€_‡ðëb竪ÃÎ÷ìá÷0:€ÝMË2.Pè8ô´õ•=[âàÔyü½ŽH‚¹ë›{°¹Ð/ÎaV¢b?7{®&#WB²EÏz½ÀÇãuNeÒânÔ)˜Ü8XÙ+ÜGO=i õÕm³ÄünÏl¹Y@ý+Žˆßä] ‡G$£|ùáò>UüÍR' w…ºEaN)‹/ÄD\þ)HHC¤!#ôWRâ¿B¤1í¨Q=—sR£·ÏHaºþ7¬LwHLÕÊ”#å©ÚQ©½|™t½èŒ¹'Ruïˬֆ/SßÃ޾̯®{x?šþA*ª,=3„ççG'sæ°&Ï9¡µ}À/ìnºK$Š A[;ÆéQ'µwÁÙÐ sW7ýƒ5©ŸbbÝz¥Û«ºÞ¾ÏK’ªP…”Î} ¥U_¢ºõö|‰œòÔ$\§ÊÓöñl“ò0Û®ž·òH+ÔªòT·~å©ÉüN•§íÃå¢òðZ.$“Þg3(ÏÑ;oç´‹Í)OM zª<-ï¹wàwÒð{çx«–" Ï÷¢¶Å‡Œ»·.=Áúùí“ß[ÎWh4‡ßcšCÄßËK!`^<éÙ˜çªÕÄÍûåëôòàëüð®B´­XU‹ÐþqRM“¤~§?7„`Éæ³ìð¤!¡=2q}\…]xˆ­ef¤‡ÐmyˆëîžXˆsÚ ÝY¡Ý²q8¶möá lkÖ9°f­«ºõ…LJ§[‰â浯[‰MS¯i„ ÖÓåþ ð$ŒZŸ”kPzf¯@x~Œ·Ï÷Šyã:Æ/¸rˆ? ë_ÕèŒëå* øûàž7Px•—©‡+î<\ñ”‡+í<\騆køàér ü¯ÐEÿ'·%ù¾û´€À’¼¢¨¬8²5M”Yô8¿|´àÓO.R~ÄD~$ññuãj¼Ð5NÀ×"ÿ{Ĉkš–žp\¿J>âW¢"9Y:—¤™CõŽLcab>xKa\ATñbZËÐeL¿a÷jŒßj9«ÌÂ=ùú<ç–®š¶‘{ñ°6áx¬ëJ®™®¢?ÅiÀï^$濘*©³ƒÄ=GE±_Ä/&PéêÚK•xQ™Ô³”ðÒ›‰/Vâ±ÈÏdc¢&X$›àÓ˜½|ŒB¼µ|ªBì– a–Öª—¤ÊQXK$ª ¤l õ t¤c€ki®£Í³%Äé…&g7F ë©°EáBÑÖÛ5dÞãx¹‰Þhžtá[hAq} ­+ ~5¹ #Ð7Då¬Uø¢(žXáB«œÚä:±F¡u-tQMžÿþTLóÑÛeÖFYÞ¼)F7À›¢z7ðz®úÀ ìØÝ» ™C1@q€"%'µÛš¤` ‚¬‰l³“\Ä- ›nG›à­Ø Åb¹~…ã6—^ò7X@S_¿~ýúÕ¤|1¹â•&¡$j,¶â~7UMŠ•õþ %ù°†íµö—»¶ÁBÚTAè,L6ä¸M´Ÿ!ÖâFÉŠ’?ùpŽ#Ô˜¡…=zÓ…ø*GþaC…ž —"È–z7@˜Žý Á„[q<ʈ¸G`¯ ~û§ rü”†x~ýð|Â&¼þÓ(eqÏó—ÑOÆt|Šüu†©Ñ$O¨#?¼Ö´ .uno:ToolsMenu\.uno:SpellingAndGrammarDialog AddAfter AddPath com.sun.star.text.TextDocument be.docarch.accessodf.ooo.accessodfaddon:TaskPanelCommand ~Accessibility Evaluation… ~Accesibilidad… ~Toegankelijkheid… ~Accessibilité… ~ΠÏοσβασιμότητα… ~Barrierefreiheit… be.docarch.accessodf.ooo.accessodfaddon:TaskPanelCommand %origin%/images/logo_16x16.png accessodf-0.1.1~b/accessodf-addon/src/main/oxt/Factories.xcu000066400000000000000000000016661225501747700240300ustar00rootroot00000000000000 toolpanel be.docarch.accessodf.ooo.toolpanel be.docarch.accessodf.ooo.toolpanel.ToolPanelFactory accessodf-0.1.1~b/accessodf-addon/src/main/oxt/META-INF/000077500000000000000000000000001225501747700225175ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/META-INF/manifest.xml000066400000000000000000000023531225501747700250520ustar00rootroot00000000000000 accessodf-0.1.1~b/accessodf-addon/src/main/oxt/ProtocolHandler.xcu000066400000000000000000000012041225501747700251740ustar00rootroot00000000000000 be.docarch.accessodf.ooo.accessodfaddon:* accessodf-0.1.1~b/accessodf-addon/src/main/oxt/Settings.xcs000066400000000000000000000014511225501747700236770ustar00rootroot00000000000000 1 1 accessodf-0.1.1~b/accessodf-addon/src/main/oxt/WriterWindowState.xcu000066400000000000000000000021551225501747700255500ustar00rootroot00000000000000 Accessibility Evaluation Accesibilidad Toegankelijkheid Accessibilité Barrierefreiheit ΠÏοσβασιμότητα accessodf-0.1.1~b/accessodf-addon/src/main/oxt/description.xml000066400000000000000000000020231225501747700244210ustar00rootroot00000000000000 AccessODF ÆGIS accessodf-0.1.1~b/accessodf-addon/src/main/oxt/description/000077500000000000000000000000001225501747700237025ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/description/desc_en.txt000066400000000000000000000001411225501747700260370ustar00rootroot00000000000000Evaluate accessibility for people with disabilites, and compatibility with DAISY and Braille. accessodf-0.1.1~b/accessodf-addon/src/main/oxt/dialogs/000077500000000000000000000000001225501747700230015ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/dialogs/Dialog.xdl000066400000000000000000000041421225501747700247120ustar00rootroot00000000000000 accessodf-0.1.1~b/accessodf-addon/src/main/oxt/dialogs/OptionsPage.xdl000066400000000000000000000014311225501747700257410ustar00rootroot00000000000000 accessodf-0.1.1~b/accessodf-addon/src/main/oxt/help/000077500000000000000000000000001225501747700223075ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/help/en/000077500000000000000000000000001225501747700227115ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/help/en/be.docarch.accessodf.ooo.accessodfaddon/000077500000000000000000000000001225501747700323645ustar00rootroot00000000000000checks/000077500000000000000000000000001225501747700335455ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/help/en/be.docarch.accessodf.ooo.accessodfaddonE_HeadingSkip.xhp000066400000000000000000000015551225501747700367260ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/help/en/be.docarch.accessodf.ooo.accessodfaddon/checks E_HeadingSkip /be.docarch.accessodf.ooo.accessodfaddon/checks/E_HeadingSkip.xhp E_SkipHeading Bla bla bla Externe link main.xhp000066400000000000000000000032101225501747700337460ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/help/en/be.docarch.accessodf.ooo.accessodfaddon Accessibility Checker /be.docarch.accessodf.ooo.accessodfaddon/main.xhp Accessibility Checker Some introducting words: this is the help page to our Option page demo extension. The extension shows how to add an options dialog page for an extension and how to integrate the page seamlessly into the OOo option pages. This is the extended tool tip for chkFoobarA. chkFoobarA This a sample help text for the component chkFoobarA. Bla bla foo foo... accessodf-0.1.1~b/accessodf-addon/src/main/oxt/images/000077500000000000000000000000001225501747700226245ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/images/alert.png000066400000000000000000000154541225501747700244520ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ $Þ6[ ¬IDATxÚíé“å}Ç?Owϱ3{’@·9X`„0Äåò‹Ä‡MÙIŸ¸“TÅ/ó&@R•Jª\q\qQ.c‹`›l" ªrªì2B] a@HH²ÐJ{Ì}v?yñ<ÝÓÓÛ3»+iwfZéªÑÌÎάúy¾ßßý{žGÐe—¢ú-á{Ýk—ÔL==¶nšï@Ì;€Í`Hß,ÊA]4¢üÈÇA ™ÿ'@øœÀ8“`߉U°©› ¶&€= ò¤Pc2Jpþspèqø0öpº‰¬¿b`¤A̪ù‹½[7ÂwâðyÃj=¨þ…Ó³exîü÷Cðnè‘ÛémÐq Ãj€Ÿ|¶m€o“0n6T¿ì5èëðÕ˜?€'¾ÇgXk»Ãã2;ùŸ'À`Õ©Ç`û­ð­q¸o&’Š¡ÒÒÎa=¼ûŽÁpV¹>Þ 3epÀp€Nj³“àFE©Äô£°m |}B¿"®>æÌT¯D~@¥P„JÂê`®…É×`¦N„ì :B€†R߇­·Á×V½°2®fP2×éëÅpPHE#¦Hpõ*ë5 ª`÷ƒ°A:Wâj"Œ0©…­[à¡JòWÅRD[¸Þµhµºí!EàÖEÃ0,ꃫ&€0ùªÒv¿2ËNs¹%?fDRÿ[¶(Éÿâ ¬J„«Aá‚ß a OâCoÕP$qI°ν³°Ó`ØjœÑ#€F ̼züOغMƒ?+[ïJT€ïI¼lh+2"£}pÕ `ƒ&Aœ”62J ð…ÉGaË6øÆ ¸_;|-Á—>•ßc1 ÐÞ`¨6š)X=òøø70['©H°,¡ïrÀH)µ ɟ­·Á·VÀ—`\K¾”Ê1 ¿—/b­ F’°nÈOÂÙ]0SWù‘e©,5Œ˜e5øøpÛføÎ„$ÞßZˆßÊ$ȆY“B…ÄÃIX?b œùµ"ŒksГÐ*Ϊªxßúl¹ ¾;_„¡Ä\ðýÒðÃLB:/2ÔúÁا~3¶N$-eŽÀ\ªÁÆø&`<[o‚G&àþAŒ+àƒà÷š·1Ù¡ÐÑ%AÓ°! æmðÑK0å€a.¡?`.±ä‹Çàö›áïV‡`¨ øDüVþ@1M‚~ˆo‚S/Ãy fl‰²…—›b¬¢ ù(l߬„{a8¾Ô¥à¨ƒ?Ÿ?àƒ~X7±ÕpzœwÀì[Çðr@ )ðqÀúÜ~|wüåŒÆšm~“ô·xy"øÍBðg S°æjHŽÃéÿ… D Œêe$y9Á/€¬Cü¿àö»øŸ€17ΗÍ^¾7â >RÄ` W¯Äœú-L SªŽ"»‚¢¡öñƒ?1ã1]íòƒ-ñ>ú3W Â$?„à#ÁZHNÀ™=0%@&/“&0/ü¸¶ùX~ð5ø?2™¾¥ÎÒ¨† Òpõj ¤ Å¥úæ¥ ÖðöÍÀ·Ô Z¼¬áž_»Ì§ióÙ¥Ž Dƒ †Ÿ£ÊLÕUeµ)·°\0â8_< ÛïhØ|WòC“<ˆõýfG\ÆÏ.5 ¿sI°z]Ã1<ï€i^ .†FL-ùÆcpû6xD{ûc±†j­êùü‹%N'4A«ÄÍ7ÃȈß²ÔW«0=óÖ[8/½„óúëpþ|( :‘3j‡ü|/<þ]x¨§A–ÁžÏ$˜óI~Lõí{<·Á·Ü’îÀ_véa¡ÜUWa~éK˜<‚q÷Ý×\ƒ˜˜@ŒŒ ††ÔctTi„oD\wB8{™Ét´/]¶i2uû âÊ'X?|þ´Kwõk²8C€„nÝ.iHé¾oèNž‘D@í‡eø:]Ü‘## ð?ýiD"¡S!Dcé±”H!ñ8bíZÄÚµÏ#‡b±i‰òršvy¿vˆÃ`Rùòº½L·œíZÎÍVà£ûöÇt÷î6øšîá·næè¸ÝFÆÖ­˜?Œñ™Ï c1¼ïî„H­·„~–B FG!‡“'‘~¨¾·Ìà/&O qJÀÚqp6øºûÛ¬@2ÃÀ¾EºoßíÞ]ÖÉ# žŽJ¾ú+WbÜ?ÆÝw#ÆÇ=I¾»kzíëJ¦ é4 È÷ßGÎÌtÔ’À=PJ&Ã}ºÑ4ÐrºÉ Ú|K©}ÙéïëEnëv Éwëùt[UOlÞŒñàƒ[¶ b1„ã4$ß¾Bi÷{®9H&¡XD<ˆsòdÇwªð-0Á„Q Ÿ`Äm9wŸTÁеÙÞ7âü¤rø$ú^®µîôõíK¥!Â’erÁÁçkïõð0bÕ*H&Õ j›ß’¦ZÍ{¿³,å7ýÝNޱ]Ê×í6@?\»ü<ð/p˪÷M?q ÷‹ý*ÎHþ¶m…¯ëµz«ü}ûF`Íž˜Þn‘~ ÐׇèëŸt£I 5àsÂG=2ß0蚪" t"0ï†ÚUE å¼_³¼þêŸáF ±¢&ûKK¾™U0ñc¸ývøæÜÝßX¨9'¾–¾‚]xZL6«*×û2ïçàšÓ„TJ=Ûv7mRÐ”ÈægMŽ4|b-áîbòˆë`DÀÑPœ‚€½§‡:·$ §‘åó%~DHà¾/¥l ¶ZE–˽´A‘Ñnt`ôÁºUpÿŸÁ"µó8ÄJÊ{¬·Ù—OôÚ Ï#§§‘Õ*"‘h9ô{þ¬ +• T* +1wŸIhzO‚4@$aÕ¬8£JaX%0k`É;"zPú=d209 ¥h,êªÕÔß(šº[{H аüŒvÌ7 aFÌºŽœhîäõöꡯRIX*Áðp“ä‡iÿ{¹òìYÏè±K´f ²Ö4Ä-T‰éèmY]û/›Ã¾Þ¼r9œ?ÆÈfUFЯâÛ€ï΂œžÆ9yÒ«ô8 ü¦@ÔT_§e *E†Ý z$.9;«:|fgçÝtÅsþdC d.‡q™Í6í*gjÊÛTJí$ÐÑê–ËØ““*ÔlLH©„=5…S©àí«íÂೈã©Vqr9d ÝÛ™žÆ~ï=µš8bcÓð²U8ÇsŽˆíóV g2ØÇŽ!§¦`ݺ†X¯«ðPÇÿQõ‚8·,ûÇ{^òÝ1I©Â<·ÝËÍärØ}„ËÍùŽˆˆÃØZ¨äD…õ²ZÅ>}Z­ú¡‘ t2ì“'›V‰I~«Ëj'ýQbÇmøÐma²ZÅÎd°Ç ¢Ø Ü5*j / ‹²Yªøö… ^2¨þÁ8ù|ä@d@3X­TF”C!'Ÿ§¼s'æêÕÄú;ïPzþùÈlÑø`ÍgÞÕÁ‘”‚zÚÑ£äøCÌ^À™œ¤~ü¸WˆjÀ‚ó2ba`˜†“• µ£G©ÿñHÛn}®@4°­4AÛ<@Ä"¡¹šNJoñ‡ˆâ`[Ÿ¡ííkèD›¹Š¤_Ô*óEef ÜÍA-»Iû·M’õ "HÀsÃõEÄã*œžÆ>qûÄ ÷ô°©~aŸ0Ô±¦Ž…ÚCÞ1THhÒ8œ˜íãE/‹€16Fbûv’wßM|ûvL}z¸,—±Ïœ¡ºw/å]»¨ìÝ«ZÇz×'=C[Ÿ(FŠ(Ö]  ÷Ž­I¨¶(õ, Üq˜kÖÐ÷•¯þæ7‰Ýx#"•jˆ¹f ±›o&~×]vì ôÜs*cØ{¬='À=^®™÷aïkðAF…Fˆ¯‡‘«aM&b7ÂÙß“GÇãã¤x€þï}øæÍ±˜úãx]ÁBŒX ó꫱®½™ÉP;~Ü["ÖÃ’¯‚‘‡ÌÛð‡§à×ÃÑ:”M ¯}ǡڕ!uìèXâ-*b=A7™% ’Ÿý,éo›Ä¶mjQ¨>GÈ=2Ö¿U¼Âó ìÓ§©ôQ/lå?ÓjøD2‡àŸÃî§á A ! Qg?äÒP…á4Œ& &ZÏo×;‡Û¸‘þ‡"ù…/ R©Ð-âüÏîkcx ªÇŽQŸžîf¶‡šg©:C?{öý^ý²Ê hqÔyÀ1äQÈ%¡: ) Úh®#ÿ~·ÜBêˆÝt“w2hËÓÃ}¿É$N¡@íÀê'Nt£CÚ³£‘öÔþ¬ÿ)Øók8 Ì ()w€’ÔQÎ_H”`æ)د‘×ÃÍÃÐg‚tÜyš[SèNÛßßµq#Æè¨·< |v”Œ”££êûûöy…"Ñ]Nvø2ä~ðsûá§`Ï.x[´=ë¨[ÚWªT‹@»‰ÏÃ[î‘2›à–å4ª(ª™<ÑŽ“À©TTŸµê?(ýÞ`¤Dêï»›EÈ.}4¬©¾ü[°÷I > ü<çú5掛 vI4s" “Ï)Ÿ@ÜŸÒ!¢˜»ÑŠì¦PÑ™™¡~êTSßl¼_ø­©tCÃ\Žú©SÞ~A]¾W°õ_Ü{¯î†wBÀ/ûÀ·ñäö„m‹%ò0ù¬ò ¤c|j@Ÿ9Gãœáà¢Îk væ õ³g‰Û6Â0æ½1o¦+j'ORýè#m;¨Z‚oèÃísP| ^^ÑàÏ„H~Å>Úé#$ßãß,D¢µ?BÖ„Â ôÃDLðB»)aäJ¼µr%ñë¯Çö$?èúßBP=vŒÂ³ÏRþÝïpÊåN²¹Õº§„‹”´Íß½sà 0/ l¨ƒLL‘`Ð%Ñ:.í< ŠEo“èØ 7`$ˆ p‚ˆ0 „ØÙ,Å_$ÿÌ3ÔOêdx3Gõk-Œ+ùE%ùûž„];•ÍŸ](øahG„"ý6Ì& ?Ãý*mljF†&&‚gÚ/ÇÃMƒJ)©ONâ\¸€‘Ja­_Ñ×§¤_?¼”0`ÏÌPxñEr;vP9téëËûpçL†©VŒäÁ›OÀÎ]pÄçå/üVhKTD`†™8Vè´±ÖîÓÁ ªcšÀ•ôú™3Ô?üPmgYˆDB= Y¯c_¸@åàAòO>Iö'?¡¼o_ø]âô!t¨—‡üaØÿ3ØýŠ?§%?»PðçÓl.MTÙ8ôÀ Ð n¿î½6 @Â×SßÊqšQs`€ä]w‘¸ãbkÖxýµÓ§©¼þ:åßÿ[Ÿ,:*𠬦ï%y29{Ÿ…=¯,3øKE€vCQ‡Ú È™P†”.%Ç‚;séëe4-×òï¸bj-7 ™ƒðÆs üV œKþR - ªP; Y JCÊôü2´ù¤>˜ÞÍÀì!Ø÷<ìy¹Cà/5Úšƒ*TOB.¦4A¿« ÚTãzE´_/Ôœ= o>{vwüå @[T ²–‰ Dïå Bã|wÑF2‡aÿ³–üN  jÇ•cX…þŒø4A=é ˆFëvö¼ù¬òö;þr  `Ô úžê6.ÂPZ“Àh¡z%4ôߣwïyȆýOÃotŸ»\«cà/'æÓFªÇ WµƒÁ´ª"ÆDsæ¬WL²QúyȽ o>¯hðg„Z¨ÙQðaùvZ¨sÈ:È_ÂÈσX ŸŒA·¹Û·®“øz„B5ÿ!ì{^~YŸá2Öó{Aß—/À¾*”7Á»q°Õ Z@ÒTêUf`jù-ó¥wsÝ>ÀÿÒEÊðçIEND®B`‚accessodf-0.1.1~b/accessodf-addon/src/main/oxt/images/alert_20x20.gif000066400000000000000000000012271225501747700252570ustar00rootroot00000000000000GIF89aÆÿÿÿþþýýýüÿÿÿÿ ÿ ÿÿÿÿ45ÿ9;þKNÿijÿ{|ÿ•—ÿ˜™ÿŸ þ¥§ÿ¸¹ÿÍÎÿÓÔþ¸ºÿÕÖÿØÙþÜÝþÇÊÿËÎýíîÿðñÿÎÒÿçéÿìîÿþÿûÿÿþÿÿþÿýÿÿýÿøõþ¿ºÿÓÐþa\ÿ…‚ÿˆ…üçæÿþþýýÿþÿþ ÿ ÿþþýþÿÿÿÿ'&ü('ÿ**þ1.ÿ11þ21ÿ32þ42ý33ÿ55ÿ<:ÿVVÿWWþZYÿjiýmlÿrqýywÿƒþ†…ÿŠŠÿ‹‹þÿ••þ  ÿ««ÿ­­ÿ®­ÿ³³ÿµ´ÿÌËþÌËÿÐÐÿÑÑÿÛÛþðð!ù ,ô€‚ƒ„…†‡ˆ‰&WO4EQ)ŠZ;344šˆ/48GMKL ›@$†1¢7.'+'?85C"„% š3'‚=ÀU„X¢4e)''>8878 #ƒJ›7¢(,Ý™aƒA4Ì´gš¢8[ƒ:573VÒ-ð™4² z P¤è"Ê@³IÉaÇ&$cÈL±!À¢¦ƒ¾Ð(‹'ˆhÂQÁB'’dâ$!€ ðrÐSèC5f<Ñ'M2’<Tɘ 4Œ€Q$.,˜áJ–P ;accessodf-0.1.1~b/accessodf-addon/src/main/oxt/images/ignored.png000066400000000000000000000026361225501747700247700ustar00rootroot00000000000000‰PNG  IHDR''Œ£Q5tEXtSoftwareAdobe ImageReadyqÉe<@IDATxÚ”XIK-G.ÛvžçYT"êE]ø@ÄàJÙ‹‹È&íû úÙ>qcÈÛŠ%‚nTœÏ%¨ˆŽx}õU¬Ë©ºUÕíCuWõõ9ߪÆÇÇYBB4“1ö+×>~übÞ&¯¯¯ÖѦ///®ù>~áão}}}Q±þ¸Z®ÿø¾ÿ]bb"ó<Ï ,,8zn&õùù™=<<@¿òóúûûÿóøó‰\ÿ0®]ÌÌ”·Q‡$%%1Ž!ÂÏÿÄ9|âÖú`ú&€a®¿Gu‹¾ü~hhè úWâ‚t¥~Ö­.5Ýcs5ððk=~‘®t¹N·Œ‹ga¬èâàÛ³ ’sNθ\Jç@ k“×ø˜ì›Ü¨Gª tjj*+,,d¹¹¹,;;[yæîîŽ]^^²££#vvvÆžžžÞÅ?9útAg&)))¬ººš[£À¡%%%èÖÖ;88 Pª¯»ŠÒ-VPPÀêëëaà @¶´´°ÒÒR¶¸¸(rY(9çqDJYYkll|0*EEE¬««‹%''ÇB¦àË%\X¬®®.î^prr"4þÏ999ÂRÊý8ooogSSSq–¢£ƒÅt9==\’ ¨,,¬ƒƒäå屿æfáb”~ì™üNçjkk™ž÷÷÷Ùêê*»½½»ç ¬¦¦ÆúÁðBzzzÌBM®õ\ä™Á*H ››› (úBXÙLÖO™`=߬ं74zñÀÚÚZœùƒ€-//³ÝÝ]e®²²RðSë¹òM~~¾òB$UpÌô•MMMF`KKK‚›ëëëÊ<8‰@sYÏsÕ7ÐÇÇÇÆ—D"'0,ŽŠquu6`qyNÉ1¤·“" ,0pS’zqq¡Ü“––fÃ@‰$J €Ôˆf]Øöö¶Â#ÙíRÁÇëE O'iÉB™1•"é0ÍÔ*È™T°†¼¦·ôÆ<'GXéþþ^y2?®Ù€ÍÏϳ %wIEÔëÍÒ’‰s1Ëén¥ãùù¹H'4üñõAÀLV«ªªbr+ eoo/v/];Ö2龦î=<Ì¢\×çëþqÃu]FŸf™íÒîÉ‹˜V‚QAË!¬DvNšWzÍ¿ûžÒ¸žS¸e€lë0nUɪÝ0ùô,Þ÷ç ûÉ«GLe`ÇcšÜ\AÆGðYÀMÄoZ|è1äÛ7!ë®ÑàµÏM2}>þÙôþØ7¦q»·d={¿Žl5Á»¯#ö=ú+e'H%B^ß–_ú$jÆuÜ/Ì* ‘QܽEŠ{¾Šl-ÅC¡àã^+•m뤯`p.Gçðì{Qç凤|ºF`ÞúIãÁfp%úÎ Å¡2¶ž qŠî'Egæ "ƒCäìÁø½äç/Áïó8ÆjGTÚ©ÝuDí™í,ÆšZÑT5UÕT3Ñt¾¥Éj<²_ãÛ÷jSµëîxQ/N0NL€¾ÀÁo 3AWxÈ„l?L¶ØÀØÉsH34×¢Kºh`U0â@X‡:Aš·”ÒíÒ ÉsLjÑ4Q°:$ô2w" h´qÝ©”ËIã±t”Ú¥c$òÒP¤ ÞMW‘Ÿ’ûn¤{±†;H’¡%Î,˜ö¹ªéD>¤)d´Sdb+òÁ‰Bsdíåì|P“ÉÇó£“AÜI0í }î~äØ)¤Âúkñ^ùAƒþv ï_=Ôÿh˜~ dhNý4ßÃä9®Ú„[× ŸÍàO}‡¹kª-EOì!|óË ¾±ŸöªüÀ­=s'ft“­<ÿ~X{wß÷ µh«£›±“OÚÃÇÃú ‡°s˜«—il³^˜­Ò»n[cË­n˜c`eÑÓ³aüÄAÜ ½43«ÿwkhH¿‰k \ßÇ€œšÓEJ² 6¸çJï_ .ª&Ö;ÙIEND®B`‚accessodf-0.1.1~b/accessodf-addon/src/main/oxt/images/repaired.png000066400000000000000000000050151225501747700251260ustar00rootroot00000000000000‰PNG  IHDR00Wù‡tEXtSoftwareAdobe ImageReadyqÉe< ¯IDATxÚìZ{lGþööÞw¾ó#~ÅŽãÆN£ÄJpå¼ P A­¡RRRµ‚?ójAj¤Š©Ð‚„j(T€ ©ÿTÉ¢D¥MÚBPEê´F çå@ÍßïÜ4:¶|®eÔi¼™Þ¹ãV 1pƒ+ý¸Z±¾õ«˜L\À±+¶°‘H\XJ$~qËŠ £÷õ®Ç…ÌkKϪ*à-ö îë•>œœÁ<&b¯by¨›º·¶Gƒé½)ôÀŽÑž}Ÿíß‚ó™qäõä‚z¯3Vfg%½³ŠÞKàª÷™¼¸'fFÑ|ÿVG‡°¶md³ˆ7‹&`ºËßl]±S¹7P$7¹xÝTµ`J@t‹Þ™ ŽYfÅ,žg%ð•çÅu]ÃsãX×¶V|îû¦=.jö~¦wõº€7†¬6ÛÄX¹MÇÜžWF¹¤wÝ*£Šlx•˜<µý‘§ñqê=Œun ÓëžY,gFºVbVùWc½óE+s0V¸&d¢ðÊ,ØfÎø›WúÇ”i´Pn%IØgƣƨÃh_Û²Q…Ÿ^’Þ«ÆÊŒª[FÕ*¡ù«€ziù”åƒI‰óªÍçþÿ+‚C3i\pöö„¢¸F WކIL£“Þk½K981Kp*ßçV½SÇù+À®•ð«ožDg~”L™·»T1SôÒl†#•VÀTM@y¼$9n°Ïd‘#®0¤‹ŒrQ½j°ÖàÔÐX­n¼„]ƒðØÖgá÷„ð£¯FOÁ$aé«ÖBŽ\jŠQ-}s&uYàÛlƧztCʘäNÛô.¦µ@dÒ¤ÙùÊ3¤ˆT–^\ÐK¤‘±–õÎx ün|¹x݃DŸº Å ­mèLš“ òn1‹"‹ ¹"üæF30Ü ÊRMpr LŠ äˆP*Ï£%r:’ô;Kr´î*˜U̺J âà­$>?ºYz_Þ!dÃLC®u ¥àTÖ4Z‘ ûܬšIr^5ÜÚLÒlUú`æb |½i¸C¢·é^Œ|~Ö…=÷:ƒå­ó‡ðë“ßµ=Ç-ö`ýžR¤òKUÇë´Ðàæ‡9wò.Õ—I£òô^|ìz”PÒV?^’VSðçá¥OZ¾ÃÍj÷nUo'üŸ±Îv$$^y‡àdõ>¼7v/~üÈÛ芬Äsÿ½EÒq¦ªÛ|lqàm£nË3Z1Ð`5þ^%CöήÁó¿…¶Pw1ª9 …&#ÿfyä+žŠW<s¼rð4K¾ cR]p²êYT—,ã;½Toó(Æ€¾{Ö,¼ƒ±ZÝo•T©Oi£™FF<¥3·±ƒàľò2òú/ŸÞ‹ý ?u9Ÿ¦<¼+¸ŠÜY‹£l–œê v–G ü<’lZ\ú6áxïVw§w‰í½þ`o¸ 4­Ì#–½n·SNc N¶ÅÑ’~¾3´O u 6#¢îÓþàí:XOÍán_×À2o±°H*q$È`‹z±ÞÛ”åcn€¡xáeZiÔ[|mÓ9í²®9áD¾EàÇo÷ M5¯µºÛvP…Ï*­Ì´Í éUIÑâ?ßTïBãAoao”×&w´Gåv¸%uµ$Ö­DHœL*Z?¸dx¨Èå…w±–‚–EšÇ‘—“"Rý’ê >yÇO)‰HÔÜ«|ÊËýá ÔBëÑür°©ÞsjžEž')¿Q!¹pˆ.ÿÐ)ÊÞÑcV ‘bGO´´Šz¸Ï8fuÃo¹êtQƒblHŠÓKÉmx5ÏŠ_7½Ý'NìpR/Ö{£f•-­(g̵¬h?². oõ¤^úÿÿ­ò)—ÿ 0™ú?5ôDoIEND®B`‚accessodf-0.1.1~b/accessodf-addon/src/main/oxt/images/warning.png000066400000000000000000001541601225501747700250060ustar00rootroot00000000000000‰PNG  IHDRìÆ¶¸0 EiCCPICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüï5”‚bKGDÿÿÿ ½§“ pHYs.#.#x¥?vtIMEÛ  f¾/¢ IDATxÚì½y˜eÙUÝùÛûÜ9V•„˜ŒÁÅ`aÚÛÝ6m0¨Á¸qÛn†ÆCV3È´lDIƒDÛ ,$Œ$HXÌ ‚B`À–”†*Õ”óœ•óÓ»gïþcŸ{ß‹¬”2’ÊÊŒÈØK_eÆ‹|Š8÷޳ΞÖw'‘¸]p@0@™ýå(/€ø‡ŠO/â‹{¼.@.üýê£h=€Ø9Ô—¡ô¸(î»}&ÏF·&ìþ«è®OG¶2yŽ ® ã‚?”!ÿµŸh€Ì½‡¹Ï'‰ÄÓ IÂNÜnÆv™#ÉF€î‘2{ÛôÜóûóソ?õó襷ӕcèÄñ¢ˆ"ꎫƒ« 8Tè‚àý]¬.ü%Êî¿KyÆóñÝŸ&Rv£H³ "²ö à:ÇÖíÇõÙëD"‘HÂNl  \1™"LuqŸ÷GοŽN"Û ¢†˜cÒHÓ¡Š]us U‚Y‹<Ⱦ øŸ‡»¾ýدDv|¶ˆ ѽ2ãä!ʶöZ©@É+˜H$’°[‹°Á}°úò!_9ø*äÜkév\¢tíósä,U¤Ñj4"˜#q¼…ðB©í{t =® ^ǪSõo Ïyò¬çŠv»÷Åûæ¢êù2ÂN$I؉­‚ʬ ,n=ýáŸðÕÃßÍöçaÁ)RÀj¤F”ëä­3Š¥‘sû~â˜RÀm–Õn…j—ˆ—‹ÌžWAªÒû'£Ïzþ1_u®týQMë¬ví-úNÂN$I؉-eãØ•G|ù¡oEíìØÝRÜÆH¬°6IÑó@õ pwwG¥ÐSiéëöýÆÜTé1T@ú8AD/¸}<úìcÏùªO‘îûf©ûÚ Ùt–H$’°[ƒ«‡é‘7ùêcßÊö{.P¶ÙäÆÕѪ-‚jÌÕâÌ…ÍÚòêŽÏGÞCþÚ‚Ô‡ïÓ(›£BÁ©Ìç»]ã}fŸ…~ìËÑgÿ=‰4þ|y"‘H$a'îxÆž²ôð÷¸;žUÑ«jÕ‚ã²fø qp‰¦³bà2,3²›Ðfÿ„l˜x‹¶¯nJ«­îT„â‘6(½²ºó+è>þûÐ]Ÿ%YÃN$I؉;.ŠÆ+HAÜ@Ç~•Kü&ïNÿ$;ž Ö)ꆉ¢f-u}{QÄÁ$ˆ[c<¬Ênìî3ùÄot[û%Û8Úy÷¸wYãN$I؉ÍCÖBÏÐm=4™Y½ÂÊ{ÿ…Ë¥·°ý£Á'1O=Ôª‹Õý¶Wˆ£)-šÜŒŽ"fXWèý¯3ù¤×à»?SÔ$f¸–Î9íD"‘„Ø<„í5Æ©æ„ËÌY|ï?uÎÿ"»žcø¤ µBêѵí.ÄÀ–m¨£Ç|º]·]LŸó™|Ü¿qHÜÉè:‘HÜTd‹kâé=jeíNsëY}àΙŸgû³ ëñ k÷ÖµmÒ(²ÞþŸçêÁkÁ*‚”+LN#ÓG¾Ökúçâ`âˆX^üD"‘vbó ýZƒ&÷ÊÃ÷ùê£ß˶g+ ÷ÄØVSÈŽªbÕõq´ê¶GÖ®ˆåâ­—M‰^ôVw¨ò)Ÿôf¸û/Kª %‰Œ°› Å J+Ú—ý^¶=£0¹;ÈÚ4nÁ"ŽŠbUPUÄ7Y·^2ñ6æMë<ÔÔ ¨R#+ J‘G¨û¿;ýs^jP‰D" ;±Iî0£x‡Ÿ/~ð[évÊ]5ô¼ÔŒ"c\R*xÅT‘ б%}ë"ÐÆùmغXÔ­k:ór ;þUØ‘—¹á¸×$îD"‘„Øøp«çï½üþo¢øº»²0¨‘ÅX[{›{v5ßÖ^´j…å§‹PÕ©"ˆ(UcÖ»ˆcf(Jç ïÃûzw*YvJ$I؉ €y ʹÏù“+ïÿ®½œ7“ÎÂŽ âð«ŽF³ù›Pš— ‚èd8Lˆ0H™j‹®½} Œ–œâÞÞ ºòfìáÿÝ}záðÚÄÖœøÓnlm‰Ä–G6%ni+FE)#oPO¾Í¯üÑW0Y€…g+Ý«ºjS½³ï?W§úçÐ}ʯ#;þ¼Ð´ÈL¦(“k{óäN$‰Œ°7ƒZ̈ê¥YdöF™^bùƒßªÒmWÊŽ–Z®1"5¦Åïä¬ÂD¤îýbêâžA#µ=|¾<É:‘H$a'n*bZK[šÛB,Ä;@Y|èߺ^x™Àdw4—Áà–µE2;ª¸9*{aÏßI;Ö ¿D"‘„¸•¤­Ñ(63œ6¦g~×ûý¯e:1¶o‡²] Æh”Éœ©Æž¨Z°*”²yüK©‹{\<Ž,×®dí:‘H$a'ž–[ÈÀ+ƒi–Û”•^H•J)‚ì2ªÆ¬2ÅKŒHÉeKQªUºf¢ ñÇ¿_>à‚}ùÒ|,‰Dî ‰›Aú Þˆ[`å¡—z½ô>DÝ&L¶Ô¡Š!Hy ¹ó×Çè\š)HÁWA'ð½_>îÐgDH$’°· ‚”Öv&®Ôóê+{ÿ&Щ³m‡á„Ìh8ZE„=*„Ýá°ñPâa1ªMwò0ýž/ǦË#açÀF"‘HÂN<õH‘¡MÌžôyõ¦IæÎ•÷ÿ+¨ËÔUaê …ÐßviÂ(mo…lðõæ³GLèüA챿íîÓ6Æ5¬qQ·L_^"‘HÂNÜTÆöðwöÁò2ˆ;$DÂUkúØp;óÀs¬ ÛÊGst©È»°G¿Ö¥)½ÅÁ§‹yö\žD"‘„¸¡ÈÚ#åíb8µ‘Š<ŽH¡¿ô!¿òø4B/€³°Íé¶ûLE2d|zþ—èÙ‹Ö¼—|H$’°7„HxG5V(x‹ª(]cÎòû¾Y½‚`˜j0¹ËA­؃ŸôÕom˜E eåG°ß†!b¹B‰D" ;q#dÝ¢>÷=Gú[¤´€¹guÿxê÷âm-Šöe»¶HQ¹:¿›B^bàîezùÅØñ·øðhæ%‰$ìÄ Ý"¡`֚Ĥ´”xÅŰK}ñáïE¬(æLvl—µ”¹Œéð”Ü\ æzÌ GNý3ìôïú`ž’H$I؉ˆ²£ë¬«eéýÿ›ž¦ªP¦AÈî0¹«2©‘DŸ¯]õìaÖV¡¦¥¬À±H½ô {>ž‰D" ;q÷‰Dý¡Ëû§Oüf³˜tê&d[K‡3³1_³–fU™€ŠGòÛ ±7§” pàïÂò±<Ö$‰$ìÄ:1”°éGŠ[:꫼\ÑÚÒÝïÚ¶X°¹(Zæþ»ó-5oÅ£î/t¸ö€àæHwýû0½2\¢!­Ôå&I؉Ä<\ £Æ¼µ36x¯>ðíôËG¢[\Z¥J}(‚HÞ^×Û1H*Ñß²|òÇô{¿ÚÝ+.ƒ@†;ÉÙ‰Dv"1ð¹F›—Ñý¯¾xòç˜ÔI¤·Uo£ìppÏHz="ƒ5cnÝáŠ#ÕÑúVlᅫøz–âÀ¥ÏÅK$’°‰kÜ"Þæ®WOŸ]~ð»Q*!©YÙ…m»A»l*[ÿ‰h}•ù´F{™‹²øcÔïðH‹G´-t©C“H$a'W“е†³Êâ¾ó™Ó+{ ‘ðaLËD²LæM/qi%4Äe˜_ÿ†¨ÛÀTéμˆzâg\½„8M&ĉ$ìDâš·‰@=ùv_=øfD„êÒ=ëLœ²Í(ÛâÓ%ç­×½¶nŠ»Œ¤=KwTÄ :§;õôç~ßÝ£G µÆ‰$ìDbÄ@!ÖŸ¿wéƒ/D¥âî,xY“’&w¨4³ýX×úºGZÜçl8G1ñQÇÄÁ µ,RŽ~¾ø¨7‘÷\ÀD" ;‘hDÜ’¯ý^¼wõò#ô"t^èeÚdH!Rã“]„…¦ ^“²oäH4k¨oÕkQÄÃ;»¸‚ÅAä$²ÿa+OœÍ"v"‘„Ø‚°! ÛzæÇ¬LO¿Ã—¼†®Uµ9r‰îð…]Ž.@o†à˜ % e]G¢!Òö¹·»‡li[Ã*Ä¿aþñ3é¯ÀXÍŽkRçf´sõ‰$ìÄEÕM½¬Ñ‡+â V¢]—Y~ÿw6Ókfð6C,êLv ˆP$&‰ÖPâÏHç¢1"9ð q­ï`ºÿ›Ý]åÇ£\qÞÚ‰D" ;qçÜNS­ö6ß+Ct¦,=ü·‹ï±˜­‰Nqs¤ƒn—¬oC 6 û)#fÙ½YœýŽš²°òÓ¬x‘C?Qk#zǘæ&I؉;)Â"lëðn¼3ú³äË{^…x‡›Rµ™{0Å"†F¤0Ùiè¤EuͲ"äÂ3){3®ŽË܃ê€+U CÙ¾øJ¦G_íacÚ`b€¢Lr‰$ìÄÁ ·€ƒPñ#¯¼ÿÛѺ„·n%gér ì†±Û‚êš|}“PkB*­RÝMêĸ—;åì¿¡žýUF ÙYÈH$’°wfÃDíRÀ…凿ߧgß$!‚Ì×FE(´¨m•ÉöAb³}OoÌŒýÔ¯‡_ö ¤3ÛŽŒµkCeŠ?ñ ø¥÷º{T»å*ñ´D"‘„Øü!6HÓ®– …zùƒ¾úØË¨Rã&©¡j6UG ]q­m/Ü-Hd"ÍdHáfÛÓM¸É:‘HÂNÜ©œ·‚b8Ëúz[¤´¨ÙŠ€ +¸TcZ tÛýIF×7 & æ›ÄaÈ#/"Ã!ËcñǰC_‡O/ߛ˟H$a'6ïÖ?÷ßdG‰ñ®þ±ñþÌ£XYswhs‡2ÄÃûz²]èvHß\fFÙ ~“P—6ÝÏ.´1¯XsqfºÕwÑúƽbKs×}øÐ¯qPK$I؉ x©õš—ÌàÃ|µ‡˜‡ˆ°°+oŸ ‘! ÃvJš,ývèÛ¯sר ]Ã6ÒYD" ;±ñ"ëõaå}߯žF0Tš‚VR‰ z¦pæê1{¸­ˆyë¹Úbˆ^/ÿ¦‡_Cvcà\3šÐÆ¿‰DvbøÚZP¦ÿ‹O¿ õh*3Wð:GÒs »@2D»ý—S(îˆ(V†hp£»ü°¯uÄæì;›ü¬;’"‘„ØèѶ®ù\¿tØWºÕACÜõñmŽ^åÌUXØ=“&MÜÎ'Øq*†º€ âŠIAª£g¿ƒéÙßr\gã^ДÓ2ÂN$’°øϽö ãÕ|ýÊ ¼ï ¨!î ÎC”-­©L&•²ƒPGIÜVTo#uB»fj!âà~…ɱN½ü€3’µŽ±D"‘„Øè—Û¦ô‡Ö§G5꟥¯¸)½3×-ˆÓ oÎ\†vŒiÖÄí¼¢-µÝK“ŽÕðs©RšäÜ ôø?ÆWöµ¾´6–Ë—H$a'68Y×é"‹ý[œ+‚›‚Bq£x¡—Š[ŒqÙàæEaá.¢ã8ùú¶CÌ mr¥nPEH íwdú(þ—ÈôÔhž)ñD" ;±q`CÞÚç'k]ÂÂÊ^à¾xhÚÔ-ÄVÄ(H¤ÁÕQwÜÝnÈvp‹F§Äm>{y\#Ú¿ÅGkSwÁ$èª.ÿ.vôÏÃVÛ[uÍ,¶·10kéôD"‘„¸•ØËL0CwŒéñ·ûòá7®ƒ|M$=Ù%h‘$ëMsý%siR+‹? ‡þ­Ç\¶­I‹‹F¯‘äìD" ;qk!¡N6ÄÛ°ráùK|!ºŽYK|qÎèv·f&‹ï—Øà¸ŽR\qéA.ÿرW´1€P¸kªñ1Ö'ƒÄ|^ßD" ;që6ìÁ¹Z,¶_+¼ô~»üHK‘_/Â\º„ÉN(;<"öl8Û4×ßK¹!U‰Ù=GÏ¿;õ÷&}ª-îb!=›ÛC"‘„¸Å¶+Þ:‰‹)vþ!¯^‡‰ 7Ø'¼°›V/•6B”}ÆÅ­i‹Ä¬*Èüô7bçÿ°Ù‰”+5é3žH$a'n}„UÛü´Âò#ÿﯠޚ‹®GøC­zbt;Ãôƒ©§ÃǦ8±“×QǰÖ`ˆ*¥¿€œø§°ø°2¥*@—éðD" ;qË÷kÊx©§§~Û—O¼ª@-£ÊG$|x·´›sÒ2-¾ `êg.ᾦ昪Ô0s±ýÈ¡¯Ã§§ÏâgQ*Ñu•L‰Dvâæ16CcÑò¾›RcD éoˆo'»5†~ZÅ3×w£_~ õ3q‹‰>µJ±f‰Zú¨‡¾þ™Ôe|”£MaœD" ;qsáC$\¹ºkÛ¡98)ÓS¿ëÓ‹ïÅÚ˜–·Ê=ætź’Åç¬Í銃ì€Év§ºnÌêãi ±áOlíª‰à ÞåírKÌæO–~›þÐ \| Jã>t‘áºÏî«ÕN$’°–: 9®6õÀÕ©j¬<òRÜ£:)"Q£”IK‹ËZW.WÀ£³Ü…í»hR¤ÌÕ­%#ì;apÜnñ¿ÀÁïqÁp¦-9£3Éxõf¥í †§˜|"‘„¸ÛëHÐk#lý}ñ·SïFMgïW ûLš8ŠXHXJÔ¶‡m/NÙ ¸£®a«œ¢)wÎyO G\©îpåô‡Øi½®Pl:ÅÄ$/™aI$’°7²áÊš¨úZøòc?H¯« –˜®˜@¹:BÃ<¢'‘ð½žlwʶh6s·1ÂÎâ;äÀ7¦ÈÞ³Ré.~õ䛣åÌ+è¤I™V ‹¯’ÛG"‘„ø³]Bº«ÈÛ`z…zâmHˆh¾v:Ó³,·ŒzâÑ%\q¶Ý%PfuP$š˜”Œ´ïˆŸûHÛà‘t±)åô7a§ßîQjO‡C)$G¿‰$ìÄSŠ˜ÃW¦Gßì¾r!¬œÆ^ÆíVD¢ùLfui7¡tNÙå!¦±æÿu„%6àˆG3š ˆ¶q» §þ9~á=>kkBsù¯ÎI$’°7ŒY¤#ÚT«ðÊòþ×a8Ui¤ÜÈv¬_Ï6]Ÿk(«8Ûvƒ,кƒù®p÷èOlnôæXi‡5‡âDÉDAûÔãÿ¿¼Ï¡Uµ]gý‰yhK$’°7QÛ“/c#ëÕÕC^Ï¿?<¬­`ZŠiÈS¶Æ"“ùˆ9j܈±c—´oííX0Û sD÷Î@'ƒó‡µYtº)âNW¥ýzX9éƒ5k hÞ‰DvâFpÍ0T¨ÿø ˆQÕP ¨^׈:ÅbæÚJÔ¶£›@¿Ó‘>´ÃGy˹9Þ¼yî„_óÓnþÙ³Ž¹mºégõÈ·àÓ Ïww¤ÝG1Ú5HÜÚL`H$’°k.¡®y=l¢«Ç~þúö\Z[=Ìœ0gûneÒeÊ3ÑöÂÒ/Q½è~·F[N"ÊïKlÑwn/‰DvâÄ[[zÜ":õ.gqïõ#t‘™ÿqSAC½k'%¶.d``ÊÊk±C÷9¾Ê즹Z]ÏZÆòîI$’°׊’E îÑîî¬îû1ª¯ÓÜcn{v‡n‡2Ù.É׉P¶Áœ^(‹?DôG}Öp¦W¼æÖ’H$a'®I¸XSœêCËÂAúeVÎüj×—Žg¬[{Ó/wÓæ­s}s‡(¨…T-„î|¹øÝÔ?å]ÛXªöÙ³è<‘H$a'ÂÚ¡•k…é‰_óº|ŠB¹[Àq´s&;E³Ür·üa†43¤A×%ʹÒŸúMw×Y¦Æ×ž&‰Dvbæ >‰Ô8°´ÿ?£&×ïÒñ™0¹ º‰Ï ©$¶6+M[^œÞBáÎëôÔ¿Â/üQxˆÌÒá2Ô²û\¾D" ;1c\‹T¸BÁ–ޏŸ?³õ…8ƒ™¨Óíl®:XŽå䡨[Ìà›Ñ xL"‚ß‚/>âÃX—À(ʃw¹~‰Dvbþúp)ÅX=ø:de¤RB|ПGUèZsštPv9Õ g¯Œ°3¾vÇ[ì<úi‹G ¦ :}?ö¯±åC>8®V)¬qb cöÑGË\y"‘„½%akœ©W½…FØØ:JØê`˜³íE‹„S–)ñÄuѲz?õÈ‹aå˜#F¡YqztVDد㦓¦wŸH$’°·T¤A®vþçòÞ6[o`K Ù²n·ƒû8ZëÙ&ž¸:1˜,ÿ väåøôâ½>ŠØÎt ²ç€JÉH;‘HÂÞb˜“_ÞûjÌWGí3Û¯G¾ÝN¡,î4ƒ\ÚÄ:΋ÖDkMÑÅ×Ðý½Ø0D ê“FØum^2y“%IØ[³Í–éOþ&Šàœ…kš3\+ÍíÕ™ìÑh@s'­ë‚©‚cTŒ²øJú#¯tlH‡G3š"ýHÚŽ“·X"‘„½%/ãô䯻/ïZ4³µèk4š­!kwdè7ÆùëtbJ¬Q¯6TÅQëé.}?õäë]¼RQL¼Y|éiÇXN!$IØ[)ÂÁÁ¡ßûñZ¦¨t¡`¶áñ˜½. ³nà¸32üI\î‚Ìh8„Ïl9vê×¼x(ñ ¤­á×¾8·ŸD" { A|zÜû³ïnöˆ‚™aEfó°éë¥0Ù¥Ã^;줸)U•¸þý#í. ®" ­Ç±3ßEî÷\ÜÚ8X¤Çé\÷x"‘H¾cBèAòÑÖðç0Ó*@àÍÐ_uÌ%Pz•±f­¡†‚¸‡÷µ4 Äm•…펹R$¢%‰ÄGް#²žSÀ oíÒïAN~vñÝ-–Ö6P®íãžH$’°7÷bÖZg¶kÆeŒÅ#?ŽJîHk w-W¥g{›Û2ƒ…ÝÊ9wwÜæ;Ê3ÂN<5ûìø}È•G„X·Ü~‰$ì;ô2ÍúÆj‹—'8.<âœñBaafÂà5þ} Ô£ÉgˆiÔï`á®H}Ë(jÁ(Q•ñuâ)£ RßAô»±•.CC£æy0‘H¾ã;NcÉ\#™–¼ ÷¾©JEÔ-­#WZè,"HkûRä^……  3*ñùtxn¨‰›À×ê7tú ÔƒßÓ'ÎÂ>y"L$’°ïÌKä3ò£…ŠØ”éÑ·6?kÁð¨US#í=ŒtyèŒÏÃmwù“uÝÙLW§x÷:`áöU¦o¢þÞgbS”’Jz‰Döe7=桵G¤Ð?q¿³|²•¶+âJŒ¦êe í7A¶µÙë9b~’EŽv%ž*\±¡8#FY|=vø•î¶’Zõ‰DöºïyÙ¶ùÊþ×àÖGê[Zê[gݺVj‹¬ <‹=6Î…ÝŽL@l~ÓDS¢ó7F»‰?;GÔu¥²ˆ\~%Ó“oô0M$IØwÚe¢‘–E¬ý¹çsúš0Y ˜;“ ˜¯˜RÖ¢tqXØ ®óþ‡3ˆáX`%ž"ªzWQ*†¨#vžröeÔÓ¿˜9ñD" ûЬJ¸Î5êõð›ï—åK!\!Áˆ:UY3åèHK†•f¥l/”í0k"ÈzH¸©qM±çÄSD±¸‹Ýãþ“w™ÊaôäK˜ž{ÛÕ‰D" {sB0 ]~,ÍGXY>ð¦åú)kñFàŽ7)RÕ¹p=‘xZw…h‚´*x÷(zì%ÔK¿7æ\S¥çí™H$ao¾[™5U”‚]|Ĺðм*ó‡ÿro®HMݬèv×\×Ä­¹}GÒmZã8"¡Šÿ ¹–ÞçîB“ƺ\¾D" {“…س¿ÚèÖò§ÖÕQ¶ô#~ùPûC ºJ·mØH3帬-sJcäi£û}¦^Œ¯îuÄ¢üã ’”H$ao¦½ŽùlÅm•zô—£û{=cW£ˆƒ wÇìµä¥OÜŠó¦„ÏzòøŒ´qC-ú2:{;~ð%x*|B’¬‰$ìM`»ƒ¶nïÓä¶t Y§ðÄa›A™€îtr/LÜÒC§î6GÚ-é'Ç–íqÊÊÏÑ|9ø¥8œæö”H$ao."ÃqVöÿ(æ«8u]/ƾ‚¡·Ý#”¤ã)\‘¸d-àÝÜ'”YÇ0oQ¸;U¦L–Šþð„°JV±‰$ìÍµã Æ„‚O/Þ;=ùûaOè`óá‡ÿ„áa¡»;æg¤y_§0Jâé?nR›Œ€µÃc>1ŸaN»^/Á¥WaOü„cÙ™HÌ£Ë%Ø,‘J¥?ú‹{uõS…‚´™Y'øhìáóF‚U¥Û])“ nq§ø5¤H·Öж5RÜ“XLœR…Zœb‚‹Q¡«£¥uKZ‰|E Ô î S ǪfQU=½âŽ•«%Þ‡.j¨.wÄ5ÒùH{Íý¿nÜÅÒº&ˆ¢?óCT}†—ç|Íì -<Þkû¾™J$a'6*†JayÿSñ/T5æG±×õ½„4ä¶»J¨XX#m"ÒÞ:þ Wš sé±êæˆ*ÅÔ(&Xqt¢ÐÅB¯žWŽ=aœº¤œ9Ó³ÿ˜pú,œ¿ÍU÷ÜŸðÑʽŸ`|̳OüØý1S`ê¨{¸©‰ æˆ7%xÒDn£ Í·üΦ%>LHÑ IDATsÃEši ôÅÐ?ñx·Ó»gü1!dw}ð »êr&I؉Û!R…—÷¹Ÿ{+‚šŽÊQkÞ*WG1AH¥«t»Á\QrPÙ:!¶»su¹~8̘8j‚‰PT¨b øvG–„=;ïÛ#üÆsÞù9‹‹Íö›£D"V é9A>îYÎW|ü“¿峜É]‚_1¬Ù²ÔÅ2´‰§-Ò¨RZ†"²D¨®1&þAV½œªw¹Þó·$4óÛº´†µDbKÑAZÜm²–>øï|yÏ‚õaMh‚hχuÚCar±ëã†4«Se!ÝJ;ž·Œ‚\ã!hѶ„!ŠoƒcGàþwÂÿ<<ðAXž‰è }wGæ¤©È ‡¬Ùc¥HSîzÞs•ïû6çK¾ÀQê*o‘´+¢67?Ø¢ÞÙϧÅJâ"-³04ª ¦FA1ý›è'½v=OÆó ®I؉‰ž ¿õn—÷FV»H|¡ØœšÙµ"mWv}¢3ÙåxÓu¶:q­8ïøýšõ}À + ÒaÛ{Žìxí›{^ó … çÃr ÜæÖ¾¾€ >76FíŒï%Äd‡Z­GûkÿžñŸ^õ±P—„®…ÖÞ2'®P¢ÿÎ?F©GíÓãe(_´d…°ÀJù[Lî} ²ýÏ‹4ÿwé‰Dvbƒ žúC¿üß¿ïÑŠË@Ò…Ò:½‡Ï]MØ2qîþäØq§êÐHµµûjòöqÝÙn,^“ðÒ×8/ÇZy‹ŽƒZW3 j0®é2o2°£°¦Ðfæë7£>ýS_ùaøô¿èø’¢‡®¨çf hkxÛ×ÄL¢®5|E½‚(.Ó…D÷^–kKŸ£‰‰­…ëÚXÙÿãX5P‰WÔêñY³¹;Ûî!ê±m¼K×ÈDn…ÕµâÖµ º;Œ÷?¨|ñ×Àw¼Â¹p9ÖM‹ÄWûœëYxŠ‹•׈¶¥™“©Û𠇇Îf‹£òøç‹ÿ©óèÃñ3 Ñ½/v”‘&Þdí‚©ã%q§#:õÝc Ñ Ü{Êò/á—ƒ]ŽAÉ`#‘„Ø@°þÜóWŸ¸méVqº_Z³÷µ&³yršìŽndðñí[sœkíæ® º­ã-¿"|ÁWï}hF°áÝÌ8Ósѽ=8I9:~Üëx,ð'ý?Yy;!x‹Â«À±Sðw¾ ž8ªx©yiãlÙÁPkÃpÚ²Ö®…è·}q§È2¾ôf¦Ç~È]û4lO$a'n—xÛàç7ûzì­÷Ûô‰Öx,¸×Qqgh7b$É¥ŒU=«ÐítÊ‚0L­>¹áêÎßðÄÁZd<#Pðïëùêït®,Ï­5b~òµ¸ê(5V¶×ãÛì{̱úþ#ðÕ/Œf3 ‰ÌTïür(É„>@¸xÍn8Ec Qü,zá Ô?æÑ¬ÇÜ!Šyáý´çL$a'nò†å¾Ö‘ËgÚöeyÿO µ9¹SE#BV™E€-jVlŒžE„…»òò†s«‰ºGP¶ ^õø¶ïŸl„ÿöxÉ ²k`™k±¼| G,¯` ‡àô«à‰Ÿj}y:–#¢Œ=žx" ;qS÷#iÕe¯cd0JC,qξ¯‘sEE(2¤½=žZ““4¹Ò¨:2qº])=j^ÀÍPUt¼ííð‚—).Ó ‘\qàûÞÿã] Ûãq­ùxJkø3¤CÜÀœŽ½Ø©ÿ„ŸùŹÛÖliYâN$a'žŽ0¤Œ!׺^>ðzª-Ê5.뀻œWŠÿÍ]ŽNæ¢ø­zƒ+¨µåÝfÚ#|ý‹c‹ßº¢ýÔù—/_–6Öjkyâr:‰û¿Ò#¦(|þØP/þ¶+CO‡™ªD" ;qÓ/Œ ÔÚFU"Z˜~Î4ˆEÓæÜUZzwÐÃÆP‰h[=:Å'ÏQg|kŸ…Zÿ¶¦Uø^áœ9Û"[Ù(?£‚+>êüÇŸtW4§åÄ% ‚Y#n…¾!«AwúvðepåýkWKl¿K$’°7g³ž…ÑMÜ!ú³ïv¿| &]¨n£©3¥˜ÆhÒÜ®îٺݘl÷kªzm½ý>ú»ÙUyÛo;¿ü;Mô„‘2¬ÉF÷øË_¯œ>jȤÌ5ÊméªÚ+¡ÓhÌÓv¸Åzм›zðßÁê^·Ö‰ïñŽ\¿DvâfnØÃÚÎâåê×€O1/AäêÜBÝLu­ üÐt0¹;¾É•«f´·R„-®œ/Ü÷Ÿ•!¹ºö°t›ŸÀ¡ïÐáܹÊË_,ÔÖ-žGÚ˜ˆPÌܨ8U ¡•‡dŠøï1Ýÿ"´ó˜gÏí-‘„xÚ¶%kq6P±£¿Ý¢„B±‚VǵǺ *ô¾Jñ‚¸""ãHªª²p·6{ÇÜð|üÎV>øX›£v¥ âîw ‹ÁõÜpÞðkðÄ`¡äµ“V,2C4F½:JŒ{‰b]› ¾LWïgõà}0½¼eÌSI؉[MÔ XnE«Çßæýê©1]êb¡3‡.•ѹ(j×ñÝÊC&ÝVk"M¿# üê:¥<éµ «Âý"£ÒcÃ(“øÚåüEå^/°P1•ñ÷2düýÝBY#¡;nÝ­ å•óL®üvôß»ÔåYeª˜ËªÄTF"‘„¸‘­È—>6’&…¹¼ÿÕ„íÄz.Í‘2l†Î„U¶Â ìW1ßÕ˜=ìüÎ;‡šõœyÇÆ8r4iS™]K1ÞôVçü(bAÒ}|ìípg^‰n¬­ƒh6²¢OP/¿…z앎¯2껋!ôsÏ]É T" ;qÃÁavâ(¾tÄåÜŸ¬ÿ´ W¤ƒ²kð¹v¶¢ÔÓ°ö6á}GÕ:ÚÏ”Ñ8bc\~Ü+Æ0¢§àðĹÂOþ‚â;B0„.š ¥ÕqE„*igoMPEDƺõÄág_ÏôÄÍÄÏP°nvƒh˜º$I؉ˆ¯š‘GSsšüiúÕ+¸ß ݺ³p·Î„S¶ð^$ÌÒȘóÎ?•´ÊU‰ pûûÜ£†šCƒaå5¿hÔ+ %ü¡ÝçGÑœ’uڸΪccš»cÅéÊAääâ§Ƈ†>“YÉÄ\·ˆZ{" ;q/€´áЦž~S{¨´´ø:6,ÔY¸;RÄ"ƒóÑÖem@„zExç@˜àÕš†\iĽ6ì&3ÓÍ¥ §Òñøø“ߟ)6Ôìg^Þ[þù±ãñ±OC,é®ì£}œýuw1T%´~lòK$’°¦Ka>àõÒðÌ)ë ±cöÚ‘m&-ë·u’®ý:ÌQŽröôÙ®ÚÞµÚÄ ãBr³¶ŸI¤Ç*ü𛣅Ü% \Š †‚ey«M+nƒ‹6‹Ó‚cLÊúãß/¾g´«s/QÉÕK$a'nl¿¶&x Ëû^¾ŠÉ4jr¬ÏœÂ¶Ý-sJÈ–ÊÖðSf~Þ|æ¢bôÑ“ÂåEoö6¾e£Üøòáεöß{¯qéHg³ë©¡ŽG6:7²6D Äq‹ÔxmÒ³î˨¿‡éþ—â«æÑ3Ë—HÂNÜІ㊫€­bÇÃé\˜ŠSµ_ß7)Êd­N× ¾5{jÖŒ:©PW‰Ñ¸¦N"J ®Û5`mgmT«ù ÝR'ÎÂÛÿ@aˆ(.Žxü>ùðÆ×:ƒâm¶Þ,J k†LÙVÿ€éþýÑf¸šñu" ;qÈôlâmnË'À•ŠÐyiéíWñ¦Œ¢ÕÑ*íµã&wÚET¦.ˆÆ†¾U¤IÝ!ÁénC6|85Ôöah²Ó\Î6D†ÅgÏKÕ‘ökÅ)ã!Ìy4ÍÇ5Ç›«07³ÝŒqL@)+¿ÃôÐKé™?ŒBâÞ˜[÷yoúäôDvb͆-wXÙÿzÌB†u4fU¥Ïé…ëLÕ QeÇî¡&7ÖÖܸg{î܈Υ%"X ˜› iKŒƒ³g.æ° áè•sÄë@‹¶« EÏ£—•zäåÏs[Á=œ¿Ät6(!«#ji‰$ìÄ“iFVOz=ó¨L(ѳA¸sQ":Ôy“‹×&°`”톚"¬i¼ÚJké׎`ñy"—Mô;=q¦ãwÿ¨¥Å[D(&é÷¼Î-ÎÄ)"ÑÈÙÂ/üWêÑ—»°j‚:DÔÖ´üË»çò%’°s„âÎò¡7býÀÚX–€„~øš:«ùœÀF|í¶»:_óý¶äÁçÃüÚ “ˆ˜fçõ™˜Æ¦@Ï›½ÙmΙºx2öõŸ/±(#˜QEÃdzÄ[ÓIJ¶3a¹'ÍÊ'IØwQ·­!¢g™=ñ«û~tQb|•¦mÕ¾ÇÂn…¬³]U¸÷ãè×̪Ë&“Žq£xLŸ8m|`øÂ ;›„ñÔOD¡E.v]ù]¦¿éÏÃp{„ k(㕦û.d[g" ûÎ܆±_ ÖÕSÜŸ}÷õ¿^=¤K‰®`wG·A·£é&'>2¦Âg|ªóÑ÷0§b¥k4Å6|aTB/üÆï R¢!KØ7cyC‹)H9.ý*õà÷¼‹1Ëf…7&¿\›ì/¶!”òI؉›¾áÎIašƒ;ÓÃozž¯^^იeìß~ÏpÜÏûºjï<çÏ)_ø×f(ú÷6Áíï 2$c+ÿý•ºâA0IØO}y¬•Äí.à~Žþè÷¹¸Ïõ…Äã&-*²]‰Dö´!0—>“hCéÁŸAêô†¾˜!º]áÔ$¹c_ÿÀÓRÇ_ú¿–q¡‰l‚”rSŒo!58á¬\l÷Už×nÂE¼ ¦8ôB·p?õ:üÄøÌ7½û¦Ù´ Ù˜–H¾óöƒ¡{Û†j¶R/~Èû‹C¹¾¡±»#†f0Ùå”iÖ¹c¯'‚¢Âsï­ctT6á­ïírÇÏûŽ‚t5g…oÊ.&ü\@”öœõLž žø!ìô›ÃGÛ;@1&3c¬I$’°ï´aPÄ óD1gzàuPq©ëØPdœ¿VînQºä¥[ïð©ðÜOWþÂ'Dy•aÎv㯡¬Ò0*ð§ yeo*àehà, 4w§›œdzø>¸øVzÄ ³Îý­>6™H¾ó"¼1²ögeõÈ/£°ë/¿»cj¨)¥eGÔ´=ûT×}Äœ»žeü_IM”¬6I 2zŒaŽüÞ™Ú’%‘§Œb‚xH½:­gSïÙÖ¥ß÷=ØÒ{½bŽgí:‘„}ÇØk¢¥zê~·+ǨZG]ðë^$§Rîvd&ç•›õºÖߟà_ôùo5Kßè¨/=âðð>¢‰ùQ^Ôìç•òñ8׿õ‡òÒ a0<½UVÐòuï¿¡¬<ì.åªîðVã^s/Åçò M$aoºø®™L¸"^YÚóÈöqH—~W¨m$*,ìnB]¹ߨ.Sd ÏýTcÛÂ@d›åÖ·ÙÁÏG9~¶pþ  ú$qœù¾†ô˾ ·ƒÊ"ÈÓïý‘éq2—ÍÍÈëldŽª3’HÂÞ„¶{<Ðuñ°ûÉwŒ™7²¡v P¶;ÖÜÿÄeËê†ßÝI#±)|ʧ*óóÛk‘M1'k~€gÎWöï,3-O{†FpS&¶„Lÿé¾vîùb3E=3Wî‘ ǽ\¿Döf£Œa"‡é‰_ÂÌp)7¶ümözè?Rš{õõ7ܪ³H§3þá—”æ~V7Ñ/1w/y8uý™ Q\ÞO#c‡Ã—(¥\€¥·aûî»ßY/‹ª¶KÐE w¡j˜«—HÂÞdp r°¦û_bL†ùzWÉ®¡. â–iñØp½©‚YU>ïÓêж¿VW|£Þ>×xdxçû€^Æ'xm½:oŽ›…*P<š<½Âdávùg©Ç^êƒzaŒxU ¯—2‰>‰D" {3 »ø×óBD0¡ÍQ_Ÿ°Ý„É] “Håó¸‰õSž ±æ«Âg}|æ'ÿä›ãm"/"2žÃ+>Ž|e½úiZ}—±9TŠR«Ðug‘S¯£žüFmÏ8se‹á°žH$ao:Î6–¾‘‚[‰º×zCd1î‘QO\š>bŠf¬õŠˆUvÝÿàËnŠ5´Qs¸8}NX\d.KãWEÙIà7åîÁc +^·ƒQéÎ0=öýØé7z±¡–­sÍ™èH$aoÆ[½ðüzøM¸WDûpüYçÈM×)e»µJÀ 7mrîëÛt5ÖÛS¾ðyÃd¼o’[ÈÆ(ZZ:ÿì8}h›ñwu’´oæÚ»u(0köµF•ÊÂÂ9úC/£^þub„{~É3ë‘HÂÞ€Ðüǃ%Ÿ»ƒÇÉÛϼëþ~õU/¢C\Ìñ¶ãš„¹Ö"j䙆ŠF–Í›O¶X›ÎÍ áºdÝ, bý—áyÑyÎ3ž|ûǰ—lÀGCŸDÁ—Wœ‡ö ÒÒ¶íNTGšœmŽaßÄ+О½Èr·5÷žná ¾ïÅø¥?to&?N Iâ¹Ƹ?xX$ÓsaIØ·m ›•¦ˆcCâ••}?Fg•B<ÌU4l3ÛC=Œx©K{íHPcÇN…MkÂ'É{=Ç©2º‘S južõ‰ÂßýZ­Q‘ÖµïkJ £a(21vC¢ò‡µq®\ieymÞëyž»O…ò!êÁïD– ÇÛöìÇ7'¢âŠP¢Äá ^rIØ·-Ê–! Ü| [>á«'ÞÑö°â*M*3„Uܤº3£ì€²àcjmH£‘S*Y]QI°ñ€#¢˜;ço —lñR ¬•”ò вæÇúÓ…Œ¦»­i î—$ì[´‰JO×?DÝ÷-h=ì¬|áh#j‹{kôO‰ÓDömÜ[ÛIz¨ ÐÿœŠëàUb#5»HÝ£¦-C'°*¶»‚C‚œU+O—®@A1ÒÅM7º*ù3`g'ãáJhæfä7@—¯Ï ×ÔDÅØÒð¥sþ⸭IöÌ¥÷OçyJ]°Édúêãß õÒÚ÷ˆ…xR+dÍFÁòD•H¾ ›j¤¸ÖÎ]*n=+{^ƒk8 §´úâšž^Ÿuûº Lœnçðd D]-C™üõ“†"z “–Oþ´ÂÿöeÖz&kÂRccúeëhïxöL—­iŠG„x›&0È"öÓA©RÑ*0YFVÞÁê¾ov‘aа¯kŒ€2C–H¾ݛiÛï+`ôzñA´õ’I„=¨DÔ¨¶¥ñd° ,ìt[l̳Tx¤t¯Ž½á0Õ¢OÌèJËnx‡”Êßÿ‹N4•™ô'3µ²ѵë…óÊÅ¥– pEb†V‡tt»çAoþêâ´)—~þð óHÒxm–œeÜ"I–Ûo" ûvµÁµyu…žé¡ŸŽÍß ¨·îñ9²Õ'GêâAÞÝ]Wm¶2¤Ãs¾ñ ÓBµÆôµ8¬Âç&,`í4e8ÚÒÈuãˆ^ÈüÄýÚéûó}G&ñºÌRâ`—÷ÊÓ¿ƒ*ÖZ$ G Jw ?õFìÄË÷&EÜ¢k±YM;‘H¾ågì±Áll:sÁ§—ï]>ô¦ö€Öðµ.1nc®t€[DÔ°gNK]'t;smêfs#\­“<±N¾¡â˜ÆZÆ «ðÙŸõ¯@i]×AÚsM^ê7é@@‡^¡GùÐã•h6Ž4ŽÈÐp–d}K6Ðf¡]]Iñ¨uM&W¨Ç_…œþ©iG#Å(+œW(‘„}[–ðj5*Áξk¯/Ÿio ’U'ædÕ©"ˆ‹+ h10§{flz­HQ|&¢’¸.Ü}¤™EžâTY(|Í—BEÁ­¥-‡yœ~.M~;acïÁ™MîZüñ§æ­ã~¨´Ò ¾FP%ñ4]‰&PevàvÇèΰrø>äâ/ðY ;£ìDömØOm~–ö¾šâ× c»µÍñÛwDQFI7—¸‡¿Çqö¾òùŸ=[ø;bkWØêƒ, Þ¥‘ˆˆ¦›ÛÀ¶Éúý/¢^y×p“µŒ\n¿‰$ì[Ææôƒ}ù„OOÞ•u„8*ÍM*¼®ËÎR¤yø~zÂÕaÙ¼‡Ï}®ð?}F¹Œ4"±IkHØÐ8qA©+MêVb.ÛÄ©½m˜@Ñøãߌ¯<ìH?Ûvó@•H¾ä)Éþè/!>]wJÒÝC‡X ÷ÌÈ%kÕOóÕª0Ù _óåkë¾iÛ¦˜“=wÁ¸¼ÂxÐpÊ ã#ùxßþ#¢!ºŠú‡°½ß€¯žðÁ}-…SIØ·‹©Ûç¶ÊÊׯÇuö™î(%†&•…3IÉL‰?=[èlôI0w¾à/ÉÌÂ2†æçó–çÏÁ‰'é“ lÐfR‘÷ÏíFiò£º0¥®¼Û÷C=/­2‘H¾-4ЂÎ?âvá¡P2[GJuЊ6sv9Ò‘dp}3¯Ìüz·Ï뻟ó¹ðéŸ<÷nŸÃ6:V¦ï±íòPr›ýÎIØ!Âö¦jÖ-Laé~êþoÝ+u1'‘„}û‚lEp¦G~’Ф.7áH…{f))?z“®Ëu–Q vÞc|õW”¹ÔpM7þ5péyߣ:>Ì"B1i¿º1î¿6²iR&«ø¥·àÇ_ì£pR"‘„}‹6Ìf£‰ƒô—Y:ò“˜;H¥˜®ëë] ›@Ù&¸y›ËÎèèæ¨äšQ·7Ù×/ü¼:“ŽmoµMBxï{Ì ‚àTÏTëFBm‡oÕ8РLzVO½?þù'’°ouç­æi§Þéuùb¨SyiÖŽkkÑ£WöðZZ(Ï:›M‡9¹ñÞ”Õ¬ó†ÌÅUD¼"ü•çÂ'}œŒÖ‡CM{3àÈ Á—†zð[Î{gCl°MÛÝ=|ùÜCa¡ôpòáô뼎GÈùû-ÒIØ7Ÿ¯bõÊÒþW#ÍÜý"®£×=ù[QGÔ i£^# Ÿ‘µˆàt»Q`þí2>Ù‰§wCÕFW{¾ôVdPÛ$¶§ÎÙóÝpÄZÜóþÙ'ª¬GÙØÖ«R* zŽºïÛñ¥÷z胨KÖIØOÏŽ)ýñ_mc\Ã8â¦K|>êF„íÏ'_‰ÜkoÑvj‘å˜*Ÿ÷\ãÏ}ŒÌT`7ÉïpeIØsÐñnveÏâF:R±ö5”e¼ô”r€~Ï?Cú=‘ƒkF4é¶–HÂ~âk©+¬î}í8‹í FElm [Džœ"ïŒn§S›DéXs•íº5Ûisµêg~¬ð•_Æåø¦øù£.úþG›+h»×lÎf3±¢ì¹ÅcÞ@âLüQVû'Èô¨Æ3’]þ‰$웋ŠbözñA\*†Sê¤É"È“"뵯aû]Q·.s^Ú3rÏöéßJkxx‰ƒ9_ò¿8ƒ.ìfX}ÃAŒ^VÇA$ïŸ m‹5ÿòhZ±®g²úêÞoÀëù{s*/‘„ý4 `,yãHÀ3’V¬É‹õÕÍgªÂä֒yÔ"%•ªnÉ&jN]u Ÿÿ9ðñÏ’fĹI‡=‡Z§¸ÎÝ}¹áo èZ®ú;Ž[‘…ÔÀ'†_ù êÁoÙknd§x" ûfcõâ½õàOƒÍ\ jé£K\Aæ#ç]סۼåÐ}M <òàÅ[ß *XŠÃ=æ…`抩•ïÝËìhø^Ï9žÏ<—!5k>ÏŽ“ÝãàtéÄj|ÁyÒe¦M–IÂOèÛãÀ¡ƒ°ÿ@Îr}k× ’™5¹Ð˜ íš[ŒzJ ©Q8q5v󹨤&5`¯åfZñ*9þÃyñâŠzñÃF:—.ÔQ¿b ba„^\Ü¡ÚÌú _ÅùLÈ‚•+êr^Xã6‚>ȹü‡¡:×¾W^º.¼ÛëÏÅ‘ò¯·3‚ºTñºéò„¢‹™Õ¥Õ:$.jb†ÛÝH"GÞÁp×O{w éÞ{7­çH Øú%oÚ!§n|CŒU¬¢Žé¤I=ã ÌmªôĘÒ(ó "]{Ö3b ÄØ”‘©\ÞÓIxôÑÃi'®½.¾¨šé€8$ÌB91ãØ,èÞ߄ݿä.¥Hœz›Cj_(TÔ€½1wNüg »Ý÷}x™FøjŽÔ˜½Vt&Ý-Ö,x’6À¸TŠ04žz©°u®˜È·1qœ Ø>¡ÐûŸþÁ©€àRT¬ód²Lj ŒÊû™²Âœb»þ'rð­žÚ ³ØrâN’¬¨ûîÛ1m¦³×K;ߌâ®z54\iÿŽH7{Ýg‘‹IÛrl`|‡ÎW?Lxö×—­âÚÍλ{¹ Yãåé2ÖP¶ï[ôºÆ¦érQš– £†š¡³™¼ý'ñ#å1zªåzĨñ°7neMHG‰Þôû˜¶Æ«£öˆ:ƒÍE­Hê:Y¢}nxK1,ÉÚ ¿©-¹­Û6B31-qA:¾Ã‡ai¼–×Srü´Ü #‹‘Ê¢“’8¦t‚áM/'Ÿü‡~ò~,±¬¨{cÙ’°#Ÿw?öELò¶Al64I©Îd,hWLÀ»{û“ ›Ò†0šˆí³rÖÿðaáЉÈ6ꛆՔ3“D2…–°É™%ßðBXøb˜~‰A˳¨¨{cbÄÂmWtwD1¿›V®!iÌ^/ Zý®×ÅÛ.<äkßú4ïÞQJ'LBKÜ»À plÞ¹n{‚µ-: [ãê™,c¦eR4«“L0Ϥ´û·ïA–v;¦¡*Pßÿ°7"`éØ+†Û¯è2WEpY]K¼i”4VTÑDœ‘yíˆOÒ{,Ò‘ÄcªL͘C2^ø¬ ™ÉX ô ÙÂ"©ÈÞÆb½ö‹¹˜ÇÕ¶îè,ä"«X¸zy4Ê“§1PÔ¯exÓó£EN¹Nã×€½‘Ñ¡|£/ ßj+Vš*f- )¾§á{]>Ç„æ‚Q™Ñî_ö$5ž t¬È‚l¦Þz " KÎS š|¹ÂÔDÄñ™[ "䧯F@íˆOA…-ã‡t!GJ˜†ô³ÚEðg ¤…ftóy§àÝ*áô1¯:öUö"ù¥·ß6šâò´âžÈ=‚R(Ÿ¥2»u<´wŽ^+ õ¬¹Ã(ñÐGÀ·<ÙQs›€¨]k¾õ\¿ñð%X.ÑV1éfPÍ\„l  èÑ«ðÛ~"¤€$®Ftì¬éçöëñ_ö4f¹ »}qߺ"FJEmÒ«Å_Ô^ݬ¥íÎft¦üa]_Ðõ”¬!¸i/zÎcXÊ×Iêh÷ÑÝÙwT.Ô jCœMx§œ˜J eéÐïÀî׸3« ´]º}ந{Ú°´û/n„«¿‡[îĵüEUDÙ XÖ›ô>½=£4iÅÄ•0eÀ“9 çBš Dï;ÜäbôìÐçø<Ë•`*¦syŠ sÚ^FPGdf‰¼ë‘Ø{åñõ\ÍCjÀžªÌµ±y‰Å~r‚rÏÙ‹UŒUÌæc |6€ÙmѰL€hѯ;e¡8®-(~”òÍOißrˆí#´ÚÓí†N> Ûo¼©ïÞ´#»#.dwLÇh·L3ÛþJ8ú—.X¸ÑÉxu^QöÔd®å¸>þ¯îǯ…’†+ˆ,#šîyh³Ù!yGBsïÿ\\ª°ÁºÈÜ¢ÍlÉ 1.ÿÖöFÒ( U¬cgƒÏÝèHS3Ãp€»;ˆ“,V„I"; ŠFø/ùkÊ•¶²ãÃZa×€=E•uÇX¸ùÍ8 +óu-=® 'åøkï6cfkl $ÞUåîÖå·õÅ_ë¡Ø!‰AÎðäǃÂ!œ„9lC±å®MŸ¾®Çe…Š&p)WlŽ»Ñh±V‡Á1†7¼F×{pn@¬©%v ØÓSYƒ‘—íü³P*ˉÆÃ:Ó=<¯)¶š&ÚÝa·LÝ””™ÍàVb|9I½¾âëî@„âš´¨<æ‘ÎÓ_‚㤌u‘HEЇòñ3_lXOä©_¢˜g'K;ŸM.d@Liì£ëŸ ¶×cú¯^b×€½na¥@±°Ìtp8ða·¥Ãˆ:YÜùx„¶ˆ€ ɇxaè&'“¶ÙØ«+ÝáÞ:uUÂÙºIáº~ >'\þí廓=Id„”å—n…‡i¼L6Dõ%(L æS±:Ý;óšä!°sÚ¥ƒçR®K2ÉnÀ¿ô|ð“…0Û:e$ÕÇÒÔ:dPöÄe¨^ 9JVªH·POÝôºUTä­|QsTiÀ© Úªx9O~ÌØÝñ%ãÛúðÑ`‹£%YÔ’8º,KD*¦ü€w‰Ê;iøf/^Ãèæïu—þRÎ$¦ybT®W«ÝÀ°'ñ(nƒz‹BWÇNÝìóª€ïES¼½ãnf!ÍÚØáX±®×ˆÄ ¶8\öHxÊã|"Ì–‡ßb¿ˆ1¿‡)¤ò=·±çÓ?¯Ši?ߌä!…“* Ç¯‚?êíXj¢.cã¼­kÀžØ*›ÞÆ" o}’W7ȪÞß]‹3Û¤k²W¬÷/H<ê=Ó?m†«NDBæ··nÛ­P?MÓ‚xÅôñ.‚¦¢¬èã~~ß÷Çsi‡·k$G÷¨ær5`O艌¶,ï6ðŽÞrEÜéœõ ¯»v½kãÌl‹ ^ ˜iÈæJ…:®fgðµ6T&%àÙŠÏ^G±roep},`×drC,_1 AóX{EFÈ»;ôo ¤ÔÛ.DÙúòÕ€=¹q»°¾EûŒç“_ZÝ\t!aæèfGOÕ+g*†àNg´ "ø\ö¸ÿ¨ :˜W®e‡O}!E _!z šPn”“-• %£ÅK»I`·þ8rü½Þ޶æ6RTó*jÀž0”…é…„á™…í¿OvÁW¡í­ðòbª0saË÷z NC…BFÑ2çêñuš-K\þìIÙÂýXaˆ§ÄAû¹›ùãŠêøM·ñ*Çb#„k3ð&æÔ‹ÄznR&ßü½0ÿÏÞ¯-„´jÀžÈCY;m]{¦íxgÌ2®¢Âõ.me°™íuëÎ*Ös­„±BGMŒûŽ¡ðuœ„3ÚÞ˵Hw0Ž2dŸ¢o‘WL;²„S—›ÜÊXŸ•Ö`«žÄnúvdñïL‹êI Ø{(—ƒÏá¾_mÈøª®•;p'Ólµe† ©–Øë?™óP‹réßOwÁ—à²KáÒ‡Å8Ì2¶¶¬Õö-;hçOÀÁ£moW¹t–Œµá¹1øÖS»õAðâ÷5t13âù†ïÀ=„Ub‰ô܈–öÐOñ[ ê5`¯ÍKв$Åœ…^‡]…á±–E¬ ³ÛRW½¸PµÂ§&ÓpCj'ŠŽüÜ–/~®ô6X§±Ÿ\û¸ÿ@Ónó¶z²ºù+ú¤´h«]|édN”µÜŽ †ÿ;ÞŠð€xÌuWÔ€½FDzà§ntýRXß« ¸âqÏ)3‚l²±.zÏÊ­XïUöøûX4Ï ÈÆ3ãÑrôöîoüm_ûíõ…=²Ê²VC¥¯¬O«ësß{#_&æØÒ'H·ü çbn7ƒŽ˜9Ó-…<ÕðQöÚ,Z@Œùï û¨›§^­=‡;Ì\ ˜Xw(BeáNgð–rX-e.» þÕín2ðÜuÄ}*O}º©¤¥ÞŠIŒ$VlhduÌ ™àIãÄ;ödç+;¼X-M¨çÕ–x ØksdÌÝ|Eñ½Ö.ˆ¯æ%la°­õQzÞºÀ¦e‘Œ‹ŒÄÑÇ׿‹…ïy^Zµ±%5!¸öK` à:ÓâgêTlT$ Ù]ð¸êÁ5#ûߌï{­¡‘Ð(~ a~T_¿°Ï{y . ;ôYçÄ ‚ZÆVY_g3Ò&G×x ÔÓ—Ñyé˜ÀÐyÆãÚ¥ÔŽÂèÄDî›w‘Ã+»=•tVÑ.ï ie‘˜8¢†ïù8øV—>?b†Õ‰ëëWöZÄlcéæ7‘U1DUKKüìsØ¢ÎÌׄ*H ÖÓµ6D Á”ñïI?÷¼,|Íý‹ƒ[©B&e{;ƒ4q8·£×&uóW€‰’Ýõîº$Î2GEÉ»~;þ×£ Qâ™»‚ ê Xöy_²ä¥ƒŸÌ»þÍÎaè=™ì¬/à@I›)²¦VÊ*é¯ +Öw}í­œgK"Œöxû^»Á%¾ï¹¾|WÉd°Ä‡#8x¼(X• )²¹5¹¬7’8–Kç¥dt¹ü§d¸år˜ÿŒ;ijV–¼öhjÀ>÷'.½&¸}¯ûT±½zBÎG‚å[Úοº5ƒ·˜Ëw0!» #Ç·Ú9iFÙ"î4ZÅ)¦±³ò?qË<í2íæ¤Køt"ò ·4ÑòËM±Ö ¦b£¯i÷±ŽQÂV”¨¦ÕçÝò\dñúÖ‡~’Û°ö<õ¾ª¨ûNÆkG$E6ؒȤÜØˆù[^ærocÁwK4ž"p‹õÌq vQÇaëͲ B÷V  Únˆ \€%xÊãá«îWªjo—™MÂà³_Ôe;>—ÇUIâ«YßY¡Éû±›¿ ívT0†¥á¤è s¯Nò¶æƒ5`ßáü±±byÅ£¨†ŸÜîùÀ?uÁ¶KÍ ¥27/ò¥¤ ‰VUšÙnÖ›€ÔCpcÕ'âØ¶ÝÛøÞçôklrÌU•O]çØÐ»†0þz V¬ ÉÀ<£KŸÇ·¿ì$ꃮÑÔu0Å:q!/_WÔ€}§ªŒÎ&ÑCK·Ív¼µW)w6ý)6ê‚°D•ÝÉì*îÐln¥HÛ A_ö’ÖÑ™ °´Ð#å `¸&˜óãúíΩc¥®Šd­k³b•ë;ˆŠRÌBüäÇñ[Ð+ ‘!Í­qE$o¸ðRö9>°èŒ–µ©ÅN1ºå­àªU…Qûw¬´À‹ åÊNe’Ó, ëâÚ 56ê` ÆSž¸DË 6-qàÀaåÀ~/ª©a">æñ]Qq{BÃ:²bØñ¿„ÿ!Šh)W@î- hdrZL5`¯¯âZ—±½}Úùð5n'w”ìÐcœÁÁb!–»ëö²/ˆÂ9‚÷¬£ÂF©¸¡Õå­³Ø'\{Q}R.¼7\þ¬r}2)¤3`i‡NñÌŒ˜Û©Ô ŠUTØ‚™áÚÈ£ô9ø&dïk`$Á¼-ΡòW[â5`ßñµwP Åž¶e“9uÓ›0MaØ U5½ý`°ÂË×>öR‰1»Íƒ¾²Jû—kÔžvä2 ãdø¦§Òs&$$š·ˆ–f—\ºÕ†eÅÙ×·;šÂT[Dq’”)š=¯Å½Ñkex3“¤APöz… ¢%Û¸;6:üμç¯HeÞZI!|!*˜ ¢}À•â”RJÌlÕÖb¬‚/•x]«Écº ™â#xÊep¿{È„¥kʵ_(¤31„TÚá5¡¬øòhJ•í"Ñ>t ™RQ\ÝñJ8þî“´¼«T°ïpK'¢m_)—ÙÁÑî÷¿È†ó%HËØÇÂ*/ÁÚ Á•‘8iS†C³ô# ŒßŸþ½Š)]_ÒhŽà^_/ø–¨¸'ãÝo@,L@F‚‹bšÃIêZq¶õ-] ðB®uZU´0aûÀÉb¸÷V³ËRB[öqùÜvE Øã!SÀdˆH0e…ÌÂõ¿]ègY°î˜üR ¶ÛVlìMwDŠmN|ëÓ D'ä{„ \w#,žŒÖ¥Œ€T™âç`ù;X:E¾å;…Ϲ«t“8Þn£¿÷Ö®çg Ø·[e Ü3аtà\Ž|šá*”#Úê»ûzàÌl•È$+*¢ 7nË0óÔKážNáÆÝÙ¹_9xÐI åv]jÀ®8%‘š’ò¸õ9Èp·/×¾ˆ¤vœçª×þc ØgŽÖ=ñ¬Ì îy?¦Âj¿»±.Bžt°ÙðÆÇ´¥+ê.r›Ô …û­À.ŠSwv‹{?pãìÂAF¡jö¯ÖL ™uÒ&\²ÇzâÕ@bÚò ˜‹ð„K•‹·MÀQF‡ÏߘKu½|ª¡¢âNŸ¯îE\EÑÖñkþ}°ã'=#¥T×QQ÷•6µÂ®ûL*c÷&ÂÒ®?!c8ЬbìÀ½ýÛÆ`kù…âEP¥.  `¾Á-íUqt îÿ ã…ß¼ö»'–)ŸúÂJýðšqVÜÅóUBÒÙ‰9mÇÍðÃûþ‡7"=Á,×1EH«v ØgBÉêòÑ/úh×{0`0¦)¾ªJa°-ªu‘Ö¹. “¢t&Š!ç4ÀKž?j‹kop8Õ{a[-°+ÎAB˜¬Õ7² ®)n"÷½޾ÅÅœÿ1Xc…VQ»;5`ŸyÅ(îÊÒá¹úld}¦Eª´YÅ $0pf¶Å°¿¸ŒiõÔUWÑÆÖÕ T–ͼôJŒì·~ê ŒPä¼ «´j|Ã%Ø8šC¡ÆW×oÅy¨¾}ˆßüÈÒÜeL ­ÞÉÔ€}z…ã\¶ë½a´.‚¨áÉ1­ê°KsŽ6ýÁ‡ô±]nØj<Æ]àq3.¾°Ÿ9mWŒáçÝÍÈnÙÓÚlVŽnÅyXsâ¸eR>ŒÝò<°ÝV¼ÙëùYöÊCÔ†åÔö·ÑHÓµ¸ÅV¿`f·gŒ¬$‡µ+^E“»µT “w‡‘r¯À7<É¢S㊌µÏÛúéCóoRáH¥ýTÜíH-ÜÁn‚í/Ë…WTQöÊ Y`aߦfä£ÚÏM «ÁÀl‘Û+¿ë ªèíX[GUTK \à‡Ÿ_d{Ä0/ºJ:ïõß¶GüŽ1œúÞUœŸ“’82ÿOøŽïwaÏŠ°—U?@¾õOÉ9c-iLF€â«¸Clv$ù˜+Wyá*q¢¢”Éî1—ß^‘ÄÈ_D[„§>V¸h“Å`G¡—¹¿ÄâP YÜ~E±”iÂÛ:ç-•åmL´km:qe°¹.˜Š»Xalñ']êÜû¢`N„Ø­—weR99‹ Ö¹vUT¬%l×ËáØUž\B.ºÓ®ùä4VØîm&®8CDÃY:òwÎáÏ ’:/ìòCì;•*ïL>¢*Ô\XHÅ]Ü`.ÈH¸ç%pùs ¼Y³m'",àÔ" Bu$®˜ˆóû¶ïÁþ©gTHkÙP•ø¦¯ÂЏ“`”"N!øŽ÷a’p±NUª Ê]>6 +m›Û:ã¤Ùº@*îêú´èæ¸ðò„Ç—ó¼ýDz²4„Ø­5LÅZ ÇG§à–çâÃëÆrH«¤Þ鬰…V ÂÉQÁÈÒ¾Có·½5G ¢XÜŽhg«iåþÚ…h«Kÿ;[«\xŹ’Bv‡EçQWÿ5nš¬‰4hv#¨Â?“’Ò" Œà7½íuÇ‚˜V_œé¬°£ju6n,íûÈźt¨ ÖBêˆf™ø™`‰G;Ö"4afK*m­@*îâ„‚FB(K½`¼äòÖ¥ýŒ¸Ò¸Äx€@VC=æ©• -/ ÁÐÆIÛri‡×R¤â..MumÕváÇ¿ Ä5ÎùL´Û’"çfõ-·2Œ„V5>¯•vÅd ˜Í´Z‘#oÃöü§nFÛ=ƒ—î¹û†½Í™‚€]$ÝP†`™¼ã-d[˰U;kETÒ&A“D;¼^bWÜåÕöš"BF`üPáßÜäÖ¨UJpi='x4žúuZýqÔÉæ)4›ãŽO¤º{Tœ“óËÍ+s{™ó]ß­½,66~Xм9t²Ïþ IDAT§2m5½yÖØ¼ÕÁê-vÅd ×EY=¦nQÄ,eîx»Ê£(³N“#žÎëÏŠ•±V‡Sû|ñ¶+œð”Veé¥]i[™iM**ÎÑa¤í½´bÖGÊÿþK÷.¶ƒòÑÎ]ƒgì>üþ_ÛîÁølWEÅæ³åBȃç‘éMt‚It¥ü¶ï&Ÿ¸Ú½å‚8²:5c]†“þ=²p•Œùêî8¢6\…™ ÚÓÍðZ`Wœ“ÕécŠb–›(²}4|ß·—yléña{TÝ-œÇ'>Ú™Ù¸TóŠIˆØ…^Zã(ˆF &FpEeÒmß ‹Ÿvݰg³NÉ{ŽzâÔmoÇ4Ç,µ®Ž´ãnÂ`ÖH›2õ «8wkÓã@Fêˆ(ê$ð†×þlžiMlbÔËÊÏ9›Ó#Õ~Ó“ÆœêêB¯Xc¸KÇÊh¨’‹;bHú₊㣓p˳‘ÅË­¤³õù¦ùøç|¸÷*4ƒ0ˆÖ£Øª_†Á0èÝ»êÈKŹ@nm7ÕiLðl˜²¤K#ò0忼¬mZO6“sw Åš6T•Ç?<¦ +á¬bRNïP˜t†B1¥‰˜œÕ‹„¯àêÈÒ~ì–g#£]îRIg»ÏÇ1b´ÿ£Hîoÿ\ iÛ~V¤H=ªé•¦*™æb‚UnF¡j¦TœË æE dI[ÑúP?ûé—ÂC¾r\H»ªXZrMk±MÛ)û~7ÍZ>oÿ®ÐG;xâ¿3ü`¡Üq©ÒkÞC~¹{\YÍS¨£\~‰¼ýyÈhogÝ~²ì㦥º¾¢ŽÒNTeoùCÔrˆšFâ½ÇµMñv¶Ú<9 ƒÁ ‚¤É®[©â<W‹ÆÖ{Â[~¡xñŸ6·ËPÊ©$¤Ó£}®>èö‚ áFI>ÝÃŒPóûo¯P[ÁÌA›2ËZQ1ÁõwéPe—.kutþ_ð[_ v¼»NB¬ÿ¸^ÂÛ´ì¶n?J×*,â(Ã#׸û–„àšywhµJg-¹°«´¥­hœÁf‡T29TŒ*Î×úNÀ<|Ý3”W¿Ôb¬+h8EGÀJ¡ Œ\$tcNÌdØ$F®H‘ém×6sç®ÅFsoàÒ‘W,Ýúv4 ÉÙG%ßþÓkÙãîNš…4šÏµª®8ï«;Ç*5SføÓß„G<8á.XiíÅýw+ÍØÎt'FQ‚àž# —º¢mŸ'`ÓŒñ¿ÃyÄ£Y0œ"HaNª‰iÅz¨°ÅǼRqº ÛZO†¼öý¬ã”½Ðþp ØkTeSf£¥gÏzB\YÚÿ‘7úh?CȨÆX ¦qÏW4±ösA´Ÿlí5$¼^\Wœ÷ ¢³Ê#¸÷½¿%óÔÇX$§Pªë–…f% ç0 q/µIÓr®Âýî«\ùFxÞ·óRœ‘ µWEÕܦbâvdŸ"ÁÏ’Ë8b±¨-‡wÞ÷«pàW] ‘Ò1¼’ÎÖ q¯ð¨ ÙG‹|´ã 1< ŠzŽL?“šÓ˜¡‡4Â`e8Ÿ²0„å¶ wgÄŽ6^r'Y‚á’û ¹~üû…M3Egë\½¼%£yÜS‡QHtw¸÷6xù áŸÿÌyæÓÁŽÇ~Ðnj¢j T¬—¥d {«aŠ!vVw1 É{ÿ+~ðEw\Ï¿ßüùI`Ö×Îu¬¼Æâüõ>ÿÁÇÐd' q·b“é•1‚N» c\a0HlyPFÚLÇŒ¢r©ŽFçeU $ q•ä 0ŸúWø_¿ûìÙÝþme|dE.¾ÈyÀýà…Ï€y1<àÀø°Ì¯Z´³DIŸÂ©°p+*&´T'å^[×ÅqÑŽŒ6žø Ž%Gï÷§øÅ—‹8Sןø€=^Y,«yÝÞô{>ÿ¯¯XK‘zÌ5XWL9²H1²Q­Ì™n'°íß ‹_ô¶ ‚±x&­SBš®Ÿ‡i1oZ!l×Y-)LÔO›Çž»*I¶b=,}¥qk5¼#޹ô»Øe(/Ü‹T¯+¦¾Â6’;YÃa1‡Â âŠö`·>±[½ÝK©¨«¬WnÒºØÑÞ*›Yh+3<òà…í¸*¦kדl”˜Ù*TÛ늉_û’:g-—¸Ö1Õ¸›VBÝO\H"c£,>•c-ËvIX% ¢)f³E°d(Ž.ÜL¾ùE0:ô •Öxc>ô5`ß]S£ŽøûYܹÊ7T–nóÌ`3¼7a¨¨˜Ø•Ÿ‰[¹œÝ·[l™²Z´[Ý«Ä+*¦:`kÈQ7Ž55CsTÚY =õÏØm/~#y‰NÜÔY—žÚëBK\J¥ÉJÞù WIhý®ãçUh¶ÅÌjU6«˜üõ/dBv×Xnûê^Äz%Zá¶B?@¤¶Ä+¦f†$-N^Š+N.G*ã^züjØñ2Ç—Š.ÿú¼üÝžPÅЀ…}qçÛi,­Š¿gÌ6¢Â&¬4+*&Ÿ Ø= ìLŠŠyßG±Ñ‘x‘EpSÄã¿þWxÇÇ MßLh6Ã`.Çp—uEWTTTL)Â]YBWœÞG‹ §šâFhõ/Ý„íx!ŒöR(F!Vâ„w1ÊX+åß Øýà /ûöEÉ;þ,íC³fX-¾׊T$Zå2pÛ@ÇÈi¤—{dWTTTTlÄxmAFs¼ŒAÇHÈþß‚½¿ìˆ•Q`-Zãº&ñ‰ ÉØ‹,ï†Æ¾ë}¡8㎷ pÉÝ@»Ž]³¢ ÊqKqf6ÎÊõ\º7À¤ìŠŠŠŠŠ¨œ[2™ ’0 /ùV}?|½‡›W\Ã:¶&ßd°Ä;Õ1íÚÔ>:üÌ…[¯À%ƒ–»joO¸DCB4/{ +_ÀÁLÐõƒ)6æîUcuEEEE­°½t]c";Çè—Šáâd1d×ÿ~›·1JPD6jÀÖÞÕ´ þãÕ,î,õw°ÀEsç-ežÎÅ:53q%k¼èôb‘”â[Ðb³ž©Å+µ¢b²k€H6#cE<>o»C½a“ƒ8vlìgÀq¤qd2ãÈœ#3sŽÌ–?Sï« )º"E%ªÿ¾•jdü÷WT¬ÓˆÍò*Nè™Q1 œÚõ¾ëepìÝQi{ÆÑŽ(=^0ÚÝ(¹2!êæJÇ–/þ×yçŸáw  †§ f1Î5k4ƒ„[åƒW¬óÅCøADÁdEøG„¬F¢fÄpI3i (âFžWî1ŽœrN,Âp1öÝ q6Í8lQîy˜Ûfqpe`)¤ÃáH GÛÿv/å/§%ud²b*ÒeSL I‚rëÂW\.xް¢È”–cE"ògëÂÿ9; ÖœxeÞF[‚-®äSÛýäÕ /-žÕà£U6µP@Ó0,ß|‰3{/a"õå**V»=$ƒÄ‹v¾ÆuP ŸIÂÃ7»“T¡É0ù pý.øì—”<ó‰k•[ö:‹ Îhftc*M#ÌÍ:÷½§ò”Kg=<îáðÐ Í…°apG\"â/ìnÝ}ßxÀv¯SÓ.GçÊ¥]φËEȃ®„ÍO“¶IížI»"Ü•Îý㙦´á…sŸ ·_á§>ùÒUt¸‡-š`ýïQaÛƒ !KWQ±n —’©YñN«ÀѸšMà™» ÞóQxë_ ×Ýääa)´ÁmÔÕ¾¾ì“øEÇ\™—> ^ù=ð̧Ã}: ãM¥kŸ/ïtyͬû®bJ’fu’ÅeSÜI)6{ô+¯F6]ZêhïöOD¡(>§.`·™I?Œž9ù÷Ïòá¾ å®ùË?âwí÷Ûæ ¶)[ž­ë>`gµð굌ªv]©,FjKµŸ7~õ- ïþ@æÔ’—Àd4^üŽ$Ö5ñbB#>×"Ü^S]xxõ5¼ä»FÜ÷àÇ[a¢`Óv.úªºŽLVL"U”‘:ÉcW%æ¾ ¾úÃ0øj1ñh…—m&ndQÒ9?Ö:`3.ím ]ë'¯~xF,%àšDVo M#F[ï+4{‘z­»b=Ÿ‚'C{¾dH/©À&åÀ¾¿ü»Êëþ·‘s“KÕÝ&³$Ü3*m¬—âvWªt!®• Æ‹èj¤¹¿´->Ép7´Äל%ž æw. mßóTâ@j•ÌÎðãnÏ1f‹à&5TWLA‰m!üãRô€&á³ÆG>>â‰/‚ßx»1Ê­T¢ö§²A¼^[Va7¡mеѰæ]{Ü»Cª âûÃË~¾õ¥™/Þ$ø–èšPî²W’Ïj¯XßHYC×K¤ ÖÙcJÃÒ©C·_ùÐ+ÄBÐ ÷ Þ jhk°OˆGë@ò<§n{3VîÚVã†"/œ¨‡vø¬"³N©çEÅtdù³¢&  Ìox;|ËÃöÅj¶‹•¶ì XIüI%€·mòÖØ !ý#ÁJï~¯GåýÑkàk_ W^¥èlé´4º¢býõÒW2Fòv®©ä³'ÿ¿õ{߈œˆÉ&m{Uç>¼®ý¶X!¿(Ã#×x>z $?„¾Üi¤³\†Üg¶ö 4^Yª“$tq¯ÃÐÎNKǶvŒ$‚Ì*¯ýMã'þG[1[Q]‚Ó|å9ý.¹­¶Ç6PüÏœ>Um+Âoì-s8rÌyÁO¯{sFfÔþ[1~&iBEÅz†tz.>Ú7E«œ)èñ’o{™ §h$±AG±oll_úòýµ¾¶Ç½€ ä]ï/ä# àƒ³ÿx+SêBšQÒ¦qÒKÍô+ÖIØ–v-ûXpõ’t:*Šov~ù Æ/¼AË|çÚoߟúç½A`®U~Š‹ò¬ uûUL9 Å[1¡cï†?åÂ(®c5d¶m#xákYÄr¿ãûw2´Ä]ñáw.Þö6ÈŽjBÈàÃUWé–!Í:ð;õBTT¬u•½<ÁŒÄ3ÅÍ¾Õø“wÁÏþ¶ôÙ¹L‚(òêßvÞô6‡ÍEsE~xõ­­˜jhQEP }Žþy÷«¼¹l J±±¸äŠˆ•9Œ;+ל%’¢‹{¯ô…¿€¬ñä"I«>”Ü„Í_aÌ\ äv Îë¡Q±Î‚v¿^¥hË,\ÿoðøË…ùE ©…‰h µvàê·À×=MSN¢¥eÒÓ·mCÛPCs ºÇ}_ƒ^ò rZ¬C{:ȘÕÖIØðŒvüI< +âêeôdÕOdF™ÙÜ“[k°®XX¾^Ý ,-5üðOœ\ˆéhm·î,o/;m)7üÀ«áØAgÔ@r%K•¬˜ò[<,¢ãm˜Äˆ£ì{-~à7º"º‹eæc[w=¶Ä]É‹7ûÒ®¿À=F±4K¨Å¬’4fæ¤YCf¢Ò–:Z±^6¼ŸþµfŠ È¼íÏü\ü2¥ý6 ˼õ¤gÄŽÝðs¿¥¤AåêvÅF¨°Ckß1ùìvÙÛžWaGþ èþ…ÃWŒ‡>ºS&!ÀÛûw¤Ñ¨áb˜ ¦V™¡‹À`K´ õvª•ŠŠ ÝﳺÿÚ¥h£4phü×ߢ»nex{mã5Þ¾6vŒˆðúwŸø¸Ã–ª2X1ýÈÄPA-&9Ô\ÙõJ8úçN™2Û O¨ßqa•5ØFfñ–? ‡®Ò2ˆ*[CÝi5‡F#ÌlÕ)÷{­ aEÅ: ßË’Pi”7ÿ¥pøh°J]89v­ër³»»±S¼çQ~ýíÚYsVTL3’I˜áˆ”¡ì¸ŠM²4h^Âwü,|Î¥Õ>@ñ¢2Û– wº·mýòý£ŸóÑþ¿ Õ‹ªÁˆ™PÓT˜u¼;šþ˜0§™˜É©K°óR×ë¢Ê"J¸ZzÙü±ƒÆ¯½­­¬ýÔ„1Å'­9‰ÅÿÞõ!çÓŸR˜+íòöúNúƒ W«¨Xß{·ÄWßõ­äXçv vüÈ c+¾—ž°€­a>жŠkhU2KûßhŒ+–|™±•^ü!^œÁ–ò›[ }™Á®ÇAŤ#Ü­¼«F›¢É­³Î'>ŸØ¿ß» Øæ¨“PY/{$Æ­±Ý÷ÜЦïrµíûå{´¢bÚ÷wÄ;;ù÷°ÿçÇDî\ø=O-ñV¸u'…¢eoùc°8´ÁÆR'•´ÂH¬œ\ a°Õ!Ç×.ã‚)µ%W1áú˜ºYdã}`~Ç_gÂ#6uIjom“ø$ºýþŽ¿†“Gc2ÓKÐV?Ã_­¨˜êýídoöýœx¯‡&ù#ÞíÛÇþ%©†\Y<üîÇ>×}‹•AtÂð`ܪO¥»›VZ{?§Ùäha¥/E]%ë)ï6aŒ“sôò¡ƒ3\&'Õuk´1 A¡TØm;[Ïko„Ï}t0žl×½Y±ñ*l5GÍÉ2Bvþ$’¼ÂïäXæÝ¾ãeÙ¶•Ü÷¼7Zá®Ñ"÷°þîRÉÅ_Äoõ2°>³¹Ì®¯u„zGV±6ô¸ia'Ø¿×Øu@ºMÝh €k_e ½ÀÊ£åº[Õ®QÏ¡íŠTa[è6yé&Øý_Þ»`ï°}<“PÜsÌ£-îÿäÂö?"‹b>ìý{½ˆª«œÑ< 3ö0Al)ŸKÿ„*9µbýlèrÏÕÞK»Bö̼0>´«¬—ûIyÚåÈ-‘F0>ó¥3%Íå´îÓŠ \¬qck z+~ìÝî“z‡ímÁn¸g÷\ùYØ-píÛ^‚±Cç’²Rõ¬SÙ2-E_1FR'º*ÖÂKD;ß=Êšc„Ï]·N^k«—U iÙ©ò…/:ž -b0ýöóyüTT¬!B9¡Oe ÔñݯFò¾C“°ËÈÇ8‹TH ÷~ D‹=¦—rÚSa‡‹{²þ!ªHŒºÌÌ–/Š$\+°œ}9Y­¢b’7t.;ÑMñ-´ý‡„p‰ïý­Ý{¦µO {K(×Xd ‹±Ê%oíAoçౚUWLùî'’tBc» K7à{éâ ¬°[UïÞ[×N~ÉÙùþ8ª4î¢EƒX¦.}%¡ÔR“îPÈå¾l¹(|F]Šgi±÷SÀk¬®X'Z]ÂÁ§E†ÙÏ ]Øî z£˜íçÞN€xÙ¾D7l|?Š„ìpÝ£Ó÷ÖO[ 9sló|=œø˜ƒÑ{wYÝÌg¤`–ø°'–°»¸û]Œì8YÒ*žðò]=Úãi“šTWDÅú†…¬!b RnŽ„Í›d}Ýñv’R…%‹ç²RSÜÝ'§CPQ±†íû9`ˆ"qmTØãLµó°…A—}ÇGÃw} ¤ýމŸ·óœî^´Ã«u_ÅTÙÞVÎíD…sɽm]øºwEì¨Û“ ó£q¹U)ZÊ} _Q±‘ÑÌÿ-vðMá"ŒµÏFg´9,q:O\†‡®ñÅÃWÜ|g?d¬Ò.ÕG3€fkÍÒ+Ö?\<îyǶ¤»sŸ{¬pÖ=Ærí8hðVÔCrµM<¢²Ž¤½’B+*b¿Ë_‡á^»œ–ÒÖ$`·é¶ÇæÎ{þrTÚ‰¡¹ê£0Ä%Ñj¶6›Ü®riEźI°.œÂ¤Aqî}ÌÍ­.ãÙu ÒNè¢Çœ¥æ,Vï¯+*¢«fK·Â_`,%iÇÎHÊÔó±›…&ˆ-‘w¿?Ô_DŠÅÇ*~…z?ö%Nڔ˓­oxÅ:ϯËv³bÊAFÊ%÷Ü{< éÅ\´mxG‰}殾êDXƒVT¬ùÖEqüàð…/x«1&è åÏß%™Àhß{}xì³JÓj²ì~BËÀ„4# ¶Ä³ª›¾b*²l2ÉS1Ê0gî"xÖ¿_/UB¿Ç½KÕG>(tLè5Ò[g£šmWT=Œ¯Ä¿Œnwâñ¼µÄîþ ˜"¤Î•ëì§AØkŽ 1'  º|½«˜† ;¶ˆ#R·Tpƒç?k=‹(РEl¡Irãé—©èѝúdWTt»Ç±×G~äàä¿DŸJΞÏéL‘Å£Œö\í?Í(Ò‰¥|ùŸÏÂg°5‡¬¡ÇÁVQ±®«ëB5q5Ä$¤ Å`I¹ì¡páÖÔ¯±]å<çÚgÍ8BØ¥/˜µ{d—>\a©½ÊŠ'‘¼·¿­¨¨vt¾“ â#8ô[Ñ/Þç=`{Ñ_Øó.Ïó;BK<£UdÚ"‚–êºÀìæ˜ë¬¤•Š)©±C–tŒêYñ ÷¹¿ñÏÌÑjnMsºjÕ&#h—ƒ%4 ƒájÀÓ—xÂã ϶â<¨ïxEE‹Fã¶ÈR¨¡ ý)vò_» wFû®îm5žëÅPÀMhf¹1}e«4ñŠõÕ~ôÑÝ–é„ÿø÷ר=qb¥†÷Z¦… #”;øqx勌Á\lÑ ÖéŠ{ëêÜUQÑ™ÿ˜ $9£GÞ|»{ûîNqȧ¶ûÒÞ+SDRÌ`“Hwð¼I›¼O©¨˜¦Mæ­e&!äSÂí<ãq©óŒyÞó•o¯"¡hм*ŒxÔCáÛžéØBKt•Áºîኊ>uÄ'“EðÃoƒ¥ë}M6b,ìþsté®+\·VÉuÔ3ôIK~¯¨˜†-«ªÝ}6žp ÅÑüòöЖBàéÜïÖ>bGw`$1ù¡¿ø“pѽ@FÒ“êj°®¨8CAã.Ñ…Jø"zÛÚTظ"»>„ I†¸âbXZ]ÀuwtÎ]¯˜ IDATH3 Öû×û°Š©Ø´Ò»Ë‰´&6Elžôdã{¿­õ èî&jù; ‰ù.xþ³ÀN¦¨ÜW<ða’iXXºûª[âîÐl^YQ× _1-0°V Ì03D@%‘]I£Ä¯ÿ7áÞC¦ÏóDÔª©lEAyìÃ2¯µ¦DVN_E¢RQ±Qw~¯«ù¬ (2Üý?ï{q÷_ã6Â%“5/»«3_K<%lVpAŠörüYm¯U¬û»#Qºnºì.[1—<Ày믄ãt.> á.—Û©Kîi¼ëuÊÌ…-ÔÇF½zÓžå‰xÝ¿©§RÎc$6ÓÇÞ}î+lïFM¬ Å]V_glוŒ4æ/Õ˜ZÌe»ž&îîá©kA`1)ºÒ\TÑ —e]EÅúE;§\ÚÅ#]»ã{rByö·À¯ýLlòØ{ºº-,ÍØßUƺð_æHÐÛy´ô€÷¾®ü]á!1d±ßÖÒ>þÓþ©Áº¢‚h‰»H·Ó\„ÔÆµãWã§>áã\•sPa1×¢!\©K>è‹'?Cã€pÏÑBë¤IS˜,«¼EÄbÞšã\oÛ?i**¦0œ #@İyxÕ+àç~Ü;Ò™Œmãåâ*M÷=qFev›±±1ëX—à/Öm­vÖ[IåÏR¿õ\2—ÜKxÏï Oz‚ÃI%¶x†3j!WTTÜ€~ì}PÌÎMÀn=­¥w‰ÉQ%ï~ƒ%CHd†%õîI'ã~ØËﳊ’+Ú83[Ëáã§×÷Ó½c#ôŽ(„ËS𚟆×ÿ,ÌÎ iËuke;*ñXËnÒNmÌ=w÷åm"ŸÛ˜Wu[½.9þÜ=v\Ùv—>þæmðä' ùd¨µEv`4BX‘UTTÜùrøØ•à1ÊäÈ]®Rˆù¨t²j><òà¥ÝWâ2À<ôR…T6qdî]E=¬—} id®—>¬R) – ¿»èFe…“Â|9¼ÿM‰G<`LD¥t¹´´ÔÄelÇÄŸSŠóØg”}ÌH§½–‚P)Œïi§brÀÊKž{‡ðˆ‡8÷¸‹#¡¦Q÷›ŒÍ‹WTTÜäÅOãóóÈÇõTØÝ¦,AÕ#&/íý«íÄm˜ 1 fkÛ )„³BaGì4¤˜ß4š9)~ºgªÄ+*¦<ö¶Ð\.Ç xÆÓ2Ÿx'üän‰[.›€flO)ËÒݱ=$Xˆ•°/’Ê÷ ¼ØâŠ3åÒ‡Â_ÿ®óÖß„­›Á'‹âd#I>ƒ]QQqGLùwÉô¹!‰€7±É%îÛØõaT"[O>À³ušà.…í-§WÌ¢ÞWíÉH[[ÎxvP[á¤Â.”Á’9ªMTÅ'”mÀo¼þå]ðÒç ÷¸¨TÊŒÆK¹¤Je/ÅWZ||³pPJå-£²áQþÿŸ7®y§óíÏt8:Š6¼˜:sŬ­âk?¬¢â®FX?ùw]±*ç‚­é”ûåö.ìän?ô‘G#KG•«´æB–Ôä娞ùKÔK-Ñ0rcv“±åRH2íýw©\ªpJÅÔ#‹Ó xvÁÔÀƒ¤Ù´ûAf o„»à÷ßå¼ëCpýveþ¤a® Ö±·½DÁÐV=-ŒþÊkHŒøŠûÃÿüØåð Ofg²cªˆ[·E¢µ[Ý‘¤àÑί¨¨¸ Ð-ð5×"ƒ¯”»°­øƒr‹ 7þ–/|úU ¾|îZ@ÝËÝš†ò™ônENŽn'²d¶\³_2Ò>ÈÿA»6^EÅ4#ºÑNvã‹Òí©¨‚-\D’Á&àlß-¼ÿã·>×ïj8|tıcprAY˜W‹›6 Û¶_(\r¡óÔËàÛžO|dbËÅŽ$ƒS‚yȧ*aô‘<ö ¸—é8b®Ô‹ÜjÝ£w~ï;Y„ô€+àâ”sRa¹´Û L8þ‰çzÞù¾¢y|–¶˜+H.AÜÉö™Š3÷@e0W7|EÅY7¶ŒÏ6;¢|.C†§œ…y8vB9rÜ8q Ü”MsÆÅÛ”‹· 3s™ÁÐà#‡!TæXEÅZÑKþ¸Ïÿ”朗¯’O|Îm÷Õ¥êîǸnÿ‡[²ZO4Yaf¶ÖЫÚÒ¥“Õm7G<“OIœÀ`+l»Ð¹¿jicÇ<¶d‡\öê’“£ªW©]¬ŠŠµ„A¶O}hÕîZðïªhwa´óÏ1_ŠϘ®î „èüE[-m¯~EÅÚË¿¦ÁÊ<µ÷Ëâc¼M!CÛ ™ÄD´¸k°®¨˜øü';v¶ô KÂ…½ï ¢`ºŠ`ëZ.é ÇËu¸3³5åúfUTœ5c>æ¤TÐE6ED{é`×F‹;i/S—:ö{ƒsR把µ‚–=ëy'²xƒŸ›AÉ¢h4Üÿ·n¯‰ëUÞ !MJ!©@ˆ¥¤9«Zá«Í›åÌwëïnˆ¯P/Òåₘ ¦…=^RðZ`WT¬í¾.Ò‚N†ÅëïúvnO ‡¥½W¡$´ÌY·R¥g‰öhjS %4[¤:qUTÜ‘:ÛoïûÞm|)Î@ýÖ²2LïÐ÷.šKM˜+*Öv_·lWîºë-ñ–næù8Ãï‰c@3š) Jv–Ê@ºÀ/>Bg Ù\ŠŠŠs˜§ãgH€-òìeÖ!ínÕrXTTT¬uÔÇóšss£Ýïù?í½{eYvÞõ[kŸ›ï¬WwO¿Ô©êîêé„eK¡ñ ²±16(,!Â`@ÈAød a6Š‹‚"ŒCòHÈ’G- {dëÒ #[!¦¥Ñhú1ÓÝÓ¯ªÊÌ{öZü±÷>gŸûÈÌꮪ®®Ú_D½²î½yóÜsη¿µ×ú>—+¿™.öÜèbÄ*L`Ý{I ¢0ÛP6ö;ÂÖa§þí<øQÒµrêkz€\{Á¯½ôcK +ž÷Êô¸}h•œü“¶ÀCPt&”¼woM/ wóRœlýi]â94 <¯­äŒë«/þ(×01¢tcxÇ©:Å=%uF·9fñz Òlhhhh¸ËÕuâaO=^§'ú‘|˜Ò}|(|é9z‰)ÖOæ#QK8Ý[G;'l¦„Ÿæ?ÜÐÐÐÐÐPHÛ1?:a—>•l’Ò£žcúˆØëŸñù ?…’wA<•Ïã)œ’$[$êL(F©"’µM솆†††»co &§SØR+ëü'%pøòßB-&U¬`æ"æN8E´ž« Á LºUSW\SÚ ¸Í»Svn0ƒ²—­˜8H ³Èü¥Ÿ¢—ˆh ¾TIJ[ôông &mߺ¡¡¡¡¡¡–Ë" ¾uš’xúåôCЇçÌÛù«?ëþÊÿ^Ä•;Ä5eÙŸÊ­LD„NV”î^e]ìÄ÷NgœâBŽäËÉ×Ì_úI\R,Ÿ{Ì„îô‰×SŸ·Ä¼¤¬‹mñx0ÔSœ_²5-îLm´¡¡¡¡ánVÙFÔs'vâ`Ÿçx| ûâOžîÛcÀ èj§&ÇO744444$£¹£LØbž½Fsb®Äœ£—¯ü&š%´\§+RI’`„ Õò ¡¡¡¡¡¡ADŒ>ÎÐ3_wŠ=l@;Rg*ÄÿA¦¾Ã×KNi Ú%?µº ­ÞÐÐÐÐp7«k·4N½ñ5Èî§tö<Î%ÉíL}†]ûŸ¿ø ±¸°œð«¾ªyÖºËeñ†††††††‰xÅ îþ>DÂéºÄÕ'æ38|áGñùxeöýN”¶¨YØ>¤¸ÐF°îjº§ïÙù(À)Â?<í_«§lÄð—>‰;ô§biYù&‡³nÿ’FÒ ‰U°ø³{ÿàÇOEØ"‚ãÃ<¶½ñŸ¿øÉ4?mïÎ:TÄ!,¾†cm뺡¡¡¡ánWØ&øþƒÙùçNEØxîèv€žùbÈØ=õhRÏ>}Áòm5u‰†.ù»Jší–&¹îXBNœè¢)–ÁÄQ8º²ÉìþƒÒ”}rI\J&6ˆ ó—~í@ŠRÉ<õ‰û #Q{Öª‚þûzg¹Þ¯è¤O¢®’®Eàð­]6ÿ(n'rš=l'~àô/ÿ4$ù…ljúhZI¨Ââ v›¿nhhhh¸ÓáEÄbˆ%F(ñ@‘s߉žù:©‹Ï§ër"Ú¿qñê Ÿ ºà½`ÁÙLåzQò® š-Ió›¯f¹šÚnhhhh¸£ [RÇ– Øtì•Ël^ú¾),ØéJâî)JóÚ Ÿøœ^ùÔ"ª)9SýôŽ'5›b¹4® Šz±I­¡¡¡¡¡á΃šáÒe®0®½æÌ.ÿ·°yïwX¦Cw±Sx‰‹=öòsAÃMègÎi#¬}…ÊñÍj´îd… šy5\}ÕÙüà_¦»ï €Š¥²y¶§j:³«_ôøÂcj ŽKÊ¯Öø.Hµ4«e‹ÒÕûÖ´îdÒV"pøšÁÞŸ`öÁ?/2ôuiÅŒF®š[E‘Æ´ æ/üߢs!º`"¸Û©Upm„’þLRÎçø:©­…44444Üî°%é™ÇÒŸ&#·¥íñÿÄ…Cè¿ìôÝïgûkþ;ñ¥Â·v2|ÁÒŸžÇ¬*.Ž/ýÝa¨[1Ä%­ ä]«`–›×ZE¼¡¡¡¡ávFðZ)Ë„¿Ä!¸c*ˆg®†±-!^uÞrdó_d÷ëì’„³/‹mf ý„Å¥¬r•ºý—|þ¥çòA 9àËÝðpº ì*#dâŽæ*¨Þðå_*ã¯ÅǨCå`æ’l·…€ÛýëÆákFØú&v¾á—Ù™ç½z _±cÝ1Èï)›{ûý‹?}Ïq£l»ä²õuì¢Ó¨»ƒ·l͆††††Û¬W|ÕOZ¸"‰§Ýs,¦8Ïv˜Aÿ6ôoqt˜=ø'Øøç~HTv²`6\@\Wnwå­ ýg2Žr‰EŽ^üÛHØFíÄ0ÔW=u‡øqÊ[$dU]ö¬›Änhhhh¸ˆz>‹cXV¡c±Ùó9“[èýŒ£kôW;ú¹°õÄÂÖÓß/%¶Ú1…(FX­°‹º†b&pæ½òœ÷o~:•´5Õ܃œˆØõ«ËÂĵ{n?[©ÇÛ¹ÒÐÐÐÐðBV¸L‰Üó¿=o‹$…ì½ßžsp`ø‘{îIö>öýtý«–ÄrÑ«Åõ ¿V¶»§NµúÛ;ˆwðÅ¿‹FEÄ@4)k"âŠ{D‚^÷¼´ O]æXZ X¶:mhhhhh¸Ý ¼HÜ€¦r¸ .u…9ô†FâÑñHÁ„h‘íÿ›_ý_aö …û],uâB±”Ô5t§Õ„]¢3M|œø#ö¯×Û/þªNÌepEèÅSgœfÒ=UĦ,»x1GÑua] ï!|P̸àB*W‹bl"fpé™aóˆG0‚°õ(»Ïþeº‡ÿ¸`Ž‹ ÛÐR&³0”ô÷ˆ¡JRÚË ;¢“Ù/¥ñoÿÙÕ‰:vyI û°y}вµëÐÀéµR™^!:n‡(3ðy*™gµ1‚ -a³¡¡¡á½%¬UJS|1üÉ—”èúבJÈ­Þ'N¯ïk¹¦8eNÅàôñ2¨Ø.ñWxÇJn`©wKBù˜ufÀ6â‚Ûœ¾?Bû«ôóCüè>ï±(˜9ÄBœŽîÑ?ÍÞïú/Ùg÷}m9fÏ2y·ü;¬ñ4K ›.ѱçÎoâË?KÔðy¯éLswÜ=ý!æEc]¹ÌÐæ¼Þ+¢¾Å$'¿VÕ¬5Vhe5±+Xj™F+b½H| ôÄÝɾ³&pO;¢™Œg¸(ŽfÂßÊ=[]RÐfXœãó«x<Âíë3?EÃ#©¡ OÝ&`†iô³gžbJ÷à¿4å^æt6K[Ë"œ2áz$ìallß‚]ý ?|ñGqqôKÜDÔym^‘Nó÷‰2o}g ï¤4Sù2)—nèÓ½NΠ`¼ÿBpŸŽÔäï&èDÆ;cv‚e¥ŽŒêX<@QɺIð©gÊ"¯aý5Ì ¿Š™á}LÿËcY$RŽn©`Ͼ%išKðX:ÃòcŽÀUÙ¸øï²ýì!2Ûˇ(MwÌp-?Êõs\ç€h"ÒrÜŽ^ú)äèћǘi$¸+¢{¸½Q ed¼Ù“6444ÜòlÜ÷9ÖÃRÏ—hV¨!5qóÎüGº²ÙÊ–:À_þd çÈ+‹›r¢¸&·´yv0qÚRºnNºßº·/½¸GœóœÎ¯,îwçnk„‘Ù°¯›»6€€‡YZ4DÇâðx„Å·ÒÈÑüúLÈfžÙGB. ŽBÈÃ{Ê[²õ›*Û´å1ê‚`ÉÛ·Þáæ8=ÒkK4BØfóéÿ€ÍËß'tÛƒä (¦©a{ØGó·µÓæoU„Í(Í%¾õi¿öê'Q±TfðxCWsu Å]ÒŠÈÏT'Ïh–î­ã¬¡¡¡á½ÐÞ JzQUKEÔ©t^¸?»y0ôGI.Q YÏ@6@6“H3ÃcÄã!±x€Ç«‰@û8¨c÷Ô%.ãÖª@°¡b;¾s+>6òÊð3©[ðüÿÉ6»P”Iþe¢€wˆö@‹¤”IKû×áÂÇØùÈ_'\øz¼FJÜÕ’¸1G˜¥‘hyúz {´$uÌ_ú9tn©)€xC ÒuÙ}h:ë‹sTëÅA>j¹á ¡¡¡¡á¦éì%²*«&S%£ø2•­ò…Ô%3`#ý©¢â6OûÆñ‰=Ö@Ì 3ƒ<%^H5{p»f®(¥uÅî±RÉ2!d¸DV5µ™¢Jçà¡,>&ežö³ƒxîêΩ’A‘(`í³ué/0{ú{Åu–ÊßÔÞáÉÃÄsc̲}i®fsý]Ý ¹“[ ÄWþ>Q"ª¹5ý&ˆÜÁ¬Å€èÄ™…-ܯN º‘uCCCíÕÖƒªl¶]‘xH ‘€Ëæ tÍ"ô×òÞñU<¾MŒ1Á­OåèèCÎr)û§Æ²!ÁÊ%—ÿ—,qÞ¨ X²ã¦§DÕ¸œ‚¥ •))zŽt PÒë«X^Ä’‘‘”u”Hç–r%=íjw÷}[þ¯éÎL0Ï Ûéy‚¥ìRk*Óg#”Ò.þNÈ:)ì¼!î~õó>õgÒ¦zL›é7¾K\憛‚9>ïaûÄ+“£5544¼g„U Œ©Boº>ID>N`HeÍÒë«4ª4¾–Çn Ö³Ì&,ݯ±yk|' Tº´íYÎ;D:Ü7üu±9ÞÏÓ¨S<ÂíÒÖGÌ,‘²ûÆåÛŒ]ÖZ‘m |U²f5{ѾõOéV“ÏC&ÿ–nºO¾ÄÕX±W¹ÒåèˆÔ"ÁÜÐ9¸å'õt’ý½Yw—ÿc6Ÿú 2¼ÞМ=–¸'-ešiúôƒuE]ãJüÒ߃ùTÒª"˜V&)7ü²H‡,üð 7€«£Qr³C#놆†› _!*Nº÷dG,¢1Ý—Wñµ§Îfqnâ—!„lR¦…tk5ꙸ§÷ÎòÿÅ$ä¹dfƒ8È&©L½KÖUçöüf=Öáñ í'÷1uX»çÒ5cäcI¢rŽøwŒ]ÕÃÏ'¹{nÝ÷-l~ì ;O•hë[NQÝà9îpôÚ/ î F0'ªÝo¯=RŰ#'öG„°•ºÅ›Ânhh¸ùjÚe[׺îèe¯¢jë¼Ò]mšK®,>ÆÓþhíM=:‚¤ò0”™[‚д7ŠÌºäÆ…àt¨l"²‘ˆÕæ¸õÄùaV·7±~1ëñ˜ö†Ý±Š\­ªrÚª.jO{Ç9§¦/õåFµºË|¢ŒWt’¯äŠ£¸žðüzf™¬§£lýt:~m#*ó`DŒ(Âlã!¶žù>6ÿs‚„Š– Ð[z¾v‚bjoÑ¿òIœ€S&·ß\ÂtwÜ›;~xÙ¿úßI'¥Ñ¸º¡¡áæêkY¯´O‚Á’ †‹Oœ!Õ“Š >%®ñûI¥>àÙL4uQwÝð`×ò&.iOÔæ˜A¼Š÷=1@|b U2³äeíÙ2ÓúÂܱ¯™Gׯ8)­;±+B6ñˆËŸ*¾¦šQ¾ïI„÷îqÜ2°à‹Ã¦{ªævªÙ¤ÅˆJ®.§ýîíÿ56¿æ¯"³Gs ¹‘v¢ßrêrŽG¯ý¼Ë¿•‹ï’Úν¿IMg’=É“⵫Ìv?€C£4²nhh¸”½x‹Ÿ²¹øZB.Dæ$‹LÇœÀJ×pÈêXÓ¼±÷8¸lÉ:ÓŽ°x„ÙnW‘¾Çû¼H.U[¬÷Œ¥ê¢žŽ/E[VÊË“áý—Ú÷ho-y¯¹,$—Ý !ÛÊãéÃÏ­Ç,wÖù× úÝ~¼iÒ)•ÄG²&&–s²¡‰sBÔ4µ{‘Ýg¾ŸÙ#¼î'£„UõD:·¾$>1^ÿ ª’† ~ÕþP†ð¨ôGF<¸Šnï¿DºÜþÞÐÐÐp3P†j¯ƘX,Ýú„ÏÇ1MäT,2ÉÉNÈFræ’qÅâ¯Áá±wÜ®+u\öSÇòÅyr‡,³Ã)éÉ0 ·œÃ\ÊÜnÕÛõ‰Ë‰á©ë»Ú?OÕ™Œ¥(Òi“W2.„¼ÄW®«¿>9èÕ=ÝüøÇŸÔCu ’B2;qå†çJ*åŠ8ji]³ýØŸeëw}?²ñ`úørà•Pöï…NÃ0]uK »¬ìêç@óVŽaNð'Þä Ü-¬Ã7 »!| µr¤ÚM¥¡¡áf ‡åäAF„ ˜ƒ*ƨŒ'¦ÛIçð<9rÑ_ƒx””°@4¬Ÿ]Õ–‰ªL-ɤ™ËG¢²ºT=5—JcFyÜ‹´4ø$’f¨KD%5£«.!+õÞìàÈű}*r¾¡¼!“JÂq„nnIšOKÙbiñ‘EvØ»ÄöG~€ÙÿŠx>6åqâ:+íqºw<šõ®» …½òïîˆô¢ö7|¬kP×RV‚A¢stõ*áì5TîAùÊ©ó¶ޕ–.{Vp!dIëv†@‰X”üªc¼±Çû×K^©¬1}°ÇôêWª­êНQ ׯ!ú ¿˜¸ O‰ä¸b)ãO©,H&™…°Ãa¿X¹2í§KÉ›˜ÿ¿nÌÒ¢ïöœë-ƒuĬ'¨ß¸bÍóË[;éùe¯ZLXÙ0H‡ؼøçØ|ö/}·l\ø¡´€ É‘LBJö‚쮃Ð÷¢'ºÀ^ÿ§noý:ê©3¼ó2ƒ}³.’±áBL ¤™líøö«è…§è¯üÂ`ÜABjΖ•ÝÐpâµæ¾ÒÃù:–×§º­®¿ û1ïmjo¹ÚqkjQ,¥ñÇOå8(æ•ÔqMnâò²Ÿ¼Wíç¡?LcMÖcýÄ’#£äf®‘|©æŽIîB^Üc>] Ñs¹Zu]i¨ÒUŸOýˆ×eh…`ó¿eñÊÚÏýf©Íj~ÜMP’K™XD=-*Lª½æ>5ÛI~®‹å±a° Mdï)Î|õ_Cîÿúë˜zã[:=–ïÿtŽßú4Î ©Ž7¿žÎ+:ô< ó·ß ì+ÝæÃpí…a¸±÷ˆŠ&+»pó;Øî¨VìàÇDMŠ£/t©„­z|Ê’ÁEøzÉ~9XBV(©U„WöZV„œÇžð"›CÐC²È>©&Éèµ®ð¡ê•â³Á‘,VϦ!>«¿Oýu_ñžJ#ÔVš•WiìI²_µi¶~´óC,H¸]K.Š}“ìW]š¨L@ò÷©NêÈõÞ±2qÊLjΧÝÎËë ¼ IDAT¥J•­xˆèº Á$ký^°ë}þj.Ý/7I“D½ÀÌ!ærµÆˆ÷‚‘s±{P%z"„ó_ÇÖG€pþ_É‘®2*«<Åo3ŽI^âG¯‚f9U0ˆs HQSw¤@4A¢`o¿Höuº½ào:ÈÔÑ—:!S{ù‰Y® w9Fµ¼Îü£îŽ–I¹QDr%k|ž×Ò{‰üW»q¥×®çó©šcQMªF45ôÈv2ñ>'Æ<BŸ\¹ÌßHÆóL•2®÷ŒErŒ¯•$§²W›‰ÎÆrx½È)ïS¼våZ¾'BöÕ¤]Æ`¿VÁNº}­œkÒc–[wð‚SlR'%Ý€E ©æb-½òÂlŸÍKÿ>›OÿEA7+T‘ª¡Ìé’7Émxp;€þÊ?K§8&ãþЭ±5L”`–öbú¹Ãk¿J÷ЂÙçþjj«×€DK'¹J[heñ††ÓÜú–nñ¥<ë>%é,-רsYVx²¨¨%/° [E›g•Ü!º‰û •5hñË]ÕÒÏq;Äû7“—sÏK•u\WêT§IŒ¢—E¾ÔS^ÒŠæ%É>©O)NÈx‰±:ËjÅ‚é¤.i=ñþx}¿ÃÎZYu ªcaNo1 "hœa~„jª¤XÞÜÕóßÀöGÿ:œû˜Œ&*¹Äá1½VVíd²~§‰Z7•°-ßü§9E-ͨ™ ¢ÅLþæßF‚)QÓ YMRÔÚ›oÓïüݹÃë?xÄbDUÓ>CïÉ%® 솆cÊ¢ö©zÉ~ÐÈ‹ŽVå¦V @Š£p2IsÇ"›w‡¡T éÿû#°#,ÎÓÞ±àñu¼/ñºcÎñ Š½n⪾w{²5¦çp‰åxÅò³uU~r+ÊYJJÔTÄLŸ—ž@ u3—®¨HÚ¸°Y© «ŽÔ?Þ•çoÝO1rª†Ï•NÀ$-ÀÜРô8êN×£{òϳóô÷&[Ñ…cŸN³P#}ªìX꯺íö°ýðKεWÓÉ‘¤+¢ãlß­Xø»GByÀ,2õÿEö%ìünìʧÐ|“Q“c›i¬Æ'Ô©D-iÜ=—†e,yÏj‰ÊÜÑÜ+y?;-6ªEÕ×U†a¤¸RÄs‰uµU¦.l»ä]½XÁ.ƫշ¯8ÜÛý-Í«6ìg—…™ÓI$š¢"y?W°`lžÿ=l}Ížy&µŸåµh„ºR®­ P]®4Yâ¿ÛnûàE¢¿¸£¢ô Ö¥•†‡›˜ÖUÝ<4 ±§ B´HÒ!ô½Ó½ð÷ÐGþetóƒpø[©3UŒˆÜ–{ ·¯BÉó¶¡#@Â0.„o€ä_¹»Ùü™bî©‘+^K¥ò~ŽÇÔÚÛ¨Žee¹zêá<‰V¤tas¿#‡%âÕº4¯’-<ŠkWÒjº•8–ûM†’}5Õ<«”2ØÊ™_c$Íi¸ÇzÅ]/ ü%íœÜ#$ÿ}îå-e.q¬NLP„¨)Ì£—Ô(̱­{8ûÔ÷2»ô=B®¥ŠL"ü ©»lksÒL×HêNý˜Ûˆ°íàKHi0SC{†ÎÏD‹r >˜‚ÅÝ Y5›ôÂáÁòÒÏÑ=ô±ø::ë ä¼î`©S5Šæ»´tòìÛ:ÉïvÂ’åÑšªLì²8δðo[Ü£•ÊcºÞ6ZÝšžr{K¾ãéNU7ôˆ“ø"1¬xíêÛËD×€è‚b¢y5 ¾º•›¸§Ç¬‡Ã+Y_Åâx44f G‹ãë»ûè¼UHÔÖeGçŸË­?ÇÏ"ÖÊU*QY7´é´ ¬c¿•º8ƒ|Œ]f )×A„rƒJÕwýíIlœ›VC,¤sO:yÓ’˜f§£“ÑèèÎéH{RîÂ’J1×2‚·ð»þ†à¾‚¤ Æ—”í2¹OŸ/ ±‰#Ñ{¥ÖÎÍI 5ÿ]¼\²HHŠAèr Ä&Ù¡ËŽèç×x”¹ânoä™c‡­èµ WÝÔ%)@"íN'-̧Í’¯I˪Oï>ìû© yz|mMý mm'ñ +æ\ªÙ„Çr…T Ò¡Ö#Òa±§ÓÜTÛÜdç¡?ÃÖ3ߺ_¤ô7 Õœ;ëüéäèZº`'J¢ì%ÝzuZ|_]³^޹8n¾üëtºÉìÌ·Ó}å¸\ËS%J,;P6$„6²n˜”¼WSÂHÂÆ8{i'ÐÅ4:qTÀCSUîj.ÛKÉ}+uQ»†LšÑ­ÔYÍF—¶‡ì09qõGô~ˆÄ+XÿÒ§}c÷dhRgD¤ïWö‰+³‰U& ¯ð²žæOÎÅÌã0¹w,Û“ûl!ßͨ›ú\<{™§-O; I„™“6;#1G»Mfø#l>û—èö?<¤j $p‡žWÇ·B}!½wå(±äŸ+½ jB!¾ô@˜ÝóG‰¯‚.^Ã%‘µxÚPŒ^Òko»Dw÷ ~²o¼Î«Ú'Ô!ž}.£ñÆÊsT2£IÊ6†ˆæÒuÞc“Ý4{,]Ú¶#¤?„x€ÇHß_Áý-(\u´â Ïê¡e‹JLnr·ªR0ÞÕ½c ¹Õ«2 ÑÑaÈ;VY1mÃ_}èÖ^­Ÿ”ãóŽîòë3‚jÀ%"Öañèô±#H_È YŒºÒmœGïÿvžü>äܳR¶j$v¥%džp½ãšºØ¿±@ÖuYú½ñf+Ý¢êÐKÄîóÁH_þL*œÿvìÍ¿ƒÄWˆšž£ùFÝö¯¦ aÓòw:×½›­rãJQ"!…Gä$'E˜áðÍmpA]qëñÓ~q<ÊÎ\ˆÅ4‡\:ªmÜ+îrrm2*f™¨c—Ú($‘o?&Éx¾ûH¸&ãˆæÐ^öá+e¼˜Â”^Wð«¡ê:]wWª“ˆú˜=îº*ÐpgBBvÕ¼wèÐýé`Áñ½³ùð¿Îöÿ ¾õ˜Œ RËžãØ×Ð|už:Wf¶¥ãµ$›¼§¥Ì¬ˆÒ–Ù+¡í±ãPæØ+Ÿ%Ä+ÌîûVxûç±ÃÏrw¸c„c»lî¢[BE6IIrÉ&<¤&.—@'fiïÌ7‡Ù[·9ÄäÈÕÇ+É ©ÿr0<¦&,õÕcNuG2yÄ©/DXˆÚÆÅ…øB×µ[KÍžÿžÍƒßmÜZ:Éu\†{e šÀÆë|¿/ÂeW3Y$Úî§[b Á· øÎ¿:!öŠ˜¡ªD7bp¶·žFîû=l>ú„û¾^¼Œ`•fТ r“â0˜Èû<{:Õ=Ï\‘ɬ~½XyoH›4mBpMùÜôtQ‰†¿ú[Xÿ:÷}+²y/¼ù éóËÕüHÛ!»Û±ÔU­ÙSfˆÌ0™eS˜º©çW±~žÃ#$ͻ㑩ˆ1q¡¬0ÝÇq%×*ñ·ŽëÑQ,æg3t|{ǹ§*ék>Xf†\40¦¾àšÝ¼l2ÿ<¶¬ èÅ›©ÈØT½î°è¸ b—yÉ ïóës–·•tóAØ}„í|3³þ(röY‘°1\câ1y”ó"ÏÎKÞ·vIç:ÌôßygOçgÒE¨žV8ye²ûö^­¿’÷˜%w÷”Ð"s…öæëpð7Ù|ààç¿ yóSèüuú.ÒŬ>²á‚£÷Ês¸V–¿ >Ýx^ÕMW§NMKsɲðøÑ¸bþâK•˜iÌá¢iS=¯\?UðÄr¼à0» „I)¸ 0Çu7SžCºª7Y{‡x²ÅÄŽàð‹W°ìÄÅ<ÿÇ¥¡aÌb¬0ªßªI&{X×Çq:é`¬Ï†®-1|¸é {Ç,‡ÛÔgãHœ>@°J­úrle1¢8yÁì'viKÛš~— JCdl\u<N’=ÒËë¾jºÁ†i€lʺdµêRî÷q¼ë\]=)_Ÿl£”jìô|(ï×…!P À¼ŒmA7îEº ÈÞ3l^øç™Ýû{‘Ý'DºÝáD_ºûÖùÔKùÜš{2òïwèJ¯ë6îåHRº‰”YÒÛ$²mõ¸H±6,Î4Éíà·šîÞ'è.üadþYº·þŸ±çÀS° 9ä¼¾iÖ„4*ªty›ß‘D爧7èi‰ÑWÌ%ûÂãÓ×,w7OM>Â0Ú“ŒGVoSNç•ËDíC³• [BáN ÃÌñ¥«Z}ž 9Z‘>r"`KcO™èGéâbàÖòo­:ÒÚF‚%¦cM¹­L°ZíU=.žZÞñ]].Û#eÏ_ÖU!rÅĈ¯ÀÁ¯àG¯€¦1¯(ãÏÚyŽWsOã9“›ðíŸæ'TÄÇñ¼2—nUtðqun2’µ””¤•®SUùNeØ›YU§ ¤ì¼%!‡„d7È&Aº‘§§<C؄ٹ'éÎ| ——· Ÿ¿šÎ]ˆÁsy·8¢­RŠ·ýÕ~¬šKãmåØ-”{^>¾éB®æzUs#× M @JóÓÈV¾±Äd Ò`ñ0»qõÄè¹Û?“n´AO Yªñ¥ºÜϰ@X^ÌÉ’Bv—áœZ]œðc-2ÝýØ 9õ§³~VyA«/,¸ÚMêŽæj©'|E¤g6ß!°²|O‹a:=·,mG%ÇiK ‘a ç°ÌÎÁ潄‹„³Ïv/£;!›÷]Ýy>9ïÁ¢‰O²tN;+üÛZV&úÙ‡eÊÙ,vÃø1¾ö-oýÌÓ?ã¯fÅeô]r·ž¬W}x5a›$ÅMHÞéæ›oäÁ º©ÈÙ'èÎ}‘·‘ƒó—!^ˆiüYÇÓèVÿüïüŠ÷µT±®Œ½.‘›¥DQM„œõÂÐÈ%º5>Á †Ç·Æ8Eë³ùGú?³q£Î:.„œö㪕ÿ‚R.£u“×r¡ÜÖ쫌‹±Ü¤ã“›xMζ¢B±XÆžv²Õ•ˆÕ[Ómžx,¡7Â¾Ó Ûε*˜F ­]ëV4¹bšr3é›tÈìB"ånÙ¸Ù{œ°ÿ ºûa÷"aãþÓí>GXTÈU‰~ˆ \¥ l¹Ô]©irÕ6Õ,O¯™½4Ç5½æ~`=o}ê›=¾ò©T ·å›ø­RŠ"ËÆÿ'v0åHSœžæ!ûÔ´äXp:ˆÆ¤¼g »Ð]øjt¶‹þ6Ì?ÅWÁKþi Op‘÷ac³YjåÂ3Ѫ)µ MUÙÄe#ï'{Lâ숯Aì ÷1‘tž;634jU¢®÷‚3‰ydºwìÃT¥¬Ÿ§kwVÕC‰ÚrÀ‡E×H¶†§d¬"ØB‡myþpÞÙñÆ '–¯KÞ w±Fذ‡1¼I˜†T¥òÔ\[º&M:tv4)dݸ€î<Žî=EØÙ½HØzè»-ìþê&ëÊBΤ/tuõÇÕü ÄêkëwzÚ[YC… „Ý'°/*}zªÙ»5ßÌo™º>æC÷õ¶G HêIÝînifÕ“´bSKikóþ%üÍ—akÆÆþ“øþ7ü*Ä—ñø|þzöyzu銤Rµ@:©ÑĤCHê8xT]´kXËR•aØË"S©Zr™ 7…œË×9^Ñ-7rͯ!–gŽÍ&¥j±¤áŽd\+ÊÒ´5ì«Uójöx Ÿ˜6¶•#d²zÖzül§GK×Ê­Ôûøõ©ñǪU»®W«~²ª=Qឤ°& Ú iå¼o}ÎImTÍK¥ó<ò²‚³¡R6XW.U6ÆÇ ÎJù.ö0L…:õ@ÆêŒ¹¤VÆâû®iJÅ-Â>Úí» èìaçÂÞ“ÈþÓ„Ý'Ð퇠;›æ’ßá™sò^ðI¦5ú®ÏÙc߃Ю‹ë&l9ó4½ôt½B—»~%’føÞßu‰d†‘÷¶sÌ¡hZ}ŠÞäàMä­ÏÃgasÙ³¹y«„Á·¸2›,yaá)Ý” {„nïÎ#³óèö£t»O¢{O"{Sc×ìœÈ Ã¤TÝаZL˜ÃüµïúÊÏ<ý7ôà¢:Á²¡ˆëMUØÇ©ëÅ2ø;¾L‚*_x)Mj>,èŠúO–ÀgHèÝÒm£³=è6ñöœÄ®àÌ?Âý¡OfÅ2²$θd[½b‚ @Àt H]œxÂ#bˆÙô¥«Ú–Òœ0aˆc0©J½:t7K\Ým¿8{¼nïØNhš:ñãYpFZ[Zn¸»9[V”kYì$·!|¢ Ãðœ¡2$ ¡éVòäBö\`Õø±§“%xnSœÞ GPÝCK—u·l=ˆî]&ì_&ì<…ì>ŠÌÎ ³í<’µ\>É>óNµ×lx7„ïØ¿ð§üêÿ&RLF< Ä5yÂ7†¬×Œ‹Vš7‘iž/bCég$qÁÅRÌ KÓ<”7U“Y†è,ŀРa,} %5ÂDÒŽ@¹„&1Ì«®êjïØê§×å7.hsŸ”ÖKhD™v\±59ǵN\ù¦º²Kõäq¥Óž€í"¼»ï@6,2מuƒßäñ‚"½r B^Ȧÿ_\,ÊŠòy²¢5ˆ®ˆlº¼»f{ÈöèÎEºýö/ÃöcèÆ¹KtûÏ—ÃñD»ºwáú6ØîvtCIè¾ß~á‡Ac"0ç&úù±«Ê› uU:Ìñ–ÑMJVKé,¹˜§ÙÅè“ñ˜:p¸†·Êp‚/)‰Ú‘«vÚɸHþ±hX2쉙Vf>Õò¼û­ËGÛU†ùÏPG8®š÷üÞ97bn8ƽåaÔnpƒK_O6ÃcZ“‘ÉZ%¶sï@ ±â“ïÙIk‹ÐíaçA÷Íû™í]"ì?…ì=ì>Fظ½çEÂ1ÂÁ–þ-•1ÑÈȺò¹«÷‰×5&64ÂFqœÍþ‡ÝóhAÈ‘–7\]sì¸Ö ®!L˜Hdм‰x]Òè“ļßÒÍ@|p¡rËûfd¡q«ou¥zˆ %½Es6ÇF.sÏÍm1™¨âÒÌåâã‚ÀSÀ‰ 5ý±§+?ƒb£ ‡jÁŠÓ!\9…ï¼:UPêŠZ»!ÝÍpÊÖR¥¬hälÊS›ä ýõy „˜’ýÜBÇ,ìaá|}ºÝ{Ý»„ì_F·/Òm>ðqŸí>'Ú±r\©|Á©+/$7ùûÂëTî‰+ m×]4íÄhXCgyNs®ýâŸôƒ/üïˆB‡Ñ¿k/íé,³_YßÈrøº2û˜<µ±J£Z Í‘5—âhÑiqZnžªi&„;)•yŸHÊAöÉ|!B]Z•Ë qz+µV…KÇLrhÊqŸÓ „;1†h„ݰòü¨üªÕ+UKÚ®ˆ[¶HPLGQÝÍ H8‹ÌÎv?8Ì"³óÝöÃ?»ýï:[I‚Ãò°6]T¼‹sȺº@(Óë#UíÖó×3®d4ònX¡°³ å¿}á# ã7Š(OOÂ7zïz]S[='ë:Úb–QàècsZM°ƒ:_,k‰zÔa¹¨ˆiÕ9‡ˆ «x™ü›\u‘äóÝU±yõ½dºïl«”ö1ãMÆú0‹Ó•¹uùÙа@LeOÙcöŽ×Ž®Û v÷!afÐÝbò²ûÄ8‹¬[£ vÍ‹ÚÔ˜¬0rÎN^ V&׊.Ÿ»«¶‚ò"ëë«Xà¦m³ºs‘t¯‡€Y7,)ì±¼^ô+Ï}5vô‘ÆcÕçõ¦ÊÉì¶UkJöµ•jÝV¬SÝ}åqq¤kåÝ}žì„Vdõ<ð°HS¯R[d’«¬@¬¬–|ï”ú4$AUyÌée|ì“Á³÷þ°õ4å`‡9äò¾TÊØ_M„†¥Ñ,Bòa÷ Å>sëaºý§ýgÐÝK„݇°î‚!§¡µk¥án'lóžÊAoýêw¹=ÿ?ÐûhJr£Ô­¬(¯Þ)c ã˜Ôôç1IÇqi¬JmêòîÆÉixËfµýª,Œ^úªªRíѾç¸">´äOçkäæ.ÝëÒuÝ!ºÏîAØA¶¢Ûy:Ùgî?IØyé.Hš¡œ­.-{Ìï­‘uCC7)9l|àÛ¸úüÿL çFx‰O“’îÌá_«ª‘Rr¦©R®žFÂäöïlx¯WÔã¢ÎÅÆÆ¬¡ùº”µ /f#RBVd á¡—!«ëôôìøEådçɛ߇ç4ûï‚nâá^B·KØ8—r‘÷/!{Böž¡Ûù*tvA7àY»-ÝåWà’ú^Gšf’«Rx¡²a<ÏÇiÉ^Ùîàthwí£á,¾y/º{‘°ÿ4º™Ùöãøöƒ—$l>n¥pY9_̲‚^¡˜i¼ÌÈ ×Sí^ÖNƒ††SÝ.Ü<™ZˆL‚Êû—ÒßüG߆r}„½ªüN%ìÓ½¤=뚬«݆FØ+ˆzòÿUÿ—*w× dIDATƒœî!+Ú]@º]Âì,Ì>€î>–bÏ~Ý~ßzô¯Èlû{U·ª±¦lÖ³8qº+vÚà&ƒšž\ Ã,²¬|®®÷äluð††cÛ=wb†aå\æ ¯üòŸõùçÿ×ë&ì²w}ÒÔû‘°×uƒGÖ‹eðŽƆ»øÔq„jz~å/tçéº3ÐÁg÷Ðí>‚ì¥\ä°ýì>þÝ2Ûþ!‘íêUû|ëÄd‘§Ö˜Õ<þ±$¾J]¯WÛìòŠ×®ùz‰¿›ÉvCÃjÂ^y5ûœùüE¿úÜ×bóW“u`ZÓÓ‹lqLd¹ ~'ÌY[eö’ŽÁTY#°mÎúÝ)Ìã>—²È©Õ¡+.©‹¹|ÏùÃ¥©ÊKü!‹îo£Ý¥2mœœÏUæòd”ªVÄkr½žSñÊÎV'½¢gÐY"dº{ »ç\äg »á»—þJÐï•°•ãWa«cº´~ç‡ý­_úÓtAÝS „Éèq}RGøûÅø$‘òr¼¶6G·Òžu›³~÷„=$1UŸQ¨‹êñ¾lŸ*ìfí‹ñŽ9z–ä~W‡£ˆkЦ-~×*ˆl#³sØìÒ]@·`¶ÿºÿ,ºõ(zö"¢;BØ©yL¤ÔébÃW¥bîR…íyÊR Cb×Á¯|—ÏëÄMPqÌ,å=fýS²¾“ QLв>M<Ë ¨¶ZÞ ;Is ª•ćœf&.¸ÄS‘*í©Ê}I¥á²¯8|t[.Ò¦yù˜½ßu0 q »H·Ýy¤;Ÿb÷.Î|˜nç"¾ó:Ûû¸t{Ï-*äE/ëSž‘¬aOI[ŠÒb|‹«ÿ›Ü_ÿUzé醮T¯Â(ÞŸuãæ¬}a!¤¢èm7ÖwMÖãœfÂÌþ탂ž’ôPéÅð†’¥ÉTCƤRÉ=¶‰âtÈì<Ò]€°nÝOWyûñÌ%B·Iºýçú@J/HRÿÅß`0Щ8:êõUª³ØÐа’°WîU3‰C¼òYë|3ñàK ÎÀBœØn®ê¦~?£œ¦|]ÜJG3FywŸ,Xs.èßt+ê‚()»\«=ãÚX„´­ ½çó[2;Ý9$œ%lžGw/¢g>BØ{’nç"lì}Å»³ÐͱËzhÎ<æ\²q!°ö28&ù‰\àØÌäv~54ÜE„9~ærT|éÿô«ÿ×·ÒϯD«fŸÕÑ•ïW®oö×3g‚VJ-“D#ìw¬¬Ó_FƒËÇÖ‚§†³nánˆæ=éA!w˜;:;‡t÷@w™í£û g>œf’w.£gavN&„œC18ge…«×˜â”ªT^¬¬s«¼º½"b©”ùjÒnçWCÃ]¨°×ߘëRWæ_üQ¿òËÿ&ÄGeyžøý<¶•¾vz»Q(£[c\DÛœõuó‰ç 0ATîŽFÍ{°îÌö ݽt»£ûÏ û—Ðݧ­³xwVDwUk‘…˜›%2^«nO£pW5Õihhx„m>dÉ®»9¥¬×\Æ8üöÃ_úÎDÚêko¼ïâ^=g­×å ^ÏYÇÁ䎷f½YŸÇä³1RÉzvíöavÝyŒpæÃÈÞ‘Ët[÷"³sâºÍ`ÿ#)ÿxÈ&Î+O_eêṆ´4q aãC§ùÈÃÏ1¼¯rEä'û¦°šÂžÜ?¬r3sxã‹?îoÿò¿Eìߤsö U OîÅBŒµubÅGo¡5ç;™³>ެÁnÁœufX=JŸ‡NKß,Æ-VyÈùx»L,)ƒI©gÕÁÐ¥Në IÕ&0º°’[“fé¬ÎØæ©Œm {Xw çÐÙtûatÿYfûOÁî“tÛ@¸ ÞmeG¾FT °×¯â…’"ùÄ#ö•_ñ·éOboÿ¢>ÐD`$èòoâÈ1}*Ó!æ÷'ÍYוƒI!€ªrÓç¬5Ew¦¦4û‹É` 2ÉÚÞ_š%bZå"¯Xx¤üãªÃZ½©ÝV»Qå½yÅðlB‚b‚ ÄÜx×y‡…m¼;Kè΢³3ØÖƒt{¢Û ö/Óm=ŒlÜ+è,oÚv£Â´t®œÎu«¡¡¡án&lŸ'C‡BØÌ“¹ÀáKþö/þ;}é9‚§ùlSCK˜½ Á#âZbü@˜¡2_—/xK ûzç¬ëÑ­›±O]—ÒÓžxZßx&ç¢X¢,Ä*æ¦%©È[#Žâ&Yí¦¯«)!—÷=»ˆ•qªà`:~ßbRÒŸ@‘° zíÎ#g`ó~ÂþÓÌvŸÄÏ|ˆ°ý ºy¿˜l¤EŽWiN+»lRAHÏ®d“’qŒ‘î w7aת*•O}É؈|æ?ôÃÏý  21­ˆ"–«©Š¨3)b¿Y¸sÖõèV1Eul ±›GØ.¤ØÄlê‘ÖMÎʱ±ÁT$)ì©CXý™eêüsøŠ4‰†RÖ±î#³ Èì,²ùÂþ“t{—ð½g˜í|²ñ XØÌåõ°¢cº~¯‹Õ©£:´V*>¿o“I¹½¡¡¡¡ö©Ho,CúÂ5¾ðã~õWÿ#ìêóXH%fU¥÷õ¤î"±Ð Q!Ü\¾¾¡sÖ‰¬S¼Ž;¼)ŒÈ°*ß#•«mRöt4Ë‹âi ©O"„°†{`¶ugÑýKÌvŸD÷/'BÞ}ôGb·÷A;ðì®ud9ÉCÈrJŽ«ùzEY{…öÚé‹SrùâPQX~yo{Û °o,óDú~ܯýÆ_cþú?¤3ï‰a†ø|!å+‘¸“ÔVRÖ;ÌGVÏ/÷—aJlêm®D"µÓe‹2IÒHÊó=PåÒ‚¦„²ô=ÆÈÆÔ-—²‘Ç£™Ô°e»Ì“h¤ê¯`¸¥òºx@uŸ]@»30;ƒn?Âlï2¾™nïºó„=I¹Èa=ƒ644444Â~'H )¯8þú/ûµßøAì՟î|tl^qLÊL´0˜FZoéL—šàÓwZ.WƒAžÞƒ›`:Ƃʂq‹f»W!¦IPefYFNMÙy¬Ê|xi *ýL ì`›Ðp&5vm?FؽHwöYdçƒèÎcÈìL&äÙt»a½SÅ*kÕrCCCCC#ìw"°'B0ï—Î_¿8ù§?7ÿüÿB|óÓØµÀ¢ÉË•l÷™ÈQ}TÌîqµê‹åîbZý&yºT9ÇÉD=k)†t`¢Ì\ò~± ÕW/¿¹BL i¶°îA!ËÎ#Èîㄳ¢Û¹„ì\D6.$B&äf½ÅD)&U„zÙ³8J·úq °ß1YÛ°ßl%kÕ˜Kßó+Ø+Ÿò£/þ(ñ_"^ý>}’e,âCY<õðŒß+‹áa$*oà&®õù†ÕôS îPðJÖN²Ou݆î,¡;‡vûøÖÄÝÇéÎ< ûÂÎ ³{/IØ}U+-D ñÊÂ|{õ÷Õeî:ÎqÅX]CCCCC#ì'¯ûAMúྕ¼«ë ,b‡/úüµŸÇ¾ü)⛟ÆÞÀŽ^K$¯Žˆb(:t4Sí…ÇAa'—5|Ú”îIÕ“ÚØ¼#Ï Û0Û¾ˆì?…î=‰ì>A7»ðqf{Ï¡³%ò\ú±‹ÚÏ6'ä½²ˆIÆ!ŠH#솆†††Û°³ƒUnCr)ºHˤ¼} !Ë4,µ –GˆØÑk¯þ6~åÿî|ŽþÚKÈ•ßÄüï¯àö6n‡à>µˆ¡²è&*¶`ótëQÂÖøîC„­‡‘ÍGí>îÝÎsª³døA›Ìóea6½î¦güÙÊb T“ì“ÎíVohhhh8ÿ?£s#ê.égÌIEND®B`‚accessodf-0.1.1~b/accessodf-addon/src/main/oxt/images/warning_20x20.gif000066400000000000000000000011471225501747700256160ustar00rootroot00000000000000GIF89aÆP I»¸Ê÷× Å²{w™ùîB‹}.åÜŒúúûæÖmPE@ôØË´Hîíòÿü†¸¨i…¡·žÿåèåÐãÐ çà¬õîl3(@ÿð&íÛ3°­ÂÚØâÿîòñõÿø`mcJèçíôóÊüüÿó:_Q2ïëŠšŠ ÿݶ¬LÔ¶ èßtÿëêéãÿÿÿåâÃŬðÖõôäõõøìÞBíæl^TJÿúsÿõMŶ õã_TDñîšÜÛäçå¹ùß æß”Œ‰¦ìêÙñÑìéàïÞ}xš3)Gõßëêð‹~7·¢åá¹ûû£Ó»æÚ}òåE!ù ,Ä€-‚ƒ„…††!"L1‡ŽA‘;Ž…%6™6=•‚.¢¢ ž-47(577?ŽK##:F¶,•OI Á*²…?Í8Í͇ 9+Ø&ØØ32ÊÝØã+É- Gîî$0ïNóîJùî²C>ø5‘—ïˆ) ø½pŸ„ø8A±b†3.@ÂC@ÆŠ)„|¬ÈƒÇ‘#Sž`°¡A EÈœIs& NU ;accessodf-0.1.1~b/accessodf-addon/src/main/oxt/licenses/000077500000000000000000000000001225501747700231645ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/licenses/Lesser General Public License version 3/000077500000000000000000000000001225501747700323125ustar00rootroot00000000000000lgpl.txt000066400000000000000000000167431225501747700337450ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/licenses/Lesser General Public License version 3 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. accessodf-0.1.1~b/accessodf-addon/src/main/oxt/registry/000077500000000000000000000000001225501747700232275ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/registry/data/000077500000000000000000000000001225501747700241405ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/registry/data/org/000077500000000000000000000000001225501747700247275ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/registry/data/org/openoffice/000077500000000000000000000000001225501747700270445ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/registry/data/org/openoffice/Office/000077500000000000000000000000001225501747700302375ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-addon/src/main/oxt/registry/data/org/openoffice/Office/OptionsDialog.xcu000066400000000000000000000020571225501747700335370ustar00rootroot00000000000000 be.docarch.accessodf.ooo.AccessODFAddOn AccessODF %origin%/../../../../../dialogs/OptionsPage.xdl be.docarch.accessodf.ooo.optionspage.DialogEventHandler accessodf-0.1.1~b/accessodf-api/000077500000000000000000000000001225501747700165165ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-api/pom.xml000066400000000000000000000010511225501747700200300ustar00rootroot00000000000000 4.0.0 be.docarch accessodf 0.1.0-SNAPSHOT accessodf-api 0.1.0-SNAPSHOT jar accessodf :: API accessodf-0.1.1~b/accessodf-api/src/000077500000000000000000000000001225501747700173055ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-api/src/main/000077500000000000000000000000001225501747700202315ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-api/src/main/java/000077500000000000000000000000001225501747700211525ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-api/src/main/java/be/000077500000000000000000000000001225501747700215405ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/000077500000000000000000000000001225501747700231435ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/000077500000000000000000000000001225501747700250755ustar00rootroot00000000000000accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/Check.java000066400000000000000000000034151225501747700267600ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.Locale; /** * * @author Bert Frees */ public abstract class Check { public static enum Status { ALERT, ERROR }; public abstract String getIdentifier(); public abstract Status getStatus(); public abstract String getName(Locale locale); public abstract String getDescription(Locale locale); public abstract String getSuggestion(Locale locale); @Override public String toString() { return getIdentifier(); } @Override public int hashCode() { return getIdentifier().hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Check)) { return false; } final Check that = (Check)obj; return (this.getIdentifier().equals(that.getIdentifier())); } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/CheckProvider.java000066400000000000000000000027061225501747700304750ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.Map; import java.util.TreeMap; import java.util.Collection; public class CheckProvider implements Provider { private Map checks = new TreeMap(); public CheckProvider(Provider checkers) { for (Checker checker : checkers.list()) { for (Check check : checker.list()) { checks.put(check.getIdentifier(), check); } } } public Collection list() { return checks.values(); } public Check get(String identifier) { return checks.get(identifier); } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/Checker.java000066400000000000000000000022321225501747700273030ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; /** * * @author Bert Frees */ public interface Checker extends Provider { /* * @return Returns a valid URI reference: * http://www.w3.org/TR/2003/WD-rdf-concepts-20030123/#dfn-URI-reference */ public String getIdentifier(); @Override public String toString(); } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/CheckerException.java000066400000000000000000000023551225501747700311700ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; /** * * @author Bert Frees */ public class CheckerException extends Exception { private String error = null; public CheckerException() { super(); this.error = "accessibility checker exception"; } public CheckerException(String error) { super(error); this.error = error; } public String getError() { return error; } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/Constants.java000066400000000000000000000106641225501747700277230ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.io.File; /** * * @author Bert Frees */ public abstract class Constants { public static final String LOGGER_NAME = "be.docarch.accessodf"; public static final String TMP_PREFIX = "accessodf."; private static final File TMP_DIRECTORY = new File(System.getProperty("java.io.tmpdir") + File.separator + "accessodf"); public final static String BERT = "http://www.docarch.be/bert"; private final static String DCT = "http://purl.org/dc/elements/1.1/"; private final static String FOAF = "http://xmlns.com/foaf/0.1/"; private final static String EARL = "http://www.w3.org/ns/earl#"; private final static String XSD = "http://www.w3.org/2001/XMLSchema#"; private final static String A11Y = "http://www.docarch.be/accessodf/"; public final static String A11Y_CHECKER = A11Y + "Checker"; public final static String A11Y_DOCUMENT = A11Y + "types#Document"; public final static String A11Y_PARAGRAPH = A11Y + "types#Paragraph"; public final static String A11Y_SPAN = A11Y + "types#Span"; public final static String A11Y_TABLE = A11Y + "types#Table"; public final static String A11Y_OBJECT = A11Y + "types#Object"; public final static String A11Y_CHECKS = A11Y + "checks#"; public final static String A11Y_START = A11Y + "start"; public final static String A11Y_END = A11Y + "end"; public final static String A11Y_IGNORE = A11Y + "ignore"; public final static String A11Y_COUNT = A11Y + "count"; public static final String XSD_INTEGER = XSD + "integer"; public static final String XSD_STRING = XSD + "string"; public static final String XSD_BOOLEAN = XSD + "boolean"; public static final String XSD_DATETIME = XSD + "dateTime"; public static final String DCT_DATE = DCT + "date"; public static final String DCT_TITLE = DCT + "title"; public static final String DCT_DESCRIPTION = DCT + "description"; public static final String DCT_HASVERSION = DCT + "hasVersion"; public static final String FOAF_GROUP = FOAF + "Group"; public static final String FOAF_MEMBER = FOAF + "member"; public static final String FOAF_PERSON = FOAF + "Person"; public static final String FOAF_NAME = FOAF + "name"; public static final String FOAF_HOMEPAGE = FOAF + "homepage"; public static final String EARL_ASSERTOR = EARL + "Assertor"; public static final String EARL_MAINASSERTOR = EARL + "mainAssertor"; public static final String EARL_SOFTWARE = EARL + "Software"; public static final String EARL_TESTSUBJECT = EARL + "TestSubject"; public static final String EARL_TESTRESULT = EARL + "TestResult"; public static final String EARL_TESTCASE = EARL + "TestCase"; public static final String EARL_ASSERTION = EARL + "Assertion"; public static final String EARL_OUTCOME = EARL + "outcome"; public static final String EARL_RESULT = EARL + "result"; public static final String EARL_TEST = EARL + "test"; public static final String EARL_SUBJECT = EARL + "subject"; public static final String EARL_ASSERTEDBY = EARL + "assertedBy"; public static final String EARL_FAILED = EARL + "failed"; public static final String EARL_PASSED = EARL + "passed"; public static File getTmpDirectory() { if (!TMP_DIRECTORY.isDirectory()) { TMP_DIRECTORY.mkdir(); } return TMP_DIRECTORY; } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/DummyCheck.java000066400000000000000000000030511225501747700277700ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.Locale; /** * * @author Bert Frees */ public class DummyCheck extends Check { @Override public String getIdentifier() { return "DUMMY_CHECK"; } @Override public Status getStatus() { throw new UnsupportedOperationException("Not supported."); } @Override public String getName(Locale locale) { throw new UnsupportedOperationException("Not supported."); } @Override public String getDescription(Locale locale) { throw new UnsupportedOperationException("Not supported."); } @Override public String getSuggestion(Locale locale) { throw new UnsupportedOperationException("Not supported."); } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/Element.java000066400000000000000000000021121225501747700273250ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; /** * * @author Bert Frees */ public abstract class Element { @Override public abstract int hashCode(); @Override public abstract boolean equals(Object obj); @Override public abstract String toString(); } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/FilterSorter.java000066400000000000000000000065431225501747700303740ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.ArrayList; import java.util.TreeMap; /** * * @author Bert Frees */ public class FilterSorter implements java.util.Comparator { public static enum Property { NATURAL, CATEGORY, CHECKID, NAME } public static final Property NATURAL = Property.NATURAL; public static final Property CHECKID = Property.CHECKID; public static final Property NAME = Property.NAME; private TreeMap upDown; private ArrayList priority; public FilterSorter() { upDown = new TreeMap(); upDown.put(NATURAL, true); upDown.put(NAME, true); upDown.put(CHECKID, true); priority = new ArrayList(); priority.add(NATURAL); priority.add(NAME); priority.add(CHECKID); } public void setOrder(Property property, boolean upDown) { if (this.upDown.containsKey(property)) { this.upDown.put(property, upDown); } } public void setOrderPriority(Property property, boolean highestLowest) { if (priority.contains(property)) { priority.remove(property); if (highestLowest) { priority.add(0, property); } else { priority.add(property); } } } public int compare(Issue entry1, Issue entry2) { if (entry1 == null && entry2 == null) { return 0; } else if (entry1 == null) { return -1; } else if (entry2 == null) { return 1; } Property property; int compare = 0; for (int i=0; i. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.Date; import java.util.Collection; import java.util.ArrayList; /** * * @author Bert Frees */ public class Issue { private Collection listeners; private final Element element; private final Check check; private final Checker checker; private final Date checkDate; private final int count; private boolean ignored = false; private boolean repaired = false; public Issue(Element element, Check check, Checker checker) { this(element, check, checker, 1); } public Issue(Element element, Check check, Checker checker, int count) { this(element, check, checker, new Date(), count); } public Issue(Element element, Check check, Checker checker, Date checkDate) { this(element, check, checker, checkDate, 1); } public Issue(Element element, Check check, Checker checker, Date checkDate, int count) { this.element = element; this.check = check; this.checker = checker; this.checkDate = checkDate; this.count = count; } public Element getElement() { return element; } public boolean ignored() { return ignored; } public boolean repaired() { return repaired; } public Date getCheckDate() { return checkDate; } public Check getCheck() { return check; } public Checker getChecker() { return checker; } public int getCount() { return count; } public void ignored(boolean ignored) { this.ignored = ignored; fireEvent(IssueEvent.Type.IGNORE); } public void repaired(boolean repaired) { this.repaired = repaired; fireEvent(IssueEvent.Type.REPAIR); } public void remove() { fireEvent(IssueEvent.Type.REMOVE); } public String getName() { if (element == null) { return ""; } else { return element.toString(); } } private void fireEvent(IssueEvent.Type type) { if (listeners == null) { return; } IssueEvent event = new IssueEvent(this, type); for (IssueListener listener : listeners) { listener.issueUpdated(event); } } public void addListener(IssueListener listener) { if (listeners == null) { listeners = new ArrayList(); } listeners.add(listener); } @Override public int hashCode() { final int PRIME = 31; int hash = 1; hash = hash * PRIME + getCheck().hashCode(); if (element != null) { hash = hash * PRIME + element.hashCode(); } return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Issue)){ return false; } final Issue that = (Issue)obj; if (!this.getCheck().equals(that.getCheck())) { return false; } if (element == null) { return (that.getElement() == null); } else { return element.equals(that.getElement()); } } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/IssueEvent.java000066400000000000000000000022041225501747700300300ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.EventObject; public class IssueEvent extends EventObject { public static enum Type { REPAIR, IGNORE, REMOVE } public final Type type; public IssueEvent(Issue issue, Type type) { super(issue); this.type = type; } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/IssueListener.java000066400000000000000000000017631225501747700305450ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.EventListener; public interface IssueListener extends EventListener { public void issueUpdated(IssueEvent event); } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/Provider.java000066400000000000000000000020101225501747700275230ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.util.Collection; /** * * @author Bert Frees */ public interface Provider { public Collection list(); public T get(String identifier); } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/RemoteRunnableChecker.java000066400000000000000000000021621225501747700321500ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.io.File; /** * * @author Bert Frees */ public interface RemoteRunnableChecker extends RunnableChecker { public void setOdtFile(File odtFile); /** * @return Returns the accessibility report */ public Report getAccessibilityReport(); } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/Repairer.java000066400000000000000000000022671225501747700275200ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; /** * * @author Bert Frees */ public interface Repairer { public static enum RepairMode { AUTO, SEMI_AUTOMATED}; public String getIdentifier(); public boolean supports(Issue issue); public abstract RepairMode getRepairMode(Issue issue); public boolean repair(Issue issue); } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/Report.java000066400000000000000000000024161225501747700272160ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; import java.io.File; /** * Class representing an accessibility report (EARL) * * @author Bert Frees */ public class Report { private File file = null; private String name = null; public Report(File file, String name) { this.file = file; this.name = name; } public File getFile() { return file; } public String getName() { return name; } } accessodf-0.1.1~b/accessodf-api/src/main/java/be/docarch/accessodf/RunnableChecker.java000066400000000000000000000020361225501747700307740ustar00rootroot00000000000000/** * AccessODF - Accessibility checker for OpenOffice.org and LibreOffice Writer. * * Copyright (c) 2011 by DocArch . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ package be.docarch.accessodf; /** * * @author Bert Frees */ public interface RunnableChecker extends Checker { /** * @return true if the check was successful */ public boolean run(); } accessodf-0.1.1~b/pom.xml000066400000000000000000000113651225501747700153400ustar00rootroot00000000000000 4.0.0 be.docarch accessodf 0.1.0-SNAPSHOT pom accessodf AccessODF is an extension for LibreOffice Writer that helps authors evaluate and repair accessibility issues in OpenDocument Text. https://sourceforge.net/p/accessodf/home/Home/ scm:hg:ssh://bertfrees@hg.code.sf.net/p/accessodf/code scm:hg:ssh://bertfrees@hg.code.sf.net/p/accessodf/code https://sourceforge.net/p/accessodf/code/ci/tip/tree/ GNU Lesser General Public License 3 http://www.gnu.org/licenses/lgpl.html Bert Frees bertfrees@gmail.com http://github.com/bertfrees Christophe Strobbe UTF-8 ${project.version} 3.3.0 accessodf-api accessodf-addon be.docarch accessodf-api ${accessodf.version} be.docarch accessodf-addon ${accessodf.version} org.libreoffice juh [${openoffice.version},) provided org.libreoffice jurt [${openoffice.version},) provided org.libreoffice ridl [${openoffice.version},) provided org.libreoffice unoil [${openoffice.version},) provided be.docarch l10n-maven-plugin 1.0-SNAPSHOT be.docarch oxt-maven-plugin 1.0-SNAPSHOT localized src/main/l10n be.docarch l10n-maven-plugin generate-resources resources addon src/main/oxt be.docarch oxt-maven-plugin true bertfrees-github-snapshots http://bertfrees.github.com/maven-snapshots/ bertfrees-github-snapshots http://bertfrees.github.com/maven-snapshots/ sonatype-nexus-staging oss.sonatype.org Staging Repository http://oss.sonatype.org/service/local/staging/deploy/maven2/ sonatype-nexus-snapshots oss.sonatype.org github Release Repository Snapshot Repository http://oss.sonatype.org/content/repositories/snapshots/