22
22
#include < filesystem>
23
23
#include < string>
24
24
#include < vector>
25
+
25
26
extern " C" {
26
27
#include < fcntl.h>
27
28
}
@@ -46,7 +47,9 @@ FcitxCskkEngine::FcitxCskkEngine(Instance *instance)
46
47
reloadConfig ();
47
48
instance_->inputContextManager ().registerProperty (" cskkcontext" , &factory_);
48
49
}
50
+
49
51
FcitxCskkEngine::~FcitxCskkEngine () = default ;
52
+
50
53
void FcitxCskkEngine::keyEvent (const InputMethodEntry &, KeyEvent &keyEvent) {
51
54
CSKK_DEBUG () << " Engine keyEvent start: " << keyEvent.rawKey ();
52
55
// delegate to context
@@ -55,6 +58,7 @@ void FcitxCskkEngine::keyEvent(const InputMethodEntry &, KeyEvent &keyEvent) {
55
58
context->keyEvent (keyEvent);
56
59
CSKK_DEBUG () << " Engine keyEvent end" ;
57
60
}
61
+
58
62
void FcitxCskkEngine::save () {
59
63
if (factory_.registered ()) {
60
64
instance_->inputContextManager ().foreach ([this ](InputContext *ic) {
@@ -63,24 +67,29 @@ void FcitxCskkEngine::save() {
63
67
});
64
68
}
65
69
}
70
+
66
71
void FcitxCskkEngine::activate (const InputMethodEntry &, InputContextEvent &) {}
72
+
67
73
void FcitxCskkEngine::deactivate (const InputMethodEntry &entry,
68
74
InputContextEvent &event) {
69
75
reset (entry, event);
70
76
}
77
+
71
78
void FcitxCskkEngine::reset (const InputMethodEntry &,
72
79
InputContextEvent &event) {
73
80
CSKK_DEBUG () << " Reset" ;
74
81
auto ic = event.inputContext ();
75
82
auto context = ic->propertyFor (&factory_);
76
83
context->reset ();
77
84
}
85
+
78
86
void FcitxCskkEngine::setConfig (const RawConfig &config) {
79
87
CSKK_DEBUG () << " Cskk setconfig" ;
80
88
config_.load (config, true );
81
89
safeSaveAsIni (config_, FcitxCskkEngine::config_file_path);
82
90
reloadConfig ();
83
91
}
92
+
84
93
void FcitxCskkEngine::reloadConfig () {
85
94
CSKK_DEBUG () << " Cskkengine reload config" ;
86
95
readAsIni (config_, FcitxCskkEngine::config_file_path);
@@ -96,6 +105,7 @@ void FcitxCskkEngine::reloadConfig() {
96
105
}
97
106
98
107
typedef enum _FcitxSkkDictType { FSDT_Invalid, FSDT_File } FcitxSkkDictType;
108
+
99
109
void FcitxCskkEngine::loadDictionary () {
100
110
freeDictionaries ();
101
111
@@ -124,6 +134,8 @@ void FcitxCskkEngine::loadDictionary() {
124
134
int mode = 0 ;
125
135
std::string path;
126
136
std::string encoding;
137
+ bool complete = false ;
138
+
127
139
for (auto &token : tokens) {
128
140
auto equal = token.find (' =' );
129
141
if (equal == std::string::npos) {
@@ -149,6 +161,10 @@ void FcitxCskkEngine::loadDictionary() {
149
161
}
150
162
} else if (key == " encoding" ) {
151
163
encoding = value;
164
+ } else if (key == " complete" ) {
165
+ if (value == " true" ) {
166
+ complete = true ;
167
+ }
152
168
}
153
169
}
154
170
@@ -165,9 +181,11 @@ void FcitxCskkEngine::loadDictionary() {
165
181
}
166
182
if (mode == 1 ) {
167
183
// readonly mode
168
- auto *dict = skk_file_dict_new (path.c_str (), encoding.c_str ());
184
+ auto *dict =
185
+ skk_file_dict_new (path.c_str (), encoding.c_str (), complete);
169
186
if (dict) {
170
- CSKK_DEBUG () << " Adding file dict: " << path;
187
+ CSKK_DEBUG () << " Adding file dict: " << path
188
+ << " complete:" << complete;
171
189
dictionaries_.emplace_back (dict);
172
190
} else {
173
191
CSKK_WARN () << " Static dictionary load error. Ignored: " << path;
@@ -182,7 +200,8 @@ void FcitxCskkEngine::loadDictionary() {
182
200
StandardPath::global ().userDirectory (StandardPath::Type::PkgData),
183
201
path.substr (var_len));
184
202
}
185
- auto *userdict = skk_user_dict_new (realpath .c_str (), encoding.c_str ());
203
+ auto *userdict =
204
+ skk_user_dict_new (realpath .c_str (), encoding.c_str (), complete);
186
205
if (userdict) {
187
206
CSKK_DEBUG () << " Adding user dict: " << realpath ;
188
207
dictionaries_.emplace_back (userdict);
@@ -201,6 +220,7 @@ void FcitxCskkEngine::freeDictionaries() {
201
220
}
202
221
dictionaries_.clear ();
203
222
}
223
+
204
224
KeyList FcitxCskkEngine::getSelectionKeys (
205
225
CandidateSelectionKeys candidateSelectionKeys) {
206
226
switch (candidateSelectionKeys) {
@@ -223,6 +243,7 @@ KeyList FcitxCskkEngine::getSelectionKeys(
223
243
Key (FcitxKey_0)};
224
244
}
225
245
}
246
+
226
247
std::string FcitxCskkEngine::subModeIconImpl (const InputMethodEntry &,
227
248
InputContext &ic) {
228
249
auto context = ic.propertyFor (&factory_);
@@ -242,6 +263,7 @@ std::string FcitxCskkEngine::subModeIconImpl(const InputMethodEntry &,
242
263
return " " ;
243
264
}
244
265
}
266
+
245
267
bool FcitxCskkEngine::isEngineReady () { return factory_.registered (); }
246
268
247
269
/* ******************************************************************************
@@ -256,7 +278,9 @@ FcitxCskkContext::FcitxCskkContext(FcitxCskkEngine *engine, InputContext *ic)
256
278
CSKK_ERROR () << " Failed to create new cskk context" ;
257
279
}
258
280
}
281
+
259
282
FcitxCskkContext::~FcitxCskkContext () { skk_free_context (context_); }
283
+
260
284
void FcitxCskkContext::keyEvent (KeyEvent &keyEvent) {
261
285
if (!context_) {
262
286
CSKK_ERROR () << " CSKK Context is not setup. Ignored key." ;
@@ -291,6 +315,7 @@ void FcitxCskkContext::keyEvent(KeyEvent &keyEvent) {
291
315
updateUI ();
292
316
}
293
317
}
318
+
294
319
bool FcitxCskkContext::handleCandidateSelection (
295
320
const std::shared_ptr<FcitxCskkCandidateList> &candidateList,
296
321
KeyEvent &keyEvent) {
@@ -331,9 +356,12 @@ bool FcitxCskkContext::handleCandidateSelection(
331
356
}
332
357
333
358
void FcitxCskkContext::reset () {
334
- skk_context_reset (context_);
359
+ if (context_) {
360
+ skk_context_reset (context_);
361
+ }
335
362
updateUI ();
336
363
}
364
+
337
365
void FcitxCskkContext::updateUI () {
338
366
if (!context_) {
339
367
CSKK_WARN () << " No context setup" ;
@@ -403,6 +431,7 @@ void FcitxCskkContext::updateUI() {
403
431
ic_->updateUserInterface (UserInterfaceComponent::StatusArea);
404
432
ic_->updateUserInterface (UserInterfaceComponent::InputPanel);
405
433
}
434
+
406
435
void FcitxCskkContext::applyConfig () {
407
436
CSKK_DEBUG () << " apply config" ;
408
437
if (!context_) {
@@ -418,6 +447,7 @@ void FcitxCskkContext::applyConfig() {
418
447
skk_context_set_period_style (context_, *config.periodStyle );
419
448
skk_context_set_comma_style (context_, *config.commaStyle );
420
449
}
450
+
421
451
void FcitxCskkContext::copyTo (InputContextProperty *) {
422
452
// auto otherContext = dynamic_cast<FcitxCskkContext *>(context);
423
453
// Ignored.
@@ -426,6 +456,7 @@ void FcitxCskkContext::copyTo(InputContextProperty *) {
426
456
// fcitx5-cskk will just hold each cskkcontext in each input context's
427
457
// property and shares nothing.
428
458
}
459
+
429
460
bool FcitxCskkContext::saveDictionary () {
430
461
if (!context_) {
431
462
CSKK_WARN () << " No cskk context setup. Ignored dictionary save." ;
@@ -435,13 +466,15 @@ bool FcitxCskkContext::saveDictionary() {
435
466
// cskk v0.8 doesn't return value on save dict, return true for now.
436
467
return true ;
437
468
}
469
+
438
470
int FcitxCskkContext::getInputMode () {
439
471
if (!context_) {
440
472
CSKK_WARN () << " No cskk context setup. No inputmode." ;
441
473
return -1 ;
442
474
}
443
475
return skk_context_get_input_mode (context_);
444
476
}
477
+
445
478
/* *
446
479
* format preedit state into Text.
447
480
* Returns tuple of <Main content Text, Supplement content Text>
@@ -453,6 +486,7 @@ FcitxCskkContext::formatPreedit(CskkStateInfoFfi *cskkStateInfoArray,
453
486
uint32_t stateLen) {
454
487
std::string precomposition_marker = " ▽" ;
455
488
std::string selection_marker = " ▼" ;
489
+ std::string completion_marker = " ■" ;
456
490
Text mainContent = Text (" " ), supplementContent = Text (" " );
457
491
mainContent.clear ();
458
492
supplementContent.clear ();
@@ -564,11 +598,25 @@ FcitxCskkContext::formatPreedit(CskkStateInfoFfi *cskkStateInfoArray,
564
598
mainCursorIdx += strlen (" 【" );
565
599
mainContent.append (" 【" , TextFormatFlag::DontCommit);
566
600
} break ;
601
+ case CompleteStateInfo: {
602
+ auto completeStateInfo = cskkStateInfo.complete_state_info ;
603
+ mainContent.append (completion_marker, TextFormatFlag::DontCommit);
604
+ if (completeStateInfo.completed ) {
605
+ mainCursorIdx += strlen (completeStateInfo.completed );
606
+ mainContent.append (completeStateInfo.completed ,
607
+ TextFormatFlag::Underline);
608
+ }
609
+ if (completeStateInfo.completed_midashi ) {
610
+ supplementContent.append (completeStateInfo.completed_midashi ,
611
+ TextFormatFlag::DontCommit);
612
+ }
613
+ } break ;
567
614
}
568
615
}
569
616
// FIXME: Silently assuming length is less than int_max here. May fail when
570
617
// length is over UINT_MAX. very unlikely, not high priority.
571
618
mainContent.setCursor ((int )mainCursorIdx);
619
+ // Starting from 1 on purpose. No paren for submodes on top of the stack.
572
620
for (uint32_t i = 1 ; i < stateLen; i++) {
573
621
mainContent.append (" 】" , TextFormatFlag::DontCommit);
574
622
}
0 commit comments