Home | History | Annotate | Download | only in ibus
      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 
     14 namespace chromeos {
     15 
     16 namespace {
     17 // The default entry number of a page in IBusLookupTable.
     18 const int kDefaultPageSize = 9;
     19 const char kShowWindowAtCompositionKey[] = "show_window_at_composition";
     20 }  // namespace
     21 
     22 void 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 
     70 bool 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
    185 IBusLookupTable::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 
    193 IBusLookupTable::~IBusLookupTable() {
    194 }
    195 
    196 bool 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 
    218 void 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 
    228 IBusLookupTable::Entry::Entry() {
    229 }
    230 
    231 IBusLookupTable::Entry::~Entry() {
    232 }
    233 
    234 }  // namespace chromeos
    235