mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-22 00:07:46 +00:00
163 lines
4 KiB
C++
163 lines
4 KiB
C++
/*
|
|
Copyright: Copyright (C) 2003-2018 SIL International.
|
|
Authors: mcdurdin
|
|
*/
|
|
#include <kmx/kmx_processevent.h>
|
|
|
|
using namespace km::kbp;
|
|
using namespace kmx;
|
|
|
|
/* KMX_Context */
|
|
|
|
KMX_Context::KMX_Context()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
void KMX_Context::Add(KMX_WCHAR ch)
|
|
{
|
|
DebugLog("KMX_Context::Add(%x): ENTER [%d]: %s", ch, pos, Debug_UnicodeString(CurContext));
|
|
|
|
if(pos == MAXCONTEXT - 1)
|
|
{
|
|
auto p = incxstr(CurContext);
|
|
auto n = (int)(p - CurContext);
|
|
memmove(CurContext, p, (MAXCONTEXT - n) * sizeof(KMX_WCHAR));
|
|
pos -= n;
|
|
}
|
|
|
|
CurContext[pos++] = ch;
|
|
CurContext[pos] = 0;
|
|
|
|
// DebugLog("KMX_Context::Add(%x): EXIT [%d]: %s", ch, pos, Debug_UnicodeString(CurContext));
|
|
}
|
|
|
|
KMX_WCHAR *KMX_Context::BufMax(int n)
|
|
{
|
|
KMX_WCHAR *p = (KMX_WCHAR *) u16chr(CurContext, 0);
|
|
if (CurContext == p || n == 0)
|
|
return p; // empty context or 0 characters requested, return pointer to end of context
|
|
|
|
KMX_WCHAR *q = p;
|
|
for (; p != NULL && p > CurContext && (intptr_t)(q-p) < n; p = decxstr(p, CurContext))
|
|
; // ; on new line to tell compiler empty loop is intentional
|
|
|
|
if ((intptr_t)(q-p) > n)
|
|
p = incxstr(p); // Copes with deadkey or supplementary pair at start of returned buffer making it too long
|
|
|
|
return p;
|
|
}
|
|
|
|
KMX_WCHAR *KMX_Context::Buf(int n)
|
|
{
|
|
KMX_WCHAR *p;
|
|
|
|
for(p = (KMX_WCHAR *) u16chr(CurContext, 0); p != NULL && n > 0 && p > CurContext; p = decxstr(p, CurContext), n--);
|
|
|
|
if(n > 0) return NULL;
|
|
return p;
|
|
}
|
|
|
|
void KMX_Context::Delete()
|
|
{
|
|
DebugLog("KMX_Context::Delete: ENTER [%d]: %s", pos, Debug_UnicodeString(CurContext));
|
|
if (CharIsDeadkey()) {
|
|
pos -= 2;
|
|
} else if (CharIsSurrogatePair()) {
|
|
pos--;
|
|
}
|
|
|
|
if(pos > 0) pos--;
|
|
CurContext[pos] = 0;
|
|
// DebugLog("KMX_Context::Delete: EXIT [%d]: %s", pos, Debug_UnicodeString(CurContext));
|
|
}
|
|
|
|
void KMX_Context::Reset()
|
|
{
|
|
DebugLog("KMX_Context::Reset");
|
|
pos = 0;
|
|
CurContext[0] = 0;
|
|
}
|
|
|
|
void KMX_Context::Get(KMX_WCHAR *buf, int bufsize)
|
|
{
|
|
for (KMX_WCHAR *p = this->BufMax(bufsize); *p && bufsize > 0; p++, bufsize--)
|
|
{
|
|
*buf = *p;
|
|
if(Uni_IsSurrogate1(*p) && bufsize - 2 > 0) {
|
|
buf++; p++;
|
|
*buf = *p;
|
|
bufsize--;
|
|
}
|
|
buf++;
|
|
}
|
|
|
|
*buf = 0;
|
|
}
|
|
|
|
void KMX_Context::CopyFrom(KMX_Context *source) // I3575
|
|
{
|
|
DebugLog("KMX_Context::CopyFrom source=%s; before copy, dest=%s", Debug_UnicodeString(source->CurContext, 0), Debug_UnicodeString(CurContext, 1));
|
|
u16cpy(CurContext, /*_countof(CurContext),*/ source->CurContext);
|
|
pos = source->pos;
|
|
}
|
|
|
|
|
|
void KMX_Context::Set(const KMX_WCHAR *buf)
|
|
{
|
|
DebugLog("KMX_Context::Set(): ENTER [%d]: (%d) %s", pos, u16len(CurContext), Debug_UnicodeString(CurContext, 1));
|
|
DebugLog(" (%d) %s", u16len(buf), Debug_UnicodeString(buf));
|
|
const KMX_WCHAR *p;
|
|
KMX_WCHAR *q;
|
|
|
|
// We may be past a buffer longer than our internal
|
|
// buffer. So we shift to make sure we capture the end
|
|
// of the string, not the start
|
|
p = u16chr(buf, 0);
|
|
q = (KMX_WCHAR*)p;
|
|
while(p != NULL && p > buf && (intptr_t)(q-p) < MAXCONTEXT - 1) {
|
|
p = decxstr((KMX_WCHAR*)p, (KMX_WCHAR*)buf);
|
|
}
|
|
|
|
// If the first character in the buffer is a surrogate pair,
|
|
// or a deadkey, our buffer may be too long, so move to the
|
|
// next character in the buffer
|
|
if ((intptr_t)(q-p) > MAXCONTEXT - 1) {
|
|
p = incxstr((KMX_WCHAR*)p);
|
|
}
|
|
|
|
for(q = CurContext; *p; p++, q++)
|
|
{
|
|
*q = *p;
|
|
}
|
|
|
|
*q = 0;
|
|
pos = (int)(intptr_t)(q-CurContext);
|
|
CurContext[MAXCONTEXT-1] = 0;
|
|
|
|
// DebugLog("KMX_Context::Set(): EXIT [%d]: (%d) %s", pos, u16len(CurContext), Debug_UnicodeString(CurContext, 1));
|
|
// DebugLog(" (%d) %s", u16len(buf), Debug_UnicodeString(buf));
|
|
}
|
|
|
|
KMX_BOOL KMX_Context::CharIsDeadkey()
|
|
{
|
|
if(pos < 3)
|
|
return FALSE;
|
|
return CurContext[pos-3] == UC_SENTINEL &&
|
|
CurContext[pos-2] == CODE_DEADKEY;
|
|
}
|
|
|
|
KMX_BOOL KMX_Context::CharIsSurrogatePair()
|
|
{
|
|
if (pos < 2)
|
|
return FALSE;
|
|
|
|
return Uni_IsSurrogate1(CurContext[pos - 2]) &&
|
|
Uni_IsSurrogate2(CurContext[pos - 1]);
|
|
}
|
|
|
|
KMX_BOOL KMX_Context::IsEmpty()
|
|
{
|
|
return (KMX_BOOL)(pos == 0);
|
|
}
|
|
|