diff --git a/jni/Android.mk b/jni/Android.mk index 6417e1e96..624cc6d7c 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -76,15 +76,27 @@ LOCAL_SRC_FILES := \ NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.cpp \ NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.cpp \ NativeFormats/zlibrary/core/src/unix/library/ZLUnixLibrary.cpp \ + NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.cpp \ + NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.cpp \ + NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp \ + NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp \ NativeFormats/zlibrary/ui/src/android/filesystem/JavaFSDir.cpp \ NativeFormats/zlibrary/ui/src/android/filesystem/JavaInputStream.cpp \ NativeFormats/zlibrary/ui/src/android/filesystem/ZLAndroidFSManager.cpp \ NativeFormats/zlibrary/ui/src/android/library/ZLAndroidLibraryImplementation.cpp \ + NativeFormats/fbreader/src/bookmodel/BookModel.cpp \ + NativeFormats/fbreader/src/bookmodel/BookReader.cpp \ + NativeFormats/fbreader/src/formats/EncodedTextReader.cpp \ NativeFormats/fbreader/src/formats/FormatPlugin.cpp \ NativeFormats/fbreader/src/formats/PluginCollection.cpp \ + NativeFormats/fbreader/src/formats/txt/PlainTextFormat.cpp \ + NativeFormats/fbreader/src/formats/txt/TxtBookReader.cpp \ + NativeFormats/fbreader/src/formats/txt/TxtPlugin.cpp \ + NativeFormats/fbreader/src/formats/txt/TxtReader.cpp \ NativeFormats/fbreader/src/library/Author.cpp \ NativeFormats/fbreader/src/library/Book.cpp \ NativeFormats/fbreader/src/library/Comparators.cpp \ + NativeFormats/fbreader/src/library/Library.cpp \ NativeFormats/fbreader/src/library/Tag.cpp LOCAL_C_INCLUDES := \ @@ -96,6 +108,7 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/library \ $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/logger \ $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/util \ - $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/xml + $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/xml \ + $(LOCAL_PATH)/NativeFormats/zlibrary/text/src/model include $(BUILD_SHARED_LIBRARY) diff --git a/jni/NativeFormats/fbreader/src/bookmodel/BookModel.cpp b/jni/NativeFormats/fbreader/src/bookmodel/BookModel.cpp new file mode 100644 index 000000000..246b8d7ef --- /dev/null +++ b/jni/NativeFormats/fbreader/src/bookmodel/BookModel.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include + +#include "BookModel.h" +#include "BookReader.h" + +#include "../formats/FormatPlugin.h" +#include "../library/Book.h" +#include "../library/Library.h" + +BookModel::BookModel(const shared_ptr book) : myBook(book) { + const std::string cacheDirectory = Library::Instance().cacheDirectory(); + myImagesWriter = new ZLImageMapWriter(131072, cacheDirectory, "nimages"); + myBookTextModel = new ZLTextPlainModel(std::string(), book->language(), 131072, cacheDirectory, "ncache"); + myContentsModel = new ContentsModel(book->language(), cacheDirectory, "ncontents"); + /*shared_ptr plugin = PluginCollection::Instance().plugin(book->file(), false); + if (!plugin.isNull()) { + plugin->readModel(*this); + }*/ +} + +BookModel::~BookModel() { +} + +void BookModel::setHyperlinkMatcher(shared_ptr matcher) { + myHyperlinkMatcher = matcher; +} + +BookModel::Label BookModel::label(const std::string &id) const { + if (!myHyperlinkMatcher.isNull()) { + return myHyperlinkMatcher->match(myInternalHyperlinks, id); + } + + std::map::const_iterator it = myInternalHyperlinks.find(id); + return (it != myInternalHyperlinks.end()) ? it->second : Label(0, -1); +} + +ContentsModel::ContentsModel(const std::string &language, + const std::string &directoryName, const std::string &fileExtension) : + ZLTextTreeModel(std::string(), language, directoryName, fileExtension) { +} + +void ContentsModel::setReference(const ZLTextTreeParagraph *paragraph, int reference) { + myReferenceByParagraph[paragraph] = reference; +} + +int ContentsModel::reference(const ZLTextTreeParagraph *paragraph) const { + std::map::const_iterator it = myReferenceByParagraph.find(paragraph); + return (it != myReferenceByParagraph.end()) ? it->second : -1; +} + +const shared_ptr BookModel::book() const { + return myBook; +} + +void BookModel::flush() { + myBookTextModel->flush(); + myContentsModel->flush(); + myImagesWriter->flush(); + + std::map >::const_iterator it = myFootnotes.begin(); + for (; it != myFootnotes.end(); ++it) { + it->second->flush(); + } +} diff --git a/jni/NativeFormats/fbreader/src/bookmodel/BookModel.h b/jni/NativeFormats/fbreader/src/bookmodel/BookModel.h new file mode 100644 index 000000000..98036249b --- /dev/null +++ b/jni/NativeFormats/fbreader/src/bookmodel/BookModel.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __BOOKMODEL_H__ +#define __BOOKMODEL_H__ + +#include +#include + +#include +#include +#include +#include + +class ZLImage; +class Book; + +class ContentsModel : public ZLTextTreeModel { + +public: + ContentsModel(const std::string &language, const std::string &directoryName, const std::string &fileExtension); + void setReference(const ZLTextTreeParagraph *paragraph, int reference); + int reference(const ZLTextTreeParagraph *paragraph) const; + +private: + std::map myReferenceByParagraph; +}; + +class BookModel : public ZLUserDataHolder { + +public: + struct Label { + Label(shared_ptr model, int paragraphNumber) : Model(model), ParagraphNumber(paragraphNumber) {} + + const shared_ptr Model; + const int ParagraphNumber; + }; + +public: + class HyperlinkMatcher { + + public: + virtual Label match(const std::map &lMap, const std::string &id) const = 0; + }; + +public: + BookModel(const shared_ptr book); + ~BookModel(); + + void setHyperlinkMatcher(shared_ptr matcher); + + shared_ptr bookTextModel() const; + shared_ptr contentsModel() const; + const std::map > &footnotes() const; + + shared_ptr imageMapWriter() const; + + Label label(const std::string &id) const; + const std::map &internalHyperlinks() const; + + const shared_ptr book() const; + + void flush(); + +private: + const shared_ptr myBook; + shared_ptr myBookTextModel; + shared_ptr myContentsModel; + shared_ptr myImagesWriter; + std::map > myFootnotes; + std::map myInternalHyperlinks; + shared_ptr myHyperlinkMatcher; + +friend class BookReader; +}; + +inline shared_ptr BookModel::bookTextModel() const { return myBookTextModel; } +inline shared_ptr BookModel::contentsModel() const { return myContentsModel; } +inline const std::map > &BookModel::footnotes() const { return myFootnotes; } +inline shared_ptr BookModel::imageMapWriter() const { return myImagesWriter; } +inline const std::map &BookModel::internalHyperlinks() const { return myInternalHyperlinks; } + +#endif /* __BOOKMODEL_H__ */ diff --git a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp new file mode 100644 index 000000000..7e8ffa273 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include + +#include "BookReader.h" +#include "BookModel.h" + +#include "../library/Book.h" +#include "../library/Library.h" + +BookReader::BookReader(BookModel &model) : myModel(model) { + myCurrentTextModel = 0; + myLastTOCParagraphIsEmpty = false; + + myTextParagraphExists = false; + myContentsParagraphExists = false; + + myInsideTitle = false; + mySectionContainsRegularContents = false; +} + +BookReader::~BookReader() { +} + +void BookReader::setMainTextModel() { + myCurrentTextModel = myModel.myBookTextModel; +} + +void BookReader::setFootnoteTextModel(const std::string &id) { + std::map >::iterator it = myModel.myFootnotes.find(id); + if (it != myModel.myFootnotes.end()) { + myCurrentTextModel = (*it).second; + } else { + myCurrentTextModel = new ZLTextPlainModel(id, myModel.myBookTextModel->language(), 8192, + Library::Instance().cacheDirectory(), "nfootnote_id=" + id); + myModel.myFootnotes.insert(std::make_pair(id, myCurrentTextModel)); + } +} + +void BookReader::unsetTextModel() { + myCurrentTextModel = 0; +} + +void BookReader::pushKind(FBTextKind kind) { + myKindStack.push_back(kind); +} + +bool BookReader::popKind() { + if (!myKindStack.empty()) { + myKindStack.pop_back(); + return true; + } + return false; +} + +bool BookReader::isKindStackEmpty() const { + return myKindStack.empty(); +} + +void BookReader::beginParagraph(ZLTextParagraph::Kind kind) { + if (myCurrentTextModel != 0) { + ((ZLTextPlainModel&)*myCurrentTextModel).createParagraph(kind); + for (std::vector::const_iterator it = myKindStack.begin(); it != myKindStack.end(); ++it) { + myCurrentTextModel->addControl(*it, true); + } + if (!myHyperlinkReference.empty()) { + myCurrentTextModel->addHyperlinkControl(myHyperlinkKind, myHyperlinkType, myHyperlinkReference); + } + myTextParagraphExists = true; + } +} + +void BookReader::endParagraph() { + if (myTextParagraphExists) { + flushTextBufferToParagraph(); + myTextParagraphExists = false; + } +} + +void BookReader::addControl(FBTextKind kind, bool start) { + if (myTextParagraphExists) { + flushTextBufferToParagraph(); + myCurrentTextModel->addControl(kind, start); + } + if (!start && !myHyperlinkReference.empty() && (kind == myHyperlinkKind)) { + myHyperlinkReference.erase(); + } +} + +void BookReader::addControl(const ZLTextStyleEntry &entry) { + if (myTextParagraphExists) { + flushTextBufferToParagraph(); + myCurrentTextModel->addControl(entry); + } +} + +void BookReader::addFixedHSpace(unsigned char length) { + if (myTextParagraphExists) { + myCurrentTextModel->addFixedHSpace(length); + } +} + +void BookReader::addHyperlinkControl(FBTextKind kind, const std::string &label) { + myHyperlinkKind = kind; + std::string type; + switch (myHyperlinkKind) { + case INTERNAL_HYPERLINK: + case FOOTNOTE: + myHyperlinkType = HYPERLINK_INTERNAL; + type = "internal"; + break; + case EXTERNAL_HYPERLINK: + myHyperlinkType = HYPERLINK_EXTERNAL; + type = "external"; + break; + /*case BOOK_HYPERLINK: + myHyperlinkType = HYPERLINK_BOOK; + type = "book"; + break;*/ + default: + myHyperlinkType = HYPERLINK_NONE; + break; + } + ZLLogger::Instance().println( + "hyperlink", + " + control (" + type + "): " + label + ); + if (myTextParagraphExists) { + flushTextBufferToParagraph(); + myCurrentTextModel->addHyperlinkControl(kind, myHyperlinkType, label); + } + myHyperlinkReference = label; +} + +void BookReader::addHyperlinkLabel(const std::string &label) { + if (!myCurrentTextModel.isNull()) { + int paragraphNumber = myCurrentTextModel->paragraphsNumber(); + if (myTextParagraphExists) { + --paragraphNumber; + } + addHyperlinkLabel(label, paragraphNumber); + } +} + +void BookReader::addHyperlinkLabel(const std::string &label, int paragraphNumber) { + ZLLogger::Instance().println( + "hyperlink", + " + label: " + label + ); + myModel.myInternalHyperlinks.insert(std::make_pair( + label, BookModel::Label(myCurrentTextModel, paragraphNumber) + )); +} + +void BookReader::addData(const std::string &data) { + if (!data.empty() && myTextParagraphExists) { + if (!myInsideTitle) { + mySectionContainsRegularContents = true; + } + myBuffer.push_back(data); + } +} + +void BookReader::addContentsData(const std::string &data) { + if (!data.empty() && !myTOCStack.empty()) { + myContentsBuffer.push_back(data); + } +} + +void BookReader::flushTextBufferToParagraph() { + myCurrentTextModel->addText(myBuffer); + myBuffer.clear(); +} + +void BookReader::addImage(const std::string &id, shared_ptr image) { + if (!image.isNull()) { + myModel.myImagesWriter->addImage(id, *image); + } +} + +void BookReader::insertEndParagraph(ZLTextParagraph::Kind kind) { + if ((myCurrentTextModel != 0) && mySectionContainsRegularContents) { + size_t size = myCurrentTextModel->paragraphsNumber(); + if ((size > 0) && (((*myCurrentTextModel)[(size_t)-1])->kind() != kind)) { + ((ZLTextPlainModel&)*myCurrentTextModel).createParagraph(kind); + mySectionContainsRegularContents = false; + } + } +} + +void BookReader::insertEndOfSectionParagraph() { + insertEndParagraph(ZLTextParagraph::END_OF_SECTION_PARAGRAPH); +} + +void BookReader::insertEndOfTextParagraph() { + insertEndParagraph(ZLTextParagraph::END_OF_TEXT_PARAGRAPH); +} + +void BookReader::addImageReference(const std::string &id, short vOffset) { + if (myCurrentTextModel != 0) { + mySectionContainsRegularContents = true; + if (myTextParagraphExists) { + flushTextBufferToParagraph(); + myCurrentTextModel->addImage(id, vOffset); + } else { + beginParagraph(); + myCurrentTextModel->addControl(IMAGE, true); + myCurrentTextModel->addImage(id, vOffset); + myCurrentTextModel->addControl(IMAGE, false); + endParagraph(); + } + } +} + +void BookReader::beginContentsParagraph(int referenceNumber) { + if (myCurrentTextModel == myModel.myBookTextModel) { + ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel; + if (referenceNumber == -1) { + referenceNumber = myCurrentTextModel->paragraphsNumber(); + } + ZLTextTreeParagraph *peek = myTOCStack.empty() ? 0 : myTOCStack.top(); + if (!myContentsBuffer.empty()) { + contentsModel.addText(myContentsBuffer); + myContentsBuffer.clear(); + myLastTOCParagraphIsEmpty = false; + } + if (myLastTOCParagraphIsEmpty) { + contentsModel.addText("..."); + } + ZLTextTreeParagraph *para = contentsModel.createParagraph(peek); + contentsModel.addControl(CONTENTS_TABLE_ENTRY, true); + contentsModel.setReference(para, referenceNumber); + myTOCStack.push(para); + myLastTOCParagraphIsEmpty = true; + myContentsParagraphExists = true; + } +} + +void BookReader::endContentsParagraph() { + if (!myTOCStack.empty()) { + ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel; + if (!myContentsBuffer.empty()) { + contentsModel.addText(myContentsBuffer); + myContentsBuffer.clear(); + myLastTOCParagraphIsEmpty = false; + } + if (myLastTOCParagraphIsEmpty) { + contentsModel.addText("..."); + myLastTOCParagraphIsEmpty = false; + } + myTOCStack.pop(); + } + myContentsParagraphExists = false; +} + +void BookReader::setReference(size_t contentsParagraphNumber, int referenceNumber) { + ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel; + if (contentsParagraphNumber >= contentsModel.paragraphsNumber()) { + return; + } + contentsModel.setReference((const ZLTextTreeParagraph*)contentsModel[contentsParagraphNumber], referenceNumber); +} + +void BookReader::reset() { + myKindStack.clear(); +} diff --git a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.h b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.h new file mode 100644 index 000000000..03c477215 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __BOOKREADER_H__ +#define __BOOKREADER_H__ + +#include +#include +#include + +#include + +#include "FBHyperlinkType.h" +#include "FBTextKind.h" + +class BookModel; +class ZLTextModel; +class ZLInputStream; + +class BookReader { + +public: + BookReader(BookModel &model); + virtual ~BookReader(); + + void setMainTextModel(); + void setFootnoteTextModel(const std::string &id); + void unsetTextModel(); + + void insertEndOfSectionParagraph(); + void insertEndOfTextParagraph(); + + void pushKind(FBTextKind kind); + bool popKind(); + bool isKindStackEmpty() const; + + void beginParagraph(ZLTextParagraph::Kind kind = ZLTextParagraph::TEXT_PARAGRAPH); + void endParagraph(); + bool paragraphIsOpen() const; + void addControl(FBTextKind kind, bool start); + void addControl(const ZLTextStyleEntry &entry); + void addHyperlinkControl(FBTextKind kind, const std::string &label); + void addHyperlinkLabel(const std::string &label); + void addHyperlinkLabel(const std::string &label, int paragraphNumber); + void addFixedHSpace(unsigned char length); + + void addImageReference(const std::string &id, short vOffset = 0); + void addImage(const std::string &id, shared_ptr image); + + void beginContentsParagraph(int referenceNumber = -1); + void endContentsParagraph(); + bool contentsParagraphIsOpen() const; + void setReference(size_t contentsParagraphNumber, int referenceNumber); + + void addData(const std::string &data); + void addContentsData(const std::string &data); + + void enterTitle() { myInsideTitle = true; } + void exitTitle() { myInsideTitle = false; } + + const BookModel &model() const { return myModel; } + + void reset(); + +private: + void insertEndParagraph(ZLTextParagraph::Kind kind); + void flushTextBufferToParagraph(); + +private: + BookModel &myModel; + shared_ptr myCurrentTextModel; + + std::vector myKindStack; + + bool myTextParagraphExists; + bool myContentsParagraphExists; + std::stack myTOCStack; + bool myLastTOCParagraphIsEmpty; + + bool mySectionContainsRegularContents; + bool myInsideTitle; + + std::vector myBuffer; + std::vector myContentsBuffer; + + std::string myHyperlinkReference; + FBHyperlinkType myHyperlinkType; + FBTextKind myHyperlinkKind; +}; + +inline bool BookReader::paragraphIsOpen() const { + return myTextParagraphExists; +} + +inline bool BookReader::contentsParagraphIsOpen() const { + return myContentsParagraphExists; +} + +#endif /* __BOOKREADER_H__ */ diff --git a/jni/NativeFormats/fbreader/src/bookmodel/FBHyperlinkType.h b/jni/NativeFormats/fbreader/src/bookmodel/FBHyperlinkType.h new file mode 100644 index 000000000..7fa091c5a --- /dev/null +++ b/jni/NativeFormats/fbreader/src/bookmodel/FBHyperlinkType.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __FBHYPERLINKTYPE_H__ +#define __FBHYPERLINKTYPE_H__ + +enum FBHyperlinkType { + HYPERLINK_NONE = 0, + HYPERLINK_INTERNAL = 1, + HYPERLINK_EXTERNAL = 2, + //HYPERLINK_BOOK = 3, +}; + +#endif /* __FBHYPERLINKTYPE_H__ */ diff --git a/jni/NativeFormats/fbreader/src/bookmodel/FBTextKind.h b/jni/NativeFormats/fbreader/src/bookmodel/FBTextKind.h new file mode 100644 index 000000000..d495cd10a --- /dev/null +++ b/jni/NativeFormats/fbreader/src/bookmodel/FBTextKind.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __FBTEXTKIND_H__ +#define __FBTEXTKIND_H__ + +enum FBTextKind { + // please, don't change these numbers + // add new text kinds at end of this enumeration + // + // all the values MUST be in the range 0..127 + REGULAR = 0, + TITLE = 1, + SECTION_TITLE = 2, + POEM_TITLE = 3, + SUBTITLE = 4, + ANNOTATION = 5, + EPIGRAPH = 6, + STANZA = 7, + VERSE = 8, + PREFORMATTED = 9, + IMAGE = 10, + END_OF_SECTION = 11, + CITE = 12, + AUTHOR = 13, + DATEKIND = 14, + INTERNAL_HYPERLINK = 15, + FOOTNOTE = 16, + EMPHASIS = 17, + STRONG = 18, + SUB = 19, + SUP = 20, + CODE = 21, + STRIKETHROUGH = 22, + CONTENTS_TABLE_ENTRY = 23, + //LIBRARY_AUTHOR_ENTRY = 24, + //LIBRARY_BOOK_ENTRY = 25, + LIBRARY_ENTRY = 25, + //RECENT_BOOK_LIST = 26, + ITALIC = 27, + BOLD = 28, + DEFINITION = 29, + DEFINITION_DESCRIPTION = 30, + H1 = 31, + H2 = 32, + H3 = 33, + H4 = 34, + H5 = 35, + H6 = 36, + EXTERNAL_HYPERLINK = 37, + //BOOK_HYPERLINK = 38, +}; + +#endif /* __FBTEXTKIND_H__ */ diff --git a/jni/NativeFormats/fbreader/src/formats/EncodedTextReader.cpp b/jni/NativeFormats/fbreader/src/formats/EncodedTextReader.cpp new file mode 100644 index 000000000..362d269be --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/EncodedTextReader.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "EncodedTextReader.h" + +EncodedTextReader::EncodedTextReader(const std::string &encoding) { + ZLEncodingCollection &collection = ZLEncodingCollection::Instance(); + ZLEncodingConverterInfoPtr info = collection.info(encoding); + myConverter = (!info.isNull()) ? info->createConverter() : collection.defaultConverter(); +} + +EncodedTextReader::~EncodedTextReader() { +} diff --git a/jni/NativeFormats/fbreader/src/formats/EncodedTextReader.h b/jni/NativeFormats/fbreader/src/formats/EncodedTextReader.h new file mode 100644 index 000000000..8035508bf --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/EncodedTextReader.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ENCODEDTEXTREADER_H__ +#define __ENCODEDTEXTREADER_H__ + +#include + +#include + +class EncodedTextReader { + +protected: + EncodedTextReader(const std::string &encoding); + virtual ~EncodedTextReader(); + +protected: + shared_ptr myConverter; +}; + +#endif /* __ENCODEDTEXTREADER_H__ */ diff --git a/jni/NativeFormats/fbreader/src/formats/PluginCollection.cpp b/jni/NativeFormats/fbreader/src/formats/PluginCollection.cpp index c63168ddb..0b1c98b49 100644 --- a/jni/NativeFormats/fbreader/src/formats/PluginCollection.cpp +++ b/jni/NativeFormats/fbreader/src/formats/PluginCollection.cpp @@ -29,7 +29,7 @@ //#include "fb2/FB2Plugin.h" ////#include "docbook/DocBookPlugin.h" //#include "html/HtmlPlugin.h" -//#include "txt/TxtPlugin.h" +#include "txt/TxtPlugin.h" //#include "pdb/PdbPlugin.h" //#include "tcr/TcrPlugin.h" //#include "oeb/OEBPlugin.h" @@ -46,7 +46,7 @@ PluginCollection &PluginCollection::Instance() { //ourInstance->myPlugins.push_back(new FB2Plugin()); // //ourInstance->myPlugins.push_back(new DocBookPlugin()); //ourInstance->myPlugins.push_back(new HtmlPlugin()); - //ourInstance->myPlugins.push_back(new TxtPlugin()); + ourInstance->myPlugins.push_back(new TxtPlugin()); // ourInstance->myPlugins.push_back(new PluckerPlugin()); // ourInstance->myPlugins.push_back(new PalmDocPlugin()); // ourInstance->myPlugins.push_back(new MobipocketPlugin()); diff --git a/jni/NativeFormats/fbreader/src/formats/txt/PlainTextFormat.cpp b/jni/NativeFormats/fbreader/src/formats/txt/PlainTextFormat.cpp new file mode 100644 index 000000000..4736d0dd6 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/PlainTextFormat.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include + +//#include +//#include +//#include +#include + +#include "PlainTextFormat.h" + +//#include "../../options/FBCategoryKey.h" + +const std::string OPTION_Initialized = "Initialized"; +const std::string OPTION_BreakType = "BreakType"; +const std::string OPTION_IgnoredIndent = "IgnoredIndent"; +const std::string OPTION_EmptyLinesBeforeNewSection = "EmptyLinesBeforeNewSection"; +const std::string OPTION_CreateContentsTable = "CreateContentsTable"; + +PlainTextFormat::PlainTextFormat(const ZLFile &file) : +// InitializedOption(FBCategoryKey::BOOKS, file.path(), OPTION_Initialized, false), +// BreakTypeOption(FBCategoryKey::BOOKS, file.path(), OPTION_BreakType, 1), +// IgnoredIndentOption(FBCategoryKey::BOOKS, file.path(), OPTION_IgnoredIndent, 1, 100, 1), +// EmptyLinesBeforeNewSectionOption(FBCategoryKey::BOOKS, file.path(), OPTION_EmptyLinesBeforeNewSection, 1, 100, 1), +// CreateContentsTableOption(FBCategoryKey::BOOKS, file.path(), OPTION_CreateContentsTable, false) { + myInitialized(false), + myBreakType(1), + myIgnoredIndent(1), + myEmptyLinesBeforeNewSection(1), + myCreateContentsTable(false) { +} + +/*PlainTextInfoPage::PlainTextInfoPage(ZLOptionsDialog &dialog, const ZLFile &file, const ZLResourceKey &key, bool showContentsEntry) : myFormat(file) { + if (!myFormat.initialized()) { + PlainTextFormatDetector detector; + shared_ptr stream = file.inputStream(); + if (!stream.isNull()) { + detector.detect(*stream, myFormat); + } + } + + ZLDialogContent &tab = dialog.createTab(key); + + BreakTypeOptionEntry *breakEntry = new BreakTypeOptionEntry(*this, myFormat.BreakTypeOption); + myIgnoredIndentEntry = new ZLSimpleSpinOptionEntry(myFormat.IgnoredIndentOption, 1); + tab.addOption(ZLResourceKey("breakType"), breakEntry); + tab.addOption(ZLResourceKey("ignoreIndent"), myIgnoredIndentEntry); + breakEntry->onValueSelected(breakEntry->initialIndex()); + + if (showContentsEntry) { + CreateContentsTableOptionEntry *contentsTableEntry = new CreateContentsTableOptionEntry(*this, myFormat.CreateContentsTableOption); + myEmptyLinesBeforeNewSectionEntry = new ZLSimpleSpinOptionEntry(myFormat.EmptyLinesBeforeNewSectionOption, 1); + tab.addOption(ZLResourceKey("buildTOC"), contentsTableEntry); + tab.addOption(ZLResourceKey("emptyLines"), myEmptyLinesBeforeNewSectionEntry); + contentsTableEntry->onStateChanged(contentsTableEntry->initialState()); + } +}*/ + +/*PlainTextInfoPage::~PlainTextInfoPage() { +}*/ + +const int BUFFER_SIZE = 4096; + +void PlainTextFormatDetector::detect(ZLInputStream &stream, PlainTextFormat &format) { + if (!stream.open()) { + return; + } + + const unsigned int tableSize = 10; + + unsigned int lineCounter = 0; + int emptyLineCounter = -1; + unsigned int stringsWithLengthLessThan81Counter = 0; + unsigned int stringIndentTable[tableSize] = { 0 }; + unsigned int emptyLinesTable[tableSize] = { 0 }; + unsigned int emptyLinesBeforeShortStringTable[tableSize] = { 0 }; + + bool currentLineIsEmpty = true; + unsigned int currentLineLength = 0; + unsigned int currentLineIndent = 0; + int currentNumberOfEmptyLines = -1; + + char *buffer = new char[BUFFER_SIZE]; + int length; + char previous = 0; + do { + length = stream.read(buffer, BUFFER_SIZE); + const char *end = buffer + length; + for (const char *ptr = buffer; ptr != end; ++ptr) { + ++currentLineLength; + if (*ptr == '\n') { + ++lineCounter; + if (currentLineIsEmpty) { + ++emptyLineCounter; + ++currentNumberOfEmptyLines; + } else { + if (currentNumberOfEmptyLines >= 0) { + int index = std::min(currentNumberOfEmptyLines, (int)tableSize - 1); + emptyLinesTable[index]++; + if (currentLineLength < 51) { + emptyLinesBeforeShortStringTable[index]++; + } + } + currentNumberOfEmptyLines = -1; + } + if (currentLineLength < 81) { + ++stringsWithLengthLessThan81Counter; + } + if (!currentLineIsEmpty) { + stringIndentTable[std::min(currentLineIndent, tableSize - 1)]++; + } + + currentLineIsEmpty = true; + currentLineLength = 0; + currentLineIndent = 0; + } else if (*ptr == '\r') { + continue; + } else if (isspace((unsigned char)*ptr)) { + if (currentLineIsEmpty) { + ++currentLineIndent; + } + } else { + currentLineIsEmpty = false; + } + previous = *ptr; + } + } while (length == BUFFER_SIZE); + delete[] buffer; + + unsigned int nonEmptyLineCounter = lineCounter - emptyLineCounter; + + { + unsigned int indent = 0; + unsigned int lineWithIndent = 0; + for (; indent < tableSize; ++indent) { + lineWithIndent += stringIndentTable[indent]; + if (lineWithIndent > 0.1 * nonEmptyLineCounter) { + break; + } + } + format.myIgnoredIndent = (indent + 1); + } + + { + int breakType = 0; + breakType |= PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE; + if (stringsWithLengthLessThan81Counter < 0.3 * nonEmptyLineCounter) { + breakType |= PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE; + } else { + breakType |= PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT; + } + format.myBreakType = (breakType); + } + + { + unsigned int max = 0; + unsigned index; + int emptyLinesBeforeNewSection = -1; + for (index = 2; index < tableSize; ++index) { + if (max < emptyLinesBeforeShortStringTable[index]) { + max = emptyLinesBeforeShortStringTable[index]; + emptyLinesBeforeNewSection = index; + } + } + if (emptyLinesBeforeNewSection > 0) { + for (index = tableSize - 1; index > 0; --index) { + emptyLinesTable[index - 1] += emptyLinesTable[index]; + emptyLinesBeforeShortStringTable[index - 1] += emptyLinesBeforeShortStringTable[index]; + } + for (index = emptyLinesBeforeNewSection; index < tableSize; ++index) { + if ((emptyLinesBeforeShortStringTable[index] > 2) && + (emptyLinesBeforeShortStringTable[index] > 0.7 * emptyLinesTable[index])) { + break; + } + } + emptyLinesBeforeNewSection = (index == tableSize) ? -1 : (int)index; + } + format.myEmptyLinesBeforeNewSection = (emptyLinesBeforeNewSection); + format.myCreateContentsTable = (emptyLinesBeforeNewSection > 0); + } + + format.myInitialized = (true); +} + +/*BreakTypeOptionEntry::BreakTypeOptionEntry(PlainTextInfoPage &page, ZLIntegerOption &breakTypeOption) : myPage(page), myBreakTypeOption(breakTypeOption) { +} + +BreakTypeOptionEntry::~BreakTypeOptionEntry() { +} + +static std::vector BREAK_TYPE_VALUES_VECTOR; + +int BreakTypeOptionEntry::initialIndex() const { + switch (myBreakTypeOption.value()) { + case PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE: + return 0; + case PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE: + return 1; + case PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE | PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT: + default: + return 2; + } +} + +const std::string &BreakTypeOptionEntry::initialValue() const { + return values()[initialIndex()]; +} + +const std::vector &BreakTypeOptionEntry::values() const { + if (BREAK_TYPE_VALUES_VECTOR.empty()) { + BREAK_TYPE_VALUES_VECTOR.push_back("New Line"); + BREAK_TYPE_VALUES_VECTOR.push_back("Empty Line"); + BREAK_TYPE_VALUES_VECTOR.push_back("Line With Indent"); + } + return BREAK_TYPE_VALUES_VECTOR; +} + +void BreakTypeOptionEntry::onAccept(const std::string &value) { + if (value == values()[0]) { + myBreakTypeOption.setValue(PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE); + } else if (value == values()[1]) { + myBreakTypeOption.setValue(PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE); + } else if (value == values()[2]) { + myBreakTypeOption.setValue(PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE | PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT); + } +} + +void BreakTypeOptionEntry::onValueSelected(int index) { + myPage.myIgnoredIndentEntry->setVisible(index == 2); +}*/ + +/*CreateContentsTableOptionEntry::CreateContentsTableOptionEntry(PlainTextInfoPage &page, ZLBooleanOption &option) : ZLSimpleBooleanOptionEntry(option), myPage(page) { +} + +CreateContentsTableOptionEntry::~CreateContentsTableOptionEntry() { +} + +void CreateContentsTableOptionEntry::onStateChanged(bool state) { + myPage.myEmptyLinesBeforeNewSectionEntry->setVisible(state); +}*/ diff --git a/jni/NativeFormats/fbreader/src/formats/txt/PlainTextFormat.h b/jni/NativeFormats/fbreader/src/formats/txt/PlainTextFormat.h new file mode 100644 index 000000000..6a9fcf7f7 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/PlainTextFormat.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __PLAINTEXTFORMAT_H__ +#define __PLAINTEXTFORMAT_H__ + +#include +//#include +//#include +//#include + +#include "../FormatPlugin.h" + +class PlainTextFormat { + +public: + enum ParagraphBreakType { + BREAK_PARAGRAPH_AT_NEW_LINE = 1, + BREAK_PARAGRAPH_AT_EMPTY_LINE = 2, + BREAK_PARAGRAPH_AT_LINE_WITH_INDENT = 4, + }; + + PlainTextFormat(const ZLFile &file); + ~PlainTextFormat() {} + + bool initialized() const { return myInitialized; } + int breakType() const { return myBreakType; } + int ignoredIndent() const { return myIgnoredIndent; } + int emptyLinesBeforeNewSection() const { return myEmptyLinesBeforeNewSection; } + bool createContentsTable() const { return myCreateContentsTable; } + +private: + bool myInitialized; + int myBreakType; + int myIgnoredIndent; + int myEmptyLinesBeforeNewSection; + bool myCreateContentsTable; + +// ZLBooleanOption InitializedOption; +// ZLIntegerOption BreakTypeOption; +// ZLIntegerRangeOption IgnoredIndentOption; +// ZLIntegerRangeOption EmptyLinesBeforeNewSectionOption; +// ZLBooleanOption CreateContentsTableOption; + +friend class PlainTextInfoPage; +friend class PlainTextFormatDetector; +}; + +/*class PlainTextInfoPage : public FormatInfoPage { + +public: + PlainTextInfoPage(ZLOptionsDialog &dialog, const ZLFile &file, const ZLResourceKey &key, bool showContentsEntry); + ~PlainTextInfoPage(); + +private: + PlainTextFormat myFormat; + + ZLSimpleSpinOptionEntry *myIgnoredIndentEntry; + ZLSimpleSpinOptionEntry *myEmptyLinesBeforeNewSectionEntry; + +friend class BreakTypeOptionEntry; +friend class CreateContentsTableOptionEntry; +};*/ + +class PlainTextFormatDetector { + +public: + PlainTextFormatDetector() {} + ~PlainTextFormatDetector() {} + + void detect(ZLInputStream &stream, PlainTextFormat &format); +}; + +/*class BreakTypeOptionEntry : public ZLComboOptionEntry { + +public: + BreakTypeOptionEntry(PlainTextInfoPage &page, ZLIntegerOption &breakTypeOption); + ~BreakTypeOptionEntry(); + + int initialIndex() const; + const std::string &initialValue() const; + const std::vector &values() const; + void onAccept(const std::string &value); + void onValueSelected(int index); + +private: + PlainTextInfoPage &myPage; + ZLIntegerOption &myBreakTypeOption; +};*/ + +/*class CreateContentsTableOptionEntry : public ZLSimpleBooleanOptionEntry { + +public: + CreateContentsTableOptionEntry(PlainTextInfoPage &page, ZLBooleanOption &option); + ~CreateContentsTableOptionEntry(); + void onStateChanged(bool state); + +private: + PlainTextInfoPage &myPage; +};*/ + +#endif /* __PLAINTEXTFORMAT_H__ */ diff --git a/jni/NativeFormats/fbreader/src/formats/txt/TxtBookReader.cpp b/jni/NativeFormats/fbreader/src/formats/txt/TxtBookReader.cpp new file mode 100644 index 000000000..33d4e994f --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/TxtBookReader.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include "TxtBookReader.h" +#include "../../bookmodel/BookModel.h" + +TxtBookReader::TxtBookReader(BookModel &model, const PlainTextFormat &format, const std::string &encoding) : TxtReader(encoding), BookReader(model), myFormat(format) { +} + +void TxtBookReader::internalEndParagraph() { + if (!myLastLineIsEmpty) { + //myLineFeedCounter = 0; + myLineFeedCounter = -1; /* Fixed by Hatred: zero value was break LINE INDENT formater - + second line print with indent like new paragraf */ + } + myLastLineIsEmpty = true; + endParagraph(); +} + +bool TxtBookReader::characterDataHandler(std::string &str) { + const char *ptr = str.data(); + const char *end = ptr + str.length(); + for (; ptr != end; ++ptr) { + if (isspace((unsigned char)*ptr)) { + if (*ptr != '\t') { + ++mySpaceCounter; + } else { + mySpaceCounter += myFormat.ignoredIndent() + 1; // TODO: implement single option in PlainTextFormat + } + } else { + myLastLineIsEmpty = false; + break; + } + } + if (ptr != end) { + if ((myFormat.breakType() & PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT) && + myNewLine && (mySpaceCounter > myFormat.ignoredIndent())) { + internalEndParagraph(); + beginParagraph(); + } + addData(str); + if (myInsideContentsParagraph) { + addContentsData(str); + } + myNewLine = false; + } + return true; +} + +bool TxtBookReader::newLineHandler() { + if (!myLastLineIsEmpty) { + myLineFeedCounter = -1; + } + myLastLineIsEmpty = true; + ++myLineFeedCounter; + myNewLine = true; + mySpaceCounter = 0; + bool paragraphBreak = + (myFormat.breakType() & PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE) || + ((myFormat.breakType() & PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE) && (myLineFeedCounter > 0)); + + if (myFormat.createContentsTable()) { +// if (!myInsideContentsParagraph && (myLineFeedCounter == myFormat.emptyLinesBeforeNewSection() + 1)) { + /* Fixed by Hatred: remove '+ 1' for emptyLinesBeforeNewSection, it looks like very strange + when we should point count of empty string decrised by 1 in settings dialog */ + if (!myInsideContentsParagraph && (myLineFeedCounter == myFormat.emptyLinesBeforeNewSection())) { + myInsideContentsParagraph = true; + internalEndParagraph(); + insertEndOfSectionParagraph(); + beginContentsParagraph(); + enterTitle(); + pushKind(SECTION_TITLE); + beginParagraph(); + paragraphBreak = false; + } + if (myInsideContentsParagraph && (myLineFeedCounter == 1)) { + exitTitle(); + endContentsParagraph(); + popKind(); + myInsideContentsParagraph = false; + paragraphBreak = true; + } + } + + if (paragraphBreak) { + internalEndParagraph(); + beginParagraph(); + } + return true; +} + +void TxtBookReader::startDocumentHandler() { + setMainTextModel(); + pushKind(REGULAR); + beginParagraph(); + myLineFeedCounter = 0; + myInsideContentsParagraph = false; + enterTitle(); + myLastLineIsEmpty = true; + myNewLine = true; + mySpaceCounter = 0; +} + +void TxtBookReader::endDocumentHandler() { + internalEndParagraph(); +} diff --git a/jni/NativeFormats/fbreader/src/formats/txt/TxtBookReader.h b/jni/NativeFormats/fbreader/src/formats/txt/TxtBookReader.h new file mode 100644 index 000000000..e02ad2a21 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/TxtBookReader.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __TXTBOOKREADER_H__ +#define __TXTBOOKREADER_H__ + +#include + +#include "TxtReader.h" +#include "PlainTextFormat.h" +#include "../../bookmodel/BookReader.h" + +class BookModel; + +class TxtBookReader : public TxtReader, public BookReader { + +public: + TxtBookReader(BookModel &model, const PlainTextFormat &format, const std::string &encoding); + ~TxtBookReader(); + +protected: + void startDocumentHandler(); + void endDocumentHandler(); + + bool characterDataHandler(std::string &str); + bool newLineHandler(); + +private: + void internalEndParagraph(); + +private: + const PlainTextFormat &myFormat; + + int myLineFeedCounter; + bool myInsideContentsParagraph; + bool myLastLineIsEmpty; + bool myNewLine; + int mySpaceCounter; +}; + +inline TxtBookReader::~TxtBookReader() {} + +#endif /* __TXTBOOKREADER_H__ */ diff --git a/jni/NativeFormats/fbreader/src/formats/txt/TxtPlugin.cpp b/jni/NativeFormats/fbreader/src/formats/txt/TxtPlugin.cpp new file mode 100644 index 000000000..47d212810 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/TxtPlugin.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include + +#include "TxtPlugin.h" +#include "TxtBookReader.h" +#include "PlainTextFormat.h" + +#include "../../bookmodel/BookModel.h" +#include "../../library/Book.h" + +TxtPlugin::~TxtPlugin() { +} + +bool TxtPlugin::providesMetaInfo() const { + return false; +} + +const std::string TxtPlugin::supportedFileType() const { + return "plain text"; +} + +bool TxtPlugin::readMetaInfo(Book &book) const { + return true; +} + +bool TxtPlugin::readModel(BookModel &model) const { + const Book &book = *model.book(); + const ZLFile &file = book.file(); + shared_ptr stream = file.inputStream(); + if (stream.isNull()) { + return false; + } + + PlainTextFormat format(file); + if (!format.initialized()) { + PlainTextFormatDetector detector; + detector.detect(*stream, format); + } + + TxtBookReader(model, format, book.encoding()).readDocument(*stream); + return true; +} + +//FormatInfoPage *TxtPlugin::createInfoPage(ZLOptionsDialog &dialog, const ZLFile &file) { +// return new PlainTextInfoPage(dialog, file, ZLResourceKey("Text"), true); +//} + +bool TxtPlugin::readLanguageAndEncoding(Book &book) const { + shared_ptr stream = book.file().inputStream(); + if (stream.isNull()) { + return false; + } + detectEncodingAndLanguage(book, *stream); + return !book.encoding().empty(); +} diff --git a/jni/NativeFormats/fbreader/src/formats/txt/TxtPlugin.h b/jni/NativeFormats/fbreader/src/formats/txt/TxtPlugin.h new file mode 100644 index 000000000..c399eb78e --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/TxtPlugin.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __TXTPLUGIN_H__ +#define __TXTPLUGIN_H__ + +#include "../FormatPlugin.h" + +class TxtPlugin : public FormatPlugin { + +public: + ~TxtPlugin(); + bool providesMetaInfo() const; + const std::string supportedFileType() const; + bool readMetaInfo(Book &book) const; + bool readLanguageAndEncoding(Book &book) const; + bool readModel(BookModel &model) const; +// FormatInfoPage *createInfoPage(ZLOptionsDialog &dialog, const ZLFile &file); +}; + +#endif /* __TXTPLUGIN_H__ */ diff --git a/jni/NativeFormats/fbreader/src/formats/txt/TxtReader.cpp b/jni/NativeFormats/fbreader/src/formats/txt/TxtReader.cpp new file mode 100644 index 000000000..f04a41956 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/TxtReader.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include + +#include "TxtReader.h" + +TxtReader::TxtReader(const std::string &encoding) : EncodedTextReader(encoding) { +} + +TxtReader::~TxtReader() { +} + +void TxtReader::readDocument(ZLInputStream &stream) { + if (!stream.open()) { + return; + } + + startDocumentHandler(); + + const size_t BUFSIZE = 2048; + char *buffer = new char[BUFSIZE]; + std::string str; + size_t length; + do { + length = stream.read(buffer, BUFSIZE); + char *start = buffer; + const char *end = buffer + length; + for (char *ptr = start; ptr != end; ++ptr) { + if (*ptr == '\n' || *ptr == '\r') { + bool skipNewLine = false; + if (*ptr == '\r' && (ptr + 1) != end && *(ptr + 1) == '\n') { + skipNewLine = true; + *ptr = '\n'; + } + if (start != ptr) { + str.erase(); + myConverter->convert(str, start, ptr + 1); + characterDataHandler(str); + } + if (skipNewLine) { + ++ptr; + } + start = ptr + 1; + newLineHandler(); + } else if (isspace((unsigned char)*ptr)) { + if (*ptr != '\t') { + *ptr = ' '; + } + } else { + } + } + if (start != end) { + str.erase(); + myConverter->convert(str, start, end); + characterDataHandler(str); + } + } while (length == BUFSIZE); + delete[] buffer; + + endDocumentHandler(); + + stream.close(); +} diff --git a/jni/NativeFormats/fbreader/src/formats/txt/TxtReader.h b/jni/NativeFormats/fbreader/src/formats/txt/TxtReader.h new file mode 100644 index 000000000..de9c3857a --- /dev/null +++ b/jni/NativeFormats/fbreader/src/formats/txt/TxtReader.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __TXTREADER_H__ +#define __TXTREADER_H__ + +#include + +#include + +#include "../EncodedTextReader.h" + +class ZLInputStream; + +class TxtReader : public EncodedTextReader { + +public: + void readDocument(ZLInputStream &stream); + +protected: + TxtReader(const std::string &encoding); + virtual ~TxtReader(); + +protected: + virtual void startDocumentHandler() = 0; + virtual void endDocumentHandler() = 0; + + virtual bool characterDataHandler(std::string &str) = 0; + virtual bool newLineHandler() = 0; +}; + +#endif /* __TXTREADER_H__ */ diff --git a/jni/NativeFormats/fbreader/src/library/Library.cpp b/jni/NativeFormats/fbreader/src/library/Library.cpp new file mode 100644 index 000000000..5b29228b0 --- /dev/null +++ b/jni/NativeFormats/fbreader/src/library/Library.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include "Library.h" + + +shared_ptr Library::ourInstance; + +Library &Library::Instance() { + if (ourInstance.isNull()) { + ourInstance = new Library(); + } + return *ourInstance; +} + +Library::Library() { + JNIEnv *env = AndroidUtil::getEnv(); + jclass paths = env->FindClass(AndroidUtil::Class_Paths); + myPathsClass = (jclass)env->NewGlobalRef(paths); + env->DeleteLocalRef(paths); +} + +Library::~Library() { + JNIEnv *env = AndroidUtil::getEnv(); + env->DeleteGlobalRef(myPathsClass); +} + +std::string Library::cacheDirectory() const { + JNIEnv *env = AndroidUtil::getEnv(); + jstring res = (jstring)env->CallStaticObjectMethod(myPathsClass, AndroidUtil::SMID_Paths_cacheDirectory); + const char *data = env->GetStringUTFChars(res, 0); + std::string str(data); + env->ReleaseStringUTFChars(res, data); + env->DeleteLocalRef(res); + return str; +} diff --git a/jni/NativeFormats/fbreader/src/library/Library.h b/jni/NativeFormats/fbreader/src/library/Library.h new file mode 100644 index 000000000..8ec84252d --- /dev/null +++ b/jni/NativeFormats/fbreader/src/library/Library.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __LIBRARY_H__ +#define __LIBRARY_H__ + +#include + +#include + +#include + + +class Library { + +public: + static Library &Instance(); + +private: + static shared_ptr ourInstance; + +private: + Library(); + +public: + ~Library(); + + std::string cacheDirectory() const; + +private: + jclass myPathsClass; +}; + +#endif /* __LIBRARY_H__ */ diff --git a/jni/NativeFormats/util/AndroidUtil.cpp b/jni/NativeFormats/util/AndroidUtil.cpp index 9cceac31d..14285bb4c 100644 --- a/jni/NativeFormats/util/AndroidUtil.cpp +++ b/jni/NativeFormats/util/AndroidUtil.cpp @@ -27,6 +27,7 @@ const char * const AndroidUtil::Class_java_io_InputStream = "java/io/InputStream const char * const AndroidUtil::Class_ZLibrary = "org/geometerplus/zlibrary/core/library/ZLibrary"; const char * const AndroidUtil::Class_NativeFormatPlugin = "org/geometerplus/fbreader/formats/NativeFormatPlugin"; const char * const AndroidUtil::Class_PluginCollection = "org/geometerplus/fbreader/formats/PluginCollection"; +const char * const AndroidUtil::Class_Paths = "org/geometerplus/fbreader/Paths"; const char * const AndroidUtil::Class_ZLFile = "org/geometerplus/zlibrary/core/filesystem/ZLFile"; const char * const AndroidUtil::Class_Book = "org/geometerplus/fbreader/library/Book"; const char * const AndroidUtil::Class_Tag = "org/geometerplus/fbreader/library/Tag"; @@ -53,6 +54,8 @@ jmethodID AndroidUtil::MID_ZLFile_getPath; jmethodID AndroidUtil::MID_ZLFile_isDirectory; jmethodID AndroidUtil::MID_ZLFile_size; +jmethodID AndroidUtil::SMID_Paths_cacheDirectory; + jfieldID AndroidUtil::FID_Book_File; jmethodID AndroidUtil::MID_Book_getTitle; jmethodID AndroidUtil::MID_Book_getLanguage; @@ -109,6 +112,10 @@ bool AndroidUtil::init(JavaVM* jvm) { CHECK_NULL( MID_ZLFile_size = env->GetMethodID(cls, "size", "()J") ); env->DeleteLocalRef(cls); + CHECK_NULL( cls = env->FindClass(Class_Paths) ); + CHECK_NULL( SMID_Paths_cacheDirectory = env->GetStaticMethodID(cls, "cacheDirectory", "()Ljava/lang/String;") ); + env->DeleteLocalRef(cls); + CHECK_NULL( cls = env->FindClass(Class_Book) ); CHECK_NULL( FID_Book_File = env->GetFieldID(cls, "File", "Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;") ); CHECK_NULL( MID_Book_getTitle = env->GetMethodID(cls, "getTitle", "()Ljava/lang/String;") ); diff --git a/jni/NativeFormats/util/AndroidUtil.h b/jni/NativeFormats/util/AndroidUtil.h index 82afa1d47..4a7b7d057 100644 --- a/jni/NativeFormats/util/AndroidUtil.h +++ b/jni/NativeFormats/util/AndroidUtil.h @@ -37,6 +37,7 @@ public: static const char * const Class_ZLFile; static const char * const Class_NativeFormatPlugin; static const char * const Class_PluginCollection; + static const char * const Class_Paths; static const char * const Class_Book; static const char * const Class_Tag; @@ -62,6 +63,8 @@ public: static jmethodID SMID_PluginCollection_Instance; + static jmethodID SMID_Paths_cacheDirectory; + static jfieldID FID_Book_File; static jmethodID MID_Book_getTitle; static jmethodID MID_Book_getLanguage; diff --git a/jni/NativeFormats/zlibrary/core/src/image/ZLFileImage.h b/jni/NativeFormats/zlibrary/core/src/image/ZLFileImage.h new file mode 100644 index 000000000..7f299b426 --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/image/ZLFileImage.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLFILEIMAGE_H__ +#define __ZLFILEIMAGE_H__ + +#include + +#include "ZLStreamImage.h" + +class ZLFileImage : public ZLStreamImage { + +public: + ZLFileImage(const ZLFile &file, size_t offset, size_t size = 0); + + Kind kind() const; + const ZLFile &file() const; + +protected: + shared_ptr inputStream() const; + +private: + const ZLFile myFile; +}; + +inline ZLFileImage::ZLFileImage(const ZLFile &file, size_t offset, size_t size) : ZLStreamImage(file.mimeType(), offset, size), myFile(file) {} +inline ZLSingleImage::Kind ZLFileImage::kind() const { return FILE_IMAGE; } +inline const ZLFile &ZLFileImage::file() const { return myFile; } + +#endif /* __ZLFILEIMAGE_H__ */ diff --git a/jni/NativeFormats/zlibrary/core/src/image/ZLStreamImage.h b/jni/NativeFormats/zlibrary/core/src/image/ZLStreamImage.h new file mode 100644 index 000000000..6139bc1a2 --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/image/ZLStreamImage.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLSTREAMIMAGE_H__ +#define __ZLSTREAMIMAGE_H__ + +#include + +#include +#include + +class ZLStreamImage : public ZLSingleImage { + +public: + ZLStreamImage(const std::string &mimeType, size_t offset, size_t size = 0); + const shared_ptr stringData() const; + + size_t offset() const; + size_t size() const; + +private: + virtual shared_ptr inputStream() const = 0; + +private: + const size_t myOffset; + mutable size_t mySize; +}; + +inline ZLStreamImage::ZLStreamImage(const std::string &mimeType, size_t offset, size_t size) : ZLSingleImage(mimeType), myOffset(offset), mySize(size) {} +inline size_t ZLStreamImage::offset() const { return myOffset; } +inline size_t ZLStreamImage::size() const { return mySize; } + +#endif /* __ZLSTREAMIMAGE_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.cpp b/jni/NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.cpp new file mode 100644 index 000000000..81b53b4f8 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "ZLCachedMemoryAllocator.h" + + + +ZLCachedMemoryAllocator::ZLCachedMemoryAllocator(const size_t rowSize, + const std::string &directoryName, const std::string &fileExtension) : + myRowSize(rowSize), + myCurrentRowSize(0), + myOffset(0), + myHasChanges(false), + myDirectoryName(directoryName), + myFileExtension(fileExtension) { + ZLFile(directoryName).directory(true); +} + +ZLCachedMemoryAllocator::~ZLCachedMemoryAllocator() { + flush(); + for (std::vector::const_iterator it = myPool.begin(); it != myPool.end(); ++it) { + delete[] *it; + } +} + +void ZLCachedMemoryAllocator::flush() { + if (!myHasChanges) { + return; + } + char *ptr = myPool.back() + myOffset; + *ptr++ = 0; + *ptr = 0; + writeCache(myOffset + 2); + myHasChanges = false; +} + +std::string ZLCachedMemoryAllocator::makeFileName(size_t index) { + std::string name(myDirectoryName); + name.append("/"); + ZLStringUtil::appendNumber(name, index); + return name.append(".").append(myFileExtension); +} + +void ZLCachedMemoryAllocator::writeCache(size_t blockLength) { + if (myPool.size() == 0) { + return; + } + const size_t index = myPool.size() - 1; + const std::string fileName = makeFileName(index); + ZLFile file(fileName); + shared_ptr stream = file.outputStream(); + stream->open(); + stream->write(myPool[index], blockLength); + stream->close(); +} + +char *ZLCachedMemoryAllocator::allocate(size_t size) { + myHasChanges = true; + if (myPool.empty()) { + myCurrentRowSize = std::max(myRowSize, size + 2 + sizeof(char*)); + myPool.push_back(new char[myCurrentRowSize]); + } else if (myOffset + size + 2 + sizeof(char*) > myCurrentRowSize) { + myCurrentRowSize = std::max(myRowSize, size + 2 + sizeof(char*)); + char *row = new char[myCurrentRowSize]; + + char *ptr = myPool.back() + myOffset; + *ptr++ = 0; + *ptr++ = 0; + memcpy(ptr, &row, sizeof(char*)); + writeCache(myOffset + 2); + + myPool.push_back(row); + myOffset = 0; + } + char *ptr = myPool.back() + myOffset; + myOffset += size; + return ptr; +} + +char *ZLCachedMemoryAllocator::reallocateLast(char *ptr, size_t newSize) { + myHasChanges = true; + const size_t oldOffset = ptr - myPool.back(); + if (oldOffset + newSize + 2 + sizeof(char*) <= myCurrentRowSize) { + myOffset = oldOffset + newSize; + return ptr; + } else { + myCurrentRowSize = std::max(myRowSize, newSize + 2 + sizeof(char*)); + char *row = new char[myCurrentRowSize]; + memcpy(row, ptr, myOffset - oldOffset); + + *ptr++ = 0; + *ptr++ = 0; + memcpy(ptr, &row, sizeof(char*)); + writeCache(oldOffset + 2); + + myPool.push_back(row); + myOffset = newSize; + return row; + } +} diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.h b/jni/NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.h new file mode 100644 index 000000000..54f36cf98 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLCACHEDMEMORYALLOCATOR_H__ +#define __ZLCACHEDMEMORYALLOCATOR_H__ + +#include + +class ZLCachedMemoryAllocator { + +public: + ZLCachedMemoryAllocator(const size_t rowSize, const std::string &directoryName, const std::string &fileExtension); + ~ZLCachedMemoryAllocator(); + + char *allocate(size_t size); + char *reallocateLast(char *ptr, size_t newSize); + + void flush(); + + static void writeUInt16(char *ptr, uint16_t value); + static void writeUInt32(char *ptr, uint32_t value); + static uint16_t readUInt16(const char *ptr); + static uint32_t readUInt32(const char *ptr); + +public: + const std::string &directoryName() const; + const std::string &fileExtension() const; + size_t blocksNumber() const; + size_t currentBytesOffset() const; + +private: + std::string makeFileName(size_t index); + void writeCache(size_t blockLength); + +private: + const size_t myRowSize; + size_t myCurrentRowSize; + std::vector myPool; + size_t myOffset; + + bool myHasChanges; + + const std::string myDirectoryName; + const std::string myFileExtension; + +private: // disable copying + ZLCachedMemoryAllocator(const ZLCachedMemoryAllocator&); + const ZLCachedMemoryAllocator &operator = (const ZLCachedMemoryAllocator&); +}; + +inline const std::string &ZLCachedMemoryAllocator::directoryName() const { return myDirectoryName; } +inline const std::string &ZLCachedMemoryAllocator::fileExtension() const { return myFileExtension; } +inline size_t ZLCachedMemoryAllocator::blocksNumber() const { return myPool.size(); } +inline size_t ZLCachedMemoryAllocator::currentBytesOffset() const { return myOffset; } + +inline void ZLCachedMemoryAllocator::writeUInt16(char *ptr, uint16_t value) { + *ptr++ = value; + *ptr = value >> 8; +} +inline void ZLCachedMemoryAllocator::writeUInt32(char *ptr, uint32_t value) { + *ptr++ = value; + value >>= 8; + *ptr++ = value; + value >>= 8; + *ptr++ = value; + *ptr = value >> 8; +} +inline uint16_t ZLCachedMemoryAllocator::readUInt16(const char *ptr) { + const uint8_t *tmp = (const uint8_t*)ptr; + return *tmp + ((uint16_t)*(tmp + 1) << 8); +} +inline uint32_t ZLCachedMemoryAllocator::readUInt32(const char *ptr) { + const uint8_t *tmp = (const uint8_t*)ptr; + return *tmp + + ((uint32_t)*(tmp + 1) << 8) + + ((uint32_t)*(tmp + 2) << 16) + + ((uint32_t)*(tmp + 3) << 24); +} + +#endif /* __ZLCACHEDMEMORYALLOCATOR_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLHyperlinkType.h b/jni/NativeFormats/zlibrary/text/src/model/ZLHyperlinkType.h new file mode 100644 index 000000000..3c2e23132 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLHyperlinkType.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLHYPERLINKTYPE_H__ +#define __ZLHYPERLINKTYPE_H__ + +typedef unsigned char ZLHyperlinkType; + +#endif /* __ZLHYPERLINKTYPE_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.cpp b/jni/NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.cpp new file mode 100644 index 000000000..5b0c3121f --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2011-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include + +#include "ZLImageMapWriter.h" + +ZLImageMapWriter::ZLImageMapWriter(const size_t rowSize, + const std::string &directoryName, const std::string &fileExtension) : + myAllocator(rowSize, directoryName, fileExtension) { +} + + +void ZLImageMapWriter::addImage(const std::string &id, const ZLImage &image) { + const size_t dataSize = myAllocator.blocksNumber(); + const size_t bytesOffset = myAllocator.currentBytesOffset(); + + myIds.push_back(id); + myIndices.push_back((dataSize == 0) ? 0 : (dataSize - 1)); + myOffsets.push_back(bytesOffset / 2); // offset in words for future use in Java + + if (image.isSingle()) { + addSingleImageEntry((const ZLSingleImage&)image); + } else { + addMultiImageEntry((const ZLMultiImage&)image); + } +} + +void ZLImageMapWriter::addSingleImageEntry(const ZLSingleImage &image) { + ZLUnicodeUtil::Ucs2String ucs2mime; + ZLUnicodeUtil::utf8ToUcs2(ucs2mime, image.mimeType()); + const size_t mimeSize = ucs2mime.size() * 2; + + const size_t len = 4 + mimeSize; + char *address = myAllocator.allocate(len); + + char *ptr = address; + *ptr++ = image.kind(); + *ptr++ = 0; // multi ? 1 : 0 + ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2mime.size()); + memcpy(ptr + 2, &ucs2mime.front(), mimeSize); + + switch (image.kind()) { + case ZLSingleImage::BASE64_ENCODED_IMAGE: + case ZLSingleImage::REGULAR_IMAGE: + { + const shared_ptr data = image.stringData(); + size_t length = data.isNull() ? 0 : data->length(); + size_t dataSize = (length + 1) / 2; + + const size_t newlen = len + 4 + dataSize * 2; + address = myAllocator.reallocateLast(address, newlen); + ptr = address + len; + + ZLCachedMemoryAllocator::writeUInt32(ptr, dataSize); + ptr += 4; + if (length > 0) { + memcpy(ptr, data->data(), length); + ptr += length; + if (length % 2) { + *ptr++ = 0; + } + } + break; + } + case ZLSingleImage::FILE_IMAGE: + { + const ZLFileImage &fileImage = (const ZLFileImage&)image; + + ZLUnicodeUtil::Ucs2String ucs2path; + ZLUnicodeUtil::utf8ToUcs2(ucs2path, fileImage.file().path()); + const size_t pathSize = ucs2path.size() * 2; + + const size_t newlen = len + 10 + pathSize; + address = myAllocator.reallocateLast(address, newlen); + ptr = address + len; + + ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.offset()); + ptr += 4; + ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.size()); + ptr += 4; + ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2path.size()); + ptr += 2; + memcpy(ptr, &ucs2path.front(), pathSize); + ptr += pathSize; + break; + } + } +} + +void ZLImageMapWriter::addMultiImageEntry(const ZLMultiImage &image) { + const size_t len = 2; + char *address = myAllocator.allocate(len); + + char *ptr = address; + *ptr++ = 0; // kind -- N/A for multi images + *ptr++ = 1; // multi ? 1 : 0 + + // TODO: implement +} + +void ZLImageMapWriter::flush() { + myAllocator.flush(); +} diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.h b/jni/NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.h new file mode 100644 index 000000000..f24fee6fb --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLIMAGEMAPWRITER_H__ +#define __ZLIMAGEMAPWRITER_H__ + +#include + +#include +#include + +#include +#include + +class ZLImageMapWriter { + +public: + ZLImageMapWriter(const size_t rowSize, const std::string &directoryName, const std::string &fileExtension); + + void addImage(const std::string &id, const ZLImage &image); + + void flush(); + + const std::vector identifiers() const; + const std::vector indices() const; + const std::vector offsets() const; + + const ZLCachedMemoryAllocator &allocator() const; + +private: + void addSingleImageEntry(const ZLSingleImage &image); + void addMultiImageEntry(const ZLMultiImage &image); + +private: + ZLCachedMemoryAllocator myAllocator; + + std::vector myIds; + std::vector myIndices; + std::vector myOffsets; + +private: + ZLImageMapWriter(const ZLImageMapWriter &); + const ZLImageMapWriter &operator = (const ZLImageMapWriter &); +}; + +inline const std::vector ZLImageMapWriter::identifiers() const { return myIds; } +inline const std::vector ZLImageMapWriter::indices() const { return myIndices; } +inline const std::vector ZLImageMapWriter::offsets() const { return myOffsets; } +inline const ZLCachedMemoryAllocator &ZLImageMapWriter::allocator() const { return myAllocator; } + +#endif /* __ZLIMAGEMAPWRITER_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextAlignmentType.h b/jni/NativeFormats/zlibrary/text/src/model/ZLTextAlignmentType.h new file mode 100644 index 000000000..ac77bbff2 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextAlignmentType.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLTEXTALIGNMENTTYPE_H__ +#define __ZLTEXTALIGNMENTTYPE_H__ + +enum ZLTextAlignmentType { + ALIGN_UNDEFINED = 0, + ALIGN_LEFT = 1, + ALIGN_RIGHT = 2, + ALIGN_CENTER = 3, + ALIGN_JUSTIFY = 4, + ALIGN_LINESTART = 5 // left for LTR languages and right for RTL +}; + +#endif /* __ZLTEXTALIGNMENTTYPE_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextFontModifier.h b/jni/NativeFormats/zlibrary/text/src/model/ZLTextFontModifier.h new file mode 100644 index 000000000..73847a5fc --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextFontModifier.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLTEXTFONTMODIFIER_H__ +#define __ZLTEXTFONTMODIFIER_H__ + +enum ZLTextFontModifier { + FONT_MODIFIER_DEFAULT = 0, + FONT_MODIFIER_BOLD = 1 << 0, + FONT_MODIFIER_ITALIC = 1 << 1, + FONT_MODIFIER_SMALLCAPS = 1 << 2, +}; + +#endif /* __ZLTEXTFONTMODIFIER_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextKind.h b/jni/NativeFormats/zlibrary/text/src/model/ZLTextKind.h new file mode 100644 index 000000000..e6584e470 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextKind.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLTEXTKIND_H__ +#define __ZLTEXTKIND_H__ + +typedef unsigned char ZLTextKind; + +#endif /* __ZLTEXTKIND_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp new file mode 100644 index 000000000..fd2299e11 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +#include +//#include +//#include +#include + +#include "ZLTextModel.h" +#include "ZLTextParagraph.h" + +ZLTextModel::ZLTextModel(const std::string &id, const std::string &language, const size_t rowSize, + const std::string &directoryName, const std::string &fileExtension) : + myId(id), + myLanguage(language.empty() ? ZLibrary::Language() : language), + myAllocator(rowSize, directoryName, fileExtension), + myLastEntryStart(0) { +} + +ZLTextModel::~ZLTextModel() { + for (std::vector::const_iterator it = myParagraphs.begin(); it != myParagraphs.end(); ++it) { + delete *it; + } +} + +/* +bool ZLTextModel::isRtl() const { + return ZLLanguageUtil::isRTLLanguage(myLanguage); +} + +void ZLTextModel::search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const { + ZLSearchPattern pattern(text, ignoreCase); + myMarks.clear(); + + std::vector::const_iterator start = + (startIndex < myParagraphs.size()) ? myParagraphs.begin() + startIndex : myParagraphs.end(); + std::vector::const_iterator end = + (endIndex < myParagraphs.size()) ? myParagraphs.begin() + endIndex : myParagraphs.end(); + for (std::vector::const_iterator it = start; it < end; ++it) { + int offset = 0; + for (ZLTextParagraph::Iterator jt = **it; !jt.isEnd(); jt.next()) { + if (jt.entryKind() == ZLTextParagraphEntry::TEXT_ENTRY) { + const ZLTextEntry& textEntry = (ZLTextEntry&)*jt.entry(); + const char *str = textEntry.data(); + const size_t len = textEntry.dataLength(); + for (int pos = ZLSearchUtil::find(str, len, pattern); pos != -1; pos = ZLSearchUtil::find(str, len, pattern, pos + 1)) { + myMarks.push_back(ZLTextMark(it - myParagraphs.begin(), offset + pos, pattern.length())); + } + offset += len; + } + } + } +} + +void ZLTextModel::selectParagraph(size_t index) const { + if (index < paragraphsNumber()) { + myMarks.push_back(ZLTextMark(index, 0, (*this)[index]->textDataLength())); + } +} + +ZLTextMark ZLTextModel::firstMark() const { + return marks().empty() ? ZLTextMark() : marks().front(); +} + +ZLTextMark ZLTextModel::lastMark() const { + return marks().empty() ? ZLTextMark() : marks().back(); +} + +ZLTextMark ZLTextModel::nextMark(ZLTextMark position) const { + std::vector::const_iterator it = std::upper_bound(marks().begin(), marks().end(), position); + return (it != marks().end()) ? *it : ZLTextMark(); +} + +ZLTextMark ZLTextModel::previousMark(ZLTextMark position) const { + if (marks().empty()) { + return ZLTextMark(); + } + std::vector::const_iterator it = std::lower_bound(marks().begin(), marks().end(), position); + if (it == marks().end()) { + --it; + } + if (*it >= position) { + if (it == marks().begin()) { + return ZLTextMark(); + } + --it; + } + return *it; +} +*/ + +void ZLTextModel::addParagraphInternal(ZLTextParagraph *paragraph) { + checkUtf8Text(); + + const size_t dataSize = myAllocator.blocksNumber(); + const size_t bytesOffset = myAllocator.currentBytesOffset(); + + myStartEntryIndices.push_back((dataSize == 0) ? 0 : (dataSize - 1)); + myStartEntryOffsets.push_back(bytesOffset / 2); // offset in words for future use in Java + myParagraphLengths.push_back(0); + myTextSizes.push_back(myTextSizes.empty() ? 0 : myTextSizes.back()); + myParagraphKinds.push_back(paragraph->kind()); + + myParagraphs.push_back(paragraph); + myLastEntryStart = 0; +} + +ZLTextTreeModel::ZLTextTreeModel(const std::string &id, const std::string &language, + const std::string &directoryName, const std::string &fileExtension) : + ZLTextModel(id, language, 8192, directoryName, fileExtension) { + myRoot = new ZLTextTreeParagraph(); + myRoot->open(true); +} + +ZLTextTreeModel::~ZLTextTreeModel() { + delete myRoot; +} + +ZLTextTreeParagraph *ZLTextTreeModel::createParagraph(ZLTextTreeParagraph *parent) { + if (parent == 0) { + parent = myRoot; + } + ZLTextTreeParagraph *tp = new ZLTextTreeParagraph(parent); + addParagraphInternal(tp); + return tp; +} + +/* +void ZLTextTreeModel::search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const { + ZLTextModel::search(text, startIndex, endIndex, ignoreCase); + for (std::vector::const_iterator it = marks().begin(); it != marks().end(); ++it) { + ((ZLTextTreeParagraph*)(*this)[it->ParagraphIndex])->openTree(); + } +} + +void ZLTextTreeModel::selectParagraph(size_t index) const { + if (index < paragraphsNumber()) { + ZLTextModel::selectParagraph(index); + ((ZLTextTreeParagraph*)(*this)[index])->openTree(); + } +} +*/ + +ZLTextPlainModel::ZLTextPlainModel(const std::string &id, const std::string &language, const size_t rowSize, + const std::string &directoryName, const std::string &fileExtension) : + ZLTextModel(id, language, rowSize, directoryName, fileExtension) { +} + +void ZLTextPlainModel::createParagraph(ZLTextParagraph::Kind kind) { + ZLTextParagraph *paragraph = (kind == ZLTextParagraph::TEXT_PARAGRAPH) ? new ZLTextParagraph() : new ZLTextSpecialParagraph(kind); + addParagraphInternal(paragraph); +} + +void ZLTextModel::checkUtf8Text() { + if (myLastEntryStart == 0 || *myLastEntryStart != ZLTextParagraphEntry::TEXT_ENTRY + || *(myLastEntryStart + 1) == 0) { + return; + } + const size_t utf8Len = ZLCachedMemoryAllocator::readUInt32(myLastEntryStart + 2); + ZLUnicodeUtil::Ucs2String ucs2str; + ZLUnicodeUtil::utf8ToUcs2(ucs2str, myLastEntryStart + 6, utf8Len); + + const size_t newLen = ucs2str.size() * 2; + myLastEntryStart = myAllocator.reallocateLast(myLastEntryStart, newLen + 6); + + *(myLastEntryStart + 1) = 0; + ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, ucs2str.size()); + memcpy(myLastEntryStart + 6, &ucs2str.front(), newLen); + myTextSizes.back() += ucs2str.size(); +} + +void ZLTextModel::addText(const std::string &text) { + const size_t len = text.length(); + if (myLastEntryStart != 0 && *myLastEntryStart == ZLTextParagraphEntry::TEXT_ENTRY + && *(myLastEntryStart + 1) != 0) { + const size_t oldLen = ZLCachedMemoryAllocator::readUInt32(myLastEntryStart + 2); + const size_t newLen = oldLen + len; + myLastEntryStart = myAllocator.reallocateLast(myLastEntryStart, newLen + 6); + ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, newLen); + memcpy(myLastEntryStart + 6 + oldLen, text.data(), len); + } else { + myLastEntryStart = myAllocator.allocate(len + 6); + *myLastEntryStart = ZLTextParagraphEntry::TEXT_ENTRY; + *(myLastEntryStart + 1) = 1; + ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, len); + memcpy(myLastEntryStart + 6, text.data(), len); + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back(); + } +} + +void ZLTextModel::addText(const std::vector &text) { + if (text.size() == 0) { + return; + } + size_t len = 0; + for (std::vector::const_iterator it = text.begin(); it != text.end(); ++it) { + len += it->length(); + } + if (myLastEntryStart != 0 && *myLastEntryStart == ZLTextParagraphEntry::TEXT_ENTRY + && *(myLastEntryStart + 1) != 0) { + const size_t oldLen = ZLCachedMemoryAllocator::readUInt32(myLastEntryStart + 2); + const size_t newLen = oldLen + len; + myLastEntryStart = myAllocator.reallocateLast(myLastEntryStart, newLen + 6); + ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, newLen); + size_t offset = 6 + oldLen; + for (std::vector::const_iterator it = text.begin(); it != text.end(); ++it) { + memcpy(myLastEntryStart + offset, it->data(), it->length()); + offset += it->length(); + } + } else { + myLastEntryStart = myAllocator.allocate(len + 6); + *myLastEntryStart = ZLTextParagraphEntry::TEXT_ENTRY; + *(myLastEntryStart + 1) = 1; + ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, len); + size_t offset = 6; + for (std::vector::const_iterator it = text.begin(); it != text.end(); ++it) { + memcpy(myLastEntryStart + offset, it->data(), it->length()); + offset += it->length(); + } + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back(); + } +} + +void ZLTextModel::addFixedHSpace(unsigned char length) { + checkUtf8Text(); + myLastEntryStart = myAllocator.allocate(4); + *myLastEntryStart = ZLTextParagraphEntry::FIXED_HSPACE_ENTRY; + *(myLastEntryStart + 1) = 0; + *(myLastEntryStart + 2) = length; + *(myLastEntryStart + 3) = 0; + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back(); +} + +void ZLTextModel::addControl(ZLTextKind textKind, bool isStart) { + checkUtf8Text(); + myLastEntryStart = myAllocator.allocate(4); + *myLastEntryStart = ZLTextParagraphEntry::CONTROL_ENTRY; + *(myLastEntryStart + 1) = 0; + *(myLastEntryStart + 2) = textKind; + *(myLastEntryStart + 3) = isStart ? 1 : 0; + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back(); +} + +void ZLTextModel::addControl(const ZLTextStyleEntry &entry) { + /*checkUtf8Text(); + + size_t len = 10 + 2 * (ZLTextStyleEntry::NUMBER_OF_LENGTHS + + (ZLTextStyleEntry::NUMBER_OF_LENGTHS + 1) / 2); + + ZLUnicodeUtil::Ucs2String fontFamily; + size_t fontFamilyLen = 0; + if (entry.fontFamilySupported()) { + ZLUnicodeUtil::utf8ToUcs2(fontFamily, entry.fontFamily()); + fontFamilyLen = fontFamily.size() * 2; + len += 2 + fontFamilyLen; + } + + myLastEntryStart = myAllocator.allocate(len); + char *address = myLastEntryStart; + + *address++ = ZLTextParagraphEntry::STYLE_ENTRY; + *address++ = 0; + + ZLCachedMemoryAllocator::writeUInt32(address, entry.myMask); + address += 4;*/ + + // Pack myLengths array so: + // + // 1) for every two elements there is a word with those Units (two Units + // in two bytes) followed by two words with those Sizes; + // + // 2) if there is one last element (without a pair) => then another one + // word is appended with only one Unit (in the first byte) followed by + // a word containing corresponding Size. + // + /*const int lengthMinusOne = ZLTextStyleEntry::NUMBER_OF_LENGTHS - 1; + for (int i = 0; i < lengthMinusOne; i += 2) { + const ZLTextStyleEntry::LengthType &l0 = entry.myLengths[i]; + const ZLTextStyleEntry::LengthType &l1 = entry.myLengths[i + 1]; + *address++ = l0.Unit; + *address++ = l1.Unit; + ZLCachedMemoryAllocator::writeUInt16(address, l0.Size); + address += 2; + ZLCachedMemoryAllocator::writeUInt16(address, l1.Size); + address += 2; + } + if (ZLTextStyleEntry::NUMBER_OF_LENGTHS % 2) { + const ZLTextStyleEntry::LengthType &l0 = entry.myLengths[lengthMinusOne]; + *address++ = l0.Unit; + *address++ = 0; + ZLCachedMemoryAllocator::writeUInt16(address, l0.Size); + address += 2; + } + *address++ = entry.mySupportedFontModifier; + *address++ = entry.myFontModifier; + *address++ = entry.myAlignmentType; + *address++ = entry.myFontSizeMag; + if (entry.fontFamilySupported()) { + ZLCachedMemoryAllocator::writeUInt16(address, fontFamily.size()); + memcpy(address + 2, &fontFamily.front(), fontFamilyLen); + } + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back();*/ +} + +void ZLTextModel::addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label) { + checkUtf8Text(); + + ZLUnicodeUtil::Ucs2String ucs2label; + ZLUnicodeUtil::utf8ToUcs2(ucs2label, label); + + const size_t len = ucs2label.size() * 2; + + myLastEntryStart = myAllocator.allocate(len + 6); + *myLastEntryStart = ZLTextParagraphEntry::HYPERLINK_CONTROL_ENTRY; + *(myLastEntryStart + 1) = 0; + *(myLastEntryStart + 2) = textKind; + *(myLastEntryStart + 3) = hyperlinkType; + ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 4, ucs2label.size()); + memcpy(myLastEntryStart + 6, &ucs2label.front(), len); + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back(); +} + +void ZLTextModel::addImage(const std::string &id, short vOffset) { + checkUtf8Text(); + + ZLUnicodeUtil::Ucs2String ucs2id; + ZLUnicodeUtil::utf8ToUcs2(ucs2id, id); + + const size_t len = ucs2id.size() * 2; + + myLastEntryStart = myAllocator.allocate(len + 6); + *myLastEntryStart = ZLTextParagraphEntry::IMAGE_ENTRY; + *(myLastEntryStart + 1) = 0; + ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 2, vOffset); + ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 4, ucs2id.size()); + memcpy(myLastEntryStart + 6, &ucs2id.front(), len); + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back(); +} + +void ZLTextModel::addBidiReset() { + checkUtf8Text(); + myLastEntryStart = myAllocator.allocate(2); + *myLastEntryStart = ZLTextParagraphEntry::RESET_BIDI_ENTRY; + *(myLastEntryStart + 1) = 0; + myParagraphs.back()->addEntry(myLastEntryStart); + ++myParagraphLengths.back(); +} + +void ZLTextModel::flush() { + checkUtf8Text(); + myAllocator.flush(); +} diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.h b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.h new file mode 100644 index 000000000..6a290324c --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLTEXTMODEL_H__ +#define __ZLTEXTMODEL_H__ + +#include + +#include +#include +#include + +#include +#include +#include +//#include +#include + +class ZLTextParagraph; +class ZLTextTreeParagraph; + +class ZLTextModel { + +public: + enum Kind { + PLAIN_TEXT_MODEL, + TREE_MODEL, + }; + +protected: + ZLTextModel(const std::string &id, const std::string &language, const size_t rowSize, + const std::string &directoryName, const std::string &fileExtension); + +public: + virtual ~ZLTextModel(); + virtual Kind kind() const = 0; + + const std::string &id() const; + const std::string &language() const; + //bool isRtl() const; + + size_t paragraphsNumber() const; + ZLTextParagraph *operator [] (size_t index); + const ZLTextParagraph *operator [] (size_t index) const; +/* + const std::vector &marks() const; + + virtual void search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const; + virtual void selectParagraph(size_t index) const; + void removeAllMarks(); + + ZLTextMark firstMark() const; + ZLTextMark lastMark() const; + ZLTextMark nextMark(ZLTextMark position) const; + ZLTextMark previousMark(ZLTextMark position) const; +*/ + void addControl(ZLTextKind textKind, bool isStart); + void addControl(const ZLTextStyleEntry &entry); + void addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label); + void addText(const std::string &text); + void addText(const std::vector &text); + void addImage(const std::string &id, short vOffset); + void addFixedHSpace(unsigned char length); + void addBidiReset(); + + void flush(); + + const ZLCachedMemoryAllocator &allocator() const; + + const std::vector &startEntryIndices() const; + const std::vector &startEntryOffsets() const; + const std::vector ¶graphLengths() const; + const std::vector &textSizes() const; + const std::vector ¶graphKinds() const; + +protected: + void addParagraphInternal(ZLTextParagraph *paragraph); + + void checkUtf8Text(); + +private: + const std::string myId; + const std::string myLanguage; + std::vector myParagraphs; + //mutable std::vector myMarks; + mutable ZLCachedMemoryAllocator myAllocator; + + char *myLastEntryStart; + + std::vector myStartEntryIndices; + std::vector myStartEntryOffsets; + std::vector myParagraphLengths; + std::vector myTextSizes; + std::vector myParagraphKinds; + +private: + ZLTextModel(const ZLTextModel&); + const ZLTextModel &operator = (const ZLTextModel&); +}; + +class ZLTextPlainModel : public ZLTextModel { + +public: + ZLTextPlainModel(const std::string &id, const std::string &language, const size_t rowSize, + const std::string &directoryName, const std::string &fileExtension); + Kind kind() const; + void createParagraph(ZLTextParagraph::Kind kind); +}; + +class ZLTextTreeModel : public ZLTextModel { + +public: + ZLTextTreeModel(const std::string &id, const std::string &language, + const std::string &directoryName, const std::string &fileExtension); + ~ZLTextTreeModel(); + Kind kind() const; + + ZLTextTreeParagraph *createParagraph(ZLTextTreeParagraph *parent = 0); + + void search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const; + void selectParagraph(size_t index) const; + +private: + ZLTextTreeParagraph *myRoot; +}; + +inline const std::string &ZLTextModel::id() const { return myId; } +inline const std::string &ZLTextModel::language() const { return myLanguage; } +inline size_t ZLTextModel::paragraphsNumber() const { return myParagraphs.size(); } +//inline const std::vector &ZLTextModel::marks() const { return myMarks; } +//inline void ZLTextModel::removeAllMarks() { myMarks.clear(); } +inline const ZLCachedMemoryAllocator &ZLTextModel::allocator() const { return myAllocator; } +inline const std::vector &ZLTextModel::startEntryIndices() const { return myStartEntryIndices; } +inline const std::vector &ZLTextModel::startEntryOffsets() const { return myStartEntryOffsets; } +inline const std::vector &ZLTextModel::paragraphLengths() const { return myParagraphLengths; }; +inline const std::vector &ZLTextModel::textSizes() const { return myTextSizes; }; +inline const std::vector &ZLTextModel::paragraphKinds() const { return myParagraphKinds; }; + +inline ZLTextParagraph *ZLTextModel::operator [] (size_t index) { + return myParagraphs[std::min(myParagraphs.size() - 1, index)]; +} + +inline const ZLTextParagraph *ZLTextModel::operator [] (size_t index) const { + return myParagraphs[std::min(myParagraphs.size() - 1, index)]; +} + +inline ZLTextModel::Kind ZLTextPlainModel::kind() const { return PLAIN_TEXT_MODEL; } + +inline ZLTextModel::Kind ZLTextTreeModel::kind() const { return TREE_MODEL; } + +#endif /* __ZLTEXTMODEL_H__ */ diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp b/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp new file mode 100644 index 000000000..3b32bd302 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include + +#include +#include + +#include "ZLCachedMemoryAllocator.h" +#include "ZLTextParagraph.h" + + +const shared_ptr ResetBidiEntry::Instance = new ResetBidiEntry(); + +short ZLTextStyleEntry::length(Length name, const Metrics &metrics) const { + switch (myLengths[name].Unit) { + default: + case SIZE_UNIT_PIXEL: + return myLengths[name].Size; + case SIZE_UNIT_EM_100: + return (myLengths[name].Size * metrics.FontSize + 50) / 100; + case SIZE_UNIT_EX_100: + return (myLengths[name].Size * metrics.FontXHeight + 50) / 100; + case SIZE_UNIT_PERCENT: + switch (name) { + default: + case LENGTH_LEFT_INDENT: + case LENGTH_RIGHT_INDENT: + case LENGTH_FIRST_LINE_INDENT_DELTA: + return (myLengths[name].Size * metrics.FullWidth + 50) / 100; + case LENGTH_SPACE_BEFORE: + case LENGTH_SPACE_AFTER: + return (myLengths[name].Size * metrics.FullHeight + 50) / 100; + } + } +} + +ZLTextStyleEntry::ZLTextStyleEntry(char *address) { + myMask = ZLCachedMemoryAllocator::readUInt32(address); + address += 4; + + const int lengthMinusOne = ZLTextStyleEntry::NUMBER_OF_LENGTHS - 1; + for (int i = 0; i < lengthMinusOne; i += 2) { + ZLTextStyleEntry::LengthType &l0 = myLengths[i]; + ZLTextStyleEntry::LengthType &l1 = myLengths[i + 1]; + l0.Unit = (SizeUnit)*address++; + l1.Unit = (SizeUnit)*address++; + l0.Size = ZLCachedMemoryAllocator::readUInt16(address); + address += 2; + l1.Size = ZLCachedMemoryAllocator::readUInt16(address); + address += 2; + } + if (ZLTextStyleEntry::NUMBER_OF_LENGTHS % 2) { + ZLTextStyleEntry::LengthType &l0 = myLengths[lengthMinusOne]; + l0.Unit = (SizeUnit)*address; + address += 2; + l0.Size = ZLCachedMemoryAllocator::readUInt16(address); + address += 2; + } + mySupportedFontModifier = *address++; + myFontModifier = *address++; + myAlignmentType = (ZLTextAlignmentType)*address++; + myFontSizeMag = *address++; + if (fontFamilySupported()) { + const size_t len = ZLCachedMemoryAllocator::readUInt16(address); + ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 2); + ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len); + ZLUnicodeUtil::ucs2ToUtf8(myFontFamily, ucs2str); + } +} + +ZLTextControlEntryPool ZLTextControlEntryPool::Pool; + +shared_ptr ZLTextControlEntryPool::controlEntry(ZLTextKind kind, bool isStart) { + std::map > &entries = isStart ? myStartEntries : myEndEntries; + std::map >::iterator it = entries.find(kind); + if (it != entries.end()) { + return it->second; + } + shared_ptr entry = new ZLTextControlEntry(kind, isStart); + entries[kind] = entry; + return entry; +} + +ZLTextHyperlinkControlEntry::ZLTextHyperlinkControlEntry(const char *address) : ZLTextControlEntry((ZLTextKind)*address, true), myHyperlinkType((ZLHyperlinkType)*(address + 1)) { + const size_t len = ZLCachedMemoryAllocator::readUInt16(address + 2); + ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 4); + ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len); + ZLUnicodeUtil::ucs2ToUtf8(myLabel, ucs2str); +} + +ZLTextEntry::ZLTextEntry(const char *address) { + const size_t len = ZLCachedMemoryAllocator::readUInt32(address); + ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 4); + ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len); + ZLUnicodeUtil::ucs2ToUtf8(myText, ucs2str); +} + +ImageEntry::ImageEntry(const char *address) { + myVOffset = ZLCachedMemoryAllocator::readUInt16(address); + const size_t len = ZLCachedMemoryAllocator::readUInt16(address + 2); + ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 4); + ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len); + ZLUnicodeUtil::ucs2ToUtf8(myId, ucs2str); +} + + +const shared_ptr ZLTextParagraph::Iterator::entry() const { + if (myEntry.isNull()) { + switch (*myPointer) { + case ZLTextParagraphEntry::TEXT_ENTRY: + myEntry = new ZLTextEntry(myPointer + 2); + break; + case ZLTextParagraphEntry::CONTROL_ENTRY: + myEntry = ZLTextControlEntryPool::Pool.controlEntry( + (ZLTextKind)*(myPointer + 2), *(myPointer + 3) != 0); + break; + case ZLTextParagraphEntry::HYPERLINK_CONTROL_ENTRY: + myEntry = new ZLTextHyperlinkControlEntry(myPointer + 2); + break; + case ZLTextParagraphEntry::IMAGE_ENTRY: + myEntry = new ImageEntry(myPointer + 2); + break; + case ZLTextParagraphEntry::STYLE_ENTRY: + myEntry = new ZLTextStyleEntry(myPointer + 2); + break; + case ZLTextParagraphEntry::FIXED_HSPACE_ENTRY: + myEntry = new ZLTextFixedHSpaceEntry(*(myPointer + 2)); + break; + case ZLTextParagraphEntry::RESET_BIDI_ENTRY: + myEntry = ResetBidiEntry::Instance; + break; + } + } + return myEntry; +} + +void ZLTextParagraph::Iterator::next() { + ++myIndex; + myEntry = 0; + if (myIndex != myEndIndex) { + switch (*myPointer) { + case ZLTextParagraphEntry::TEXT_ENTRY: + { + const size_t len = ZLCachedMemoryAllocator::readUInt32(myPointer + 2); + myPointer += len * 2 + 6; + break; + } + case ZLTextParagraphEntry::CONTROL_ENTRY: + myPointer += 4; + break; + case ZLTextParagraphEntry::HYPERLINK_CONTROL_ENTRY: + { + const size_t len = ZLCachedMemoryAllocator::readUInt16(myPointer + 4); + myPointer += len * 2 + 6; + break; + } + case ZLTextParagraphEntry::IMAGE_ENTRY: + { + const size_t len = ZLCachedMemoryAllocator::readUInt16(myPointer + 4); + myPointer += len * 2 + 6; + break; + } + case ZLTextParagraphEntry::STYLE_ENTRY: + { + unsigned int mask = ZLCachedMemoryAllocator::readUInt32(myPointer + 2); + bool withFontFamily = (mask & ZLTextStyleEntry::SUPPORT_FONT_FAMILY) == ZLTextStyleEntry::SUPPORT_FONT_FAMILY; + + myPointer += 10 + 2 * (ZLTextStyleEntry::NUMBER_OF_LENGTHS + + (ZLTextStyleEntry::NUMBER_OF_LENGTHS + 1) / 2); + if (withFontFamily) { + const size_t len = ZLCachedMemoryAllocator::readUInt16(myPointer); + myPointer += 2 + 2 * len; + } + break; + } + case ZLTextParagraphEntry::FIXED_HSPACE_ENTRY: + myPointer += 4; + break; + case ZLTextParagraphEntry::RESET_BIDI_ENTRY: + myPointer += 2; + break; + } + if (*myPointer == 0) { + memcpy(&myPointer, myPointer + 1, sizeof(char*)); + } + } +} + +size_t ZLTextParagraph::textDataLength() const { + size_t len = 0; + for (Iterator it = *this; !it.isEnd(); it.next()) { + if (it.entryKind() == ZLTextParagraphEntry::TEXT_ENTRY) { + len += ((ZLTextEntry&)*it.entry()).dataLength(); + } + } + return len; +} + +size_t ZLTextParagraph::characterNumber() const { + size_t len = 0; + for (Iterator it = *this; !it.isEnd(); it.next()) { + switch (it.entryKind()) { + case ZLTextParagraphEntry::TEXT_ENTRY: + { + const ZLTextEntry &entry = (ZLTextEntry&)*it.entry(); + len += ZLUnicodeUtil::utf8Length(entry.data(), entry.dataLength()); + break; + } + case ZLTextParagraphEntry::IMAGE_ENTRY: + len += 100; + break; + default: + break; + } + } + return len; +} + + +ZLTextTreeParagraph::ZLTextTreeParagraph(ZLTextTreeParagraph *parent) : myIsOpen(false), myParent(parent) { + if (parent != 0) { + parent->addChild(this); + myDepth = parent->myDepth + 1; + } else { + myDepth = 0; + } +} + +void ZLTextTreeParagraph::openTree() { + for (ZLTextTreeParagraph *p = parent(); p != 0; p = p->parent()) { + p->open(true); + } +} + +void ZLTextTreeParagraph::removeFromParent() { + if (myParent != 0) { + myParent->myChildren.erase(std::find(myParent->myChildren.begin(), myParent->myChildren.end(), this)); + } +} + +int ZLTextTreeParagraph::fullSize() const { + int size = 1; + for (std::vector::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it) { + size += (*it)->fullSize(); + } + return size; +} diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.h b/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.h new file mode 100644 index 000000000..6ddb4cff9 --- /dev/null +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.h @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLTEXTPARAGRAPH_H__ +#define __ZLTEXTPARAGRAPH_H__ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +class ZLImage; +typedef std::map > ZLImageMap; + +class ZLTextParagraphEntry { + +public: + enum Kind { + TEXT_ENTRY = 1, + IMAGE_ENTRY = 2, + CONTROL_ENTRY = 3, + HYPERLINK_CONTROL_ENTRY = 4, + STYLE_ENTRY = 5, + FIXED_HSPACE_ENTRY = 6, + RESET_BIDI_ENTRY = 7, + }; + +protected: + ZLTextParagraphEntry(); + +public: + virtual ~ZLTextParagraphEntry(); + +private: // disable copying + ZLTextParagraphEntry(const ZLTextParagraphEntry &entry); + const ZLTextParagraphEntry &operator = (const ZLTextParagraphEntry &entry); +}; + +class ZLTextStyleEntry : public ZLTextParagraphEntry { + +public: + enum SizeUnit { + SIZE_UNIT_PIXEL, + SIZE_UNIT_EM_100, + SIZE_UNIT_EX_100, + SIZE_UNIT_PERCENT + }; + + struct Metrics { + Metrics(int fontSize, int fontXHeight, int fullWidth, int fullHeight); + + int FontSize; + int FontXHeight; + int FullWidth; + int FullHeight; + }; + + enum Length { + LENGTH_LEFT_INDENT = 0, + LENGTH_RIGHT_INDENT = 1, + LENGTH_FIRST_LINE_INDENT_DELTA = 2, + LENGTH_SPACE_BEFORE = 3, + LENGTH_SPACE_AFTER = 4, + NUMBER_OF_LENGTHS = 5, + }; + +private: + struct LengthType { + SizeUnit Unit; + short Size; + }; + +public: + ZLTextStyleEntry(); + ZLTextStyleEntry(char *address); + ~ZLTextStyleEntry(); + + bool isEmpty() const; + + bool lengthSupported(Length name) const; + short length(Length name, const Metrics &metrics) const; + void setLength(Length name, short length, SizeUnit unit); + + bool alignmentTypeSupported() const; + ZLTextAlignmentType alignmentType() const; + void setAlignmentType(ZLTextAlignmentType alignmentType); + + unsigned char supportedFontModifier() const; + unsigned char fontModifier() const; + void setFontModifier(ZLTextFontModifier style, bool set); + + bool fontSizeSupported() const; + signed char fontSizeMag() const; + void setFontSizeMag(signed char fontSizeMag); + + bool fontFamilySupported() const; + const std::string &fontFamily() const; + void setFontFamily(const std::string &fontFamily); + + static const unsigned int SUPPORT_ALIGNMENT_TYPE = 1U << NUMBER_OF_LENGTHS; + static const unsigned int SUPPORT_FONT_SIZE = 1U << (NUMBER_OF_LENGTHS + 1); + static const unsigned int SUPPORT_FONT_FAMILY = 1U << (NUMBER_OF_LENGTHS + 2); + +private: + unsigned int myMask; + + LengthType myLengths[NUMBER_OF_LENGTHS]; + + ZLTextAlignmentType myAlignmentType; + unsigned char mySupportedFontModifier; + unsigned char myFontModifier; + signed char myFontSizeMag; + std::string myFontFamily; + +friend class ZLTextModel; +}; + +class ZLTextControlEntry : public ZLTextParagraphEntry { + +protected: + ZLTextControlEntry(ZLTextKind kind, bool isStart); + +public: + virtual ~ZLTextControlEntry(); + ZLTextKind kind() const; + bool isStart() const; + virtual bool isHyperlink() const; + +private: + ZLTextKind myKind; + bool myStart; + +friend class ZLTextControlEntryPool; +}; + +class ZLTextControlEntryPool { + +public: + static ZLTextControlEntryPool Pool; + +public: + ZLTextControlEntryPool(); + ~ZLTextControlEntryPool(); + shared_ptr controlEntry(ZLTextKind kind, bool isStart); + +private: + std::map > myStartEntries; + std::map > myEndEntries; +}; + +class ZLTextFixedHSpaceEntry : public ZLTextParagraphEntry { + +public: + ZLTextFixedHSpaceEntry(unsigned char length); + unsigned char length() const; + +private: + const unsigned char myLength; +}; + +class ZLTextHyperlinkControlEntry : public ZLTextControlEntry { + +public: + ZLTextHyperlinkControlEntry(const char *address); + ~ZLTextHyperlinkControlEntry(); + const std::string &label() const; + ZLHyperlinkType hyperlinkType() const; + bool isHyperlink() const; + +private: + std::string myLabel; + ZLHyperlinkType myHyperlinkType; +}; + +class ZLTextEntry : public ZLTextParagraphEntry { + +public: + ZLTextEntry(const char *address); + ~ZLTextEntry(); + + size_t dataLength() const; + const char *data() const; + +private: + std::string myText; +}; + +class ImageEntry : public ZLTextParagraphEntry { + +public: + ImageEntry(const char *address); + ~ImageEntry(); + const std::string &id() const; + short vOffset() const; + +private: + std::string myId; + short myVOffset; +}; + +class ResetBidiEntry : public ZLTextParagraphEntry { + +public: + static const shared_ptr Instance; + +private: + ResetBidiEntry(); +}; + +class ZLTextParagraph { + +public: + class Iterator { + + public: + Iterator(const ZLTextParagraph ¶graph); + ~Iterator(); + + bool isEnd() const; + void next(); + const shared_ptr entry() const; + ZLTextParagraphEntry::Kind entryKind() const; + + private: + char *myPointer; + size_t myIndex; + size_t myEndIndex; + mutable shared_ptr myEntry; + }; + + enum Kind { + TEXT_PARAGRAPH, + TREE_PARAGRAPH, + EMPTY_LINE_PARAGRAPH, + BEFORE_SKIP_PARAGRAPH, + AFTER_SKIP_PARAGRAPH, + END_OF_SECTION_PARAGRAPH, + END_OF_TEXT_PARAGRAPH, + }; + +protected: + ZLTextParagraph(); + +public: + virtual ~ZLTextParagraph(); + virtual Kind kind() const; + + size_t entryNumber() const; + + size_t textDataLength() const; + size_t characterNumber() const; + +private: + void addEntry(char *address); + +private: + char *myFirstEntryAddress; + size_t myEntryNumber; + +friend class Iterator; +friend class ZLTextModel; +friend class ZLTextPlainModel; +}; + +class ZLTextSpecialParagraph : public ZLTextParagraph { + +private: + ZLTextSpecialParagraph(Kind kind); + +public: + ~ZLTextSpecialParagraph(); + Kind kind() const; + +private: + Kind myKind; + +friend class ZLTextPlainModel; +}; + +class ZLTextTreeParagraph : public ZLTextParagraph { + +public: + ZLTextTreeParagraph(ZLTextTreeParagraph *parent = 0); + ~ZLTextTreeParagraph(); + Kind kind() const; + + bool isOpen() const; + void open(bool o); + void openTree(); + int depth() const; + ZLTextTreeParagraph *parent(); + const ZLTextTreeParagraph *parent() const; + const std::vector &children() const; + int fullSize() const; + + void removeFromParent(); + +private: + void addChild(ZLTextTreeParagraph *child); + +private: + bool myIsOpen; + int myDepth; + ZLTextTreeParagraph *myParent; + std::vector myChildren; +}; + +inline ZLTextParagraphEntry::ZLTextParagraphEntry() {} +inline ZLTextParagraphEntry::~ZLTextParagraphEntry() {} + +inline ZLTextStyleEntry::ZLTextStyleEntry() : myMask(0), myAlignmentType(ALIGN_UNDEFINED), mySupportedFontModifier(0), myFontModifier(0), myFontSizeMag(0) {} +inline ZLTextStyleEntry::~ZLTextStyleEntry() {} + +inline ZLTextStyleEntry::Metrics::Metrics(int fontSize, int fontXHeight, int fullWidth, int fullHeight) : FontSize(fontSize), FontXHeight(fontXHeight), FullWidth(fullWidth), FullHeight(fullHeight) {} + +inline bool ZLTextStyleEntry::isEmpty() const { return myMask == 0; } + +inline bool ZLTextStyleEntry::lengthSupported(Length name) const { return (myMask & (1U << name)) != 0; } +inline void ZLTextStyleEntry::setLength(Length name, short length, SizeUnit unit) { + myLengths[name].Size = length; + myLengths[name].Unit = unit; + myMask |= 1U << name; +} + +inline bool ZLTextStyleEntry::alignmentTypeSupported() const { return (myMask & SUPPORT_ALIGNMENT_TYPE) == SUPPORT_ALIGNMENT_TYPE; } +inline ZLTextAlignmentType ZLTextStyleEntry::alignmentType() const { return myAlignmentType; } +inline void ZLTextStyleEntry::setAlignmentType(ZLTextAlignmentType alignmentType) { myAlignmentType = alignmentType; myMask |= SUPPORT_ALIGNMENT_TYPE; } + +inline unsigned char ZLTextStyleEntry::supportedFontModifier() const { return mySupportedFontModifier; } +inline unsigned char ZLTextStyleEntry::fontModifier() const { return myFontModifier; } +inline void ZLTextStyleEntry::setFontModifier(ZLTextFontModifier style, bool set) { + if (set) { + myFontModifier |= style; + } else { + myFontModifier &= ~style; + } + mySupportedFontModifier |= style; +} + +inline bool ZLTextStyleEntry::fontSizeSupported() const { return (myMask & SUPPORT_FONT_SIZE) == SUPPORT_FONT_SIZE; } +inline signed char ZLTextStyleEntry::fontSizeMag() const { return myFontSizeMag; } +inline void ZLTextStyleEntry::setFontSizeMag(signed char fontSizeMag) { myFontSizeMag = fontSizeMag; myMask |= SUPPORT_FONT_SIZE; } + +inline bool ZLTextStyleEntry::fontFamilySupported() const { return (myMask & SUPPORT_FONT_FAMILY) == SUPPORT_FONT_FAMILY; } +inline const std::string &ZLTextStyleEntry::fontFamily() const { return myFontFamily; } +inline void ZLTextStyleEntry::setFontFamily(const std::string &fontFamily) { myFontFamily = fontFamily; myMask |= SUPPORT_FONT_FAMILY; } + +inline ZLTextControlEntry::ZLTextControlEntry(ZLTextKind kind, bool isStart) : myKind(kind), myStart(isStart) {} +inline ZLTextControlEntry::~ZLTextControlEntry() {} +inline ZLTextKind ZLTextControlEntry::kind() const { return myKind; } +inline bool ZLTextControlEntry::isStart() const { return myStart; } +inline bool ZLTextControlEntry::isHyperlink() const { return false; } + +inline ZLTextFixedHSpaceEntry::ZLTextFixedHSpaceEntry(unsigned char length) : myLength(length) {} +inline unsigned char ZLTextFixedHSpaceEntry::length() const { return myLength; } + +inline ZLTextControlEntryPool::ZLTextControlEntryPool() {} +inline ZLTextControlEntryPool::~ZLTextControlEntryPool() {} + +inline ZLTextHyperlinkControlEntry::~ZLTextHyperlinkControlEntry() {} +inline const std::string &ZLTextHyperlinkControlEntry::label() const { return myLabel; } +inline ZLHyperlinkType ZLTextHyperlinkControlEntry::hyperlinkType() const { return myHyperlinkType; } +inline bool ZLTextHyperlinkControlEntry::isHyperlink() const { return true; } + +inline ZLTextEntry::~ZLTextEntry() {} +inline const char *ZLTextEntry::data() const { return myText.data(); } +inline size_t ZLTextEntry::dataLength() const { return myText.length(); } + +inline ImageEntry::~ImageEntry() {} +inline const std::string &ImageEntry::id() const { return myId; } +inline short ImageEntry::vOffset() const { return myVOffset; } + +inline ResetBidiEntry::ResetBidiEntry() {} + +inline ZLTextParagraph::ZLTextParagraph() : myEntryNumber(0) {} +inline ZLTextParagraph::~ZLTextParagraph() {} +inline ZLTextParagraph::Kind ZLTextParagraph::kind() const { return TEXT_PARAGRAPH; } +inline size_t ZLTextParagraph::entryNumber() const { return myEntryNumber; } +inline void ZLTextParagraph::addEntry(char *address) { if (myEntryNumber == 0) myFirstEntryAddress = address; ++myEntryNumber; } + +inline ZLTextParagraph::Iterator::Iterator(const ZLTextParagraph ¶graph) : myPointer(paragraph.myFirstEntryAddress), myIndex(0), myEndIndex(paragraph.entryNumber()) {} +inline ZLTextParagraph::Iterator::~Iterator() {} +inline bool ZLTextParagraph::Iterator::isEnd() const { return myIndex == myEndIndex; } +inline ZLTextParagraphEntry::Kind ZLTextParagraph::Iterator::entryKind() const { return (ZLTextParagraphEntry::Kind)*myPointer; } + +inline ZLTextSpecialParagraph::ZLTextSpecialParagraph(Kind kind) : myKind(kind) {} +inline ZLTextSpecialParagraph::~ZLTextSpecialParagraph() {} +inline ZLTextParagraph::Kind ZLTextSpecialParagraph::kind() const { return myKind; } + +inline ZLTextTreeParagraph::~ZLTextTreeParagraph() {} +inline ZLTextParagraph::Kind ZLTextTreeParagraph::kind() const { return TREE_PARAGRAPH; } +inline bool ZLTextTreeParagraph::isOpen() const { return myIsOpen; } +inline void ZLTextTreeParagraph::open(bool o) { myIsOpen = o; } +inline int ZLTextTreeParagraph::depth() const { return myDepth; } +inline ZLTextTreeParagraph *ZLTextTreeParagraph::parent() { return myParent; } +inline const ZLTextTreeParagraph *ZLTextTreeParagraph::parent() const { return myParent; } +inline const std::vector &ZLTextTreeParagraph::children() const { return myChildren; } +inline void ZLTextTreeParagraph::addChild(ZLTextTreeParagraph *child) { myChildren.push_back(child); } + +#endif /* __ZLTEXTPARAGRAPH_H__ */ diff --git a/proguard.cfg b/proguard.cfg index 17ba868f5..3e0a0c2ef 100755 --- a/proguard.cfg +++ b/proguard.cfg @@ -31,6 +31,10 @@ -keepclassmembers class org.geometerplus.fbreader.formats.PluginCollection { public static ** Instance(); } +-keep class org.geometerplus.fbreader.Paths +-keepclassmembers class org.geometerplus.fbreader.Paths { + public static ** cacheDirectory(); +} -keep class org.geometerplus.fbreader.library.Book -keepclassmembers class org.geometerplus.fbreader.library.Book { public ** File;