1 /*
2 FXiTe - The Free eXtensIble Text Editor
3 Copyright (c) 2009-2013 Jeffrey Pohlmeyer <yetanothergeek@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License version 3 as
7 published by the Free Software Foundation.
8
9 This software is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19
20 #include <fx.h>
21 #include <Scintilla.h>
22
23 #include "compat.h"
24 #include "macro.h"
25
26 #include "intl.h"
27 #include "recorder.h"
28
29
30 #define _LUAMOD_ LUA_MODULE_NAME
31
32 struct MacroMessage {
33 int message;
34 uptr_t wParam;
35 sptr_t lParam;
36 unsigned char allocd;
37 };
38
MacroRecorder()39 MacroRecorder::MacroRecorder():FXObject() {
40
41 }
42
43
44
45 #define NewMessage() \
46 MacroMessage* mm=new MacroMessage; \
47 mm->message=message; \
48 mm->wParam=wParam; \
49 mm->lParam=lParam; \
50 mm->allocd=0; \
51 list.prepend((FXObject*)mm);
52
53
54
55 #define AddString() { \
56 NewMessage(); \
57 mm->lParam=reinterpret_cast<long>(strdup((char*)lParam)); \
58 mm->allocd=1; \
59 }
60
61
62
63 #define AppendString() { \
64 char *s=(char*)calloc(strlen((char*)prev->lParam)+strlen((char*)lParam)+1,1); \
65 strcpy(s,(char*)prev->lParam); \
66 strcat(s,(char*)lParam); \
67 free((void*)prev->lParam); \
68 prev->lParam=reinterpret_cast<long>(s); \
69 }
70
71
record(int message,uptr_t wParam,sptr_t lParam)72 void MacroRecorder::record(int message, uptr_t wParam, sptr_t lParam)
73 {
74 FXString msgstring;
75 MacroMessage*prev=list[0];
76 switch (message) {
77 case SCI_CUT:
78 case SCI_COPY:
79 case SCI_CLEARALL:
80 case SCI_SELECTALL:
81 case SCI_HOME:
82 case SCI_HOMEEXTEND:
83 case SCI_LINEEND:
84 case SCI_LINEENDEXTEND:
85 case SCI_HOMEWRAP:
86 case SCI_HOMEWRAPEXTEND:
87 case SCI_LINEENDWRAP:
88 case SCI_LINEENDWRAPEXTEND:
89 case SCI_DOCUMENTSTART:
90 case SCI_DOCUMENTSTARTEXTEND:
91 case SCI_DOCUMENTEND:
92 case SCI_DOCUMENTENDEXTEND:
93 case SCI_LINECOPY:
94 case SCI_LINECUT:
95 case SCI_LINEDELETE:
96 case SCI_LOWERCASE:
97 case SCI_UPPERCASE:
98 case SCI_COPYALLOWLINE:
99 case SCI_HOMERECTEXTEND:
100 case SCI_LINEENDRECTEXTEND:
101 case SCI_SEARCHANCHOR:
102 {
103 if ((!prev)||(prev->message!=message)) {
104 NewMessage();
105 }
106 return;
107 }
108
109 case SCI_GOTOLINE:
110 case SCI_GOTOPOS:
111 case SCI_SETSELECTIONMODE:
112 {
113 if ((!prev)||(prev->message!=message)||(prev->wParam!=wParam)||(prev->lParam!=lParam)) {
114 NewMessage();
115 }
116 return;
117 }
118
119 case SCI_REPLACESEL:
120 case SCI_ADDTEXT:
121 case SCI_INSERTTEXT:
122 case SCI_APPENDTEXT:
123 {
124 if ((prev) && (prev->message==message)) {
125 AppendString();
126 } else {
127 AddString();
128 }
129 return;
130 }
131
132 case SCI_SEARCHNEXT:
133 case SCI_SEARCHPREV:
134 {
135 if (!prev) {
136 AddString();
137 } else {
138 if ((prev->message==SCI_SEARCHNEXT)||(prev->message==SCI_SEARCHPREV)) {
139 NewMessage();
140 if (strcmp((char*)prev->lParam,(char*)lParam)==0) {
141 mm->lParam=prev->lParam;
142 } else {
143 mm->lParam=reinterpret_cast<long>(strdup((char*)lParam));
144 mm->allocd=1;
145 }
146 } else {
147 AddString();
148 }
149 }
150 return;
151 }
152 case SCI_REPLACETARGET: { // Hijacked message, see SciSearch::NotifyRecorder()
153 AddString();
154 return;
155 }
156 case SCI_PASTE:
157 case SCI_LINEDOWN:
158 case SCI_LINEDOWNEXTEND:
159 case SCI_PARADOWN:
160 case SCI_PARADOWNEXTEND:
161 case SCI_LINEUP:
162 case SCI_LINEUPEXTEND:
163 case SCI_PARAUP:
164 case SCI_PARAUPEXTEND:
165 case SCI_CHARLEFT:
166 case SCI_CHARLEFTEXTEND:
167 case SCI_CHARRIGHT:
168 case SCI_CHARRIGHTEXTEND:
169 case SCI_WORDLEFT:
170 case SCI_WORDLEFTEXTEND:
171 case SCI_WORDRIGHT:
172 case SCI_WORDRIGHTEXTEND:
173 case SCI_WORDPARTLEFT:
174 case SCI_WORDPARTLEFTEXTEND:
175 case SCI_WORDPARTRIGHT:
176 case SCI_WORDPARTRIGHTEXTEND:
177 case SCI_WORDLEFTEND:
178 case SCI_WORDLEFTENDEXTEND:
179 case SCI_WORDRIGHTEND:
180 case SCI_WORDRIGHTENDEXTEND:
181 case SCI_STUTTEREDPAGEUP:
182 case SCI_STUTTEREDPAGEUPEXTEND:
183 case SCI_STUTTEREDPAGEDOWN:
184 case SCI_STUTTEREDPAGEDOWNEXTEND:
185 case SCI_PAGEUP:
186 case SCI_PAGEUPEXTEND:
187 case SCI_PAGEDOWN:
188 case SCI_PAGEDOWNEXTEND:
189 case SCI_DELETEBACK:
190 case SCI_TAB:
191 case SCI_BACKTAB:
192 case SCI_FORMFEED:
193 case SCI_DELWORDLEFT:
194 case SCI_DELWORDRIGHT:
195 case SCI_EDITTOGGLEOVERTYPE:
196 case SCI_CANCEL:
197 case SCI_VCHOME:
198 case SCI_VCHOMEEXTEND:
199 case SCI_VCHOMEWRAP:
200 case SCI_VCHOMEWRAPEXTEND:
201 case SCI_DELWORDRIGHTEND:
202 case SCI_DELLINELEFT:
203 case SCI_DELLINERIGHT:
204 case SCI_LINETRANSPOSE:
205 case SCI_LINEDUPLICATE:
206 case SCI_HOMEDISPLAY:
207 case SCI_HOMEDISPLAYEXTEND:
208 case SCI_LINEENDDISPLAY:
209 case SCI_LINEENDDISPLAYEXTEND:
210 case SCI_LINEDOWNRECTEXTEND:
211 case SCI_LINEUPRECTEXTEND:
212 case SCI_CHARLEFTRECTEXTEND:
213 case SCI_CHARRIGHTRECTEXTEND:
214 case SCI_VCHOMERECTEXTEND:
215 case SCI_PAGEUPRECTEXTEND:
216 case SCI_PAGEDOWNRECTEXTEND:
217 case SCI_SELECTIONDUPLICATE:
218 case SCI_LINESCROLLDOWN:
219 case SCI_LINESCROLLUP:
220 case SCI_DELETEBACKNOTLINE:
221 case SCI_CLEAR:
222 {
223 if ( (!prev) || (prev->message!=message) ) {
224 NewMessage();
225 } else {
226 prev->lParam++;
227 }
228 return;
229 }
230 }
231 }
232
233
playback(PlaybackFunc callback,void * user_data)234 void MacroRecorder::playback(PlaybackFunc callback, void*user_data)
235 {
236
237 for (FXint i=list.no()-1; i>=0; i--) {
238 MacroMessage* mm=list[i];
239 callback(mm->message, mm->wParam, mm->lParam, user_data);
240 }
241 }
242
243
244
clear()245 void MacroRecorder::clear()
246 {
247
248 for (FXint i=list.no()-1; i>=0; i--) {
249 MacroMessage* mm=list[i];
250 if (mm->allocd) { free((void*)mm->lParam); }
251 delete mm;
252 }
253 list.clear();
254 }
255
256
257
~MacroRecorder()258 MacroRecorder::~MacroRecorder() {
259 clear();
260 }
261
requote(FXString & s)262 static void requote(FXString&s)
263 {
264 s.substitute("\\", "\\\\", true);
265 s.substitute("\n", "\\n", true);
266 s.substitute("\r", "\\r", true);
267 s.substitute("\"", "\\\"", true);
268 }
269
270 #define noimpl(msg) { text="-- message " msg " not implemented"; break; }
271
translate(TranslateFunc callback,void * user_data)272 void MacroRecorder::translate(TranslateFunc callback, void* user_data)
273 {
274
275 for (FXint i=list.no()-1; i>=0; i--) {
276 FXString text;
277 MacroMessage* mm=list[i];
278 switch (mm->message) {
279 case SCI_CUT: {
280 text=_LUAMOD_".cut()";
281 break;
282 }
283 case SCI_COPY: {
284 text=_LUAMOD_".copy()";
285 break;
286 }
287 case SCI_CLEARALL: {
288 text=_LUAMOD_".text(\"\")";
289 break;
290 }
291 case SCI_SELECTALL: {
292 text=_LUAMOD_".select(0," _LUAMOD_ ".nchars())";
293 break;
294 }
295
296
297 case SCI_HOME:
298 case SCI_VCHOME:{
299 text=_LUAMOD_".go(\"edge\", -1)";
300 break;
301 }
302
303 case SCI_HOMEEXTEND:
304 case SCI_VCHOMEEXTEND:{
305 text=_LUAMOD_".go(\"edge\", -1, true)";
306 break;
307 }
308
309
310 case SCI_LINEEND: {
311 text=_LUAMOD_".go(\"edge\", 1)";
312 break;
313 }
314 case SCI_LINEENDEXTEND: {
315 text=_LUAMOD_".go(\"edge\", 1, true)";
316 break;
317 }
318 case SCI_DOCUMENTSTART: {
319 text=_LUAMOD_".go(\"body\", -1)";
320 break;
321 }
322 case SCI_DOCUMENTSTARTEXTEND: {
323 text=_LUAMOD_".go(\"body\", -1, true)";
324 break;
325 }
326 case SCI_DOCUMENTEND: {
327 text=_LUAMOD_".go(\"body\", 1)";
328 break;
329 }
330 case SCI_DOCUMENTENDEXTEND: {
331 text=_LUAMOD_".go(\"body\", 1, true)";
332 break;
333 }
334 case SCI_HOMERECTEXTEND:
335 case SCI_VCHOMERECTEXTEND: {
336 text=_LUAMOD_".go(\"edge\", -1, true, true)";
337 break;
338 }
339 case SCI_LINEENDRECTEXTEND: {
340 text=_LUAMOD_".go(\"edge\", 1, true, true)";
341 break;
342 }
343 case SCI_GOTOLINE: {
344 text.format(_LUAMOD_".caret(%ld,%ld)", mm->wParam+1, mm->lParam);
345 break;
346 }
347 case SCI_GOTOPOS: {
348 if ((i>1)&&(list[i-1]->message==SCI_SEARCHNEXT)&&(list[i-2]->message==SCI_REPLACETARGET)&&(list[i-2]->wParam==2)) {
349 // If message was generated inside SciSearch::ReplaceAllInDoc() just ignore it.
350 } else {
351 text.format(_LUAMOD_".caret(%ld)", mm->wParam);
352 }
353 break;
354 }
355 case SCI_REPLACESEL: {
356 FXString s=(char*)mm->lParam;
357 FXint n=s.contains('\n');
358 if ( (n>0) && (s.length()>1) ) { // If multiple lines, split into lines for playback...
359 int p;
360 for (p=0; p<n; p++) {
361 FXString part=s.section('\n', p);
362 requote(part);
363 text.format(_LUAMOD_".insert(\"%s\\n\",true)", part.text());
364 callback(text.text(), user_data);
365 }
366 if (!s.section('\n', n).empty()) { // there may still be text beyond the last LF...
367 FXString part=s.section('\n', n);
368 requote(part);
369 text.format(_LUAMOD_".insert(\"%s\",true)", part.text());
370 callback(text.text(), user_data);
371 }
372 continue;
373 }
374 requote(s);
375 text.format(_LUAMOD_".insert(\"%s\",true)", s.text());
376 break;
377 }
378
379 case SCI_SEARCHNEXT:
380 case SCI_SEARCHPREV: {
381 FXString what=(char*)mm->lParam;
382 requote(what);
383 FXString flags="";
384 if (mm->wParam & SCFIND_MATCHCASE) { flags.append("\"matchcase\""); }
385 if (mm->wParam & SCFIND_WHOLEWORD) { flags.append(",\"wholeword\""); }
386 if (mm->wParam & SCFIND_REGEXP) { flags.append(",\"regexp\""); }
387 if (flags[0]==',') { flags.erase(0,1); }
388 if ((i>0)&&(list[i-1]->message==SCI_REPLACETARGET)) {
389 FXString with=(char*)list[i-1]->lParam;
390 requote(with);
391 const char*how=NULL;
392 switch (list[i-1]->wParam) {
393 case 0: { how=mm->message==SCI_SEARCHNEXT?"next":"prev"; break; }
394 case 1: { how="sel"; break; }
395 case 2: { how="all"; break; }
396 }
397 text.format(_LUAMOD_".replace(\"%s\",\"%s\", {%s},\"%s\")",
398 what.text(), with.text(), flags.text(), how );
399
400 } else {
401
402 text.format( _LUAMOD_".gofind(\"%s\", {%s}%s)",
403 what.text(), flags.text(), mm->message==SCI_SEARCHNEXT?"":", false" );
404 }
405 break;
406 }
407 case SCI_REPLACETARGET: {
408 break;
409 }
410 case SCI_PASTE: {
411 text=_LUAMOD_".paste()";
412 break;
413 }
414 case SCI_LINEDOWN: {
415 text.format(_LUAMOD_".go(\"line\", %ld)", mm->lParam+1);
416 break;
417 }
418 case SCI_LINEDOWNEXTEND: {
419 text.format(_LUAMOD_".go(\"line\", %ld, true)", mm->lParam+1);
420 break;
421 }
422 case SCI_PARADOWN: {
423 text.format(_LUAMOD_".go(\"para\", %ld)", mm->lParam+1);
424 break;
425 }
426 case SCI_PARADOWNEXTEND: {
427 text.format(_LUAMOD_".go(\"para\", %ld, true)", mm->lParam+1);
428 break;
429 }
430 case SCI_LINEUP: {
431 text.format(_LUAMOD_".go(\"line\", -%ld)", mm->lParam+1);
432 break;
433 }
434 case SCI_LINEUPEXTEND: {
435 text.format(_LUAMOD_".go(\"line\", -%ld, true)", mm->lParam+1);
436 break;
437 }
438 case SCI_PARAUP: {
439 text.format(_LUAMOD_".go(\"para\", -%ld)", mm->lParam+1);
440 break;
441 }
442 case SCI_PARAUPEXTEND: {
443 text.format(_LUAMOD_".go(\"para\", -%ld, true)", mm->lParam+1);
444 break;
445 }
446 case SCI_CHARLEFT: {
447 text.format(_LUAMOD_".go(\"char\", -%ld)", mm->lParam+1);
448 break;
449 }
450 case SCI_CHARLEFTEXTEND: {
451 text.format(_LUAMOD_".go(\"char\", -%ld, true)", mm->lParam+1);
452 break;
453 }
454 case SCI_CHARRIGHT: {
455 text.format(_LUAMOD_".go(\"char\", %ld)", mm->lParam+1);
456 break;
457 }
458 case SCI_CHARRIGHTEXTEND: {
459 text.format(_LUAMOD_".go(\"char\", %ld, true)", mm->lParam+1);
460 break;
461 }
462 case SCI_WORDLEFT: {
463 text.format(_LUAMOD_".go(\"word\", -%ld)", mm->lParam+1);
464 break;
465 }
466 case SCI_WORDLEFTEXTEND: {
467 text.format(_LUAMOD_".go(\"word\", -%ld, true)", mm->lParam+1);
468 break;
469 }
470 case SCI_WORDRIGHT: {
471 text.format(_LUAMOD_".go(\"word\", %ld)", mm->lParam+1);
472 break;
473 }
474 case SCI_WORDRIGHTEXTEND: {
475 text.format(_LUAMOD_".go(\"word\", %ld, true)", mm->lParam+1);
476 break;
477 }
478 case SCI_WORDPARTLEFT: {
479 text.format(_LUAMOD_".go(\"part\", -%ld)", mm->lParam+1);
480 break;
481 }
482 case SCI_WORDPARTLEFTEXTEND: {
483 text.format(_LUAMOD_".go(\"part\", -%ld, true)", mm->lParam+1);
484 break;
485 }
486 case SCI_WORDPARTRIGHT: {
487 text.format(_LUAMOD_".go(\"part\", %ld)", mm->lParam+1);
488 break;
489 }
490 case SCI_WORDPARTRIGHTEXTEND: {
491 text.format(_LUAMOD_".go(\"part\", %ld, true)", mm->lParam+1);
492 break;
493 }
494 case SCI_PAGEUP: {
495 text.format(_LUAMOD_".go(\"page\", -%ld)", mm->lParam+1);
496 break;
497 }
498 case SCI_PAGEUPEXTEND: {
499 text.format(_LUAMOD_".go(\"page\", -%ld, true)", mm->lParam+1);
500 break;
501 }
502 case SCI_PAGEDOWN: {
503 text.format(_LUAMOD_".go(\"page\", %ld)", mm->lParam+1);
504 break;
505 }
506 case SCI_PAGEDOWNEXTEND: {
507 text.format(_LUAMOD_".go(\"page\", %ld, true)", mm->lParam+1);
508 break;
509 }
510 case SCI_LINEDOWNRECTEXTEND: {
511 text.format(_LUAMOD_".go(\"line\", %ld, true, true)", mm->lParam+1);
512 break;
513 }
514 case SCI_LINEUPRECTEXTEND: {
515 text.format(_LUAMOD_".go(\"line\", -%ld, true, true)", mm->lParam+1);
516 break;
517 }
518 case SCI_CHARLEFTRECTEXTEND: {
519 text.format(_LUAMOD_".go(\"char\", -%ld, true, true)", mm->lParam+1);
520 break;
521 }
522 case SCI_CHARRIGHTRECTEXTEND: {
523 text.format(_LUAMOD_".go(\"char\", %ld, true, true)", mm->lParam+1);
524 break;
525 }
526 case SCI_PAGEUPRECTEXTEND: {
527 text.format(_LUAMOD_".go(\"page\", -%ld, true, true)", mm->lParam+1);
528 break;
529 }
530 case SCI_PAGEDOWNRECTEXTEND: {
531 text.format(_LUAMOD_".go(\"page\", %ld, true, true)", mm->lParam+1);
532 break;
533 }
534 case SCI_TAB: {
535 text.format(_LUAMOD_".indent(%ld)", mm->lParam+1);
536 break;
537 }
538 case SCI_BACKTAB: {
539 text.format(_LUAMOD_".indent(-%ld)", mm->lParam+1);
540 break;
541 }
542 case SCI_DELETEBACK: {
543 text.format(_LUAMOD_".delete(-%ld)", mm->lParam+1);
544 break;
545 }
546 case SCI_CLEAR: {
547 text.format(_LUAMOD_".delete(%ld)", mm->lParam+1);
548 break;
549 }
550 case SCI_UPPERCASE: {
551 text.format(_LUAMOD_".uppercase()");
552 break;
553 }
554 case SCI_LOWERCASE: {
555 text.format(_LUAMOD_".lowercase()");
556 break;
557 }
558 case SCI_DELWORDLEFT: {
559 text.format(_LUAMOD_".delete(\"word\", -%ld)", mm->lParam+1);
560 break;
561 }
562 case SCI_DELWORDRIGHT: {
563 text.format(_LUAMOD_".delete(\"word\", %ld)", mm->lParam+1);
564 break;
565 }
566 case SCI_DELLINELEFT: {
567 text.format(_LUAMOD_".delete(\"edge\", -1)");
568 break;
569 }
570 case SCI_DELLINERIGHT: {
571 text.format(_LUAMOD_".delete(\"edge\", 1)");
572 break;
573 }
574 case SCI_HOMEWRAP: noimpl("SCI_HOMEWRAP");
575 case SCI_HOMEWRAPEXTEND: noimpl("SCI_HOMEWRAP");
576 case SCI_LINEENDWRAP: noimpl("SCI_LINEENDWRAP");
577 case SCI_LINEENDWRAPEXTEND: noimpl("SCI_LINEENDWRAPEXTEND");
578 case SCI_LINECOPY: noimpl("SCI_LINECOPY");
579 case SCI_LINECUT: noimpl("SCI_LINECUT");
580 case SCI_LINEDELETE: noimpl("SCI_LINEDELETE");
581 case SCI_COPYALLOWLINE: noimpl("SCI_COPYALLOWLINE");
582 case SCI_SEARCHANCHOR: noimpl("SCI_SEARCHANCHOR");
583 case SCI_ADDTEXT: noimpl("SCI_ADDTEXT");
584 case SCI_INSERTTEXT: noimpl("SCI_INSERTTEXT");
585 case SCI_APPENDTEXT: noimpl("SCI_APPENDTEXT");
586 case SCI_WORDLEFTEND: noimpl("SCI_WORDLEFTEND");
587 case SCI_WORDLEFTENDEXTEND: noimpl("SCI_WORDLEFTENDEXTEND");
588 case SCI_WORDRIGHTEND: noimpl("SCI_WORDRIGHTEND");
589 case SCI_WORDRIGHTENDEXTEND: noimpl("SCI_WORDRIGHTENDEXTEND");
590 case SCI_STUTTEREDPAGEUP: noimpl("SCI_STUTTEREDPAGEUP");
591 case SCI_STUTTEREDPAGEUPEXTEND: noimpl("SCI_STUTTEREDPAGEUPEXTEND");
592 case SCI_STUTTEREDPAGEDOWN: noimpl("SCI_STUTTEREDPAGEDOWN");
593 case SCI_STUTTEREDPAGEDOWNEXTEND: noimpl("SCI_STUTTEREDPAGEDOWNEXTEND");
594 case SCI_FORMFEED: noimpl("SCI_FORMFEED");
595 case SCI_EDITTOGGLEOVERTYPE: noimpl("SCI_EDITTOGGLEOVERTYPE");
596 case SCI_CANCEL: noimpl("SCI_CANCEL");
597
598 case SCI_VCHOMEWRAP: noimpl("SCI_VCHOMEWRAP");
599 case SCI_VCHOMEWRAPEXTEND: noimpl("SCI_VCHOMEWRAPEXTEND");
600 case SCI_DELWORDRIGHTEND: noimpl("SCI_DELWORDRIGHTEND");
601 case SCI_LINETRANSPOSE: noimpl("SCI_LINETRANSPOSE");
602 case SCI_LINEDUPLICATE: noimpl("SCI_LINEDUPLICATE");
603 case SCI_HOMEDISPLAY: noimpl("SCI_HOMEDISPLAY");
604 case SCI_HOMEDISPLAYEXTEND: noimpl("SCI_HOMEDISPLAYEXTEND");
605 case SCI_LINEENDDISPLAY: noimpl("SCI_LINEENDDISPLAY");
606 case SCI_LINEENDDISPLAYEXTEND: noimpl("SCI_LINEENDDISPLAYEXTEND");
607 case SCI_SELECTIONDUPLICATE: noimpl("SCI_SELECTIONDUPLICATE");
608
609 case SCI_LINESCROLLDOWN: noimpl("SCI_LINESCROLLDOWN");
610 case SCI_LINESCROLLUP: noimpl("SCI_LINESCROLLUP");
611 case SCI_DELETEBACKNOTLINE: noimpl("SCI_DELETEBACKNOTLINE");
612 case SCI_SETSELECTIONMODE: noimpl("SCI_SETSELECTIONMODE");
613 }
614 callback(text.text(), user_data);
615 }
616 }
617
618
619
620 // Used by the macro recorder to translate "machine language" into a Lua macro.
TranslatorCB(const char * text,void * user_data)621 static void TranslatorCB(const char*text, void*user_data)
622 {
623 FXString*all=(FXString*)user_data;
624 all->append(text);
625 all->append('\n');
626 }
627
628
629
translate()630 const FXString MacroRecorder::translate()
631 {
632 FXString out;
633 translate(TranslatorCB,&out);
634 return out;
635 }
636
637