pdf/plugin_impl/document_impl.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: document_impl.cpp
00003  */
00004 
00005 /*
00006  * This file is part of uds-plugin-pdf.
00007  *
00008  * uds-plugin-pdf is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * uds-plugin-pdf is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #include <cassert>
00028 #include "document_impl.h"
00029 #include "view_impl.h"
00030 #include "collection_impl.h"
00031 #include "string_impl.h"
00032 #include "search_criteria_impl.h"
00033 #include "pdf_anchor.h"
00034 
00035 namespace pdf
00036 {
00037 
00038 utils::ObjectTable<PluginDocImpl> PluginDocImpl::g_instances_table;
00039 
00040 PluginDocImpl::PluginDocImpl()
00041 {
00042     // IPluginUnknown
00043     query_interface = query_interface_impl;
00044     release         = release_impl;
00045 
00046     // IPluginDocument
00047     open        = open_impl;
00048     is_open     = is_open_impl;
00049     close       = close_impl;
00050     create_view = create_view_impl;
00051 
00052     // IPluginDocNavigator
00053     get_initial_anchor      = get_initial_anchor_impl;
00054     get_object_from_anchor  = get_object_from_anchor_impl;
00055     get_type_of_object      = get_type_of_object_impl;
00056     get_words_from_range    = get_words_from_range_impl;
00057     get_text_from_range     = get_text_from_range_impl;
00058     is_anchor_in_current_document = is_anchor_in_current_document_impl;
00059     get_file_name_from_anchor = get_file_name_from_anchor_impl;
00060     get_file_position_from_anchor = get_file_position_from_anchor_impl;
00061     compare_anchor_location = compare_anchor_location_impl;
00062 
00063     // IPluginDocAttributes
00064     get_attribute = get_attribute_impl;
00065     set_attribute = set_attribute_impl;
00066 
00067     // IPluginEventBroadcaster
00068     add_event_receiver      = add_event_receiver_impl;
00069     remove_event_receiver   = remove_event_receiver_impl;
00070 
00071     // IPluginDocHyperlink
00072     is_hyperlink                = is_hyperlink_impl;
00073     get_target_from_hyperlink   = get_target_from_hyperlink_impl;
00074     get_hyperlinks_in_range     = get_hyperlinks_in_range_impl;
00075 
00076     // IPluginDocDictionary
00077     is_dictionary = is_dictionary_impl;
00078 
00079     // IPluginDocMarker
00080     get_supported_marker_types  = get_supported_marker_types_impl;
00081     request_marker_trees        = request_marker_trees_impl;
00082     has_toc                     = has_toc_impl;
00083 
00084     // IPluginDocSearch
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     // Initialize interface and object table.
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<IPluginDocMarker>(this);
00099     g_instances_table.add_interface<IPluginDocSearch>(this);
00100 
00101     // connect to the search ready signal
00102     doc_ctrl.sig_search_results_ready.add_slot(this
00103         , &PluginDocImpl::on_search_results_ready);
00104 
00105     // Initialize document attributes map.
00106     init_doc_attributes();
00107 }
00108 
00109 void PluginDocImpl::init_doc_attributes()
00110 {
00111     doc_attr_map.insert(std::make_pair("fixed-page", "yes"));
00112 }
00113 
00114 PluginDocImpl::~PluginDocImpl()
00115 {
00116     g_instances_table.remove(this);
00117 }
00118 
00119 unsigned int PluginDocImpl::get_page_count()
00120 {
00121     return doc_ctrl.page_count();
00122 }
00123 
00124 unsigned int PluginDocImpl::get_page_number(const std::string & anchor)
00125 {
00126     return doc_ctrl.get_page_number_of_anchor(anchor);
00127 }
00128 
00129 bool PluginDocImpl::get_anchor_of_page(const unsigned int page_number,
00130                                        std::string & anchor)
00131 {
00132     return doc_ctrl.get_anchor_of_page(page_number, anchor);
00133 }
00134 
00135 bool PluginDocImpl::get_prev_page(std::string & anchor)
00136 {
00137     return doc_ctrl.get_prev_page_anchor(anchor);
00138 }
00139 
00140 bool PluginDocImpl::get_next_page(std::string & anchor)
00141 {
00142     return doc_ctrl.get_next_page_anchor(anchor);
00143 }
00144 
00145 bool PluginDocImpl::get_original_size(const std::string &anchor,
00146                                       unsigned int &width,
00147                                       unsigned int &height)
00148 {
00149     double w, h;
00150     if (doc_ctrl.get_page_crop_width(anchor, w) &&
00151         doc_ctrl.get_page_crop_height(anchor, h))
00152     {
00153         width = static_cast<unsigned int>(w);
00154         height = static_cast<unsigned int>(h);
00155         return true;
00156     }
00157 
00158     return false;
00159 }
00160 
00161 bool PluginDocImpl::get_content_area(const std::string &anchor,
00162                                      RenderArea &area)
00163 {
00164     return doc_ctrl.get_page_content_area(anchor, area);
00165 }
00166 
00167 PluginRotationDegree PluginDocImpl::get_page_original_rotation(const std::string &anchor)
00168 {
00169     return doc_ctrl.get_page_original_rotation(anchor);
00170 }
00171 
00172 PluginStatus 
00173 PluginDocImpl::query_interface_impl(IPluginUnknown    *thiz,
00174                                     const UDSString   *id, 
00175                                     void              **ptr )
00176 {
00177     // check object. 
00178     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00179 
00180     // check interface.
00181     if (g_instances_table.query_interface(instance, id->get_buffer(id), ptr))
00182     {
00183         return PLUGIN_OK;
00184     }
00185     return PLUGIN_FAIL;
00186 }
00187 
00188 int 
00189 PluginDocImpl::release_impl(IPluginUnknown  *thiz )
00190 {
00191     // Check object. 
00192     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00193     instance->release_signal.safe_broadcast(instance);
00194     return 0;
00195 }
00196 
00197 
00198 PluginStatus
00199 PluginDocImpl::open_impl(IPluginUnknown    *thiz, 
00200                          const UDSString   *path)
00201 {
00202     // Check object. 
00203     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00204     
00205     // Check document has been opened or not.
00206     if (instance->doc_ctrl.is_open())
00207     {
00208         return PLUGIN_ERROR_OPEN_FILE;
00209     }
00210 
00211     return instance->doc_ctrl.open(path->get_buffer(path));
00212 }
00213 
00214 PluginBool
00215 PluginDocImpl::is_open_impl(IPluginUnknown    *thiz)
00216 {
00217     // Check object. 
00218     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00219     
00220     // Check document has been opened or not.
00221     if (instance->doc_ctrl.is_open())
00222     {
00223         return PLUGIN_TRUE;
00224     }
00225     return PLUGIN_FALSE;
00226 }
00227 
00228 PluginStatus
00229 PluginDocImpl::close_impl(IPluginUnknown   *thiz)
00230 {
00231     // Check object. 
00232     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00233     
00234     // Check document has been opened or not.
00235     if (!instance->doc_ctrl.is_open())
00236     {
00237         return PLUGIN_FAIL;
00238     }
00239 
00240     if (instance->doc_ctrl.close())
00241     {
00242         return PLUGIN_OK;
00243     }
00244 
00245     return PLUGIN_FAIL;
00246 }
00247 
00248 IPluginUnknown *
00249 PluginDocImpl::create_view_impl(IPluginUnknown   *thiz)
00250 {
00251     // Check object. 
00252     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00253     
00254     // Create the view.
00255     ViewPtr ptr = new PluginViewImpl(instance);
00256     if (ptr == 0)
00257     {
00258         return 0;
00259     }
00260 
00261     instance->views.push_back(ptr);
00262     ptr->release_signal.add_slot(instance, &PluginDocImpl::on_view_released);
00263     return static_cast<IPluginUnknown *>(ptr);
00264 }
00265 
00266 PluginStatus 
00267 PluginDocImpl::get_initial_anchor_impl(IPluginUnknown   *thiz,
00268                                        UDSString        *anchor)
00269 {
00270     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00271 
00272     // Use first page as the initial anchor.
00273     std::string temp;
00274     if (instance->doc_ctrl.get_anchor_of_page(1, temp))
00275     {
00276         anchor->assign(anchor, temp.c_str());
00277         return PLUGIN_OK;
00278     }
00279 
00280     return PLUGIN_FAIL;
00281 }
00282 
00283 PluginStatus 
00284 PluginDocImpl::get_object_from_anchor_impl(IPluginUnknown  *thiz,
00285                                            const UDSString *anchor, 
00286                                            PluginRange     *range)
00287 {
00288     PluginStatus ret = PLUGIN_FAIL;
00289     if (thiz && anchor && range)
00290     {
00291         PDFAnchor param(anchor->get_buffer(anchor));
00292         PluginDocImpl *instance = g_instances_table.get_object(thiz);
00293         PDFAnchor start, end;
00294 
00295         if (param.page_num > 0)
00296         {
00297             PagePtr page = instance->doc_ctrl.get_page(param.page_num);
00298             if (param.link_idx != -1)
00299             {
00300                 // check 'anchor' is a link?
00301                 // get the range anchor of this link.
00302                 if (page && page->get_range_param_by_link_index(param.link_idx, start, end))
00303                 {
00304                     ret = PLUGIN_OK;
00305                 }
00306             }
00307 
00308             if (param.word_num != -1)
00309             {
00310                 // check the word
00311                 if (page && page->get_range_param_by_word_index(param.word_num, start, end))
00312                 {
00313                     ret = PLUGIN_OK;
00314                 }
00315             }
00316         }
00317 
00318         if (param.toc_idx != -1)
00319         {
00320             // check 'anchor' is a TOC item?
00321             start.toc_idx = param.toc_idx;
00322             end.toc_idx = param.toc_idx;
00323             ret = PLUGIN_OK;
00324         }
00325 
00326         if (ret == PLUGIN_OK)
00327         {
00328             range->start_anchor->assign(range->start_anchor, 
00329                                         start.get_string().c_str());
00330             range->end_anchor->assign(range->end_anchor, 
00331                                       end.get_string().c_str());
00332         }
00333     }
00334 
00335     return ret;
00336 }
00337 
00338 PluginStatus
00339 PluginDocImpl::get_file_name_from_anchor_impl(IPluginUnknown    *thiz,
00340                                             const UDSString   *anchor,
00341                                             UDSString         *file_name)
00342 {
00343     PDFAnchor anchor_param(anchor->get_buffer(anchor));
00344 
00345     gchar * name = 0;
00346     if (!anchor_param.file_name.empty())
00347     {
00348         // if anchor contains the file name, use it
00349         name = g_path_get_basename(anchor_param.file_name.c_str());
00350     }
00351     else
00352     {
00353         // otherwise, use the file name stored in controller
00354         PluginDocImpl *instance = g_instances_table.get_object(thiz);
00355         name = g_path_get_basename(instance->doc_ctrl.name().c_str());
00356     }
00357 
00358     if (name != 0)
00359     {
00360         file_name->assign(file_name, name);
00361         return PLUGIN_OK;
00362     }
00363 
00364     return PLUGIN_FAIL;
00365 }
00366 
00367 PluginStatus 
00368 PluginDocImpl::get_file_position_from_anchor_impl(IPluginUnknown    *thiz,
00369                                                 const UDSString   *anchor,
00370                                                 signed long long  *position)
00371 {
00372     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00373     PDFAnchor anchor_param(anchor->get_buffer(anchor));
00374 
00375     if (anchor_param.page_num <= 0 ||
00376         anchor_param.page_num > static_cast<int>(instance->get_page_count()))
00377     {
00378         return PLUGIN_FAIL;
00379     }
00380 
00381     *position = anchor_param.page_num;
00382     return PLUGIN_OK;
00383 }
00384 
00385 PluginBool 
00386 PluginDocImpl::is_anchor_in_current_document_impl(IPluginUnknown    *thiz,
00387                                                   const UDSString   *anchor)
00388 {
00389     // check object. 
00390     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00391     
00392     if (instance->doc_ctrl.is_anchor_in_current_document(
00393         anchor->get_buffer(anchor)))
00394     {
00395         return PLUGIN_TRUE;
00396     }
00397 
00398     return PLUGIN_FALSE;
00399 }
00400 
00401 int 
00402 PluginDocImpl::compare_anchor_location_impl(IPluginUnknown   *thiz,
00403                                             const UDSString  *anchor_a,
00404                                             const UDSString  *anchor_b)
00405 {
00406     // check object. 
00407     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00408     
00409     return instance->doc_ctrl.compare_anchor(anchor_a->get_buffer(anchor_a)
00410         , anchor_a->get_buffer(anchor_b));
00411 }
00412     
00413 PluginStatus 
00414 PluginDocImpl::add_event_receiver_impl(IPluginUnknown     *thiz,
00415                                        const PluginEvent  plugin_event,
00416                                        EventFunc          callback,
00417                                        void               *user_data,
00418                                        unsigned long      *handler_id)
00419 {
00420     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00421     if (handler_id == 0)
00422     {
00423         return PLUGIN_FAIL;
00424     }
00425 
00426     *handler_id = instance->listeners.add_listener(plugin_event, callback, user_data);
00427 
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     if (range)
00448     {
00449         // Parse the range.
00450         UDSString * start = range->start_anchor;
00451         PDFAnchor start_param(start->get_buffer(start));
00452 
00453         UDSString * end = range->end_anchor;
00454         PDFAnchor end_param(end->get_buffer(end));
00455 
00456         // Check the startpos and endpos is in the same link 
00457         // in the same page. If yes, it's a sensible hyperlink.
00458         if ( (start_param.page_num != 0) && (end_param.page_num != 0)
00459              && (start_param.page_num == end_param.page_num)
00460              && (start_param.link_idx != -1) && (end_param.link_idx != -1)
00461              && (start_param.link_idx == end_param.link_idx))
00462         {
00463             return PLUGIN_TRUE;
00464         }
00465         else if ((start_param.toc_idx = -1) && (end_param.toc_idx = -1)
00466                 && (start_param.toc_idx == end_param.toc_idx))
00467         {
00468             return PLUGIN_TRUE;
00469         }
00470     }
00471 
00472     return PLUGIN_FALSE;
00473 }
00474 
00475 PluginStatus 
00476 PluginDocImpl::get_target_from_hyperlink_impl(IPluginUnknown     *thiz,
00477                                               const PluginRange  *range, 
00478                                               UDSString          *anchor )
00479 {
00480     if (is_hyperlink_impl(thiz, range))
00481     {
00482         // Parse the range.
00483         UDSString * start = range->start_anchor;
00484         PDFAnchor param(start->get_buffer(start));
00485 
00486         // Get the anchor of link's destination.
00487         PluginDocImpl *instance = g_instances_table.get_object(thiz);
00488 
00489         std::string temp;
00490         if (param.link_idx != -1)
00491         {
00492             PagePtr page = instance->doc_ctrl.get_page(param.page_num);
00493 
00494             if (page && page->get_goto_anchor_of_link(param.link_idx, temp))
00495             {
00496                 anchor->assign(anchor, temp.c_str());
00497                 return PLUGIN_OK;
00498             }
00499         }
00500         else if (param.toc_idx != -1)
00501         {
00502             PDFToc * toc = instance->doc_ctrl.get_toc();
00503             if (toc && toc->get_goto_anchor_of_toc_idx(param.toc_idx, temp))
00504             {
00505                 anchor->assign(anchor, temp.c_str());
00506                 return PLUGIN_OK;
00507             }
00508         }
00509     }
00510 
00511     return PLUGIN_FAIL;
00512 }
00513 
00514 // The dummy document supports table of content.
00515 IPluginUnknown* 
00516 PluginDocImpl::get_supported_marker_types_impl(IPluginUnknown  *thiz )
00517 {
00518     // Not necessary to check thiz in this kind of document.
00519     // But if the document has different marker type it should
00520     // make necessary check.
00521 
00522     typedef PDFCollection<PluginMarkerType*> PDFMarkers;
00523     PDFMarkers *markers = new PDFMarkers;
00524     PluginMarkerType type = MARKER_TOC;
00525     markers->add(&type);
00526 
00527     PluginCollectionImpl *collection = new PluginCollectionImpl;
00528     
00529     collection->set_data(markers);
00530 
00531     // It's not necessary to connect the release signal, because
00532     // the collection can remove the memory itself. Document object
00533     // does not store any pointer data in the collection here.
00534     return static_cast<IPluginUnknown *>(collection);
00535 }
00536 
00537 void PluginDocImpl::add_toc_children(MarkerEntry * parent, 
00538                                      TocItem * item, 
00539                                      const unsigned int uds_private_size)
00540 {
00541     while (item)
00542     {
00543         // Create a MarkerEntryImpl using item.
00544         MarkerEntry * entry = generate_marker_entry(item->anchor, 
00545                                                     item->text, 
00546                                                     item->goto_anchor,
00547                                                     uds_private_size);
00548 
00549         // Insert this item as the last child of the parent.
00550         if (!parent->first_child)
00551         {
00552             parent->first_child = entry;
00553         }
00554         else
00555         {
00556             MarkerEntry* cur = parent->first_child;
00557             while (cur->sibling)
00558             {
00559                 cur = cur->sibling;
00560             }
00561             cur->sibling = entry;
00562         }
00563     
00564         // Recursively descend over children
00565         if (item->first_child)
00566         {
00567             add_toc_children(entry, item->first_child, uds_private_size);
00568         }
00569 
00570         // Next sibling
00571         item = item->sibling;
00572     }
00573 }
00574 
00575 // Steps to generate marker tree.
00576 // 1. Generate the collection object.
00577 // 2. Add marker tree nodes into the collection.
00578 // 3. Invoke the callback function registered in listeners list.
00579 // TODO. Remove the marker tree copy, use the MarkerEntryImpl in PDFToc instead.
00580 PluginStatus 
00581 PluginDocImpl::request_marker_trees_impl(IPluginUnknown     *thiz, 
00582                                          const unsigned int uds_private_size )
00583 {
00584     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00585 
00586     // Retrieve TOC.
00587     PDFToc * toc = instance->doc_ctrl.get_toc();
00588     TocItem * item = toc->get_toc();
00589 
00590     if (item == 0)
00591     {
00592         return PLUGIN_FAIL;
00593     }
00594 
00595     MarkerEntry* root_toc = marker_entry_new(uds_private_size);
00596     root_toc->type = MARKER_TOC;
00597 
00598     // Allocate collection object.
00599     typedef PDFCollection<MarkerEntry *> PDFMarkerEntries;
00600     PDFMarkerEntries * entries = new PDFMarkerEntries;
00601 
00602     // Traverse the whole TOC tree.
00603     instance->add_toc_children(root_toc, item, uds_private_size);
00604     entries->add(root_toc->first_child);
00605 
00606     // Root node is useless, disconnect it with other nodes
00607     root_toc->sibling = 0;
00608     root_toc->first_child = 0;
00609     marker_entry_free_recursive(root_toc);
00610 
00611     // Return the results as collection.
00612     PluginCollectionImpl *collection = new PluginCollectionImpl;
00613     collection->set_data(entries);
00614 
00615     // Notify all listeners.
00616     PluginEventAttrs event_data;
00617     event_data.marker_ready.result = static_cast<IPluginUnknown *>(collection);
00618     instance->listeners.broadcast(thiz, EVENT_MARKER_READY, &event_data);
00619 
00620     return PLUGIN_OK;
00621 }
00622 
00623 PluginBool PluginDocImpl::has_toc_impl(IPluginUnknown *thiz)
00624 {
00625     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00626     if (instance->doc_ctrl.get_toc()->has_toc())
00627     {
00628         return PLUGIN_TRUE;
00629     }
00630     return PLUGIN_FALSE;
00631 }
00632 
00633 MarkerEntry * PluginDocImpl::generate_marker_entry(const std::string & anchor,
00634                                                    const std::string & text,
00635                                                    const std::string & goto_anchor,
00636                                                    const unsigned int uds_private_size)
00637 {
00638     MarkerEntry * entry = marker_entry_new(uds_private_size);
00639     if (entry == 0)
00640     {
00641         return 0;
00642     }
00643 
00644     entry->type         = MARKER_TOC;
00645     entry->anchor       = new StringImpl(anchor);
00646     entry->text         = new StringImpl(text);
00647     entry->sibling      = 0;
00648     entry->first_child  = 0;
00649     entry->uds_private_size = uds_private_size;
00650 
00651     return entry;
00652 }
00653 
00654 IPluginUnknown* PluginDocImpl::get_hyperlinks_in_range_impl(IPluginUnknown      *thiz,
00655                                                             const PluginRange   *range)
00656 {
00657     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00658 
00659     // Parse the range.
00660     UDSString * start = range->start_anchor;
00661     if (start == 0)
00662     {
00663         // start anchor cannot be NULL
00664         return 0;
00665     }
00666     UDSString * end = range->end_anchor;
00667     std::string start_anchor = start->get_buffer(start);
00668     std::string end_anchor;
00669     if (end != 0)
00670     {
00671         end_anchor = end->get_buffer(end);
00672     }
00673     else
00674     {
00675         PDFAnchor param;
00676         param.set_end_anchor();
00677         end_anchor = param.get_string();
00678     }
00679 
00680     PDFCollectionBase * results = instance->doc_ctrl.get_hyperlinks_from_range(
00681         start_anchor, end_anchor);
00682 
00683     if (results == 0)
00684     {
00685         // no hyperlinks
00686         return 0;
00687     }
00688 
00689     if (results->get_count() <= 0)
00690     {
00691         // no hyperlinks
00692         delete results;
00693         results = 0;
00694         return 0;
00695     }
00696 
00697     // Return the results as collection.
00698     PluginCollectionImpl *collection = new PluginCollectionImpl;
00699     collection->set_data(results);
00700     return collection;
00701 }
00702 
00703 // Don't support search criteria.
00704 IPluginUnknown *
00705 PluginDocImpl::create_search_criteria_impl(IPluginUnknown  *thiz )
00706 {
00707     return new PluginSearchCriteria;
00708 }
00709 
00710 PluginStatus
00711 PluginDocImpl::request_search_next_impl(IPluginUnknown      *thiz,
00712                                         IPluginUnknown      *criteria,
00713                                         const UDSString     *from_anchor,
00714                                         const unsigned int  search_id)
00715 {
00716     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00717     if (instance->doc_ctrl.search_next(
00718         (static_cast<PluginSearchCriteria*>(criteria))->get_data()
00719         , from_anchor->get_buffer(from_anchor)
00720         , search_id))
00721     {
00722         return PLUGIN_OK;
00723     }
00724     return PLUGIN_FAIL;
00725 }
00726 
00727 PluginStatus
00728 PluginDocImpl::request_search_all_impl(IPluginUnknown *thiz,
00729                                        IPluginUnknown *criteria,
00730                                        const unsigned int  search_id)
00731 {
00732     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00733     if (instance->doc_ctrl.search_all(
00734         (static_cast<PluginSearchCriteria*>(criteria))->get_data()
00735         , search_id))
00736     {
00737         return PLUGIN_OK;
00738     }
00739     return PLUGIN_FAIL;
00740 }
00741 
00742 PluginStatus
00743 PluginDocImpl::abort_search_impl(IPluginUnknown *thiz,
00744                                  const unsigned int  search_id)
00745 {
00746     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00747     if (instance->doc_ctrl.abort_search(search_id))
00748     {
00749         return PLUGIN_OK;
00750     }
00751     return PLUGIN_FAIL;
00752 }
00753 
00754 void PluginDocImpl::on_view_released(ViewPtr view)
00755 {
00756     ViewsIter iter = std::find(views.begin(), views.end(), view);
00757     if (iter != views.end())
00758     {
00759         delete *iter;
00760         views.erase(iter);
00761     }
00762 }
00763 
00764 void PluginDocImpl::on_search_results_ready(SearchResult res
00765                                             , PDFRangeCollection* coll
00766                                             , unsigned int search_id)
00767 {
00768     PluginEventAttrs attrs;
00769 
00770     PluginCollectionImpl * results = new PluginCollectionImpl;
00771     results->set_data(coll);
00772 
00773     attrs.search_end.result = static_cast<IPluginUnknown *>(results);
00774     attrs.search_end.search_id = search_id;
00775 
00776     PluginEvent e = EVENT_SEARCH_END;
00777     if (res == RES_ABORTED)
00778     {
00779         e = EVENT_SEARCH_ABORTED;
00780     }
00781 
00782     listeners.broadcast(this, e, &attrs);
00783 }
00784 
00785 // Define pdf attribute.
00786 PluginStatus
00787 PluginDocImpl::get_attribute_impl(IPluginUnknown     *thiz,
00788                                   const UDSString    *key, 
00789                                   UDSString          *value )
00790 {
00791     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00792 
00793     // Check whether the key exists or not.
00794     if (instance->doc_attr_map.find(key->get_buffer(key)) 
00795             == instance->doc_attr_map.end())
00796     {
00797         return PLUGIN_NOT_SUPPORTED;
00798     }
00799 
00800     value->assign(value, instance->doc_attr_map[key->get_buffer(key)].c_str());
00801     return PLUGIN_OK;
00802 }
00803 
00804 PluginStatus 
00805 PluginDocImpl::set_attribute_impl(IPluginUnknown     *thiz,
00806                                   const UDSString    *key,
00807                                   const UDSString    *value )
00808 {
00809     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00810 
00811     const char* key_cstr = key->get_buffer(key);
00812     DocAttrMapIter iter = instance->doc_attr_map.find(key_cstr);
00813     if (iter == instance->doc_attr_map.end())
00814     {
00815         return PLUGIN_NOT_SUPPORTED;
00816     }
00817 
00818     iter->second = value->get_buffer(value);
00819     return PLUGIN_OK;
00820 }
00821 
00822 PluginBool 
00823 PluginDocImpl::is_dictionary_impl(IPluginUnknown  *thiz )
00824 {
00825     return PLUGIN_FALSE;
00826 }
00827 
00828 PluginDocObjectType 
00829 PluginDocImpl::get_type_of_object_impl(IPluginUnknown      *thiz,
00830                                        const PluginRange   *range)
00831 {
00832     // Parse the range.
00833     UDSString * start = range->start_anchor;
00834     PDFAnchor start_param(start->get_buffer(start));
00835 
00836     UDSString * end = range->end_anchor;
00837     PDFAnchor end_param(end->get_buffer(end));
00838 
00839     // TODO. Use bit to indicate a type, instead of integer
00840     if (start_param.link_idx >= 0 && end_param.link_idx >= 0)
00841     {
00842         if (start_param.word_num >= 0 && end_param.word_num >= 0)
00843         {
00844             return PLUGIN_DOC_OBJECT_TEXT_HYPERLINK;
00845         }
00846         return PLUGIN_DOC_OBJECT_HYPERLINK;
00847     }
00848 
00849     if (start_param.toc_idx >= 0 && end_param.toc_idx >= 0)
00850     {
00851         return PLUGIN_DOC_OBJECT_HYPERLINK;
00852     }
00853 
00854     if (start_param.word_num >= 0 && end_param.word_num >= 0)
00855     {
00856         return PLUGIN_DOC_OBJECT_TEXT;
00857     }
00858 
00859     return PLUGIN_DOC_OBJECT_NONE;
00860 }
00861 
00862 PluginStatus 
00863 PluginDocImpl::get_words_from_range_impl(IPluginUnknown     *thiz, 
00864                                          const PluginRange  *chars_range, 
00865                                          PluginRange        *words_range )
00866 {
00867     return PLUGIN_NOT_SUPPORTED;
00868 }
00869 
00870 PluginStatus 
00871 PluginDocImpl::get_text_from_range_impl(IPluginUnknown        *thiz, 
00872                                         const PluginRange     *range, 
00873                                         UDSString             *result)
00874 {
00875     // Parse the range.
00876     UDSString * start = range->start_anchor;
00877     PDFAnchor start_param(start->get_buffer(start));
00878 
00879     UDSString * end = range->end_anchor;
00880     PDFAnchor end_param(end->get_buffer(end));
00881     
00882     // Make the PDFAnchors valid for getting text.
00883     start_param.validate_for_getting_text();
00884     end_param.validate_for_getting_text();
00885 
00886     std::string result_str;
00887 
00888     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00889     if (instance->doc_ctrl.get_text_from_range(start_param, end_param, result_str))
00890     {
00891         result->assign(result, result_str.c_str());
00892         return PLUGIN_OK;
00893     }
00894 
00895     return PLUGIN_FAIL;
00896 }
00897 
00898 }   // namespace pdf
00899 
Generated by  doxygen 1.6.2-20100208