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.
5 #include "chromeos/dbus/ibus/ibus_text.h"
7 #include "base/logging.h"
8 #include "base/values.h"
9 #include "chromeos/dbus/ibus/ibus_object.h"
10 #include "dbus/message.h"
15 const uint32 kAttributeUnderline = 1; // Indicates underline attribute.
16 const uint32 kAttributeSelection = 2; // Indicates background attribute.
17 const char kAnnotationKey[] = "annotation";
18 const char kDescriptionTitleKey[] = "description_title";
19 const char kDescriptionBodyKey[] = "description_body";
21 struct IBusAttribute {
22 IBusAttribute() : type(0), value(0), start_index(0), end_index(0) {}
29 // Pops a IBusAttribute from |reader|.
30 // Returns false if an error occurs.
31 bool PopIBusAttribute(dbus::MessageReader* reader, IBusAttribute* attribute) {
32 IBusObjectReader ibus_object_reader("IBusAttribute", reader);
33 if (!ibus_object_reader.Init())
36 if (!ibus_object_reader.PopUint32(&attribute->type) ||
37 !ibus_object_reader.PopUint32(&attribute->value) ||
38 !ibus_object_reader.PopUint32(&attribute->start_index) ||
39 !ibus_object_reader.PopUint32(&attribute->end_index)) {
40 LOG(ERROR) << "Invalid variant structure[IBusAttribute]: "
41 << "IBusAttribute should contain 4 unsigned integers.";
47 // Appends a IBusAttribute into |writer|.
48 void AppendIBusAttribute(dbus::MessageWriter* writer,
49 const IBusAttribute& attribute) {
50 IBusObjectWriter ibus_attribute_writer("IBusAttribute", "uuuu", writer);
51 ibus_attribute_writer.CloseHeader();
52 ibus_attribute_writer.AppendUint32(attribute.type);
53 ibus_attribute_writer.AppendUint32(attribute.value);
54 ibus_attribute_writer.AppendUint32(attribute.start_index);
55 ibus_attribute_writer.AppendUint32(attribute.end_index);
56 ibus_attribute_writer.CloseAll();
61 void AppendIBusText(const IBusText& ibus_text, dbus::MessageWriter* writer) {
62 IBusObjectWriter ibus_text_writer("IBusText", "sv", writer);
64 if (!ibus_text.annotation().empty()) {
65 scoped_ptr<base::Value> annotation(
66 base::Value::CreateStringValue(ibus_text.annotation()));
67 ibus_text_writer.AddAttachment(kAnnotationKey, *annotation.get());
69 if (!ibus_text.description_title().empty()) {
70 scoped_ptr<base::Value> description_title(
71 base::Value::CreateStringValue(ibus_text.description_title()));
72 ibus_text_writer.AddAttachment(kDescriptionTitleKey,
73 *description_title.get());
75 if (!ibus_text.description_body().empty()) {
76 scoped_ptr<base::Value> description_body(
77 base::Value::CreateStringValue(ibus_text.description_body()));
78 ibus_text_writer.AddAttachment(kDescriptionBodyKey,
79 *description_body.get());
81 ibus_text_writer.CloseHeader();
83 ibus_text_writer.AppendString(ibus_text.text());
85 // Start appending IBusAttrList into IBusText
86 IBusObjectWriter ibus_attr_list_writer("IBusAttrList", "av", NULL);
87 ibus_text_writer.AppendIBusObject(&ibus_attr_list_writer);
88 ibus_attr_list_writer.CloseHeader();
89 dbus::MessageWriter attribute_array_writer(NULL);
90 ibus_attr_list_writer.OpenArray("v", &attribute_array_writer);
92 const std::vector<IBusText::UnderlineAttribute>& underline_attributes =
93 ibus_text.underline_attributes();
94 for (size_t i = 0; i < underline_attributes.size(); ++i) {
95 IBusAttribute attribute;
96 attribute.type = kAttributeUnderline;
97 attribute.value = static_cast<uint32>(underline_attributes[i].type);
98 attribute.start_index = underline_attributes[i].start_index;
99 attribute.end_index = underline_attributes[i].end_index;
100 AppendIBusAttribute(&attribute_array_writer, attribute);
103 const std::vector<IBusText::SelectionAttribute>& selection_attributes =
104 ibus_text.selection_attributes();
105 for (size_t i = 0; i < selection_attributes.size(); ++i) {
106 IBusAttribute attribute;
107 attribute.type = kAttributeSelection;
109 attribute.start_index = selection_attributes[i].start_index;
110 attribute.end_index = selection_attributes[i].end_index;
111 AppendIBusAttribute(&attribute_array_writer, attribute);
114 // Close all writers.
115 ibus_attr_list_writer.CloseContainer(&attribute_array_writer);
116 ibus_attr_list_writer.CloseAll();
117 ibus_text_writer.CloseAll();
120 void CHROMEOS_EXPORT AppendStringAsIBusText(const std::string& text,
121 dbus::MessageWriter* writer) {
123 ibus_text.set_text(text);
124 AppendIBusText(ibus_text, writer);
127 bool PopIBusText(dbus::MessageReader* reader, IBusText* ibus_text) {
128 IBusObjectReader ibus_text_reader("IBusText", reader);
130 if (!ibus_text_reader.Init())
133 const base::Value* annotation_value =
134 ibus_text_reader.GetAttachment(kAnnotationKey);
135 if (annotation_value) {
136 std::string annotation;
137 if (annotation_value->GetAsString(&annotation))
138 ibus_text->set_annotation(annotation);
141 const base::Value* description_title_value =
142 ibus_text_reader.GetAttachment(kDescriptionTitleKey);
143 if (description_title_value) {
144 std::string description_title;
145 if (description_title_value->GetAsString(&description_title))
146 ibus_text->set_description_title(description_title);
149 const base::Value* description_body_value =
150 ibus_text_reader.GetAttachment(kDescriptionBodyKey);
151 if (description_body_value) {
152 std::string description_body;
153 if (description_body_value->GetAsString(&description_body))
154 ibus_text->set_description_body(description_body);
158 if (!ibus_text_reader.PopString(&text)) {
159 LOG(ERROR) << "Invalid variant structure[IBusText]: "
160 << "1st argument should be string.";
164 ibus_text->set_text(text);
166 // Start reading IBusAttrList object
167 IBusObjectReader ibus_attr_list_reader("IBusAttrList", NULL);
168 if (!ibus_text_reader.PopIBusObject(&ibus_attr_list_reader)) {
169 LOG(ERROR) << "Invalid variant structure[IBusText]: "
170 << "2nd argument should be IBusAttrList.";
174 dbus::MessageReader attribute_array_reader(NULL);
175 if (!ibus_attr_list_reader.PopArray(&attribute_array_reader)) {
176 LOG(ERROR) << "Invalid variant structure[IBusAttrList]: "
177 << "1st argument should be array of IBusAttribute.";
181 std::vector<IBusText::UnderlineAttribute>* underline_attributes =
182 ibus_text->mutable_underline_attributes();
184 std::vector<IBusText::SelectionAttribute>* selection_attributes =
185 ibus_text->mutable_selection_attributes();
187 while (attribute_array_reader.HasMoreData()) {
188 IBusAttribute attribute;
189 if (!PopIBusAttribute(&attribute_array_reader, &attribute))
192 if (attribute.type == kAttributeUnderline) {
193 IBusText::UnderlineAttribute underline_attribute;
194 underline_attribute.type =
195 static_cast<IBusText::IBusTextUnderlineType>(attribute.value);
196 underline_attribute.start_index = attribute.start_index;
197 underline_attribute.end_index = attribute.end_index;
198 underline_attributes->push_back(underline_attribute);
199 } else if (attribute.type == kAttributeSelection) {
200 IBusText::SelectionAttribute selection_attribute;
201 selection_attribute.start_index = attribute.start_index;
202 selection_attribute.end_index = attribute.end_index;
203 selection_attributes->push_back(selection_attribute);
205 DVLOG(1) << "Chrome does not support background attribute.";
212 bool CHROMEOS_EXPORT PopStringFromIBusText(dbus::MessageReader* reader,
215 if (!PopIBusText(reader, &ibus_text))
217 *text = ibus_text.text();
221 ///////////////////////////////////////////////////////////////////////////////
227 IBusText::~IBusText() {
230 void IBusText::CopyFrom(const IBusText& obj) {
232 annotation_ = obj.annotation();
233 description_title_ = obj.description_title();
234 description_body_ = obj.description_body();
235 underline_attributes_ = obj.underline_attributes();
236 selection_attributes_ = obj.selection_attributes();
239 } // namespace chromeos