Comments only, no code changes. Replaces vague or personified phrasing with explicit statements of what the code does and why, uses bullet lists for multi-case behavior, and fixes the settings path in WindowSettings.h (~/.config/sloposk/sloposk.conf). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
2.6 KiB
C++
92 lines
2.6 KiB
C++
#include "DeadKeys.h"
|
|
|
|
#include "layout/KeymapKeys.h"
|
|
|
|
#include <xkbcommon/xkbcommon-compose.h>
|
|
#include <xkbcommon/xkbcommon.h>
|
|
|
|
namespace {
|
|
|
|
QByteArray systemLocale()
|
|
{
|
|
for (const char *name : {"LC_ALL", "LC_CTYPE", "LANG"}) {
|
|
if (const QByteArray value = qgetenv(name); !value.isEmpty())
|
|
return value;
|
|
}
|
|
return "C";
|
|
}
|
|
|
|
} // namespace
|
|
|
|
DeadKeys::DeadKeys(const QString &locale)
|
|
: m_context(xkb_context_new(XKB_CONTEXT_NO_FLAGS), xkb_context_unref)
|
|
, m_table(nullptr, xkb_compose_table_unref)
|
|
, m_state(nullptr, xkb_compose_state_unref)
|
|
{
|
|
// The C locale has no compose table; en_US.UTF-8's is the common base of all.
|
|
const QByteArray name = locale.isEmpty() ? systemLocale() : locale.toUtf8();
|
|
for (const QByteArray &candidate : {name, QByteArrayLiteral("en_US.UTF-8")}) {
|
|
m_table.reset(xkb_compose_table_new_from_locale(m_context.get(), candidate.constData(),
|
|
XKB_COMPOSE_COMPILE_NO_FLAGS));
|
|
if (m_table)
|
|
break;
|
|
}
|
|
if (m_table)
|
|
m_state.reset(xkb_compose_state_new(m_table.get(), XKB_COMPOSE_STATE_NO_FLAGS));
|
|
}
|
|
|
|
DeadKeys::~DeadKeys() = default;
|
|
|
|
QString DeadKeys::press(quint32 deadKeysym)
|
|
{
|
|
if (!m_state) {
|
|
m_pending += deadKeyText(deadKeysym);
|
|
return {};
|
|
}
|
|
xkb_compose_state_feed(m_state.get(), deadKeysym);
|
|
switch (xkb_compose_state_get_status(m_state.get())) {
|
|
case XKB_COMPOSE_COMPOSED: {
|
|
const QString composed = composedText();
|
|
cancel();
|
|
return composed;
|
|
}
|
|
case XKB_COMPOSE_CANCELLED: {
|
|
// No compose sequence continues with this key: flush the pending accents
|
|
// and start a new sequence.
|
|
const QString accents = m_pending;
|
|
cancel();
|
|
return accents + press(deadKeysym);
|
|
}
|
|
default:
|
|
m_pending += deadKeyText(deadKeysym);
|
|
return {};
|
|
}
|
|
}
|
|
|
|
QString DeadKeys::composedText() const
|
|
{
|
|
char utf8[64];
|
|
xkb_compose_state_get_utf8(m_state.get(), utf8, sizeof utf8);
|
|
return QString::fromUtf8(utf8);
|
|
}
|
|
|
|
QString DeadKeys::compose(const QString &text)
|
|
{
|
|
QString result = m_pending + text;
|
|
if (m_state && !text.isEmpty()) {
|
|
const char32_t ucs = text.toUcs4().first();
|
|
xkb_compose_state_feed(m_state.get(), xkb_utf32_to_keysym(ucs));
|
|
if (xkb_compose_state_get_status(m_state.get()) == XKB_COMPOSE_COMPOSED)
|
|
result = composedText() + text.mid(QString::fromUcs4(&ucs, 1).size());
|
|
}
|
|
cancel();
|
|
return result;
|
|
}
|
|
|
|
void DeadKeys::cancel()
|
|
{
|
|
m_pending.clear();
|
|
if (m_state)
|
|
xkb_compose_state_reset(m_state.get());
|
|
}
|