You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tqscintilla/qt/qextscintillamacro.cpp

330 lines
5.8 KiB

// This module implements the QextScintillaMacro class.
//
// Copyright (c) 2006
// Riverbank Computing Limited <info@riverbankcomputing.co.uk>
//
// This file is part of TQScintilla.
//
// This copy of TQScintilla 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.
//
// TQScintilla 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
// TQScintilla; 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 <tqstring.h>
#include "qextscintillamacro.h"
#include "qextscintilla.h"
static TQCString extract(const TQCString &asc,int &start);
static int fromHex(unsigned char ch);
// The ctor.
QextScintillaMacro::QextScintillaMacro(QextScintilla *parent,const char *name)
: TQObject(parent,name), qsci(parent)
{
}
// The ctor that initialises the macro.
QextScintillaMacro::QextScintillaMacro(const TQCString &asc,
QextScintilla *parent,const char *name)
: TQObject(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 TQCString &asc)
{
bool rc = TRUE;
macro.clear();
int pos = 0;
while (pos < asc.length())
{
TQCString 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.
TQCString QextScintillaMacro::save() const
{
TQCString ms;
for (TQValueList<Macro>::const_iterator it = macro.begin(); it != macro.end(); ++it)
{
if (!ms.isEmpty())
ms += ' ';
unsigned len = (*it).text.size();
TQCString 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 (TQValueList<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,
TQT_SIGNAL(SCN_MACRORECORD(unsigned int,unsigned long,long)),
TQT_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.
TQByteArray &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 TQCString extract(const TQCString &asc,int &fstart)
{
TQCString 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;
}