feat: commit dictated text through TSF edit sessions
This commit is contained in:
1 parent
1ab6f7b7ab
commit
0f28bb1a3e
4 files changed
+151
-2
No files matched your search
@@ -76,11 +76,13 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\class_factory.cpp" />
|
||||
<ClCompile Include="src\dllmain.cpp" />
|
||||
<ClCompile Include="src\edit_session.cpp" />
|
||||
<ClCompile Include="src\registry.cpp" />
|
||||
<ClCompile Include="src\text_service.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\class_factory.h" />
|
||||
<ClInclude Include="src\edit_session.h" />
|
||||
<ClInclude Include="src\guids.h" />
|
||||
<ClInclude Include="src\registry.h" />
|
||||
<ClInclude Include="src\text_service.h" />
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "edit_session.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
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<ITfEditSession*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) OpenLessEditSession::AddRef() {
|
||||
return static_cast<ULONG>(InterlockedIncrement(&ref_count_));
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) OpenLessEditSession::Release() {
|
||||
const ULONG count = static_cast<ULONG>(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<void**>(
|
||||
&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<LONG>(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<LONG>(text_.size()),
|
||||
&committed_range);
|
||||
if (committed_range != nullptr) {
|
||||
committed_range->Release();
|
||||
}
|
||||
}
|
||||
|
||||
insert_at_selection->Release();
|
||||
return hr;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <msctf.h>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
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_;
|
||||
};
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "text_service.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#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() {
|
||||
|
||||
Reference in new issue
Block a user