spiegel-keyman/common/engine/keyboardprocessor/src/kmx/kmx_options.cpp

204 lines
6.1 KiB
C++

/*
Copyright: Copyright (C) 2003-2018 SIL International.
Authors: mcdurdin
*/
#include "kmx_processor.h"
#include <option.hpp>
#include <state.hpp>
using namespace km::kbp::kmx;
int KMX_Options::_GetIndex(std::u16string const &key) const {
auto i = 0U;
;
for (auto sp = _kp->Keyboard->dpStoreArray;
i != _kp->Keyboard->cxStoreArray; ++i, ++sp)
{
if (sp->dpName && sp->dpName == key) break;
}
return -1;
}
void KMX_Options::AddOptionsStoresFromXString(PKMX_WCHAR s) {
auto idx = 0U;
for (; s && *s; s = incxstr(s)) {
if (*s == UC_SENTINEL) {
switch (*(s + 1)) {
case CODE_IFOPT:
case CODE_SETOPT:
case CODE_SAVEOPT:
case CODE_RESETOPT:
idx = *(s + 2) - 1;
if (idx >= 0 && idx < _kp->Keyboard->cxStoreArray && _kp->Keyboard->dpStoreArray[idx].dpName != NULL) {
_kp->KeyboardOptions[idx].OriginalStore = _kp->Keyboard->dpStoreArray[idx].dpString;
}
break;
}
}
}
}
void KMX_Options::Load(options *options, std::u16string const &key) {
LPSTORE sp;
auto i = 0U;
assert(options != nullptr);
assert(!key.empty());
if (options == nullptr || key.empty()) return;
for (i = 0, sp = _kp->Keyboard->dpStoreArray; i < _kp->Keyboard->cxStoreArray; i++, sp++) {
if (_kp->KeyboardOptions[i].OriginalStore != NULL
&& sp->dpName != NULL
&& u16icmp(sp->dpName, key.c_str()) == 0) {
Reset(options, i);
return;
}
}
// No entry was found.
assert(false);
}
void KMX_Options::Init(std::vector<option> &opts) {
opts.clear();
_kp->KeyboardOptions = new INTKEYBOARDOPTIONS[_kp->Keyboard->cxStoreArray];
memset(_kp->KeyboardOptions, 0, sizeof(INTKEYBOARDOPTIONS) * _kp->Keyboard->cxStoreArray);
// Scan all rules to find options references.
auto i = 0U, j = 0U;
LPGROUP gp;
LPKEY kkp;
for (i = 0U, gp = _kp->Keyboard->dpGroupArray; i < _kp->Keyboard->cxGroupArray; i++, gp++) {
for (j = 0U, kkp = gp->dpKeyArray; j < gp->cxKeyArray; j++, kkp++) {
AddOptionsStoresFromXString(kkp->dpContext);
AddOptionsStoresFromXString(kkp->dpOutput);
}
AddOptionsStoresFromXString(gp->dpMatch);
AddOptionsStoresFromXString(gp->dpNoMatch);
}
LPINTKEYBOARDOPTIONS ko;
int n = 0;
for (i = 0, ko = _kp->KeyboardOptions; i < _kp->Keyboard->cxStoreArray; i++, ko++) {
if (ko->OriginalStore != NULL) {
n++;
}
}
if (n == 0) {
opts.emplace_back(); // Terminate the options array
return;
}
// Setup the default options for KPAPI to maintain
LPSTORE sp;
for (n = 0, i = 0, ko = _kp->KeyboardOptions, sp = _kp->Keyboard->dpStoreArray; i < _kp->Keyboard->cxStoreArray; i++, sp++, ko++) {
if (ko->OriginalStore == NULL) continue;
opts.emplace_back(KM_KBP_OPT_KEYBOARD, sp->dpName, sp->dpString);
n++;
}
opts.emplace_back(); // Terminate the options array
}
KMX_Options::~KMX_Options()
{
//TODO: move ownership of _kp->KeyboardOptions into this class (so we control lifetime of it here)
if (!_kp || !_kp->Keyboard || !_kp->KeyboardOptions) return;
for(KMX_DWORD i = 0; i < _kp->Keyboard->cxStoreArray; i++)
if(_kp->KeyboardOptions[i].Value)
{
_kp->Keyboard->dpStoreArray[i].dpString = _kp->KeyboardOptions[i].OriginalStore;
delete _kp->KeyboardOptions[i].Value;
}
delete _kp->KeyboardOptions;
_kp->KeyboardOptions = NULL;
}
void KMX_Options::Set(int nStoreToSet, std::u16string const & rValueToSet)
{
assert(_kp != NULL);
assert(_kp->Keyboard != NULL);
assert(_kp->KeyboardOptions != NULL);
assert(nStoreToSet >= 0);
assert(nStoreToSet < (int) _kp->Keyboard->cxStoreArray);
auto & rStoreToSetValue = _kp->KeyboardOptions[nStoreToSet].Value;
if(rStoreToSetValue)
{
delete rStoreToSetValue;
}
rStoreToSetValue = new std::u16string::value_type[rValueToSet.size()+1];
u16cpy(rStoreToSetValue, /*u16len(sp->dpString)+1,*/ rValueToSet.c_str());
_kp->Keyboard->dpStoreArray[nStoreToSet].dpString = rStoreToSetValue;
}
void KMX_Options::Set(int nStoreToSet, int nStoreToRead)
{
assert(_kp != NULL);
assert(_kp->Keyboard != NULL);
assert(_kp->KeyboardOptions != NULL);
assert(nStoreToSet >= 0);
assert(nStoreToSet < (int) _kp->Keyboard->cxStoreArray);
assert(nStoreToRead >= 0);
assert(nStoreToRead < (int) _kp->Keyboard->cxStoreArray);
std::u16string const & rStoreToReadValue = _kp->Keyboard->dpStoreArray[nStoreToRead].dpString;
Set(nStoreToSet, rStoreToReadValue);
}
void KMX_Options::Reset(options *options, int nStoreToReset)
{
assert(_kp != NULL);
assert(_kp->Keyboard != NULL);
assert(_kp->KeyboardOptions != NULL);
assert(nStoreToReset >= 0);
assert(nStoreToReset < (int) _kp->Keyboard->cxStoreArray);
auto & rStoreToReset = _kp->Keyboard->dpStoreArray[nStoreToReset];
auto & rOptionToReset = _kp->KeyboardOptions[nStoreToReset];
if (rOptionToReset.Value)
{
rStoreToReset.dpString = rOptionToReset.OriginalStore;
delete rOptionToReset.Value;
rOptionToReset.Value = nullptr;
}
if(rStoreToReset.dpName == nullptr) return;
// Now we need to go back and get any saved value from KPAPI. internal_value is owned by options api
km_kbp_cp const *internal_value = options->lookup(km_kbp_option_scope(KM_KBP_OPT_KEYBOARD), _kp->Keyboard->dpStoreArray[nStoreToReset].dpName);
if(internal_value) {
// Copy the value from KPAPI
_kp->KeyboardOptions[nStoreToReset].Value = new KMX_WCHAR[u16len(internal_value) + 1];
u16cpy(_kp->KeyboardOptions[nStoreToReset].Value, /*u16len(val) + 1,*/ internal_value);
_kp->Keyboard->dpStoreArray[nStoreToReset].dpString = _kp->KeyboardOptions[nStoreToReset].Value;
}
}
void KMX_Options::Save(km_kbp_state *state, int nStoreToSave)
{
assert(_kp != NULL);
assert(_kp->Keyboard != NULL);
assert(_kp->KeyboardOptions != NULL);
assert(nStoreToSave >= 0);
assert(nStoreToSave < (int)_kp->Keyboard->cxStoreArray);
auto const & rStoreToSave = _kp->Keyboard->dpStoreArray[nStoreToSave];
if (rStoreToSave.dpName == nullptr) return;
auto opt_ = state->options().assign(state, KM_KBP_OPT_KEYBOARD, rStoreToSave.dpName, rStoreToSave.dpString);
state->actions().push_persist(*static_cast<option const *>(opt_));
}