- add sources.
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / ibus / ibus_text.cc
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_text.h"
6
7 #include "base/logging.h"
8 #include "base/values.h"
9 #include "chromeos/dbus/ibus/ibus_object.h"
10 #include "dbus/message.h"
11
12 namespace chromeos {
13
14 namespace {
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";
20
21 struct IBusAttribute {
22   IBusAttribute() : type(0), value(0), start_index(0), end_index(0) {}
23   uint32 type;
24   uint32 value;
25   uint32 start_index;
26   uint32 end_index;
27 };
28
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())
34     return false;
35
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.";
42     return false;
43   }
44   return true;
45 }
46
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();
57 }
58
59 }  // namespace
60
61 void AppendIBusText(const IBusText& ibus_text, dbus::MessageWriter* writer) {
62   IBusObjectWriter ibus_text_writer("IBusText", "sv", writer);
63
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());
68   }
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());
74   }
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());
80   }
81   ibus_text_writer.CloseHeader();
82
83   ibus_text_writer.AppendString(ibus_text.text());
84
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);
91
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);
101   }
102
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;
108     attribute.value = 0;
109     attribute.start_index = selection_attributes[i].start_index;
110     attribute.end_index = selection_attributes[i].end_index;
111     AppendIBusAttribute(&attribute_array_writer, attribute);
112   }
113
114   // Close all writers.
115   ibus_attr_list_writer.CloseContainer(&attribute_array_writer);
116   ibus_attr_list_writer.CloseAll();
117   ibus_text_writer.CloseAll();
118 }
119
120 void CHROMEOS_EXPORT AppendStringAsIBusText(const std::string& text,
121                                             dbus::MessageWriter* writer) {
122   IBusText ibus_text;
123   ibus_text.set_text(text);
124   AppendIBusText(ibus_text, writer);
125 }
126
127 bool PopIBusText(dbus::MessageReader* reader, IBusText* ibus_text) {
128   IBusObjectReader ibus_text_reader("IBusText", reader);
129
130   if (!ibus_text_reader.Init())
131     return false;
132
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);
139   }
140
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);
147   }
148
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);
155   }
156
157   std::string text;
158   if (!ibus_text_reader.PopString(&text)) {
159     LOG(ERROR) << "Invalid variant structure[IBusText]: "
160                << "1st argument should be string.";
161     return false;
162   }
163
164   ibus_text->set_text(text);
165
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.";
171     return false;
172   }
173
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.";
178     return false;
179   }
180
181   std::vector<IBusText::UnderlineAttribute>* underline_attributes =
182       ibus_text->mutable_underline_attributes();
183
184   std::vector<IBusText::SelectionAttribute>* selection_attributes =
185       ibus_text->mutable_selection_attributes();
186
187   while (attribute_array_reader.HasMoreData()) {
188     IBusAttribute attribute;
189     if (!PopIBusAttribute(&attribute_array_reader, &attribute))
190       return false;
191
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);
204     } else {
205       DVLOG(1) << "Chrome does not support background attribute.";
206     }
207   }
208
209   return true;
210 }
211
212 bool CHROMEOS_EXPORT PopStringFromIBusText(dbus::MessageReader* reader,
213                                            std::string* text) {
214   IBusText ibus_text;
215   if (!PopIBusText(reader, &ibus_text))
216     return false;
217   *text = ibus_text.text();
218   return true;
219 }
220
221 ///////////////////////////////////////////////////////////////////////////////
222 // IBusText
223 IBusText::IBusText()
224     : text_("") {
225 }
226
227 IBusText::~IBusText() {
228 }
229
230 void IBusText::CopyFrom(const IBusText& obj) {
231   text_ = obj.text();
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();
237 }
238
239 }  // namespace chromeos