00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <cassert>
00028 #include "log.h"
00029 #include "document_impl.h"
00030 #include "view_impl.h"
00031 #include "collection_impl.h"
00032 #include "string_impl.h"
00033 #include "search_criteria_impl.h"
00034 #include "text_base_types.h"
00035
00036 namespace text
00037 {
00038
00039 utils::ObjectTable<PluginDocImpl> PluginDocImpl::g_instances_table;
00040
00041 PluginDocImpl::PluginDocImpl()
00042 : controller(0)
00043 {
00044
00045 query_interface = query_interface_impl;
00046 release = release_impl;
00047
00048
00049 open = open_impl;
00050 is_open = is_open_impl;
00051 close = close_impl;
00052 create_view = create_view_impl;
00053
00054
00055 get_initial_anchor = get_initial_anchor_impl;
00056 get_object_from_anchor = get_object_from_anchor_impl;
00057 get_type_of_object = get_type_of_object_impl;
00058 get_words_from_range = get_words_from_range_impl;
00059 get_text_from_range = get_text_from_range_impl;
00060 is_anchor_in_current_document = is_anchor_in_current_document_impl;
00061 get_file_name_from_anchor = get_file_name_from_anchor_impl;
00062 get_file_position_from_anchor = get_file_position_from_anchor_impl;
00063 compare_anchor_location = compare_anchor_location_impl;
00064
00065
00066 get_attribute = get_attribute_impl;
00067 set_attribute = set_attribute_impl;
00068
00069
00070 add_event_receiver = add_event_receiver_impl;
00071 remove_event_receiver = remove_event_receiver_impl;
00072
00073
00074 is_hyperlink = is_hyperlink_impl;
00075 get_target_from_hyperlink = get_target_from_hyperlink_impl;
00076
00077
00078 is_dictionary = is_dictionary_impl;
00079
00080
00081
00082 request_marker_trees = request_marker_trees_impl;
00083
00084
00085 create_search_criteria = create_search_criteria_impl;
00086 request_search_next = request_search_next_impl;
00087 request_search_all = request_search_all_impl;
00088 abort_search = abort_search_impl;
00089
00090
00091 g_instances_table.add_interface<IPluginUnknown>(this);
00092 g_instances_table.add_interface<IPluginDocument>(this);
00093 g_instances_table.add_interface<IPluginDocNavigator>(this);
00094 g_instances_table.add_interface<IPluginDocAttributes>(this);
00095 g_instances_table.add_interface<IPluginEventBroadcaster>(this);
00096 g_instances_table.add_interface<IPluginDocHyperlink>(this);
00097 g_instances_table.add_interface<IPluginDocDictionary>(this);
00098 g_instances_table.add_interface<IPluginDocSearch>(this);
00099
00100 document.search_done_signal.add_slot(this,
00101 &PluginDocImpl::on_search_done);
00102
00103
00104 init_doc_attributes();
00105 }
00106
00107 void PluginDocImpl::init_doc_attributes()
00108 {
00109 doc_attr_map.insert(std::make_pair("fixed-page", "no"));
00110 doc_attr_map.insert(std::make_pair("reflowable", "yes"));
00111 }
00112
00113 PluginDocImpl::~PluginDocImpl()
00114 {
00115 g_instances_table.remove(this);
00116 }
00117
00118 PluginStatus
00119 PluginDocImpl::query_interface_impl(IPluginUnknown *thiz,
00120 const UDSString *id,
00121 void **ptr )
00122 {
00123
00124 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00125
00126
00127 if (g_instances_table.query_interface(instance, id->get_buffer(id), ptr))
00128 {
00129 return PLUGIN_OK;
00130 }
00131 return PLUGIN_FAIL;
00132 }
00133
00134 int
00135 PluginDocImpl::release_impl(IPluginUnknown *thiz )
00136 {
00137
00138 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00139 instance->release_signal.safe_broadcast(instance);
00140 return 0;
00141 }
00142
00143
00144 PluginStatus
00145 PluginDocImpl::open_impl(IPluginUnknown *thiz,
00146 const UDSString *path)
00147 {
00148
00149 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00150
00151
00152 assert(!instance->document.is_open());
00153
00154
00155 return instance->document.open(path->get_buffer(path));
00156 }
00157
00158 PluginBool
00159 PluginDocImpl::is_open_impl(IPluginUnknown *thiz)
00160 {
00161
00162 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00163
00164
00165 if (instance->document.is_open())
00166 {
00167 return PLUGIN_TRUE;
00168 }
00169 return PLUGIN_FALSE;
00170 }
00171
00172 PluginStatus
00173 PluginDocImpl::close_impl(IPluginUnknown *thiz)
00174 {
00175
00176 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00177
00178
00179 assert(instance->document.is_open());
00180
00181
00182 instance->controller->stop();
00183 instance->document.close();
00184 return PLUGIN_OK;
00185 }
00186
00187 IPluginUnknown *
00188 PluginDocImpl::create_view_impl(IPluginUnknown *thiz)
00189 {
00190
00191 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00192
00193
00194
00195
00196 ViewPtr ptr = new PluginViewImpl(instance);
00197 assert(ptr);
00198
00199 if (instance->controller == 0)
00200 {
00201 instance->controller = ptr->get_text_controller();
00202 instance->controller->start();
00203 }
00204
00205 return static_cast<IPluginUnknown *>(ptr);
00206 }
00207
00208 PluginStatus
00209 PluginDocImpl::get_initial_anchor_impl(IPluginUnknown *thiz,
00210 UDSString *anchor)
00211 {
00212
00213 Position pos;
00214 std::string temp = pos.to_string();
00215 anchor->assign(anchor, temp.c_str());
00216 return PLUGIN_OK;
00217 }
00218
00219 PluginStatus
00220 PluginDocImpl::get_object_from_anchor_impl(IPluginUnknown *thiz,
00221 const UDSString *anchor,
00222 PluginRange *range)
00223 {
00224 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00225
00226 Position object_start_pos, object_end_pos;
00227 Position anchor_pos(anchor->get_buffer(anchor));
00228
00229 if (!instance->document.get_word_from_anchor(anchor_pos,
00230 object_start_pos,
00231 object_end_pos))
00232 {
00233 return PLUGIN_FAIL;
00234 }
00235
00236 range->start_anchor->assign(range->start_anchor,
00237 object_start_pos.to_string().c_str());
00238 range->end_anchor->assign(range->end_anchor,
00239 object_end_pos.to_string().c_str());
00240
00241 return PLUGIN_OK;
00242 }
00243
00244 PluginDocObjectType
00245 PluginDocImpl::get_type_of_object_impl(IPluginUnknown *thiz,
00246 const PluginRange *range)
00247 {
00248 return PLUGIN_DOC_OBJECT_TEXT;
00249 }
00250
00251 PluginStatus
00252 PluginDocImpl::get_words_from_range_impl(IPluginUnknown *thiz,
00253 const PluginRange *char_range,
00254 PluginRange *words_range )
00255 {
00256 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00257
00258 Position char_start_pos(char_range->start_anchor->get_buffer(char_range->start_anchor));
00259 Position char_end_pos(char_range->end_anchor->get_buffer(char_range->end_anchor));
00260
00261 if (char_start_pos > char_end_pos)
00262 {
00263 ERRORPRINTF("Invalid range, range_start = %s, range_end = %s",
00264 char_start_pos.to_string().c_str(),
00265 char_end_pos.to_string().c_str());
00266 return PLUGIN_FAIL;
00267 }
00268
00269 Position words_start, words_end;
00270 if (!instance->document.get_words_from_range(char_start_pos, char_end_pos, words_start, words_end))
00271 {
00272 return PLUGIN_FAIL;
00273 }
00274
00275 words_range->start_anchor->assign(words_range->start_anchor, words_start.to_string().c_str());
00276 words_range->end_anchor->assign(words_range->end_anchor, words_end.to_string().c_str());
00277 return PLUGIN_OK;
00278 }
00279
00280 PluginStatus
00281 PluginDocImpl::get_text_from_range_impl(IPluginUnknown *thiz,
00282 const PluginRange *range,
00283 UDSString *result)
00284 {
00285
00286 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00287
00288 Position text_start_pos(range->start_anchor->get_buffer(range->start_anchor));
00289 Position text_end_pos(range->end_anchor->get_buffer(range->end_anchor));
00290
00291 if (text_start_pos > text_end_pos)
00292 {
00293 ERRORPRINTF("Invalid range, range_start = %s, range_end = %s",
00294 text_start_pos.to_string().c_str(),
00295 text_end_pos.to_string().c_str());
00296 return PLUGIN_FAIL;
00297 }
00298
00299 std::string result_string;
00300 instance->document.get_text_from_range(result_string, text_start_pos, text_end_pos);
00301 result->assign(result, result_string.c_str());
00302
00303 return PLUGIN_OK;
00304 }
00305
00306 PluginBool
00307 PluginDocImpl::is_anchor_in_current_document_impl(IPluginUnknown *thiz,
00308 const UDSString *anchor)
00309 {
00310
00311 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00312 Position pos(anchor->get_buffer(anchor));
00313 if (instance->document.has_anchor(pos))
00314 {
00315 return PLUGIN_TRUE;
00316 }
00317 return PLUGIN_FALSE;
00318 }
00319
00320 PluginStatus
00321 PluginDocImpl::get_file_name_from_anchor_impl(IPluginUnknown *thiz,
00322 const UDSString *anchor,
00323 UDSString *file_name )
00324 {
00325
00326 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00327
00328
00329 const std::string& file_path = instance->document.get_path();
00330
00331
00332 char* basename = g_path_get_basename(file_path.c_str());
00333 file_name->assign(file_name, basename);
00334 g_free(basename);
00335
00336 return PLUGIN_OK;
00337 }
00338
00339 PluginStatus
00340 PluginDocImpl::get_file_position_from_anchor_impl(IPluginUnknown *thiz,
00341 const UDSString *anchor,
00342 signed long long *position )
00343 {
00344 Position internal_anchor(anchor->get_buffer(anchor));
00345 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00346
00347 size_t pos;
00348 if (instance->document.get_file_pos_from_anchor(pos, internal_anchor))
00349 {
00350 *position = pos;
00351 return PLUGIN_OK;
00352 }
00353
00354 return PLUGIN_FAIL;
00355 }
00356
00357 int
00358 PluginDocImpl::compare_anchor_location_impl(IPluginUnknown *thiz,
00359 const UDSString *anchor_a,
00360 const UDSString *anchor_b)
00361 {
00362
00363 Position a(anchor_a->get_buffer(anchor_a));
00364 Position b(anchor_b->get_buffer(anchor_b));
00365
00366 if (a > b)
00367 {
00368 return 1;
00369 }
00370 else if (a == b)
00371 {
00372 return 0;
00373 }
00374 else
00375 {
00376 return -1;
00377 }
00378 }
00379
00380
00381 PluginStatus
00382 PluginDocImpl::get_attribute_impl(IPluginUnknown *thiz,
00383 const UDSString *key,
00384 UDSString *value )
00385 {
00386 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00387
00388
00389 if (instance->doc_attr_map.find(key->get_buffer(key))
00390 == instance->doc_attr_map.end())
00391 {
00392 return PLUGIN_NOT_SUPPORTED;
00393 }
00394
00395 value->assign(value, instance->doc_attr_map[key->get_buffer(key)].c_str());
00396 return PLUGIN_OK;
00397 }
00398
00399 PluginStatus
00400 PluginDocImpl::set_attribute_impl(IPluginUnknown *thiz,
00401 const UDSString *key,
00402 const UDSString *value )
00403 {
00404 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00405
00406 const char* key_cstr = key->get_buffer(key);
00407 DocAttrMapIter iter = instance->doc_attr_map.find(key_cstr);
00408 if (iter == instance->doc_attr_map.end())
00409 {
00410 return PLUGIN_NOT_SUPPORTED;
00411 }
00412
00413 iter->second = value->get_buffer(value);
00414 return PLUGIN_OK;
00415 }
00416
00417 PluginStatus
00418 PluginDocImpl::add_event_receiver_impl(IPluginUnknown *thiz,
00419 const PluginEvent plugin_event,
00420 EventFunc callback,
00421 void *user_data,
00422 unsigned long *handler_id)
00423 {
00424 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00425 assert(handler_id);
00426 *handler_id =
00427 instance->listeners.add_listener(plugin_event, callback, user_data);
00428 return PLUGIN_OK;
00429 }
00430
00431 PluginStatus
00432 PluginDocImpl::remove_event_receiver_impl(IPluginUnknown *thiz,
00433 unsigned long handler_id )
00434 {
00435 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00436 if (instance->listeners.remove_listener(handler_id))
00437 {
00438 return PLUGIN_OK;
00439 }
00440 return PLUGIN_FAIL;
00441 }
00442
00443 PluginBool
00444 PluginDocImpl::is_hyperlink_impl(IPluginUnknown *thiz,
00445 const PluginRange *range )
00446 {
00447
00448 return PLUGIN_FALSE;
00449 }
00450
00451 PluginStatus
00452 PluginDocImpl::get_target_from_hyperlink_impl(IPluginUnknown *thiz,
00453 const PluginRange *range,
00454 UDSString *anchor )
00455 {
00456 return PLUGIN_FAIL;
00457 }
00458
00459 PluginBool
00460 PluginDocImpl::is_dictionary_impl(IPluginUnknown *thiz )
00461 {
00462 return PLUGIN_FALSE;
00463 }
00464
00465
00466 IPluginUnknown*
00467 PluginDocImpl::get_supported_marker_types_impl(IPluginUnknown *thiz )
00468 {
00469 return 0;
00470 }
00471
00472
00473 PluginStatus
00474 PluginDocImpl::request_marker_trees_impl(IPluginUnknown *thiz,
00475 const unsigned int uds_private_size )
00476 {
00477 return PLUGIN_FAIL;
00478 }
00479
00480 IPluginUnknown *
00481 PluginDocImpl::create_search_criteria_impl(IPluginUnknown *thiz )
00482 {
00483 return new PluginSearchCriteria;
00484 }
00485
00486
00487 PluginStatus
00488 PluginDocImpl::request_search_next_impl(IPluginUnknown *thiz,
00489 IPluginUnknown *criteria,
00490 const UDSString *from_anchor,
00491 const unsigned int search_id)
00492 {
00493 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00494
00495
00496 instance->document.set_aborting_search_task_id(0);
00497
00498 PluginSearchCriteria* search_criteria =
00499 static_cast<PluginSearchCriteria *>(criteria);
00500 SearchContext& sc = search_criteria->get_search_context();
00501 sc.search_id = search_id;
00502 sc.search_type = SEARCH_NEXT;
00503 sc.from = Position(from_anchor->get_buffer(from_anchor));
00504 instance->controller->search(&sc);
00505 return PLUGIN_OK;
00506 }
00507
00508
00509 PluginStatus
00510 PluginDocImpl::request_search_all_impl(IPluginUnknown *thiz,
00511 IPluginUnknown *criteria,
00512 const unsigned int search_id)
00513 {
00514 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00515
00516
00517 instance->document.set_aborting_search_task_id(0);
00518
00519 PluginSearchCriteria* search_criteria =
00520 static_cast<PluginSearchCriteria *>(criteria);
00521 SearchContext& sc = search_criteria->get_search_context();
00522 sc.search_id = search_id;
00523 sc.search_type = SEARCH_ALL;
00524 instance->controller->search(&sc);
00525 return PLUGIN_OK;
00526 }
00527
00528 PluginStatus PluginDocImpl::abort_search_impl(
00529 IPluginUnknown *thiz,
00530 const unsigned int search_id)
00531 {
00532 PluginDocImpl *instance = g_instances_table.get_object(thiz);
00533 instance->document.set_aborting_search_task_id(search_id);
00534 return PLUGIN_OK;
00535 }
00536
00537 void PluginDocImpl::on_search_done(const std::vector<Range>& result,
00538 const SearchContext* sc)
00539 {
00540 PluginCollectionImpl *coll_p = new PluginCollectionImpl();
00541 coll_p->create<RangeImpl *>();
00542 std::vector<RangeImpl *>& data = coll_p->take_data_ref<RangeImpl *>();
00543
00544 for (unsigned int i=0; i<result.size(); i++)
00545 {
00546 data.push_back(new RangeImpl(result[i]));
00547 }
00548
00549 PluginEventAttrs attrs;
00550 attrs.search_end.search_id = sc->search_id;
00551 attrs.search_end.result = coll_p;
00552 listeners.broadcast(this, EVENT_SEARCH_END, &attrs);
00553 }
00554
00555 }
00556