blob: 5c0183311602070029dc6e07ec9c523d72491162 [file] [log] [blame]
// 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