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/Key.h"
22 #include "input/KeyboardLayoutManager.h"
23 #include "input/XBMC_vkeys.h"
24 #include "interfaces/AnnouncementManager.h"
25 #include "messaging/ApplicationMessenger.h"
26 #include "settings/Settings.h"
27 #include "settings/SettingsComponent.h"
28 #include "speech/ISpeechRecognition.h"
29 #include "speech/ISpeechRecognitionListener.h"
30 #include "speech/SpeechRecognitionErrors.h"
31 #include "utils/CharsetConverter.h"
32 #include "utils/RegExp.h"
33 #include "utils/StringUtils.h"
34 #include "utils/Variant.h"
35 #include "utils/log.h"
36 #include "windowing/WinSystem.h"
40 using namespace KODI::MESSAGING
;
42 #define BUTTON_ID_OFFSET 100
43 #define BUTTONS_PER_ROW 20
44 #define BUTTONS_MAX_ROWS 4
46 #define CTL_BUTTON_DONE 300
47 #define CTL_BUTTON_CANCEL 301
48 #define CTL_BUTTON_SHIFT 302
49 #define CTL_BUTTON_CAPS 303
50 #define CTL_BUTTON_SYMBOLS 304
51 #define CTL_BUTTON_LEFT 305
52 #define CTL_BUTTON_RIGHT 306
53 #define CTL_BUTTON_IP_ADDRESS 307
54 #define CTL_BUTTON_CLEAR 308
55 #define CTL_BUTTON_LAYOUT 309
56 #define CTL_BUTTON_REVEAL 310
57 #define CTL_LABEL_HEADING 311
59 #define CTL_LABEL_HZCODE 313
60 #define CTL_LABEL_HZLIST 314
62 #define CTL_BUTTON_BACKSPACE 8
63 #define CTL_BUTTON_SPACE 32
65 #define SEARCH_DELAY 1000
67 class CSpeechRecognitionListener
: public speech::ISpeechRecognitionListener
70 CSpeechRecognitionListener(int dialogId
) : m_dialogId(dialogId
) {}
72 void OnReadyForSpeech() override
74 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info
,
75 g_localizeStrings
.Get(39177), // Speech to text
76 g_localizeStrings
.Get(39179)); // Listening...
79 void OnError(int recognitionError
) override
82 switch (recognitionError
)
84 case speech::RecognitionError::SERVICE_NOT_AVAILABLE
:
85 msgId
= 39178; // Speech recognition service not available
87 case speech::RecognitionError::NO_MATCH
:
88 msgId
= 39180; // No recognition result matched
90 case speech::RecognitionError::INSUFFICIENT_PERMISSIONS
:
91 msgId
= 39185; // Insufficient permissions for speech recognition
94 msgId
= 39181; // Speech recognition error
98 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error
,
99 g_localizeStrings
.Get(39177), // Speech to text
100 g_localizeStrings
.Get(msgId
));
103 void OnResults(const std::vector
<std::string
>& results
) override
105 if (!results
.empty())
107 CGUIMessage
msg(GUI_MSG_SET_TEXT
, m_dialogId
, CTL_EDIT
);
108 msg
.SetLabel(results
.front());
110 // dispatch to GUI thread
111 CServiceBroker::GetAppMessenger()->SendGUIMessage(msg
, m_dialogId
);
116 const int m_dialogId
{0};
119 CGUIDialogKeyboardGeneric::CGUIDialogKeyboardGeneric()
120 : CGUIDialog(WINDOW_DIALOG_KEYBOARD
, "DialogKeyboard.xml")
122 , m_pCharCallback(NULL
)
124 m_bIsConfirmed
= false;
126 m_hiddenInput
= false;
129 m_loadType
= KEEP_IN_MEMORY
;
130 m_isKeyboardNavigationMode
= false;
131 m_previouslyFocusedButton
= 0;
136 void CGUIDialogKeyboardGeneric::OnWindowLoaded()
138 CGUIEditControl
*edit
= static_cast<CGUIEditControl
*>(GetControl(CTL_EDIT
));
141 // add control CTL_LABEL_HZCODE and CTL_LABEL_HZLIST if not exist
142 CGUIControlGroup
*ParentControl
= static_cast<CGUIControlGroup
*>(edit
->GetParentControl());
143 CLabelInfo labelInfo
= edit
->GetLabelInfo();
144 float px
= edit
->GetXPosition();
145 float py
= edit
->GetYPosition();
146 float pw
= edit
->GetWidth();
147 float ph
= edit
->GetHeight();
149 CGUILabelControl
* control
= static_cast<CGUILabelControl
*>(GetControl(CTL_LABEL_HZCODE
));
152 control
= new CGUILabelControl(GetID(), CTL_LABEL_HZCODE
, px
, py
+ ph
, 90, 30, labelInfo
, false, false);
153 ParentControl
->AddControl(control
);
156 control
= static_cast<CGUILabelControl
*>(GetControl(CTL_LABEL_HZLIST
));
159 labelInfo
.align
= XBFONT_CENTER_Y
;
160 control
= new CGUILabelControl(GetID(), CTL_LABEL_HZLIST
, px
+ 95, py
+ ph
, pw
- 95, 30, labelInfo
, false, false);
161 ParentControl
->AddControl(control
);
165 CGUIDialog::OnWindowLoaded();
168 void CGUIDialogKeyboardGeneric::OnInitWindow()
170 CGUIDialog::OnInitWindow();
172 m_bIsConfirmed
= false;
173 m_isKeyboardNavigationMode
= false;
175 // fill in the keyboard layouts
178 const KeyboardLayouts
& keyboardLayouts
= CServiceBroker::GetKeyboardLayoutManager()->GetLayouts();
179 const std::shared_ptr
<CSettings
> settings
= CServiceBroker::GetSettingsComponent()->GetSettings();
180 std::vector
<CVariant
> layoutNames
= settings
->GetList(CSettings::SETTING_LOCALE_KEYBOARDLAYOUTS
);
181 std::string activeLayout
= settings
->GetString(CSettings::SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT
);
183 for (const auto& layoutName
: layoutNames
)
185 const auto keyboardLayout
= keyboardLayouts
.find(layoutName
.asString());
186 if (keyboardLayout
!= keyboardLayouts
.end())
188 m_layouts
.emplace_back(keyboardLayout
->second
);
189 if (layoutName
.asString() == activeLayout
)
190 m_currentLayout
= m_layouts
.size() - 1;
194 // set alphabetic (capitals)
198 if (!m_strHeading
.empty())
200 SET_CONTROL_LABEL(CTL_LABEL_HEADING
, m_strHeading
);
201 SET_CONTROL_VISIBLE(CTL_LABEL_HEADING
);
205 SET_CONTROL_HIDDEN(CTL_LABEL_HEADING
);
209 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CTL_EDIT
, m_hiddenInput
? CGUIEditControl::INPUT_TYPE_PASSWORD
: CGUIEditControl::INPUT_TYPE_TEXT
);
214 SET_CONTROL_VISIBLE(CTL_BUTTON_REVEAL
);
215 SET_CONTROL_LABEL(CTL_BUTTON_REVEAL
, g_localizeStrings
.Get(12308));
218 SET_CONTROL_HIDDEN(CTL_BUTTON_REVEAL
);
222 // get HZLIST label options
223 CGUILabelControl
* pEdit
= static_cast<CGUILabelControl
*>(GetControl(CTL_LABEL_HZLIST
));
224 CLabelInfo labelInfo
= pEdit
->GetLabelInfo();
225 m_listfont
= labelInfo
.font
;
226 m_listwidth
= pEdit
->GetWidth();
229 SET_CONTROL_LABEL(CTL_LABEL_HZCODE
, "");
230 SET_CONTROL_LABEL(CTL_LABEL_HZLIST
, "");
233 data
["title"] = m_strHeading
;
234 data
["type"] = !m_hiddenInput
? "keyboard" : "password";
235 data
["value"] = GetText();
236 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input
, "OnInputRequested", data
);
239 bool CGUIDialogKeyboardGeneric::OnAction(const CAction
&action
)
241 int actionId
= action
.GetID();
243 if (actionId
== (KEY_VKEY
| XBMCVK_BACK
))
245 else if (actionId
== ACTION_ENTER
||
246 (actionId
== ACTION_SELECT_ITEM
&& (m_isKeyboardNavigationMode
|| GetFocusedControlID() == CTL_EDIT
)))
248 else if (actionId
== ACTION_SHIFT
)
250 else if (actionId
== ACTION_SYMBOLS
)
252 // don't handle move left/right and select in the edit control
253 else if (!m_isKeyboardNavigationMode
&&
254 (actionId
== ACTION_MOVE_LEFT
||
255 actionId
== ACTION_MOVE_RIGHT
||
256 actionId
== ACTION_SELECT_ITEM
))
258 else if (actionId
== ACTION_VOICE_RECOGNIZE
)
259 OnVoiceRecognition();
262 std::wstring wch
= L
"";
263 wch
.insert(wch
.begin(), action
.GetUnicode());
265 g_charsetConverter
.wToUTF8(wch
, ch
);
266 handled
= CodingCharacter(ch
);
269 // send action to edit control
270 CGUIControl
*edit
= GetControl(CTL_EDIT
);
272 handled
= edit
->OnAction(action
);
273 if (!handled
&& actionId
>= KEY_VKEY
&& actionId
< KEY_UNICODE
)
275 unsigned char b
= actionId
& 0xFF;
278 // Toggle left/right key mode
279 m_isKeyboardNavigationMode
= !m_isKeyboardNavigationMode
;
280 if (m_isKeyboardNavigationMode
)
282 m_previouslyFocusedButton
= GetFocusedControlID();
283 SET_CONTROL_FOCUS(edit
->GetID(), 0);
286 SET_CONTROL_FOCUS(m_previouslyFocusedButton
, 0);
293 if (!handled
) // unhandled by us - let's see if the baseclass wants it
294 handled
= CGUIDialog::OnAction(action
);
299 bool CGUIDialogKeyboardGeneric::OnMessage(CGUIMessage
& message
)
301 switch ( message
.GetMessage() )
303 case GUI_MSG_CLICKED
:
305 int iControl
= message
.GetSenderId();
309 case CTL_BUTTON_DONE
:
312 case CTL_BUTTON_CANCEL
:
315 case CTL_BUTTON_SHIFT
:
318 case CTL_BUTTON_CAPS
:
319 if (m_keyType
== LOWER
)
321 else if (m_keyType
== CAPS
)
325 case CTL_BUTTON_LAYOUT
:
328 case CTL_BUTTON_REVEAL
:
331 case CTL_BUTTON_SYMBOLS
:
334 case CTL_BUTTON_LEFT
:
337 case CTL_BUTTON_RIGHT
:
340 case CTL_BUTTON_IP_ADDRESS
:
343 case CTL_BUTTON_CLEAR
:
348 CGUIMessage
msg(GUI_MSG_ITEM_SELECTED
, GetID(), CTL_EDIT
);
350 // update callback I guess?
352 { // we did _something_, so make sure our search message filter is reset
353 m_pCharCallback(this, msg
.GetLabel());
355 m_text
= msg
.GetLabel();
359 OnClickButton(iControl
);
365 case GUI_MSG_SET_TEXT
:
367 // the edit control only handles these messages if it is either focused
368 // or its specific control ID is set in the message. As neither is the
369 // case here (focus is on one of the keyboard buttons) we have to force
370 // the control ID of the message to the control ID of the edit control
371 // (unfortunately we have to create a whole copy of the message object for that)
372 CGUIMessage
messageCopy(message
.GetMessage(), message
.GetSenderId(), CTL_EDIT
, message
.GetParam1(), message
.GetParam2(), message
.GetItem());
373 messageCopy
.SetLabel(message
.GetLabel());
375 // ensure this goes to the edit control
376 CGUIControl
*edit
= GetControl(CTL_EDIT
);
378 edit
->OnMessage(messageCopy
);
380 // close the dialog if requested
381 if (message
.GetMessage() == GUI_MSG_SET_TEXT
&& message
.GetParam1() > 0)
385 case GUI_MSG_CODINGTABLE_LOOKUP_COMPLETED
:
387 const std::string
& code
= message
.GetStringParam();
388 if (code
== m_hzcode
)
390 int response
= message
.GetParam1();
391 auto words
= m_codingtable
->GetResponse(response
);
392 m_words
.insert(m_words
.end(), words
.begin(), words
.end());
398 return CGUIDialog::OnMessage(message
);
401 void CGUIDialogKeyboardGeneric::SetEditText(const std::string
&text
)
403 CGUIMessage
msg(GUI_MSG_SET_TEXT
, GetID(), CTL_EDIT
);
408 void CGUIDialogKeyboardGeneric::SetText(const std::string
& text
)
413 const std::string
&CGUIDialogKeyboardGeneric::GetText() const
418 void CGUIDialogKeyboardGeneric::Character(const std::string
&ch
)
420 if (ch
.empty()) return;
421 if (!CodingCharacter(ch
))
425 void CGUIDialogKeyboardGeneric::NormalCharacter(const std::string
&ch
)
427 // send text to edit control
428 CGUIControl
*edit
= GetControl(CTL_EDIT
);
431 CAction
action(ACTION_INPUT_TEXT
);
433 edit
->OnAction(action
);
437 void CGUIDialogKeyboardGeneric::Backspace()
439 if (m_codingtable
&& m_hzcode
.length() > 0)
442 g_charsetConverter
.utf8ToW(m_hzcode
, tmp
);
443 tmp
.erase(tmp
.length() - 1, 1);
444 g_charsetConverter
.wToUTF8(tmp
, m_hzcode
);
446 switch (m_codingtable
->GetType())
448 case IInputCodingTable::TYPE_WORD_LIST
:
449 SetControlLabel(CTL_LABEL_HZCODE
, m_hzcode
);
453 case IInputCodingTable::TYPE_CONVERT_STRING
:
454 SetEditText(m_codingtable
->ConvertString(m_hzcode
));
460 // send action to edit control
461 CGUIControl
*edit
= GetControl(CTL_EDIT
);
463 edit
->OnAction(CAction(ACTION_BACKSPACE
));
465 if (m_codingtable
&& m_codingtable
->GetType() == IInputCodingTable::TYPE_CONVERT_STRING
)
466 m_codingtable
->SetTextPrev(GetText());
470 void CGUIDialogKeyboardGeneric::OnClickButton(int iButtonControl
)
472 if (iButtonControl
== CTL_BUTTON_BACKSPACE
)
476 else if (iButtonControl
== CTL_BUTTON_SPACE
)
482 const CGUIControl
* pButton
= GetControl(iButtonControl
);
483 // Do not register input for buttons with id >= 500
484 if (pButton
&& iButtonControl
< 500)
486 Character(pButton
->GetDescription());
487 // reset the shift keys
488 if (m_bShift
) OnShift();
493 void CGUIDialogKeyboardGeneric::UpdateButtons()
495 SET_CONTROL_SELECTED(GetID(), CTL_BUTTON_SHIFT
, m_bShift
);
496 SET_CONTROL_SELECTED(GetID(), CTL_BUTTON_CAPS
, m_keyType
== CAPS
);
497 SET_CONTROL_SELECTED(GetID(), CTL_BUTTON_SYMBOLS
, m_keyType
== SYMBOLS
);
499 if (m_currentLayout
>= m_layouts
.size())
501 CKeyboardLayout layout
= m_layouts
.empty() ? CKeyboardLayout() : m_layouts
[m_currentLayout
];
502 m_codingtable
= layout
.GetCodingTable();
503 if (m_codingtable
&& !m_codingtable
->IsInitialized())
504 m_codingtable
->Initialize();
506 bool bShowWordList
= false;
509 switch (m_codingtable
->GetType())
511 case IInputCodingTable::TYPE_WORD_LIST
:
512 bShowWordList
= true;
515 case IInputCodingTable::TYPE_CONVERT_STRING
:
516 m_codingtable
->SetTextPrev(GetText());
524 SET_CONTROL_VISIBLE(CTL_LABEL_HZCODE
);
525 SET_CONTROL_VISIBLE(CTL_LABEL_HZLIST
);
529 SET_CONTROL_HIDDEN(CTL_LABEL_HZCODE
);
530 SET_CONTROL_HIDDEN(CTL_LABEL_HZLIST
);
532 SET_CONTROL_LABEL(CTL_BUTTON_LAYOUT
, layout
.GetName());
534 unsigned int modifiers
= CKeyboardLayout::ModifierKeyNone
;
535 if ((m_keyType
== CAPS
&& !m_bShift
) || (m_keyType
== LOWER
&& m_bShift
))
536 modifiers
|= CKeyboardLayout::ModifierKeyShift
;
537 if (m_keyType
== SYMBOLS
)
539 modifiers
|= CKeyboardLayout::ModifierKeySymbol
;
541 modifiers
|= CKeyboardLayout::ModifierKeyShift
;
544 for (unsigned int row
= 0; row
< BUTTONS_MAX_ROWS
; row
++)
546 for (unsigned int column
= 0; column
< BUTTONS_PER_ROW
; column
++)
548 int buttonID
= (row
* BUTTONS_PER_ROW
) + column
+ BUTTON_ID_OFFSET
;
549 std::string label
= layout
.GetCharAt(row
, column
, modifiers
);
550 SetControlLabel(buttonID
, label
);
552 SET_CONTROL_VISIBLE(buttonID
);
554 SET_CONTROL_HIDDEN(buttonID
);
559 void CGUIDialogKeyboardGeneric::OnDeinitWindow(int nextWindowID
)
561 for (auto& layout
: m_layouts
)
563 auto codingTable
= layout
.GetCodingTable();
564 if (codingTable
&& codingTable
->IsInitialized())
565 codingTable
->Deinitialize();
568 CGUIDialog::OnDeinitWindow(nextWindowID
);
569 // reset the heading (we don't always have this)
572 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input
, "OnInputFinished");
575 void CGUIDialogKeyboardGeneric::MoveCursor(int iAmount
)
577 if (m_codingtable
&& m_words
.size())
578 ChangeWordList(iAmount
);
581 CGUIControl
*edit
= GetControl(CTL_EDIT
);
583 edit
->OnAction(CAction(iAmount
< 0 ? ACTION_CURSOR_LEFT
: ACTION_CURSOR_RIGHT
));
587 void CGUIDialogKeyboardGeneric::OnLayout()
590 if (m_currentLayout
>= m_layouts
.size())
592 CKeyboardLayout layout
= m_layouts
.empty() ? CKeyboardLayout() : m_layouts
[m_currentLayout
];
593 CServiceBroker::GetSettingsComponent()->GetSettings()->SetString(CSettings::SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT
, layout
.GetName());
597 void CGUIDialogKeyboardGeneric::OnSymbols()
599 if (m_keyType
== SYMBOLS
)
606 void CGUIDialogKeyboardGeneric::OnReveal()
608 m_hiddenInput
= !m_hiddenInput
;
609 SET_CONTROL_LABEL(CTL_BUTTON_REVEAL
, g_localizeStrings
.Get(m_hiddenInput
? 12308 : 12309));
610 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CTL_EDIT
,
611 m_hiddenInput
? CGUIEditControl::INPUT_TYPE_PASSWORD
612 : CGUIEditControl::INPUT_TYPE_TEXT
);
616 void CGUIDialogKeyboardGeneric::OnShift()
618 m_bShift
= !m_bShift
;
622 void CGUIDialogKeyboardGeneric::OnIPAddress()
624 // find any IP address in the current string if there is any
625 // We match to #.#.#.#
626 std::string text
= GetText();
629 reg
.RegComp("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+");
630 int start
= reg
.RegFind(text
.c_str());
634 length
= reg
.GetSubLength(0);
635 ip
= text
.substr(start
, length
);
639 if (CGUIDialogNumeric::ShowAndGetIPAddress(ip
, g_localizeStrings
.Get(14068)))
640 SetEditText(text
.substr(0, start
) + ip
+ text
.substr(start
+ length
));
643 void CGUIDialogKeyboardGeneric::OnVoiceRecognition()
645 const auto speechRecognition
= CServiceBroker::GetSpeechRecognition();
646 if (speechRecognition
)
648 if (!m_speechRecognitionListener
)
649 m_speechRecognitionListener
= std::make_shared
<CSpeechRecognitionListener
>(GetID());
651 speechRecognition
->StartSpeechRecognition(m_speechRecognitionListener
);
655 CLog::LogF(LOGWARNING
, "No voice recognition implementation available.");
659 void CGUIDialogKeyboardGeneric::SetControlLabel(int id
, const std::string
&label
)
660 { // find all controls with this id, and set all their labels
661 CGUIMessage
message(GUI_MSG_LABEL_SET
, GetID(), id
);
662 message
.SetLabel(label
);
663 for (unsigned int i
= 0; i
< m_children
.size(); i
++)
665 if (m_children
[i
]->GetID() == id
|| m_children
[i
]->IsGroup())
666 m_children
[i
]->OnMessage(message
);
670 void CGUIDialogKeyboardGeneric::OnOK()
672 m_bIsConfirmed
= true;
676 void CGUIDialogKeyboardGeneric::SetHeading(const std::string
&heading
)
678 m_strHeading
= heading
;
681 int CGUIDialogKeyboardGeneric::GetWindowId() const
686 void CGUIDialogKeyboardGeneric::Cancel()
688 m_bIsConfirmed
= false;
692 bool CGUIDialogKeyboardGeneric::ShowAndGetInput(char_callback_t pCallback
, const std::string
&initialString
, std::string
&typedString
, const std::string
&heading
, bool bHiddenInput
)
694 CGUIDialogKeyboardGeneric
*pKeyboard
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogKeyboardGeneric
>(WINDOW_DIALOG_KEYBOARD
);
699 m_pCharCallback
= pCallback
;
701 pKeyboard
->Initialize();
702 pKeyboard
->SetHeading(heading
);
703 pKeyboard
->SetHiddenInput(bHiddenInput
);
704 pKeyboard
->SetText(initialString
);
708 // If have text - update this.
709 if (pKeyboard
->IsConfirmed())
711 typedString
= pKeyboard
->GetText();
717 float CGUIDialogKeyboardGeneric::GetStringWidth(const std::wstring
& utf16
)
721 utf32
.resize(utf16
.size());
722 for (unsigned int i
= 0; i
< utf16
.size(); i
++)
725 return m_listfont
->GetTextWidth(utf32
);
728 void CGUIDialogKeyboardGeneric::ChangeWordList(int direct
)
734 m_codingtable
->GetWordListPage(m_hzcode
, true);
738 ShowWordList(direct
);
739 if (direct
> 0 && m_pos
+ m_num
== static_cast<int>(m_words
.size()))
740 m_codingtable
->GetWordListPage(m_hzcode
, false);
744 void CGUIDialogKeyboardGeneric::ShowWordList(int direct
)
746 std::unique_lock
<CCriticalSection
> lock(m_CS
);
747 std::wstring hzlist
= L
"";
748 CServiceBroker::GetWinSystem()->GetGfxContext().SetScalingResolution(m_coordsRes
, true);
749 float width
= m_listfont
->GetCharWidth(L
'<') + m_listfont
->GetCharWidth(L
'>');
750 float spacewidth
= m_listfont
->GetCharWidth(L
' ');
751 float numwidth
= m_listfont
->GetCharWidth(L
'1') + m_listfont
->GetCharWidth(L
'.');
758 if (m_pos
> static_cast<int>(m_words
.size()) - 1)
760 for (i
= 0; m_pos
+ i
< static_cast<int>(m_words
.size()); i
++)
762 if ((i
> 0 && width
+ GetStringWidth(m_words
[m_pos
+ i
]) + numwidth
> m_listwidth
) || i
> 9)
764 hzlist
.insert(hzlist
.length(), 1, (wchar_t)(i
+ 48));
765 hzlist
.insert(hzlist
.length(), 1, L
'.');
766 hzlist
.append(m_words
[m_pos
+ i
]);
767 hzlist
.insert(hzlist
.length(), 1, L
' ');
768 width
+= GetStringWidth(m_words
[m_pos
+ i
]) + numwidth
+ spacewidth
;
776 for (i
= 1; i
<= 10; i
++)
778 if (m_pos
- i
< 0 || (i
> 1 && width
+ GetStringWidth(m_words
[m_pos
- i
]) + numwidth
> m_listwidth
))
780 width
+= GetStringWidth(m_words
[m_pos
- i
]) + numwidth
+ spacewidth
;
784 for (i
= 0; i
< m_num
; i
++)
786 hzlist
.insert(hzlist
.length(), 1, (wchar_t)(i
+ 48));
787 hzlist
.insert(hzlist
.length(), 1, L
'.');
788 hzlist
.append(m_words
[m_pos
+ i
]);
789 hzlist
.insert(hzlist
.length(), 1, L
' ');
792 hzlist
.erase(hzlist
.find_last_not_of(L
' ') + 1);
794 hzlist
.insert(0, 1, L
'<');
795 if (m_pos
+ m_num
< static_cast<int>(m_words
.size()))
796 hzlist
.insert(hzlist
.length(), 1, L
'>');
797 std::string utf8String
;
798 g_charsetConverter
.wToUTF8(hzlist
, utf8String
);
799 SET_CONTROL_LABEL(CTL_LABEL_HZLIST
, utf8String
);
802 bool CGUIDialogKeyboardGeneric::CodingCharacter(const std::string
&ch
)
807 switch (m_codingtable
->GetType())
809 case IInputCodingTable::TYPE_CONVERT_STRING
:
810 if (!ch
.empty() && ch
[0] != 0)
813 SetEditText(m_codingtable
->ConvertString(m_hzcode
));
818 case IInputCodingTable::TYPE_WORD_LIST
:
819 if (m_codingtable
->GetCodeChars().find(ch
) != std::string::npos
)
822 SetControlLabel(CTL_LABEL_HZCODE
, m_hzcode
);
826 if (ch
[0] >= '0' && ch
[0] <= '9')
828 int i
= m_pos
+ (int)ch
[0] - 48;
829 if (i
< (m_pos
+ m_num
))
832 SetControlLabel(CTL_LABEL_HZCODE
, m_hzcode
);
833 std::string utf8String
;
834 g_charsetConverter
.wToUTF8(m_words
[i
], utf8String
);
835 NormalCharacter(utf8String
);