4541f4aea8
X-SVN-Rev: 649
152 lines
4.7 KiB
C++
152 lines
4.7 KiB
C++
/*
|
|
**********************************************************************
|
|
* Copyright (c) 2000, International Business Machines
|
|
* Corporation and others. All Rights Reserved.
|
|
**********************************************************************
|
|
* Date Name Description
|
|
* 01/17/2000 aliu Ported from Java.
|
|
**********************************************************************
|
|
*/
|
|
#include "unicode/jamohang.h"
|
|
#include "unicode/rep.h"
|
|
#include "unicode/unifilt.h"
|
|
#include "unicode/unicode.h"
|
|
|
|
/**
|
|
* ID for this transliterator.
|
|
*/
|
|
const char* JamoHangulTransliterator::_ID = "Jamo-Hangul";
|
|
|
|
/**
|
|
* Constructs a transliterator.
|
|
*/
|
|
JamoHangulTransliterator::JamoHangulTransliterator(UnicodeFilter* adoptedFilter) :
|
|
Transliterator(_ID, adoptedFilter) {
|
|
setMaximumContextLength(3);
|
|
}
|
|
|
|
/**
|
|
* Copy constructor.
|
|
*/
|
|
JamoHangulTransliterator::JamoHangulTransliterator(const JamoHangulTransliterator& o) :
|
|
Transliterator(o) {
|
|
}
|
|
|
|
/**
|
|
* Assignment operator.
|
|
*/
|
|
JamoHangulTransliterator& JamoHangulTransliterator::operator=(
|
|
const JamoHangulTransliterator& o) {
|
|
Transliterator::operator=(o);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Transliterator API.
|
|
*/
|
|
Transliterator* JamoHangulTransliterator::clone(void) const {
|
|
return new JamoHangulTransliterator(*this);
|
|
}
|
|
|
|
/**
|
|
* Implements {@link Transliterator#handleTransliterate}.
|
|
*/
|
|
void JamoHangulTransliterator::handleTransliterate(Replaceable& text, Position& offsets,
|
|
bool_t isIncremental) const {
|
|
/**
|
|
* Performs transliteration changing Jamo to Hangul
|
|
*/
|
|
int32_t cursor = offsets.cursor;
|
|
int32_t limit = offsets.limit;
|
|
if (cursor >= limit) return;
|
|
|
|
int32_t count;
|
|
|
|
UChar last = filteredCharAt(text, cursor++);
|
|
UnicodeString str("a", 1);
|
|
while (cursor <= limit) {
|
|
UChar next = 0xFFFF; // go over end of string, just in case
|
|
if (cursor < limit) next = filteredCharAt(text, cursor);
|
|
UChar replacement = composeHangul(last, next, count);
|
|
if (replacement != last) {
|
|
str[0] = replacement;
|
|
text.handleReplaceBetween(cursor-1, cursor-1 + count, str);
|
|
limit = limit - count + 1; // fix up limit 2 => -1, 1 => 0
|
|
last = replacement;
|
|
if (next == 0xFFFF) break;
|
|
// don't change cursor, so we revisit char
|
|
} else {
|
|
++cursor;
|
|
last = next;
|
|
}
|
|
}
|
|
|
|
offsets.limit = limit + 1;
|
|
offsets.cursor = cursor;
|
|
}
|
|
|
|
// These constants are from the Unicode book's algorithm.
|
|
|
|
#define SBase (0xAC00)
|
|
#define LBase (0x1100)
|
|
#define VBase (0x1161)
|
|
#define TBase (0x11A7)
|
|
#define LCount (19)
|
|
#define VCount (21)
|
|
#define TCount (28)
|
|
#define NCount (VCount * TCount) // 588
|
|
#define SCount (LCount * NCount) // 11172
|
|
#define LLimit (0x1200)
|
|
|
|
/**
|
|
* Return composed character (if it is a modern jamo)
|
|
* last otherwise.
|
|
* If there is a replacement, returns count[0] = 2 if ch was used, 1 otherwise
|
|
*/
|
|
UChar JamoHangulTransliterator::composeHangul(UChar last, UChar ch, int32_t& count) {
|
|
count = 2; // default is replace 2 chars
|
|
// check to see if two current characters are L and V
|
|
int32_t LIndex = last - LBase;
|
|
if (0 <= LIndex && LIndex < LCount) {
|
|
int32_t VIndex = ch - VBase;
|
|
if (0 <= VIndex && VIndex < VCount) {
|
|
// make syllable of form LV
|
|
return (UChar)(SBase + (LIndex * VCount + VIndex) * TCount);
|
|
} else {
|
|
// it is isolated, so fix!
|
|
count = 1; // not using ch
|
|
return (UChar)(SBase + (LIndex * VCount) * TCount);
|
|
}
|
|
}
|
|
|
|
// if neither case was true, see if we have an isolated Jamo we need to fix
|
|
if (LBase <= last && last < LLimit) {
|
|
// need to fix: it is either medial or final!
|
|
int32_t VIndex = last - VBase;
|
|
if (0 <= VIndex && VIndex < VCount) {
|
|
LIndex = 0x110B - LBase; // use empty consonant
|
|
// make syllable of form LV
|
|
count = 1; // not using ch
|
|
return (UChar)(SBase + (LIndex * VCount + VIndex) * TCount);
|
|
}
|
|
// ok, see if final. Use null consonant + a + final
|
|
int32_t TIndex = last - TBase;
|
|
if (0 <= TIndex && TIndex <= TCount) { // need to fix!
|
|
count = 1; // not using ch
|
|
return (UChar)(0xC544 + TIndex);
|
|
}
|
|
}
|
|
|
|
// check to see if two current characters are LV and T
|
|
int32_t SIndex = last - SBase;
|
|
if (0 <= SIndex && SIndex < SCount && (SIndex % TCount) == 0) {
|
|
int32_t TIndex = ch - TBase;
|
|
if (0 <= TIndex && TIndex <= TCount) {
|
|
// make syllable of form LVT
|
|
return (UChar)(last + TIndex);
|
|
}
|
|
}
|
|
|
|
return last;
|
|
}
|