113 lines
3.7 KiB
C++
113 lines
3.7 KiB
C++
/*
|
|
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
|
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
|
|
* (C) 1999 Antti Koivisto (koivisto@kde.org)
|
|
* (C) 2001 Dirk Mueller (mueller@kde.org)
|
|
* Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
|
|
* (C) 2006 Alexey Proskuryakov (ap@nypop.com)
|
|
* Copyright (C) 2010 Google Inc. All rights reserved.
|
|
* Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "TypeAhead.h"
|
|
|
|
#include "KeyboardEvent.h"
|
|
#include <wtf/text/StringToIntegerConversion.h>
|
|
#include <wtf/unicode/CharacterNames.h>
|
|
|
|
namespace WebCore {
|
|
|
|
TypeAhead::TypeAhead(TypeAheadDataSource* dataSource)
|
|
: m_dataSource(dataSource)
|
|
, m_repeatingChar(0)
|
|
{
|
|
}
|
|
|
|
static const Seconds typeAheadTimeout { 1_s };
|
|
|
|
static String stripLeadingWhiteSpace(const String& string)
|
|
{
|
|
unsigned length = string.length();
|
|
unsigned i;
|
|
for (i = 0; i < length; ++i) {
|
|
if (string[i] != noBreakSpace && !isSpaceOrNewline(string[i]))
|
|
break;
|
|
}
|
|
return string.substring(i, length - i);
|
|
}
|
|
|
|
int TypeAhead::handleEvent(KeyboardEvent* event, MatchModeFlags matchMode)
|
|
{
|
|
if (event->timeStamp() < m_lastTypeTime)
|
|
return -1;
|
|
|
|
int optionCount = m_dataSource->optionCount();
|
|
Seconds delta = event->timeStamp() - m_lastTypeTime;
|
|
m_lastTypeTime = event->timeStamp();
|
|
|
|
UChar c = event->charCode();
|
|
|
|
if (delta > typeAheadTimeout)
|
|
m_buffer.clear();
|
|
m_buffer.append(c);
|
|
|
|
if (optionCount < 1)
|
|
return -1;
|
|
|
|
int searchStartOffset = 1;
|
|
String prefix;
|
|
if (matchMode & CycleFirstChar && c == m_repeatingChar) {
|
|
// The user is likely trying to cycle through all the items starting
|
|
// with this character, so just search on the character.
|
|
prefix = String(&c, 1);
|
|
m_repeatingChar = c;
|
|
} else if (matchMode & MatchPrefix) {
|
|
prefix = m_buffer.toString();
|
|
if (m_buffer.length() > 1) {
|
|
m_repeatingChar = 0;
|
|
searchStartOffset = 0;
|
|
} else
|
|
m_repeatingChar = c;
|
|
}
|
|
|
|
if (!prefix.isEmpty()) {
|
|
int selected = m_dataSource->indexOfSelectedOption();
|
|
int index = (selected < 0 ? 0 : selected) + searchStartOffset;
|
|
index %= optionCount;
|
|
|
|
String prefixWithCaseFolded(prefix.foldCase());
|
|
for (int i = 0; i < optionCount; ++i, index = (index + 1) % optionCount) {
|
|
// Fold the option string and check if its prefix is equal to the folded prefix.
|
|
String text = m_dataSource->optionAtIndex(index);
|
|
if (stripLeadingWhiteSpace(text).foldCase().startsWith(prefixWithCaseFolded))
|
|
return index;
|
|
}
|
|
}
|
|
|
|
if (matchMode & MatchIndex) {
|
|
int index = parseIntegerAllowingTrailingJunk<int>(m_buffer).value_or(0);
|
|
if (index > 0 && index <= optionCount)
|
|
return index - 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
} // namespace WebCore
|