From 492afba8b1eeda47a6d3080ebf0b5c6e85f8e67a Mon Sep 17 00:00:00 2001 From: "G.K.MacGregor" Date: Sun, 29 Nov 2020 11:48:08 +0000 Subject: [PATCH] Untangle hashstring exporting into loadsave --- levelonepage.cpp | 65 ------------------------------------- levelonepage.h | 3 -- loadsave.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ loadsave.h | 6 ++++ mainwindow.cpp | 23 ++++++++++--- mainwindow.h | 3 +- 6 files changed, 110 insertions(+), 74 deletions(-) diff --git a/levelonepage.cpp b/levelonepage.cpp index 6ae586a..c37968d 100644 --- a/levelonepage.cpp +++ b/levelonepage.cpp @@ -414,71 +414,6 @@ void LevelOnePage::loadPagePacket(QByteArray &inLine) } } -int LevelOnePage::controlBitsToPS() const -{ - //TODO map page language for regions other than 0 - int pageStatus = 0x8000 | (controlBit(PageBase::C4ErasePage) << 14) | ((m_defaultNOS & 1) << 9) | ((m_defaultNOS & 2) << 7) | ((m_defaultNOS & 4) << 5); - for (int i=C5Newsflash; i<=C11SerialMagazine; i++) - pageStatus |= controlBit(i) << (i-1); - return pageStatus; -} - -QString LevelOnePage::exportURLHash(QString pageHash) -{ - int hashDigits[1167]={0}; - int totalBits, charBit; - const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - - //TODO deal with "black text allowed" - pageHash.append(QString("#%1:").arg(m_defaultNOS, 1, 16)); - for (int r=0; r<25; r++) - for (int c=0; c<40; c++) - for (int b=0; b<7; b++) { - totalBits = (r * 40 + c) * 7 + b; - charBit = ((m_level1Page[r][c]) >> (6 - b)) & 0x01; - hashDigits[totalBits / 6] |= charBit << (5 - (totalBits % 6)); - } - - for (int i=0; i<1167; i++) - pageHash.append(base64[hashDigits[i]]); - - if (packetNeeded(28,0) || packetNeeded(28,4)) { - QString x28StringBegin, x28StringEnd; - - x28StringBegin.append(QString("00%1").arg((m_defaultCharSet << 3) | m_defaultNOS, 2, 16, QChar('0')).toUpper()); - x28StringBegin.append(QString("%1").arg((m_secondCharSet << 3) | m_secondNOS, 2, 16, QChar('0')).toUpper()); - x28StringBegin.append(QString("%1%2%3%4").arg(m_leftSidePanelDisplayed, 1, 10).arg(m_rightSidePanelDisplayed, 1, 10).arg(m_sidePanelStatusL25, 1, 10).arg(m_sidePanelColumns, 1, 16)); - - x28StringEnd = QString("%1%2%3%4").arg(m_defaultScreenColour, 2, 16, QChar('0')).arg(m_defaultRowColour, 2, 16, QChar('0')).arg(m_blackBackgroundSubst, 1, 10).arg(m_colourTableRemap, 1, 10); - - if (packetNeeded(28,0)) { - pageHash.append(":X280="); - pageHash.append(x28StringBegin); - pageHash.append(colourHash(1)); - pageHash.append(x28StringEnd); - } - if (packetNeeded(28,4)) { - pageHash.append(":X284="); - pageHash.append(x28StringBegin); - pageHash.append(colourHash(0)); - pageHash.append(x28StringEnd); - } - } - - if (!localEnhance.isEmpty()) { - pageHash.append(":X26="); - for (int i=0; i> 1]); - pageHash.append(base64[localEnhance.at(i).mode() | ((localEnhance.at(i).data() & 1) << 5)]); - pageHash.append(base64[localEnhance.at(i).address()]); - } - //TODO need to add one or more terminators to X26 - } - //TODO check if 0x8000 | is needed for zxnet - pageHash.append(QString(":PS=%1").arg(0x8000 | controlBitsToPS(), 0, 16, QChar('0'))); - return pageHash; -} - /* 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 765d0eb..9e1fcf7 100644 --- a/levelonepage.h +++ b/levelonepage.h @@ -104,9 +104,6 @@ public: QString colourHash(int); QList localEnhance; -protected: - int controlBitsToPS() const; - private: unsigned char m_level1Page[25][40]; /* int m_subPageNumber; */ diff --git a/loadsave.cpp b/loadsave.cpp index 83f067c..db4ea2a 100644 --- a/loadsave.cpp +++ b/loadsave.cpp @@ -24,6 +24,7 @@ #include #include "document.h" +#include "levelonepage.h" #include "pagebase.h" // Used by TTI and hashstring @@ -157,3 +158,86 @@ void saveTTI(QSaveFile &file, const TeletextDocument &document) subPageNumber++; } } + +QByteArray rowPacketAlways(PageBase *subPage, int packetNumber) +{ + if (subPage->packetNeeded(packetNumber)) + return subPage->packet(packetNumber); + else + return QByteArray(40, ' '); +} + +QString exportHashStringPage(LevelOnePage *subPage) +{ + int hashDigits[1167]={0}; + int totalBits, charBit; + const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + QString hashString; + + // TODO int editTFCharacterSet = 5; + bool blackForeground = false; + + for (int r=0; r<25; r++) { + QByteArray rowPacket = rowPacketAlways(subPage, r); + for (int c=0; c<40; c++) { + if (rowPacket.at(c) == 0x00 || rowPacket.at(c) == 0x10) + blackForeground = true; + for (int b=0; b<7; b++) { + totalBits = (r * 40 + c) * 7 + b; + charBit = ((rowPacket.at(c)) >> (6 - b)) & 0x01; + hashDigits[totalBits / 6] |= charBit << (5 - (totalBits % 6)); + } + } + } + + hashString.append(QString("#%1:").arg(blackForeground ? 8 : 0, 1, 16)); + + for (int i=0; i<1167; i++) + hashString.append(base64[hashDigits[i]]); + + return hashString; +} + +QString exportHashStringPackets(LevelOnePage *subPage) +{ + auto colourToHexString=[&](int whichCLUT) + { + QString resultHexString; + + for (int i=whichCLUT*8; iCLUT(i), 3, 16, QChar('0'))); + return resultHexString; + }; + + const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + QString result; + + if (subPage->packetNeeded(28,0) || subPage->packetNeeded(28,4)) { + // X/28/0 and X/28/4 are duplicates apart from the CLUT definitions + // Assemble the duplicate beginning and ending of both packets + QString x28StringBegin, x28StringEnd; + + x28StringBegin.append(QString("00%1").arg((subPage->defaultCharSet() << 3) | subPage->defaultNOS(), 2, 16, QChar('0')).toUpper()); + x28StringBegin.append(QString("%1").arg((subPage->secondCharSet() << 3) | subPage->secondNOS(), 2, 16, QChar('0')).toUpper()); + x28StringBegin.append(QString("%1%2%3%4").arg(subPage->leftSidePanelDisplayed(), 1, 10).arg(subPage->rightSidePanelDisplayed(), 1, 10).arg(subPage->sidePanelStatusL25(), 1, 10).arg(subPage->sidePanelColumns(), 1, 16)); + + x28StringEnd = QString("%1%2%3%4").arg(subPage->defaultScreenColour(), 2, 16, QChar('0')).arg(subPage->defaultRowColour(), 2, 16, QChar('0')).arg(subPage->blackBackgroundSubst(), 1, 10).arg(subPage->colourTableRemap(), 1, 10); + + if (subPage->packetNeeded(28,0)) + result.append(":X280=" + x28StringBegin + colourToHexString(2) + colourToHexString(3) + x28StringEnd); + if (subPage->packetNeeded(28,4)) + result.append(":X284=" + x28StringBegin + colourToHexString(0) + colourToHexString(1) + x28StringEnd); + } + + if (!subPage->localEnhance.isEmpty()) { + result.append(":X26="); + for (int i=0; ilocalEnhance.size(); i++) { + result.append(base64[subPage->localEnhance.at(i).data() >> 1]); + result.append(base64[subPage->localEnhance.at(i).mode() | ((subPage->localEnhance.at(i).data() & 1) << 5)]); + result.append(base64[subPage->localEnhance.at(i).address()]); + } + } + + result.append(QString(":PS=%1").arg(0x8000 | controlBitsToPS(subPage), 0, 16, QChar('0'))); + return result; +} diff --git a/loadsave.h b/loadsave.h index 7179d5e..3678cf6 100644 --- a/loadsave.h +++ b/loadsave.h @@ -25,10 +25,16 @@ #include #include "document.h" +#include "levelonepage.h" #include "pagebase.h" int controlBitsToPS(PageBase *); void saveTTI(QSaveFile &, const TeletextDocument &); +QByteArray rowPcketAlways(PageBase *, int); + +QString exportHashStringPage(LevelOnePage *); +QString exportHashStringPackets(LevelOnePage *subPage); + #endif diff --git a/mainwindow.cpp b/mainwindow.cpp index 43c1bfc..bde23a1 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -117,9 +117,14 @@ bool MainWindow::saveAs() return saveFile(fileName); } -void MainWindow::exportURL() +void MainWindow::exportZXNet() { - QDesktopServices::openUrl(QUrl(m_textWidget->document()->currentSubPage()->exportURLHash("http://www.zxnet.co.uk/teletext/editor/"))); + QDesktopServices::openUrl(QUrl("http://zxnet.co.uk/teletext/editor/" + exportHashStringPage(m_textWidget->document()->currentSubPage()) + exportHashStringPackets(m_textWidget->document()->currentSubPage()))); +} + +void MainWindow::exportEditTF() +{ + QDesktopServices::openUrl(QUrl("http://edit.tf/" + exportHashStringPage(m_textWidget->document()->currentSubPage()))); } void MainWindow::about() @@ -239,9 +244,17 @@ void MainWindow::createActions() setRecentFilesVisible(MainWindow::hasRecentFiles()); - QAction *exportAct = fileMenu->addAction(tr("Export to zxnet.co.uk")); - exportAct->setStatusTip("Export URL to zxnet.co.uk online editor"); - connect(exportAct, &QAction::triggered, this, &MainWindow::exportURL); + QMenu *exportHashStringSubMenu = fileMenu->addMenu(tr("Export to online editor")); + + QAction *exportZXNetAct = exportHashStringSubMenu->addAction(tr("Open in zxnet.co.uk")); + exportZXNetAct->setStatusTip("Export and open page in zxnet.co.uk online editor"); + connect(exportZXNetAct, &QAction::triggered, this, &MainWindow::exportZXNet); + + QAction *exportEditTFAct = exportHashStringSubMenu->addAction(tr("Open in edit.tf")); + exportEditTFAct->setStatusTip("Export and open page in edit.tf online editor"); + connect(exportEditTFAct, &QAction::triggered, this, &MainWindow::exportEditTF); + + fileMenu->addSeparator(); QAction *closeAct = fileMenu->addAction(tr("&Close"), this, &QWidget::close); closeAct->setShortcut(tr("Ctrl+W")); diff --git a/mainwindow.h b/mainwindow.h index 3731d95..f0a5df1 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -56,7 +56,8 @@ private slots: void open(); bool save(); bool saveAs(); - void exportURL(); + void exportZXNet(); + void exportEditTF(); void updateRecentFileActions(); void openRecentFile(); void about();