├── .gitignore ├── COPYING.txt ├── README.md ├── pom.xml └── src ├── main ├── assembly │ └── oxt.xml ├── java │ └── org │ │ └── writingtool │ │ ├── WritingTool.java │ │ ├── WtAnalyzedParagraphsCache.java │ │ ├── WtCacheIO.java │ │ ├── WtCheckRequestAnalysis.java │ │ ├── WtDictionary.java │ │ ├── WtDocumentCache.java │ │ ├── WtDocumentsHandler.java │ │ ├── WtErrorPositionComparator.java │ │ ├── WtIgnoredMatches.java │ │ ├── WtLanguageTool.java │ │ ├── WtLinguisticServices.java │ │ ├── WtMenus.java │ │ ├── WtProofreadingError.java │ │ ├── WtPropertyValue.java │ │ ├── WtQuotesDetection.java │ │ ├── WtResultCache.java │ │ ├── WtSingleCheck.java │ │ ├── WtSingleDocument.java │ │ ├── WtSingletonFactory.java │ │ ├── WtSortedTextRules.java │ │ ├── WtSpellChecker.java │ │ ├── WtTextLevelCheckQueue.java │ │ ├── aisupport │ │ ├── WtAiCheckQueue.java │ │ ├── WtAiConfusionPairs.java │ │ ├── WtAiDetectionRule.java │ │ ├── WtAiDetectionRule_de.java │ │ ├── WtAiErrorDetection.java │ │ ├── WtAiParagraphChanging.java │ │ ├── WtAiRemote.java │ │ ├── WtAiTextToSpeech.java │ │ ├── WtAiToken.java │ │ └── WtAiTranslateDocument.java │ │ ├── config │ │ ├── WtCategoryNode.java │ │ ├── WtCheckBoxTreeCellRenderer.java │ │ ├── WtConfigThread.java │ │ ├── WtConfiguration.java │ │ ├── WtRuleNode.java │ │ ├── WtSavablePanel.java │ │ └── WtTreeListener.java │ │ ├── dialogs │ │ ├── WtAboutDialog.java │ │ ├── WtAiDialog.java │ │ ├── WtAiResultDialog.java │ │ ├── WtAiTranslationDialog.java │ │ ├── WtCheckDialog.java │ │ ├── WtConfigurationDialog.java │ │ ├── WtMoreInfoDialog.java │ │ ├── WtOptionPane.java │ │ └── WtStatAnDialog.java │ │ ├── languagedetectors │ │ ├── WtKhmerDetector.java │ │ ├── WtTamilDetector.java │ │ └── WtUnicodeLanguageDetector.java │ │ ├── remote │ │ ├── CheckConfiguration.java │ │ ├── CheckConfigurationBuilder.java │ │ ├── RemoteConfigurationInfo.java │ │ ├── RemoteIgnoreRange.java │ │ ├── RemoteLanguageTool.java │ │ ├── RemoteResult.java │ │ ├── RemoteRuleMatch.java │ │ ├── RemoteServer.java │ │ └── WtRemoteLanguageTool.java │ │ ├── sidebar │ │ ├── WtSidebarContent.java │ │ ├── WtSidebarFactory.java │ │ └── WtSidebarPanel.java │ │ ├── stylestatistic │ │ ├── WtLevelRule.java │ │ ├── WtStatAnCache.java │ │ ├── WtStatAnConfiguration.java │ │ └── WtUsedWordRule.java │ │ └── tools │ │ ├── WtDocumentCursorTools.java │ │ ├── WtFlatParagraphTools.java │ │ ├── WtGeneralTools.java │ │ ├── WtMessageHandler.java │ │ ├── WtOfficeDrawTools.java │ │ ├── WtOfficeGraphicTools.java │ │ ├── WtOfficeSpreadsheetTools.java │ │ ├── WtOfficeTools.java │ │ ├── WtResourceBundle.java │ │ ├── WtVersionInfo.java │ │ └── WtViewCursorTools.java └── resources │ ├── Accelerators.xcu │ ├── Addons.xcu │ ├── COPYING.txt │ ├── CalcWindowState.xcu │ ├── Factories.xcu │ ├── ImpressWindowState.xcu │ ├── Linguistic.xcu │ ├── META-INF │ └── manifest.xml │ ├── README.txt │ ├── Sidebar.xcu │ ├── WriterWindowState.xcu │ ├── description.xml │ ├── description │ ├── desc_de.txt │ ├── desc_en.txt │ ├── desc_es.txt │ ├── desc_fr.txt │ ├── desc_hu.txt │ ├── desc_pt-BR.txt │ └── desc_pt.txt │ ├── help │ ├── en │ │ ├── help.tree │ │ └── org.openoffice.languagetool.oxt │ │ │ └── 0100000.xhp │ └── ru │ │ ├── help.tree │ │ └── org.openoffice.languagetool.oxt │ │ ├── 0100000.xhp │ │ └── 0100010.xhp │ ├── images │ ├── WTAIGeneralBig.png │ ├── WTAboutBig.png │ ├── WTAboutSmall.png │ ├── WTActivateRulesBig.png │ ├── WTActivateRulesSmall.png │ ├── WTAiBetterStyleBig.png │ ├── WTAiBetterStyleSmall.png │ ├── WTAiExpandBig.png │ ├── WTAiExpandSmall.png │ ├── WTAiGeneralSmall.png │ ├── WTAiReformulateBig.png │ ├── WTAiReformulateSmall.png │ ├── WTAiTextToSpeechBig.png │ ├── WTAiTextToSpeechSmall.png │ ├── WTAiTranslateTextBig.png │ ├── WTAiTranslateTextSmall.png │ ├── WTBackCheckOffBig.png │ ├── WTBackCheckOffSmall.png │ ├── WTBackCheckOnBig.png │ ├── WTBackCheckOnSmall.png │ ├── WTBig.png │ ├── WTCheckAgainBig.png │ ├── WTCheckAgainSmall.png │ ├── WTCheckBig.png │ ├── WTCheckSmall.png │ ├── WTNextBig.png │ ├── WTNextSmall.png │ ├── WTOptionsBig.png │ ├── WTOptionsSmall.png │ ├── WTProfilesBig.png │ ├── WTProfilesSmall.png │ ├── WTRefreshBig.png │ ├── WTRefreshSmall.png │ ├── WTResetPermanentBig.png │ ├── WTResetPermanentSmall.png │ ├── WTSmall.png │ ├── WTStatAnBig.png │ ├── WTStatAnSmall.png │ └── dialog.png │ ├── languagetool │ └── language-module.properties │ ├── org │ └── writingtool │ │ ├── de │ │ ├── MessagesBundle_de.properties │ │ └── URLsBundle_de.properties │ │ ├── en │ │ ├── MessagesBundle_en.properties │ │ └── URLsBundle_en.properties │ │ ├── hu │ │ ├── MessagesBundle_hu.properties │ │ └── URLsBundle_hu.properties │ │ └── resource │ │ └── de │ │ └── confusion_sets.txt │ ├── third-party-licenses │ ├── Apache-License.txt │ ├── BSD.txt │ ├── CC-Attr-SA-4.0.txt │ ├── CPL.txt │ ├── LGPL-2.1.txt │ ├── MIT-slf4j.txt │ ├── MIT.txt │ ├── Morfologik-license.txt │ ├── README.txt │ └── segment-license.txt │ └── version.txt └── test ├── java └── org │ └── writingtool │ ├── ErrorSortTest.java │ ├── KhmerDetectorTest.java │ ├── MainTest.java │ └── TamilDetectorTest.java └── resources └── manual-testing.odt /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *sw? 3 | *.iml 4 | *.bak 5 | .wti 6 | .class 7 | .classpath 8 | .idea 9 | .ignore 10 | .project 11 | .settings 12 | .metadata 13 | .vscode/ 14 | build 15 | target 16 | target-ide 17 | atomFeedChecksDB 18 | derby.log 19 | .surefire-* 20 | .flattened-pom.xml 21 | dependency-reduced-pom.xml 22 | .factorypath 23 | pom.xml.versionsBackup 24 | pom.xml.asc 25 | .DS_Store 26 | /data/ 27 | .attach_pid* 28 | bin/ 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WritingTool (a LibreOffice Extension based on LanguageTool) 2 | 3 | ***NOTE: WritingTool requires Java 17 or higher now*** 4 | 5 | WritingTool is a LibreOffice extension for LibreOffice that adds a writing assistant to text editing. It is designed for creating and editing extensive texts (e.g. for literature, science or business). 6 | 7 | In addition to a spelling, grammar and style checker based on LanguageTool, it provides statistical methods for optimizing texts as well as AI support (in development). 8 | 9 | Compared to using the internal LanguageTool in LibreOffice, the extension offers the following advantages: 10 | 11 | * The application runs on the local computer. Therefore, no remote server is required (the use of a remote server including the LanguageTool premium service is still supported). 12 | * All rules that work at the full-text level are also supported across paragraph boundaries (e.g. opening and closing quotation marks are recognized even if they are more than one paragraph apart). 13 | * In addition to that of LibreOffice, the LanguageTool spell checker is used. 14 | * A custom caching mechanism is used, which significantly speeds up repeated work on long texts. It avoids rechecking unchanged sections, saving time. When a text that has already been checked is loaded, all previously found errors are displayed almost immediately. 15 | * A custom WritingTool check dialog is used, designed to be highly performant. It has been optimized for WritingTool's internal caching system to ensure fast and efficient operation. 16 | * Grammar checking of Impress and Calc documents is supported (Manual checking only through the LT check dialog. Automatic checking is not supported by LibreOffice.) 17 | * Using a configuration dialog, users can change the following settings, for example: 18 | * Easily activate/deactivate optional rules 19 | * Easily deactivate/reactivate standard rules 20 | * Define custom colors and styles for rule groups or individual rules 21 | * Change parameters for some special rules 22 | * Define profiles for checking different document types 23 | * The extension offers the possibility of statistical analyses, such as frequently used words, filler words, etc. (So far only for individual languages). 24 | * Support for (local) AI: 25 | * Supplement to the grammar check 26 | * Generation, improvement, rewriting, expansion and translation of paragraphs 27 | * Creating illustrations for a paragraph 28 | * supporting OpenAI like API (Local applications such as https://localai.io are particularly supported) 29 | 30 | The nightly snapshots contain the current LanguageTool snapshots, see here: https://writingtool.org/writingtool/snapshots/ 31 | The releases contain the current LanguageTool releases, see here: https://writingtool.org/writingtool/releases/ 32 | 33 | You can find more information (requirements, licence, downloads, etc.) here: https://writingtool.org 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/assembly/oxt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | bin 4 | 5 | zip 6 | 7 | false 8 | 9 | 10 | src/main/resources 11 | 12 | 13 | COPYING.txt 14 | README.txt 15 | help/** 16 | images/** 17 | META-INF/** 18 | description.xml 19 | description/** 20 | Addons.xcu 21 | Accelerators.xcu 22 | Factories.xcu 23 | Sidebar.xcu 24 | Linguistic.xcu 25 | WriterWindowState.xcu 26 | ImpressWindowState.xcu 27 | CalcWindowState.xcu 28 | 29 | 30 | 31 | src/main/resources/third-party-licenses 32 | third-party-licenses 33 | 34 | 35 | 36 | 37 | src/main/resources/version.txt 38 | 39 | true 40 | 41 | 42 | 43 | 44 | 45 | metaInf-services 46 | 47 | 48 | file-aggregator 49 | 50 | META-INF/org/languagetool/language-module.properties 51 | META-INF/org/languagetool/language-module.properties 52 | 53 | 54 | 55 | 56 | 57 | 58 | false 59 | runtime 60 | 61 | org.languagetool:language-* 62 | 63 | 64 | 65 | 66 | true 67 | 68 | 69 | 70 | 74 | **/*.pom 75 | **/hunspell/*sh 76 | **/hunspell/*README* 77 | 78 | 79 | 80 | runtime 81 | 82 | org.languagetool:language-* 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/WtAnalyzedParagraphsCache.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | 20 | package org.writingtool; 21 | 22 | import java.io.File; 23 | import java.io.FileOutputStream; 24 | import java.io.IOException; 25 | import java.io.OutputStreamWriter; 26 | import java.nio.charset.StandardCharsets; 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | import java.util.zip.GZIPOutputStream; 30 | 31 | import org.json.JSONObject; 32 | import org.languagetool.AnalyzedSentence; 33 | import org.languagetool.AnalyzedToken; 34 | import org.languagetool.AnalyzedTokenReadings; 35 | import org.languagetool.JLanguageTool; 36 | import org.languagetool.Language; 37 | import org.languagetool.Languages; 38 | import org.writingtool.WtDocumentCache.TextParagraph; 39 | import org.writingtool.tools.WtMessageHandler; 40 | import org.writingtool.tools.WtOfficeTools; 41 | 42 | import com.sun.star.lang.Locale; 43 | 44 | /** 45 | * Class to cache analyzed Sentences 46 | * For test reasons only / not shown to the user 47 | * @since 1.0 48 | * @author Fred Kruse 49 | */ 50 | public class WtAnalyzedParagraphsCache { 51 | private JSONObject doc = new JSONObject(); 52 | private String locale; 53 | 54 | WtAnalyzedParagraphsCache(WtDocumentsHandler mDocHandler) { 55 | WtSingleDocument document = mDocHandler.getCurrentDocument(); 56 | if (document == null) { 57 | return; 58 | } 59 | WtDocumentCache docCache = document.getDocumentCache(); 60 | if (docCache == null) { 61 | return; 62 | } 63 | Locale tmpLocale = docCache.getFlatParagraphLocale(0); 64 | if (tmpLocale == null || !WtDocumentsHandler.hasLocale(tmpLocale)) { 65 | locale = null; 66 | return; 67 | } 68 | locale = WtOfficeTools.localeToString(tmpLocale); 69 | Language language = Languages.getLanguageForShortCode(WtOfficeTools.localeToString(tmpLocale)); 70 | JLanguageTool lt = new JLanguageTool(language); 71 | try { 72 | TextParagraph tPara = new TextParagraph(WtDocumentCache.CURSOR_TYPE_TEXT, 0); 73 | List jParagraphs = new ArrayList(); 74 | for (int n = 0; n < docCache.textSize(tPara); n++) { 75 | tPara = new TextParagraph(WtDocumentCache.CURSOR_TYPE_TEXT, n); 76 | String para = docCache.getTextParagraph(tPara); 77 | List sentences = lt.sentenceTokenize(para); 78 | List jSentences = new ArrayList(); 79 | JSONObject jParagraph = new JSONObject(); 80 | for (String sentence : sentences) { 81 | JAnalyzedSentence jSentence = new JAnalyzedSentence(lt.getAnalyzedSentence(sentence)); 82 | jSentences.add(jSentence.getJSON()); 83 | } 84 | jParagraph.put("pa", jSentences); 85 | jParagraphs.add(jParagraph.toString()); 86 | } 87 | doc.put("locale", locale); 88 | doc.put("paragraphs", jParagraphs); 89 | writeIntoFile(); 90 | } catch (IOException e) { 91 | WtMessageHandler.printException(e); 92 | return; 93 | } 94 | } 95 | 96 | String getLocaleAsString() { 97 | return locale; 98 | } 99 | 100 | void writeIntoFile() { 101 | try { 102 | File tmpDir = new File(WtOfficeTools.getWtConfigDir(), "tmp"); 103 | if (tmpDir != null && !tmpDir.exists()) { 104 | tmpDir.mkdirs(); 105 | } 106 | File tmpCacheFile = new File(tmpDir, "tmp_AnalyzedParagraphsCache"); 107 | if (tmpCacheFile.exists()) { 108 | tmpCacheFile.delete(); 109 | } 110 | GZIPOutputStream fileOut = new GZIPOutputStream(new FileOutputStream(tmpCacheFile.getAbsolutePath())); 111 | OutputStreamWriter out = new OutputStreamWriter(fileOut, StandardCharsets.UTF_8); 112 | out.write(doc.toString()); 113 | out.close(); 114 | fileOut.close(); 115 | File cacheFile = new File(tmpDir, "AnalyzedParagraphsCache"); 116 | if (cacheFile.exists()) { 117 | cacheFile.delete(); 118 | } 119 | tmpCacheFile.renameTo(cacheFile); 120 | } catch (Throwable t) { 121 | WtMessageHandler.printException(t); // all Exceptions thrown by UnoRuntime.queryInterface are caught 122 | } 123 | } 124 | 125 | private class JAnalyzedSentence { 126 | private List tokens = new ArrayList(); 127 | 128 | JAnalyzedSentence(AnalyzedSentence sentences) { 129 | for (AnalyzedTokenReadings token : sentences.getTokensWithoutWhitespace()) { 130 | tokens.add(new JAnalyzedTokenReadings(token)); 131 | } 132 | } 133 | 134 | String getJSON() { 135 | JSONObject obj = new JSONObject(); 136 | List jSentences = new ArrayList(); 137 | for (JAnalyzedTokenReadings token : tokens) { 138 | jSentences.add(token.getJSON()); 139 | } 140 | obj.put("aS", jSentences); 141 | return obj.toString(); 142 | } 143 | 144 | } 145 | 146 | private class JAnalyzedTokenReadings { 147 | private List tokenReadings = new ArrayList(); 148 | private String token; 149 | private int startPos; 150 | 151 | JAnalyzedTokenReadings(AnalyzedTokenReadings anTokReadings) { 152 | token = anTokReadings.getToken(); 153 | startPos = anTokReadings.getStartPos(); 154 | for (AnalyzedToken aToken : anTokReadings.getReadings()) { 155 | tokenReadings.add(new JAnalyzedToken(aToken)); 156 | } 157 | } 158 | 159 | String getJSON() { 160 | JSONObject obj = new JSONObject(); 161 | obj.put("to", token); 162 | obj.put("sP", startPos); 163 | List jReadings = new ArrayList(); 164 | for (JAnalyzedToken reading : tokenReadings) { 165 | jReadings.add(reading.getJSON()); 166 | } 167 | obj.put("tR", jReadings); 168 | return obj.toString(); 169 | } 170 | 171 | } 172 | 173 | private class JAnalyzedToken { 174 | private String posTag; 175 | private String lemma; 176 | private boolean hasNoTag = false; 177 | 178 | JAnalyzedToken(AnalyzedToken token) { 179 | posTag = token.getPOSTag() == null ? "" : token.getPOSTag(); 180 | lemma = token.getLemma() == null ? "" : token.getLemma(); 181 | hasNoTag = token.hasNoTag(); 182 | } 183 | 184 | String getJSON() { 185 | JSONObject obj = new JSONObject(); 186 | obj.put("pT", posTag); 187 | obj.put("le", lemma); 188 | obj.put("hT", hasNoTag); 189 | return obj.toString(); 190 | } 191 | 192 | } 193 | 194 | } 195 | 196 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/WtErrorPositionComparator.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import java.util.Comparator; 22 | 23 | /** 24 | * A simple comparator for sorting errors by their position. 25 | */ 26 | public class WtErrorPositionComparator implements Comparator { 27 | 28 | @Override 29 | public int compare(WtProofreadingError match1, WtProofreadingError match2) { 30 | int error1pos = match1.nErrorStart; 31 | int error2pos = match2.nErrorStart; 32 | int error1len = match1.nErrorLength; 33 | int error2len = match2.nErrorLength; 34 | if (error1pos == error2pos) { 35 | if (error2len < error1len) { 36 | return 1; 37 | } else if (error1len < error1len) { 38 | return -1; 39 | } 40 | } 41 | if (error2pos > error1pos && error2pos < error1pos + error1len) { 42 | return 1; 43 | } 44 | if (error1pos > error2pos && error1pos < error2pos + error2len) { 45 | return -1; 46 | } 47 | if (error1pos > error2pos) { 48 | return 1; 49 | } else if (error1pos < error2pos) { 50 | return -1; 51 | } else { 52 | if (error1len > error2len) { 53 | return 1; 54 | } 55 | if (error1len < error2len) { 56 | return -1; 57 | } 58 | return Integer.compare(match2.aSuggestions.length, match1.aSuggestions.length); 59 | /* 60 | if (match1.aSuggestions.length == 0 && match2.aSuggestions.length > 0) { 61 | return 1; 62 | } 63 | if (match2.aSuggestions.length == 0 && match1.aSuggestions.length > 0) { 64 | return -1; 65 | } 66 | if (match1.aSuggestions.length != 0 && match2.aSuggestions.length != 0 67 | && match1.aSuggestions.length != match2.aSuggestions.length) { 68 | return Integer.compare(match1.aSuggestions.length, match2.aSuggestions.length); 69 | } 70 | */ 71 | } 72 | // return match1.aRuleIdentifier.compareTo(match2.aRuleIdentifier); 73 | // return 0; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/WtProofreadingError.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import java.io.Serializable; 22 | 23 | import com.sun.star.beans.PropertyValue; 24 | import com.sun.star.linguistic2.SingleProofreadingError; 25 | 26 | /** 27 | * Class of serializable proofreading errors 28 | * @author Fred Kruse 29 | * @since 1.0 30 | */ 31 | public class WtProofreadingError implements Serializable { 32 | 33 | private static final long serialVersionUID = 1L; 34 | public int nErrorStart; 35 | public int nErrorLength; 36 | public int nErrorType; 37 | public boolean bDefaultRule; 38 | public boolean bStyleRule; 39 | public boolean bPunctuationRule; 40 | public String aFullComment; 41 | public String aRuleIdentifier; 42 | public String aShortComment; 43 | public String[] aSuggestions; 44 | public WtPropertyValue[] aProperties = null; 45 | 46 | public WtProofreadingError() { 47 | } 48 | 49 | public WtProofreadingError(WtProofreadingError error) { 50 | nErrorStart = error.nErrorStart; 51 | nErrorLength = error.nErrorLength; 52 | nErrorType = error.nErrorType; 53 | aFullComment = error.aFullComment; 54 | aRuleIdentifier = error.aRuleIdentifier; 55 | aShortComment = error.aShortComment; 56 | aSuggestions = error.aSuggestions; 57 | bDefaultRule = error.bDefaultRule; 58 | bStyleRule = error.bStyleRule; 59 | bPunctuationRule = error.bPunctuationRule; 60 | if (error.aProperties != null) { 61 | aProperties = new WtPropertyValue[error.aProperties.length]; 62 | for (int i = 0; i < error.aProperties.length; i++) { 63 | aProperties[i] = new WtPropertyValue(error.aProperties[i]); 64 | } 65 | } 66 | } 67 | 68 | public WtProofreadingError(SingleProofreadingError error) { 69 | nErrorStart = error.nErrorStart; 70 | nErrorLength = error.nErrorLength; 71 | nErrorType = error.nErrorType; 72 | aFullComment = error.aFullComment; 73 | aRuleIdentifier = error.aRuleIdentifier; 74 | aShortComment = error.aShortComment; 75 | aSuggestions = error.aSuggestions; 76 | if (error.aProperties != null) { 77 | aProperties = new WtPropertyValue[error.aProperties.length]; 78 | for (int i = 0; i < error.aProperties.length; i++) { 79 | aProperties[i] = new WtPropertyValue(error.aProperties[i]); 80 | } 81 | } 82 | } 83 | 84 | public SingleProofreadingError toSingleProofreadingError () { 85 | SingleProofreadingError error = new SingleProofreadingError(); 86 | error.nErrorStart = nErrorStart; 87 | error.nErrorLength = nErrorLength; 88 | error.nErrorType = nErrorType; 89 | error.aFullComment = aFullComment; 90 | error.aRuleIdentifier = aRuleIdentifier; 91 | error.aShortComment = aShortComment; 92 | error.aSuggestions = aSuggestions; 93 | if (aProperties != null) { 94 | error.aProperties = new PropertyValue[aProperties.length]; 95 | for (int i = 0; i < aProperties.length; i++) { 96 | error.aProperties[i] = aProperties[i].toPropertyValue(); 97 | } 98 | } else { 99 | error.aProperties = null; 100 | } 101 | return error; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/WtPropertyValue.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import java.io.Serializable; 22 | 23 | import com.sun.star.beans.PropertyState; 24 | import com.sun.star.beans.PropertyValue; 25 | 26 | /** 27 | * Class of serializable property values 28 | * @author Fred Kruse 29 | * @since 1.0 30 | */ 31 | public class WtPropertyValue implements Serializable { 32 | 33 | private static final long serialVersionUID = 1L; 34 | public String name; 35 | public Object value; 36 | 37 | public WtPropertyValue(WtPropertyValue properties) { 38 | name = properties.name; 39 | value = properties.value; 40 | } 41 | 42 | public WtPropertyValue(String name, Object value) { 43 | this.name = name; 44 | this.value = value; 45 | } 46 | 47 | public WtPropertyValue(PropertyValue properties) { 48 | name = properties.Name; 49 | value = properties.Value; 50 | } 51 | 52 | PropertyValue toPropertyValue() { 53 | PropertyValue properties = new PropertyValue(); 54 | properties.Name = name; 55 | properties.Value = value; 56 | properties.Handle = -1; 57 | properties.State = PropertyState.DIRECT_VALUE; 58 | return properties; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/WtQuotesDetection.java: -------------------------------------------------------------------------------- 1 | package org.writingtool; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.regex.Pattern; 7 | 8 | import org.writingtool.tools.WtMessageHandler; 9 | 10 | public class WtQuotesDetection { 11 | 12 | private static final List startSymbols = Arrays.asList("“", "„", "»", "«", "\""); 13 | private static final List endSymbols = Arrays.asList("”", "“", "«", "»", "\""); 14 | private static final Pattern PUNCTUATION = Pattern.compile("[\\p{Punct}…–—&&[^\"'_]]"); 15 | private static final Pattern PUNCT_MARKS = Pattern.compile("[\\?\\.!,]"); 16 | 17 | private List openingQuotes; 18 | private List closingQuotes; 19 | 20 | private String openQuote = new String(); 21 | 22 | /** 23 | * Defines exceptions from quotes 24 | */ 25 | private boolean isNotQuote (String txt, int i, int j) throws Throwable { 26 | if ((i == 0 || Character.isWhitespace(txt.charAt(i - 1))) 27 | && (i >= txt.length() - 1 || Character.isWhitespace(txt.charAt(i + 1)))) { 28 | return true; 29 | } 30 | if (endSymbols.get(j).equals(startSymbols.get(j))) { 31 | if (i > 0 && i < txt.length() - 1 32 | && !Character.isWhitespace(txt.charAt(i - 1)) 33 | && !Character.isWhitespace(txt.charAt(i + 1))) { 34 | String pChar = txt.substring(i - 1, i); 35 | String nChar = txt.substring(i + 1, i + 2); 36 | if(PUNCTUATION.matcher(pChar).matches() 37 | && !".".equals(nChar) 38 | && PUNCTUATION.matcher(nChar).matches()) { 39 | return true; 40 | } 41 | } 42 | } 43 | return false; 44 | } 45 | 46 | /** 47 | * defines an opening quote 48 | */ 49 | private boolean isOpeningQuote(String txt, int i) throws Throwable { 50 | String tChar = txt.substring(i, i + 1); 51 | for (int j = 0; j < startSymbols.size(); j++) { 52 | if (startSymbols.get(j).equals(tChar)) { 53 | if (isNotQuote (txt, i, j)) { 54 | return false; 55 | } 56 | if (endSymbols.contains(startSymbols.get(j))) { 57 | return (i == 0 58 | || Character.isWhitespace(txt.charAt(i - 1)) 59 | || (i < txt.length() - 1 && !Character.isWhitespace(txt.charAt(i + 1)) 60 | && ((!PUNCT_MARKS.matcher(txt.substring(i + 1, i + 2)).matches() 61 | && PUNCTUATION.matcher(txt.substring(i - 1, i)).matches()) 62 | || (txt.charAt(i + 1) == '-')))); 63 | } 64 | return true; 65 | } 66 | } 67 | return false; 68 | } 69 | 70 | /** 71 | * defines an closing quote 72 | */ 73 | private boolean isClosingQuote(String txt, int i) throws Throwable { 74 | String tChar = txt.substring(i, i + 1); 75 | for (int j = 0; j < endSymbols.size(); j++) { 76 | if (endSymbols.get(j).equals(tChar)) { 77 | if (isNotQuote (txt, i, j) && !openQuote.equals(startSymbols.get(j))) { 78 | return false; 79 | } 80 | return true; 81 | } 82 | } 83 | return false; 84 | } 85 | 86 | /** 87 | * analyse one paragraph 88 | */ 89 | private boolean analyzeOneParagraph(String txt, boolean isQuoteBefore) throws Throwable { 90 | openingQuotes = new ArrayList<>(); 91 | closingQuotes = new ArrayList<>(); 92 | if (isQuoteBefore) { 93 | openingQuotes.add(-1); 94 | } 95 | for (int i = 0; i < txt.length(); i++) { 96 | if (isOpeningQuote(txt, i)) { 97 | if (i == 0 && openingQuotes.size() > 0) { 98 | openingQuotes.set(0, i); 99 | } else { 100 | openingQuotes.add(i); 101 | } 102 | openQuote = new String(txt.substring(i, i + 1)); 103 | isQuoteBefore = true; 104 | } else if (isClosingQuote(txt, i)) { 105 | closingQuotes.add(i); 106 | openQuote = new String(); 107 | isQuoteBefore = false; 108 | } 109 | } 110 | return isQuoteBefore; 111 | } 112 | 113 | /** 114 | * analyse all paragraphs 115 | * NOTE: only text paragraphs will be analyzed (no footnotes, tables, etc.) 116 | * NOTE: Quotes lists have to initialized 117 | */ 118 | public void analyzeTextParagraphs(List paragraphs, List> oQuotes, List> cQuotes) { 119 | try { 120 | oQuotes.clear(); 121 | cQuotes.clear(); 122 | boolean isQuoteBefore = false; 123 | for (int i = 0; i < paragraphs.size(); i++) { 124 | isQuoteBefore = analyzeOneParagraph(paragraphs.get(i), isQuoteBefore); 125 | oQuotes.add(openingQuotes); 126 | cQuotes.add(closingQuotes); 127 | } 128 | } catch (Throwable t) { 129 | WtMessageHandler.showError(t); 130 | } 131 | } 132 | 133 | /** 134 | * update a following paragraph 135 | * returns true, if the following paragraph has to be changed 136 | */ 137 | private boolean updateFollowingParagraph(List> oQuotes, List> cQuotes, int nPara, boolean isQuoteBefore) { 138 | if (isQuoteBefore) { 139 | if (oQuotes.get(nPara) != null && oQuotes.get(nPara).size() > 0 && oQuotes.get(nPara).get(0) <= 0) { 140 | return false; 141 | } 142 | if (oQuotes.get(nPara) == null) { 143 | oQuotes.set(nPara, new ArrayList()); 144 | } 145 | oQuotes.get(nPara).add(0, -1); 146 | if (cQuotes.get(nPara) != null && cQuotes.get(nPara).size() > 0) { 147 | return false; 148 | } else { 149 | return true; 150 | } 151 | } else { 152 | if (oQuotes.get(nPara) == null || oQuotes.get(nPara).size() == 0 || oQuotes.get(nPara).get(0) >= 0) { 153 | return false; 154 | } 155 | oQuotes.get(nPara).remove(0); 156 | if (cQuotes.get(nPara) == null || cQuotes.get(nPara).size() == 0) { 157 | return true; 158 | } else { 159 | return false; 160 | } 161 | } 162 | 163 | } 164 | 165 | private void updateTextParagraphs(List> oQuotes, List> cQuotes, int nPara, boolean isQuoteBefore) { 166 | boolean hasChanged = true; 167 | for (int i = nPara + 1; hasChanged && i < oQuotes.size(); i++) { 168 | hasChanged = updateFollowingParagraph(oQuotes, cQuotes, i, isQuoteBefore); 169 | } 170 | } 171 | 172 | public void updateTextParagraph(String txt, int nPara, List> oQuotes, List> cQuotes) throws Throwable { 173 | boolean isQuoteBefore = oQuotes.get(nPara) != null && oQuotes.get(nPara).size() > 0 && oQuotes.get(nPara).get(0) < 0; 174 | isQuoteBefore = analyzeOneParagraph(txt, isQuoteBefore); 175 | oQuotes.set(nPara, openingQuotes); 176 | cQuotes.set(nPara, closingQuotes); 177 | updateTextParagraphs(oQuotes, cQuotes, nPara, isQuoteBefore); 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/WtSingletonFactory.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import org.writingtool.sidebar.WtSidebarFactory; 22 | 23 | import com.sun.star.lang.XServiceInfo; 24 | import com.sun.star.lang.XSingleComponentFactory; 25 | import com.sun.star.lang.XSingleServiceFactory; 26 | import com.sun.star.uno.Exception; 27 | import com.sun.star.uno.XComponentContext; 28 | 29 | /** 30 | * This class is a factory that creates only a single instance, 31 | * or a singleton, of the Main class. Used for performance 32 | * reasons and to allow various parts of code to interact. 33 | * 34 | * @author Fred Kruse 35 | */ 36 | public class WtSingletonFactory implements XSingleComponentFactory, XSingleServiceFactory, XServiceInfo { 37 | 38 | enum serviceType {Proofreading, Spellchecking, Sidebar }; 39 | 40 | // private transient org.languagetool.openoffice.Main instance; 41 | private static org.writingtool.WritingTool instance = null; 42 | // private static org.languagetool.openoffice.LanguageToolSpellChecker spellInstance = null; 43 | private serviceType service; 44 | 45 | WtSingletonFactory(serviceType service) { 46 | this.service = service; 47 | } 48 | 49 | @Override 50 | public final Object createInstanceWithArgumentsAndContext(Object[] arguments, 51 | XComponentContext xContext) { 52 | return createInstanceWithContext(xContext); 53 | } 54 | 55 | @Override 56 | public final Object createInstanceWithContext(XComponentContext xContext) { 57 | if (service == serviceType.Spellchecking) { 58 | return new org.writingtool.WtSpellChecker(xContext); 59 | // if (spellInstance == null) { 60 | // spellInstance = new org.languagetool.openoffice.LanguageToolSpellChecker(xContext); 61 | // } 62 | // return spellInstance; 63 | } else if (service == serviceType.Sidebar) { 64 | return new WtSidebarFactory(xContext); 65 | } else { 66 | if (instance == null) { 67 | instance = new org.writingtool.WritingTool(xContext); 68 | } else { 69 | instance.changeContext(xContext); 70 | } 71 | return instance; 72 | } 73 | } 74 | 75 | @Override 76 | public final String getImplementationName() { 77 | if (service == serviceType.Spellchecking) { 78 | return WtSpellChecker.class.getName(); 79 | } else if (service == serviceType.Sidebar) { 80 | return WtSidebarFactory.class.getName(); 81 | } else { 82 | return WritingTool.class.getName(); 83 | } 84 | } 85 | 86 | @Override 87 | public final boolean supportsService(String serviceName) { 88 | for (String s : getSupportedServiceNames()) { 89 | if (s.equals(serviceName)) { 90 | return true; 91 | } 92 | } 93 | return false; 94 | } 95 | 96 | @Override 97 | public final String[] getSupportedServiceNames() { 98 | if (service == serviceType.Spellchecking) { 99 | return WtSpellChecker.getServiceNames(); 100 | } else if (service == serviceType.Sidebar) { 101 | return WtSidebarFactory.getServiceNames(); 102 | } else { 103 | return WritingTool.getServiceNames(); 104 | } 105 | } 106 | 107 | /* only sidebar */ 108 | @Override 109 | public final Object createInstance() throws Exception { 110 | return new WtSidebarFactory(WtDocumentsHandler.getComponentContext()); 111 | } 112 | 113 | @Override 114 | public final Object createInstanceWithArguments(Object[] arg0) throws Exception { 115 | return createInstance(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/WtSortedTextRules.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.Set; 24 | 25 | import org.languagetool.rules.Rule; 26 | import org.languagetool.rules.TextLevelRule; 27 | import org.writingtool.config.WtConfiguration; 28 | import org.writingtool.tools.WtMessageHandler; 29 | import org.writingtool.tools.WtOfficeTools; 30 | 31 | /** 32 | * class to store all text level rules sorted by the minimum to check paragraphs 33 | * (currently only full text check and all other text level rules) 34 | * @since 1.0 35 | * @author Fred Kruse 36 | */ 37 | public class WtSortedTextRules { 38 | 39 | private static boolean debugMode = false; // should be false except for testing 40 | 41 | List minToCheckParagraph; 42 | List> textLevelRules; 43 | 44 | WtSortedTextRules (WtLanguageTool lt, WtConfiguration config, Set disabledRulesUI, boolean checkImpressDocument) { 45 | minToCheckParagraph = new ArrayList<>(WtOfficeTools.NUMBER_TEXTLEVEL_CACHE); 46 | textLevelRules = new ArrayList<>(WtOfficeTools.NUMBER_TEXTLEVEL_CACHE); 47 | minToCheckParagraph.add(0,0); 48 | minToCheckParagraph.add(1,1); 49 | minToCheckParagraph.add(2,-1); 50 | minToCheckParagraph.add(3,-2); 51 | for (int i = 0; i < WtOfficeTools.NUMBER_TEXTLEVEL_CACHE; i++) { 52 | textLevelRules.add(i, new ArrayList<>()); 53 | } 54 | debugMode = WtOfficeTools.DEBUG_MODE_SR; 55 | List rules = checkImpressDocument ? lt.getAllActiveRules() : lt.getAllActiveOfficeRules(); 56 | int numParasToCheck = config.getNumParasToCheck(); 57 | for (Rule rule : rules) { 58 | if (rule instanceof TextLevelRule && !lt.getDisabledRules().contains(rule.getId()) 59 | && !disabledRulesUI.contains(rule.getId())) { 60 | insertRule(((TextLevelRule) rule).minToCheckParagraph(), numParasToCheck, rule.getId()); 61 | } 62 | } 63 | if (debugMode) { 64 | WtMessageHandler.printToLogFile("SortedTextRules: Number different minToCheckParagraph: " + minToCheckParagraph.size()); 65 | for ( int i = 0; i < minToCheckParagraph.size(); i++) { 66 | WtMessageHandler.printToLogFile("SortedTextRules: minToCheckParagraph: " + minToCheckParagraph.get(i)); 67 | for (int j = 0; j < textLevelRules.get(i).size(); j++) { 68 | WtMessageHandler.printToLogFile("RuleId: " + textLevelRules.get(i).get(j)); 69 | } 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * Insert a rule to list of text level rules 76 | */ 77 | private void insertRule(int minPara, int numParasToCheck, String ruleId) { 78 | if (minPara == 0) { 79 | textLevelRules.get(0).add(ruleId); 80 | } else { 81 | if (numParasToCheck >= 0) { 82 | textLevelRules.get(1).add(ruleId); 83 | if (minPara < 0 && minToCheckParagraph.get(1) < numParasToCheck) { 84 | minToCheckParagraph.set(1, numParasToCheck); 85 | } else if (minPara <= numParasToCheck && minPara > minToCheckParagraph.get(1)) { 86 | minToCheckParagraph.set(1, minPara); 87 | } 88 | } else if (minPara > 0) { 89 | textLevelRules.get(1).add(ruleId); 90 | if (minPara > minToCheckParagraph.get(1)) { 91 | minToCheckParagraph.set(1, minPara); 92 | } 93 | } else if (minPara == -2 && numParasToCheck == -2) { 94 | textLevelRules.get(3).add(ruleId); 95 | } else { 96 | textLevelRules.get(2).add(ruleId); 97 | } 98 | } 99 | } 100 | 101 | /** 102 | * Get the minimum of paragraphs that should be checked 103 | */ 104 | public List getMinToCheckParas() { 105 | return minToCheckParagraph; 106 | } 107 | 108 | /** 109 | * Activate the text level rules for a specified cache 110 | */ 111 | public void activateTextRulesByIndex(int nCache, WtLanguageTool lt) { 112 | for (int i = 0; i < textLevelRules.size(); i++) { 113 | if (i == nCache) { 114 | for (String ruleId : textLevelRules.get(i)) { 115 | lt.enableRule(ruleId); 116 | } 117 | } else { 118 | for (String ruleId : textLevelRules.get(i)) { 119 | lt.disableRule(ruleId); 120 | } 121 | } 122 | } 123 | } 124 | 125 | /** 126 | * Reactivate the text level rules which was deactivated for a specified cache 127 | */ 128 | public void reactivateTextRules(WtLanguageTool lt) { 129 | for (List textRules : textLevelRules) { 130 | for (String ruleId : textRules) { 131 | lt.enableRule(ruleId); 132 | } 133 | } 134 | } 135 | 136 | } 137 | 138 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/aisupport/WtAiCheckQueue.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.aisupport; 20 | 21 | import java.util.List; 22 | 23 | import org.languagetool.Language; 24 | import org.languagetool.UserConfig; 25 | import org.writingtool.WtDocumentCache; 26 | import org.writingtool.WtDocumentsHandler; 27 | import org.writingtool.WtSingleDocument; 28 | import org.writingtool.WtLanguageTool; 29 | import org.writingtool.WtLinguisticServices; 30 | import org.writingtool.WtTextLevelCheckQueue; 31 | import org.writingtool.aisupport.WtAiErrorDetection.DetectionType; 32 | import org.writingtool.WtDocumentCache.TextParagraph; 33 | import org.writingtool.config.WtConfiguration; 34 | import org.writingtool.tools.WtMessageHandler; 35 | import org.writingtool.tools.WtOfficeTools; 36 | import org.writingtool.tools.WtOfficeTools.DocumentType; 37 | 38 | /** 39 | * Class of a queue to handle check of AI error detection 40 | * @since 1.0 41 | * @author Fred Kruse 42 | */ 43 | public class WtAiCheckQueue extends WtTextLevelCheckQueue { 44 | 45 | private int debugMode = WtOfficeTools.DEBUG_MODE_AI; // should be false except for testing 46 | 47 | public WtAiCheckQueue(WtDocumentsHandler multiDocumentsHandler) { 48 | super(multiDocumentsHandler); 49 | WtMessageHandler.printToLogFile("AI Queue started"); 50 | } 51 | 52 | /** 53 | * Add a new entry to queue 54 | * add it only if the new entry is not identical with the last entry or the running 55 | */ 56 | public void addQueueEntry(TextParagraph nTPara, String docId, boolean next) { 57 | try { 58 | if (nTPara == null || nTPara.type < 0 || nTPara.number < 0 || docId == null || interruptCheck) { 59 | if (debugMode > 1) { 60 | WtMessageHandler.printToLogFile("AiCheckQueue: addQueueEntry: Return without add to queue: nCache = " + WtOfficeTools.CACHE_AI 61 | + ", nTPara = " + (nTPara == null ? "null" : ("(" + nTPara.number + "/" + nTPara.type + ")")) + ", docId = " + docId); 62 | } 63 | return; 64 | } 65 | QueueEntry queueEntry = new QueueEntry(nTPara, nTPara, WtOfficeTools.CACHE_AI, 0, docId, false); 66 | if (!textRuleQueue.isEmpty()) { 67 | synchronized(textRuleQueue) { 68 | for (int i = 0; i < textRuleQueue.size(); i++) { 69 | QueueEntry entry = textRuleQueue.get(i); 70 | if (entry.equals(queueEntry)) { 71 | if (debugMode > 1) { 72 | WtMessageHandler.printToLogFile("AiCheckQueue: addQueueEntry: Entry removed: nCache = " + WtOfficeTools.CACHE_AI 73 | + ", nTPara = (" + nTPara.number + "/" + nTPara.type + "), docId = " + docId); 74 | } 75 | textRuleQueue.remove(i); 76 | break; 77 | } 78 | } 79 | } 80 | } 81 | synchronized(textRuleQueue) { 82 | if (next) { 83 | textRuleQueue.add(0, queueEntry); 84 | } else { 85 | textRuleQueue.add(queueEntry); 86 | } 87 | if (debugMode > 1) { 88 | WtMessageHandler.printToLogFile("AiCheckQueue: addQueueEntry: Entry added: nCache = " + WtOfficeTools.CACHE_AI 89 | + ", nTPara = (" + nTPara.number + "/" + nTPara.type + "), docId = " + docId); 90 | } 91 | } 92 | interruptCheck = false; 93 | wakeupQueue(); 94 | } catch (Throwable t) { 95 | WtMessageHandler.showError(t); 96 | } 97 | } 98 | 99 | /** 100 | * get an entry for the next unchecked paragraphs 101 | */ 102 | @Override 103 | protected QueueEntry getNextQueueEntry(TextParagraph nPara, String docId) { 104 | try { 105 | List documents = multiDocHandler.getDocuments(); 106 | int nDoc = 0; 107 | for (int n = 0; n < documents.size(); n++) { 108 | if ((docId == null || docId.equals(documents.get(n).getDocID())) && !documents.get(n).isDisposed() && documents.get(n).getDocumentType() == DocumentType.WRITER) { 109 | QueueEntry queueEntry = documents.get(n).getNextAiQueueEntry(nPara); 110 | if (queueEntry != null) { 111 | return queueEntry; 112 | } 113 | nDoc = n; 114 | break; 115 | } 116 | } 117 | for (int i = nDoc + 1; i < documents.size(); i++) { 118 | if (!documents.get(i).isDisposed() && documents.get(i).getDocumentType() == DocumentType.WRITER) { 119 | QueueEntry queueEntry = documents.get(i).getNextAiQueueEntry(null); 120 | if (queueEntry != null) { 121 | return queueEntry; 122 | } 123 | } 124 | } 125 | for (int i = 0; i < nDoc; i++) { 126 | if (!documents.get(i).isDisposed() && documents.get(i).getDocumentType() == DocumentType.WRITER) { 127 | QueueEntry queueEntry = documents.get(i).getNextAiQueueEntry(null); 128 | if (queueEntry != null) { 129 | return queueEntry; 130 | } 131 | } 132 | } 133 | } catch (Throwable t) { 134 | WtMessageHandler.showError(t); 135 | } 136 | return null; 137 | } 138 | 139 | /** 140 | * initialize languagetool for text level iteration 141 | */ 142 | @Override 143 | public void initLangtool(Language language) throws Throwable { 144 | lt = null; 145 | try { 146 | if (debugMode > 1) { 147 | WtMessageHandler.printToLogFile("TextLevelCheckQueue: initLangtool: language = " + (language == null ? "null" : language.getShortCodeWithCountryAndVariant())); 148 | } 149 | WtConfiguration config = WtDocumentsHandler.getConfiguration(language); 150 | WtLinguisticServices linguServices = multiDocHandler.getLinguisticServices(); 151 | linguServices.setNoSynonymsAsSuggestions(config.noSynonymsAsSuggestions() || multiDocHandler.isTestMode()); 152 | Language fixedLanguage = config.getDefaultLanguage(); 153 | if (fixedLanguage != null) { 154 | language = fixedLanguage; 155 | } 156 | lt = new WtLanguageTool(language, config.getMotherTongue(), 157 | new UserConfig(config.getConfigurableValues(), linguServices), config, multiDocHandler.getExtraRemoteRules(), 158 | !config.useLtSpellChecker(), false, multiDocHandler.isTestMode(), true); 159 | } catch (Throwable t) { 160 | WtMessageHandler.showError(t); 161 | } 162 | } 163 | 164 | /** 165 | * run a queue entry for the specific document 166 | */ 167 | @Override 168 | protected void runQueueEntry(QueueEntry qEntry, WtDocumentsHandler multiDocHandler, WtLanguageTool lt) throws Throwable { 169 | try { 170 | if (debugMode > 1) { 171 | WtMessageHandler.printToLogFile("Try to run AI Queue Entry for " + qEntry.nStart.number); 172 | } 173 | WtSingleDocument document = getSingleDocument(qEntry.docId); 174 | TextParagraph nTPara = qEntry.nStart; 175 | if (document != null && !document.isDisposed() && nTPara != null) { 176 | WtDocumentCache docCache = document.getDocumentCache(); 177 | if (docCache != null) { 178 | int nFPara = nTPara.type == WtDocumentCache.CURSOR_TYPE_UNKNOWN ? nTPara.number : docCache.getFlatParagraphNumber(nTPara); 179 | if (debugMode > 1) { 180 | WtMessageHandler.printToLogFile("Run AI Queue Entry for " 181 | + ", nTPara = (" + nTPara.number + "/" + nTPara.type + "), docId = " + qEntry.docId 182 | + ", nFPara = " + nFPara); 183 | } 184 | WtAiErrorDetection aiError = new WtAiErrorDetection(document, multiDocHandler.getConfiguration(), lt); 185 | aiError.addAiRuleMatchesForParagraph(nFPara, DetectionType.GRAMMAR); 186 | if (multiDocHandler.useAiSuggestion()) { 187 | aiError.addAiRuleMatchesForParagraph(nFPara, DetectionType.REWRITE); 188 | } 189 | } 190 | } 191 | } catch (Throwable t) { 192 | WtMessageHandler.showError(t); 193 | } 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/aisupport/WtAiConfusionPairs.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.aisupport; 20 | 21 | import java.io.BufferedReader; 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.io.InputStreamReader; 25 | import java.nio.charset.StandardCharsets; 26 | import java.util.HashMap; 27 | import java.util.HashSet; 28 | import java.util.List; 29 | import java.util.Map; 30 | import java.util.Set; 31 | 32 | import org.languagetool.JLanguageTool; 33 | import org.writingtool.tools.WtMessageHandler; 34 | import org.writingtool.tools.WtOfficeTools; 35 | 36 | import com.sun.star.lang.Locale; 37 | 38 | /** 39 | * Class of confusion pairs handled by AI 40 | * @since 1.0 41 | * @author Fred Kruse 42 | */ 43 | public class WtAiConfusionPairs { 44 | 45 | private static String getConfusionSetFilePath(Locale locale, String fileName) { 46 | return "/" + locale.Language + "/" + fileName; 47 | } 48 | 49 | private static void addToWordMap (String word1, String word2, Map> words) { 50 | if (!word1.equalsIgnoreCase(word2)) { 51 | if (words.containsKey(word1)) { 52 | Set wList = words.get(word1); 53 | wList.add(word2); 54 | } else if (words.containsKey(word2)) { 55 | Set wList = words.get(word2); 56 | wList.add(word1); 57 | } else { 58 | Set wList = new HashSet(); 59 | wList.add(word2); 60 | words.put(word1, wList); 61 | } 62 | // WtMessageHandler.printToLogFile("Word pair added: " + word1 + ", " + word2); 63 | } 64 | } 65 | 66 | /** 67 | * get the list of words out of spelling.txt files defined by LT 68 | */ 69 | public static Map> getConfusionWordMap(Locale locale, String fileName) { 70 | return getConfusionWordMap(locale, fileName, null); 71 | } 72 | 73 | public static Map> getConfusionWordMap(Locale locale, String fileName, Map> words) { 74 | if (words == null) { 75 | words = new HashMap<>(); 76 | } 77 | String path = getConfusionSetFilePath(locale, fileName); 78 | WtMessageHandler.printToLogFile("Confusion set path: " + path); 79 | if (JLanguageTool.getDataBroker().resourceExists(path)) { 80 | List lines = JLanguageTool.getDataBroker().getFromResourceDirAsLines(path); 81 | if (lines != null) { 82 | for (String line : lines) { 83 | line = line.trim(); 84 | if (!line.isEmpty()) { 85 | if (line.startsWith("#")) { 86 | line = line.substring(1); 87 | } 88 | String[] lineString = line.split("#"); 89 | String wLine; 90 | if (lineString.length == 2) { 91 | wLine = lineString[0].trim(); 92 | } else { 93 | continue; 94 | } 95 | String[] sWords = wLine.split(";"); 96 | String word1; 97 | String word2; 98 | if (sWords.length == 3) { 99 | word1 = sWords[0].trim(); 100 | word2 = sWords[1].trim(); 101 | } else if (sWords.length == 2) { 102 | String[] tmpWords = sWords[0].trim().split("->"); 103 | word1 = tmpWords[0].trim(); 104 | word2 = tmpWords[1].trim(); 105 | } else { 106 | continue; 107 | } 108 | addToWordMap(word1, word2, words); 109 | } 110 | } 111 | } 112 | 113 | } else { 114 | WtMessageHandler.printToLogFile("Confusion path doe not exist: " + path); 115 | } 116 | return words; 117 | } 118 | 119 | public static Map> getWtConfusionWordMap(Locale locale, String fileName, Map> words) { 120 | try { 121 | if (words == null) { 122 | words = new HashMap<>(); 123 | } 124 | try (InputStream stream = WtOfficeTools.getWtRessourceAsInputStream(fileName, locale); 125 | InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8); 126 | BufferedReader br = new BufferedReader(reader) ) { 127 | String line; 128 | while ((line = br.readLine()) != null) { 129 | line = line.trim(); 130 | if (!line.isEmpty() && !line.startsWith("#")) { 131 | String[] sWords = line.split(";"); 132 | if (sWords.length == 2) { 133 | addToWordMap(sWords[0].trim(), sWords[1].trim(), words); 134 | } 135 | } 136 | } 137 | } catch (IOException e) { 138 | throw new RuntimeException(e); 139 | } 140 | } catch (Throwable t) { 141 | WtMessageHandler.showError(t); 142 | } 143 | return words; 144 | } 145 | 146 | 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/aisupport/WtAiDetectionRule_de.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.aisupport; 20 | 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.ResourceBundle; 25 | import java.util.Set; 26 | 27 | import org.languagetool.AnalyzedSentence; 28 | import org.languagetool.rules.RuleMatch; 29 | import org.writingtool.WtLinguisticServices; 30 | import com.sun.star.lang.Locale; 31 | 32 | /** 33 | * AI detection rule 34 | * analyzes output of AI 35 | * @since 1.0 36 | * @author Fred Kruse 37 | */ 38 | public class WtAiDetectionRule_de extends WtAiDetectionRule { 39 | 40 | private static final String CAPITALIZATION_MSG = "KI: Groß-/Kleinschreibung"; 41 | private static final String COMBINE_MSG = "KI: Zusammen-/Getrenntschreibung"; 42 | 43 | private static final String CONFUSION_FILE_1 = "confusion_set_candidates.txt"; 44 | private static final String CONFUSION_FILE_2 = "confusion_sets.txt"; 45 | private static final String WT_CONFUSION_FILE = "confusion_sets.txt"; 46 | 47 | private static Map> confusionWords = null; 48 | private static Map noneConfusionWords = null; 49 | 50 | WtAiDetectionRule_de(String aiResultText, List analyzedAiResult, String paraText, 51 | WtLinguisticServices linguServices, Locale locale, ResourceBundle messages, int showStylisticHints) throws Throwable { 52 | super(aiResultText, analyzedAiResult, paraText, linguServices, locale, messages, showStylisticHints); 53 | if (confusionWords == null) { 54 | confusionWords = WtAiConfusionPairs.getConfusionWordMap(locale, CONFUSION_FILE_1); 55 | confusionWords = WtAiConfusionPairs.getConfusionWordMap(locale, CONFUSION_FILE_2, confusionWords); 56 | confusionWords = WtAiConfusionPairs.getWtConfusionWordMap(locale, WT_CONFUSION_FILE, confusionWords); 57 | } 58 | if (noneConfusionWords == null) { 59 | noneConfusionWords = getNoneConfusionWords(); 60 | } 61 | } 62 | 63 | private Map getNoneConfusionWords() { 64 | Map noneConfusionWords = new HashMap<>(); 65 | noneConfusionWords.put("die", "sie"); 66 | noneConfusionWords.put("Die", "Sie"); 67 | return noneConfusionWords; 68 | } 69 | 70 | @Override 71 | public String getLanguage() { 72 | return "de"; 73 | } 74 | 75 | /** 76 | * Set Exceptions to set Color for specific Languages 77 | */ 78 | @Override 79 | public boolean isNoneHintException(int nParaStart, int nParaEnd, int nResultStart, int nResultEnd, 80 | List paraTokens, List resultTokens, RuleMatch ruleMatch) throws Throwable { 81 | // WtMessageHandler.printToLogFile("isHintException in: de" 82 | // + ", paraToken: " + paraToken.getToken() + ", resultToken: " + resultToken.getToken()); 83 | if (nParaStart == nParaEnd && nResultStart == nResultEnd) { 84 | String pToken = paraTokens.get(nParaStart).getToken(); 85 | String rToken = resultTokens.get(nResultStart).getToken(); 86 | for (String s : noneConfusionWords.keySet()) { 87 | if (pToken.equals(s)) { 88 | if (rToken.equals(noneConfusionWords.get(s))) { 89 | return true; 90 | } 91 | } 92 | } 93 | } 94 | return false; 95 | } 96 | 97 | /** 98 | * Set Exceptions to set Color for specific Languages 99 | */ 100 | @Override 101 | public boolean isHintException(int nParaStart, int nParaEnd, int nResultStart, int nResultEnd, 102 | List paraTokens, List resultTokens, RuleMatch ruleMatch) throws Throwable { 103 | // WtMessageHandler.printToLogFile("isHintException in: de" 104 | // + ", paraToken: " + paraToken.getToken() + ", resultToken: " + resultToken.getToken()); 105 | if (nParaStart == nParaEnd) { 106 | String pToken = paraTokens.get(nParaStart).getToken(); 107 | if (nResultStart == nResultEnd) { 108 | String rToken = resultTokens.get(nResultStart).getToken(); 109 | if ("dass".equals(pToken) || "dass".equals(rToken)) { 110 | ruleMatch.setMessage(ruleMessageWordConfusion); 111 | return true; 112 | } else if (pToken.equalsIgnoreCase(rToken)) { 113 | ruleMatch.setMessage(CAPITALIZATION_MSG); 114 | return true; 115 | } else if (isConfusionPair(pToken, rToken)) { 116 | ruleMatch.setMessage(ruleMessageWordConfusion); 117 | return true; 118 | } 119 | } else if (nResultStart == nResultEnd - 1) { 120 | if (",".equals(resultTokens.get(nResultStart).getToken()) 121 | && (pToken.equals(resultTokens.get(nResultEnd).getToken()) || "dass".equals(resultTokens.get(nResultEnd).getToken()))) { 122 | ruleMatch.setMessage(ruleMessageMissingPunctuation); 123 | return true; 124 | } else if (pToken.equals(resultTokens.get(nResultStart).getToken() + resultTokens.get(nResultEnd).getToken())) { 125 | ruleMatch.setMessage(COMBINE_MSG); 126 | return true; 127 | } 128 | } 129 | } else if (nResultStart == nResultEnd) { 130 | if (nParaStart == nParaEnd - 1) { 131 | String rToken = resultTokens.get(nResultStart).getToken(); 132 | if (rToken.equals(paraTokens.get(nParaStart).getToken() + paraTokens.get(nParaEnd).getToken())) { 133 | ruleMatch.setMessage(COMBINE_MSG); 134 | return true; 135 | } 136 | } 137 | } 138 | return false; 139 | } 140 | 141 | /** 142 | * If tokens (from start to end) contains sToken return true 143 | * else false 144 | */ 145 | private boolean containToken(String sToken, int start, int end, List tokens) throws Throwable { 146 | for (int i = start; i <= end; i++) { 147 | if (sToken.equals(tokens.get(i).getToken())) { 148 | return true; 149 | } 150 | } 151 | return false; 152 | } 153 | 154 | /** 155 | * Set language specific exceptions to handle change as a match 156 | * @throws Throwable 157 | */ 158 | @Override 159 | public boolean isMatchException(int nParaStart, int nParaEnd, 160 | int nResultStart, int nResultEnd, List paraTokens, List resultTokens) throws Throwable { 161 | if (nResultStart < 0 || nResultStart >= resultTokens.size() - 1) { 162 | return false; 163 | } 164 | if ((resultTokens.get(nResultStart).getToken().equals(",") && nResultStart < resultTokens.size() - 1 165 | && (resultTokens.get(nResultStart + 1).getToken().equals("und") || resultTokens.get(nResultStart + 1).getToken().equals("oder"))) 166 | || (resultTokens.get(nResultStart + 1).getToken().equals(",") && nResultStart < resultTokens.size() - 2 167 | && (resultTokens.get(nResultStart + 2).getToken().equals("und") 168 | || resultTokens.get(nResultStart + 2).getToken().equals("oder")))) { 169 | return true; 170 | } 171 | if (nParaStart < paraTokens.size() - 1 172 | && isQuote(paraTokens.get(nParaStart).getToken()) 173 | && ",".equals(paraTokens.get(nParaStart + 1).getToken()) 174 | && !containToken(paraTokens.get(nParaStart).getToken(), nResultStart, nResultEnd, resultTokens)) { 175 | return true; 176 | } 177 | if(nParaStart == nParaEnd && nResultStart == nResultEnd 178 | && !paraTokens.get(nParaStart).isNonWord() && resultTokens.get(nResultStart).getToken().contains("-") 179 | && resultTokens.get(nResultStart).getToken().replace("-", "").equalsIgnoreCase(paraTokens.get(nParaStart).getToken())) { 180 | return true; 181 | } 182 | return false; 183 | } 184 | 185 | private boolean isConfusionPair(String wPara, String wResult) { 186 | if (confusionWords.containsKey(wPara) && confusionWords.get(wPara).contains(wResult)) { 187 | return true; 188 | } 189 | if (confusionWords.containsKey(wResult) && confusionWords.get(wResult).contains(wPara)) { 190 | return true; 191 | } 192 | return false; 193 | } 194 | 195 | 196 | 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/aisupport/WtAiTextToSpeech.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.aisupport; 20 | 21 | import java.io.File; 22 | import java.net.URI; 23 | import java.net.URISyntaxException; 24 | import java.util.Map; 25 | import java.util.ResourceBundle; 26 | import java.util.regex.Pattern; 27 | 28 | import javax.swing.JFileChooser; 29 | import javax.swing.SwingUtilities; 30 | 31 | import org.writingtool.WtDocumentCache; 32 | import org.writingtool.WtSingleDocument; 33 | import org.writingtool.WtDocumentCache.TextParagraph; 34 | import org.writingtool.WtDocumentsHandler.WaitDialogThread; 35 | import org.writingtool.config.WtConfiguration; 36 | import org.writingtool.tools.WtMessageHandler; 37 | import org.writingtool.tools.WtOfficeTools; 38 | 39 | import com.sun.star.frame.XModel; 40 | import com.sun.star.uno.UnoRuntime; 41 | 42 | /** 43 | * Class for a new document filled by AI 44 | * @since 1.0 45 | * @author Fred Kruse 46 | */ 47 | 48 | public class WtAiTextToSpeech extends Thread { 49 | 50 | private static final ResourceBundle messages = WtOfficeTools.getMessageBundle(); 51 | private final static String ParaEndSign = "."; // Sign to force speech to make a small pause 52 | private final static String PauseSign = " - . - . - ."; 53 | 54 | public final static String WAIT_TITLE = messages.getString("loAiWaitDialogTitle"); 55 | public final static String WAIT_MESSAGE = messages.getString("loAiWaitDialogMessage"); 56 | 57 | public final static String TMP_DIRNAME = "audioOut"; 58 | 59 | private int debugMode = WtOfficeTools.DEBUG_MODE_AI; // should be false except for testing 60 | 61 | private final Pattern ALPHA_NUM = Pattern.compile("[\\p{L}\\d]"); 62 | private WaitDialogThread waitDialog = null; 63 | private final WtSingleDocument document; 64 | private final WtDocumentCache docCache; 65 | private final Map headingMap; 66 | // private XComponentContext xContext; 67 | // private WtDocumentCursorTools docCursor; 68 | // private XComponent xToComponent; 69 | 70 | public WtAiTextToSpeech(WtSingleDocument document, ResourceBundle messages) { 71 | //- this.xContext = xContext; 72 | this.document = document; 73 | docCache = document.getDocumentCache(); 74 | headingMap = docCache.getHeadingMap(); 75 | } 76 | 77 | @Override 78 | public void run() { 79 | try { 80 | String audioDir = getAudioDir(); 81 | if (audioDir == null) { 82 | return; 83 | } 84 | waitDialog = new WaitDialogThread(WAIT_TITLE, WAIT_MESSAGE); 85 | waitDialog.start(); 86 | /* 87 | WtConfiguration config = document.getMultiDocumentsHandler().getConfiguration(); 88 | XComponent xComponent = document.getXComponent(); 89 | WtViewCursorTools viewCursor = new WtViewCursorTools(xComponent); 90 | TextParagraph tPara = viewCursor.getViewCursorParagraph(); 91 | WtDocumentCache docCache = document.getDocumentCache(); 92 | String text = docCache.getTextParagraph(tPara); 93 | */ 94 | WtConfiguration config = document.getMultiDocumentsHandler().getConfiguration(); 95 | WtAiRemote aiRemote = new WtAiRemote(document.getMultiDocumentsHandler(), config); 96 | int nParaStart = 0; 97 | int nFile = 0; 98 | int maxPara = docCache.textSize(WtDocumentCache.CURSOR_TYPE_TEXT); 99 | SwingUtilities.invokeLater(() -> { waitDialog.initializeProgressBar(0, maxPara); }); 100 | 101 | while ((nParaStart = createAudioFile(nParaStart, nFile, audioDir, aiRemote)) < maxPara) { 102 | nFile++; 103 | if (waitDialog.canceled()) { 104 | waitDialog.close(); 105 | return; 106 | } 107 | int nValue = nParaStart; 108 | SwingUtilities.invokeLater(() -> { waitDialog.setValueForProgressBar(nValue, true); }); 109 | } 110 | waitDialog.close(); 111 | } catch (Throwable e) { 112 | WtMessageHandler.showError(e); 113 | } 114 | } 115 | 116 | private String getAudioDir() { 117 | String sAudioDir = null; 118 | XModel xModel = UnoRuntime.queryInterface(XModel.class, document.getXComponent()); 119 | if (xModel != null) { 120 | String url = xModel.getURL(); 121 | if (url != null && url.startsWith("file://")) { 122 | URI uri; 123 | try { 124 | uri = new URI(url); 125 | sAudioDir = uri.getPath(); 126 | int nDir = sAudioDir.lastIndexOf("."); 127 | sAudioDir = sAudioDir.substring(0, nDir) + "_audio"; 128 | } catch (URISyntaxException e) { 129 | } 130 | } 131 | } 132 | if (sAudioDir == null) { 133 | sAudioDir = System.getProperty("user.home"); 134 | if (sAudioDir == null) { 135 | return null; 136 | } 137 | sAudioDir += "/" + TMP_DIRNAME; 138 | } 139 | File audioDir = new File(sAudioDir); 140 | if (audioDir.exists()) { 141 | String path = audioDir.getAbsolutePath(); 142 | int i = 1; 143 | while ((audioDir = new File(path + "." + i)).exists()) { 144 | i++; 145 | }; 146 | } 147 | JFileChooser fileChooser = new JFileChooser(audioDir.getParent()); 148 | fileChooser.setSelectedFile(audioDir); 149 | int choose = fileChooser.showSaveDialog(null); 150 | if (choose != JFileChooser.APPROVE_OPTION) { 151 | return null; 152 | } 153 | audioDir = fileChooser.getSelectedFile(); 154 | audioDir.mkdirs(); 155 | return audioDir.getAbsolutePath() + "/"; 156 | } 157 | 158 | /** is Header of chapter 159 | * NOTE: nPara is number of text paragraph 160 | */ 161 | private boolean isRealHeader(int nPara) { 162 | return (headingMap.containsKey(nPara) && headingMap.get(nPara) > 0); 163 | } 164 | 165 | private boolean isPause(String sPara) { 166 | return !sPara.isBlank() && !ALPHA_NUM.matcher(sPara).find(); 167 | } 168 | 169 | private StringBuilder addToText(int nPara, StringBuilder sb) { 170 | String sPara = docCache.getTextParagraph(new TextParagraph(WtDocumentCache.CURSOR_TYPE_TEXT, nPara)); 171 | sb.append(sPara); 172 | if (!sPara.endsWith(ParaEndSign)) { 173 | sb.append(ParaEndSign); 174 | } 175 | sb.append(" "); 176 | if (isRealHeader(nPara) || isPause(sPara)) { 177 | sb.append(PauseSign); 178 | } 179 | return sb; 180 | } 181 | 182 | private int createAudioFile(int nParaStart, int nFile, String audioDir, WtAiRemote aiRemote) { 183 | int n = nParaStart; 184 | String filename; 185 | try { 186 | if (isRealHeader(nParaStart)) { 187 | filename = docCache.getTextParagraph(new TextParagraph(WtDocumentCache.CURSOR_TYPE_TEXT, nParaStart)); 188 | filename.replaceAll("[^\\w\\d]", "_"); 189 | } else { 190 | filename = "Intro"; 191 | } 192 | filename = audioDir + (nFile < 10 ? "0" : "") + nFile + "_" + filename; 193 | StringBuilder sb = new StringBuilder(); 194 | if (n < docCache.textSize(WtDocumentCache.CURSOR_TYPE_TEXT)) { 195 | addToText(n, sb); 196 | n++; 197 | } 198 | for (; n < docCache.textSize(WtDocumentCache.CURSOR_TYPE_TEXT) && !isRealHeader(n); n++) { 199 | addToText(n, sb); 200 | } 201 | String text = sb.toString(); 202 | if (debugMode > 1) { 203 | WtMessageHandler.printToLogFile("AiTextToSpeech: runInstruction: text: " + text); 204 | } 205 | aiRemote.runTtsInstruction(text, filename); 206 | } catch (Throwable t) { 207 | WtMessageHandler.showError(t); 208 | n = docCache.textSize(WtDocumentCache.CURSOR_TYPE_TEXT); 209 | } 210 | return n; 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/aisupport/WtAiToken.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.aisupport; 20 | 21 | import java.util.List; 22 | 23 | import org.languagetool.AnalyzedSentence; 24 | import org.languagetool.AnalyzedToken; 25 | import org.languagetool.AnalyzedTokenReadings; 26 | 27 | /** 28 | * Defines an easy token 29 | * @since 1.0 30 | * @author Fred Kruse 31 | */ 32 | public class WtAiToken { 33 | private final AnalyzedTokenReadings token; 34 | private final AnalyzedSentence sentence; 35 | private final int sentencePos; 36 | 37 | WtAiToken(AnalyzedTokenReadings token, int sentencePos, AnalyzedSentence sentence) { 38 | this.sentence = sentence; 39 | this.token = token; 40 | this.sentencePos = sentencePos; 41 | } 42 | 43 | int getStartPos() { 44 | return token.getStartPos() + sentencePos; 45 | } 46 | 47 | int getEndPos() { 48 | return token.getEndPos() + sentencePos; 49 | } 50 | 51 | String getToken() { 52 | return token.getToken(); 53 | } 54 | 55 | AnalyzedSentence getSentence() { 56 | return sentence; 57 | } 58 | 59 | boolean isNonWord() { 60 | return token.isNonWord(); 61 | } 62 | 63 | boolean hasLemma(String s) { 64 | return token.hasLemma(s); 65 | } 66 | 67 | List getReadings() { 68 | return token.getReadings(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/aisupport/WtAiTranslateDocument.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.aisupport; 20 | 21 | import java.util.ResourceBundle; 22 | 23 | import javax.swing.SwingUtilities; 24 | 25 | import org.writingtool.WtDocumentCache; 26 | import org.writingtool.WtSingleDocument; 27 | import org.writingtool.dialogs.WtAiTranslationDialog; 28 | import org.writingtool.dialogs.WtAiTranslationDialog.TranslationOptions; 29 | import org.writingtool.WtDocumentCache.TextParagraph; 30 | import org.writingtool.WtDocumentsHandler.WaitDialogThread; 31 | import org.writingtool.tools.WtDocumentCursorTools; 32 | import org.writingtool.tools.WtMessageHandler; 33 | import org.writingtool.tools.WtOfficeTools; 34 | 35 | import com.sun.star.beans.PropertyValue; 36 | import com.sun.star.beans.PropertyVetoException; 37 | import com.sun.star.beans.UnknownPropertyException; 38 | import com.sun.star.beans.XPropertySet; 39 | import com.sun.star.frame.XModel; 40 | import com.sun.star.frame.XStorable; 41 | import com.sun.star.io.IOException; 42 | import com.sun.star.lang.IllegalArgumentException; 43 | import com.sun.star.lang.Locale; 44 | import com.sun.star.lang.WrappedTargetException; 45 | import com.sun.star.text.XParagraphCursor; 46 | import com.sun.star.uno.UnoRuntime; 47 | 48 | /** 49 | * Class for a new document filled by AI 50 | * @since 1.0 51 | * @author Fred Kruse 52 | */ 53 | 54 | public class WtAiTranslateDocument extends Thread { 55 | 56 | // private static final ResourceBundle messages = WtOfficeTools.getMessageBundle(); 57 | 58 | private String TRANSLATE_INSTRUCTION = "Print the translation of the following text in the language "; 59 | private String TRANSLATE_INSTRUCTION_POST = " (without comments)"; 60 | 61 | private final ResourceBundle messages; 62 | private WaitDialogThread waitDialog = null; 63 | // private XComponentContext xContext; 64 | private WtSingleDocument document; 65 | WtDocumentCursorTools docCursor; 66 | // private XComponent xToComponent; 67 | private Locale locale; 68 | private float temperature; 69 | private String fromUrl; 70 | 71 | public WtAiTranslateDocument(WtSingleDocument document, ResourceBundle messages) { 72 | //- this.xContext = xContext; 73 | this.document = document; 74 | this.messages = messages; 75 | XModel xModel = UnoRuntime.queryInterface(XModel.class, document.getXComponent()); 76 | if (xModel == null) { 77 | WtMessageHandler.printToLogFile("CacheIO: getDocumentPath: XModel not found!"); 78 | return; 79 | } 80 | fromUrl = xModel.getURL(); 81 | 82 | } 83 | 84 | @Override 85 | public void run() { 86 | try { 87 | // xToComponent = openNewFile(); 88 | TranslationOptions transOpt = getTranslationOptions(); 89 | if (transOpt != null) { 90 | locale = transOpt.locale; 91 | temperature = transOpt.temperature; 92 | WtMessageHandler.printToLogFile("Locale: " + WtOfficeTools.localeToString(locale)); 93 | saveFile(); 94 | writeText(); 95 | } else { 96 | WtMessageHandler.printToLogFile("Locale: null"); 97 | } 98 | } catch (Throwable e) { 99 | WtMessageHandler.showError(e); 100 | } 101 | } 102 | private TranslationOptions getTranslationOptions() { 103 | WtAiTranslationDialog langDialog = new WtAiTranslationDialog(document, messages); 104 | return langDialog.run(); 105 | } 106 | /* 107 | private XComponent openNewFile() throws IOException, IllegalArgumentException { 108 | XDesktop xDesktop = WtOfficeTools.getDesktop(xContext); 109 | XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface( 110 | XComponentLoader.class, xDesktop); 111 | String loadURL = "private:factory/swriter"; 112 | 113 | // the boolean property Hidden tells the office to open a file in hidden mode 114 | PropertyValue[] loadProps = new PropertyValue[1]; 115 | loadProps[0] = new PropertyValue(); 116 | loadProps[0].Name = "Hidden"; 117 | loadProps[0].Value = false; 118 | return xComponentLoader.loadComponentFromURL(loadURL, "_blank", 0, loadProps); 119 | } 120 | 121 | private void insertParagraph(String str, XText docText) { 122 | docText.getEnd().setString(str); 123 | docText.getEnd().setString("\n"); 124 | } 125 | *//* 126 | private void replaceParagraph(int nFPara, int oldLength, String str, Locale locale) { 127 | document.getFlatParagraphTools().changeTextAndLocaleOfParagraph(nFPara, 0, oldLength, str, locale); 128 | } 129 | */ 130 | private void replaceParagraph(TextParagraph textPara, String str, Locale locale) 131 | throws UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException { 132 | XParagraphCursor pCursor = docCursor.getParagraphCursor(textPara); 133 | if (pCursor == null) { 134 | docCursor = new WtDocumentCursorTools(document.getXComponent()); 135 | pCursor = docCursor.getParagraphCursor(textPara); 136 | } 137 | pCursor.gotoStartOfParagraph(false); 138 | pCursor.gotoEndOfParagraph(true); 139 | pCursor.setString(str); 140 | XPropertySet xCursorProps = UnoRuntime.queryInterface( 141 | XPropertySet.class, pCursor ); 142 | xCursorProps.setPropertyValue ( "CharLocale", locale); 143 | } 144 | 145 | private String outUrl(String inUrl, String lang) { 146 | int n = inUrl.lastIndexOf('.'); 147 | String name = inUrl.substring(0, n); 148 | String ext = inUrl.substring(n); 149 | return name + "_" + lang + ext; 150 | } 151 | 152 | private void saveFile() throws IOException { 153 | XStorable xStore = UnoRuntime.queryInterface (com.sun.star.frame.XStorable.class, document.getXComponent()); 154 | PropertyValue[] sProps = new PropertyValue[1]; 155 | sProps[0] = new PropertyValue(); 156 | sProps[0].Name = "Overwrite"; 157 | sProps[0].Value = true; 158 | xStore.storeAsURL (outUrl(fromUrl, locale.Language), sProps); 159 | } 160 | 161 | private void writeText() { 162 | try { 163 | WtDocumentCache fromCache = document.getDocumentCache(); 164 | waitDialog = new WaitDialogThread(WtAiParagraphChanging.WAIT_TITLE, WtAiParagraphChanging.WAIT_MESSAGE); 165 | waitDialog.start(); 166 | WtAiRemote aiRemote = new WtAiRemote(document.getMultiDocumentsHandler(), document.getMultiDocumentsHandler().getConfiguration()); 167 | docCursor = document.getDocumentCursorTools(); 168 | String instruction = TRANSLATE_INSTRUCTION + locale.Language + TRANSLATE_INSTRUCTION_POST; 169 | SwingUtilities.invokeLater(() -> { waitDialog.initializeProgressBar(0, fromCache.size()); }); 170 | for(int i = 0; i < fromCache.size(); i++) { 171 | if (waitDialog.canceled()) { 172 | break; 173 | } 174 | String str = fromCache.getFlatParagraph(i); 175 | if(str.trim().isEmpty()) { 176 | continue; 177 | } 178 | String out = aiRemote.runInstruction(instruction, str, temperature, 1, locale, true); 179 | TextParagraph textPara = fromCache.getNumberOfTextParagraph(i); 180 | replaceParagraph(textPara, out, locale); 181 | int nValue = i; 182 | SwingUtilities.invokeLater(() -> { waitDialog.setValueForProgressBar(nValue, true); }); 183 | } 184 | } catch (Throwable t) { 185 | WtMessageHandler.printException(t); 186 | } 187 | if (waitDialog != null) { 188 | waitDialog.close(); 189 | } 190 | 191 | } 192 | 193 | } 194 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/config/WtCategoryNode.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.config; 20 | 21 | import javax.swing.tree.DefaultMutableTreeNode; 22 | import org.languagetool.rules.Category; 23 | 24 | /** 25 | * 26 | * @author Panagiotis Minos 27 | * @since 1.0 28 | */ 29 | public class WtCategoryNode extends DefaultMutableTreeNode { 30 | 31 | private static final long serialVersionUID = 1L; 32 | private final Category category; 33 | private boolean enabled; 34 | 35 | public WtCategoryNode(Category category, boolean enabled) { 36 | super(category); 37 | this.category = category; 38 | this.enabled = enabled; 39 | } 40 | 41 | public Category getCategory() { 42 | return category; 43 | } 44 | 45 | public boolean isEnabled() { 46 | return enabled; 47 | } 48 | 49 | public void setEnabled(boolean enabled) { 50 | this.enabled = enabled; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | int children = this.getChildCount(); 56 | int selected = 0; 57 | for (int i = 0; i < children; i++) { 58 | WtRuleNode child = (WtRuleNode) this.getChildAt(i); 59 | if (child.isEnabled()) { 60 | selected++; 61 | } 62 | } 63 | return String.format("%s (%d/%d)", category.getName(), selected, children); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/config/WtCheckBoxTreeCellRenderer.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.config; 20 | 21 | import java.awt.BorderLayout; 22 | import java.awt.Component; 23 | import javax.swing.JCheckBox; 24 | import javax.swing.JPanel; 25 | import javax.swing.JTree; 26 | import javax.swing.tree.DefaultTreeCellRenderer; 27 | import javax.swing.tree.TreeCellRenderer; 28 | 29 | /** 30 | * 31 | * @author Panagiotis Minos 32 | * @since 1.0 33 | */ 34 | public class WtCheckBoxTreeCellRenderer extends JPanel implements TreeCellRenderer { 35 | 36 | private static final long serialVersionUID = 1L; 37 | private final DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); 38 | private final JCheckBox checkBox = new JCheckBox(); 39 | 40 | private Component defaultComponent; 41 | 42 | public WtCheckBoxTreeCellRenderer() { 43 | setLayout(new BorderLayout()); 44 | setOpaque(false); 45 | checkBox.setOpaque(false); 46 | renderer.setLeafIcon(null); 47 | add(checkBox, BorderLayout.WEST); 48 | } 49 | 50 | @Override 51 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { 52 | Component component = renderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); 53 | 54 | if (value instanceof WtCategoryNode) { 55 | if (defaultComponent != null) { 56 | remove(defaultComponent); 57 | } 58 | defaultComponent = component; 59 | add(component, BorderLayout.CENTER); 60 | WtCategoryNode node = (WtCategoryNode) value; 61 | checkBox.setSelected(node.isEnabled()); 62 | return this; 63 | } 64 | 65 | if (value instanceof WtRuleNode) { 66 | if (defaultComponent != null) { 67 | remove(defaultComponent); 68 | } 69 | defaultComponent = component; 70 | add(component, BorderLayout.CENTER); 71 | WtRuleNode node = (WtRuleNode) value; 72 | checkBox.setSelected(node.isEnabled()); 73 | return this; 74 | } 75 | 76 | return component; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/config/WtConfigThread.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.config; 20 | 21 | import java.util.HashSet; 22 | import java.util.List; 23 | import java.util.Set; 24 | 25 | import org.languagetool.Language; 26 | import org.languagetool.rules.Rule; 27 | import org.writingtool.tools.WtMessageHandler; 28 | import org.writingtool.tools.WtOfficeTools; 29 | import org.writingtool.tools.WtVersionInfo; 30 | import org.writingtool.WtDocumentsHandler; 31 | import org.writingtool.WtLanguageTool; 32 | import org.writingtool.dialogs.WtConfigurationDialog; 33 | 34 | /** 35 | * A thread that shows the configuration dialog which lets the 36 | * user enable/disable rules. 37 | * 38 | * @author Fred Kruse 39 | */ 40 | public class WtConfigThread extends Thread { 41 | 42 | private final Language docLanguage; 43 | private final WtConfiguration config; 44 | private final WtLanguageTool lt; 45 | private final WtDocumentsHandler documents; 46 | private final WtConfigurationDialog cfgDialog; 47 | 48 | public WtConfigThread(Language docLanguage, WtConfiguration config, WtLanguageTool lt, WtDocumentsHandler documents) { 49 | if (config.getDefaultLanguage() == null) { 50 | this.docLanguage = docLanguage; 51 | } else { 52 | this.docLanguage = config.getDefaultLanguage(); 53 | } 54 | this.config = config; 55 | this.lt = lt; 56 | this.documents = documents; 57 | String title = WtOfficeTools.getMessageBundle().getString("guiWtConfigWindowTitle") 58 | + " (WT " + WtVersionInfo.getWtInformation() 59 | + ", LT " + WtVersionInfo.getLtInformation() + ")"; 60 | cfgDialog = new WtConfigurationDialog(null, WtOfficeTools.getLtImage(), title, config); 61 | } 62 | 63 | @Override 64 | public void run() { 65 | if(!documents.javaVersionOkay()) { 66 | return; 67 | } 68 | if (!WtDocumentsHandler.isJavaLookAndFeelSet()) { 69 | WtDocumentsHandler.setJavaLookAndFeel(); 70 | } 71 | documents.setConfigurationDialog(cfgDialog); 72 | try { 73 | List allRules = lt.getAllRules(); 74 | Set disabledRulesUI = WtDocumentsHandler.getDisabledRules(docLanguage.getShortCodeWithCountryAndVariant()); 75 | config.addDisabledRuleIds(disabledRulesUI); 76 | boolean configChanged = cfgDialog.show(allRules); 77 | if (configChanged) { 78 | Set disabledRules = config.getDisabledRuleIds(); 79 | Set tmpDisabledRules = new HashSet<>(disabledRulesUI); 80 | for (String ruleId : tmpDisabledRules) { 81 | if(!disabledRules.contains(ruleId)) { 82 | disabledRulesUI.remove(ruleId); 83 | } 84 | } 85 | documents.setDisabledRules(docLanguage.getShortCodeWithCountryAndVariant(), disabledRulesUI); 86 | config.removeDisabledRuleIds(disabledRulesUI); 87 | config.saveConfiguration(docLanguage); 88 | documents.resetDocumentCaches(); 89 | documents.resetConfiguration(); 90 | } else { 91 | config.removeDisabledRuleIds(WtDocumentsHandler.getDisabledRules(docLanguage.getShortCodeWithCountryAndVariant())); 92 | } 93 | } catch (Throwable e) { 94 | WtMessageHandler.showError(e); 95 | } 96 | documents.setConfigurationDialog(null); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/config/WtRuleNode.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.config; 20 | 21 | import javax.swing.tree.DefaultMutableTreeNode; 22 | import org.languagetool.rules.Rule; 23 | 24 | /** 25 | * @author Panagiotis Minos 26 | * @since 1.0 27 | */ 28 | public class WtRuleNode extends DefaultMutableTreeNode { 29 | 30 | private static final long serialVersionUID = 1L; 31 | private final Rule rule; 32 | private boolean enabled; 33 | 34 | public WtRuleNode(Rule rule, boolean enabled) { 35 | super(rule); 36 | this.rule = rule; 37 | this.enabled = enabled; 38 | } 39 | 40 | public Rule getRule() { 41 | return rule; 42 | } 43 | 44 | public boolean isEnabled() { 45 | return enabled; 46 | } 47 | 48 | public void setEnabled(boolean enabled) { 49 | this.enabled = enabled; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return rule.getDescription(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/config/WtSavablePanel.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.config; 20 | 21 | import org.writingtool.dialogs.WtConfigurationDialog; 22 | 23 | /** 24 | * Interface for JPanel that can persist its state. 25 | *

26 | * See {@link WtConfigurationDialog#addExtraPanel} 27 | * 28 | * @author Panagiotis Minos 29 | * @since 1.0 30 | */ 31 | public interface WtSavablePanel { 32 | 33 | /** 34 | * Called when {@link WtConfigurationDialog} is about to be shown. 35 | */ 36 | public void componentShowing(); 37 | 38 | /** 39 | * Invoke the save operation. 40 | */ 41 | public void save(); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/config/WtTreeListener.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.config; 20 | 21 | import java.awt.Dimension; 22 | import java.awt.MouseInfo; 23 | import java.awt.Point; 24 | import java.awt.event.KeyEvent; 25 | import java.awt.event.KeyListener; 26 | import java.awt.event.MouseEvent; 27 | import java.awt.event.MouseListener; 28 | import javax.swing.JCheckBox; 29 | import javax.swing.JTree; 30 | import javax.swing.event.TreeExpansionEvent; 31 | import javax.swing.event.TreeWillExpandListener; 32 | import javax.swing.tree.DefaultTreeModel; 33 | import javax.swing.tree.ExpandVetoException; 34 | import javax.swing.tree.TreePath; 35 | 36 | /** 37 | * 38 | * @author Panagiotis Minos 39 | * @since 1.0 40 | */ 41 | public class WtTreeListener implements KeyListener, MouseListener, TreeWillExpandListener { 42 | 43 | public static void install(JTree tree) { 44 | WtTreeListener listener = new WtTreeListener(tree); 45 | tree.addMouseListener(listener); 46 | tree.addKeyListener(listener); 47 | tree.addTreeWillExpandListener(listener); 48 | } 49 | 50 | private static final Dimension checkBoxDimension = new JCheckBox().getPreferredSize(); 51 | 52 | private final JTree tree; 53 | 54 | private WtTreeListener(JTree tree) { 55 | this.tree = tree; 56 | } 57 | 58 | @Override 59 | public void keyTyped(KeyEvent e) { 60 | } 61 | 62 | @Override 63 | public void keyPressed(KeyEvent e) { 64 | if (e.getKeyCode() == KeyEvent.VK_SPACE) { 65 | TreePath[] paths = tree.getSelectionPaths(); 66 | if (paths != null) { 67 | for (TreePath path : paths) { 68 | handle(path); 69 | } 70 | } 71 | } 72 | } 73 | 74 | @Override 75 | public void keyReleased(KeyEvent e) { 76 | } 77 | 78 | @Override 79 | public void mouseClicked(MouseEvent e) { 80 | } 81 | 82 | @Override 83 | public void mousePressed(MouseEvent e) { 84 | int x = e.getX(); 85 | int y = e.getY(); 86 | TreePath path = tree.getPathForLocation(x, y); 87 | if (isOverCheckBox(x, y, path)) { 88 | handle(path); 89 | } 90 | } 91 | 92 | @Override 93 | public void mouseReleased(MouseEvent e) { 94 | } 95 | 96 | @Override 97 | public void mouseEntered(MouseEvent e) { 98 | } 99 | 100 | @Override 101 | public void mouseExited(MouseEvent e) { 102 | } 103 | 104 | private void handle(TreePath path) { 105 | if ((path != null) && (path.getPathCount() > 0)) { 106 | if (path.getLastPathComponent() instanceof WtCategoryNode) { 107 | DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); 108 | 109 | WtCategoryNode node = (WtCategoryNode) path.getLastPathComponent(); 110 | node.setEnabled(!node.isEnabled()); 111 | model.nodeChanged(node); 112 | 113 | for (int i = 0; i < node.getChildCount(); i++) { 114 | WtRuleNode child = (WtRuleNode) node.getChildAt(i); 115 | if (child.isEnabled() != node.isEnabled()) { 116 | child.setEnabled(node.isEnabled()); 117 | model.nodeChanged(child); 118 | } 119 | } 120 | } 121 | if (path.getLastPathComponent() instanceof WtRuleNode) { 122 | DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); 123 | 124 | WtRuleNode node = (WtRuleNode) path.getLastPathComponent(); 125 | node.setEnabled(!node.isEnabled()); 126 | model.nodeChanged(node); 127 | 128 | if (node.isEnabled()) { 129 | WtCategoryNode parent = (WtCategoryNode) node.getParent(); 130 | parent.setEnabled(true); 131 | } 132 | model.nodeChanged(node.getParent()); 133 | } 134 | } 135 | } 136 | 137 | private boolean isOverCheckBox(int x, int y, TreePath path) { 138 | if ((path == null) || (path.getPathCount() == 0)) { 139 | return false; 140 | } 141 | if (!isValidNode(path.getLastPathComponent())) { 142 | return false; 143 | } 144 | //checkbox is east 145 | //int offset = tree.getPathBounds(path).x + tree.getPathBounds(path).width - checkBoxDimension.width; 146 | //if (x < offset) { 147 | 148 | //checkbox is west 149 | int offset = tree.getPathBounds(path).x + checkBoxDimension.width; 150 | if (x > offset) { 151 | return false; 152 | } 153 | return true; 154 | } 155 | 156 | private boolean isValidNode(Object c) { 157 | return ((c instanceof WtCategoryNode) || (c instanceof WtRuleNode)); 158 | } 159 | 160 | @Override 161 | public void treeWillExpand(TreeExpansionEvent e) throws ExpandVetoException { 162 | Point cursorPosition = MouseInfo.getPointerInfo().getLocation(); 163 | Point treePosition = tree.getLocationOnScreen(); 164 | int x = (int) (cursorPosition.getX() - treePosition.getX()); 165 | int y = (int) (cursorPosition.getY() - treePosition.getY()); 166 | TreePath path = tree.getPathForLocation(x, y); 167 | if (isOverCheckBox(x, y, path)) { 168 | throw new ExpandVetoException(e); 169 | } 170 | } 171 | 172 | @Override 173 | public void treeWillCollapse(TreeExpansionEvent e) throws ExpandVetoException { 174 | treeWillExpand(e); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/dialogs/WtMoreInfoDialog.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.dialogs; 20 | 21 | import java.awt.Color; 22 | import java.awt.Container; 23 | import java.awt.Dimension; 24 | import java.awt.Frame; 25 | import java.awt.GridBagConstraints; 26 | import java.awt.GridBagLayout; 27 | import java.awt.Image; 28 | import java.awt.Insets; 29 | import java.awt.Toolkit; 30 | import java.awt.event.WindowEvent; 31 | import java.awt.event.WindowFocusListener; 32 | import java.net.URL; 33 | import java.util.ResourceBundle; 34 | import javax.swing.BorderFactory; 35 | import javax.swing.BoxLayout; 36 | import javax.swing.JButton; 37 | import javax.swing.JDialog; 38 | import javax.swing.JPanel; 39 | import javax.swing.JScrollPane; 40 | import javax.swing.JTextPane; 41 | 42 | import org.languagetool.rules.Category; 43 | import org.languagetool.rules.Rule; 44 | import org.languagetool.rules.patterns.FalseFriendPatternRule; 45 | import org.writingtool.tools.WtGeneralTools; 46 | import org.writingtool.tools.WtMessageHandler; 47 | import org.writingtool.tools.WtOfficeTools; 48 | 49 | 50 | /** 51 | * A dialog with information about a special rule. 52 | * 53 | * @author Fred Kruse 54 | * @since 1.0 55 | */ 56 | public class WtMoreInfoDialog { 57 | 58 | private final JDialog dialog = new JDialog(); 59 | private final String title; 60 | private final String message; 61 | private final Rule rule; 62 | private final URL matchUrl; 63 | private final ResourceBundle messages; 64 | private final String lang; 65 | 66 | public WtMoreInfoDialog(String title, String message, Rule rule, URL matchUrl, ResourceBundle messages, String lang) { 67 | this.title = title; 68 | this.message = message; 69 | this.rule = rule; 70 | this.matchUrl = matchUrl; 71 | this.messages = messages; 72 | this.lang = lang; 73 | } 74 | 75 | public void show() { 76 | try { 77 | int dialogWidth = 320; 78 | JTextPane textPane = new JTextPane(); 79 | textPane.setEditable(false); 80 | textPane.setContentType("text/html"); 81 | textPane.setBorder(BorderFactory.createEmptyBorder()); 82 | textPane.setOpaque(false); 83 | textPane.setBackground(new Color(0, 0, 0, 0)); 84 | WtGeneralTools.addHyperlinkListener(textPane); 85 | textPane.setSize(dialogWidth, Short.MAX_VALUE); 86 | String messageWithBold = message.replaceAll("", "").replaceAll("", ""); 87 | String exampleSentences = WtGeneralTools.getExampleSentences(rule, messages); 88 | String url = "http://community.languagetool.org/rule/show/" + WtGeneralTools.encodeUrl(rule) 89 | + "?lang=" + lang + "&ref=standalone-gui"; 90 | boolean isExternal = rule.getCategory().getLocation() == Category.Location.EXTERNAL; 91 | String ruleDetailLink = rule instanceof FalseFriendPatternRule || isExternal ? 92 | "" : "" + messages.getString("ruleDetailsLink") +""; 93 | textPane.setText("" 94 | + messageWithBold + exampleSentences + WtGeneralTools.formatURL(matchUrl) 95 | + "

" 96 | + ruleDetailLink 97 | + ""); 98 | JScrollPane scrollPane = new JScrollPane(textPane); 99 | scrollPane.setPreferredSize( 100 | new Dimension(dialogWidth, textPane.getPreferredSize().height)); 101 | scrollPane.setBorder(BorderFactory.createEmptyBorder()); 102 | 103 | String cleanTitle = title.replace("", "'").replace("", "'"); 104 | 105 | dialog.setName(cleanTitle); 106 | dialog.setTitle(cleanTitle); 107 | dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 108 | Image ltImage = WtOfficeTools.getLtImage(); 109 | ((Frame) dialog.getOwner()).setIconImage(ltImage); 110 | 111 | dialog.addWindowFocusListener(new WindowFocusListener() { 112 | @Override 113 | public void windowGainedFocus(WindowEvent e) { 114 | } 115 | 116 | @Override 117 | public void windowLostFocus(WindowEvent e) { 118 | close(); 119 | } 120 | }); 121 | 122 | JButton close = new JButton(messages.getString("guiOOoCloseButton")); 123 | close.addActionListener(e -> { 124 | close(); 125 | }); 126 | 127 | JPanel infoPanel = new JPanel(); 128 | infoPanel.setLayout(new GridBagLayout()); 129 | GridBagConstraints cons = new GridBagConstraints(); 130 | cons.insets = new Insets(6, 0, 0, 15); 131 | cons.gridx = 0; 132 | cons.gridy = 0; 133 | cons.anchor = GridBagConstraints.WEST; 134 | cons.fill = GridBagConstraints.NONE; 135 | cons.weightx = 1.0f; 136 | cons.weighty = 1.0f; 137 | infoPanel.add(textPane, cons); 138 | 139 | JPanel closeButtonPanel = new JPanel(); 140 | closeButtonPanel.setLayout(new GridBagLayout()); 141 | cons = new GridBagConstraints(); 142 | cons.insets = new Insets(6, 12, 0, 15); 143 | cons.gridx = 0; 144 | cons.gridy = 0; 145 | cons.anchor = GridBagConstraints.EAST; 146 | cons.fill = GridBagConstraints.NONE; 147 | cons.weightx = 1.0f; 148 | cons.weighty = 1.0f; 149 | closeButtonPanel.add(close, cons); 150 | 151 | JPanel panel = new JPanel(); 152 | panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); 153 | panel.add(infoPanel); 154 | panel.add(closeButtonPanel); 155 | Container contentPane = dialog.getContentPane(); 156 | contentPane.setLayout(new GridBagLayout()); 157 | cons = new GridBagConstraints(); 158 | cons.insets = new Insets(8, 8, 8, 8); 159 | cons.gridx = 0; 160 | cons.gridy = 0; 161 | cons.weightx = 10.0f; 162 | cons.weighty = 10.0f; 163 | cons.fill = GridBagConstraints.BOTH; 164 | cons.anchor = GridBagConstraints.NORTHWEST; 165 | contentPane.add(panel, cons); 166 | dialog.pack(); 167 | Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 168 | Dimension frameSize = dialog.getSize(); 169 | dialog.setLocation(screenSize.width / 2 - frameSize.width / 2, 170 | screenSize.height / 2 - frameSize.height / 2); 171 | dialog.setLocationByPlatform(true); 172 | dialog.setAutoRequestFocus(true); 173 | dialog.setVisible(true); 174 | dialog.setAlwaysOnTop(true); 175 | dialog.toFront(); 176 | } catch (Throwable t) { 177 | WtMessageHandler.showError(t); 178 | } 179 | } 180 | 181 | public void close() { 182 | dialog.setVisible(false); 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/dialogs/WtOptionPane.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.dialogs; 20 | 21 | import java.awt.Color; 22 | import java.awt.Component; 23 | 24 | import javax.swing.JOptionPane; 25 | 26 | import org.writingtool.tools.WtMessageHandler; 27 | 28 | /** 29 | * simple panes for information and confirmation 30 | * (adapter for JOptionPane) 31 | * NOTE: JOptionPane does not work with FlatLight and FlatDark themes 32 | * @since 1.2 33 | * @author Fred Kruse 34 | */ 35 | public class WtOptionPane { 36 | 37 | public static final int OK_OPTION = JOptionPane.OK_OPTION; 38 | public static final int CANCEL_OPTION = JOptionPane.NO_OPTION; 39 | public static final int OK_CANCEL_OPTION = JOptionPane.OK_CANCEL_OPTION; 40 | public static final int QUESTION_MESSAGE = JOptionPane.QUESTION_MESSAGE; 41 | public static final int ERROR_MESSAGE = JOptionPane.ERROR_MESSAGE; 42 | public static final int INFORMATION_MESSAGE = JOptionPane.INFORMATION_MESSAGE; 43 | public static final int MESSAGE_BOX = 0; 44 | public static final int INPUT_BOX = 1; 45 | public static final Color DARK_FOREGROUND = new Color(0xbabab2); 46 | public static final Color DARK_BACKGROUND = new Color(0x3c3f41); 47 | public static final Color DARK_BUTTON_BACKGROUND = new Color(0x4e5052); 48 | public static final Color DARK_BORDER = new Color(0x565c5f); 49 | 50 | public static void showMessageDialog (Component parent, String msg) { 51 | try { 52 | JOptionPane.showMessageDialog(parent, msg); 53 | } catch (Exception e) { 54 | WtMessageHandler.printException(e); 55 | } 56 | } 57 | 58 | public static void showMessageDialog (Component parent, String msg, String title, int opt) { 59 | try { 60 | JOptionPane.showMessageDialog(parent, msg, title, opt); 61 | } catch (Exception e) { 62 | WtMessageHandler.printException(e); 63 | } 64 | } 65 | 66 | public static String showInputDialog(Component parent, Object msg, String title, int opt) { 67 | try { 68 | String txt = JOptionPane.showInputDialog(parent, msg, title, opt); 69 | return txt; 70 | } catch (Exception e) { 71 | WtMessageHandler.printException(e); 72 | } 73 | return null; 74 | } 75 | 76 | public static String showInputDialog(Component parent, String title, String initial) { 77 | try { 78 | String txt = JOptionPane.showInputDialog(parent, title, initial); 79 | return txt; 80 | } catch (Exception e) { 81 | WtMessageHandler.printException(e); 82 | } 83 | return null; 84 | } 85 | 86 | public static int showConfirmDialog (Component parent, String msg, String title, int opt) { 87 | try { 88 | int ret = JOptionPane.showConfirmDialog(parent, msg, title, opt); 89 | return ret; 90 | } catch (Exception e) { 91 | WtMessageHandler.printException(e); 92 | } 93 | return CANCEL_OPTION; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/languagedetectors/WtKhmerDetector.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.languagedetectors; 20 | 21 | /** 22 | * Helps to detect Khmer strings by their Unicode range. 23 | */ 24 | public 25 | class WtKhmerDetector extends WtUnicodeLanguageDetector { 26 | 27 | @Override 28 | protected boolean isInAlphabet(int numericValue) { 29 | return numericValue >= 6016 && numericValue <= 6143; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/languagedetectors/WtTamilDetector.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.languagedetectors; 20 | 21 | /** 22 | * Helps to detect Tamil strings by their Unicode range. 23 | * @since 1.0 24 | */ 25 | public 26 | class WtTamilDetector extends WtUnicodeLanguageDetector { 27 | 28 | @Override 29 | protected boolean isInAlphabet(int numericValue) { 30 | return numericValue >= 2946 && numericValue <= 3066; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/languagedetectors/WtUnicodeLanguageDetector.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.languagedetectors; 20 | 21 | /** 22 | * Helps to detect the language of strings by the Unicode range used by the characters. 23 | * @since 1.0 24 | */ 25 | public abstract class WtUnicodeLanguageDetector { 26 | 27 | private static final int MAX_CHECK_LENGTH = 100; 28 | 29 | protected abstract boolean isInAlphabet(int numericValue); 30 | 31 | public boolean isThisLanguage(String str) { 32 | int maxCheckLength = Math.min(str.length(), MAX_CHECK_LENGTH); 33 | for (int i = 0; i < maxCheckLength; i++) { 34 | int numericValue = str.charAt(i); 35 | if (isInAlphabet(numericValue)) { 36 | return true; 37 | } 38 | } 39 | return false; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/remote/CheckConfiguration.java: -------------------------------------------------------------------------------- 1 | /* LanguageTool, a natural language style checker 2 | * Copyright (C) 2016 Daniel Naber (http://www.danielnaber.de) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.remote; 20 | 21 | import java.util.List; 22 | import java.util.Objects; 23 | import java.util.Optional; 24 | 25 | import org.jetbrains.annotations.Nullable; 26 | 27 | /** 28 | * Configuration for checking a text with {@link RemoteLanguageTool}. 29 | * Use {@link CheckConfigurationBuilder} to create a configuration. 30 | * @since 3.4 31 | */ 32 | public class CheckConfiguration { 33 | 34 | private final String langCode; 35 | private final String motherTongueLangCode; 36 | private final boolean guessLanguage; 37 | private final List enabledRuleIds; 38 | private final boolean enabledOnly; 39 | private final List disabledRuleIds; 40 | private final String mode; 41 | private final String level; 42 | private final List ruleValues; 43 | @Nullable 44 | private final String textSessionID; 45 | @Nullable 46 | private final String username; 47 | @Nullable 48 | private final String apiKey; 49 | 50 | CheckConfiguration(String langCode, String motherTongueLangCode, boolean guessLanguage, List enabledRuleIds, boolean enabledOnly, 51 | List disabledRuleIds, String mode, String level, List ruleValues, String textSessionID, 52 | String username, String apiKey) { 53 | if (langCode == null && !guessLanguage) { 54 | throw new IllegalArgumentException("No language was set but language guessing was not activated either"); 55 | } 56 | if (langCode != null && guessLanguage) { 57 | throw new IllegalArgumentException("Language was set but language guessing was also activated"); 58 | } 59 | this.langCode = langCode; 60 | this.motherTongueLangCode = motherTongueLangCode; 61 | this.guessLanguage = guessLanguage; 62 | this.enabledRuleIds = Objects.requireNonNull(enabledRuleIds); 63 | this.enabledOnly = enabledOnly; 64 | this.disabledRuleIds = Objects.requireNonNull(disabledRuleIds); 65 | this.mode = mode; 66 | this.level = level; 67 | this.ruleValues = Objects.requireNonNull(ruleValues); 68 | this.textSessionID = textSessionID; 69 | this.username = username; 70 | this.apiKey = apiKey; 71 | } 72 | 73 | public Optional getLangCode() { 74 | return Optional.ofNullable(langCode); 75 | } 76 | 77 | public String getMotherTongueLangCode() { 78 | return motherTongueLangCode; 79 | } 80 | 81 | public boolean guessLanguage() { 82 | return guessLanguage; 83 | } 84 | 85 | public List getEnabledRuleIds() { 86 | return enabledRuleIds; 87 | } 88 | 89 | public boolean enabledOnly() { 90 | return enabledOnly; 91 | } 92 | 93 | public List getDisabledRuleIds() { 94 | return disabledRuleIds; 95 | } 96 | 97 | public String getMode() { 98 | return mode; 99 | } 100 | 101 | public String getLevel() { 102 | return level; 103 | } 104 | 105 | public List getRuleValues() { 106 | return ruleValues; 107 | } 108 | 109 | @Nullable 110 | public String getTextSessionID() { 111 | return textSessionID; 112 | } 113 | 114 | @Nullable 115 | public String getUsername() { 116 | return username; 117 | } 118 | 119 | @Nullable 120 | public String getAPIKey() { 121 | return apiKey; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/remote/CheckConfigurationBuilder.java: -------------------------------------------------------------------------------- 1 | /* LanguageTool, a natural language style checker 2 | * Copyright (C) 2016 Daniel Naber (http://www.danielnaber.de) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.remote; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import java.util.Objects; 25 | 26 | /** 27 | * Builder for a {@link CheckConfiguration}. 28 | * @since 3.4 29 | */ 30 | public class CheckConfigurationBuilder { 31 | 32 | private final String langCode; 33 | 34 | private String motherTongueLangCode; 35 | private boolean autoDetectLanguage; 36 | private boolean enabledOnly; 37 | private List enabledRuleIds = new ArrayList<>(); 38 | private List disabledRuleIds = new ArrayList<>(); 39 | private String mode = null; 40 | private String level = null; 41 | private List ruleValues = new ArrayList<>(); 42 | private String textSessionID = null; 43 | private String username = null; 44 | private String apiKey = null; 45 | 46 | /** 47 | * @param langCode a language code like {@code en} or {@code en-US} 48 | */ 49 | public CheckConfigurationBuilder(String langCode) { 50 | this.langCode = Objects.requireNonNull(langCode); 51 | } 52 | 53 | /** 54 | * A configuration that causes the server to automatically detected the text language. 55 | * Note that this requires at least a few sentences of text to work reliably. 56 | */ 57 | public CheckConfigurationBuilder() { 58 | this.langCode = null; 59 | this.autoDetectLanguage = true; 60 | } 61 | 62 | public CheckConfiguration build() { 63 | if (enabledOnly && enabledRuleIds.isEmpty()) { 64 | throw new IllegalStateException("You cannot use 'enabledOnly' when you haven't set rule ids to be enabled"); 65 | } 66 | return new CheckConfiguration(langCode, motherTongueLangCode, autoDetectLanguage, enabledRuleIds, enabledOnly, 67 | disabledRuleIds, mode, level, ruleValues, textSessionID, username, apiKey); 68 | } 69 | 70 | public CheckConfigurationBuilder setMotherTongueLangCode(String motherTongueLangCode) { 71 | this.motherTongueLangCode = motherTongueLangCode; 72 | return this; 73 | } 74 | 75 | public CheckConfigurationBuilder enabledRuleIds(List ruleIds) { 76 | this.enabledRuleIds = Objects.requireNonNull(ruleIds); 77 | return this; 78 | } 79 | 80 | public CheckConfigurationBuilder enabledRuleIds(String... ruleIds) { 81 | return enabledRuleIds(Arrays.asList(ruleIds)); 82 | } 83 | 84 | public CheckConfigurationBuilder enabledOnly() { 85 | this.enabledOnly = true; 86 | return this; 87 | } 88 | 89 | public CheckConfigurationBuilder disabledRuleIds(List ruleIds) { 90 | this.disabledRuleIds = Objects.requireNonNull(ruleIds); 91 | return this; 92 | } 93 | 94 | public CheckConfigurationBuilder disabledRuleIds(String... ruleIds) { 95 | return disabledRuleIds(Arrays.asList(ruleIds)); 96 | } 97 | 98 | public CheckConfigurationBuilder mode(String mode) { 99 | this.mode = mode; 100 | return this; 101 | } 102 | 103 | public CheckConfigurationBuilder level(String level) { 104 | this.level = level; 105 | return this; 106 | } 107 | 108 | public CheckConfigurationBuilder ruleValues(List ruleValues) { 109 | this.ruleValues = Objects.requireNonNull(ruleValues); 110 | return this; 111 | } 112 | 113 | public CheckConfigurationBuilder textSessionID(String textSessionID) { 114 | this.textSessionID = textSessionID; 115 | return this; 116 | } 117 | 118 | public CheckConfigurationBuilder username(String username) { 119 | this.username = username; 120 | return this; 121 | } 122 | 123 | public CheckConfigurationBuilder apiKey(String apiKey) { 124 | this.apiKey = apiKey; 125 | return this; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/remote/RemoteConfigurationInfo.java: -------------------------------------------------------------------------------- 1 | /* LanguageTool, a natural language style checker 2 | * Copyright (C) 2016 Daniel Naber (http://www.danielnaber.de) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.remote; 20 | 21 | import com.fasterxml.jackson.databind.ObjectMapper; 22 | 23 | import java.io.*; 24 | import java.util.List; 25 | import java.util.Map; 26 | 27 | /** 28 | * Check a text using a remote LanguageTool server via HTTP or HTTPS. 29 | * Our public HTTPS API and its restrictions are documented 30 | * here. 31 | * @since 4.8 32 | */ 33 | public class RemoteConfigurationInfo { 34 | 35 | private final int maxTextLength; 36 | private final Map softwareInfo; 37 | private final List> rules; 38 | 39 | @SuppressWarnings("unchecked") 40 | RemoteConfigurationInfo(ObjectMapper mapper, InputStream inputStream) throws IOException { 41 | Map map = mapper.readValue(inputStream, Map.class); 42 | softwareInfo = (Map) map.get("software"); 43 | Map parameter = (Map) map.get("parameter"); 44 | maxTextLength = (int)parameter.get("maxTextLength"); 45 | rules = (List>) map.get("rules"); 46 | } 47 | 48 | public Map getSoftwareInfo() { 49 | return softwareInfo; 50 | } 51 | 52 | public int getMaxTextLength() { 53 | return maxTextLength; 54 | } 55 | 56 | public List> getRemoteRules() { 57 | return rules; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/remote/RemoteIgnoreRange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * LanguageTool, a natural language style checker 3 | * Copyright (c) 2022. Stefan Viol (https://stevio.de) 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 18 | * USA 19 | */ 20 | 21 | package org.writingtool.remote; 22 | 23 | public class RemoteIgnoreRange { 24 | 25 | private int from; 26 | private int to; 27 | private String languageCode; 28 | 29 | public RemoteIgnoreRange(int from, int to, String languageCode) { 30 | this.from = from; 31 | this.to = to; 32 | this.languageCode = languageCode; 33 | } 34 | 35 | public int getFrom() { 36 | return from; 37 | } 38 | 39 | public void setFrom(int from) { 40 | this.from = from; 41 | } 42 | 43 | public int getTo() { 44 | return to; 45 | } 46 | 47 | public void setTo(int to) { 48 | this.to = to; 49 | } 50 | 51 | public String getLanguageCode() { 52 | return languageCode; 53 | } 54 | 55 | public void setLanguageCode(String languageCode) { 56 | this.languageCode = languageCode; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/remote/RemoteResult.java: -------------------------------------------------------------------------------- 1 | /* LanguageTool, a natural language style checker 2 | * Copyright (C) 2016 Daniel Naber (http://www.danielnaber.de) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.remote; 20 | 21 | import org.jetbrains.annotations.Nullable; 22 | import java.util.Collections; 23 | import java.util.List; 24 | import java.util.Objects; 25 | 26 | /** 27 | * The result of checking text on a remote LanguageTool server. 28 | * @since 3.4 29 | */ 30 | public class RemoteResult { 31 | 32 | private final String language; 33 | private final String languageCode; 34 | private final String languageDetectedCode; 35 | private final String languageDetectedName; 36 | private final List matches; 37 | private final List ignoreRanges; 38 | private final RemoteServer remoteServer; 39 | 40 | RemoteResult(String language, String languageCode, @Nullable String languageDetectedCode, @Nullable String languageDetectedName, List matches, List ignoreRanges, RemoteServer remoteServer) { 41 | this.language = Objects.requireNonNull(language); 42 | this.languageCode = Objects.requireNonNull(languageCode); 43 | this.languageDetectedCode = languageDetectedCode; 44 | this.languageDetectedName = languageDetectedName; 45 | this.matches = Collections.unmodifiableList(Objects.requireNonNull(matches)); 46 | this.ignoreRanges = ignoreRanges; 47 | this.remoteServer = Objects.requireNonNull(remoteServer); 48 | } 49 | 50 | public List getMatches() { 51 | return matches; 52 | } 53 | 54 | public String getLanguage() { 55 | return language; 56 | } 57 | 58 | public String getLanguageCode() { 59 | return languageCode; 60 | } 61 | 62 | public RemoteServer getRemoteServer() { 63 | return remoteServer; 64 | } 65 | 66 | /** 67 | * @since 4.3 68 | */ 69 | @Nullable 70 | public String getLanguageDetectedCode() { 71 | return languageDetectedCode; 72 | } 73 | 74 | /** 75 | * @since 4.3 76 | */ 77 | @Nullable 78 | public String getLanguageDetectedName() { 79 | return languageDetectedName; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return matches.toString(); 85 | } 86 | 87 | public List getIgnoreRanges() { 88 | return ignoreRanges; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/remote/RemoteRuleMatch.java: -------------------------------------------------------------------------------- 1 | /* LanguageTool, a natural language style checker 2 | * Copyright (C) 2016 Daniel Naber (http://www.danielnaber.de) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.remote; 20 | 21 | import java.util.Collections; 22 | import java.util.List; 23 | import java.util.Objects; 24 | import java.util.Optional; 25 | 26 | /** 27 | * A potential error as returned by the HTTP API of LanguageTool. 28 | * @since 3.4 29 | */ 30 | public class RemoteRuleMatch { 31 | 32 | private final String ruleId; 33 | private final String ruleDescription; 34 | private final String msg; 35 | private final String context; 36 | private final int contextOffset; 37 | private final int offset; 38 | private final int errorLength; 39 | 40 | private String subId; 41 | private String shortMsg; 42 | private List replacements; 43 | private String url; 44 | private String category; 45 | private String categoryId; 46 | private String locQualityIssueType; 47 | 48 | RemoteRuleMatch(String ruleId, String ruleDescription, String msg, String context, int contextOffset, int offset, int errorLength) { 49 | this.ruleId = Objects.requireNonNull(ruleId); 50 | this.ruleDescription = ruleDescription; 51 | this.msg = Objects.requireNonNull(msg); 52 | this.context = Objects.requireNonNull(context); 53 | this.contextOffset = contextOffset; 54 | this.offset = offset; 55 | this.errorLength = errorLength; 56 | } 57 | 58 | /** Unique (per language) identifier for the error. */ 59 | public String getRuleId() { 60 | return ruleId; 61 | } 62 | 63 | /** Description of the rule. */ 64 | public String getRuleDescription() { 65 | return ruleDescription; 66 | } 67 | 68 | /** Optional sub id (rule groups have a sub id for each rule). */ 69 | public Optional getRuleSubId() { 70 | return Optional.ofNullable(subId); 71 | } 72 | 73 | /** A text describing the error to the user. */ 74 | public String getMessage() { 75 | return msg; 76 | } 77 | 78 | /** Optional short message describing the error. */ 79 | public Optional getShortMessage() { 80 | return Optional.ofNullable(shortMsg); 81 | } 82 | 83 | /** 84 | * Potential corrections for the error. Note that corrections might be wrong and 85 | * they are not necessarily ordered by quality. 86 | */ 87 | public Optional> getReplacements() { 88 | return Optional.ofNullable(replacements); 89 | } 90 | 91 | /** The error in its context. See {@link #getContextOffset()} and {@link #getErrorLength()} to get the exact position. */ 92 | public String getContext() { 93 | return context; 94 | } 95 | 96 | /** The character position of the error start inside the result of {@link #getContext()}. */ 97 | public int getContextOffset() { 98 | return contextOffset; 99 | } 100 | 101 | /** The character position where the error starts. */ 102 | public int getErrorOffset() { 103 | return offset; 104 | } 105 | 106 | /** The length of the error in characters. */ 107 | public int getErrorLength() { 108 | return errorLength; 109 | } 110 | 111 | /** URL with a more detailed explanation of the error. */ 112 | public Optional getUrl() { 113 | return Optional.ofNullable(url); 114 | } 115 | 116 | /** The error's category. */ 117 | public Optional getCategory() { 118 | return Optional.of(category); 119 | } 120 | 121 | /** The id of the error's category. */ 122 | public Optional getCategoryId() { 123 | return Optional.of(categoryId); 124 | } 125 | 126 | public Optional getLocQualityIssueType() { 127 | return Optional.ofNullable(locQualityIssueType); 128 | } 129 | 130 | // 131 | // non-public setters 132 | // 133 | 134 | void setRuleSubId(String subId) { 135 | this.subId = subId; 136 | } 137 | 138 | void setShortMsg(String shortMsg) { 139 | this.shortMsg = shortMsg; 140 | } 141 | 142 | void setReplacements(List replacements) { 143 | this.replacements = Collections.unmodifiableList(replacements); 144 | } 145 | 146 | void setUrl(String url) { 147 | this.url = url; 148 | } 149 | 150 | void setCategory(String category) { 151 | this.category = category; 152 | } 153 | 154 | void setCategoryId(String categoryId) { 155 | this.categoryId = categoryId; 156 | } 157 | 158 | void setLocQualityIssueType(String locQualityIssueType) { 159 | this.locQualityIssueType = locQualityIssueType; 160 | } 161 | 162 | @Override 163 | public String toString() { 164 | return ruleId + "@" + offset + "-" + (offset + errorLength); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/remote/RemoteServer.java: -------------------------------------------------------------------------------- 1 | /* LanguageTool, a natural language style checker 2 | * Copyright (C) 2016 Daniel Naber (http://www.danielnaber.de) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.remote; 20 | 21 | import java.util.Objects; 22 | import java.util.Optional; 23 | 24 | /** 25 | * Information about the remote server as returned by the server's XML response. 26 | * @since 3.4 27 | */ 28 | public class RemoteServer { 29 | 30 | private final String software; 31 | private final String version; 32 | private final String buildDate; 33 | 34 | RemoteServer(String software, String version, String buildDate) { 35 | this.software = Objects.requireNonNull(software); 36 | this.version = Objects.requireNonNull(version); 37 | this.buildDate = buildDate; 38 | } 39 | 40 | /** 41 | * @return the software running on the server, usually {@code LanguageTool} 42 | */ 43 | public String getSoftware() { 44 | return software; 45 | } 46 | 47 | /** 48 | * @return the version running on the server, might be something like {@code 3.4-SNAPSHOT} or {@code 3.4} 49 | */ 50 | public String getVersion() { 51 | return version; 52 | } 53 | 54 | /** 55 | * @return the build date of the version or null (in case this isn't a real build but runs in an IDE etc.) 56 | */ 57 | public Optional getBuildDate() { 58 | return Optional.ofNullable(buildDate); 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return software + "/" + version + "/" + buildDate; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/sidebar/WtSidebarFactory.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | 20 | package org.writingtool.sidebar; 21 | 22 | import com.sun.star.awt.XWindow; 23 | import com.sun.star.beans.PropertyValue; 24 | import com.sun.star.container.NoSuchElementException; 25 | import com.sun.star.lang.XServiceInfo; 26 | import com.sun.star.lib.uno.helper.WeakBase; 27 | import com.sun.star.ui.XUIElement; 28 | import com.sun.star.ui.XUIElementFactory; 29 | import com.sun.star.uno.UnoRuntime; 30 | import com.sun.star.uno.XComponentContext; 31 | 32 | /** 33 | * Factory for the the WritingTool sidebar. 34 | * 35 | * @since 1.3 36 | * @author Fred Kruse 37 | */ 38 | public class WtSidebarFactory extends WeakBase implements XUIElementFactory, XServiceInfo { 39 | 40 | public static final String SERVICE_NAME = "org.writingtool.sidebar.WtSidebarFactory"; 41 | 42 | private XComponentContext xContext; 43 | 44 | public WtSidebarFactory(XComponentContext context) { 45 | xContext = context; 46 | } 47 | 48 | public static String[] getServiceNames() { 49 | return new String[] { SERVICE_NAME }; 50 | } 51 | 52 | @Override 53 | public XUIElement createUIElement(String resourceUrl, PropertyValue[] arguments) throws NoSuchElementException { 54 | if (!resourceUrl.startsWith("private:resource/toolpanel/WtSidebarFactory")) { 55 | throw new NoSuchElementException(resourceUrl, this); 56 | } 57 | 58 | XWindow parentWindow = null; 59 | for (int i = 0; i < arguments.length; i++) { 60 | if (arguments[i].Name.equals("ParentWindow")) { 61 | parentWindow = UnoRuntime.queryInterface(XWindow.class, arguments[i].Value); 62 | break; 63 | } 64 | } 65 | 66 | return new WtSidebarPanel(xContext, parentWindow, resourceUrl); 67 | } 68 | 69 | @Override 70 | public String getImplementationName() { 71 | return this.getClass().getName(); 72 | } 73 | 74 | @Override 75 | public String[] getSupportedServiceNames() { 76 | return new String[] { SERVICE_NAME }; 77 | } 78 | 79 | @Override 80 | public boolean supportsService(String serviceName) { 81 | for (final String supportedServiceName : getSupportedServiceNames()) { 82 | if (supportedServiceName.equals(serviceName)) { 83 | return true; 84 | } 85 | } 86 | return false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/sidebar/WtSidebarPanel.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | 20 | package org.writingtool.sidebar; 21 | 22 | import com.sun.star.awt.XWindow; 23 | import com.sun.star.frame.XFrame; 24 | import com.sun.star.lang.XComponent; 25 | import com.sun.star.lib.uno.helper.ComponentBase; 26 | import com.sun.star.ui.UIElementType; 27 | import com.sun.star.ui.XToolPanel; 28 | import com.sun.star.ui.XUIElement; 29 | import com.sun.star.uno.UnoRuntime; 30 | import com.sun.star.uno.XComponentContext; 31 | 32 | /** 33 | * WT sidebar panel 34 | * @since 1.3 35 | * @author Fred Kruse 36 | */ 37 | public class WtSidebarPanel extends ComponentBase implements XUIElement { 38 | 39 | private final String resourceUrl; 40 | private XToolPanel panel; 41 | 42 | public WtSidebarPanel(XComponentContext context, XWindow parentWindow, String resourceUrl) { 43 | this.resourceUrl = resourceUrl; 44 | panel = new WtSidebarContent(context, parentWindow); 45 | } 46 | 47 | @Override 48 | public XFrame getFrame() { 49 | return null; 50 | } 51 | 52 | @Override 53 | public Object getRealInterface() { 54 | return panel; 55 | } 56 | 57 | @Override 58 | public String getResourceURL() { 59 | return resourceUrl; 60 | } 61 | 62 | @Override 63 | public short getType() { 64 | return UIElementType.TOOLPANEL; 65 | } 66 | 67 | @Override 68 | public void dispose() 69 | { 70 | XComponent xPanelComponent = UnoRuntime.queryInterface(XComponent.class, panel); 71 | if (xPanelComponent != null) { 72 | xPanelComponent.dispose(); 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/tools/WtResourceBundle.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.tools; 20 | 21 | import java.util.Enumeration; 22 | import java.util.MissingResourceException; 23 | import java.util.ResourceBundle; 24 | 25 | /** 26 | * A resource bundle that uses the bundles in the following order 27 | * 1. WT resource bundle 28 | * 2. LT resource bundle 29 | * 3. LT fallback bundle 30 | * 31 | * @since 1.0 32 | * @author Fred Kruse 33 | */ 34 | public class WtResourceBundle extends ResourceBundle { 35 | 36 | private final ResourceBundle wtBundle; 37 | private final ResourceBundle wtFallbackBundle; 38 | private final ResourceBundle bundle; 39 | private final ResourceBundle fallbackBundle; 40 | 41 | public WtResourceBundle(ResourceBundle wtBundle, ResourceBundle wtFallbackBundle, 42 | ResourceBundle bundle, ResourceBundle fallbackBundle) { 43 | this.wtBundle = wtBundle; 44 | this.wtFallbackBundle = wtFallbackBundle; 45 | this.bundle = bundle; 46 | this.fallbackBundle = fallbackBundle; 47 | } 48 | 49 | @Override 50 | public Object handleGetObject(String key) { 51 | String s = null; 52 | if (wtBundle != null) { 53 | try { 54 | s = wtBundle.getString(key); 55 | } catch (MissingResourceException e) { 56 | } 57 | } 58 | if (s == null || s.trim().isEmpty()) { 59 | if (bundle != null) { 60 | try { 61 | s = bundle.getString(key); 62 | } catch (MissingResourceException e) { 63 | } 64 | } 65 | if (s == null || s.trim().isEmpty()) { 66 | try { 67 | s = wtFallbackBundle.getString(key); 68 | } catch (MissingResourceException e) { 69 | return fallbackBundle.getString(key); 70 | } 71 | } 72 | return s; 73 | } 74 | return s; 75 | } 76 | 77 | @Override 78 | public Enumeration getKeys() { 79 | return bundle.getKeys(); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/writingtool/tools/WtVersionInfo.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool.tools; 20 | 21 | import java.io.BufferedReader; 22 | import java.io.File; 23 | import java.io.FileInputStream; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.InputStreamReader; 27 | import java.net.URL; 28 | import java.net.URLDecoder; 29 | import java.nio.charset.StandardCharsets; 30 | 31 | import org.languagetool.JLanguageTool; 32 | 33 | import com.sun.star.beans.PropertyValue; 34 | import com.sun.star.container.XNameAccess; 35 | import com.sun.star.lang.XMultiServiceFactory; 36 | import com.sun.star.uno.UnoRuntime; 37 | import com.sun.star.uno.XComponentContext; 38 | 39 | /** 40 | * class to get information about the application and the environment 41 | * @since 1.1 42 | * @author Fred Kruse 43 | */ 44 | public class WtVersionInfo { 45 | public static String wtName = null; 46 | public static String wtVersion; 47 | public static String wtBuildDate; 48 | public static String ltName; 49 | public static String ltVersion; 50 | public static String ltBuildDate; 51 | public static String ltShortGitId; 52 | public static String ooName; 53 | public static String ooVersion; 54 | public static String ooExtension; 55 | public static String ooVendor; 56 | public static String ooLocale; 57 | public static String osArch; 58 | public static String javaVersion; 59 | public static String javaVendor; 60 | public static IOException ioEx; 61 | public static Throwable thEx; 62 | 63 | public static void init(XComponentContext xContext) { 64 | setWtInfo(); 65 | setLtInfo(); 66 | setOfficeProductInfo(xContext); 67 | setJavaInfo(); 68 | } 69 | 70 | /** 71 | * Get information about WritingTool 72 | */ 73 | public static String getWtInformation () { 74 | String txt = wtVersion; 75 | if (wtVersion != null && wtVersion.contains("SNAPSHOT")) { 76 | txt += " - " + wtBuildDate; 77 | } 78 | return txt; 79 | } 80 | 81 | /** 82 | * Get name and information about WritingTool 83 | */ 84 | public static String getWtNameWithInformation () { 85 | return wtName + " " + getWtInformation(); 86 | } 87 | 88 | /** 89 | * get LanguageTool version 90 | * NOTE: The recommended method doesn't work in WritingTool 91 | */ 92 | public static String ltVersion() { 93 | return ltVersion; 94 | } 95 | 96 | /** 97 | * get LanguageTool build date 98 | * NOTE: The recommended method doesn't work in WritingTool 99 | */ 100 | public static String ltBuildDate() { 101 | return ltBuildDate; 102 | } 103 | 104 | /** 105 | * get LanguageTool short git id 106 | * NOTE: The recommended method doesn't work in WritingTool 107 | */ 108 | public static String ltShortGitId() { 109 | return ltShortGitId; 110 | } 111 | 112 | /** 113 | * Get information about LanguageTool 114 | */ 115 | public static String getLtInformation () { 116 | String txt = ltVersion(); 117 | if (txt.contains("SNAPSHOT")) { 118 | txt += " - " + ltBuildDate() + ", " + ltShortGitId(); 119 | } 120 | return txt; 121 | } 122 | 123 | /** 124 | * Set WT version and build date from version file 125 | */ 126 | private static void setWtInfo() { 127 | WtOfficeTools wtTools = new WtOfficeTools(); 128 | URL resource = wtTools.getClass().getResource(wtTools.getClass().getSimpleName() + ".class"); 129 | if (resource != null) { 130 | try { 131 | String dir = resource.getPath(); 132 | dir = dir.substring(5, dir.indexOf("!")); // get jar file 133 | dir = dir.substring(0, dir.lastIndexOf("/")); // get directory 134 | dir = URLDecoder.decode(dir, "UTF-8"); // decode URL 135 | File vFile = new File(dir, "version.txt"); 136 | try (InputStream stream = new FileInputStream(vFile); 137 | InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8); 138 | BufferedReader br = new BufferedReader(reader) 139 | ) { 140 | String line; 141 | while ((line = br.readLine()) != null) { 142 | String lines[] = line.split("="); 143 | if(lines.length > 1) { 144 | if ("version".equals(lines[0].trim())) { 145 | wtVersion = new String(lines[1].trim()); 146 | } else if ("build.date".equals(lines[0].trim())) { 147 | wtBuildDate = new String(lines[1].trim()); 148 | } 149 | } 150 | } 151 | } catch (IOException e) { 152 | ioEx = e; 153 | } 154 | } catch (Throwable e1) { 155 | thEx = e1; 156 | } 157 | } 158 | wtName = WtOfficeTools.WT_NAME; 159 | } 160 | 161 | /** 162 | * Set LT Information 163 | */ 164 | @SuppressWarnings("deprecation") 165 | private static void setLtInfo() { 166 | ltName = "LanguageTool"; 167 | ltVersion = JLanguageTool.VERSION; 168 | ltBuildDate = JLanguageTool.BUILD_DATE; 169 | ltShortGitId = JLanguageTool.GIT_SHORT_ID; 170 | } 171 | 172 | /** 173 | * Set information of LO/OO office product from system 174 | */ 175 | private static void setOfficeProductInfo(XComponentContext xContext) { 176 | try { 177 | if (xContext == null) { 178 | return; 179 | } 180 | XMultiServiceFactory xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, xContext.getServiceManager()); 181 | if (xMSF == null) { 182 | WtMessageHandler.printToLogFile("XMultiServiceFactory == null"); 183 | return; 184 | } 185 | Object oConfigProvider = xMSF.createInstance("com.sun.star.configuration.ConfigurationProvider"); 186 | XMultiServiceFactory confMsf = UnoRuntime.queryInterface(XMultiServiceFactory.class, oConfigProvider); 187 | if (oConfigProvider == null) { 188 | WtMessageHandler.printToLogFile("oConfigProvider == null"); 189 | return; 190 | } 191 | 192 | final String sView = "com.sun.star.configuration.ConfigurationAccess"; 193 | 194 | Object args[] = new Object[1]; 195 | PropertyValue aPathArgument = new PropertyValue(); 196 | aPathArgument.Name = "nodepath"; 197 | aPathArgument.Value = "org.openoffice.Setup/Product"; 198 | args[0] = aPathArgument; 199 | Object oConfigAccess = confMsf.createInstanceWithArguments(sView, args); 200 | XNameAccess xName = UnoRuntime.queryInterface(XNameAccess.class, oConfigAccess); 201 | 202 | aPathArgument.Value = "org.openoffice.Setup/L10N"; 203 | Object oConfigAccess1 = confMsf.createInstanceWithArguments(sView, args); 204 | XNameAccess xName1 = UnoRuntime.queryInterface(XNameAccess.class, oConfigAccess1); 205 | if (xName != null) { 206 | ooName = (String) xName.getByName("ooName"); 207 | ooVersion = (String) xName.getByName("ooSetupVersion"); 208 | ooExtension = (String) xName.getByName("ooSetupExtension"); 209 | ooVendor = (String) xName.getByName("ooVendor"); 210 | } 211 | if (xName1 != null) { 212 | ooLocale = (String) xName1.getByName("ooLocale"); 213 | } 214 | osArch = System.getProperty("os.arch"); 215 | } catch (Throwable t) { 216 | WtMessageHandler.printException(t); // all Exceptions thrown by UnoRuntime.queryInterface are caught 217 | } 218 | } 219 | 220 | private static void setJavaInfo() { 221 | javaVersion = System.getProperty("java.version"); 222 | javaVendor = System.getProperty("java.vm.vendor"); 223 | } 224 | 225 | 226 | } 227 | -------------------------------------------------------------------------------- /src/main/resources/Accelerators.xcu: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | service:org.writingtool.WritingTool?checkDialog 10 | 11 | 12 | 13 | 14 | service:org.writingtool.WritingTool?checkAgainDialog 15 | 16 | 17 | 18 | 19 | 20 | 21 | service:org.writingtool.WritingTool?checkDialog 22 | 23 | 24 | 25 | 26 | service:org.writingtool.WritingTool?checkAgainDialog 27 | 28 | 29 | 30 | 31 | 32 | 33 | service:org.writingtool.WritingTool?checkDialog 34 | 35 | 36 | 37 | 38 | service:org.writingtool.WritingTool?checkAgainDialog 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/main/resources/CalcWindowState.xcu: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | WritingTool 12 | 13 | 14 | //org.openoffice.writingtool.oxt/images/WTBig.png 15 | 16 | 17 | 1,0 18 | 19 | 20 | true 21 | 22 | 23 | 0 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/resources/Factories.xcu: -------------------------------------------------------------------------------- 1 | 2 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | toolpanel 36 | 37 | 38 | WtSidebarFactory 39 | 40 | 41 | 42 | 43 | 44 | org.writingtool.sidebar.WtSidebarFactory 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/resources/ImpressWindowState.xcu: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | WritingTool 12 | 13 | 14 | //org.openoffice.writingtool.oxt/images/WTBig.png 15 | 16 | 17 | 1,0 18 | 19 | 20 | true 21 | 22 | 23 | 0 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/resources/Linguistic.xcu: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 10 | 11 | en de-LU de-LI de-BE pl-PL fr-FR fr fr-BE fr-CH fr-CA fr-LU fr-MC fr-CM fr-CI fr-HT fr-ML fr-SN fr-CD fr-MA fr-RE es-ES es es-MX es-GT es-CR es-PA es-DO es-VE es-PE es-AR es-EC es-CL es-UY es-PY es-BO es-SV es-HN es-NI es-PR es-US es-CU it-IT it-CH km-KH nl-NL nl-BE uk-UA ru-RU sk-SK sl-SI sv-SE sv-FI ro-RO gl-ES ca-ES ca-ES-valencia da-DK be-BY eo zh-CN ast-ES tl-PH br-FR el-GR en-US en-GB en-CA en-ZA en-NZ en-AU de-DE de-AT de-CH pt-AO pt-MZ pt-PT pt-BR ja-JP ta-IN sr sr-RS sr-BA sr-HR sr-ME ar ar-DZ ga-IE 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | org.writingtool.WritingTool.Images 22 | 23 | 24 | 25 | 26 | 27 | 28 | %origin%/images/dialog.png 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/resources/README.txt: -------------------------------------------------------------------------------- 1 | WritingTool (a LibreOffice Extension based on LanguageTool) 2 | 3 | Copyright (C) 2024 Fred Kruse (https://writingtool.org) 4 | 5 | See https://writingtool.org for more information 6 | -------------------------------------------------------------------------------- /src/main/resources/Sidebar.xcu: -------------------------------------------------------------------------------- 1 | 2 | 24 | 31 | 32 | 33 | 34 | 35 | WritingTool 36 | 37 | 38 | ToolsDeck 39 | 40 | 41 | vnd.sun.star.extension://org.openoffice.writingtool.oxt/images/WTBig.png 42 | 43 | 44 | 45 | WriterVariants, any, visible ; 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | WritingTool 54 | 55 | 56 | WtSidebarPanel 57 | 58 | 59 | ToolsDeck 60 | 61 | 62 | 63 | WriterVariants, any, visible ; 64 | 65 | 66 | 67 | private:resource/toolpanel/WtSidebarFactory/WtSidebarPanel 68 | 69 | 70 | 100 71 | 72 | 73 | false 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/main/resources/WriterWindowState.xcu: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | WritingTool 12 | 13 | 14 | //org.openoffice.writingtool.oxt/images/WTBig.png 15 | 16 | 17 | 1,0 18 | 19 | 20 | true 21 | 22 | 23 | 0 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/resources/description.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | WritingTool 13 | WritingTool 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | WritingTool 43 | WritingTool 44 | WritingTool 45 | WritingTool 46 | WritingTool 47 | WritingTool 48 | WritingTool 49 | WritingTool 50 | WritingTool 51 | WritingTool 52 | 53 | WritingTool 54 | WritingTool 55 | WritingTool 56 | WritingTool 57 | WritingTool 58 | WritingTool 59 | WritingTool 60 | WritingTool 61 | WritingTool 62 | WritingTool 63 | WritingTool 64 | WritingTool 65 | WritingTool 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/main/resources/description/desc_de.txt: -------------------------------------------------------------------------------- 1 | WritingTool Ihr Schreibassistent. 2 | Basierend auf LanguageTool (Grammatik-, Stil- und Rechtschreibprüfung für mehr als 25 Sprachen). 3 | -------------------------------------------------------------------------------- /src/main/resources/description/desc_en.txt: -------------------------------------------------------------------------------- 1 | WritingTool your writing assistant. 2 | Based on LanguageTool (grammar, style and spelling checker for more than 25 languages). -------------------------------------------------------------------------------- /src/main/resources/description/desc_es.txt: -------------------------------------------------------------------------------- 1 | WritingTool, tu asistente de escritura. 2 | Basado en LanguageTool (corrector de gramática, estilo y ortografía para más de 25 idiomas). -------------------------------------------------------------------------------- /src/main/resources/description/desc_fr.txt: -------------------------------------------------------------------------------- 1 | WritingTool, votre assistant d'écriture. 2 | Basé sur LanguageTool (correcteur de grammaire, style et orthographe pour plus de 25 langues). -------------------------------------------------------------------------------- /src/main/resources/description/desc_hu.txt: -------------------------------------------------------------------------------- 1 | Íróeszköz az írósegéd. 2 | Nyelveszköz (nyelvtani, stílus- és helyesírás-ellenőrző több mint 25 nyelvhez) alapján. 3 | -------------------------------------------------------------------------------- /src/main/resources/description/desc_pt-BR.txt: -------------------------------------------------------------------------------- 1 | WritingTool, seu assistente de escrita. 2 | Baseado no LanguageTool (verificador de gramática, estilo e ortografia para mais de 25 idiomas). -------------------------------------------------------------------------------- /src/main/resources/description/desc_pt.txt: -------------------------------------------------------------------------------- 1 | WritingTool, o seu assistente de escrita. 2 | Baseado no LanguageTool (verificador de gramática, estilo e ortografia para mais de 25 idiomas). -------------------------------------------------------------------------------- /src/main/resources/help/en/help.tree: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LanguageTool - language checker 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/help/en/org.openoffice.languagetool.oxt/0100000.xhp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LanguageTool is a proof­reading service. 6 | /org.openoffice.languagetool.oxt/0100000.xhp 7 | 8 | 9 | 10 | 11 | 12 | LanguageTool is a proof­reading service. 13 | 14 | 15 | 16 | An Open Source style and grammar checker for English, French, German, Polish, Dutch, Romanian, Russian and other languages. This is a rule-based proof­reading service that will find errors for which a rule is defined in its XML configuration files. Rules for more complicated errors can be written in Java. You can think of LanguageTool as a tool to detect errors that a simple spell checker cannot detect, e.g. mixing up there/their, no/now etc. It can also detect some grammar mistakes. It does not include spell checking for OpenOffice.org/LibreOffice version. 17 | 18 | 19 | LanguageTool will only find errors for which a rule is defined in its XML configuration files. Rules for more complicated errors can be written in Java. 20 | 21 | 22 | Requires Java 8+. We strongly recommend using LibreOffice 3.5.4 or Apache OpenOffice 3.4.1 or later as older versions have a bug that causes a freeze on startup. You need to restart OpenOffice.org/LibreOffice after installation of this extension. 23 | 24 | 25 | You can select required grammar rules in Tools -> LanguageTool -> Configuration menu. 26 | 27 | 28 | If you are using LibreOffice 3.5.x or later and you want to check English texts: Use Options -> Language Settings -> Writing Aids -> Edit... to disable LightProof and enable LanguageTool for English 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/resources/help/ru/help.tree: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LanguageTool – проверка грамматики 5 | Конфигурация LanguageTool 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/help/ru/org.openoffice.languagetool.oxt/0100000.xhp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Проверка грамматики - LanguageTool 6 | /org.openoffice.languagetool.oxt/0100000.xhp 7 | 8 | 9 | 10 | 11 | 12 | LanguageTool — расширение LibreOffice/OpenOffice для проверки грамматики. 13 | 14 | 15 | LanguageTool — это свободное программное обеспечение с открытым исходным кодом для проверки грамматики, пунктуации и стиля русского, немецкого, английского, польского, французского и других языков. 16 | LanguageTool находит ошибки, которые не могут быть обнаружены системой проверки орфографии по словарю. 17 | 18 | 19 | 20 | LanguageTool ищет ошибки на основе грамматических (языковых) правил, которые заданы в XML - файлах. Более сложные правила реализованы на Java. Версия LanguageTool для OpenOffice.org/LibreOffice не предназначена для проверки орфографии. 21 | 22 | 23 | Системные требования: Java 8+. Настоятельно рекомендуется использовать как минимум Apache OpenOffice 3.4.1 или LibreOffice 3.5.4, так как их более старые версии содержат ошибку, приводящую к медленному запуску офисного пакета. После установки расширения обязательно перезапустите OpenOffice.org/LibreOffice (включая и быстрый запуск). 24 | 25 | 26 | LanguageTool может проверять текст в режиме ручной и автоматической проверки. В автоматическом режиме программа подчёркивает обнаруженные ошибки в тексте синей волнистой линией. 27 | 28 | 29 | Выбрать грамматические правила, используемые при проверке текста, можно в меню Сервис -> Грамматика - LanguageTool -> Конфигурация. 30 | 31 | 32 | LibreOffice 3.5 и старше уже включает в себя лёгкую систему проверки грамматики (LightProof), которая блокирует работу LanguageTool для английского и русского языков. Отключить LightProof и включить LanguageTool для указанных языков можно через меню Сервис -> Параметры -> LibreOffice -> Настройки языка -> Лингвистика -> Доступные языковые модули -> Правка... Необходимо поставить галочку для LanguageTool и убрать для LightProof. 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/resources/help/ru/org.openoffice.languagetool.oxt/0100010.xhp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Конфигурация LanguageTool 6 | /org.openoffice.languagetool.oxt/0100010.xhp 7 | 8 | 9 | 10 | 11 | 12 | Конфигурация и группы правил LanguageTool. 13 | 14 | 15 | Выбрать используемые при проверке текста грамматические правила можно в меню Сервис -> Грамматика – LanguageTool -> Конфигурация. 16 | 17 | 18 | 19 | Набор правил, выбранный по умолчанию, обеспечивает наилучшее качество проверки. 20 | 21 | 22 | Правила для русскоязычных текстов разделены по смыслу на несколько групп: грамматика, логические ошибки, заглавные буквы, общие правила, пунктуация, стиль, дополнительные правила и типографика. 23 | 24 | 25 | В группу общие правила входят сложные правила, реализованные на Java. 26 | 27 | 28 | В группу пунктуация входят правила, описывающие расстановку знаков препинания. 29 | 30 | 31 | В группу типографика входят правила, которые позволяют привести текст к типографским стандартам. Например заменить три точки на символ троеточия. 32 | 33 | 34 | В группу стиль входят правила, помогающие найти сложный для восприятия текст и стилистические ошибки. 35 | 36 | 37 | В группу заглавные буквы входят правила, срабатывающие в случаях, когда должны употребляться прописные буквы. 38 | 39 | 40 | В группу грамматика входят правила, описывающие связь слов в предложении. 41 | 42 | 43 | В группу логические ошибки входят правила, выявляющие ошибки, связанные с нарушением логической правильности рассуждений и фактические ошибки. 44 | 45 | 46 | В группу проверка орфографии входят правила, выявляющие орфографические ошибки. 47 | 48 | 49 | В группу дополнительные правила включены правила, не вошедшие в другие группы. 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/main/resources/images/WTAIGeneralBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAIGeneralBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAboutBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAboutBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAboutSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAboutSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTActivateRulesBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTActivateRulesBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTActivateRulesSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTActivateRulesSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiBetterStyleBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiBetterStyleBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiBetterStyleSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiBetterStyleSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiExpandBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiExpandBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiExpandSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiExpandSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiGeneralSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiGeneralSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiReformulateBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiReformulateBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiReformulateSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiReformulateSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiTextToSpeechBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiTextToSpeechBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiTextToSpeechSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiTextToSpeechSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiTranslateTextBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiTranslateTextBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTAiTranslateTextSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTAiTranslateTextSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTBackCheckOffBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTBackCheckOffBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTBackCheckOffSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTBackCheckOffSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTBackCheckOnBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTBackCheckOnBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTBackCheckOnSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTBackCheckOnSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTCheckAgainBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTCheckAgainBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTCheckAgainSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTCheckAgainSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTCheckBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTCheckBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTCheckSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTCheckSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTNextBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTNextBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTNextSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTNextSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTOptionsBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTOptionsBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTOptionsSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTOptionsSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTProfilesBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTProfilesBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTProfilesSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTProfilesSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTRefreshBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTRefreshBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTRefreshSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTRefreshSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTResetPermanentBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTResetPermanentBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTResetPermanentSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTResetPermanentSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/WTStatAnBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTStatAnBig.png -------------------------------------------------------------------------------- /src/main/resources/images/WTStatAnSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/WTStatAnSmall.png -------------------------------------------------------------------------------- /src/main/resources/images/dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/images/dialog.png -------------------------------------------------------------------------------- /src/main/resources/languagetool/language-module.properties: -------------------------------------------------------------------------------- 1 | languageClasses=org.languagetool.language.Demo 2 | -------------------------------------------------------------------------------- /src/main/resources/org/writingtool/de/MessagesBundle_de.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/main/resources/org/writingtool/de/MessagesBundle_de.properties -------------------------------------------------------------------------------- /src/main/resources/org/writingtool/de/URLsBundle_de.properties: -------------------------------------------------------------------------------- 1 | # English URLs (Help, Options) of WritingTool 2 | # Copyright (C) 2024 Fred Kruse (https://fk-es.de) 3 | OptionProfiles = de/hilfe/optionen/profile 4 | OptionGeneral = de/hilfe/optionen/allgemein 5 | OptionGrammarAndStyle = de/hilfe/optionen/grammatik-und-stilregeln 6 | OptionDefaultColors = de/hilfe/optionen/standardfarben 7 | OptionTechnicalSettings = de/hilfe/optionen/technische-einstellungen 8 | OptionAiSupport = de/hilfe/optionen/ki-unterstuetzung 9 | 10 | localAiInstallation = de/hilfe/installation-einer-lokalen-ki 11 | 12 | StatisticalAnalysis = de/hilfe/statistische-analyse 13 | 14 | AiDialogText = de/hilfe/ki-dialog/ki-dialog-text 15 | AiDialogImage = de/hilfe/ki-dialog/ki-dialog-bild 16 | 17 | -------------------------------------------------------------------------------- /src/main/resources/org/writingtool/en/URLsBundle_en.properties: -------------------------------------------------------------------------------- 1 | # English URLs (Help, Options) of WritingTool 2 | # Copyright (C) 2024 Fred Kruse (https://fk-es.de) 3 | OptionProfiles = en/help/options/profiles 4 | OptionGeneral = en/help/options/general 5 | OptionGrammarAndStyle = en/help/options/grammar-and-style-rules 6 | OptionDefaultColors = en/help/options/default-colors 7 | OptionTechnicalSettings = en/help/options/technical-settings 8 | OptionAiSupport = en/help/options/ai-support-settings 9 | 10 | localAiInstallation = en/help/installation-of-a-local-ai 11 | 12 | StatisticalAnalysis = en/help/statistical-analysis 13 | 14 | AiDialogText = en/help/ai-dialog/ai-dialog-text 15 | AiDialogImage = en/help/ai-dialog/ai-dialog-image 16 | -------------------------------------------------------------------------------- /src/main/resources/org/writingtool/hu/URLsBundle_hu.properties: -------------------------------------------------------------------------------- 1 | # English URLs (Help, Options) of WritingTool 2 | # Copyright (C) 2024 Fred Kruse (https://fk-es.de) 3 | OptionProfiles = en/help/options/profiles 4 | OptionGeneral = en/help/options/general 5 | OptionGrammarAndStyle = en/help/options/grammar-and-style-rules 6 | OptionDefaultColors = en/help/options/default-colors 7 | OptionTechnicalSettings = en/help/options/technical-settings 8 | OptionAiSupport = en/help/options/ai-support-settings 9 | 10 | localAiInstallation = en/help/installation-of-a-local-ai 11 | 12 | StatisticalAnalysis = en/help/statistical-analysis 13 | 14 | AiDialogText = en/help/ai-dialog/ai-dialog-text 15 | AiDialogImage = en/help/ai-dialog/ai-dialog-image 16 | -------------------------------------------------------------------------------- /src/main/resources/org/writingtool/resource/de/confusion_sets.txt: -------------------------------------------------------------------------------- 1 | die;dir -------------------------------------------------------------------------------- /src/main/resources/third-party-licenses/BSD.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) , 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted 5 | provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this list of conditions 8 | and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the nor the names of its contributors may be used to endorse or 14 | promote products derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 23 | IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /src/main/resources/third-party-licenses/MIT-slf4j.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2013 QOS.ch 2 | All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/resources/third-party-licenses/MIT.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/resources/third-party-licenses/Morfologik-license.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | Copyright (c) 2006 Dawid Weiss 4 | Copyright (c) 2007-2010 Dawid Weiss, Marcin Milkowski 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of Morfologik nor the names of its contributors 18 | may be used to endorse or promote products derived from this software 19 | without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /src/main/resources/third-party-licenses/segment-license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Jarek Lipski 2 | www: loomchild.rootnode.net 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /src/main/resources/version.txt: -------------------------------------------------------------------------------- 1 | version=${pom.version} 2 | build.date=${timestamp} -------------------------------------------------------------------------------- /src/test/java/org/writingtool/ErrorSortTest.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import static org.junit.Assert.assertEquals; 22 | 23 | import java.util.Arrays; 24 | 25 | import org.junit.Test; 26 | 27 | public class ErrorSortTest { 28 | 29 | @Test 30 | public void testIsCorrectSortTest() { 31 | 32 | WtProofreadingError[] aError = new WtProofreadingError[11]; 33 | aError[9] = createError("A1", 5, 3, 0); 34 | aError[8] = createError("B1", 17, 11, 0); 35 | aError[3] = createError("C1", 14, 5, 0); 36 | aError[10] = createError("C2", 14, 7, 0); 37 | aError[4] = createError("D1", 9, 10, 0); 38 | aError[2] = createError("E1", 30, 3, 0); 39 | aError[5] = createError("F1", 35, 4, 2); 40 | aError[6] = createError("F2", 35, 4, 2); 41 | aError[1] = createError("F3", 35, 4, 1); 42 | aError[0] = createError("F4", 35, 4, 0); 43 | aError[7] = createError("F5", 35, 4, 0); 44 | Arrays.sort(aError, new WtErrorPositionComparator()); 45 | assertEquals("A1", aError[0].aRuleIdentifier); 46 | assertEquals("B1", aError[1].aRuleIdentifier); 47 | assertEquals("C1", aError[2].aRuleIdentifier); 48 | assertEquals("C2", aError[3].aRuleIdentifier); 49 | assertEquals("D1", aError[4].aRuleIdentifier); 50 | assertEquals("E1", aError[5].aRuleIdentifier); 51 | assertEquals("F1", aError[6].aRuleIdentifier); 52 | assertEquals("F2", aError[7].aRuleIdentifier); 53 | assertEquals("F3", aError[8].aRuleIdentifier); 54 | assertEquals("F4", aError[9].aRuleIdentifier); 55 | assertEquals("F5", aError[10].aRuleIdentifier); 56 | 57 | } 58 | 59 | private WtProofreadingError createError(String id, int start, int length, int numSuggestion) { 60 | WtProofreadingError error = new WtProofreadingError(); 61 | error.aRuleIdentifier = id; 62 | error.nErrorStart = start; 63 | error.nErrorLength = length; 64 | error.aSuggestions = new String[numSuggestion]; 65 | return error; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/org/writingtool/KhmerDetectorTest.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import org.junit.Test; 22 | import org.writingtool.languagedetectors.WtKhmerDetector; 23 | 24 | import static org.junit.Assert.*; 25 | 26 | public class KhmerDetectorTest { 27 | 28 | @Test 29 | public void testIsThisLanguage() { 30 | WtKhmerDetector detector = new WtKhmerDetector(); 31 | 32 | assertTrue(detector.isThisLanguage("ប៉ុ")); 33 | assertTrue(detector.isThisLanguage("ប៉ុន្តែ​តើ")); 34 | assertTrue(detector.isThisLanguage("ហើយដោយ​ព្រោះ​")); 35 | assertTrue(detector.isThisLanguage("«ទៅ​បាន​។ «")); 36 | 37 | assertFalse(detector.isThisLanguage("Hallo")); 38 | assertFalse(detector.isThisLanguage("öäü")); 39 | 40 | assertFalse(detector.isThisLanguage("")); 41 | try { 42 | assertFalse(detector.isThisLanguage(null)); 43 | fail(); 44 | } catch (NullPointerException ignored) {} 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/org/writingtool/TamilDetectorTest.java: -------------------------------------------------------------------------------- 1 | /* WritingTool, a LibreOffice Extension based on LanguageTool 2 | * Copyright (C) 2024 Fred Kruse (https://writingtool.org) 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 17 | * USA 18 | */ 19 | package org.writingtool; 20 | 21 | import org.junit.Test; 22 | import org.writingtool.languagedetectors.WtTamilDetector; 23 | 24 | import static org.junit.Assert.assertFalse; 25 | import static org.junit.Assert.assertTrue; 26 | import static org.junit.Assert.fail; 27 | 28 | 29 | public class TamilDetectorTest { 30 | 31 | @Test 32 | public void testIsThisLanguage() { 33 | WtTamilDetector detector = new WtTamilDetector(); 34 | 35 | assertTrue(detector.isThisLanguage("இந்த")); 36 | assertTrue(detector.isThisLanguage("இ")); 37 | assertTrue(detector.isThisLanguage("\"லேங்குவேஜ்")); 38 | 39 | assertFalse(detector.isThisLanguage("Hallo")); 40 | assertFalse(detector.isThisLanguage("öäü")); 41 | 42 | assertFalse(detector.isThisLanguage("")); 43 | try { 44 | assertFalse(detector.isThisLanguage(null)); 45 | fail(); 46 | } catch (NullPointerException ignored) {} 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/test/resources/manual-testing.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/writingtool-org/writingtool/eb99ebb50a9c1dc23d1ab2d046c6b9834a1420d3/src/test/resources/manual-testing.odt --------------------------------------------------------------------------------