2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIDialogKeyboardGeneric.h"
11 #include "GUIDialogNumeric.h"
12 #include "GUIUserMessages.h"
13 #include "ServiceBroker.h"
14 #include "dialogs/GUIDialogKaiToast.h"
15 #include "guilib/GUIComponent.h"
16 #include "guilib/GUIEditControl.h"
17 #include "guilib/GUILabelControl.h"
18 #include "guilib/GUIWindowManager.h"
19 #include "guilib/LocalizeStrings.h"
20 #include "input/InputCodingTable.h"
21 #include "input/actions/Action.h"
22 #include "input/actions/ActionIDs.h"
23 #include "input/keyboard/KeyIDs.h"
24 #include "input/keyboard/KeyboardLayoutManager.h"
25 #include "input/keyboard/XBMC_vkeys.h"
26 #include "interfaces/AnnouncementManager.h"
27 #include "messaging/ApplicationMessenger.h"
28 #include "settings/Settings.h"
29 #include "settings/SettingsComponent.h"
30 #include "speech/ISpeechRecognition.h"
31 #include "speech/ISpeechRecognitionListener.h"
32 #include "speech/SpeechRecognitionErrors.h"
33 #include "utils/CharsetConverter.h"
34 #include "utils/RegExp.h"
35 #include "utils/StringUtils.h"
36 #include "utils/Variant.h"
37 #include "utils/log.h"
38 #include "windowing/WinSystem.h"
43 using namespace MESSAGING
;
45 #define BUTTON_ID_OFFSET 100
46 #define BUTTONS_PER_ROW 20
47 #define BUTTONS_MAX_ROWS 4
49 #define CTL_BUTTON_DONE 300
50 #define CTL_BUTTON_CANCEL 301
51 #define CTL_BUTTON_SHIFT 302
52 #define CTL_BUTTON_CAPS 303
53 #define CTL_BUTTON_SYMBOLS 304
54 #define CTL_BUTTON_LEFT 305
55 #define CTL_BUTTON_RIGHT 306
56 #define CTL_BUTTON_IP_ADDRESS 307
57 #define CTL_BUTTON_CLEAR 308
58 #define CTL_BUTTON_LAYOUT 309
59 #define CTL_BUTTON_REVEAL 310
60 #define CTL_LABEL_HEADING 311
62 #define CTL_LABEL_HZCODE 313
63 #define CTL_LABEL_HZLIST 314
65 #define CTL_BUTTON_BACKSPACE 8
66 #define CTL_BUTTON_SPACE 32
68 #define SEARCH_DELAY 1000
70 class CSpeechRecognitionListener
: public speech::ISpeechRecognitionListener
73 CSpeechRecognitionListener(int dialogId
) : m_dialogId(dialogId
) {}
75 void OnReadyForSpeech() override
77 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info
,
78 g_localizeStrings
.Get(39177), // Speech to text
79 g_localizeStrings
.Get(39179)); // Listening...
82 void OnError(int recognitionError
) override
85 switch (recognitionError
)
87 case speech::RecognitionError::SERVICE_NOT_AVAILABLE
:
88 msgId
= 39178; // Speech recognition service not available
90 case speech::RecognitionError::NO_MATCH
:
91 msgId
= 39180; // No recognition result matched
93 case speech::RecognitionError::INSUFFICIENT_PERMISSIONS
:
94 msgId
= 39185; // Insufficient permissions for speech recognition
97 msgId
= 39181; // Speech recognition error
101 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error
,
102 g_localizeStrings
.Get(39177), // Speech to text
103 g_localizeStrings
.Get(msgId
));
106 void OnResults(const std::vector
<std::string
>& results
) override
108 if (!results
.empty())
110 CGUIMessage
msg(GUI_MSG_SET_TEXT
, m_dialogId
, CTL_EDIT
);
111 msg
.SetLabel(results
.front());
113 // dispatch to GUI thread
114 CServiceBroker::GetAppMessenger()->SendGUIMessage(msg
, m_dialogId
);
119 const int m_dialogId
{0};
122 CGUIDialogKeyboardGeneric::CGUIDialogKeyboardGeneric()
123 : CGUIDialog(WINDOW_DIALOG_KEYBOARD
, "DialogKeyboard.xml")
125 , m_pCharCallback(NULL
)
127 m_bIsConfirmed
= false;
129 m_hiddenInput
= false;
130 m_keyType
= KEY_TYPE::LOWER
;
132 m_loadType
= KEEP_IN_MEMORY
;
133 m_isKeyboardNavigationMode
= false;
134 m_previouslyFocusedButton
= 0;
139 void CGUIDialogKeyboardGeneric::OnWindowLoaded()
141 CGUIEditControl
*edit
= static_cast<CGUIEditControl
*>(GetControl(CTL_EDIT
));
144 // add control CTL_LABEL_HZCODE and CTL_LABEL_HZLIST if not exist
145 CGUIControlGroup
*ParentControl
= static_cast<CGUIControlGroup
*>(edit
->GetParentControl());
146 CLabelInfo labelInfo
= edit
->GetLabelInfo();
147 float px
= edit
->GetXPosition();
148 float py
= edit
->GetYPosition();
149 float pw
= edit
->GetWidth();
150 float ph
= edit
->GetHeight();
152 CGUILabelControl
* control
= static_cast<CGUILabelControl
*>(GetControl(CTL_LABEL_HZCODE
));
155 control
= new CGUILabelControl(GetID(), CTL_LABEL_HZCODE
, px
, py
+ ph
, 90, 30, labelInfo
, false, false);
156 ParentControl
->AddControl(control
);
159 control
= static_cast<CGUILabelControl
*>(GetControl(CTL_LABEL_HZLIST
));
162 labelInfo
.align
= XBFONT_CENTER_Y
;
163 control
= new CGUILabelControl(GetID(), CTL_LABEL_HZLIST
, px
+ 95, py
+ ph
, pw
- 95, 30, labelInfo
, false, false);
164 ParentControl
->AddControl(control
);
168 CGUIDialog::OnWindowLoaded();
171 void CGUIDialogKeyboardGeneric::OnInitWindow()
173 CGUIDialog::OnInitWindow();
175 m_bIsConfirmed
= false;
176 m_isKeyboardNavigationMode
= false;
178 // fill in the keyboard layouts
181 const KEYBOARD::KeyboardLayouts
& keyboardLayouts
=
182 CServiceBroker::GetKeyboardLayoutManager()->GetLayouts();
183 const std::shared_ptr
<CSettings
> settings
= CServiceBroker::GetSettingsComponent()->GetSettings();
184 std::vector
<CVariant
> layoutNames
= settings
->GetList(CSettings::SETTING_LOCALE_KEYBOARDLAYOUTS
);
185 std::string activeLayout
= settings
->GetString(CSettings::SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT
);
187 for (const auto& layoutName
: layoutNames
)
189 const auto keyboardLayout
= keyboardLayouts
.find(layoutName
.asString());
190 if (keyboardLayout
!= keyboardLayouts
.end())
192 m_layouts
.emplace_back(keyboardLayout
->second
);
193 if (layoutName
.asString() == activeLayout
)
194 m_currentLayout
= m_layouts
.size() - 1;
198 // set alphabetic (capitals)
202 if (!m_strHeading
.empty())
204 SET_CONTROL_LABEL(CTL_LABEL_HEADING
, m_strHeading
);
205 SET_CONTROL_VISIBLE(CTL_LABEL_HEADING
);
209 SET_CONTROL_HIDDEN(CTL_LABEL_HEADING
);
213 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CTL_EDIT
, m_hiddenInput
? CGUIEditControl::INPUT_TYPE_PASSWORD
: CGUIEditControl::INPUT_TYPE_TEXT
);
218 SET_CONTROL_VISIBLE(CTL_BUTTON_REVEAL
);
219 SET_CONTROL_LABEL(CTL_BUTTON_REVEAL
, g_localizeStrings
.Get(12308));
222 SET_CONTROL_HIDDEN(CTL_BUTTON_REVEAL
);
226 // get HZLIST label options
227 CGUILabelControl
* pEdit
= static_cast<CGUILabelControl
*>(GetControl(CTL_LABEL_HZLIST
));
228 CLabelInfo labelInfo
= pEdit
->GetLabelInfo();
229 m_listfont
= labelInfo
.font
;
230 m_listwidth
= pEdit
->GetWidth();
233 SET_CONTROL_LABEL(CTL_LABEL_HZCODE
, "");
234 SET_CONTROL_LABEL(CTL_LABEL_HZLIST
, "");
237 data
["title"] = m_strHeading
;
238 data
["type"] = !m_hiddenInput
? "keyboard" : "password";
239 data
["value"] = GetText();
240 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input
, "OnInputRequested", data
);
243 bool CGUIDialogKeyboardGeneric::OnAction(const CAction
&action
)
245 int actionId
= action
.GetID();
247 if (actionId
== (KEY_VKEY
| XBMCVK_BACK
))
249 else if (actionId
== ACTION_ENTER
||
250 (actionId
== ACTION_SELECT_ITEM
&& (m_isKeyboardNavigationMode
|| GetFocusedControlID() == CTL_EDIT
)))
252 else if (actionId
== ACTION_SHIFT
)
254 else if (actionId
== ACTION_SYMBOLS
)
256 // don't handle move left/right and select in the edit control
257 else if (!m_isKeyboardNavigationMode
&&
258 (actionId
== ACTION_MOVE_LEFT
||
259 actionId
== ACTION_MOVE_RIGHT
||
260 actionId
== ACTION_SELECT_ITEM
))
262 else if (actionId
== ACTION_VOICE_RECOGNIZE
)
263 OnVoiceRecognition();
266 std::wstring wch
= L
"";
267 wch
.insert(wch
.begin(), action
.GetUnicode());
269 g_charsetConverter
.wToUTF8(wch
, ch
);
270 handled
= CodingCharacter(ch
);
273 // send action to edit control
274 CGUIControl
*edit
= GetControl(CTL_EDIT
);
276 handled
= edit
->OnAction(action
);
277 if (!handled
&& actionId
>= KEY_VKEY
&& actionId
< KEY_UNICODE
)
279 unsigned char b
= actionId
& 0xFF;
282 // Toggle left/right key mode
283 m_isKeyboardNavigationMode
= !m_isKeyboardNavigationMode
;
284 if (m_isKeyboardNavigationMode
)
286 m_previouslyFocusedButton
= GetFocusedControlID();
287 SET_CONTROL_FOCUS(edit
->GetID(), 0);
290 SET_CONTROL_FOCUS(m_previouslyFocusedButton
, 0);
297 if (!handled
) // unhandled by us - let's see if the baseclass wants it
298 handled
= CGUIDialog::OnAction(action
);
303 bool CGUIDialogKeyboardGeneric::OnMessage(CGUIMessage
& message
)
305 switch ( message
.GetMessage() )
307 case GUI_MSG_CLICKED
:
309 int iControl
= message
.GetSenderId();
313 case CTL_BUTTON_DONE
:
316 case CTL_BUTTON_CANCEL
:
319 case CTL_BUTTON_SHIFT
:
322 case CTL_BUTTON_CAPS
:
323 if (m_keyType
== KEY_TYPE::LOWER
)
324 m_keyType
= KEY_TYPE::CAPS
;
325 else if (m_keyType
== KEY_TYPE::CAPS
)
326 m_keyType
= KEY_TYPE::LOWER
;
329 case CTL_BUTTON_LAYOUT
:
332 case CTL_BUTTON_REVEAL
:
335 case CTL_BUTTON_SYMBOLS
:
338 case CTL_BUTTON_LEFT
:
341 case CTL_BUTTON_RIGHT
:
344 case CTL_BUTTON_IP_ADDRESS
:
347 case CTL_BUTTON_CLEAR
:
352 CGUIMessage
msg(GUI_MSG_ITEM_SELECTED
, GetID(), CTL_EDIT
);
354 // update callback I guess?
356 { // we did _something_, so make sure our search message filter is reset
357 m_pCharCallback(this, msg
.GetLabel());
359 m_text
= msg
.GetLabel();
363 OnClickButton(iControl
);
369 case GUI_MSG_SET_TEXT
:
371 // the edit control only handles these messages if it is either focused
372 // or its specific control ID is set in the message. As neither is the
373 // case here (focus is on one of the keyboard buttons) we have to force
374 // the control ID of the message to the control ID of the edit control
375 // (unfortunately we have to create a whole copy of the message object for that)
376 CGUIMessage
messageCopy(message
.GetMessage(), message
.GetSenderId(), CTL_EDIT
, message
.GetParam1(), message
.GetParam2(), message
.GetItem());
377 messageCopy
.SetLabel(message
.GetLabel());
379 // ensure this goes to the edit control
380 CGUIControl
*edit
= GetControl(CTL_EDIT
);
382 edit
->OnMessage(messageCopy
);
384 // close the dialog if requested
385 if (message
.GetMessage() == GUI_MSG_SET_TEXT
&& message
.GetParam1() > 0)
389 case GUI_MSG_CODINGTABLE_LOOKUP_COMPLETED
:
391 const std::string
& code
= message
.GetStringParam();
392 if (code
== m_hzcode
)
394 int response
= message
.GetParam1();
395 auto words
= m_codingtable
->GetResponse(response
);
396 m_words
.insert(m_words
.end(), words
.begin(), words
.end());
402 return CGUIDialog::OnMessage(message
);
405 void CGUIDialogKeyboardGeneric::SetEditText(const std::string
&text
)
407 CGUIMessage
msg(GUI_MSG_SET_TEXT
, GetID(), CTL_EDIT
);
412 void CGUIDialogKeyboardGeneric::SetText(const std::string
& text
)
417 const std::string
&CGUIDialogKeyboardGeneric::GetText() const
422 void CGUIDialogKeyboardGeneric::Character(const std::string
&ch
)
424 if (ch
.empty()) return;
425 if (!CodingCharacter(ch
))
429 void CGUIDialogKeyboardGeneric::NormalCharacter(const std::string
&ch
)
431 // send text to edit control
432 CGUIControl
*edit
= GetControl(CTL_EDIT
);
435 CAction
action(ACTION_INPUT_TEXT
);
437 edit
->OnAction(action
);
441 void CGUIDialogKeyboardGeneric::Backspace()
443 if (m_codingtable
&& m_hzcode
.length() > 0)
446 g_charsetConverter
.utf8ToW(m_hzcode
, tmp
);
447 tmp
.erase(tmp
.length() - 1, 1);
448 g_charsetConverter
.wToUTF8(tmp
, m_hzcode
);
450 switch (m_codingtable
->GetType())
452 case IInputCodingTable::TYPE_WORD_LIST
:
453 SetControlLabel(CTL_LABEL_HZCODE
, m_hzcode
);
457 case IInputCodingTable::TYPE_CONVERT_STRING
:
458 SetEditText(m_codingtable
->ConvertString(m_hzcode
));
464 // send action to edit control
465 CGUIControl
*edit
= GetControl(CTL_EDIT
);
467 edit
->OnAction(CAction(ACTION_BACKSPACE
));
469 if (m_codingtable
&& m_codingtable
->GetType() == IInputCodingTable::TYPE_CONVERT_STRING
)
470 m_codingtable
->SetTextPrev(GetText());
474 void CGUIDialogKeyboardGeneric::OnClickButton(int iButtonControl
)
476 if (iButtonControl
== CTL_BUTTON_BACKSPACE
)
480 else if (iButtonControl
== CTL_BUTTON_SPACE
)
486 const CGUIControl
* pButton
= GetControl(iButtonControl
);
487 // Do not register input for buttons with id >= 500
488 if (pButton
&& iButtonControl
< 500)
490 Character(pButton
->GetDescription());
491 // reset the shift keys
492 if (m_bShift
) OnShift();
497 void CGUIDialogKeyboardGeneric::UpdateButtons()
499 SET_CONTROL_SELECTED(GetID(), CTL_BUTTON_SHIFT
, m_bShift
);
500 SET_CONTROL_SELECTED(GetID(), CTL_BUTTON_CAPS
, m_keyType
== KEY_TYPE::CAPS
);
501 SET_CONTROL_SELECTED(GetID(), CTL_BUTTON_SYMBOLS
, m_keyType
== KEY_TYPE::SYMBOLS
);
503 if (m_currentLayout
>= m_layouts
.size())
505 KEYBOARD::CKeyboardLayout layout
=
506 m_layouts
.empty() ? KEYBOARD::CKeyboardLayout() : m_layouts
[m_currentLayout
];
507 m_codingtable
= layout
.GetCodingTable();
508 if (m_codingtable
&& !m_codingtable
->IsInitialized())
509 m_codingtable
->Initialize();
511 bool bShowWordList
= false;
514 switch (m_codingtable
->GetType())
516 case IInputCodingTable::TYPE_WORD_LIST
:
517 bShowWordList
= true;
520 case IInputCodingTable::TYPE_CONVERT_STRING
:
521 m_codingtable
->SetTextPrev(GetText());
529 SET_CONTROL_VISIBLE(CTL_LABEL_HZCODE
);
530 SET_CONTROL_VISIBLE(CTL_LABEL_HZLIST
);
534 SET_CONTROL_HIDDEN(CTL_LABEL_HZCODE
);
535 SET_CONTROL_HIDDEN(CTL_LABEL_HZLIST
);
537 SET_CONTROL_LABEL(CTL_BUTTON_LAYOUT
, layout
.GetName());
539 unsigned int modifiers
= KEYBOARD::CKeyboardLayout::ModifierKeyNone
;
540 if ((m_keyType
== KEY_TYPE::CAPS
&& !m_bShift
) || (m_keyType
== KEY_TYPE::LOWER
&& m_bShift
))
541 modifiers
|= KEYBOARD::CKeyboardLayout::ModifierKeyShift
;
542 if (m_keyType
== KEY_TYPE::SYMBOLS
)
544 modifiers
|= KEYBOARD::CKeyboardLayout::ModifierKeySymbol
;
546 modifiers
|= KEYBOARD::CKeyboardLayout::ModifierKeyShift
;
549 for (unsigned int row
= 0; row
< BUTTONS_MAX_ROWS
; row
++)
551 for (unsigned int column
= 0; column
< BUTTONS_PER_ROW
; column
++)
553 int buttonID
= (row
* BUTTONS_PER_ROW
) + column
+ BUTTON_ID_OFFSET
;
554 std::string label
= layout
.GetCharAt(row
, column
, modifiers
);
555 SetControlLabel(buttonID
, label
);
557 SET_CONTROL_VISIBLE(buttonID
);
559 SET_CONTROL_HIDDEN(buttonID
);
564 void CGUIDialogKeyboardGeneric::OnDeinitWindow(int nextWindowID
)
566 for (auto& layout
: m_layouts
)
568 auto codingTable
= layout
.GetCodingTable();
569 if (codingTable
&& codingTable
->IsInitialized())
570 codingTable
->Deinitialize();
573 CGUIDialog::OnDeinitWindow(nextWindowID
);
574 // reset the heading (we don't always have this)
577 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input
, "OnInputFinished");
580 void CGUIDialogKeyboardGeneric::MoveCursor(int iAmount
)
582 if (m_codingtable
&& m_words
.size())
583 ChangeWordList(iAmount
);
586 CGUIControl
*edit
= GetControl(CTL_EDIT
);
588 edit
->OnAction(CAction(iAmount
< 0 ? ACTION_CURSOR_LEFT
: ACTION_CURSOR_RIGHT
));
592 void CGUIDialogKeyboardGeneric::OnLayout()
595 if (m_currentLayout
>= m_layouts
.size())
597 KEYBOARD::CKeyboardLayout layout
=
598 m_layouts
.empty() ? KEYBOARD::CKeyboardLayout() : m_layouts
[m_currentLayout
];
599 CServiceBroker::GetSettingsComponent()->GetSettings()->SetString(CSettings::SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT
, layout
.GetName());
603 void CGUIDialogKeyboardGeneric::OnSymbols()
605 if (m_keyType
== KEY_TYPE::SYMBOLS
)
606 m_keyType
= KEY_TYPE::LOWER
;
608 m_keyType
= KEY_TYPE::SYMBOLS
;
612 void CGUIDialogKeyboardGeneric::OnReveal()
614 m_hiddenInput
= !m_hiddenInput
;
615 SET_CONTROL_LABEL(CTL_BUTTON_REVEAL
, g_localizeStrings
.Get(m_hiddenInput
? 12308 : 12309));
616 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CTL_EDIT
,
617 m_hiddenInput
? CGUIEditControl::INPUT_TYPE_PASSWORD
618 : CGUIEditControl::INPUT_TYPE_TEXT
);
622 void CGUIDialogKeyboardGeneric::OnShift()
624 m_bShift
= !m_bShift
;
628 void CGUIDialogKeyboardGeneric::OnIPAddress()
630 // find any IP address in the current string if there is any
631 // We match to #.#.#.#
632 std::string text
= GetText();
635 reg
.RegComp("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+");
636 int start
= reg
.RegFind(text
.c_str());
640 length
= reg
.GetSubLength(0);
641 ip
= text
.substr(start
, length
);
645 if (CGUIDialogNumeric::ShowAndGetIPAddress(ip
, g_localizeStrings
.Get(14068)))
646 SetEditText(text
.substr(0, start
) + ip
+ text
.substr(start
+ length
));
649 void CGUIDialogKeyboardGeneric::OnVoiceRecognition()
651 const auto speechRecognition
= CServiceBroker::GetSpeechRecognition();
652 if (speechRecognition
)
654 if (!m_speechRecognitionListener
)
655 m_speechRecognitionListener
= std::make_shared
<CSpeechRecognitionListener
>(GetID());
657 speechRecognition
->StartSpeechRecognition(m_speechRecognitionListener
);
661 CLog::LogF(LOGWARNING
, "No voice recognition implementation available.");
665 void CGUIDialogKeyboardGeneric::SetControlLabel(int id
, const std::string
&label
)
666 { // find all controls with this id, and set all their labels
667 CGUIMessage
message(GUI_MSG_LABEL_SET
, GetID(), id
);
668 message
.SetLabel(label
);
669 for (unsigned int i
= 0; i
< m_children
.size(); i
++)
671 if (m_children
[i
]->GetID() == id
|| m_children
[i
]->IsGroup())
672 m_children
[i
]->OnMessage(message
);
676 void CGUIDialogKeyboardGeneric::OnOK()
678 m_bIsConfirmed
= true;
682 void CGUIDialogKeyboardGeneric::SetHeading(const std::string
&heading
)
684 m_strHeading
= heading
;
687 int CGUIDialogKeyboardGeneric::GetWindowId() const
692 void CGUIDialogKeyboardGeneric::Cancel()
694 m_bIsConfirmed
= false;
698 bool CGUIDialogKeyboardGeneric::ShowAndGetInput(char_callback_t pCallback
, const std::string
&initialString
, std::string
&typedString
, const std::string
&heading
, bool bHiddenInput
)
700 CGUIDialogKeyboardGeneric
*pKeyboard
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogKeyboardGeneric
>(WINDOW_DIALOG_KEYBOARD
);
705 m_pCharCallback
= pCallback
;
707 pKeyboard
->Initialize();
708 pKeyboard
->SetHeading(heading
);
709 pKeyboard
->SetHiddenInput(bHiddenInput
);
710 pKeyboard
->SetText(initialString
);
714 // If have text - update this.
715 if (pKeyboard
->IsConfirmed())
717 typedString
= pKeyboard
->GetText();
723 float CGUIDialogKeyboardGeneric::GetStringWidth(const std::wstring
& utf16
)
727 utf32
.resize(utf16
.size());
728 for (unsigned int i
= 0; i
< utf16
.size(); i
++)
731 return m_listfont
->GetTextWidth(utf32
);
734 void CGUIDialogKeyboardGeneric::ChangeWordList(int direct
)
740 m_codingtable
->GetWordListPage(m_hzcode
, true);
744 ShowWordList(direct
);
745 if (direct
> 0 && m_pos
+ m_num
== static_cast<int>(m_words
.size()))
746 m_codingtable
->GetWordListPage(m_hzcode
, false);
750 void CGUIDialogKeyboardGeneric::ShowWordList(int direct
)
752 std::unique_lock
<CCriticalSection
> lock(m_CS
);
753 std::wstring hzlist
= L
"";
754 CServiceBroker::GetWinSystem()->GetGfxContext().SetScalingResolution(m_coordsRes
, true);
755 float width
= m_listfont
->GetCharWidth(L
'<') + m_listfont
->GetCharWidth(L
'>');
756 float spacewidth
= m_listfont
->GetCharWidth(L
' ');
757 float numwidth
= m_listfont
->GetCharWidth(L
'1') + m_listfont
->GetCharWidth(L
'.');
764 if (m_pos
> static_cast<int>(m_words
.size()) - 1)
766 for (i
= 0; m_pos
+ i
< static_cast<int>(m_words
.size()); i
++)
768 if ((i
> 0 && width
+ GetStringWidth(m_words
[m_pos
+ i
]) + numwidth
> m_listwidth
) || i
> 9)
770 hzlist
.insert(hzlist
.length(), 1, (wchar_t)(i
+ 48));
771 hzlist
.insert(hzlist
.length(), 1, L
'.');
772 hzlist
.append(m_words
[m_pos
+ i
]);
773 hzlist
.insert(hzlist
.length(), 1, L
' ');
774 width
+= GetStringWidth(m_words
[m_pos
+ i
]) + numwidth
+ spacewidth
;
782 for (i
= 1; i
<= 10; i
++)
784 if (m_pos
- i
< 0 || (i
> 1 && width
+ GetStringWidth(m_words
[m_pos
- i
]) + numwidth
> m_listwidth
))
786 width
+= GetStringWidth(m_words
[m_pos
- i
]) + numwidth
+ spacewidth
;
790 for (i
= 0; i
< m_num
; i
++)
792 hzlist
.insert(hzlist
.length(), 1, (wchar_t)(i
+ 48));
793 hzlist
.insert(hzlist
.length(), 1, L
'.');
794 hzlist
.append(m_words
[m_pos
+ i
]);
795 hzlist
.insert(hzlist
.length(), 1, L
' ');
798 hzlist
.erase(hzlist
.find_last_not_of(L
' ') + 1);
800 hzlist
.insert(0, 1, L
'<');
801 if (m_pos
+ m_num
< static_cast<int>(m_words
.size()))
802 hzlist
.insert(hzlist
.length(), 1, L
'>');
803 std::string utf8String
;
804 g_charsetConverter
.wToUTF8(hzlist
, utf8String
);
805 SET_CONTROL_LABEL(CTL_LABEL_HZLIST
, utf8String
);
808 bool CGUIDialogKeyboardGeneric::CodingCharacter(const std::string
&ch
)
813 switch (m_codingtable
->GetType())
815 case IInputCodingTable::TYPE_CONVERT_STRING
:
816 if (!ch
.empty() && ch
[0] != 0)
819 SetEditText(m_codingtable
->ConvertString(m_hzcode
));
824 case IInputCodingTable::TYPE_WORD_LIST
:
825 if (m_codingtable
->GetCodeChars().find(ch
) != std::string::npos
)
828 SetControlLabel(CTL_LABEL_HZCODE
, m_hzcode
);
832 if (ch
[0] >= '0' && ch
[0] <= '9')
834 int i
= m_pos
+ (int)ch
[0] - 48;
835 if (i
< (m_pos
+ m_num
))
838 SetControlLabel(CTL_LABEL_HZCODE
, m_hzcode
);
839 std::string utf8String
;
840 g_charsetConverter
.wToUTF8(m_words
[i
], utf8String
);
841 NormalCharacter(utf8String
);