1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chromeos/dbus/ibus/ibus_lookup_table.h" 6 7#include <string> 8#include "base/logging.h" 9#include "base/values.h" 10#include "chromeos/dbus/ibus/ibus_object.h" 11#include "chromeos/dbus/ibus/ibus_text.h" 12#include "dbus/message.h" 13 14namespace chromeos { 15 16namespace { 17// The default entry number of a page in IBusLookupTable. 18const int kDefaultPageSize = 9; 19const char kShowWindowAtCompositionKey[] = "show_window_at_composition"; 20} // namespace 21 22void AppendIBusLookupTable(const IBusLookupTable& table, 23 dbus::MessageWriter* writer) { 24 IBusObjectWriter ibus_lookup_table_writer("IBusLookupTable", 25 "uubbiavav", 26 writer); 27 scoped_ptr<base::Value> show_position( 28 base::Value::CreateBooleanValue(table.show_window_at_composition())); 29 ibus_lookup_table_writer.AddAttachment(kShowWindowAtCompositionKey, 30 *show_position.get()); 31 ibus_lookup_table_writer.CloseHeader(); 32 ibus_lookup_table_writer.AppendUint32(table.page_size()); 33 ibus_lookup_table_writer.AppendUint32(table.cursor_position()); 34 ibus_lookup_table_writer.AppendBool(table.is_cursor_visible()); 35 ibus_lookup_table_writer.AppendBool(false); // Not used in Chrome. 36 ibus_lookup_table_writer.AppendInt32(static_cast<int32>(table.orientation())); 37 38 const std::vector<IBusLookupTable::Entry>& candidates = table.candidates(); 39 dbus::MessageWriter text_writer(NULL); 40 ibus_lookup_table_writer.OpenArray("v", &text_writer); 41 bool have_labels = false; 42 for (size_t i = 0; i < candidates.size(); ++i) { 43 // Write candidate string as IBusText. 44 IBusText text; 45 text.set_text(candidates[i].value); 46 text.set_annotation(candidates[i].annotation); 47 text.set_description_title(candidates[i].description_title); 48 text.set_description_body(candidates[i].description_body); 49 AppendIBusText(text, &text_writer); 50 if (!candidates[i].label.empty()) 51 have_labels = true; 52 } 53 ibus_lookup_table_writer.CloseContainer(&text_writer); 54 55 dbus::MessageWriter label_writer(NULL); 56 ibus_lookup_table_writer.OpenArray("v", &label_writer); 57 58 // If there are not any labels, don't append labels. 59 if (have_labels) { 60 for (size_t i = 0; i < candidates.size(); ++i) { 61 // Write label string as IBusText. 62 AppendStringAsIBusText(candidates[i].label, &label_writer); 63 } 64 } 65 ibus_lookup_table_writer.CloseContainer(&label_writer); 66 67 ibus_lookup_table_writer.CloseAll(); 68} 69 70bool PopIBusLookupTable(dbus::MessageReader* reader, IBusLookupTable* table) { 71 IBusObjectReader ibus_object_reader("IBusLookupTable", reader); 72 73 if (!ibus_object_reader.Init()) 74 return false; 75 76 const base::Value* value = 77 ibus_object_reader.GetAttachment(kShowWindowAtCompositionKey); 78 if (value) { 79 bool show_window_at_composition; 80 if (value->GetAsBoolean(&show_window_at_composition)) 81 table->set_show_window_at_composition(show_window_at_composition); 82 } 83 84 uint32 page_size = 0; 85 if (!ibus_object_reader.PopUint32(&page_size)) { 86 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 87 << "1st argument should be uint32."; 88 return false; 89 } 90 table->set_page_size(page_size); 91 92 uint32 cursor_position = 0; 93 if (!ibus_object_reader.PopUint32(&cursor_position)) { 94 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 95 << "2nd argument should be uint32."; 96 return false; 97 } 98 table->set_cursor_position(cursor_position); 99 100 bool cursor_visible = true; 101 if (!ibus_object_reader.PopBool(&cursor_visible)) { 102 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 103 << "3rd argument should be boolean."; 104 return false; 105 } 106 table->set_is_cursor_visible(cursor_visible); 107 108 bool unused_round_value = true; 109 if (!ibus_object_reader.PopBool(&unused_round_value)) { 110 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 111 << "4th argument should be boolean."; 112 return false; 113 } 114 115 int32 orientation = 0; 116 if (!ibus_object_reader.PopInt32(&orientation)) { 117 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 118 << "5th argument should be int32."; 119 return false; 120 } 121 122 // Original IBus spec has third orientation IBUS_ORIENTATION_SYSTEM but it 123 // was not supported in Chrome OS. Thus do not cast from integer to enum. 124 table->set_orientation( 125 orientation == IBusLookupTable::HORIZONTAL ? 126 IBusLookupTable::HORIZONTAL : IBusLookupTable::VERTICAL); 127 128 dbus::MessageReader text_array_reader(NULL); 129 if (!ibus_object_reader.PopArray(&text_array_reader)) { 130 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 131 << "6th argument should be array."; 132 return false; 133 } 134 135 std::vector<IBusLookupTable::Entry>* candidates = table->mutable_candidates(); 136 while (text_array_reader.HasMoreData()) { 137 IBusText candidate_text; 138 // The attributes in IBusText are not used in Chrome. 139 if (!PopIBusText(&text_array_reader, &candidate_text)) { 140 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 141 << "6th argument should be array of IBusText."; 142 return false; 143 } 144 IBusLookupTable::Entry entry; 145 entry.value = candidate_text.text(); 146 entry.annotation = candidate_text.annotation(); 147 entry.description_title = candidate_text.description_title(); 148 entry.description_body = candidate_text.description_body(); 149 candidates->push_back(entry); 150 } 151 152 dbus::MessageReader label_array_reader(NULL); 153 if (!ibus_object_reader.PopArray(&label_array_reader)) { 154 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 155 << "7th argument should be array."; 156 return false; 157 } 158 159 if (!label_array_reader.HasMoreData()) { 160 return true; 161 } 162 163 for (size_t i = 0; i < candidates->size(); ++i) { 164 if (!label_array_reader.HasMoreData()) { 165 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 166 << "The number of label entry does not match with candidate " 167 << "text. Same length or no label entry can be accepted."; 168 return false; 169 } 170 171 std::string label_text; 172 // The attributes in IBusText are not used in Chrome. 173 if (!PopStringFromIBusText(&label_array_reader, &label_text)) { 174 LOG(ERROR) << "Invalid variant structure[IBusLookupTable]: " 175 << "7th argument should be array of IBusText."; 176 return false; 177 } 178 (*candidates)[i].label = label_text; 179 } 180 return true; 181} 182 183/////////////////////////////////////////////////////////////////////////////// 184// IBusLookupTable 185IBusLookupTable::IBusLookupTable() 186 : page_size_(kDefaultPageSize), 187 cursor_position_(0), 188 is_cursor_visible_(true), 189 orientation_(HORIZONTAL), 190 show_window_at_composition_(false) { 191} 192 193IBusLookupTable::~IBusLookupTable() { 194} 195 196bool IBusLookupTable::IsEqual(const IBusLookupTable& table) const { 197 if (page_size_ != table.page_size_ || 198 cursor_position_ != table.cursor_position_ || 199 is_cursor_visible_ != table.is_cursor_visible_ || 200 orientation_ != table.orientation_ || 201 show_window_at_composition_ != table.show_window_at_composition_ || 202 candidates_.size() != table.candidates_.size()) 203 return false; 204 205 for (size_t i = 0; i < candidates_.size(); ++i) { 206 const Entry& left = candidates_[i]; 207 const Entry& right = table.candidates_[i]; 208 if (left.value != right.value || 209 left.label != right.label || 210 left.annotation != right.annotation || 211 left.description_title != right.description_title || 212 left.description_body != right.description_body) 213 return false; 214 } 215 return true; 216} 217 218void IBusLookupTable::CopyFrom(const IBusLookupTable& table) { 219 page_size_ = table.page_size_; 220 cursor_position_ = table.cursor_position_; 221 is_cursor_visible_ = table.is_cursor_visible_; 222 orientation_ = table.orientation_; 223 show_window_at_composition_ = table.show_window_at_composition_; 224 candidates_.clear(); 225 candidates_ = table.candidates_; 226} 227 228IBusLookupTable::Entry::Entry() { 229} 230 231IBusLookupTable::Entry::~Entry() { 232} 233 234} // namespace chromeos 235