diff --git a/openless-all/app/windows-ime/OpenLessIme.vcxproj b/openless-all/app/windows-ime/OpenLessIme.vcxproj
index ec863ef7..d27520d7 100644
--- a/openless-all/app/windows-ime/OpenLessIme.vcxproj
+++ b/openless-all/app/windows-ime/OpenLessIme.vcxproj
@@ -76,11 +76,13 @@
+
+
diff --git a/openless-all/app/windows-ime/src/edit_session.cpp b/openless-all/app/windows-ime/src/edit_session.cpp
new file mode 100644
index 00000000..1e4210b1
--- /dev/null
+++ b/openless-all/app/windows-ime/src/edit_session.cpp
@@ -0,0 +1,81 @@
+#include "edit_session.h"
+
+#include
+
+OpenLessEditSession::OpenLessEditSession(ITfContext* context,
+ std::wstring text)
+ : context_(context), text_(std::move(text)) {
+ if (context_ != nullptr) {
+ context_->AddRef();
+ }
+}
+
+OpenLessEditSession::~OpenLessEditSession() {
+ if (context_ != nullptr) {
+ context_->Release();
+ context_ = nullptr;
+ }
+}
+
+STDMETHODIMP OpenLessEditSession::QueryInterface(REFIID iid, void** object) {
+ if (object == nullptr) {
+ return E_POINTER;
+ }
+ *object = nullptr;
+
+ if (iid == IID_IUnknown || iid == IID_ITfEditSession) {
+ *object = static_cast(this);
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) OpenLessEditSession::AddRef() {
+ return static_cast(InterlockedIncrement(&ref_count_));
+}
+
+STDMETHODIMP_(ULONG) OpenLessEditSession::Release() {
+ const ULONG count = static_cast(InterlockedDecrement(&ref_count_));
+ if (count == 0) {
+ delete this;
+ }
+ return count;
+}
+
+STDMETHODIMP OpenLessEditSession::DoEditSession(TfEditCookie edit_cookie) {
+ if (context_ == nullptr) {
+ return E_UNEXPECTED;
+ }
+
+ ITfInsertAtSelection* insert_at_selection = nullptr;
+ HRESULT hr = context_->QueryInterface(IID_ITfInsertAtSelection,
+ reinterpret_cast(
+ &insert_at_selection));
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ ITfRange* query_range = nullptr;
+ hr = insert_at_selection->InsertTextAtSelection(
+ edit_cookie, TF_IAS_QUERYONLY, text_.c_str(),
+ static_cast(text_.size()), &query_range);
+ if (query_range != nullptr) {
+ query_range->Release();
+ query_range = nullptr;
+ }
+
+ if (SUCCEEDED(hr)) {
+ ITfRange* committed_range = nullptr;
+ hr = insert_at_selection->InsertTextAtSelection(
+ edit_cookie, 0, text_.c_str(), static_cast(text_.size()),
+ &committed_range);
+ if (committed_range != nullptr) {
+ committed_range->Release();
+ }
+ }
+
+ insert_at_selection->Release();
+ return hr;
+}
diff --git a/openless-all/app/windows-ime/src/edit_session.h b/openless-all/app/windows-ime/src/edit_session.h
new file mode 100644
index 00000000..5ab96bbd
--- /dev/null
+++ b/openless-all/app/windows-ime/src/edit_session.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include
+#include
+#include
+
+class OpenLessEditSession final : public ITfEditSession {
+ public:
+ OpenLessEditSession(ITfContext* context, std::wstring text);
+ OpenLessEditSession(const OpenLessEditSession&) = delete;
+ OpenLessEditSession& operator=(const OpenLessEditSession&) = delete;
+ ~OpenLessEditSession() override;
+
+ STDMETHODIMP QueryInterface(REFIID iid, void** object) override;
+ STDMETHODIMP_(ULONG) AddRef() override;
+ STDMETHODIMP_(ULONG) Release() override;
+ STDMETHODIMP DoEditSession(TfEditCookie edit_cookie) override;
+
+ private:
+ LONG ref_count_ = 1;
+ ITfContext* context_ = nullptr;
+ std::wstring text_;
+};
diff --git a/openless-all/app/windows-ime/src/text_service.cpp b/openless-all/app/windows-ime/src/text_service.cpp
index 7a0caa79..ed911832 100644
--- a/openless-all/app/windows-ime/src/text_service.cpp
+++ b/openless-all/app/windows-ime/src/text_service.cpp
@@ -1,5 +1,9 @@
#include "text_service.h"
+#include
+
+#include "edit_session.h"
+
extern LONG g_object_count;
OpenLessTextService::OpenLessTextService() {
@@ -84,8 +88,47 @@ HRESULT OpenLessTextService::SubmitTextFromPipe(
const std::wstring& session_id,
const std::wstring& text) {
UNREFERENCED_PARAMETER(session_id);
- UNREFERENCED_PARAMETER(text);
- return E_NOTIMPL;
+
+ if (thread_mgr_ == nullptr || client_id_ == TF_CLIENTID_NULL) {
+ return E_UNEXPECTED;
+ }
+
+ ITfDocumentMgr* document_mgr = nullptr;
+ HRESULT hr = thread_mgr_->GetFocus(&document_mgr);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ if (document_mgr == nullptr) {
+ return E_FAIL;
+ }
+
+ ITfContext* context = nullptr;
+ hr = document_mgr->GetTop(&context);
+ document_mgr->Release();
+ document_mgr = nullptr;
+ if (FAILED(hr)) {
+ return hr;
+ }
+ if (context == nullptr) {
+ return E_FAIL;
+ }
+
+ auto* session = new (std::nothrow) OpenLessEditSession(context, text);
+ if (session == nullptr) {
+ context->Release();
+ return E_OUTOFMEMORY;
+ }
+
+ HRESULT edit_result = S_OK;
+ hr = context->RequestEditSession(client_id_, session,
+ TF_ES_SYNC | TF_ES_READWRITE, &edit_result);
+ session->Release();
+ context->Release();
+
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return edit_result;
}
HRESULT OpenLessTextService::StartIpcServer() {