~ubuntu-branches/ubuntu/wily/tora/wily-proposed

« back to all changes in this revision

Viewing changes to src/qscintilla2/Qt4/qscimacro.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Meskes
  • Date: 2009-11-19 15:18:19 UTC
  • mfrom: (1.2.9 upstream) (3.3.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091119151819-me89ezmxzkvl0lws
Tags: 2.1.1-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// This module implements the QsciMacro class.
 
2
//
 
3
// Copyright (c) 2008 Riverbank Computing Limited <info@riverbankcomputing.com>
 
4
// 
 
5
// This file is part of QScintilla.
 
6
// 
 
7
// This file may be used under the terms of the GNU General Public
 
8
// License versions 2.0 or 3.0 as published by the Free Software
 
9
// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
 
10
// included in the packaging of this file.  Alternatively you may (at
 
11
// your option) use any later version of the GNU General Public
 
12
// License if such license has been publicly approved by Riverbank
 
13
// Computing Limited (or its successors, if any) and the KDE Free Qt
 
14
// Foundation. In addition, as a special exception, Riverbank gives you
 
15
// certain additional rights. These rights are described in the Riverbank
 
16
// GPL Exception version 1.1, which can be found in the file
 
17
// GPL_EXCEPTION.txt in this package.
 
18
// 
 
19
// Please review the following information to ensure GNU General
 
20
// Public Licensing requirements will be met:
 
21
// http://trolltech.com/products/qt/licenses/licensing/opensource/. If
 
22
// you are unsure which license is appropriate for your use, please
 
23
// review the following information:
 
24
// http://trolltech.com/products/qt/licenses/licensing/licensingoverview
 
25
// or contact the sales department at sales@riverbankcomputing.com.
 
26
// 
 
27
// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
 
28
// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
 
29
// A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
 
30
// granted herein.
 
31
// 
 
32
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
33
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
34
 
 
35
 
 
36
#include "Qsci/qscimacro.h"
 
37
 
 
38
#include <qstringlist.h>
 
39
 
 
40
#include "Qsci/qsciscintilla.h"
 
41
 
 
42
 
 
43
static int fromHex(unsigned char ch);
 
44
 
 
45
 
 
46
 
 
47
// The ctor.
 
48
QsciMacro::QsciMacro(QsciScintilla *parent)
 
49
    : QObject(parent), qsci(parent)
 
50
{
 
51
}
 
52
 
 
53
 
 
54
// The ctor that initialises the macro.
 
55
QsciMacro::QsciMacro(const QString &asc, QsciScintilla *parent)
 
56
    : QObject(parent), qsci(parent)
 
57
{
 
58
    load(asc);
 
59
}
 
60
 
 
61
 
 
62
// The dtor.
 
63
QsciMacro::~QsciMacro()
 
64
{
 
65
}
 
66
 
 
67
 
 
68
// Clear the contents of the macro.
 
69
void QsciMacro::clear()
 
70
{
 
71
    macro.clear();
 
72
}
 
73
 
 
74
 
 
75
// Read a macro from a string.
 
76
bool QsciMacro::load(const QString &asc)
 
77
{
 
78
    bool ok = true;
 
79
 
 
80
    macro.clear();
 
81
 
 
82
    QStringList fields = asc.split(' ');
 
83
 
 
84
    int f = 0;
 
85
 
 
86
    while (f < fields.size())
 
87
    {
 
88
        Macro cmd;
 
89
        unsigned len;
 
90
 
 
91
        // Extract the 3 fixed fields.
 
92
        if (f + 3 > fields.size())
 
93
        {
 
94
            ok = false;
 
95
            break;
 
96
        }
 
97
 
 
98
        cmd.msg = fields[f++].toUInt(&ok);
 
99
 
 
100
        if (!ok)
 
101
            break;
 
102
 
 
103
        cmd.wParam = fields[f++].toULong(&ok);
 
104
 
 
105
        if (!ok)
 
106
            break;
 
107
 
 
108
        len = fields[f++].toUInt(&ok);
 
109
 
 
110
        if (!ok)
 
111
            break;
 
112
 
 
113
        // Extract any text.
 
114
        if (len)
 
115
        {
 
116
            if (f + 1 > fields.size())
 
117
            {
 
118
                ok = false;
 
119
                break;
 
120
            }
 
121
 
 
122
            cmd.text.resize(len - 1);
 
123
 
 
124
            QByteArray ba = fields[f++].toAscii();
 
125
            const char *sp = ba.data();
 
126
 
 
127
            char *dp = cmd.text.data();
 
128
 
 
129
            if (!sp)
 
130
            {
 
131
                ok = false;
 
132
                break;
 
133
            }
 
134
 
 
135
            while (len--)
 
136
            {
 
137
                unsigned char ch;
 
138
 
 
139
                ch = *sp++;
 
140
 
 
141
                if (ch == '"' || ch <= ' ' || ch >= 0x7f)
 
142
                {
 
143
                    ok = false;
 
144
                    break;
 
145
                }
 
146
 
 
147
                if (ch == '\\')
 
148
                {
 
149
                    int b1, b2;
 
150
 
 
151
                    if ((b1 = fromHex(*sp++)) < 0 ||
 
152
                        (b2 = fromHex(*sp++)) < 0)
 
153
                    {
 
154
                        ok = false;
 
155
                        break;
 
156
                    }
 
157
 
 
158
                    ch = (b1 << 4) + b2;
 
159
                }
 
160
 
 
161
                *dp++ = ch;
 
162
            }
 
163
 
 
164
            if (!ok)
 
165
                break;
 
166
        }
 
167
 
 
168
        macro.append(cmd);
 
169
    }
 
170
        
 
171
    if (!ok)
 
172
        macro.clear();
 
173
 
 
174
    return ok;
 
175
}
 
176
 
 
177
 
 
178
// Write a macro to a string.
 
179
QString QsciMacro::save() const
 
180
{
 
181
    QString ms;
 
182
 
 
183
    QList<Macro>::const_iterator it;
 
184
 
 
185
    for (it = macro.begin(); it != macro.end(); ++it)
 
186
    {
 
187
        if (!ms.isEmpty())
 
188
            ms += ' ';
 
189
 
 
190
        unsigned len = (*it).text.size();
 
191
        QString m;
 
192
 
 
193
        ms += m.sprintf("%u %lu %u", (*it).msg, (*it).wParam, len);
 
194
 
 
195
        if (len)
 
196
        {
 
197
            // In Qt v3, if the length is greater than zero then it also
 
198
            // includes the '\0', so we need to make sure that Qt v4 writes the
 
199
            // '\0'.  (That the '\0' is written at all is probably a historical
 
200
            // bug - using size() instead of length() - which we don't fix so
 
201
            // as not to break old macros.)
 
202
            ++len;
 
203
 
 
204
            ms += ' ';
 
205
 
 
206
            const char *cp = (*it).text.data();
 
207
 
 
208
            while (len--)
 
209
            {
 
210
                unsigned char ch = *cp++;
 
211
 
 
212
                if (ch == '\\' || ch == '"' || ch <= ' ' || ch >= 0x7f)
 
213
                {
 
214
                    QString buf;
 
215
 
 
216
                    ms += buf.sprintf("\\%02x", ch);
 
217
                }
 
218
                else
 
219
                    ms += ch;
 
220
            }
 
221
        }
 
222
    }
 
223
 
 
224
    return ms;
 
225
}
 
226
 
 
227
 
 
228
// Play the macro.
 
229
void QsciMacro::play()
 
230
{
 
231
    if (!qsci)
 
232
        return;
 
233
 
 
234
    QList<Macro>::const_iterator it;
 
235
 
 
236
    for (it = macro.begin(); it != macro.end(); ++it)
 
237
        qsci->SendScintilla((*it).msg, (*it).wParam, (*it).text.data());
 
238
}
 
239
 
 
240
 
 
241
// Start recording.
 
242
void QsciMacro::startRecording()
 
243
{
 
244
    if (!qsci)
 
245
        return;
 
246
 
 
247
    macro.clear();
 
248
 
 
249
    connect(qsci, SIGNAL(SCN_MACRORECORD(unsigned int, unsigned long, void *)),
 
250
            SLOT(record(unsigned int, unsigned long, void *)));
 
251
 
 
252
    qsci->SendScintilla(QsciScintillaBase::SCI_STARTRECORD);
 
253
}
 
254
 
 
255
 
 
256
// End recording.
 
257
void QsciMacro::endRecording()
 
258
{
 
259
    if (!qsci)
 
260
        return;
 
261
 
 
262
    qsci->SendScintilla(QsciScintillaBase::SCI_STOPRECORD);
 
263
    qsci->disconnect(this);
 
264
}
 
265
 
 
266
 
 
267
// Record a command.
 
268
void QsciMacro::record(unsigned int msg, unsigned long wParam, void *lParam)
 
269
{
 
270
    Macro m;
 
271
 
 
272
    m.msg = msg;
 
273
    m.wParam = wParam;
 
274
 
 
275
    // Determine commands which need special handling of the parameters.
 
276
    switch (msg)
 
277
    {
 
278
    case QsciScintillaBase::SCI_ADDTEXT:
 
279
        m.text = QByteArray(reinterpret_cast<const char *>(lParam), wParam);
 
280
        break;
 
281
 
 
282
    case QsciScintillaBase::SCI_REPLACESEL:
 
283
        if (!macro.isEmpty() && macro.last().msg == QsciScintillaBase::SCI_REPLACESEL)
 
284
        {
 
285
            // This is the command used for ordinary user input so it's a
 
286
            // significant space reduction to append it to the previous
 
287
            // command.
 
288
 
 
289
            macro.last().text.append(reinterpret_cast<const char *>(lParam));
 
290
            return;
 
291
        }
 
292
 
 
293
        /* Drop through. */
 
294
 
 
295
    case QsciScintillaBase::SCI_INSERTTEXT:
 
296
    case QsciScintillaBase::SCI_APPENDTEXT:
 
297
    case QsciScintillaBase::SCI_SEARCHNEXT:
 
298
    case QsciScintillaBase::SCI_SEARCHPREV:
 
299
        m.text.append(reinterpret_cast<const char *>(lParam));
 
300
        break;
 
301
    }
 
302
 
 
303
    macro.append(m);
 
304
}
 
305
 
 
306
 
 
307
// Return the given hex character as a binary.
 
308
static int fromHex(unsigned char ch)
 
309
{
 
310
    if (ch >= '0' && ch <= '9')
 
311
        return ch - '0';
 
312
 
 
313
    if (ch >= 'a' && ch <= 'f')
 
314
        return ch - 'a' + 10;
 
315
 
 
316
    return -1;
 
317
}