Improved control character display in ApplesoftViewer

This commit is contained in:
Mark Long 2016-10-29 18:11:42 -05:00
parent e76625bf90
commit dab8f1e7d4
7 changed files with 92 additions and 315 deletions

View File

@ -175,7 +175,6 @@ void ApplesoftRetokenizer::retokenizeLinesForFormatting()
void ApplesoftRetokenizer::retokenizeLine(ApplesoftLine &line)
{
qDebug() << "Retokenize line";
QList<ApplesoftToken> tmptokens = QList<ApplesoftToken>::fromVector(line.tokens);
tmptokens = retokenizeRems(tmptokens);
tmptokens = retokenizeStrings(tmptokens);

View File

@ -2,6 +2,7 @@
#include "util.h"
#include <QTextCursor>
#include <QTextCharFormat>
#include <QChar>
#define HEXPREFIX "0x"
@ -17,287 +18,6 @@ void ApplesoftFormatter::setFile(ApplesoftFile *file)
emit newFile(file);
}
void ApplesoftFormatter::formatText()
{
m_formattedText.clear();
if (!m_file) {
return;
}
QString formattedText;
m_flowTargets.clear();
foreach (ApplesoftLine line, m_file->getLines()) {
QString linestring = QString("%1 ").arg(line.linenum,5,10,QChar(' '));
int indentlevel = 1;
formattedText.append(linestring);
QVectorIterator<ApplesoftToken> tokenIt(line.tokens);
ApplesoftToken previousToken;
bool firstToken = true;
while (tokenIt.hasNext())
{
ApplesoftToken token = tokenIt.next();
bool isFlowTarget = false;
QString tokenstr = token.getRawPrintableString();
if (firstToken)
{
if (!tokenstr.startsWith(" "))
{
tokenstr.prepend(" ");
}
firstToken = false;
}
//TODO: Move this to the parser.
//TODO: This doesn't yet handle: ON expr GOTO/GOSUB n1,n2,n3,...
if (previousToken.getTokenId() == ApplesoftToken::ASGoto ||
previousToken.getTokenId() == ApplesoftToken::ASGosub ||
previousToken.getTokenId() == ApplesoftToken::ASThen)
{
isFlowTarget = false;
if (previousToken.getTokenId() == ApplesoftToken::ASGoto ||
previousToken.getTokenId() == ApplesoftToken::ASGosub)
{
isFlowTarget = true;
}
else if (previousToken.getTokenId() == ApplesoftToken::ASThen &&
token.getTokenId() == ApplesoftToken::IntegerTokenVal)
{
isFlowTarget = true;
}
if (isFlowTarget)
{
QPair<quint16,quint16> pair;
pair.first = line.linenum;
pair.second = token.getWordValue();
m_flowTargets.append(pair);
}
}
if (m_format_options.testFlag(ShowIntsAsHex)) {
if (token.getTokenId() == ApplesoftToken::IntegerTokenVal)
{
bool okToConvert = !isFlowTarget;
if (okToConvert)
{
quint32 ui32val = token.getUnsignedIntegerValue();
qint32 i32val = token.getIntegerValue();
if ((i32val < 128 && i32val >= -128) || ui32val < 256)
{
quint8 ui8 = ui32val;
tokenstr = HEXPREFIX+uint8ToHex(ui8);
}
else if ((i32val < 32768 && i32val >= -32768) || ui32val < 65536)
{
quint16 ui16 = ui32val;
tokenstr = HEXPREFIX+uint16ToHex(ui16);
}
else
{
tokenstr = HEXPREFIX+uint32ToHex(ui32val);
}
}
}
}
if (m_format_options.testFlag(BreakAfterReturn)) {
if (token.getTokenId() == ApplesoftToken::ASReturn)
{
tokenstr += "\n";
}
}
if (m_format_options.testFlag(ReindentCode))
{
if (token.getTokenId() == ':')
{
tokenstr += "\n";
for (int ind = 0; ind < indentlevel; ind++)
{
tokenstr += " ";
}
if (!tokenIt.peekNext().getRawPrintableString().startsWith(" "))
{
tokenstr += " ";
}
}
if (token.getTokenId() == ApplesoftToken::ASThen)
{
indentlevel++;
if (tokenIt.peekNext().getTokenId() != ApplesoftToken::IntegerTokenVal)
{
tokenstr += "\n";
for (int ind = 0; ind < indentlevel; ind++)
{
tokenstr += " ";
}
if (!tokenIt.peekNext().getRawPrintableString().startsWith(" "))
{
tokenstr += " ";
}
}
}
}
#define noDEBUGTOKENS
#ifdef DEBUGTOKENS
if (token.getTokenId() >= 0x80)
{
tokenstr = QString("{%1 (%2)}").arg(tokenstr).arg(uint16ToHex(token.getTokenId()));
// tokenstr = " __ ";
}
#endif
if (m_format_options.testFlag(ShowCtrlChars))
{
tokenstr.replace(QChar(0x7f),QChar(0x2401));
for (int idx = 1; idx <= 0x1f; idx++) {
if (idx == '\n') continue;
tokenstr.replace(QChar(idx),QChar(idx+0x2400));
// tokenstr.replace(QChar(idx), QString("<%1>").arg(uint8ToHex(idx)));
}
}
formattedText.append(tokenstr);
previousToken = token;
} // While tokenIt.hasNext();
formattedText.append("\n");
if (m_format_options.testFlag(ReindentCode))
{
// retval.append("\n");
}
} //foreach line
m_formattedText = formattedText;
}
void ApplesoftFormatter::newFormatText()
{
m_formattedText.clear();
QString formattedText;
foreach (ApplesoftLine line, m_file->getLines())
{
QString linestring = QString("%1 ").arg(line.linenum,5,10,QChar(' '));
formattedText.append(linestring);
QVectorIterator<ApplesoftToken>tokenIt(line.tokens);
while (tokenIt.hasNext())
{
ApplesoftToken token = tokenIt.next();
bool isBranchTarget = false;
if (token.isOptFmtToken())
{
switch (token.getTokenId())
{
case ApplesoftToken::OptFmtFlagFlowTargetNextTokenValue:
{
if (m_format_options.testFlag(ShowIntsAsHex))
isBranchTarget = true;
break;
}
case ApplesoftToken::OptFmtIndentLineBreakTokenValue:
{
if (m_format_options.testFlag(ReindentCode))
formattedText.append("\n");
break;
}
case ApplesoftToken::OptFmtIndentSpaceTokenValue:
{
if (m_format_options.testFlag(ReindentCode))
formattedText.append(" ");
break;
}
case ApplesoftToken::OptFmtIndentTabTokenValue:
{
if (m_format_options.testFlag(ReindentCode))
formattedText.append(" ");
break;
}
case ApplesoftToken::OptFmtLeadingSpaceTokenValue:
{
formattedText.append(" ");
break;
}
case ApplesoftToken::OptFmtReturnLineBreakTokenValue:
{
if (m_format_options.testFlag(BreakAfterReturn))
formattedText.append("\n");
break;
}
default:
{
break;
}
}
} // isOptFmt
else
{
QString tokenstr = token.getRawPrintableString();
if (token.getTokenId() == ApplesoftToken::IntegerTokenVal)
{
if (m_format_options.testFlag(ShowIntsAsHex) && !isBranchTarget)
{
quint32 ui32val = token.getUnsignedIntegerValue();
qint32 i32val = token.getIntegerValue();
if ((i32val < 128 && i32val >= -128) || ui32val < 256)
{
quint8 ui8 = ui32val;
tokenstr = HEXPREFIX+uint8ToHex(ui8);
}
else if ((i32val < 32768 && i32val >= -32768) || ui32val < 65536)
{
quint16 ui16 = ui32val;
tokenstr = HEXPREFIX+uint16ToHex(ui16);
}
else
{
tokenstr = HEXPREFIX+uint32ToHex(ui32val);
}
} // isShowIntsAsHex
}
if (m_format_options.testFlag(ShowCtrlChars))
{
tokenstr.replace(QChar(0x7f),QChar(0x2401));
for (int idx = 1; idx <= 0x1f; idx++) {
if (idx == '\n') continue;
tokenstr.replace(QChar(idx),QChar(idx+0x2400));
// tokenstr.replace(QChar(idx), QString("<%1>").arg(uint8ToHex(idx)));
}
} // if ShowCtrlChars
formattedText.append(tokenstr);
}
} // while tokenIt.hasNext()
formattedText.append("\n");
} // foreach line
m_formattedText = formattedText;
}
void ApplesoftFormatter::formatDocument(QTextDocument *doc)
{
if (!doc) return;
@ -314,7 +34,8 @@ void ApplesoftFormatter::formatDocument(QTextDocument *doc)
if (synhl)
{
cursor.insertText(linestring,ApplesoftToken::textFormat(ApplesoftToken::LineNumberTokenVal));
cursor.insertText(linestring,
ApplesoftToken::textFormat(ApplesoftToken::LineNumberTokenVal));
}
else
{
@ -406,19 +127,40 @@ void ApplesoftFormatter::formatDocument(QTextDocument *doc)
isBranchTarget = false;
}
if (m_format_options.testFlag(ShowCtrlChars))
// if (m_format_options.testFlag(ShowCtrlChars))
// {
// tokenstr.replace(QChar(0x7f),QChar(0x2401));
// for (int idx = 1; idx <= 0x1f; idx++) {
// if (idx == '\n') continue;
// tokenstr.replace(QChar(idx),QChar(idx+0x2400));
// }
// } // if ShowCtrlChars
QTextCharFormat invFormat = ApplesoftToken::defaultInverseTextFormat();
if (m_format_options.testFlag(SyntaxHighlighting))
invFormat = ApplesoftToken::textFormat(
ApplesoftToken::ControlCharTokenVal);
foreach (QChar ch, tokenstr)
{
tokenstr.replace(QChar(0x7f),QChar(0x2401));
for (int idx = 1; idx <= 0x1f; idx++) {
if (idx == '\n') continue;
tokenstr.replace(QChar(idx),QChar(idx+0x2400));
// tokenstr.replace(QChar(idx), QString("<%1>").arg(uint8ToHex(idx)));
if (ch == QChar(0x7f))
{
cursor.insertText(QChar(0x00d7),invFormat);
}
} // if ShowCtrlChars
//formattedText.append(tokenstr);
cursor.insertText(tokenstr,fmt);
else if (ch < QChar(' '))
{
if (m_format_options.testFlag(ShowCtrlChars))
{
QChar newch = ch.unicode()+0x40;
cursor.insertText(newch,invFormat);
}
}
else cursor.insertText(ch,fmt);
}
}

View File

@ -14,14 +14,13 @@ class ApplesoftFormatter : public QObject
public:
enum FormatOption {
NoOptions = 0x00,
NoOptions = 0x00,
SyntaxHighlighting = 0x01,
ShowCtrlChars = 0x02,
BreakAfterReturn = 0x04,
ReindentCode = 0x08,
ShowIntsAsHex = 0x10,
ShowCtrlChars = 0x02,
BreakAfterReturn = 0x04,
ReindentCode = 0x08,
ShowIntsAsHex = 0x10,
AllFlags = 0xffffffff
};
@ -31,15 +30,11 @@ public:
explicit ApplesoftFormatter(QObject *parent = 0);
void setFlags(FormatOptions options) { m_format_options = options; }
void setFile(ApplesoftFile *file);
FormatOptions flags() { return m_format_options; }
void formatText();
QString getFormattedText() const { return m_formattedText; }
QList<QPair<quint16, quint16> > flowTargets() const { return m_flowTargets; }
void newFormatText();
void formatDocument(QTextDocument *doc);
signals:
void newFile(ApplesoftFile *file);
@ -47,11 +42,9 @@ public slots:
private:
FormatOptions m_format_options;
QList<QPair<quint16, quint16> > m_flowTargets;
ApplesoftFile *m_file;
QString m_formattedText;
};

View File

@ -135,12 +135,18 @@ QString ApplesoftToken::getRawPrintableString() const
QTextCharFormat ApplesoftToken::defaultTextFormat()
{
QTextCharFormat tf; // Default
// tf.setFont(QFont("Courier"));
// tf.setFontPointSize(10);
tf.setForeground(Qt::black);
return tf;
}
QTextCharFormat ApplesoftToken::defaultInverseTextFormat()
{
QTextCharFormat tf;
tf.setForeground(Qt::white);
tf.setBackground(Qt::black);
return tf;
}
QTextCharFormat ApplesoftToken::textFormat(quint16 tokenType)
{
QTextCharFormat tf = defaultTextFormat();
@ -182,6 +188,12 @@ QTextCharFormat ApplesoftToken::textFormat(quint16 tokenType)
{
tf.setForeground(Qt::darkRed);
}
else if (tokenType == ControlCharTokenVal)
{
// Inverse of StringTokenVal
tf.setForeground(Qt::white);
tf.setBackground(Qt::blue);
}
return tf;
}

View File

@ -49,7 +49,7 @@ public:
static const quint16 OptFmtFlagFlowTargetNextTokenValue = 0xe004;
static const quint16 OptFmtReturnLineBreakTokenValue = 0xe005;
static const quint16 ControlCharTokenVal = 0xfffd;
static const quint16 LineNumberTokenVal = 0xfffe;
static const quint16 DefaultTokenVal = 0xffff;
@ -183,6 +183,8 @@ public:
return textFormat(m_token_id);
}
static QTextCharFormat defaultTextFormat();
static QTextCharFormat defaultInverseTextFormat();
static QTextCharFormat textFormat(quint16 tokentype) ;
QString getStringForToken(quint8 token) {
@ -190,7 +192,6 @@ public:
return m_tokens[token];
}
static QTextCharFormat defaultTextFormat();
bool isOptFmtToken() const { return (m_token_id >= 0xe000 && m_token_id < 0xf000); }

View File

@ -20,7 +20,7 @@ ApplesoftFileViewer::ApplesoftFileViewer(QWidget *parent) :
setWindowTitle(title);
m_formatter = new ApplesoftFormatter(this);
m_formatter->setFlags(ApplesoftFormatter::NoOptions);
m_formatter->setFlags(ApplesoftFormatter::ShowCtrlChars);
connect(ui->findButton,SIGNAL(clicked(bool)), SLOT(findText()));
m_isFirstFind = true;
ui->textArea->setUndoRedoEnabled(false);
@ -32,13 +32,15 @@ ApplesoftFileViewer::ApplesoftFileViewer(QWidget *parent) :
m_syntaxHighlightingAction = Q_NULLPTR;
m_showVarExplorerAction = Q_NULLPTR;
m_wordWrapAction = Q_NULLPTR;
m_showCtrlCharsAction = Q_NULLPTR;
toggleWordWrap(settings.value("ASViewer.WordWrap",true).toBool());
setIndentCode(settings.value("ASViewer.indentCode",false).toBool(), NoReformat);
setIntsAsHex(settings.value("ASViewer.intsAsHex",false).toBool(), NoReformat);
setBreakAfterReturn(settings.value("ASViewer.breakAfterReturn",false).toBool(), NoReformat);
setSyntaxHighlighting(settings.value("ASViewer.syntaxHighlighting",false).toBool(), NoReformat);
setSyntaxHighlighting(settings.value("ASViewer.syntaxHighlighting",true).toBool(), NoReformat);
setShowCtrlChars(settings.value("ASViewer.showCtrlChars",true).toBool(), NoReformat);
}
ApplesoftFileViewer::~ApplesoftFileViewer()
@ -52,7 +54,7 @@ bool ApplesoftFileViewer::makeMenuOptions(QMenu *menu)
if (!m_showIntsAction)
{
m_showIntsAction = new QAction("Show &Ints as Hex",menu);
m_showIntsAction = new QAction("Show Ints as &Hex",menu);
m_showIntsAction->setCheckable(true);
m_showIntsAction->setChecked(settings.value("ASViewer.intsAsHex",false).toBool());
setIntsAsHex(settings.value("ASViewer.intsAsHex",false).toBool(),NoReformat);
@ -83,6 +85,16 @@ bool ApplesoftFileViewer::makeMenuOptions(QMenu *menu)
}
menu->addAction(m_blankAfterReturnsAction);
if (!m_showCtrlCharsAction)
{
m_showCtrlCharsAction = new QAction("Show &Control Characters",menu);
m_showCtrlCharsAction->setCheckable(true);
m_showCtrlCharsAction->setChecked(settings.value("ASViewer.showCtrlChars",false).toBool());
setIndentCode(settings.value("ASViewer.showCtrlChars",false).toBool(),NoReformat);
connect(m_showCtrlCharsAction, SIGNAL(toggled(bool)), ui->findText,SLOT(clear()));
connect(m_showCtrlCharsAction, SIGNAL(toggled(bool)),SLOT(setShowCtrlChars(bool)));
}
menu->addAction(m_showCtrlCharsAction);
menu->addSeparator();
@ -175,6 +187,22 @@ void ApplesoftFileViewer::setBreakAfterReturn(bool enabled, ReformatRule reforma
reformatText();
}
void ApplesoftFileViewer::setShowCtrlChars(bool enabled, ReformatRule reformat)
{
if (enabled)
{
m_formatter->setFlags(m_formatter->flags() | ApplesoftFormatter::ShowCtrlChars);
}
else
{
m_formatter->setFlags(m_formatter->flags() & ~ApplesoftFormatter::ShowCtrlChars);
}
QSettings settings;
settings.setValue("ASViewer.showCtrlChars",enabled);
if (reformat == ForceReformat)
reformatText();
}
void ApplesoftFileViewer::setSyntaxHighlighting(bool enabled, ReformatRule reformat)
{
if (enabled)

View File

@ -50,6 +50,7 @@ protected slots:
void setIndentCode(bool enabled, ReformatRule reformat = ForceReformat);
void setIntsAsHex(bool enabled, ReformatRule reformat = ForceReformat);
void setBreakAfterReturn(bool enabled, ReformatRule reformat = ForceReformat);
void setShowCtrlChars(bool enabled, ReformatRule reformat = ForceReformat);
void launchVarBrowser();
void reformatText();
@ -67,6 +68,7 @@ private:
QAction *m_syntaxHighlightingAction;
QAction *m_showVarExplorerAction;
QAction *m_wordWrapAction;
QAction *m_showCtrlCharsAction;
};
#endif // APPLESOFTFILEVIEWER_H