am e3247561: Merge "Support languages that don\'t use spaces."

* commit 'e32475611ce52671802ca8d2f9694bbb82c4b120':
  Support languages that don't use spaces.
main
Jean Chalard 2013-08-16 05:08:58 -07:00 committed by Android Git Automerger
commit 5b0aeafb5e
7 changed files with 226 additions and 20 deletions

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2013, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Whether this language uses spaces -->
<bool name="current_language_has_spaces">false</bool>
</resources>

View File

@ -18,6 +18,8 @@
*/ */
--> -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- TODO: these settings depend on the language. They should be put either in the dictionary
header, or in the subtype maybe? -->
<!-- Symbols that are suggested between words --> <!-- Symbols that are suggested between words -->
<string name="suggested_punctuations">!,?,\\,,:,;,\",(,),\',-,/,@,_</string> <string name="suggested_punctuations">!,?,\\,,:,;,\",(,),\',-,/,@,_</string>
<!-- Symbols that are normally preceded by a space (used to add an auto-space before these) --> <!-- Symbols that are normally preceded by a space (used to add an auto-space before these) -->
@ -29,6 +31,8 @@
<string name="symbols_word_separators">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string> <string name="symbols_word_separators">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
<!-- Word connectors --> <!-- Word connectors -->
<string name="symbols_word_connectors">\'-</string> <string name="symbols_word_connectors">\'-</string>
<!-- Whether this language uses spaces -->
<bool name="current_language_has_spaces">true</bool>
<!-- Always show the suggestion strip --> <!-- Always show the suggestion strip -->
<string name="prefs_suggestion_visibility_show_value">0</string> <string name="prefs_suggestion_visibility_show_value">0</string>

View File

@ -1948,7 +1948,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
} }
} }
if (currentSettings.isSuggestionsRequested(mDisplayOrientation)) { if (currentSettings.isSuggestionsRequested(mDisplayOrientation)
&& currentSettings.mCurrentLanguageHasSpaces) {
restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(); restartSuggestionsOnWordBeforeCursorIfAtEndOfWord();
} }
// We just removed a character. We need to update the auto-caps state. // We just removed a character. We need to update the auto-caps state.
@ -1977,6 +1978,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void handleCharacter(final int primaryCode, final int x, private void handleCharacter(final int primaryCode, final int x,
final int y, final int spaceState) { final int y, final int spaceState) {
// TODO: refactor this method to stop flipping isComposingWord around all the time, and
// make it shorter (possibly cut into several pieces). Also factor handleNonSpecialCharacter
// which has the same name as other handle* methods but is not the same.
boolean isComposingWord = mWordComposer.isComposingWord(); boolean isComposingWord = mWordComposer.isComposingWord();
// TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead. // TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead.
@ -1996,12 +2000,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
resetEntireInputState(mLastSelectionStart); resetEntireInputState(mLastSelectionStart);
isComposingWord = false; isComposingWord = false;
} }
// NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several // We want to find out whether to start composing a new word with this character. If so,
// dozen milliseconds. Avoid calling it as much as possible, since we are on the UI // we need to reset the composing state and switch isComposingWord. The order of the
// thread here. // tests is important for good performance.
if (!isComposingWord && currentSettings.isWordCodePoint(primaryCode) // We only start composing if we're not already composing.
if (!isComposingWord
// We only start composing if this is a word code point. Essentially that means it's a
// a letter or a word connector.
&& currentSettings.isWordCodePoint(primaryCode)
// We never go into composing state if suggestions are not requested.
&& currentSettings.isSuggestionsRequested(mDisplayOrientation) && && currentSettings.isSuggestionsRequested(mDisplayOrientation) &&
!mConnection.isCursorTouchingWord(currentSettings)) { // In languages with spaces, we only start composing a word when we are not already
// touching a word. In languages without spaces, the above conditions are sufficient.
(!mConnection.isCursorTouchingWord(currentSettings)
|| !currentSettings.mCurrentLanguageHasSpaces)) {
// Reset entirely the composing state anyway, then start composing a new word unless // Reset entirely the composing state anyway, then start composing a new word unless
// the character is a single quote. The idea here is, single quote is not a // the character is a single quote. The idea here is, single quote is not a
// separator and it should be treated as a normal character, except in the first // separator and it should be treated as a normal character, except in the first
@ -2089,16 +2101,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private boolean handleSeparator(final int primaryCode, final int x, final int y, private boolean handleSeparator(final int primaryCode, final int x, final int y,
final int spaceState) { final int spaceState) {
boolean didAutoCorrect = false; boolean didAutoCorrect = false;
final SettingsValues currentSettings = mSettings.getCurrent();
// We avoid sending spaces in languages without spaces if we were composing.
final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == primaryCode
&& !currentSettings.mCurrentLanguageHasSpaces && mWordComposer.isComposingWord();
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection // If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the separator at the current cursor position. // first so that we can insert the separator at the current cursor position.
resetEntireInputState(mLastSelectionStart); resetEntireInputState(mLastSelectionStart);
} }
final SettingsValues currentSettings = mSettings.getCurrent(); if (mWordComposer.isComposingWord()) { // May have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
if (currentSettings.mCorrectionEnabled) { if (currentSettings.mCorrectionEnabled) {
// TODO: maybe cache Strings in an <String> sparse array or something final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
commitCurrentAutoCorrection(new String(new int[]{primaryCode}, 0, 1)); : new String(new int[] { primaryCode }, 0, 1);
commitCurrentAutoCorrection(separator);
didAutoCorrect = true; didAutoCorrect = true;
} else { } else {
commitTyped(new String(new int[]{primaryCode}, 0, 1)); commitTyped(new String(new int[]{primaryCode}, 0, 1));
@ -2115,7 +2131,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_handleSeparator(primaryCode, mWordComposer.isComposingWord()); ResearchLogger.latinIME_handleSeparator(primaryCode, mWordComposer.isComposingWord());
} }
sendKeyCodePoint(primaryCode);
if (!shouldAvoidSendingCode) {
sendKeyCodePoint(primaryCode);
}
if (Constants.CODE_SPACE == primaryCode) { if (Constants.CODE_SPACE == primaryCode) {
if (currentSettings.isSuggestionsRequested(mDisplayOrientation)) { if (currentSettings.isSuggestionsRequested(mDisplayOrientation)) {
@ -2260,11 +2279,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Get the word on which we should search the bigrams. If we are composing a word, it's // Get the word on which we should search the bigrams. If we are composing a word, it's
// whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we // whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we
// should just skip whitespace if any, so 1. // should just skip whitespace if any, so 1.
// TODO: this is slow (2-way IPC) - we should probably cache this instead.
final SettingsValues currentSettings = mSettings.getCurrent(); final SettingsValues currentSettings = mSettings.getCurrent();
final String prevWord = final String prevWord;
mConnection.getNthPreviousWord(currentSettings.mWordSeparators, if (currentSettings.mCurrentLanguageHasSpaces) {
mWordComposer.isComposingWord() ? 2 : 1); // If we are typing in a language with spaces we can just look up the previous
// word from textview.
prevWord = mConnection.getNthPreviousWord(currentSettings.mWordSeparators,
mWordComposer.isComposingWord() ? 2 : 1);
} else {
prevWord = LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ? null
: mLastComposedWord.mCommittedWord;
}
return suggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(), return suggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(),
currentSettings.mBlockPotentiallyOffensive, currentSettings.mBlockPotentiallyOffensive,
currentSettings.mCorrectionEnabled, sessionId); currentSettings.mCorrectionEnabled, sessionId);
@ -2534,6 +2559,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// recorrection. This is a temporary, stopgap measure that will be removed later. // recorrection. This is a temporary, stopgap measure that will be removed later.
// TODO: remove this. // TODO: remove this.
if (mAppWorkAroundsUtils.isBrokenByRecorrection()) return; if (mAppWorkAroundsUtils.isBrokenByRecorrection()) return;
// Recorrection is not supported in languages without spaces because we don't know
// how to segment them yet.
if (!mSettings.getCurrent().mCurrentLanguageHasSpaces) return;
// If the cursor is not touching a word, or if there is a selection, return right away. // If the cursor is not touching a word, or if there is a selection, return right away.
if (mLastSelectionStart != mLastSelectionEnd) return; if (mLastSelectionStart != mLastSelectionEnd) return;
// If we don't know the cursor location, return. // If we don't know the cursor location, return.
@ -2656,7 +2684,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) { if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
mUserHistoryPredictionDictionary.cancelAddingUserHistory(previousWord, committedWord); mUserHistoryPredictionDictionary.cancelAddingUserHistory(previousWord, committedWord);
} }
mConnection.commitText(originallyTypedWord + mLastComposedWord.mSeparatorString, 1); final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString;
if (mSettings.getCurrent().mCurrentLanguageHasSpaces) {
// For languages with spaces, we revert to the typed string, but the cursor is still
// after the separator so we don't resume suggestions. If the user wants to correct
// the word, they have to press backspace again.
mConnection.commitText(stringToCommit, 1);
} else {
// For languages without spaces, we revert the typed string but the cursor is flush
// with the typed word, so we need to resume suggestions right away.
mWordComposer.setComposingWord(stringToCommit, mKeyboardSwitcher.getKeyboard());
mConnection.setComposingText(stringToCommit, 1);
}
if (mSettings.isInternal()) { if (mSettings.isInternal()) {
LatinImeLoggerUtils.onSeparator(mLastComposedWord.mSeparatorString, LatinImeLoggerUtils.onSeparator(mLastComposedWord.mSeparatorString,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
@ -2674,7 +2713,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This essentially inserts a space, and that's it. // This essentially inserts a space, and that's it.
public void promotePhantomSpace() { public void promotePhantomSpace() {
if (mSettings.getCurrent().shouldInsertSpacesAutomatically() final SettingsValues currentSettings = mSettings.getCurrent();
if (currentSettings.shouldInsertSpacesAutomatically()
&& currentSettings.mCurrentLanguageHasSpaces
&& !mConnection.textBeforeCursorLooksLikeURL()) { && !mConnection.textBeforeCursorLooksLikeURL()) {
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_promotePhantomSpace(); ResearchLogger.latinIME_promotePhantomSpace();
@ -2887,6 +2928,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return mSuggest.hasMainDictionary(); return mSuggest.hasMainDictionary();
} }
// DO NOT USE THIS for any other purpose than testing. This can break the keyboard badly.
@UsedForTesting
/* package for test */ void replaceMainDictionaryForTest(final Locale locale) {
mSuggest.resetMainDict(this, locale, null);
}
public void debugDumpStateAndCrashWithException(final String context) { public void debugDumpStateAndCrashWithException(final String context) {
final StringBuilder s = new StringBuilder(mAppWorkAroundsUtils.toString()); final StringBuilder s = new StringBuilder(mAppWorkAroundsUtils.toString());
s.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes) s.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)

View File

@ -57,6 +57,7 @@ public final class SettingsValues {
public final SuggestedWords mSuggestPuncList; public final SuggestedWords mSuggestPuncList;
public final String mWordSeparators; public final String mWordSeparators;
public final CharSequence mHintToSaveText; public final CharSequence mHintToSaveText;
public final boolean mCurrentLanguageHasSpaces;
// From preferences, in the same order as xml/prefs.xml: // From preferences, in the same order as xml/prefs.xml:
public final boolean mAutoCap; public final boolean mAutoCap;
@ -118,6 +119,7 @@ public final class SettingsValues {
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec); mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mWordSeparators = res.getString(R.string.symbols_word_separators); mWordSeparators = res.getString(R.string.symbols_word_separators);
mHintToSaveText = res.getText(R.string.hint_add_to_dictionary); mHintToSaveText = res.getText(R.string.hint_add_to_dictionary);
mCurrentLanguageHasSpaces = res.getBoolean(R.bool.current_language_has_spaces);
// Store the input attributes // Store the input attributes
if (null == inputAttributes) { if (null == inputAttributes) {
@ -186,6 +188,7 @@ public final class SettingsValues {
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec); mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mWordSeparators = "&\t \n()[]{}*&<>+=|.,;:!?/_\""; mWordSeparators = "&\t \n()[]{}*&<>+=|.,;:!?/_\"";
mHintToSaveText = "Touch again to save"; mHintToSaveText = "Touch again to save";
mCurrentLanguageHasSpaces = true;
mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
mAutoCap = true; mAutoCap = true;
mVibrateOn = true; mVibrateOn = true;

View File

@ -17,6 +17,7 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.LargeTest;
import android.view.inputmethod.BaseInputConnection;
@LargeTest @LargeTest
public class InputLogicTests extends InputTestsBase { public class InputLogicTests extends InputTestsBase {
@ -290,5 +291,19 @@ public class InputLogicTests extends InputTestsBase {
} }
assertEquals("delete whole composing word", "", mEditText.getText().toString()); assertEquals("delete whole composing word", "", mEditText.getText().toString());
} }
public void testResumeSuggestionOnBackspace() {
final String WORD_TO_TYPE = "and this ";
type(WORD_TO_TYPE);
assertEquals("resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
type(Constants.CODE_DELETE);
assertEquals("resume suggestion on backspace", 4,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("resume suggestion on backspace", 8,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
// TODO: Add some tests for non-BMP characters // TODO: Add some tests for non-BMP characters
} }

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.latin;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.inputmethod.BaseInputConnection;
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
@LargeTest
public class InputLogicTestsLanguageWithoutSpaces extends InputTestsBase {
public void testAutoCorrectForLanguageWithoutSpaces() {
final String STRING_TO_TYPE = "tgis is";
final String EXPECTED_RESULT = "thisis";
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(STRING_TO_TYPE);
assertEquals("simple auto-correct for language without spaces", EXPECTED_RESULT,
mEditText.getText().toString());
}
public void testRevertAutoCorrectForLanguageWithoutSpaces() {
final String STRING_TO_TYPE = "tgis ";
final String EXPECTED_INTERMEDIATE_RESULT = "this";
final String EXPECTED_FINAL_RESULT = "tgis";
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(STRING_TO_TYPE);
assertEquals("simple auto-correct for language without spaces",
EXPECTED_INTERMEDIATE_RESULT, mEditText.getText().toString());
type(Constants.CODE_DELETE);
assertEquals("simple auto-correct for language without spaces",
EXPECTED_FINAL_RESULT, mEditText.getText().toString());
// Check we are back to composing the word
assertEquals("don't resume suggestion on backspace", 0,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("don't resume suggestion on backspace", 4,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
public void testDontResumeSuggestionOnBackspace() {
final String WORD_TO_TYPE = "and this ";
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(WORD_TO_TYPE);
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
type(" ");
type(Constants.CODE_DELETE);
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("don't resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
public void testStartComposingInsideText() {
final String WORD_TO_TYPE = "abcdefgh ";
final int typedLength = WORD_TO_TYPE.length() - 1; // -1 because space gets eaten
final int CURSOR_POS = 4;
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(WORD_TO_TYPE);
mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
mLatinIME.onUpdateSelection(typedLength, typedLength,
CURSOR_POS, CURSOR_POS, -1, -1);
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
runMessages();
assertEquals("start composing inside text", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("start composing inside text", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
type("xxxx");
assertEquals("start composing inside text", 4,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("start composing inside text", 8,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
public void testPredictions() {
final String WORD_TO_TYPE = "Barack ";
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(WORD_TO_TYPE);
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
runMessages();
// Make sure there is no space
assertEquals("predictions in lang without spaces", "Barack",
mEditText.getText().toString());
// Test the first prediction is displayed
assertEquals("predictions in lang without spaces", "Obama",
mLatinIME.getFirstSuggestedWord());
}
}

View File

@ -46,6 +46,8 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
// The message that sets the underline is posted with a 100 ms delay // The message that sets the underline is posted with a 100 ms delay
protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 200; protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 200;
// The message that sets predictions is posted with a 100 ms delay
protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS = 200;
protected LatinIME mLatinIME; protected LatinIME mLatinIME;
protected Keyboard mKeyboard; protected Keyboard mKeyboard;
@ -233,9 +235,6 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
--remainingAttempts; --remainingAttempts;
} }
} }
if (!mLatinIME.hasMainDictionary()) {
throw new RuntimeException("Can't initialize the main dictionary");
}
} }
protected void changeLanguage(final String locale) { protected void changeLanguage(final String locale) {
@ -247,6 +246,16 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
waitForDictionaryToBeLoaded(); waitForDictionaryToBeLoaded();
} }
protected void changeKeyboardLocaleAndDictLocale(final String keyboardLocale,
final String dictLocale) {
changeLanguage(keyboardLocale);
if (!keyboardLocale.equals(dictLocale)) {
mLatinIME.replaceMainDictionaryForTest(
LocaleUtils.constructLocaleFromString(dictLocale));
}
waitForDictionaryToBeLoaded();
}
protected void pickSuggestionManually(final int index, final String suggestion) { protected void pickSuggestionManually(final int index, final String suggestion) {
mLatinIME.pickSuggestionManually(index, new SuggestedWordInfo(suggestion, 1, mLatinIME.pickSuggestionManually(index, new SuggestedWordInfo(suggestion, 1,
SuggestedWordInfo.KIND_CORRECTION, "main")); SuggestedWordInfo.KIND_CORRECTION, "main"));