diff --git a/Fb2File/Fb2File.cpp b/Fb2File/Fb2File.cpp index 371d4a71bd..3bb01e1db1 100644 --- a/Fb2File/Fb2File.cpp +++ b/Fb2File/Fb2File.cpp @@ -126,20 +126,19 @@ class CFb2File_Private { public: XmlUtils::CXmlLiteReader m_oLightReader; // SAX Reader - std::wstring m_sFile; // Имя файла - std::wstring m_sDstFolder; // Путь к результату STitleInfo m_oTitleInfo; // Данные о книге SDocumentInfo m_oDocumentInfo; // Информация об fb2-документе NSStringUtils::CStringBuilder m_oBuilder; // Текст + std::wstring m_sTmpFolder; // Рабочая папка int m_nImageId; // ID картинки - int m_nHyperLinkId; // ID ссылки + int m_nFootnoteId; // ID ссылки STitleInfo* m_pSrcTitleInfo; // Данные об исходнике книги SPublishInfo* m_pPublishInfo; // Сведения об издании книги - std::map m_mXmlns; // Ссылки - std::map m_mImage; // Картинки + std::map m_mFootnotes; // Ссылки + std::map m_mImages; // Картинки std::map m_mCustomInfo; // Произвольная информация public: @@ -148,14 +147,14 @@ public: m_pSrcTitleInfo = NULL; m_pPublishInfo = NULL; m_nImageId = 1; - m_nHyperLinkId = 1; + m_nFootnoteId = 1; } ~CFb2File_Private() { m_oLightReader.Clear(); - m_mXmlns.clear(); - m_mImage.clear(); + m_mFootnotes.clear(); + m_mImages.clear(); m_mCustomInfo.clear(); if(m_pSrcTitleInfo) delete m_pSrcTitleInfo; @@ -204,7 +203,7 @@ public: // Читает image // НЕ имеет право писать p - bool readImage() + bool readImage(NSStringUtils::CStringBuilder& oBuilder) { // Читаем href std::wstring sImageName = L""; @@ -224,36 +223,36 @@ public: // Пишем image в файл std::wstring sImageId = std::to_wstring(m_nImageId); - m_oBuilder += L""; + oBuilder += L""; // extent // РАЗМЕРЫ КАРТИНКИ - m_oBuilder += L""; + oBuilder += L""; // docPr - m_oBuilder += L""; + oBuilder += L""; // graphic - m_oBuilder += L""; + oBuilder += L""; // pic:nvPicPr - m_oBuilder += L""; + oBuilder += L""; // pic:blipFill // РЕЛЬСЫ rPic + id - m_oBuilder += L""; + oBuilder += L""; // pic:spPr - m_oBuilder += L""; + oBuilder += L""; // РАЗМЕРЫ КАРТИНКИ - m_oBuilder += L""; - m_oBuilder += L""; + oBuilder += L""; + oBuilder += L""; - m_oBuilder += L""; + oBuilder += L""; // Конец записи - m_oBuilder += L""; + oBuilder += L""; - m_mImage.insert(std::make_pair(sImageName, L"rPic" + sImageId)); + m_mImages.insert(std::make_pair(sImageName, L"rPic" + sImageId)); m_nImageId++; return true; } @@ -274,7 +273,7 @@ public: std::wstring sName = m_oLightReader.GetName(); if(sName == L"p") { - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; } else if(sName == L"empty-line") @@ -300,7 +299,7 @@ public: { m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } @@ -334,7 +333,7 @@ public: return false; m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } while(m_oLightReader.ReadNextSiblingNode(nDeath)); @@ -345,7 +344,7 @@ public: // Читает p // НЕ имеет право писать p // sRStyle - накопленный стиль - bool readP(std::wstring sRStyle) + bool readP(std::wstring sRStyle, NSStringUtils::CStringBuilder& oBuilder) { // Читаем id, style, xml:lang /* @@ -361,28 +360,28 @@ public: // Читаем обычный текст if(sName == L"#text") { - m_oBuilder += L""; + oBuilder += L""; // Стиль текста - m_oBuilder += L""; - m_oBuilder += sRStyle; - m_oBuilder += L""; + oBuilder += L""; + oBuilder += sRStyle; + oBuilder += L""; // Сам текст - m_oBuilder += L""; - m_oBuilder += m_oLightReader.GetText(); - m_oBuilder += L""; - m_oBuilder += L""; + oBuilder += L""; + oBuilder += m_oLightReader.GetText(); + oBuilder += L""; + oBuilder += L""; } // Читаем полужирный текст else if (sName == L"strong") { - if(!readP(sRStyle + L"")) + if(!readP(sRStyle + L"", oBuilder)) return false; } // Читаем курсивный текст else if(sName == L"emphasis") { - if(!readP(sRStyle + L"")) + if(!readP(sRStyle + L"", oBuilder)) return false; } // Читаем стилизованный текст @@ -390,7 +389,7 @@ public: { // ИГНОРИРУЕМ // if(!readP(true, sRStyle + L"")) - if(!readP(sRStyle)) + if(!readP(sRStyle, oBuilder)) return false; } // Читаем ссылку @@ -412,39 +411,50 @@ public: return false; m_oLightReader.MoveToElement(); - // БУДУ РЕАЛИЗОВЫВАТЬ КАК footnoteReference - - if(!readP(sRStyle)) + // Читаем текст внутри ссылки + if(!readP(sRStyle, oBuilder)) return false; + + // Пишем ссылку + std::wstring sFootnoteId = std::to_wstring(m_nFootnoteId); + oBuilder += L""; + // Стиль ссылки + oBuilder += L""; + oBuilder += L""; + + m_mFootnotes.insert(std::make_pair(sHyperName, sFootnoteId)); + m_nFootnoteId++; } // Читаем вычеркнутый текст else if(sName == L"strikethrough") { - if(!readP(sRStyle + L"")) + if(!readP(sRStyle + L"", oBuilder)) return false; } // Читает нижний текст else if(sName == L"sub") { - if(!readP(sRStyle + L"")) + if(!readP(sRStyle + L"", oBuilder)) return false; } // Читает верхний текст else if(sName == L"sup") { - if(!readP(sRStyle + L"")) + if(!readP(sRStyle + L"", oBuilder)) return false; } // Читает код else if(sName == L"code") { - if(!readP(sRStyle + L"")) + if(!readP(sRStyle + L"", oBuilder)) return false; } // Читает картинку в тексте else if(sName == L"image") { - if(!readImage()) + if(!readImage(oBuilder)) return false; } else @@ -513,7 +523,7 @@ public: { m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; if(!m_oLightReader.ReadNextSiblingNode(nSDeath)) @@ -529,7 +539,7 @@ public: return false; m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } while(m_oLightReader.ReadNextSiblingNode(nSDeath)); @@ -544,7 +554,7 @@ public: break; m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } while(m_oLightReader.ReadNextSiblingNode(nDeath)); @@ -576,7 +586,7 @@ public: { m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } @@ -584,7 +594,7 @@ public: { m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } @@ -614,7 +624,7 @@ public: return false; m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } while(m_oLightReader.ReadNextSiblingNode(nDeath)); @@ -645,14 +655,14 @@ public: if(m_oLightReader.GetName() == L"th") { // m_sBody += L"th\n"; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; } // Читаем td (любое) else if(m_oLightReader.GetName() == L"td") { // m_sBody += L"td\n"; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; } else @@ -674,7 +684,7 @@ public: std::wstring sAnName = m_oLightReader.GetName(); if(sAnName == L"p") { - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; } else if(sAnName == L"poem") @@ -690,7 +700,7 @@ public: else if(sAnName == L"subtitle") { m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; } else if(sAnName == L"empty-line") @@ -741,7 +751,7 @@ public: { m_oBuilder += L""; m_oBuilder += L""; - if(!readImage()) + if(!readImage(m_oBuilder)) return false; m_oBuilder += L""; if(!m_oLightReader.ReadNextSiblingNode(nDeath)) @@ -781,7 +791,7 @@ public: // Стиль section-p m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } @@ -790,7 +800,7 @@ public: // Стиль section-image m_oBuilder += L""; m_oBuilder += L""; - if(!readImage()) + if(!readImage(m_oBuilder)) return false; m_oBuilder += L""; } @@ -804,7 +814,7 @@ public: // Стиль section-subtitle m_oBuilder += L""; m_oBuilder += L""; - if(!readP(L"")) + if(!readP(L"", m_oBuilder)) return false; m_oBuilder += L""; } @@ -844,7 +854,7 @@ public: { m_oBuilder += L""; m_oBuilder += L""; - if(!readImage()) + if(!readImage(m_oBuilder)) return false; m_oBuilder += L""; if(!m_oLightReader.ReadNextSiblingNode(nDeath)) @@ -888,6 +898,57 @@ public: return true; } + // Читает body с именем notes + bool readNotes(NSStringUtils::CStringBuilder& oFootnotes) + { + int nFootnote = 1; + int nDepth = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nDepth)) + { + // Читаем section (один или более) + if(m_oLightReader.GetName() == L"section") + { + // Читаем id + std::wstring sFootnoteName = L""; + while(m_oLightReader.MoveToNextAttribute()) + { + if(m_oLightReader.GetName() == L"id") + { + sFootnoteName = m_oLightReader.GetText(); + break; + } + } + if(sFootnoteName == L"") + return false; + m_oLightReader.MoveToElement(); + + // Пишем сноску + oFootnotes += L""; + + // Читаем внутренность section + int nSDepth = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nSDepth)) + { + if(m_oLightReader.GetName() == L"p") + { + // Стиль section-p + oFootnotes += L""; + oFootnotes += L""; + oFootnotes += L""; + if(!readP(L"", oFootnotes)) + return false; + oFootnotes += L""; + } + } + + oFootnotes += L""; + } + } + return true; + } + // Читает custom-info bool getCustomInfo() { @@ -1151,7 +1212,7 @@ public: return false; m_oBuilder += L""; m_oBuilder += L""; - if(!readImage()) + if(!readImage(m_oBuilder)) return false; m_oBuilder += L""; } @@ -1237,22 +1298,22 @@ CFb2File::~CFb2File() // Проверяет, соответствует ли fb2 файл формату bool CFb2File::IsFb2File(const std::wstring& sFile) { + // Открывает файл на проверку if (!m_internal->m_oLightReader.FromFile(sFile)) return false; // Читаем FictionBook if(!m_internal->isSection(L"FictionBook")) return false; - while(m_internal->m_oLightReader.MoveToNextAttribute()) - m_internal->m_mXmlns.insert(std::make_pair(m_internal->m_oLightReader.GetName(), m_internal->m_oLightReader.GetText())); - m_internal->m_sFile = sFile; + + m_internal->m_oLightReader.Clear(); return true; } -// Выставление временной (рабочей) папки +// Выставление рабочей папки void CFb2File::SetTmpDirectory(const std::wstring& sFolder) { - m_internal->m_sDstFolder = sFolder; + m_internal->m_sTmpFolder = CorrectPathW(sFolder); } // Проверяет, соответствует ли fb2 файл формату @@ -1260,13 +1321,21 @@ void CFb2File::SetTmpDirectory(const std::wstring& sFolder) int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, bool bNeedDocx) { // Копирование шаблона - // КОСТЫЛЬ + // присутствует КОСТЫЛЬ - путь к шаблону относительно теста std::wstring sTemplate = sDirectory + L"/../../../../template/"; NSDirectory::CopyDirectory(sTemplate, sDirectory); // Начало файла m_internal->m_oBuilder += L""; + // Открываем файл на чтение + if (!m_internal->m_oLightReader.FromFile(sPath)) + return FALSE; + + // Читаем FictionBook + if(!m_internal->isSection(L"FictionBook")) + return false; + // Читаем description if(!m_internal->isSection(L"description")) return false; @@ -1309,21 +1378,59 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, } while(m_internal->isSection(L"custom-info")); } + // Создаем сноски + NSStringUtils::CStringBuilder oFootnotes; + oFootnotes += L""; + oFootnotes += L""; + oFootnotes += L""; + oFootnotes += L""; + // Читаем body + int nDeath = m_internal->m_oLightReader.GetDepth() - 1; if(m_internal->m_oLightReader.GetName() != L"body") return false; do { - if(!m_internal->readBody()) + if(m_internal->m_oLightReader.GetName() != L"body") + break; + bool bNotes = false; + while(m_internal->m_oLightReader.MoveToNextAttribute()) + { + if(m_internal->m_oLightReader.GetName() == L"name" && + m_internal->m_oLightReader.GetText() == L"notes") + bNotes = true; + } + m_internal->m_oLightReader.MoveToElement(); + if(bNotes) + { + if(!m_internal->readNotes(oFootnotes)) + return false; + } + else if(!m_internal->readBody()) return false; - } while(m_internal->isSection(L"body")); + } while(m_internal->m_oLightReader.ReadNextSiblingNode(nDeath)); - // Конец файла + // Конец сносок + oFootnotes += L""; + // Пишем сноски в файл + std::wstring sFootnotesDirectory = sDirectory + L"/word"; + NSFile::CFileBinary oFootnotesWriter; + if (!oFootnotesWriter.CreateFileW(sFootnotesDirectory + L"/footnotes.xml")) + return false; + oFootnotesWriter.WriteStringUTF8(oFootnotes.GetData()); + oFootnotesWriter.CloseFile(); + + // Конец документа m_internal->m_oBuilder += L""; + // Пишем документ в файл + NSFile::CFileBinary oDocumentXmlWriter; + if (!oDocumentXmlWriter.CreateFileW(sDirectory + L"/word/document.xml")) + return false; + oDocumentXmlWriter.WriteStringUTF8(m_internal->m_oBuilder.GetData()); + oDocumentXmlWriter.CloseFile(); - // Создаем РЕЛЬСЫ + // Создаем рельсы NSStringUtils::CStringBuilder oRels; - // Начало файла oRels += L""; oRels += L""; oRels += L""; @@ -1373,9 +1480,8 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, oImageWriter.CloseFile(); // Ищем картинку в списке требующихся - // Если есть картинка на которую нет ссылки, то просто пишем ее - std::map::iterator it = m_internal->m_mImage.find(sId); - if(it != m_internal->m_mImage.end()) + std::map::iterator it = m_internal->m_mImages.find(sId); + if(it != m_internal->m_mImages.end()) { // Запись картинок в рельсы oRels += L"first; oRels += L"\"/>"; // Удаляем картинку из списка требующихся - m_internal->m_mImage.erase(it); + m_internal->m_mImages.erase(it); } } - } while(m_internal->m_oLightReader.ReadNextNode()); + } while(m_internal->m_oLightReader.ReadNextSiblingNode(nDeath)); // Если остались неразрешенные ссылки на картинки в тексте - if(!m_internal->m_mImage.empty()) + if(!m_internal->m_mImages.empty()) return false; - // Конец файла рельсов + + // Конец рельсов oRels += L""; // Пишем рельсы в файл std::wstring sRelsDirectory = sDirectory + L"/word/_rels"; @@ -1402,13 +1509,6 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, oRelsWriter.WriteStringUTF8(oRels.GetData()); oRelsWriter.CloseFile(); - // Создаем файл для записи - NSFile::CFileBinary oDocumentXmlWriter; - if (!oDocumentXmlWriter.CreateFileW(sDirectory + L"/word/document.xml")) - return false; - oDocumentXmlWriter.WriteStringUTF8(m_internal->m_oBuilder.GetData()); - oDocumentXmlWriter.CloseFile(); - // Архивим в docx if(bNeedDocx) { diff --git a/Fb2File/template/word/footnotes.xml b/Fb2File/template/word/footnotes.xml deleted file mode 100644 index 4b5ca7085e..0000000000 --- a/Fb2File/template/word/footnotes.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Fb2File/template/word/styles.xml b/Fb2File/template/word/styles.xml index c1f2bbe13f..8f7475c35b 100644 --- a/Fb2File/template/word/styles.xml +++ b/Fb2File/template/word/styles.xml @@ -11488,4 +11488,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Fb2File/test/main.cpp b/Fb2File/test/main.cpp index bbcc1191c1..e5c8fa8e83 100644 --- a/Fb2File/test/main.cpp +++ b/Fb2File/test/main.cpp @@ -10,7 +10,7 @@ int main() oFile.SetTmpDirectory(NSFile::GetProcessDirectory() + L"/tmp"); // файл, который открываем - std::wstring sFile = NSFile::GetProcessDirectory() + L"/../../../examples/8-sezon-groz.fb2"; + std::wstring sFile = NSFile::GetProcessDirectory() + L"/../../../examples/5-kreshcheniye-ognem.fb2"; // директория, где будем создавать docx std::wstring sOutputDirectory = NSFile::GetProcessDirectory() + L"/res";