aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/openwnn/3rdparty/openwnn/wnnEngine/composingtext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/openwnn/3rdparty/openwnn/wnnEngine/composingtext.cpp')
-rw-r--r--src/plugins/openwnn/3rdparty/openwnn/wnnEngine/composingtext.cpp490
1 files changed, 490 insertions, 0 deletions
diff --git a/src/plugins/openwnn/3rdparty/openwnn/wnnEngine/composingtext.cpp b/src/plugins/openwnn/3rdparty/openwnn/wnnEngine/composingtext.cpp
new file mode 100644
index 00000000..1f9ca4ff
--- /dev/null
+++ b/src/plugins/openwnn/3rdparty/openwnn/wnnEngine/composingtext.cpp
@@ -0,0 +1,490 @@
+/*
+ * Qt implementation of OpenWnn library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright (C) 2008-2012 OMRON SOFTWARE Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "composingtext.h"
+
+#include <QtCore/private/qobject_p.h>
+
+class ComposingTextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(ComposingText)
+public:
+ ComposingTextPrivate(ComposingText *q_ptr) :
+ QObjectPrivate(),
+ q_ptr(q_ptr)
+ {
+ memset(mCursor, 0, sizeof(mCursor));
+ }
+
+ void modifyUpper(ComposingText::TextLayer layer, int mod_from, int mod_len, int org_len)
+ {
+ Q_Q(ComposingText);
+ if (layer >= (ComposingText::MAX_LAYER - 1)) {
+ /* no layer above */
+ return;
+ }
+
+ ComposingText::TextLayer uplayer = (ComposingText::TextLayer)(layer + 1);
+ QList<StrSegment> &strUplayer = mStringLayer[uplayer];
+ if (strUplayer.size() <= 0) {
+ /*
+ * if there is no element on above layer,
+ * add a element includes whole elements of the lower layer.
+ */
+ strUplayer.append(StrSegment(q->toString(layer), 0, mStringLayer[layer].size() - 1));
+ modifyUpper(uplayer, 0, 1, 0);
+ return;
+ }
+
+ int mod_to = mod_from + ((mod_len == 0) ? 0 : (mod_len - 1));
+ int org_to = mod_from + ((org_len == 0) ? 0 : (org_len - 1));
+ StrSegment &last = strUplayer[strUplayer.size() - 1];
+ if (last.to < mod_from) {
+ /* add at the tail */
+ last.to = mod_to;
+ last.string = q->toString(layer, last.from, last.to);
+ modifyUpper(uplayer, strUplayer.size()-1, 1, 1);
+ return;
+ }
+
+ int uplayer_mod_from = -1;
+ int uplayer_org_to = -1;
+ for (int i = 0; i < strUplayer.size(); i++) {
+ const StrSegment &ss = strUplayer.at(i);
+ if (ss.from > mod_from) {
+ if (ss.to <= org_to) {
+ /* the segment is included */
+ if (uplayer_mod_from < 0) {
+ uplayer_mod_from = i;
+ }
+ uplayer_org_to = i;
+ } else {
+ /* included in this segment */
+ uplayer_org_to = i;
+ break;
+ }
+ } else {
+ if (org_len == 0 && ss.from == mod_from) {
+ /* when an element is added */
+ uplayer_mod_from = i - 1;
+ uplayer_org_to = i - 1;
+ break;
+ } else {
+ /* start from this segment */
+ uplayer_mod_from = i;
+ uplayer_org_to = i;
+ if (ss.to >= org_to) {
+ break;
+ }
+ }
+ }
+ }
+
+ int diff = mod_len - org_len;
+ if (uplayer_mod_from >= 0) {
+ /* update an element */
+ StrSegment &ss = strUplayer[uplayer_mod_from];
+ int last_to = ss.to;
+ int next = uplayer_mod_from + 1;
+ for (int i = next; i <= uplayer_org_to; i++) {
+ const StrSegment &ss2 = strUplayer.at(next);
+ if (last_to > ss2.to) {
+ last_to = ss2.to;
+ }
+ strUplayer.removeAt(next);
+ }
+ ss.to = (last_to < mod_to)? mod_to : (last_to + diff);
+
+ ss.string = q->toString(layer, ss.from, ss.to);
+
+ for (int i = next; i < strUplayer.size(); i++) {
+ StrSegment &ss2 = strUplayer[i];
+ ss2.from += diff;
+ ss2.to += diff;
+ }
+
+ modifyUpper(uplayer, uplayer_mod_from, 1, uplayer_org_to - uplayer_mod_from + 1);
+ } else {
+ /* add an element at the head */
+ strUplayer.insert(0, StrSegment(q->toString(layer, mod_from, mod_to), mod_from, mod_to));
+ for (int i = 1; i < strUplayer.size(); i++) {
+ StrSegment &ss = strUplayer[i];
+ ss.from += diff;
+ ss.to += diff;
+ }
+ modifyUpper(uplayer, 0, 1, 0);
+ }
+ }
+
+ void deleteStrSegment0(ComposingText::TextLayer layer, int from, int to, int diff)
+ {
+ QList<StrSegment> &strLayer = mStringLayer[layer];
+ if (diff != 0) {
+ for (int i = to + 1; i < strLayer.size(); i++) {
+ StrSegment &ss = strLayer[i];
+ ss.from -= diff;
+ ss.to -= diff;
+ }
+ }
+ for (int i = from; i <= to; i++) {
+ strLayer.removeAt(from);
+ }
+ }
+
+ void replaceStrSegment0(ComposingText::TextLayer layer, const QList<StrSegment> &str, int from, int to)
+ {
+ QList<StrSegment> &strLayer = mStringLayer[layer];
+
+ if (from < 0 || from > strLayer.size()) {
+ from = strLayer.size();
+ }
+ if (to < 0 || to > strLayer.size()) {
+ to = strLayer.size();
+ }
+ for (int i = from; i <= to; i++) {
+ strLayer.removeAt(from);
+ }
+ for (int i = str.size() - 1; i >= 0; i--) {
+ strLayer.insert(from, str.at(i));
+ }
+
+ modifyUpper(layer, from, str.size(), to - from + 1);
+ }
+
+ ComposingText *q_ptr;
+ QList<StrSegment> mStringLayer[ComposingText::MAX_LAYER];
+ int mCursor[ComposingText::MAX_LAYER];
+
+};
+
+ComposingText::ComposingText(QObject *parent) :
+ QObject(*new ComposingTextPrivate(this), parent)
+{
+
+}
+
+ComposingText::~ComposingText()
+{
+
+}
+
+StrSegment ComposingText::getStrSegment(TextLayer layer, int pos) const
+{
+ Q_D(const ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return StrSegment();
+
+ const QList<StrSegment> &strLayer = d->mStringLayer[layer];
+ if (pos < 0) {
+ pos = strLayer.size() - 1;
+ }
+ if (pos >= strLayer.size() || pos < 0) {
+ return StrSegment();
+ }
+ return strLayer.at(pos);
+}
+
+void ComposingText::debugout() const
+{
+ Q_D(const ComposingText);
+ for (int i = LAYER0; i < MAX_LAYER; i++) {
+ QString tmp;
+ for (QList<StrSegment>::ConstIterator it = d->mStringLayer[i].constBegin();
+ it != d->mStringLayer[i].constEnd(); it++) {
+ tmp += QStringLiteral("(%1,%2,%3)").arg(it->string).arg(it->from).arg(it->to);
+ }
+ }
+}
+
+QString ComposingText::toString(TextLayer layer, int from, int to) const
+{
+ Q_D(const ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return QString();
+
+ QString buf;
+ const QList<StrSegment> &strLayer = d->mStringLayer[layer];
+
+ for (int i = from; i <= to; i++) {
+ const StrSegment &ss = strLayer.at(i);
+ buf.append(ss.string);
+ }
+ return buf;
+}
+
+QString ComposingText::toString(TextLayer layer) const
+{
+ Q_D(const ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return QString();
+
+ return toString(layer, 0, d->mStringLayer[layer].size() - 1);
+}
+
+void ComposingText::insertStrSegment(TextLayer layer, const StrSegment& str)
+{
+ Q_D(ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return;
+
+ int cursor = d->mCursor[layer];
+ d->mStringLayer[layer].insert(cursor, str);
+ d->modifyUpper(layer, cursor, 1, 0);
+ setCursor(layer, cursor + 1);
+}
+
+void ComposingText::insertStrSegment(TextLayer layer1, TextLayer layer2, const StrSegment &str)
+{
+ Q_D(ComposingText);
+
+ if (layer1 < LAYER0 || layer1 >= MAX_LAYER || layer2 < LAYER0 || layer2 >= MAX_LAYER)
+ return;
+
+ d->mStringLayer[layer1].insert(d->mCursor[layer1], str);
+ d->mCursor[layer1]++;
+
+ for (int i = (int)layer1 + 1; i <= (int)layer2; i++) {
+ int pos = d->mCursor[i - 1] - 1;
+ StrSegment tmp(str.string, pos, pos);
+ QList<StrSegment> &strLayer = d->mStringLayer[i];
+ strLayer.insert(d->mCursor[i], tmp);
+ d->mCursor[i]++;
+ for (int j = d->mCursor[i]; j < strLayer.size(); j++) {
+ StrSegment &ss = strLayer[j];
+ ss.from++;
+ ss.to++;
+ }
+ }
+ int cursor = d->mCursor[layer2];
+ d->modifyUpper(layer2, cursor - 1, 1, 0);
+ setCursor(layer2, cursor);
+}
+
+void ComposingText::replaceStrSegment(TextLayer layer, const QList<StrSegment> &str, int num)
+{
+ Q_D(ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return;
+
+ int cursor = d->mCursor[layer];
+ d->replaceStrSegment0(layer, str, cursor - num, cursor - 1);
+ setCursor(layer, cursor + str.size() - num);
+}
+
+void ComposingText::deleteStrSegment(TextLayer layer, int from, int to)
+{
+ Q_D(ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return;
+
+ int fromL[3] = { -1, -1, -1 };
+ int toL[3] = { -1, -1, -1 };
+
+ QList<StrSegment> &strLayer2 = d->mStringLayer[LAYER2];
+ QList<StrSegment> &strLayer1 = d->mStringLayer[LAYER1];
+
+ if (layer == LAYER2) {
+ fromL[LAYER2] = from;
+ toL[LAYER2] = to;
+ fromL[LAYER1] = strLayer2.at(from).from;
+ toL[LAYER1] = strLayer2.at(to).to;
+ fromL[LAYER0] = strLayer1.at(fromL[LAYER1]).from;
+ toL[LAYER0] = strLayer1.at(toL[LAYER1]).to;
+ } else if (layer == LAYER1) {
+ fromL[LAYER1] = from;
+ toL[LAYER1] = to;
+ fromL[LAYER0] = strLayer1.at(from).from;
+ toL[LAYER0] = strLayer1.at(to).to;
+ } else {
+ fromL[LAYER0] = from;
+ toL[LAYER0] = to;
+ }
+
+ int diff = to - from + 1;
+ for (int lv = LAYER0; lv < MAX_LAYER; lv++) {
+ if (fromL[lv] >= 0) {
+ d->deleteStrSegment0((TextLayer)lv, fromL[lv], toL[lv], diff);
+ } else {
+ int boundary_from = -1;
+ int boundary_to = -1;
+ QList<StrSegment> &strLayer = d->mStringLayer[lv];
+ for (int i = 0; i < strLayer.size(); i++) {
+ const StrSegment &ss = strLayer.at(i);
+ if ((ss.from >= fromL[lv-1] && ss.from <= toL[lv-1]) ||
+ (ss.to >= fromL[lv-1] && ss.to <= toL[lv-1]) ) {
+ if (fromL[lv] < 0) {
+ fromL[lv] = i;
+ boundary_from = ss.from;
+ }
+ toL[lv] = i;
+ boundary_to = ss.to;
+ } else if (ss.from <= fromL[lv-1] && ss.to >= toL[lv-1]) {
+ boundary_from = ss.from;
+ boundary_to = ss.to;
+ fromL[lv] = i;
+ toL[lv] = i;
+ break;
+ } else if (ss.from > toL[lv-1]) {
+ break;
+ }
+ }
+ if (boundary_from != fromL[lv-1] || boundary_to != toL[lv-1]) {
+ d->deleteStrSegment0((TextLayer)lv, fromL[lv] + 1, toL[lv], diff);
+ boundary_to -= diff;
+ QList<StrSegment> tmp = QList<StrSegment>() <<
+ StrSegment(toString((TextLayer)(lv - 1)), boundary_from, boundary_to);
+ d->replaceStrSegment0((TextLayer)lv, tmp, fromL[lv], fromL[lv]);
+ return;
+ } else {
+ d->deleteStrSegment0((TextLayer)lv, fromL[lv], toL[lv], diff);
+ }
+ }
+ diff = toL[lv] - fromL[lv] + 1;
+ }
+}
+
+int ComposingText::deleteAt(TextLayer layer, bool rightside)
+{
+ Q_D(ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return 0;
+
+ int cursor = d->mCursor[layer];
+ QList<StrSegment> &strLayer = d->mStringLayer[layer];
+
+ if (!rightside && cursor > 0) {
+ deleteStrSegment(layer, cursor - 1, cursor - 1);
+ setCursor(layer, cursor - 1);
+ } else if (rightside && cursor < strLayer.size()) {
+ deleteStrSegment(layer, cursor, cursor);
+ setCursor(layer, cursor);
+ }
+ return strLayer.size();
+}
+
+QList<StrSegment> ComposingText::getStringLayer(TextLayer layer) const
+{
+ Q_D(const ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return QList<StrSegment>();
+
+ return d->mStringLayer[layer];
+}
+
+int ComposingText::included(TextLayer layer, int pos)
+{
+ Q_D(ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER - 1)
+ return 0;
+
+ if (pos == 0) {
+ return 0;
+ }
+ int uplayer = (TextLayer)(layer + 1);
+ int i;
+ QList<StrSegment> &strLayer = d->mStringLayer[uplayer];
+ for (i = 0; i < strLayer.size(); i++) {
+ const StrSegment &ss = strLayer.at(i);
+ if (ss.from <= pos && pos <= ss.to) {
+ break;
+ }
+ }
+ return i;
+}
+
+int ComposingText::setCursor(TextLayer layer, int pos)
+{
+ Q_D(ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return -1;
+
+ if (pos > d->mStringLayer[layer].size()) {
+ pos = d->mStringLayer[layer].size();
+ }
+ if (pos < 0) {
+ pos = 0;
+ }
+ if (layer == ComposingText::LAYER0) {
+ d->mCursor[ComposingText::LAYER0] = pos;
+ d->mCursor[ComposingText::LAYER1] = included(ComposingText::LAYER0, pos);
+ d->mCursor[ComposingText::LAYER2] = included(ComposingText::LAYER1, d->mCursor[ComposingText::LAYER1]);
+ } else if (layer == ComposingText::LAYER1) {
+ d->mCursor[ComposingText::LAYER2] = included(ComposingText::LAYER1, pos);
+ d->mCursor[ComposingText::LAYER1] = pos;
+ d->mCursor[ComposingText::LAYER0] = (pos > 0) ? d->mStringLayer[ComposingText::LAYER1].at(pos - 1).to + 1 : 0;
+ } else {
+ d->mCursor[ComposingText::LAYER2] = pos;
+ d->mCursor[ComposingText::LAYER1] = (pos > 0) ? d->mStringLayer[ComposingText::LAYER2].at(pos - 1).to + 1 : 0;
+ d->mCursor[ComposingText::LAYER0] = (d->mCursor[ComposingText::LAYER1] > 0) ? d->mStringLayer[ComposingText::LAYER1].at(d->mCursor[ComposingText::LAYER1] - 1).to + 1 : 0;
+ }
+ return pos;
+}
+
+int ComposingText::moveCursor(TextLayer layer, int diff)
+{
+ Q_D(ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return -1;
+
+ int c = d->mCursor[layer] + diff;
+
+ return setCursor(layer, c);
+}
+
+int ComposingText::getCursor(TextLayer layer) const
+{
+ Q_D(const ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return -1;
+
+ return d->mCursor[layer];
+}
+
+int ComposingText::size(TextLayer layer) const
+{
+ Q_D(const ComposingText);
+
+ if (layer < LAYER0 || layer >= MAX_LAYER)
+ return 0;
+
+ return d->mStringLayer[layer].size();
+}
+
+void ComposingText::clear()
+{
+ Q_D(ComposingText);
+ for (int i = 0; i < MAX_LAYER; i++) {
+ d->mStringLayer[i].clear();
+ d->mCursor[i] = 0;
+ }
+}