mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-01 20:34:30 +00:00
some formatting
This commit is contained in:
parent
eee94f2924
commit
a7a3465e9b
4 changed files with 168 additions and 168 deletions
|
@ -17,12 +17,29 @@ import java.util.*
|
|||
* feedback on the composing state and will typically be shown with different styling such as
|
||||
* a colored background.
|
||||
*/
|
||||
class CombinerChain(initialText: String?) {
|
||||
class CombinerChain(initialText: String) {
|
||||
// The already combined text, as described above
|
||||
private val mCombinedText: StringBuilder
|
||||
private val mCombinedText = StringBuilder(initialText)
|
||||
// The feedback on the composing state, as described above
|
||||
private val mStateFeedback: SpannableStringBuilder
|
||||
private val mCombiners: ArrayList<Combiner>
|
||||
private val mStateFeedback = SpannableStringBuilder()
|
||||
private val mCombiners = ArrayList<Combiner>()
|
||||
|
||||
/**
|
||||
* Create an combiner chain.
|
||||
*
|
||||
* The combiner chain takes events as inputs and outputs code points and combining state.
|
||||
* For example, if the input language is Japanese, the combining chain will typically perform
|
||||
* kana conversion. This takes a string for initial text, taken to be present before the
|
||||
* cursor: we'll start after this.
|
||||
*
|
||||
* @param initialText The text that has already been combined so far.
|
||||
*/
|
||||
init {
|
||||
// The dead key combiner is always active, and always first
|
||||
mCombiners.add(DeadKeyCombiner())
|
||||
mCombiners.add(HangulCombiner())
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
mCombinedText.setLength(0)
|
||||
mStateFeedback.clear()
|
||||
|
@ -45,15 +62,16 @@ class CombinerChain(initialText: String?) {
|
|||
* @return the processed event. It may be the same event, or a consumed event, or a completely
|
||||
* new event. However it may never be null.
|
||||
*/
|
||||
fun processEvent(previousEvents: ArrayList<Event>?,
|
||||
newEvent: Event): Event {
|
||||
fun processEvent(previousEvents: ArrayList<Event>?, newEvent: Event): Event {
|
||||
val modifiablePreviousEvents = ArrayList(previousEvents!!)
|
||||
var event = newEvent
|
||||
for (combiner in mCombiners) { // A combiner can never return more than one event; it can return several
|
||||
// code points, but they should be encapsulated within one event.
|
||||
for (combiner in mCombiners) {
|
||||
// A combiner can never return more than one event; it can return several
|
||||
// code points, but they should be encapsulated within one event.
|
||||
event = combiner.processEvent(modifiablePreviousEvents, event)
|
||||
if (event.isConsumed) { // If the event is consumed, then we don't pass it to subsequent combiners:
|
||||
// they should not see it at all.
|
||||
if (event.isConsumed) {
|
||||
// If the event is consumed, then we don't pass it to subsequent combiners:
|
||||
// they should not see it at all.
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -93,22 +111,4 @@ class CombinerChain(initialText: String?) {
|
|||
return s.append(mStateFeedback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an combiner chain.
|
||||
*
|
||||
* The combiner chain takes events as inputs and outputs code points and combining state.
|
||||
* For example, if the input language is Japanese, the combining chain will typically perform
|
||||
* kana conversion. This takes a string for initial text, taken to be present before the
|
||||
* cursor: we'll start after this.
|
||||
*
|
||||
* @param initialText The text that has already been combined so far.
|
||||
*/
|
||||
init {
|
||||
mCombiners = ArrayList()
|
||||
// The dead key combiner is always active, and always first
|
||||
mCombiners.add(DeadKeyCombiner())
|
||||
mCombiners.add(HangulCombiner())
|
||||
mCombinedText = StringBuilder(initialText!!)
|
||||
mStateFeedback = SpannableStringBuilder()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,62 +17,59 @@ import org.dslul.openboard.inputmethod.latin.common.StringUtils
|
|||
* for example.
|
||||
* The combiner should figure out what to do with this.
|
||||
*/
|
||||
class Event private constructor(// The type of event - one of the constants above
|
||||
private val mEventType: Int, // If applicable, this contains the string that should be input.
|
||||
val mText: CharSequence?, // The code point associated with the event, if relevant. This is a unicode code point, and
|
||||
// has nothing to do with other representations of the key. It is only relevant if this event
|
||||
// is of KEYPRESS type, but for a mode key like hankaku/zenkaku or ctrl, there is no code point
|
||||
// associated so this should be NOT_A_CODE_POINT to avoid unintentional use of its value when
|
||||
// it's not relevant.
|
||||
val mCodePoint: Int, // The key code associated with the event, if relevant. This is relevant whenever this event
|
||||
// has been triggered by a key press, but not for a gesture for example. This has conceptually
|
||||
// no link to the code point, although keys that enter a straight code point may often set
|
||||
// this to be equal to mCodePoint for convenience. If this is not a key, this must contain
|
||||
// NOT_A_KEY_CODE.
|
||||
class Event private constructor(
|
||||
// The type of event - one of the constants above
|
||||
private val mEventType: Int,
|
||||
// If applicable, this contains the string that should be input.
|
||||
val mText: CharSequence?,
|
||||
// The code point associated with the event, if relevant. This is a unicode code point, and
|
||||
// has nothing to do with other representations of the key. It is only relevant if this event
|
||||
// is of KEYPRESS type, but for a mode key like hankaku/zenkaku or ctrl, there is no code point
|
||||
// associated so this should be NOT_A_CODE_POINT to avoid unintentional use of its value when
|
||||
// it's not relevant.
|
||||
val mCodePoint: Int,
|
||||
// The key code associated with the event, if relevant. This is relevant whenever this event
|
||||
// has been triggered by a key press, but not for a gesture for example. This has conceptually
|
||||
// no link to the code point, although keys that enter a straight code point may often set
|
||||
// this to be equal to mCodePoint for convenience. If this is not a key, this must contain
|
||||
// NOT_A_KEY_CODE.
|
||||
val mKeyCode: Int,
|
||||
// Coordinates of the touch event, if relevant. If useful, we may want to replace this with
|
||||
// a MotionEvent or something in the future. This is only relevant when the keypress is from
|
||||
// a software keyboard obviously, unless there are touch-sensitive hardware keyboards in the
|
||||
// future or some other awesome sauce.
|
||||
// a MotionEvent or something in the future. This is only relevant when the keypress is from
|
||||
// a software keyboard obviously, unless there are touch-sensitive hardware keyboards in the
|
||||
// future or some other awesome sauce.
|
||||
val mX: Int, val mY: Int,
|
||||
// If this is of type EVENT_TYPE_SUGGESTION_PICKED, this must not be null (and must be null in
|
||||
// other cases).
|
||||
// other cases).
|
||||
val mSuggestedWordInfo: SuggestedWordInfo?,
|
||||
// Some flags that can't go into the key code. It's a bit field of FLAG_*
|
||||
private val mFlags: Int,
|
||||
// The next event, if any. Null if there is no next event yet.
|
||||
val mNextEvent: Event?// This logic may need to be refined in the future
|
||||
val mNextEvent: Event?
|
||||
// This logic may need to be refined in the future
|
||||
) {
|
||||
|
||||
// Returns whether this is a function key like backspace, ctrl, settings... as opposed to keys
|
||||
// that result in input like letters or space.
|
||||
// that result in input like letters or space.
|
||||
val isFunctionalKeyEvent: Boolean
|
||||
get() =// This logic may need to be refined in the future
|
||||
NOT_A_CODE_POINT == mCodePoint
|
||||
get() = NOT_A_CODE_POINT == mCodePoint // This logic may need to be refined in the future
|
||||
|
||||
// Returns whether this event is for a dead character. @see {@link #FLAG_DEAD}
|
||||
val isDead: Boolean
|
||||
get() = 0 != FLAG_DEAD and mFlags
|
||||
val isDead: Boolean get() = 0 != FLAG_DEAD and mFlags
|
||||
|
||||
val isKeyRepeat: Boolean
|
||||
get() = 0 != FLAG_REPEAT and mFlags
|
||||
val isKeyRepeat: Boolean get() = 0 != FLAG_REPEAT and mFlags
|
||||
|
||||
val isConsumed: Boolean
|
||||
get() = 0 != FLAG_CONSUMED and mFlags
|
||||
val isConsumed: Boolean get() = 0 != FLAG_CONSUMED and mFlags
|
||||
|
||||
val isCombining: Boolean
|
||||
get() = 0 != FLAG_COMBINING and mFlags
|
||||
val isCombining: Boolean get() = 0 != FLAG_COMBINING and mFlags
|
||||
|
||||
val isGesture: Boolean
|
||||
get() = EVENT_TYPE_GESTURE == mEventType
|
||||
val isGesture: Boolean get() = EVENT_TYPE_GESTURE == mEventType
|
||||
|
||||
// Returns whether this is a fake key press from the suggestion strip. This happens with
|
||||
// punctuation signs selected from the suggestion strip.
|
||||
val isSuggestionStripPress: Boolean
|
||||
get() = EVENT_TYPE_SUGGESTION_PICKED == mEventType
|
||||
// punctuation signs selected from the suggestion strip.
|
||||
val isSuggestionStripPress: Boolean get() = EVENT_TYPE_SUGGESTION_PICKED == mEventType
|
||||
|
||||
val isHandled: Boolean
|
||||
get() = EVENT_TYPE_NOT_HANDLED != mEventType
|
||||
val isHandled: Boolean get() = EVENT_TYPE_NOT_HANDLED != mEventType
|
||||
|
||||
// A consumed event should input no text.
|
||||
val textToCommit: CharSequence?
|
||||
|
@ -90,20 +87,20 @@ class Event private constructor(// The type of event - one of the constants abov
|
|||
|
||||
companion object {
|
||||
// Should the types below be represented by separate classes instead? It would be cleaner
|
||||
// but probably a bit too much
|
||||
// An event we don't handle in Latin IME, for example pressing Ctrl on a hardware keyboard.
|
||||
// but probably a bit too much
|
||||
// An event we don't handle in Latin IME, for example pressing Ctrl on a hardware keyboard.
|
||||
const val EVENT_TYPE_NOT_HANDLED = 0
|
||||
// A key press that is part of input, for example pressing an alphabetic character on a
|
||||
// hardware qwerty keyboard. It may be part of a sequence that will be re-interpreted later
|
||||
// through combination.
|
||||
// hardware qwerty keyboard. It may be part of a sequence that will be re-interpreted later
|
||||
// through combination.
|
||||
const val EVENT_TYPE_INPUT_KEYPRESS = 1
|
||||
// A toggle event is triggered by a key that affects the previous character. An example would
|
||||
// be a numeric key on a 10-key keyboard, which would toggle between 1 - a - b - c with
|
||||
// repeated presses.
|
||||
// be a numeric key on a 10-key keyboard, which would toggle between 1 - a - b - c with
|
||||
// repeated presses.
|
||||
const val EVENT_TYPE_TOGGLE = 2
|
||||
// A mode event instructs the combiner to change modes. The canonical example would be the
|
||||
// hankaku/zenkaku key on a Japanese keyboard, or even the caps lock key on a qwerty keyboard
|
||||
// if handled at the combiner level.
|
||||
// hankaku/zenkaku key on a Japanese keyboard, or even the caps lock key on a qwerty keyboard
|
||||
// if handled at the combiner level.
|
||||
const val EVENT_TYPE_MODE_KEY = 3
|
||||
// An event corresponding to a gesture.
|
||||
const val EVENT_TYPE_GESTURE = 4
|
||||
|
@ -119,7 +116,7 @@ class Event private constructor(// The type of event - one of the constants abov
|
|||
const val NOT_A_KEY_CODE = 0
|
||||
private const val FLAG_NONE = 0
|
||||
// This event is a dead character, usually input by a dead key. Examples include dead-acute
|
||||
// or dead-abovering.
|
||||
// or dead-abovering.
|
||||
private const val FLAG_DEAD = 0x1
|
||||
// This event is coming from a key repeat, software or hardware.
|
||||
private const val FLAG_REPEAT = 0x2
|
||||
|
@ -197,22 +194,20 @@ class Event private constructor(// The type of event - one of the constants abov
|
|||
* or combination that outputs a string.
|
||||
* @param text the CharSequence associated with this event.
|
||||
* @param keyCode the key code, or NOT_A_KEYCODE if not applicable.
|
||||
* @param next the next event, or null if not applicable.
|
||||
* @return an event for this text.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun createSoftwareTextEvent(text: CharSequence?, keyCode: Int): Event {
|
||||
return Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
|
||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
||||
null /* suggestedWordInfo */, FLAG_NONE, null /* next */)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createSoftwareTextEvent(text: CharSequence?, keyCode: Int, next: Event): Event {
|
||||
fun createSoftwareTextEvent(text: CharSequence?, keyCode: Int, next: Event?): Event {
|
||||
return Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
|
||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
||||
null /* suggestedWordInfo */, FLAG_NONE, next)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createSoftwareTextEvent(text: CharSequence?, keyCode: Int) =
|
||||
createSoftwareTextEvent(text, keyCode, null)
|
||||
|
||||
/**
|
||||
* Creates an input event representing the manual pick of a punctuation suggestion.
|
||||
* @return an event for this suggestion pick.
|
||||
|
@ -220,7 +215,7 @@ class Event private constructor(// The type of event - one of the constants abov
|
|||
@JvmStatic
|
||||
fun createPunctuationSuggestionPickedEvent(
|
||||
suggestedWordInfo: SuggestedWordInfo): Event {
|
||||
val primaryCode = suggestedWordInfo.mWord[0].toInt()
|
||||
val primaryCode = suggestedWordInfo.mWord[0].code
|
||||
return Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord, primaryCode,
|
||||
NOT_A_KEY_CODE, Constants.SUGGESTION_STRIP_COORDINATE,
|
||||
Constants.SUGGESTION_STRIP_COORDINATE, suggestedWordInfo, FLAG_NONE,
|
||||
|
@ -244,8 +239,8 @@ class Event private constructor(// The type of event - one of the constants abov
|
|||
* @param source the event to copy the properties of.
|
||||
* @return an identical event marked as consumed.
|
||||
*/
|
||||
fun createConsumedEvent(source: Event?): Event { // A consumed event should not input any text at all, so we pass the empty string as text.
|
||||
return Event(source!!.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
|
||||
fun createConsumedEvent(source: Event): Event { // A consumed event should not input any text at all, so we pass the empty string as text.
|
||||
return Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
|
||||
source.mX, source.mY, source.mSuggestedWordInfo, source.mFlags or FLAG_CONSUMED,
|
||||
source.mNextEvent)
|
||||
}
|
||||
|
@ -266,7 +261,7 @@ class Event private constructor(// The type of event - one of the constants abov
|
|||
// This method is private - to create a new event, use one of the create* utility methods.
|
||||
init {
|
||||
// Sanity checks
|
||||
// mSuggestedWordInfo is non-null if and only if the type is SUGGESTION_PICKED
|
||||
// mSuggestedWordInfo is non-null if and only if the type is SUGGESTION_PICKED
|
||||
if (EVENT_TYPE_SUGGESTION_PICKED == mEventType) {
|
||||
if (null == mSuggestedWordInfo) {
|
||||
throw RuntimeException("Wrong event: SUGGESTION_PICKED event must have a "
|
||||
|
@ -279,4 +274,4 @@ class Event private constructor(// The type of event - one of the constants abov
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,22 +6,21 @@ import java.util.ArrayList
|
|||
|
||||
class HangulCombiner : Combiner {
|
||||
|
||||
val composingWord = StringBuilder()
|
||||
private val composingWord = StringBuilder()
|
||||
|
||||
val history: MutableList<HangulSyllable> = mutableListOf()
|
||||
val syllable: HangulSyllable? get() = history.lastOrNull()
|
||||
private val syllable: HangulSyllable? get() = history.lastOrNull()
|
||||
|
||||
override fun processEvent(previousEvents: ArrayList<Event>?, event: Event): Event {
|
||||
if(event.mKeyCode == Constants.CODE_SHIFT) return event
|
||||
if(Character.isWhitespace(event.mCodePoint)) {
|
||||
if (event.mKeyCode == Constants.CODE_SHIFT) return event
|
||||
if (Character.isWhitespace(event.mCodePoint)) {
|
||||
val text = combiningStateFeedback
|
||||
reset()
|
||||
return createEventChainFromSequence(text, event)
|
||||
} else if(event.isFunctionalKeyEvent) {
|
||||
} else if (event.isFunctionalKeyEvent) {
|
||||
if(event.mKeyCode == Constants.CODE_DELETE) {
|
||||
return when {
|
||||
history.size == 1 && composingWord.isEmpty() ||
|
||||
history.isEmpty() && composingWord.length == 1 -> {
|
||||
history.size == 1 && composingWord.isEmpty() || history.isEmpty() && composingWord.length == 1 -> {
|
||||
reset()
|
||||
Event.createHardwareKeypressEvent(0x20, Constants.CODE_SPACE, event, event.isKeyRepeat)
|
||||
}
|
||||
|
@ -42,37 +41,39 @@ class HangulCombiner : Combiner {
|
|||
} else {
|
||||
val currentSyllable = syllable ?: HangulSyllable()
|
||||
val jamo = HangulJamo.of(event.mCodePoint)
|
||||
if(!event.isCombining || jamo is HangulJamo.NonHangul) {
|
||||
if (!event.isCombining || jamo is HangulJamo.NonHangul) {
|
||||
composingWord.append(currentSyllable.string)
|
||||
composingWord.append(jamo.string)
|
||||
history.clear()
|
||||
} else {
|
||||
when(jamo) {
|
||||
when (jamo) {
|
||||
is HangulJamo.Consonant -> {
|
||||
val initial = jamo.toInitial()
|
||||
val final = jamo.toFinal()
|
||||
if(currentSyllable.initial != null && currentSyllable.medial != null) {
|
||||
if(currentSyllable.final == null) {
|
||||
if (currentSyllable.initial != null && currentSyllable.medial != null) {
|
||||
if (currentSyllable.final == null) {
|
||||
val combination = COMBINATION_TABLE_DUBEOLSIK[currentSyllable.initial.codePoint to (initial?.codePoint ?: -1)]
|
||||
if(combination != null) {
|
||||
history += currentSyllable.copy(initial = HangulJamo.Initial(combination))
|
||||
} else {
|
||||
if(final != null) history += currentSyllable.copy(final = final)
|
||||
else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
history += HangulSyllable(initial = initial)
|
||||
history +=
|
||||
if (combination != null) {
|
||||
currentSyllable.copy(initial = HangulJamo.Initial(combination))
|
||||
} else {
|
||||
if (final != null) {
|
||||
currentSyllable.copy(final = final)
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
HangulSyllable(initial = initial)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val pair = currentSyllable.final.codePoint to (final?.codePoint ?: -1)
|
||||
val combination = COMBINATION_TABLE_DUBEOLSIK[pair]
|
||||
if(combination != null) {
|
||||
history += currentSyllable.copy(final = HangulJamo.Final(combination, combinationPair = pair))
|
||||
history += if (combination != null) {
|
||||
currentSyllable.copy(final = HangulJamo.Final(combination, combinationPair = pair))
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
history += HangulSyllable(initial = initial)
|
||||
HangulSyllable(initial = initial)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -83,20 +84,21 @@ class HangulCombiner : Combiner {
|
|||
}
|
||||
is HangulJamo.Vowel -> {
|
||||
val medial = jamo.toMedial()
|
||||
if(currentSyllable.final == null) {
|
||||
if(currentSyllable.medial != null) {
|
||||
val combination = COMBINATION_TABLE_DUBEOLSIK[currentSyllable.medial.codePoint to (medial?.codePoint ?: -1)]
|
||||
if(combination != null) {
|
||||
history += currentSyllable.copy(medial = HangulJamo.Medial(combination))
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
history += HangulSyllable(medial = medial)
|
||||
}
|
||||
if (currentSyllable.final == null) {
|
||||
history +=
|
||||
if (currentSyllable.medial != null) {
|
||||
val combination = COMBINATION_TABLE_DUBEOLSIK[currentSyllable.medial.codePoint to (medial?.codePoint ?: -1)]
|
||||
if (combination != null) {
|
||||
currentSyllable.copy(medial = HangulJamo.Medial(combination))
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
HangulSyllable(medial = medial)
|
||||
}
|
||||
} else {
|
||||
history += currentSyllable.copy(medial = medial)
|
||||
currentSyllable.copy(medial = medial)
|
||||
}
|
||||
} else if(currentSyllable.final.combinationPair != null) {
|
||||
} else if (currentSyllable.final.combinationPair != null) {
|
||||
val pair = currentSyllable.final.combinationPair
|
||||
|
||||
history.removeAt(history.lastIndex)
|
||||
|
@ -119,46 +121,49 @@ class HangulCombiner : Combiner {
|
|||
}
|
||||
}
|
||||
is HangulJamo.Initial -> {
|
||||
if(currentSyllable.initial != null) {
|
||||
val combination = COMBINATION_TABLE_SEBEOLSIK[currentSyllable.initial.codePoint to jamo.codePoint]
|
||||
if(combination != null && currentSyllable.medial == null && currentSyllable.final == null) {
|
||||
history += currentSyllable.copy(initial = HangulJamo.Initial(combination))
|
||||
history +=
|
||||
if (currentSyllable.initial != null) {
|
||||
val combination = COMBINATION_TABLE_SEBEOLSIK[currentSyllable.initial.codePoint to jamo.codePoint]
|
||||
if (combination != null && currentSyllable.medial == null && currentSyllable.final == null) {
|
||||
currentSyllable.copy(initial = HangulJamo.Initial(combination))
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
HangulSyllable(initial = jamo)
|
||||
}
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
history += HangulSyllable(initial = jamo)
|
||||
currentSyllable.copy(initial = jamo)
|
||||
}
|
||||
} else {
|
||||
history += currentSyllable.copy(initial = jamo)
|
||||
}
|
||||
}
|
||||
is HangulJamo.Medial -> {
|
||||
if(currentSyllable.medial != null) {
|
||||
val combination = COMBINATION_TABLE_SEBEOLSIK[currentSyllable.medial.codePoint to jamo.codePoint]
|
||||
if(combination != null) {
|
||||
history += currentSyllable.copy(medial = HangulJamo.Medial(combination))
|
||||
history +=
|
||||
if (currentSyllable.medial != null) {
|
||||
val combination = COMBINATION_TABLE_SEBEOLSIK[currentSyllable.medial.codePoint to jamo.codePoint]
|
||||
if (combination != null) {
|
||||
currentSyllable.copy(medial = HangulJamo.Medial(combination))
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
HangulSyllable(medial = jamo)
|
||||
}
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
history += HangulSyllable(medial = jamo)
|
||||
currentSyllable.copy(medial = jamo)
|
||||
}
|
||||
} else {
|
||||
history += currentSyllable.copy(medial = jamo)
|
||||
}
|
||||
}
|
||||
is HangulJamo.Final -> {
|
||||
if(currentSyllable.final != null) {
|
||||
val combination = COMBINATION_TABLE_SEBEOLSIK[currentSyllable.final.codePoint to jamo.codePoint]
|
||||
if(combination != null) {
|
||||
history += currentSyllable.copy(final = HangulJamo.Final(combination))
|
||||
history +=
|
||||
if (currentSyllable.final != null) {
|
||||
val combination = COMBINATION_TABLE_SEBEOLSIK[currentSyllable.final.codePoint to jamo.codePoint]
|
||||
if (combination != null) {
|
||||
currentSyllable.copy(final = HangulJamo.Final(combination))
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
HangulSyllable(final = jamo)
|
||||
}
|
||||
} else {
|
||||
composingWord.append(currentSyllable.string)
|
||||
history.clear()
|
||||
history += HangulSyllable(final = jamo)
|
||||
currentSyllable.copy(final = jamo)
|
||||
}
|
||||
} else {
|
||||
history += currentSyllable.copy(final = jamo)
|
||||
}
|
||||
}
|
||||
// compiler bug? when it's not added, compiler complains that it's missing
|
||||
// but when added, linter (correctly) states it's unreachable anyway
|
||||
|
@ -190,8 +195,8 @@ class HangulCombiner : Combiner {
|
|||
val ordinal: Int get() = codePoint - 0x1100
|
||||
fun toConsonant(): Consonant? {
|
||||
val codePoint = COMPAT_CONSONANTS.getOrNull(CONVERT_INITIALS.indexOf(codePoint.toChar())) ?: return null
|
||||
if(codePoint.toInt() == 0) return null
|
||||
return Consonant(codePoint.toInt())
|
||||
if(codePoint.code == 0) return null
|
||||
return Consonant(codePoint.code)
|
||||
}
|
||||
}
|
||||
data class Medial(override val codePoint: Int) : HangulJamo() {
|
||||
|
@ -199,7 +204,7 @@ class HangulCombiner : Combiner {
|
|||
val ordinal: Int get() = codePoint - 0x1161
|
||||
fun toVowel(): Vowel? {
|
||||
val codePoint = COMPAT_VOWELS.getOrNull(CONVERT_MEDIALS.indexOf(codePoint.toChar())) ?: return null
|
||||
return Vowel(codePoint.toInt())
|
||||
return Vowel(codePoint.code)
|
||||
}
|
||||
}
|
||||
data class Final(override val codePoint: Int, val combinationPair: Pair<Int, Int>? = null) : HangulJamo() {
|
||||
|
@ -207,8 +212,8 @@ class HangulCombiner : Combiner {
|
|||
val ordinal: Int get() = codePoint - 0x11a7
|
||||
fun toConsonant(): Consonant? {
|
||||
val codePoint = COMPAT_CONSONANTS.getOrNull(CONVERT_FINALS.indexOf(codePoint.toChar())) ?: return null
|
||||
if(codePoint.toInt() == 0) return null
|
||||
return Consonant(codePoint.toInt())
|
||||
if(codePoint.code == 0) return null
|
||||
return Consonant(codePoint.code)
|
||||
}
|
||||
}
|
||||
data class Consonant(override val codePoint: Int) : HangulJamo() {
|
||||
|
@ -216,13 +221,13 @@ class HangulCombiner : Combiner {
|
|||
val ordinal: Int get() = codePoint - 0x3131
|
||||
fun toInitial(): Initial? {
|
||||
val codePoint = CONVERT_INITIALS.getOrNull(COMPAT_CONSONANTS.indexOf(codePoint.toChar())) ?: return null
|
||||
if(codePoint.toInt() == 0) return null
|
||||
return Initial(codePoint.toInt())
|
||||
if(codePoint.code == 0) return null
|
||||
return Initial(codePoint.code)
|
||||
}
|
||||
fun toFinal(): Final? {
|
||||
val codePoint = CONVERT_FINALS.getOrNull(COMPAT_CONSONANTS.indexOf(codePoint.toChar())) ?: return null
|
||||
if(codePoint.toInt() == 0) return null
|
||||
return Final(codePoint.toInt())
|
||||
if(codePoint.code == 0) return null
|
||||
return Final(codePoint.code)
|
||||
}
|
||||
}
|
||||
data class Vowel(override val codePoint: Int) : HangulJamo() {
|
||||
|
@ -230,8 +235,8 @@ class HangulCombiner : Combiner {
|
|||
val ordinal: Int get() = codePoint - 0x314f1
|
||||
fun toMedial(): Medial? {
|
||||
val codePoint = CONVERT_MEDIALS.getOrNull(COMPAT_VOWELS.indexOf(codePoint.toChar())) ?: return null
|
||||
if(codePoint.toInt() == 0) return null
|
||||
return Medial(codePoint.toInt())
|
||||
if(codePoint.code == 0) return null
|
||||
return Medial(codePoint.code)
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
|
@ -265,7 +270,7 @@ class HangulCombiner : Combiner {
|
|||
val uncombined: String get() = (initial?.string ?: "") + (medial?.string ?: "") + (final?.string ?: "")
|
||||
val uncombinedCompat: String get() = (initial?.toConsonant()?.string ?: "") +
|
||||
(medial?.toVowel()?.string ?: "") + (final?.toConsonant()?.string ?: "")
|
||||
val string: String get() = if(this.combinable) this.combined else this.uncombinedCompat
|
||||
val string: String get() = if (this.combinable) this.combined else this.uncombinedCompat
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -320,7 +325,7 @@ class HangulCombiner : Combiner {
|
|||
0x11ba to 0x11ba to 0x11bb // ㅆ
|
||||
)
|
||||
private fun createEventChainFromSequence(text: CharSequence, originalEvent: Event): Event {
|
||||
return Event.createSoftwareTextEvent(text, Constants.CODE_OUTPUT_TEXT, originalEvent);
|
||||
return Event.createSoftwareTextEvent(text, Constants.CODE_OUTPUT_TEXT, originalEvent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ object HangulEventDecoder {
|
|||
else Event.createCombiningEvent(event)
|
||||
}
|
||||
|
||||
val LAYOUT_DUBEOLSIK_STANDARD = mapOf<Int, Pair<Int, Int>>(
|
||||
private val LAYOUT_DUBEOLSIK_STANDARD = mapOf<Int, Pair<Int, Int>>(
|
||||
45 to (0x3142 to 0x3143),
|
||||
51 to (0x3148 to 0x3149),
|
||||
33 to (0x3137 to 0x3138),
|
||||
|
@ -53,7 +53,7 @@ object HangulEventDecoder {
|
|||
41 to (0x3161 to 0x3161)
|
||||
)
|
||||
|
||||
val LAYOUT_SEBEOLSIK_390 = mapOf<Int, Pair<Int, Int>>(
|
||||
private val LAYOUT_SEBEOLSIK_390 = mapOf<Int, Pair<Int, Int>>(
|
||||
8 to (0x11c2 to 0x11bd),
|
||||
9 to (0x11bb to 0x0040),
|
||||
10 to (0x11b8 to 0x0023),
|
||||
|
@ -100,7 +100,7 @@ object HangulEventDecoder {
|
|||
76 to (0x1169 to 0x003f)
|
||||
)
|
||||
|
||||
val LAYOUT_SEBEOLSIK_FINAL = mapOf<Int, Pair<Int, Int>>(
|
||||
private val LAYOUT_SEBEOLSIK_FINAL = mapOf<Int, Pair<Int, Int>>(
|
||||
68 to (0x002a to 0x203b),
|
||||
|
||||
8 to (0x11c2 to 0x11a9),
|
||||
|
@ -154,7 +154,7 @@ object HangulEventDecoder {
|
|||
76 to (0x1169 to 0x0021)
|
||||
)
|
||||
|
||||
val LAYOUTS = mapOf<String, Map<Int, Pair<Int, Int>>>(
|
||||
private val LAYOUTS = mapOf<String, Map<Int, Pair<Int, Int>>>(
|
||||
"korean" to LAYOUT_DUBEOLSIK_STANDARD,
|
||||
"korean_sebeolsik_390" to LAYOUT_SEBEOLSIK_390,
|
||||
"korean_sebeolsik_final" to LAYOUT_SEBEOLSIK_FINAL
|
||||
|
|
Loading…
Add table
Reference in a new issue