diff options
Diffstat (limited to 'qt/qextscintillamacro.cpp')
-rw-r--r-- | qt/qextscintillamacro.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/qt/qextscintillamacro.cpp b/qt/qextscintillamacro.cpp new file mode 100644 index 0000000..7d2d358 --- /dev/null +++ b/qt/qextscintillamacro.cpp @@ -0,0 +1,329 @@ +// This module implements the QextScintillaMacro class. +// +// Copyright (c) 2006 +// Riverbank Computing Limited <info@riverbankcomputing.co.uk> +// +// This file is part of QScintilla. +// +// This copy of QScintilla 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 2, or (at your option) any +// later version. +// +// QScintilla is supplied 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 +// QScintilla; see the file LICENSE. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#include <string.h> + +#include <qstring.h> + +#include "qextscintillamacro.h" +#include "qextscintilla.h" + + +static QCString extract(const QCString &asc,int &start); +static int fromHex(unsigned char ch); + + +// The ctor. +QextScintillaMacro::QextScintillaMacro(QextScintilla *parent,const char *name) + : QObject(parent,name), qsci(parent) +{ +} + + +// The ctor that initialises the macro. +QextScintillaMacro::QextScintillaMacro(const QCString &asc, + QextScintilla *parent,const char *name) + : QObject(parent,name), qsci(parent) +{ + load(asc); +} + + +// The dtor. +QextScintillaMacro::~QextScintillaMacro() +{ +} + + +// Clear the contents of the macro. +void QextScintillaMacro::clear() +{ + macro.clear(); +} + + +// Read a macro from a string. +bool QextScintillaMacro::load(const QCString &asc) +{ + bool rc = TRUE; + + macro.clear(); + + int pos = 0; + + while (pos < asc.length()) + { + QCString fld; + Macro cmd; + unsigned len; + + // Extract the 3 fixed fields. + fld = extract(asc,pos); + cmd.msg = fld.toUInt(&rc); + + if (!rc) + break; + + fld = extract(asc,pos); + cmd.wParam = fld.toULong(&rc); + + if (!rc) + break; + + fld = extract(asc,pos); + len = fld.toUInt(&rc); + + if (!rc) + break; + + // Extract any text. + if (len) + { + cmd.text.resize(len); + fld = extract(asc,pos); + + char *dp = cmd.text.data(); + const char *sp = fld; + + if (!sp) + { + rc = FALSE; + break; + } + + while (len--) + { + unsigned char ch; + + ch = *sp++; + + if (ch == '"' || ch <= ' ' || ch >= 0x7f) + { + rc = FALSE; + break; + } + + if (ch == '\\') + { + int b1, b2; + + if ((b1 = fromHex(*sp++)) < 0 || + (b2 = fromHex(*sp++)) < 0) + { + rc = FALSE; + break; + } + + ch = (b1 << 4) + b2; + } + + *dp++ = ch; + } + + if (!rc) + break; + } + + macro.append(cmd); + } + + if (!rc) + macro.clear(); + + return rc; +} + + +// Write a macro to a string. +QCString QextScintillaMacro::save() const +{ + QCString ms; + + for (QValueList<Macro>::const_iterator it = macro.begin(); it != macro.end(); ++it) + { + if (!ms.isEmpty()) + ms += ' '; + + unsigned len = (*it).text.size(); + QCString m; + + m.sprintf("%u %lu %u",(*it).msg,(*it).wParam,len); + + if (len) + { + m += ' '; + + const char *cp = (*it).text.data(); + + while (len--) + { + unsigned char ch = *cp++; + + if (ch == '\\' || ch == '"' || ch <= ' ' || ch >= 0x7f) + { + char buf[4]; + + sprintf(buf,"\\%02x",ch); + m += buf; + } + else + m += ch; + } + } + + ms += m; + } + + return ms; +} + + +// Play the macro. +void QextScintillaMacro::play() +{ + if (!qsci) + return; + + for (QValueList<Macro>::const_iterator it = macro.begin(); it != macro.end(); ++it) + qsci -> SendScintilla((*it).msg,(*it).wParam,(*it).text.data()); +} + + +// Start recording. +void QextScintillaMacro::startRecording() +{ + if (!qsci) + return; + + macro.clear(); + + connect(qsci, + SIGNAL(SCN_MACRORECORD(unsigned int,unsigned long,long)), + SLOT(record(unsigned int,unsigned long,long))); + + qsci -> SendScintilla(QextScintillaBase::SCI_STARTRECORD); +} + + +// End recording. +void QextScintillaMacro::endRecording() +{ + if (!qsci) + return; + + qsci -> SendScintilla(QextScintillaBase::SCI_STOPRECORD); + qsci -> disconnect(this); +} + + +// Record a command. +void QextScintillaMacro::record(unsigned int msg,unsigned long wParam, + long lParam) +{ + Macro m; + + m.msg = msg; + m.wParam = wParam; + + // Determine commands which need special handling of the parameters. + switch (msg) + { + case QextScintillaBase::SCI_ADDTEXT: + m.text.duplicate(reinterpret_cast<const char *>(lParam),wParam); + break; + + case QextScintillaBase::SCI_REPLACESEL: + if (!macro.isEmpty() && macro.last().msg == QextScintillaBase::SCI_REPLACESEL) + { + const char *text = reinterpret_cast<const char *>(lParam); + + // This is the command used for ordinary user input so + // it's a signifacant space reduction to append it to + // the previous command. + + QByteArray &ba = macro.last().text; + + unsigned pos = ba.size() - 1; + + // Make room for the new text. + ba.resize(ba.size() + strlen(text)); + + // Copy it in. + strcpy(ba.data() + pos,text); + + return; + } + + /* Drop through. */ + + case QextScintillaBase::SCI_INSERTTEXT: + case QextScintillaBase::SCI_APPENDTEXT: + case QextScintillaBase::SCI_SEARCHNEXT: + case QextScintillaBase::SCI_SEARCHPREV: + { + const char *text = reinterpret_cast<const char *>(lParam); + + m.text.duplicate(text,strlen(text) + 1); + break; + } + } + + macro.append(m); +} + + +// Extract a macro field starting at the given position. +static QCString extract(const QCString &asc,int &fstart) +{ + QCString f; + + if (fstart < asc.length()) + { + int fend = asc.find(' ',fstart); + + if (fend < 0) + { + f = asc.mid(fstart); + fstart = asc.length(); + } + else + { + f = asc.mid(fstart,fend - fstart); + fstart = fend + 1; + } + } + + return f; +} + + +// Return the given hex character as a binary. +static int fromHex(unsigned char ch) +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + + if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + + return -1; +} |