diff --git a/levelonepage.cpp b/levelonepage.cpp index 941245d..211ad1b 100644 --- a/levelonepage.cpp +++ b/levelonepage.cpp @@ -27,18 +27,12 @@ LevelOnePage::LevelOnePage() { - m_paddingX26Triplet.setAddress(41); - m_paddingX26Triplet.setMode(0x1e); - m_paddingX26Triplet.setData(0); m_enhancements.reserve(208); clearPage(); } LevelOnePage::LevelOnePage(const PageBase &other) { - m_paddingX26Triplet.setAddress(41); - m_paddingX26Triplet.setMode(0x1e); - m_paddingX26Triplet.setData(0); m_enhancements.reserve(208); clearPage(); @@ -120,38 +114,10 @@ QByteArray LevelOnePage::packet(int packetNumber, int designationCode) const QByteArray result(40, 0x00); if (packetNumber == 26) { - if (!packetNeeded(26, designationCode)) + if (!packetFromEnhancementListNeeded(designationCode)) return result; // Blank result - int enhanceListPointer; - X26Triplet lastTriplet; - - for (int i=0; i<13; i++) { - enhanceListPointer = designationCode*13+i; - - if (enhanceListPointer < m_enhancements.size()) { - result[i*3+1] = m_enhancements.at(enhanceListPointer).address(); - result[i*3+2] = m_enhancements.at(enhanceListPointer).mode() | ((m_enhancements.at(enhanceListPointer).data() & 1) << 5); - result[i*3+3] = m_enhancements.at(enhanceListPointer).data() >> 1; - - // If this is the last triplet, get a copy to repeat to the end of the packet - if (enhanceListPointer == m_enhancements.size()-1) { - lastTriplet = m_enhancements.at(enhanceListPointer); - // If the last triplet was NOT a Termination Marker, make up one - if (lastTriplet.mode() != 0x1f || lastTriplet.address() != 0x3f) { - lastTriplet.setAddress(0x3f); - lastTriplet.setMode(0x1f); - lastTriplet.setData(0x07); - } - } - } else { - // We've gone past the end of the triplet list, so repeat the Termination Marker to the end - result[i*3+1] = lastTriplet.address(); - result[i*3+2] = lastTriplet.mode() | ((lastTriplet.data() & 1) << 5); - result[i*3+3] = lastTriplet.data() >> 1; - } - } - return result; + return packetFromEnhancementList(designationCode); } if (packetNumber == 27 && designationCode == 0) { @@ -224,28 +190,7 @@ bool LevelOnePage::setPacket(int packetNumber, QByteArray packetContents) bool LevelOnePage::setPacket(int packetNumber, int designationCode, QByteArray packetContents) { if (packetNumber == 26) { - // Preallocate entries in the m_enhancements list to hold our incoming triplets. - // We write "dummy" reserved 11110 Row Triplets in the allocated entries which then get overwritten by the packet contents. - // This is in case of missing packets so we can keep Local Object pointers valid. - while (m_enhancements.size() < (designationCode+1)*13) - m_enhancements.append(m_paddingX26Triplet); - - int enhanceListPointer; - X26Triplet newX26Triplet; - - for (int i=0; i<13; i++) { - enhanceListPointer = designationCode*13+i; - - newX26Triplet.setAddress(packetContents.at(i*3+1) & 0x3f); - newX26Triplet.setMode(packetContents.at(i*3+2) & 0x1f); - newX26Triplet.setData(((packetContents.at(i*3+3) & 0x3f) << 1) | ((packetContents.at(i*3+2) & 0x20) >> 5)); - m_enhancements[enhanceListPointer] = newX26Triplet; - } - if (newX26Triplet.mode() == 0x1f && newX26Triplet.address() == 0x3f && newX26Triplet.data() & 0x01) - // Last triplet was a Termination Marker (without ..follows) so clean up the repeated ones - while (m_enhancements.size()>1 && m_enhancements.at(m_enhancements.size()-2).mode() == 0x1f && m_enhancements.at(m_enhancements.size()-2).address() == 0x3f && m_enhancements.at(m_enhancements.size()-2).data() == newX26Triplet.data()) - m_enhancements.removeLast(); - + setEnhancementListFromPacket(designationCode, packetContents); return true; } @@ -324,7 +269,7 @@ bool LevelOnePage::packetNeeded(int packetNumber) const bool LevelOnePage::packetNeeded(int packetNumber, int designationCode) const { if (packetNumber == 26) - return ((m_enhancements.size()+12) / 13) > designationCode; + return packetFromEnhancementListNeeded(designationCode); if (packetNumber == 27 && designationCode == 0) { for (int i=0; i<6; i++) diff --git a/levelonepage.h b/levelonepage.h index 96d0283..a34c0a7 100644 --- a/levelonepage.h +++ b/levelonepage.h @@ -22,17 +22,15 @@ #include #include -#include #include #include -#include "pagebase.h" +#include "pagex26base.h" #include "x26triplets.h" QColor CLUTtoQColor(int myColour); -// If we inherit from QObject then we can't copy construct, so "make a new subpage that's a copy of this one" wouldn't work -class LevelOnePage : public PageBase //: public QObject +class LevelOnePage : public PageX26Base //: public QObject { //Q_OBJECT @@ -126,9 +124,6 @@ private: int pageNumber, subPageCodes; } m_composeLink[8]; - QList m_enhancements; - X26Triplet m_paddingX26Triplet; - const int m_defaultCLUT[32] = { 0x000, 0xf00, 0x0f0, 0xff0, 0x00f, 0xf0f, 0x0ff, 0xfff, 0x000, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0x777, diff --git a/pagex26base.cpp b/pagex26base.cpp new file mode 100644 index 0000000..3e0169a --- /dev/null +++ b/pagex26base.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2020 Gavin MacGregor + * + * This file is part of QTeletextMaker. + * + * QTeletextMaker 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 3 of the License, or + * (at your option) any later version. + * + * QTeletextMaker 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 QTeletextMaker. If not, see . + */ + +#include + +#include "pagex26base.h" + +QByteArray PageX26Base::packetFromEnhancementList(int packetNumber) const +{ + QByteArray result(40, 0x00); + + int enhanceListPointer; + X26Triplet lastTriplet; + + for (int i=0; i<13; i++) { + enhanceListPointer = packetNumber*13+i; + + if (enhanceListPointer < m_enhancements.size()) { + result[i*3+1] = m_enhancements.at(enhanceListPointer).address(); + result[i*3+2] = m_enhancements.at(enhanceListPointer).mode() | ((m_enhancements.at(enhanceListPointer).data() & 1) << 5); + result[i*3+3] = m_enhancements.at(enhanceListPointer).data() >> 1; + + // If this is the last triplet, get a copy to repeat to the end of the packet + if (enhanceListPointer == m_enhancements.size()-1) { + lastTriplet = m_enhancements.at(enhanceListPointer); + // If the last triplet was NOT a Termination Marker, make up one + if (lastTriplet.mode() != 0x1f || lastTriplet.address() != 0x3f) { + lastTriplet.setAddress(0x3f); + lastTriplet.setMode(0x1f); + lastTriplet.setData(0x07); + } + } + } else { + // We've gone past the end of the triplet list, so repeat the Termination Marker to the end + result[i*3+1] = lastTriplet.address(); + result[i*3+2] = lastTriplet.mode() | ((lastTriplet.data() & 1) << 5); + result[i*3+3] = lastTriplet.data() >> 1; + } + } + + return result; +} + +void PageX26Base::setEnhancementListFromPacket(int packetNumber, QByteArray packetContents) +{ + // Preallocate entries in the m_enhancements list to hold our incoming triplets. + // We write "dummy" reserved 11110 Row Triplets in the allocated entries which then get overwritten by the packet contents. + // This is in case of missing packets so we can keep Local Object pointers valid. + while (m_enhancements.size() < (packetNumber+1)*13) + m_enhancements.append(m_paddingX26Triplet); + + int enhanceListPointer; + X26Triplet newX26Triplet; + + for (int i=0; i<13; i++) { + enhanceListPointer = packetNumber*13+i; + + newX26Triplet.setAddress(packetContents.at(i*3+1) & 0x3f); + newX26Triplet.setMode(packetContents.at(i*3+2) & 0x1f); + newX26Triplet.setData(((packetContents.at(i*3+3) & 0x3f) << 1) | ((packetContents.at(i*3+2) & 0x20) >> 5)); + m_enhancements[enhanceListPointer] = newX26Triplet; + } + if (newX26Triplet.mode() == 0x1f && newX26Triplet.address() == 0x3f && newX26Triplet.data() & 0x01) + // Last triplet was a Termination Marker (without ..follows) so clean up the repeated ones + while (m_enhancements.size()>1 && m_enhancements.at(m_enhancements.size()-2).mode() == 0x1f && m_enhancements.at(m_enhancements.size()-2).address() == 0x3f && m_enhancements.at(m_enhancements.size()-2).data() == newX26Triplet.data()) + m_enhancements.removeLast(); +} diff --git a/pagex26base.h b/pagex26base.h new file mode 100644 index 0000000..2560815 --- /dev/null +++ b/pagex26base.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 Gavin MacGregor + * + * This file is part of QTeletextMaker. + * + * QTeletextMaker 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 3 of the License, or + * (at your option) any later version. + * + * QTeletextMaker 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 QTeletextMaker. If not, see . + */ + +#ifndef PAGEX26BASE_H +#define PAGEX26BASE_H + +#include +#include + +#include "pagebase.h" +#include "x26triplets.h" + +class PageX26Base : public PageBase //: public QObject +{ + //Q_OBJECT + +protected: + QByteArray packetFromEnhancementList(int) const; + void setEnhancementListFromPacket(int, QByteArray); + bool packetFromEnhancementListNeeded(int n) const { return ((m_enhancements.size()+12) / 13) > n; }; + + QList m_enhancements; + const X26Triplet m_paddingX26Triplet { 41, 0x1e, 0 }; +}; + +#endif diff --git a/qteletextmaker.pro b/qteletextmaker.pro index 4183a74..7cab281 100644 --- a/qteletextmaker.pro +++ b/qteletextmaker.pro @@ -8,6 +8,7 @@ HEADERS = document.h \ mainwidget.h \ mainwindow.h \ pagebase.h \ + pagex26base.h \ pageenhancementsdockwidget.h \ pageoptionsdockwidget.h \ palettedockwidget.h \ @@ -24,6 +25,7 @@ SOURCES = document.cpp \ mainwidget.cpp \ mainwindow.cpp \ pagebase.cpp \ + pagex26base.cpp \ pageenhancementsdockwidget.cpp \ pageoptionsdockwidget.cpp \ palettedockwidget.cpp \