chromium/third_party/google_input_tools/src/chrome/os/inputview/util.js

// Copyright 2014 The ChromeOS IME Authors. All Rights Reserved.
// limitations under the License.
// See the License for the specific language governing permissions and
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// distributed under the License is distributed on an "AS-IS" BASIS,
// Unless required by applicable law or agreed to in writing, software
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// You may obtain a copy of the License at
// you may not use this file except in compliance with the License.
// Licensed under the Apache License, Version 2.0 (the "License");
//
goog.provide('i18n.input.chrome.inputview.util');

goog.require('goog.string');
goog.require('goog.style');


goog.scope(function() {
var util = i18n.input.chrome.inputview.util;


/**
 * The mapping between the real character and its replacement for display.
 *
 * @type {!Object.<string, string>}
 */
util.DISPLAY_MAPPING = {
  '\u0300' : '\u0060',
  '\u0301' : '\u00B4',
  '\u0302' : '\u02C6',
  '\u0303' : '\u02DC',
  '\u0304' : '\u02c9',
  '\u0305' : '\u00AF',
  '\u0306' : '\u02D8',
  '\u0307' : '\u02D9',
  '\u0308' : '\u00a8',
  '\u0309' : '\u02C0',
  '\u030A' : '\u02DA',
  '\u030B' : '\u02DD',
  '\u030C' : '\u02C7',
  '\u030D' : '\u02C8',
  '\u030E' : '\u0022',
  '\u0327' : '\u00B8',
  '\u0328' : '\u02DB',
  '\u0345' : '\u037A',
  '\u030F' : '\u030F\u0020',
  '\u031B' : '\u031B\u0020',
  '\u0323' : '\u0323\u0020'
};


/**
 * Special lower to upper case mapping.
 *
 * @private {!Object.<string, string>}
 */
util.CASE_LOWER_TO_UPPER_MAPPING_ = {
  '\u00b5': '\u00b5',
  // Korean characters.
  '\u3142': '\u3143',
  '\u3148': '\u3149',
  '\u3137': '\u3138',
  '\u3131': '\u3132',
  '\u3145': '\u3146',
  '\u1162': '\u1164',
  '\u1166': '\u1168'
};


/**
 * Special upper to lower case mapping.
 *
 * @private {!Object.<string, string>}
 */
util.CASE_UPPER_TO_LOWER_MAPPING_ = {
  '\u0049': '\u0131'
};


/**
 * The keysets using US keyboard layouts.
 *
 * @type {!Array.<string>}
 */
util.KEYSETS_USE_US = [
  'array',
  'cangjie',
  'dayi',
  'jp_us',
  'pinyin-zh-CN',
  'pinyin-zh-TW',
  'quick',
  't13n',
  'wubi',
  'zhuyin.us',
  'ko.set2.us',
  'ko.set390.us',
  'ko.set3final.us',
  'ko.set3sun.us',
  'ko.romaja.us',
  'ko.ahn.us',
  'ko.set2y.us',
  'ko.set3yet.us',
  'ko.set32.us'
];


/**
 * The keysets that have en switcher key.
 *
 * @type {!Array.<string>}
 */
util.KEYSETS_HAVE_EN_SWTICHER = [
  // When other keysets that use us add the enswitcher key,
  // should move them to this array.
  'array',
  'cangjie',
  'dayi',
  'pinyin-zh-CN',
  'pinyin-zh-TW',
  'quick',
  'wubi',
  'zhuyin',
  'zhuyin.us'
];


/**
 * The keysets that can switch with US keyboard layouts.
 *
 * @type {!Array.<string>}
 */
util.KEYSETS_SWITCH_WITH_US = [
  'zhuyin',
  'ko.set2',
  'ko.set390',
  'ko.set3final',
  'ko.set3sun',
  'ko.romaja',
  'ko.ahn',
  'ko.set2y',
  'ko.set3yet',
  'ko.set32'
];


/**
 * The keysets that have compact keyset.
 *
 * @type {!Array.<string>}
 */
util.KEYSETS_HAVE_COMPACT = [
  'ca',
  'ca-eng',
  'de',
  'dk',
  'fi',
  'fr',
  'gb-extd',
  'ie',
  'is',
  'nl',
  'no',
  'pinyin-zh-CN',
  'se',
  'us',
  'zhuyin'
];


/**
 * A regular expression for the end of a sentence.
 *
 * @private {!RegExp}
 */
util.END_SENTENCE_REGEX_ = /[\.\?!] +$/;


/**
 * The regex of characters support dead key.
 *
 * @type {!RegExp}
 * @private
 */
util.REGEX_CHARACTER_SUPPORT_DEADKEY_ =
    /^[a-zA-ZæÆœŒΑΕΗΙΟΥΩαεηιυοωϒ]+$/;


/**
 * The regex of characters supported in language module.
 *
 * @type {!RegExp}
 */
util.REGEX_LANGUAGE_MODEL_CHARACTERS =
    /(?=[^\u00d7\u00f7])[a-z\-\'\u00c0-\u017F]/i;


/**
 * Splits a value to pieces according to the weights.
 *
 * @param {!Array.<number>} weightArray The weight array.
 * @param {number} totalValue The total value.
 * @return {!Array.<number>} The splitted values.
 */
util.splitValue = function(weightArray, totalValue) {
  if (weightArray.length == 0) {
    return [];
  }

  if (weightArray.length == 1) {
    return [totalValue];
  }

  var totalWeight = 0;
  for (var i = 0; i < weightArray.length; i++) {
    totalWeight += weightArray[i];
  }
  var tmp = totalValue / totalWeight;
  var values = [];
  var totalFlooredValue = 0;
  var diffs = [];
  for (var i = 0; i < weightArray.length; i++) {
    var result = weightArray[i] * tmp;
    values.push(result);
    diffs.push(result - Math.floor(result));
    totalFlooredValue += Math.floor(result);
  }
  var diff = totalValue - totalFlooredValue;

  // Distributes the rest pixels to values who lose most.
  for (var i = 0; i < diff; i++) {
    var max = 0;
    var index = 0;
    for (var j = 0; j < diffs.length; j++) {
      if (diffs[j] > max) {
        max = diffs[j];
        index = j;
      }
    }
    values[index] += 1;
    diffs[index] = 0;
  }
  for (var i = 0; i < values.length; i++) {
    values[i] = Math.floor(values[i]);
  }
  return values;
};


/**
 * Gets the value of a property.
 *
 * @param {Element} elem The element.
 * @param {string} property The property name.
 * @return {number} The value.
 */
util.getPropertyValue = function(elem, property) {
  var value = goog.style.getComputedStyle(elem, property);
  if (value) {
    return parseInt(value.replace('px', ''), 10);
  }
  return 0;
};


/**
 * To upper case.
 *
 * @param {string} character The character.
 * @return {string} The uppercase of the character.
 */
util.toUpper = function(character) {
  var upper = util.CASE_LOWER_TO_UPPER_MAPPING_[character];
  if (upper) {
    return upper;
  }
  return character.toUpperCase();
};


/**
 * To lower case.
 *
 * @param {string} character The character.
 * @return {string} The lower case of the character.
 */
util.toLower = function(character) {
  var lower = util.CASE_UPPER_TO_LOWER_MAPPING_[character];
  if (lower) {
    return lower;
  }
  return character.toLowerCase();
};


/**
 * Is this character trigger commit.
 *
 * @param {string} character The character.
 * @return {boolean} True to trigger commit.
 */
util.isCommitCharacter = function(character) {
  if (util.DISPLAY_MAPPING[character] ||
      util.REGEX_LANGUAGE_MODEL_CHARACTERS.test(
          character)) {
    return false;
  }

  return true;
};


/**
 * Some unicode character can't be shown in the web page, use a replacement
 *     instead.
 *
 * @param {string} invisibleCharacter The character can't be shown.
 * @return {string} The replacement.
 */
util.getVisibleCharacter = function(invisibleCharacter) {
  var map = util.DISPLAY_MAPPING;
  if (map[invisibleCharacter]) {
    return map[invisibleCharacter];
  }
  // For non-spacing marks (e.g. \u05b1), ChromeOS cannot display it correctly
  // until there is a character before it to combine with.
  if (/[\u0591-\u05cf]/.test(invisibleCharacter)) {
    return '\u00a0' + invisibleCharacter;
  }
  return invisibleCharacter;
};


/**
 * Whether this is a letter key.
 *
 * @param {!Array.<string>} characters The characters.
 * @return {boolean} True if this is a letter key.
 */
util.isLetterKey = function(characters) {
  if (characters[1] == util.toUpper(
      characters[0]) || characters[1] == util.
          toLower(characters[0])) {
    return true;
  }
  return false;
};


/**
 * True if this character supports dead key combination.
 *
 * @param {string} character The character.
 * @return {boolean} True if supports the dead key combination.
 */
util.supportDeadKey = function(character) {
  return util.REGEX_CHARACTER_SUPPORT_DEADKEY_.
      test(character);
};


/**
 * True if we need to do the auto-capitalize.
 *
 * @param {string} text .
 * @return {boolean} .
 */
util.needAutoCap = function(text) {
  if (goog.string.isEmptyOrWhitespace(text)) {
    return false;
  } else {
    return util.END_SENTENCE_REGEX_.test(text);
  }
};


/**
 * Returns the configuration file name from the keyboard code.
 *
 * @param {string} keyboardCode The keyboard code.
 * @return {string} The config file name which contains the keyset.
 */
util.getConfigName = function(keyboardCode) {
  // Strips out all the suffixes in the keyboard code.
  return keyboardCode.replace(/\..*$/, '');
};
});  // goog.scope