KeyStylesSet.java revision ed3bac91f242850c6d1833a5f8981b9cc208c5dd
10b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka/* 28632bff2d5a8e1160989008dea6eff4b94b065ddTadashi G. Takaoka * Copyright (C) 2010 The Android Open Source Project 30b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * 40b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); you may not 50b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * use this file except in compliance with the License. You may obtain a copy of 60b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * the License at 70b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * 80b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 90b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * 100b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 110b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 120b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 130b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * License for the specific language governing permissions and limitations under 140b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka * the License. 150b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka */ 160b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 1772934bd5967d0127f71fd4d66158b18b4e6ceefeTadashi G. Takaokapackage com.android.inputmethod.keyboard.internal; 180b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 190b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaokaimport android.content.res.TypedArray; 200b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaokaimport android.util.Log; 210b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 224e1dab8cfaad891fe041ed8d71893186c05cef71Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 23c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaokaimport com.android.inputmethod.latin.R; 244e1dab8cfaad891fe041ed8d71893186c05cef71Tadashi G. Takaokaimport com.android.inputmethod.latin.XmlParseUtils; 25c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaoka 26406a54f41c3e2bb90bedefb6ff80d7b874242f83Tadashi G. Takaokaimport org.xmlpull.v1.XmlPullParser; 274665463ccd4880c2392d26baa784c5d28de986ccTadashi G. Takaokaimport org.xmlpull.v1.XmlPullParserException; 28406a54f41c3e2bb90bedefb6ff80d7b874242f83Tadashi G. Takaoka 290b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaokaimport java.util.HashMap; 300b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 310b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaokapublic class KeyStyles { 32e54a4005d569cddbf8610dfd3e9afaec540fa060Tadashi G. Takaoka private static final String TAG = KeyStyles.class.getSimpleName(); 339b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka private static final boolean DEBUG = false; 340b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 350b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka private final HashMap<String, DeclaredKeyStyle> mStyles = 360b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka new HashMap<String, DeclaredKeyStyle>(); 370b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle(); 380b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 390b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka public interface KeyStyle { 4038d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka public String[] getStringArray(TypedArray a, int index); 4138d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka public String getString(TypedArray a, int index); 420b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka public int getInt(TypedArray a, int index, int defaultValue); 4317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka public int getFlag(TypedArray a, int index); 440b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 450b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 4617f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka static class EmptyKeyStyle implements KeyStyle { 475a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 4838d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka public String[] getStringArray(TypedArray a, int index) { 4917f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return KeyStyles.parseStringArray(a, index); 509b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka } 519b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka 529b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka @Override 5338d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka public String getString(TypedArray a, int index) { 5438d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka return a.getString(index); 550b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 560b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 575a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 580b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka public int getInt(TypedArray a, int index, int defaultValue) { 590b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka return a.getInt(index, defaultValue); 600b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 610b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 625a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 6317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka public int getFlag(TypedArray a, int index) { 6417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return a.getInt(index, 0); 659b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka } 660b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 670b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 6817f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka static class DeclaredKeyStyle implements KeyStyle { 6917f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka private final HashMap<Integer, Object> mStyleAttributes = new HashMap<Integer, Object>(); 700b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 710b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka @Override 7238d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka public String[] getStringArray(TypedArray a, int index) { 7317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (a.hasValue(index)) { 7417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return parseStringArray(a, index); 7517f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 7617f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return (String[])mStyleAttributes.get(index); 779b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka } 789b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka 799b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka @Override 8038d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka public String getString(TypedArray a, int index) { 8117f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (a.hasValue(index)) { 8217f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return a.getString(index); 8317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 8417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return (String)mStyleAttributes.get(index); 850b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 860b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 870b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka @Override 889b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka public int getInt(TypedArray a, int index, int defaultValue) { 8917f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (a.hasValue(index)) { 9017f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return a.getInt(index, defaultValue); 9117f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 9217f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka final Integer styleValue = (Integer)mStyleAttributes.get(index); 9317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return styleValue != null ? styleValue : defaultValue; 940b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 950b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 960b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka @Override 9717f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka public int getFlag(TypedArray a, int index) { 9817f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka final int value = a.getInt(index, 0); 9917f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka final Integer styleValue = (Integer)mStyleAttributes.get(index); 10017f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return (styleValue != null ? styleValue : 0) | value; 1010b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1020b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 10317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka void readKeyAttributes(TypedArray keyAttr) { 1040b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka // TODO: Currently not all Key attributes can be declared as style. 105ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka readString(keyAttr, R.styleable.Keyboard_Key_code); 106ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka readString(keyAttr, R.styleable.Keyboard_Key_altCode); 10738d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka readString(keyAttr, R.styleable.Keyboard_Key_keyLabel); 10838d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka readString(keyAttr, R.styleable.Keyboard_Key_keyOutputText); 10938d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka readString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel); 11038d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); 11115c99e9f1a7776b95325d36cf9e38b6d674e483bTadashi G. Takaoka readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys); 11213d5f6605be6a6e8d9e5dde5b204dc050a862550Tadashi G. Takaoka readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags); 113c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaoka readInt(keyAttr, R.styleable.Keyboard_Key_keyIcon); 11442fcb2de641c4cd5d57f34889c8752401e35dcc8Tadashi G. Takaoka readInt(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled); 115c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaoka readInt(keyAttr, R.styleable.Keyboard_Key_keyIconPreview); 1169d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn); 1177918ed016960908700582e47322e52d74c328cc7Tadashi G. Takaoka readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType); 11813d5f6605be6a6e8d9e5dde5b204dc050a862550Tadashi G. Takaoka readFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags); 1190b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1200b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 12138d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka private void readString(TypedArray a, int index) { 12217f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (a.hasValue(index)) { 12317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka mStyleAttributes.put(index, a.getString(index)); 12417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 1250b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1260b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 1279b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka private void readInt(TypedArray a, int index) { 12817f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (a.hasValue(index)) { 12917f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka mStyleAttributes.put(index, a.getInt(index, 0)); 13017f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 1310b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1320b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 1330b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka private void readFlag(TypedArray a, int index) { 13417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka final Integer value = (Integer)mStyleAttributes.get(index); 13517f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (a.hasValue(index)) { 13617f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka mStyleAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0)); 13717f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 1380b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1390b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 14038d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka private void readStringArray(TypedArray a, int index) { 14138d6a18821794dc733760b55fd2a896626f784e2Tadashi G. Takaoka final String[] value = parseStringArray(a, index); 14217f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (value != null) { 14317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka mStyleAttributes.put(index, value); 14417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 14517f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 14617f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka 14717f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka void addParentStyleAttributes(DeclaredKeyStyle parentStyle) { 14817f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka mStyleAttributes.putAll(parentStyle.mStyleAttributes); 1490b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 15017f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 1510b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 15217f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka static String[] parseStringArray(TypedArray a, int index) { 15317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (a.hasValue(index)) { 15417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return KeySpecParser.parseCsvString( 15517f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka a.getString(index), a.getResources(), R.string.english_ime_name); 1560b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 15717f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka return null; 1580b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1590b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 1609b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka public void parseKeyStyleAttributes(TypedArray keyStyleAttr, TypedArray keyAttrs, 1614665463ccd4880c2392d26baa784c5d28de986ccTadashi G. Takaoka XmlPullParser parser) throws XmlPullParserException { 16209430720d5eee7e2de405d600059bd39aa1d3e49Tadashi G. Takaoka final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName); 16317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (DEBUG) { 16417f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka Log.d(TAG, String.format("<%s styleName=%s />", 16517f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka Keyboard.Builder.TAG_KEY_STYLE, styleName)); 16605bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka if (mStyles.containsKey(styleName)) { 16705bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka Log.d(TAG, "key-style " + styleName + " is overridden at " 16805bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka + parser.getPositionDescription()); 16905bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka } 17017f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 1710b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 1720b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka final DeclaredKeyStyle style = new DeclaredKeyStyle(); 1739b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) { 17409430720d5eee7e2de405d600059bd39aa1d3e49Tadashi G. Takaoka final String parentStyle = keyStyleAttr.getString( 1755a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka R.styleable.Keyboard_KeyStyle_parentStyle); 1760b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka final DeclaredKeyStyle parent = mStyles.get(parentStyle); 17717f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka if (parent == null) { 1784665463ccd4880c2392d26baa784c5d28de986ccTadashi G. Takaoka throw new XmlParseUtils.ParseException( 1794665463ccd4880c2392d26baa784c5d28de986ccTadashi G. Takaoka "Unknown parentStyle " + parentStyle, parser); 18017f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka } 18117f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka style.addParentStyleAttributes(parent); 1820b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 18317f53103ee0d0360d8f93f6bac41ef37a0021402Tadashi G. Takaoka style.readKeyAttributes(keyAttrs); 1840b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka mStyles.put(styleName, style); 1850b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1860b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 1870b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka public KeyStyle getKeyStyle(String styleName) { 1880b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka return mStyles.get(styleName); 1890b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1900b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka 1918fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka public static KeyStyle getEmptyKeyStyle() { 1920b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka return EMPTY_KEY_STYLE; 1930b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka } 1940b60f831922b9341a7ef5d2eba87aa91580d371fTadashi G. Takaoka} 195