<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/services/editing/ios/keyboard_impl.h"

#include <UIKit/UIKit.h>
#include <unicode/utf16.h>
#include "base/strings/utf_string_conversions.h"

static inline UIKeyboardType ToUIKeyboardType(::editing::KeyboardType type) {
  using Type = ::editing::KeyboardType;
  switch (type) {
    case Type::TEXT:
      return UIKeyboardTypeDefault;
    case Type::NUMBER:
      return UIKeyboardTypeDecimalPad;
    case Type::PHONE:
      return UIKeyboardTypePhonePad;
    default:
      break;
  }
  return UIKeyboardTypeDefault;
}

@interface KeyboardClient : UIView<UIKeyInput>

- (void)setClient:(::editing::KeyboardClientPtr)client;
- (void)setEditingState:(::editing::EditingStatePtr)state;
- (void)show;
- (void)hide;

@end

@implementation KeyboardClient {
  ::editing::KeyboardClientPtr _client;
  ::editing::EditingStatePtr _state;
  base::string16 _text;
}

@synthesize keyboardType = _keyboardType;

- (UITextAutocorrectionType)autocorrectionType {
  return UITextAutocorrectionTypeNo;
}

- (void)setClient:(::editing::KeyboardClientPtr)client {
  _client = client.Pass();
}

- (void)setEditingState:(::editing::EditingStatePtr)state {
  _state = state.Pass();
  _text = base::UTF8ToUTF16(_state->text.To<std::string>());
}

- (void)show {
  NSAssert([UIApplication sharedApplication].keyWindow != nullptr,
           @"The application must have a key window since the keyboard client "
           @"must be part of the responder chain to function");
  [[UIApplication sharedApplication].keyWindow addSubview:self];
  [self becomeFirstResponder];
}

- (void)hide {
  [self resignFirstResponder];
  [self removeFromSuperview];
}

#pragma mark - UIResponder Overrides

- (BOOL)canBecomeFirstResponder {
  return YES;
}

#pragma mark - UIKeyInput Overrides

// TODO(abarth): We should implement UITextInput for more features.

- (BOOL)hasText {
  return YES;
}

- (void)insertText:(NSString*)text {
  int start = std::min(_state->selection_base, _state->selection_extent);
  int end = std::max(_state->selection_base, _state->selection_extent);
  int len = end - start;
  _text.replace(start, len, base::UTF8ToUTF16(text.UTF8String));
  int caret = start + text.length;
  _state->selection_base = caret;
  _state->selection_extent = caret;
  _state->selection_affinity = ::editing::TextAffinity::UPSTREAM;
  _state->selection_is_directional = false;
  _state->composing_base = 0;
  _state->composing_extent = 0;
  _state->text = base::UTF16ToUTF8(_text);
  _client->UpdateEditingState(_state.Clone());
}

- (void)deleteBackward {
  int start = std::min(_state->selection_base, _state->selection_extent);
  int end = std::max(_state->selection_base, _state->selection_extent);
  int len = end - start;
  if (len > 0) {
    _text.erase(start, len);
  } else if (start > 0) {
    start -= 1;
    len = 1;
    if (start > 0 &&
        UTF16_IS_LEAD(_text[start - 1]) &&
        UTF16_IS_TRAIL(_text[start])) {
      start -= 1;
      len += 1;
    }
    _text.erase(start, len);
  }
  _state->selection_base = start;
  _state->selection_extent = start;
  _state->selection_affinity = ::editing::TextAffinity::DOWNSTREAM;
  _state->selection_is_directional = false;
  _state->composing_base = 0;
  _state->composing_extent = 0;
  _state->text = base::UTF16ToUTF8(_text);
  _client->UpdateEditingState(_state.Clone());
}

@end

namespace sky {
namespace services {
namespace editing {

KeyboardImpl::KeyboardImpl(
    mojo::InterfaceRequest<::editing::Keyboard> request)
    : binding_(this, request.Pass()), client_([[KeyboardClient alloc] init]) {}

KeyboardImpl::~KeyboardImpl() {
  [client_ release];
}

void KeyboardImpl::SetClient(::editing::KeyboardClientPtr client,
                                    ::editing::KeyboardConfigurationPtr configuration) {
  client_.keyboardType = ToUIKeyboardType(configuration->type);
  [client_ setClient:client.Pass()];
}

void KeyboardImpl::SetEditingState(::editing::EditingStatePtr state) {
  [client_ setEditingState: state.Pass()];
}

void KeyboardImpl::Show() {
  [client_ show];
}
<commit_msg>Make iOS keyboard robust to selection of -1<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/services/editing/ios/keyboard_impl.h"

#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include <UIKit/UIKit.h>
#include <unicode/utf16.h>

static inline UIKeyboardType ToUIKeyboardType(::editing::KeyboardType type) {
  using Type = ::editing::KeyboardType;
  switch (type) {
    case Type::TEXT:
      return UIKeyboardTypeDefault;
    case Type::NUMBER:
      return UIKeyboardTypeDecimalPad;
    case Type::PHONE:
      return UIKeyboardTypePhonePad;
    default:
      break;
  }
  return UIKeyboardTypeDefault;
}

@interface KeyboardClient : UIView<UIKeyInput>

- (void)setClient:(::editing::KeyboardClientPtr)client;
- (void)setEditingState:(::editing::EditingStatePtr)state;
- (void)show;
- (void)hide;

@end

@implementation KeyboardClient {
  ::editing::KeyboardClientPtr _client;
  ::editing::EditingStatePtr _state;
  base::string16 _text;
}

@synthesize keyboardType = _keyboardType;

- (UITextAutocorrectionType)autocorrectionType {
  return UITextAutocorrectionTypeNo;
}

- (void)setClient:(::editing::KeyboardClientPtr)client {
  _client = client.Pass();
}

- (void)setEditingState:(::editing::EditingStatePtr)state {
  _state = state.Pass();
  _text = base::UTF8ToUTF16(_state->text.To<std::string>());
}

- (void)show {
  NSAssert([UIApplication sharedApplication].keyWindow != nullptr,
           @"The application must have a key window since the keyboard client "
           @"must be part of the responder chain to function");
  [[UIApplication sharedApplication].keyWindow addSubview:self];
  [self becomeFirstResponder];
}

- (void)hide {
  [self resignFirstResponder];
  [self removeFromSuperview];
}

#pragma mark - UIResponder Overrides

- (BOOL)canBecomeFirstResponder {
  return YES;
}

#pragma mark - UIKeyInput Overrides

// TODO(abarth): We should implement UITextInput for more features.

- (BOOL)hasText {
  return YES;
}

- (void)insertText:(NSString*)text {
  int start = std::max(0, std::min(_state->selection_base, _state->selection_extent));
  int end = std::max(0, std::max(_state->selection_base, _state->selection_extent));
  int len = end - start;
  _text.replace(start, len, base::SysNSStringToUTF16(text));
  int caret = start + text.length;
  _state->selection_base = caret;
  _state->selection_extent = caret;
  _state->selection_affinity = ::editing::TextAffinity::UPSTREAM;
  _state->selection_is_directional = false;
  _state->composing_base = 0;
  _state->composing_extent = 0;
  _state->text = base::UTF16ToUTF8(_text);
  _client->UpdateEditingState(_state.Clone());
}

- (void)deleteBackward {
  int start = std::max(0, std::min(_state->selection_base, _state->selection_extent));
  int end = std::max(0, std::max(_state->selection_base, _state->selection_extent));
  int len = end - start;
  if (len > 0) {
    _text.erase(start, len);
  } else if (start > 0) {
    start -= 1;
    len = 1;
    if (start > 0 &&
        UTF16_IS_LEAD(_text[start - 1]) &&
        UTF16_IS_TRAIL(_text[start])) {
      start -= 1;
      len += 1;
    }
    _text.erase(start, len);
  }
  _state->selection_base = start;
  _state->selection_extent = start;
  _state->selection_affinity = ::editing::TextAffinity::DOWNSTREAM;
  _state->selection_is_directional = false;
  _state->composing_base = 0;
  _state->composing_extent = 0;
  _state->text = base::UTF16ToUTF8(_text);
  _client->UpdateEditingState(_state.Clone());
}

@end

namespace sky {
namespace services {
namespace editing {

KeyboardImpl::KeyboardImpl(
    mojo::InterfaceRequest<::editing::Keyboard> request)
    : binding_(this, request.Pass()), client_([[KeyboardClient alloc] init]) {}

KeyboardImpl::~KeyboardImpl() {
  [client_ hide];
  [client_ release];
}

void KeyboardImpl::SetClient(::editing::KeyboardClientPtr client,
                             ::editing::KeyboardConfigurationPtr config) {
  client_.keyboardType = ToUIKeyboardType(config->type);
  [client_ setClient:client.Pass()];
}

void KeyboardImpl::SetEditingState(::editing::EditingStatePtr state) {
  [client_ setEditingState:state.Pass()];
}

void KeyboardImpl::Show() {
  [client_ show];
}

{'fraction_non_alphanumeric': 0.13369856626646462, 'fraction_numerical': 0.008975405058864669, 'mean_word_length': 4.678358702845798, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4217063', 'n_tokens_mistral': 2893, 'n_tokens_neox': 2842, 'n_words': 560}