void CGUIDialogKeyboardGeneric::UpdateLabel() // FIXME seems to be called twice for one USB SDL keyboard action/character
{
  CGUILabelControl* pEdit = ((CGUILabelControl*)GetControl(CTL_LABEL_EDIT));
  if (pEdit)
  {
    CStdStringW edit = m_strEdit;
    if (m_hiddenInput)
    { // convert to *'s
      edit.Empty();
      if (m_lastRemoteClickTime + REMOTE_SMS_DELAY > CTimeUtils::GetFrameTime() && m_strEdit.size())
      { // using the remove to input, so display the last key input
        edit.append(m_strEdit.size() - 1, L'*');
        edit.append(1, m_strEdit[m_strEdit.size() - 1]);
      }
      else
        edit.append(m_strEdit.size(), L'*');
    }
    // convert back to utf8
    CStdString utf8Edit;
    g_charsetConverter.wToUTF8(edit, utf8Edit);
    pEdit->SetLabel(utf8Edit);
    // Send off a search message
    unsigned int now = CTimeUtils::GetFrameTime();
    // don't send until the REMOTE_SMS_DELAY has passed
    if (m_lastRemoteClickTime && m_lastRemoteClickTime + REMOTE_SMS_DELAY >= now)
      return;

    if (m_pCharCallback)
      m_pCharCallback(this, utf8Edit);
  }
}
void CGUIDialogKeyboardGeneric::UpdateLabel() // FIXME seems to be called twice for one USB SDL keyboard action/character
{
  CGUILabelControl* pEdit = ((CGUILabelControl*)GetControl(CTL_LABEL_EDIT));
  if (pEdit)
  {
    CStdStringW edit = m_strEdit;
    pEdit->SetHighlight(0, 0);
    pEdit->SetSelection(0, 0);
    if (m_hiddenInput)
    { // convert to *'s
      edit.clear();
      if (m_lastRemoteClickTime + REMOTE_SMS_DELAY > CTimeUtils::GetFrameTime() && m_iCursorPos > 0)
      { // using the remove to input, so display the last key input
        edit.append(m_iCursorPos - 1, L'*');
        edit.append(1, m_strEdit[m_iCursorPos - 1]);
      }
      else
        edit.append(m_strEdit.size(), L'*');
    }
    else if (!m_strEditing.empty())
    {
      edit.insert(m_iCursorPos, m_strEditing);
      pEdit->SetHighlight(m_iCursorPos, m_iCursorPos + m_strEditing.size());
      if (m_iEditingLength > 0)
        pEdit->SetSelection(m_iCursorPos + m_iEditingOffset, m_iCursorPos + m_iEditingOffset + m_iEditingLength);
    }
    // convert back to utf8
    CStdString utf8Edit;
    g_charsetConverter.wToUTF8(edit, utf8Edit);
    pEdit->SetLabel(utf8Edit);
    // Send off a search message
    unsigned int now = CTimeUtils::GetFrameTime();
    // don't send until the REMOTE_SMS_DELAY has passed
    if (m_lastRemoteClickTime && m_lastRemoteClickTime + REMOTE_SMS_DELAY >= now)
      return;

    if (m_pCharCallback)
    {
      // do not send editing text comes from system input method
      if (!m_hiddenInput && !m_strEditing.empty())
        g_charsetConverter.wToUTF8(m_strEdit, utf8Edit);
      m_pCharCallback(this, utf8Edit);
    }
  }
}
bool CGUIDialogKeyboardGeneric::OnMessage(CGUIMessage& message)
{
    switch ( message.GetMessage() )
    {
    case GUI_MSG_CLICKED:
    {
        int iControl = message.GetSenderId();

        switch (iControl)
        {
        case CTL_BUTTON_DONE:
            OnOK();
            break;
        case CTL_BUTTON_CANCEL:
            Close();
            break;
        case CTL_BUTTON_SHIFT:
            OnShift();
            break;
        case CTL_BUTTON_CAPS:
            if (m_keyType == LOWER)
                m_keyType = CAPS;
            else if (m_keyType == CAPS)
                m_keyType = LOWER;
            UpdateButtons();
            break;
        case CTL_BUTTON_LAYOUT:
            OnLayout();
            break;
        case CTL_BUTTON_SYMBOLS:
            OnSymbols();
            break;
        case CTL_BUTTON_LEFT:
            MoveCursor( -1);
            break;
        case CTL_BUTTON_RIGHT:
            MoveCursor(1);
            break;
        case CTL_BUTTON_IP_ADDRESS:
            OnIPAddress();
            break;
        case CTL_BUTTON_CLEAR:
            SetEditText("");
            break;
        case CTL_EDIT:
        {
            CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CTL_EDIT);
            OnMessage(msg);
            // update callback I guess?
            if (m_pCharCallback)
            {   // we did _something_, so make sure our search message filter is reset
                m_pCharCallback(this, msg.GetLabel());
            }
            m_text = msg.GetLabel();
            return true;
        }
        default:
            OnClickButton(iControl);
            break;
        }
    }
    break;

    case GUI_MSG_SET_TEXT:
    case GUI_MSG_INPUT_TEXT_EDIT:
    {
        // the edit control only handles these messages if it is either focues
        // or its specific control ID is set in the message. As neither is the
        // case here (focus is on one of the keyboard buttons) we have to force
        // the control ID of the message to the control ID of the edit control
        // (unfortunately we have to create a whole copy of the message object for that)
        CGUIMessage messageCopy(message.GetMessage(), message.GetSenderId(), CTL_EDIT, message.GetParam1(), message.GetParam2(), message.GetItem());
        messageCopy.SetLabel(message.GetLabel());

        // ensure this goes to the edit control
        CGUIControl *edit = GetControl(CTL_EDIT);
        if (edit)
            edit->OnMessage(messageCopy);

        // close the dialog if requested
        if (message.GetMessage() == GUI_MSG_SET_TEXT && message.GetParam1() > 0)
            OnOK();
        return true;
    }
    }

    return CGUIDialog::OnMessage(message);
}
bool CGUIDialogKeyboardGeneric::OnAction(const CAction &action)
{
  bool handled(true);
  if (action.GetID() == ACTION_BACKSPACE)
  {
    Backspace();
  }
  else if (action.GetID() == ACTION_ENTER)
  {
    OnOK();
  }
  else if (action.GetID() == ACTION_CURSOR_LEFT)
  {
    MoveCursor( -1);
  }
  else if (action.GetID() == ACTION_CURSOR_RIGHT)
  {
    if ((unsigned int) GetCursorPos() == m_strEdit.size() && (m_strEdit.size() == 0 || m_strEdit[m_strEdit.size() - 1] != ' '))
    { // add a space
      Character(L' ');
    }
    else
      MoveCursor(1);
  }
  else if (action.GetID() == ACTION_SHIFT)
  {
    OnShift();
  }
  else if (action.GetID() == ACTION_SYMBOLS)
  {
    OnSymbols();
  }
  else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9)
  {
    OnRemoteNumberClick(action.GetID());
  }
  else if (action.GetID() >= KEY_VKEY && action.GetID() < KEY_ASCII)
  { // input from the keyboard (vkey, not ascii)
    uint8_t b = action.GetID() & 0xFF;
    if (b == XBMCVK_HOME)
    {
      MoveCursor(-GetCursorPos());
    }
    else if (b == XBMCVK_END)
    {
      MoveCursor(m_strEdit.GetLength() - GetCursorPos());
    }
    else if (b == XBMCVK_LEFT)
    {
      MoveCursor( -1);
    }
    else if (b == XBMCVK_RIGHT)
    {
      MoveCursor(1);
    }
    else if (b == XBMCVK_RETURN || b == XBMCVK_NUMPADENTER)
    {
      OnOK();
    }
    else if (b == XBMCVK_DELETE)
    {
      if (GetCursorPos() < m_strEdit.GetLength())
      {
        MoveCursor(1);
        Backspace();
      }
    }
    else if (b == XBMCVK_BACK) Backspace();
    else if (b == XBMCVK_ESCAPE) Close();
  }
  else if (action.GetID() >= KEY_ASCII)
  { // input from the keyboard
    //char ch = action.GetID() & 0xFF;
    switch (action.GetUnicode())
    {
    case 13:  // enter
    case 10:  // enter
      OnOK();
      break;
    case 8:   // backspace
      Backspace();
      break;
    case 27:  // escape
      Close();
      break;
    default:  //use character input
      Character(action.GetUnicode());
      break;
    }
  }
  else // unhandled by us - let's see if the baseclass wants it
    handled = CGUIDialog::OnAction(action);

  if (handled && m_pCharCallback)
  { // we did _something_, so make sure our search message filter is reset
    m_pCharCallback(this, GetText());
  }
  return handled;
}
bool CGUIDialogKeyboardGeneric::OnMessage(CGUIMessage& message)
{
  switch ( message.GetMessage() )
  {
  case GUI_MSG_CLICKED:
    {
      int iControl = message.GetSenderId();

      switch (iControl)
      {
      case CTL_BUTTON_DONE:
        OnOK();
        break;
      case CTL_BUTTON_CANCEL:
        Close();
        break;
      case CTL_BUTTON_SHIFT:
        OnShift();
        break;
      case CTL_BUTTON_CAPS:
        if (m_keyType == LOWER)
          m_keyType = CAPS;
        else if (m_keyType == CAPS)
          m_keyType = LOWER;
        UpdateButtons();
        break;
      case CTL_BUTTON_SYMBOLS:
        OnSymbols();
        break;
      case CTL_BUTTON_LEFT:
        MoveCursor( -1);
        break;
      case CTL_BUTTON_RIGHT:
        MoveCursor(1);
        break;
      case CTL_BUTTON_IP_ADDRESS:
        OnIPAddress();
        break;
      case CTL_BUTTON_CLEAR:
        SetEditText("");
        break;
      case CTL_EDIT:
      {
        CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CTL_EDIT);
        OnMessage(msg);
        // update callback I guess?
        if (m_pCharCallback)
        { // we did _something_, so make sure our search message filter is reset
          m_pCharCallback(this, msg.GetLabel());
        }
        m_text = msg.GetLabel();
        return true;
      }
      default:
        OnClickButton(iControl);
        break;
      }
    }
    break;

  case GUI_MSG_SET_TEXT:
  case GUI_MSG_INPUT_TEXT:
  case GUI_MSG_INPUT_TEXT_EDIT:
    {
      // ensure this goes to the edit control
      CGUIControl *edit = GetControl(CTL_EDIT);
      if (edit)
        edit->OnMessage(message);

      // close the dialog if requested
      if (message.GetMessage() == GUI_MSG_SET_TEXT && message.GetParam1() > 0)
        OnOK();
      return true;
    }
  }

  return CGUIDialog::OnMessage(message);
}
bool CGUIDialogKeyboardGeneric::OnAction(const CAction &action)
{
  bool handled(true);
  if (action.GetID() == ACTION_BACKSPACE)
  {
    Backspace();
  }
  else if (action.GetID() == ACTION_ENTER)
  {
    OnOK();
  }
  else if (action.GetID() == ACTION_CURSOR_LEFT)
  {
    MoveCursor( -1);
  }
  else if (action.GetID() == ACTION_CURSOR_RIGHT)
  {
    if (m_strEditing.empty() && (unsigned int) GetCursorPos() == m_strEdit.size() && (m_strEdit.size() == 0 || m_strEdit[m_strEdit.size() - 1] != ' '))
    { // add a space
      Character(L' ');
    }
    else
      MoveCursor(1);
  }
  else if (action.GetID() == ACTION_SHIFT)
  {
    OnShift();
  }
  else if (action.GetID() == ACTION_SYMBOLS)
  {
    OnSymbols();
  }
  else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9)
  {
    OnRemoteNumberClick(action.GetID());
  }
  else if (action.GetID() == ACTION_PASTE)
  {
    OnPasteClipboard();
  }
  else if ( (action.GetID() >= KEY_VKEY && action.GetID() < KEY_ASCII) ||
  			(action.GetButtonCode() >= KEY_VKEY && action.GetButtonCode() < KEY_ASCII) )
  { // input from the keyboard (vkey, not ascii)
    if (!m_strEditing.empty())
      return handled;
    uint8_t b = action.GetButtonCode() ? action.GetButtonCode() & 0xFF : action.GetID() & 0xFF;
    
    switch (b)
    {
	case XBMCVK_HOME:
    	SetCursorPos(0);
    	break;
    case XBMCVK_END:
	    SetCursorPos(m_strEdit.size());
    	break;
    case XBMCVK_LEFT:
    	MoveCursor( -1);
    	break;
    case XBMCVK_RIGHT:
    	MoveCursor(1);
    	break;
    case XBMCVK_RETURN:
    case XBMCVK_NUMPADENTER:
    	OnOK();
    	break;
    case XBMCVK_DELETE:
		if (GetCursorPos() < (int)m_strEdit.size())
		{
			MoveCursor(1);
			Backspace();
		}
    	break;
    case XBMCVK_BACK:
    	Backspace();
    	break;
    case XBMCVK_ESCAPE:
    	Close();
    	break;
    case XBMCVK_LSHIFT:
    case XBMCVK_RSHIFT:
		OnShift();
		break;
	case XBMCVK_CAPSLOCK:
		OnCapsLock();
		break;
	}	
  }
  else if (action.GetID() >= KEY_ASCII)
  { // input from the keyboard
    //char ch = action.GetID() & 0xFF;
    int ch = action.GetUnicode();
    
    if( m_keyType == LOWER && m_bShift )
    {
		if (ch >= 'a' && ch <= 'z')
    		ch -= 32;
    		
    	OnShift();	
	}	
	else if( m_keyType == CAPS && !m_bShift )
	{
		if (ch >= 'a' && ch <= 'z')
    		ch -= 32;
    }
    else if( m_keyType == CAPS && m_bShift )
    	OnShift();
   		
    // Ignore non-printing characters
    if ( !((0 <= ch && ch < 0x8) || (0xE <= ch && ch < 0x1B) || (0x1C <= ch && ch < 0x20)) )
    {
      switch (ch)
      {
      case 0x8: // backspace
        Backspace();
        break;
      case 0x9: // Tab (do nothing)
      case 0xB: // Non-printing character, ignore
      case 0xC: // Non-printing character, ignore
        break;
      case 0xA: // enter
      case 0xD: // enter
        OnOK();
        break;
      case 0x1B: // escape
        Close();
        break;
      case 0x7F: // Delete
        if (GetCursorPos() < (int)m_strEdit.size())
        {
          MoveCursor(1);
          Backspace();
        }
        break;
      default:  //use character input
        // When we support text input method, we only accept text by gui text message.
        if (!g_Windowing.IsTextInputEnabled())
	        Character(ch);
	        //Character(action.GetUnicode());
        break;
      }
    }
  }
  else // unhandled by us - let's see if the baseclass wants it
    handled = CGUIDialog::OnAction(action);

  if (handled && m_pCharCallback)
  { // we did _something_, so make sure our search message filter is reset
    m_pCharCallback(this, GetText());
  }
  return handled;
}