#include <text_model.h>
Data Structures | |
struct | Paragraph |
Public Member Functions | |
TextModel () | |
Constructors and destructors. | |
~TextModel () | |
PluginStatus | open (const std::string &path) |
Open specified document with default encoding. | |
PluginStatus | open (const std::string &path, const std::string &encoding) |
Open document with specified encoding. | |
bool | is_open () const |
Check if document is already open. | |
void | close () |
Close document. | |
const std::string & | get_encoding () const |
Get current encoding. | |
const std::string & | get_path () const |
unsigned int | get_paragraph_count () const |
Get number of paragraphs. | |
const std::string * | get_paragraph (unsigned int index) const |
Get 1 paragraph. | |
bool | search (std::vector< Range > &result_ranges, SearchContext *sc) |
Search specified pattern given by search criteria. | |
bool | has_anchor (const Position &pos) |
Check if the document contains the anchor or not. | |
bool | get_file_pos_from_anchor (size_t &file_pos, const Position &pos) |
Get absolute file position from anchor. | |
bool | get_word_from_anchor (const Position &pos, Position &word_start_pos, Position &word_end_pos) |
Get a word from specified document position. | |
bool | get_words_from_range (const Position &range_start, const Position &range_end, Position &words_start, Position &words_end) |
Get the words from range, the range will be extended/shrinked to words boundary. | |
bool | get_text_from_range (std::string &result, const Position &start_pos, const Position &end_pos) |
Get the text between start_pos and end_pos. | |
void | dump () |
Dump the content to disk file. | |
void | set_aborting_search_task_id (unsigned int id) |
Abort specified search task. | |
unsigned int | get_aborting_search_task_id () |
Data Fields | |
utils::Signal< const std::vector< Range > &, const SearchContext * > | search_done_signal |
Signals. |
Definition at line 44 of file text_model.h.
text::TextModel::TextModel | ( | ) |
Constructors and destructors.
Definition at line 44 of file text_model.cpp.
00045 : file_p(0) 00046 , encoding("") 00047 , path() 00048 , b_open(false) 00049 , aborting_search_task_id(0) 00050 , incomplete_line(false) 00051 { 00052 }
text::TextModel::~TextModel | ( | ) |
Definition at line 54 of file text_model.cpp.
References close().
00055 { 00056 if (b_open) 00057 { 00058 close(); 00059 } 00060 }
void text::TextModel::close | ( | ) |
Close document.
Definition at line 111 of file text_model.cpp.
Referenced by open(), and ~TextModel().
00112 { 00113 clear(); 00114 fclose(file_p); 00115 file_p = NULL; 00116 b_open = false; 00117 encoding.clear(); 00118 }
void text::TextModel::dump | ( | ) |
Dump the content to disk file.
Definition at line 647 of file text_model.cpp.
00648 { 00649 // Generate the dump file. 00650 std::string dump_path = path + ".converted"; 00651 FILE* fp = fopen(dump_path.c_str(), "w"); 00652 00653 if (fp != NULL) 00654 { 00655 for (unsigned int i=0; i<doc.size(); i++) 00656 { 00657 fputs(doc[i].text->c_str(), fp); 00658 } 00659 00660 fclose(fp); 00661 } 00662 }
unsigned int text::TextModel::get_aborting_search_task_id | ( | ) | [inline] |
Definition at line 131 of file text_model.h.
Referenced by text::SearchTask::execute().
const std::string& text::TextModel::get_encoding | ( | ) | const [inline] |
Get current encoding.
Definition at line 68 of file text_model.h.
Referenced by text::TextView::TextView().
bool text::TextModel::get_file_pos_from_anchor | ( | size_t & | file_pos, | |
const Position & | pos | |||
) |
Get absolute file position from anchor.
Definition at line 477 of file text_model.cpp.
References text::Position::offset, and text::Position::paragraph.
const std::string* text::TextModel::get_paragraph | ( | unsigned int | index | ) | const [inline] |
Get 1 paragraph.
Definition at line 85 of file text_model.h.
Referenced by text::TextView::calculate_next_page_pos(), text::TextView::calculate_prev_page_pos(), main(), text::TextView::map_doc_pos_to_view_pos(), text::TextView::map_view_pos_to_doc_pos(), text::TextView::render(), and widget_event_handler().
unsigned int text::TextModel::get_paragraph_count | ( | ) | const [inline] |
Get number of paragraphs.
Definition at line 79 of file text_model.h.
Referenced by text::TextView::calculate_next_page_pos(), main(), and text::TextView::map_view_pos_to_doc_pos().
const std::string& text::TextModel::get_path | ( | ) | const [inline] |
Definition at line 73 of file text_model.h.
00074 { 00075 return path; 00076 }
bool text::TextModel::get_text_from_range | ( | std::string & | result, | |
const Position & | start_pos, | |||
const Position & | end_pos | |||
) |
Get the text between start_pos and end_pos.
Definition at line 614 of file text_model.cpp.
References text::Position::offset, and text::Position::paragraph.
00617 { 00618 unsigned int start_paragraph = start_pos.paragraph; 00619 unsigned int end_paragraph = end_pos.paragraph; 00620 00621 for (unsigned int i = start_paragraph; 00622 (i <= end_paragraph) && (i < doc.size()); 00623 i++) 00624 { 00625 if (doc[i].text) 00626 { 00627 const char* start_p = doc[i].text->c_str(); 00628 if (i == start_paragraph) 00629 { 00630 start_p += start_pos.offset; 00631 } 00632 00633 size_t len = doc[i].text->length(); 00634 if (i == end_paragraph) 00635 { 00636 const char* p = doc[i].text->c_str() + end_pos.offset; 00637 len = g_utf8_next_char(p) - start_p; 00638 } 00639 00640 result.append(start_p, len); 00641 } 00642 } 00643 00644 return true; 00645 }
bool text::TextModel::get_word_from_anchor | ( | const Position & | pos, | |
Position & | word_start_pos, | |||
Position & | word_end_pos | |||
) |
Get a word from specified document position.
Definition at line 510 of file text_model.cpp.
References text::Position::offset, and text::Position::paragraph.
Referenced by get_words_from_range().
00513 { 00514 00515 const char* paragraph = doc[pos.paragraph].text->c_str(); 00516 word_start_pos.paragraph = word_end_pos.paragraph = pos.paragraph; 00517 00518 const char* p = paragraph + pos.offset; 00519 00520 // Check if the character at pos is a seperator. 00521 if (is_seperator(p)) 00522 { 00523 // Then there is no word at pos. 00524 word_start_pos.offset = word_end_pos.offset = pos.offset; 00525 return false; 00526 } 00527 00528 // Find the first space before pos. 00529 for (; p > paragraph; p = g_utf8_prev_char(p)) 00530 { 00531 if (is_seperator(p)) 00532 { 00533 p = g_utf8_next_char(p); 00534 break; 00535 } 00536 } 00537 word_start_pos.offset = static_cast<int>(p - paragraph); 00538 00539 // Find the first space after pos. 00540 for (p = paragraph + pos.offset; *p != 0; p = g_utf8_next_char(p)) 00541 { 00542 if (is_seperator(p)) 00543 { 00544 p = g_utf8_prev_char(p); 00545 break; 00546 } 00547 } 00548 word_end_pos.offset = static_cast<int>(p - paragraph); 00549 00550 return true; 00551 }
bool text::TextModel::get_words_from_range | ( | const Position & | range_start, | |
const Position & | range_end, | |||
Position & | words_start, | |||
Position & | words_end | |||
) |
Get the words from range, the range will be extended/shrinked to words boundary.
Definition at line 553 of file text_model.cpp.
References ERRORPRINTF, get_word_from_anchor(), text::Position::offset, text::Position::paragraph, and text::Position::to_string().
00557 { 00558 if (range_end < range_start) 00559 { 00560 ERRORPRINTF("Invalid range, range_start = %s, range_end = %s", 00561 range_start.to_string().c_str(), 00562 range_end.to_string().c_str()); 00563 return false; 00564 } 00565 00566 Position tmp; 00567 00568 // Get the object range the range_start anchor points to. 00569 get_word_from_anchor(range_start, words_start, tmp); 00570 00571 // Get the object range the range_end anchor points to. 00572 get_word_from_anchor(range_end, tmp, words_end); 00573 00574 // Strip any leading seperators. 00575 const char* start_paragraph = 0; 00576 const char* p = 0; 00577 while (true) 00578 { 00579 start_paragraph = doc[words_start.paragraph].text->c_str(); 00580 for (p = start_paragraph + words_start.offset; *p != 0; p = g_utf8_next_char(p)) 00581 { 00582 if (!is_seperator(p)) 00583 { 00584 break; 00585 } 00586 } 00587 00588 if (*p == 0) 00589 { 00590 words_start.paragraph++; 00591 words_start.offset = 0; 00592 } 00593 else 00594 { 00595 break; 00596 } 00597 } 00598 words_start.offset = static_cast<int>(p - start_paragraph); 00599 00600 // Strip any trailing seperators. 00601 const char* end_paragraph = doc[words_end.paragraph].text->c_str(); 00602 for (p = end_paragraph + words_end.offset; p > end_paragraph; p = g_utf8_prev_char(p)) 00603 { 00604 if (!is_seperator(p)) 00605 { 00606 break; 00607 } 00608 } 00609 words_end.offset = static_cast<int>(p - end_paragraph); 00610 00611 return words_end >= words_start; 00612 }
bool text::TextModel::has_anchor | ( | const Position & | pos | ) |
Check if the document contains the anchor or not.
Definition at line 466 of file text_model.cpp.
References text::Position::offset, and text::Position::paragraph.
bool text::TextModel::is_open | ( | ) | const [inline] |
Check if document is already open.
Definition at line 59 of file text_model.h.
PluginStatus text::TextModel::open | ( | const std::string & | path, | |
const std::string & | encoding | |||
) |
Open document with specified encoding.
Definition at line 67 of file text_model.cpp.
References close(), PLUGIN_FAIL, and PLUGIN_OK.
00069 { 00070 PluginStatus result = PLUGIN_FAIL; 00071 00072 // The document was opened already, close it first. 00073 if (b_open) 00074 { 00075 close(); 00076 } 00077 00078 // Try to open specified file. 00079 file_p = fopen(doc_path.c_str(), "r"); 00080 if (file_p == NULL) 00081 { 00082 return PLUGIN_FAIL; 00083 } 00084 00085 // Detect encodings if necessary. 00086 if (encoding.empty()) 00087 { 00088 detect_encoding(); 00089 } 00090 00091 // Update document information. 00092 path = doc_path; 00093 b_open = true; 00094 00095 // Build up paragraphs. 00096 result = read_text(); 00097 if (result != PLUGIN_OK) 00098 { 00099 close(); 00100 return result; 00101 } 00102 00103 if (doc.empty()) 00104 { 00105 doc.push_back(Paragraph(0, new std::string(" "))); 00106 } 00107 00108 return result; 00109 }
PluginStatus text::TextModel::open | ( | const std::string & | path | ) |
Open specified document with default encoding.
Definition at line 62 of file text_model.cpp.
Referenced by main().
00063 { 00064 return open(doc_path, ""); 00065 }
bool text::TextModel::search | ( | std::vector< Range > & | result_ranges, | |
SearchContext * | sc | |||
) |
Search specified pattern given by search criteria.
result_ranges | Output range collection. | |
search_context | Search criteria. |
Definition at line 345 of file text_model.cpp.
References text::SearchContext::case_sensitive, e, text::Range::end, text::SearchContext::forward, text::SearchContext::from, is_whole_word(), text::SearchContext::match_whole_word, text::Position::offset, text::Position::paragraph, text::SearchContext::pattern, text::SEARCH_NEXT, text::SearchContext::search_type, text::Range::start, utf8_strrstr(), and utf8_strstr().
Referenced by text::SearchTask::execute().
00346 { 00347 // Exact search type and search criteria from search context. 00348 SearchType search_type = sc->search_type; 00349 Position &from = sc->from; 00350 const char *pattern = sc->pattern.c_str(); 00351 bool case_sensitive = sc->case_sensitive; 00352 bool forward = sc->forward; 00353 bool match_whole_word = sc->match_whole_word; 00354 00355 size_t pattern_len = strlen(pattern); 00356 const char *paragraph_head = doc[from.paragraph].text->c_str(); 00357 00358 bool new_search = is_new_search(sc); 00359 00360 // Remember last search context. 00361 last_sc = *sc; 00362 00363 // Clear the last search result range. 00364 Position s(0, 0), e(0,0); 00365 last_search_result.start = s; 00366 last_search_result.end = e; 00367 00368 if (forward) 00369 { 00370 const char *p = paragraph_head + from.offset; 00371 if (p && !new_search) 00372 { 00373 // It's searching next again, move the start position of searching one character. 00374 // Otherwize, searching one letter results in deadlock. 00375 // 00376 // See more in 0003861: [UDS TXT plugin] TXT Search next 00377 // for single character word does not work. 00378 // 00379 // The solution is very dirty. But txt plugin has low priority 00380 // which is not specified for dr1000 and dr800. 00381 // And redefinition what is range takes much more time and has more effects. 00382 p++; 00383 } 00384 while (true) 00385 { 00386 const char* find = utf8_strstr(p, pattern, case_sensitive); 00387 if (find) 00388 { 00389 // See if matching whole word. 00390 if (!match_whole_word || is_whole_word(paragraph_head, find, pattern_len)) 00391 { 00392 // Pattern found. 00393 Position start(from.paragraph, static_cast<unsigned int>(find - paragraph_head)); 00394 const char* last_char = g_utf8_prev_char(find + pattern_len); 00395 Position end(from.paragraph, static_cast<unsigned int>(last_char - paragraph_head)); 00396 result_ranges.push_back(Range(start, end)); 00397 00398 if (search_type == SEARCH_NEXT) 00399 { 00400 // Remember last search result. 00401 last_search_result.start = start; 00402 last_search_result.end = end; 00403 00404 // Search complete. 00405 return true; 00406 } 00407 00408 // If SEARCH_ALL we must continue with current paragraph. 00409 } 00410 00411 p = find + pattern_len; 00412 } 00413 else 00414 { 00415 // Can't find any match in current paragraph. 00416 from.offset = 0; 00417 return ++(from.paragraph) == doc.size(); 00418 } 00419 } 00420 } 00421 else 00422 { 00423 // Backward search. 00424 int len = static_cast<int>(from.offset); 00425 while (true) 00426 { 00427 const char *find = utf8_strrstr(paragraph_head, len, pattern, case_sensitive); 00428 if (find) 00429 { 00430 // See if matching whole word. 00431 if (!match_whole_word || is_whole_word(paragraph_head, find, pattern_len)) 00432 { 00433 // Pattern found. 00434 Position start(from.paragraph, static_cast<unsigned int>(find - paragraph_head)); 00435 const char* last_char = g_utf8_prev_char(find + pattern_len); 00436 Position end(from.paragraph, static_cast<unsigned int>(last_char - paragraph_head)); 00437 result_ranges.push_back(Range(start, end)); 00438 00439 // Remember last search result. 00440 last_search_result.start = start; 00441 last_search_result.end = end; 00442 00443 return true; 00444 } 00445 00446 len = static_cast<int>(find - paragraph_head); 00447 } 00448 else 00449 { 00450 // Can't find any match in current paragraph. 00451 if (from.paragraph == 0) 00452 { 00453 return true; 00454 } 00455 else 00456 { 00457 from.paragraph--; 00458 from.offset = static_cast<unsigned int>(doc[from.paragraph].text->size()); 00459 return false; 00460 } 00461 } 00462 } 00463 } 00464 }
void text::TextModel::set_aborting_search_task_id | ( | unsigned int | id | ) | [inline] |
Abort specified search task.
Definition at line 126 of file text_model.h.
00127 { 00128 aborting_search_task_id = id; 00129 }
utils::Signal<const std::vector<Range>&, const SearchContext*> text::TextModel::search_done_signal |
Signals.
Definition at line 138 of file text_model.h.
Referenced by text::SearchTask::execute(), main(), and text::PluginDocImpl::PluginDocImpl().