diff --git a/document.cpp b/document.cpp index f8f128a..a6e5747 100644 --- a/document.cpp +++ b/document.cpp @@ -17,8 +17,6 @@ * along with QTeletextMaker. If not, see . */ -#include -#include #include #include "document.h" @@ -27,7 +25,7 @@ TeletextDocument::TeletextDocument() { - m_pageNumber = 0x198; + m_pageNumber = 0x199; m_description.clear(); m_pageFunction = PFLevelOnePage; m_packetCoding = Coding7bit; @@ -58,95 +56,6 @@ void TeletextDocument::setPacketCoding(PacketCodingEnum newPacketEncoding) } */ -void TeletextDocument::loadDocument(QFile *inFile) -{ - QByteArray inLine; - bool firstSubPageFound = false; - int cycleCommandsFound = 0; - int mostRecentCycleValue = -1; - LevelOnePage::CycleTypeEnum mostRecentCycleType; - - LevelOnePage* loadingPage = m_subPages[0]; - - for (;;) { - inLine = inFile->readLine(160).trimmed(); - if (inLine.isEmpty()) - break; - if (inLine.startsWith("DE,")) - m_description = QString(inLine.remove(0, 3)); - if (inLine.startsWith("PN,")) { - bool pageNumberOk; - int pageNumberRead = inLine.mid(3, 3).toInt(&pageNumberOk, 16); - if ((!pageNumberOk) || pageNumberRead < 0x100 || pageNumberRead > 0x8ff) - pageNumberRead = 0x199; - // When second and subsequent PN commands are found, firstSubPageFound==true at this point - // This assumes that PN is the first command of a new subpage... - if (firstSubPageFound) { - m_subPages.push_back(new LevelOnePage); - loadingPage = m_subPages.back(); - } - m_pageNumber = pageNumberRead; - firstSubPageFound = true; - } -/* if (lineType == "SC,") { - bool subPageNumberOk; - int subPageNumberRead = inLine.mid(3, 4).toInt(&subPageNumberOk, 16); - if ((!subPageNumberOk) || subPageNumberRead > 0x3f7f) - subPageNumberRead = 0; - loadingPage->setSubPageNumber(subPageNumberRead); - }*/ - if (inLine.startsWith("PS,")) { - bool pageStatusOk; - int pageStatusRead = inLine.mid(3, 4).toInt(&pageStatusOk, 16); - if (pageStatusOk) { - loadingPage->setControlBit(PageBase::C4ErasePage, pageStatusRead & 0x4000); - for (int i=PageBase::C5Newsflash, pageStatusBit=0x0001; i<=PageBase::C11SerialMagazine; i++, pageStatusBit<<=1) - loadingPage->setControlBit(i, pageStatusRead & pageStatusBit); - loadingPage->setDefaultNOS(((pageStatusRead & 0x0200) >> 9) | ((pageStatusRead & 0x0100) >> 7) | ((pageStatusRead & 0x0080) >> 5)); - } - } - if (inLine.startsWith("CT,") && (inLine.endsWith(",C") || inLine.endsWith(",T"))) { - bool cycleValueOk; - int cycleValueRead = inLine.mid(3, inLine.size()-5).toInt(&cycleValueOk); - if (cycleValueOk) { - cycleCommandsFound++; - // House-keep CT command values, in case it's the only one within multiple subpages - mostRecentCycleValue = cycleValueRead; - loadingPage->setCycleValue(cycleValueRead); - mostRecentCycleType = inLine.endsWith("C") ? LevelOnePage::CTcycles : LevelOnePage::CTseconds; - loadingPage->setCycleType(mostRecentCycleType); - } - } - if (inLine.startsWith("FL,")) { - bool fastTextLinkOk; - int fastTextLinkRead; - QString flLine = QString(inLine.remove(0, 3)); - if (flLine.count(',') == 5) - for (int i=0; i<6; i++) { - fastTextLinkRead = flLine.section(',', i, i).toInt(&fastTextLinkOk, 16); - if (fastTextLinkOk) { - if (fastTextLinkRead == 0) - fastTextLinkRead = 0x8ff; - // Stored as page link with relative magazine number, convert from absolute page number that was read - fastTextLinkRead ^= m_pageNumber & 0x700; - fastTextLinkRead &= 0x7ff; // Fixes magazine 8 to 0 - loadingPage->setFastTextLinkPageNumber(i, fastTextLinkRead); - } - } - } - if (inLine.startsWith("OL,")) - loadingPage->loadPagePacket(inLine); - } - // If there's more than one subpage but only one valid CT command was found, apply it to all subpages - // I don't know if this is correct - if (cycleCommandsFound == 1 && m_subPages.size()>1) - for (auto &subPage : m_subPages) { - subPage->setCycleValue(mostRecentCycleValue); - subPage->setCycleType(mostRecentCycleType); - } - subPageSelected(); -} - void TeletextDocument::selectSubPageIndex(int newSubPageIndex, bool forceRefresh) { // forceRefresh overrides "beyond the last subpage" check, so inserting a subpage after the last one still shows - dangerous workaround? @@ -198,10 +107,9 @@ void TeletextDocument::deleteSubPage(int subPageToDelete) void TeletextDocument::setPageNumber(QString pageNumberString) { - // The LineEdit should check if a valid hex number was entered, but just in case... bool pageNumberOk; int pageNumberRead = pageNumberString.toInt(&pageNumberOk, 16); - if ((!pageNumberOk) || pageNumberRead < 0x100 || pageNumberRead > 0x8fe) + if ((!pageNumberOk) || pageNumberRead < 0x100 || pageNumberRead > 0x8ff) return; // If the magazine number was changed, we need to update the relative magazine numbers in FastText diff --git a/document.h b/document.h index db78a86..8b8f457 100644 --- a/document.h +++ b/document.h @@ -20,9 +20,7 @@ #ifndef DOCUMENT_H #define DOCUMENT_H -#include #include -#include #include #include #include "levelonepage.h" @@ -47,7 +45,6 @@ public: PacketCodingEnum packetCoding() const { return m_packetCoding; } // void setPacketCoding(PacketCodingEnum); - void loadDocument(QFile *); int numberOfSubPages() const { return m_subPages.size(); } LevelOnePage* subPage(int p) const { return m_subPages[p]; } LevelOnePage* currentSubPage() const { return m_subPages[m_currentSubPageIndex]; } diff --git a/levelonepage.cpp b/levelonepage.cpp index c37968d..c62b83f 100644 --- a/levelonepage.cpp +++ b/levelonepage.cpp @@ -365,55 +365,6 @@ bool LevelOnePage::setControlBit(int bitNumber, bool active) } } -void LevelOnePage::loadPagePacket(QByteArray &inLine) -{ - bool lineNumberOk; - int lineNumber, secondCommaPosition; - - secondCommaPosition = inLine.indexOf(",", 3); - if (secondCommaPosition != 4 && secondCommaPosition != 5) - return; - - lineNumber = inLine.mid(3, secondCommaPosition-3).toInt(&lineNumberOk, 10); - if (lineNumberOk && lineNumber>=0 && lineNumber<=29) { - inLine.remove(0, secondCommaPosition+1); - if (lineNumber <= 25) { - for (int c=0; c<40; c++) { - // trimmed() helpfully removes CRLF line endings from the just-read line for us - // But it also (un)helpfully removes spaces at the end of a 40 character line, so put them back - if (c >= inLine.size()) - inLine.append(' '); - if (inLine.at(c) & 0x80) - inLine[c] = inLine.at(c) & 0x7f; - else if (inLine.at(c) == 0x10) - inLine[c] = 0x0d; - else if (inLine.at(c) == 0x1b) { - inLine.remove(c, 1); - inLine[c] = inLine.at(c) & 0xbf; - } - } - setPacket(lineNumber, inLine); - } else { - int designationCode = inLine.at(0) & 0x3f; - if (inLine.size() < 40) { - // OL is too short! - if (lineNumber == 26) { - // For a too-short enhancement triplets OL, first trim the line down to nearest whole triplet - inLine.resize((inLine.size() / 3 * 3) + 1); - // Then use "dummy" enhancement triplets to extend the line to the proper length - for (int i=inLine.size(); i<40; i+=3) - inLine.append("i^@"); // Address 41, Mode 0x1e, Data 0 - } else - // For other triplet OLs and Hamming 8/4 OLs, just pad with zero data - inLine.leftJustified(40, '@'); - } - for (int i=1; i<=39; i++) - inLine[i] = inLine.at(i) & 0x3f; - setPacket(lineNumber, designationCode, inLine); - } - } -} - /* void LevelOnePage::setSubPageNumber(int newSubPageNumber) { m_subPageNumber = newSubPageNumber; } */ void LevelOnePage::setCycleValue(int newValue) { m_cycleValue = newValue; }; void LevelOnePage::setCycleType(CycleTypeEnum newType) { m_cycleType = newType; } diff --git a/levelonepage.h b/levelonepage.h index 9e1fcf7..b1bcf2a 100644 --- a/levelonepage.h +++ b/levelonepage.h @@ -25,7 +25,6 @@ #include #include #include -#include #include "pagebase.h" #include "x26triplets.h" @@ -52,8 +51,6 @@ public: bool setControlBit(int, bool) override; void clearPage(); - void loadPagePacket(QByteArray &); - QString exportURLHash(QString); /* void setSubPageNumber(int); */ int cycleValue() const { return m_cycleValue; }; diff --git a/loadsave.cpp b/loadsave.cpp index 1db80a7..257e8ca 100644 --- a/loadsave.cpp +++ b/loadsave.cpp @@ -20,13 +20,146 @@ #include "loadsave.h" #include +#include #include #include +#include #include "document.h" #include "levelonepage.h" #include "pagebase.h" +void loadTTI(QFile *inFile, TeletextDocument *document) +{ + QByteArray inLine; + bool firstSubPageAlreadyFound = false; + int cycleCommandsFound = 0; + int mostRecentCycleValue = -1; + LevelOnePage::CycleTypeEnum mostRecentCycleType; + + LevelOnePage* loadingPage = document->subPage(0); + + for (;;) { + inLine = inFile->readLine(160).trimmed(); + if (inLine.isEmpty()) + break; + if (inLine.startsWith("DE,")) + document->setDescription(QString(inLine.remove(0, 3))); + if (inLine.startsWith("PN,")) { + // When second and subsequent PN commands are found, firstSubPageAlreadyFound==true at this point + // This assumes that PN is the first command of a new subpage... + if (firstSubPageAlreadyFound) { + document->insertSubPage(document->numberOfSubPages(), false); + loadingPage = document->subPage(document->numberOfSubPages()-1); + } else { + document->setPageNumber(inLine.mid(3,3)); + firstSubPageAlreadyFound = true; + } + } +/* if (lineType == "SC,") { + bool subPageNumberOk; + int subPageNumberRead = inLine.mid(3, 4).toInt(&subPageNumberOk, 16); + if ((!subPageNumberOk) || subPageNumberRead > 0x3f7f) + subPageNumberRead = 0; + loadingPage->setSubPageNumber(subPageNumberRead); + }*/ + if (inLine.startsWith("PS,")) { + bool pageStatusOk; + int pageStatusRead = inLine.mid(3, 4).toInt(&pageStatusOk, 16); + if (pageStatusOk) { + loadingPage->setControlBit(PageBase::C4ErasePage, pageStatusRead & 0x4000); + for (int i=PageBase::C5Newsflash, pageStatusBit=0x0001; i<=PageBase::C11SerialMagazine; i++, pageStatusBit<<=1) + loadingPage->setControlBit(i, pageStatusRead & pageStatusBit); + loadingPage->setDefaultNOS(((pageStatusRead & 0x0200) >> 9) | ((pageStatusRead & 0x0100) >> 7) | ((pageStatusRead & 0x0080) >> 5)); + } + } + if (inLine.startsWith("CT,") && (inLine.endsWith(",C") || inLine.endsWith(",T"))) { + bool cycleValueOk; + int cycleValueRead = inLine.mid(3, inLine.size()-5).toInt(&cycleValueOk); + if (cycleValueOk) { + cycleCommandsFound++; + // House-keep CT command values, in case it's the only one within multiple subpages + mostRecentCycleValue = cycleValueRead; + loadingPage->setCycleValue(cycleValueRead); + mostRecentCycleType = inLine.endsWith("C") ? LevelOnePage::CTcycles : LevelOnePage::CTseconds; + loadingPage->setCycleType(mostRecentCycleType); + } + } + if (inLine.startsWith("FL,")) { + bool fastTextLinkOk; + int fastTextLinkRead; + QString flLine = QString(inLine.remove(0, 3)); + if (flLine.count(',') == 5) + for (int i=0; i<6; i++) { + fastTextLinkRead = flLine.section(',', i, i).toInt(&fastTextLinkOk, 16); + if (fastTextLinkOk) { + if (fastTextLinkRead == 0) + fastTextLinkRead = 0x8ff; + // Stored as page link with relative magazine number, convert from absolute page number that was read + fastTextLinkRead ^= document->pageNumber() & 0x700; + fastTextLinkRead &= 0x7ff; // Fixes magazine 8 to 0 + loadingPage->setFastTextLinkPageNumber(i, fastTextLinkRead); + } + } + } + if (inLine.startsWith("OL,")) { + bool lineNumberOk; + int lineNumber, secondCommaPosition; + + secondCommaPosition = inLine.indexOf(",", 3); + if (secondCommaPosition != 4 && secondCommaPosition != 5) + continue; + + lineNumber = inLine.mid(3, secondCommaPosition-3).toInt(&lineNumberOk, 10); + if (lineNumberOk && lineNumber>=0 && lineNumber<=29) { + inLine.remove(0, secondCommaPosition+1); + if (lineNumber <= 25) { + for (int c=0; c<40; c++) { + // trimmed() helpfully removes CRLF line endings from the just-read line for us + // But it also (un)helpfully removes spaces at the end of a 40 character line, so put them back + if (c >= inLine.size()) + inLine.append(' '); + if (inLine.at(c) & 0x80) + inLine[c] = inLine.at(c) & 0x7f; + else if (inLine.at(c) == 0x10) + inLine[c] = 0x0d; + else if (inLine.at(c) == 0x1b) { + inLine.remove(c, 1); + inLine[c] = inLine.at(c) & 0xbf; + } + } + loadingPage->setPacket(lineNumber, inLine); + } else { + int designationCode = inLine.at(0) & 0x3f; + if (inLine.size() < 40) { + // OL is too short! + if (lineNumber == 26) { + // For a too-short enhancement triplets OL, first trim the line down to nearest whole triplet + inLine.resize((inLine.size() / 3 * 3) + 1); + // Then use "dummy" enhancement triplets to extend the line to the proper length + for (int i=inLine.size(); i<40; i+=3) + inLine.append("i^@"); // Address 41, Mode 0x1e, Data 0 + } else + // For other triplet OLs and Hamming 8/4 OLs, just pad with zero data + for (int i=inLine.size(); i<40; i++) + inLine.append("@"); + } + for (int i=1; i<=39; i++) + inLine[i] = inLine.at(i) & 0x3f; + loadingPage->setPacket(lineNumber, designationCode, inLine); + } + } + } + } + // If there's more than one subpage but only one valid CT command was found, apply it to all subpages + // I don't know if this is correct + if (cycleCommandsFound == 1 && document->numberOfSubPages()>1) + for (int i=0; inumberOfSubPages(); i++) { + document->subPage(i)->setCycleValue(mostRecentCycleValue); + document->subPage(i)->setCycleType(mostRecentCycleType); + } +} + // Used by saveTTI and HashString int controlBitsToPS(PageBase *subPage) { diff --git a/loadsave.h b/loadsave.h index f3d3972..811ec62 100644 --- a/loadsave.h +++ b/loadsave.h @@ -21,13 +21,17 @@ #define LOADSAVE_H #include +#include #include #include +#include #include "document.h" #include "levelonepage.h" #include "pagebase.h" +void loadTTI(QFile *inFile, TeletextDocument *document); + int controlBitsToPS(PageBase *); void saveTTI(QSaveFile &, const TeletextDocument &); diff --git a/mainwindow.cpp b/mainwindow.cpp index bde23a1..6aa4532 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -690,7 +690,8 @@ void MainWindow::loadFile(const QString &fileName) } QApplication::setOverrideCursor(Qt::WaitCursor); - m_textWidget->document()->loadDocument(&file); + loadTTI(&file, m_textWidget->document()); + updatePageWidgets(); QApplication::restoreOverrideCursor();