Decode/encode .macro files

Discuss and announce AkelPad plugins
Post Reply
  • Author
  • Message
Offline
Posts: 60
Joined: Tue Aug 21, 2012 11:17 am
Location: UK

Decode/encode .macro files

Post by tmsg »

The attached C program decodes and encodes .macro files as used by the Macro plugin. This can be used to edit or clean-up .macro files.

First decode the file with

Code: Select all

readMacro -decode c:\AkelPad\Plugs\Macros\some.macro c:\put\output\here.txt
then edit the resulting text file and finally encode it back with

Code: Select all

readMacro -encode c:\put\output\here.txt c:\AkelPad\Plugs\Macros\someother.macro
This was a simple and rather quick-and-dirty attempt but it seems to do its job well enough. I can also upload a compiled version if someone points me to an appropriate upload location. In the long run (very long, perhaps;-)) I might try to add this capability to the Macro plugin, in the form of separate Import and Export commands.

It is certainly possible to write new keyboard macros from scratch but unless you know a few things about how Windows keypress messages work it's probably best to start with already recorded and working (!) macros.

If something's not working or if there are suggestions please notify me.

TM

Code: Select all

/*
**  readMacro converts binary AkelPad .macro files to editable text files and vice versa.
**  Version 0.1_2012-09-23. This file and the code it contains are in the public domain.
**
**  readMacro takes three or four arguments: readMacro mode [infile] [outfile]
**  mode is either -decode (from .macro file to text) or -encode (text to .macro).
**
**  In decoding mode infile is a .macro file and outfile (optional) is the output
**  textfile (if no outfile is given, readMacro writes to stdout).
**
**  If encoding infile (optional) is a textfile, outfile is the output .macro file
**  (if no infile is given, readMacro reads from stdin).
**
**  Decoding a .macro into a text file and encoding this back into a .macro file
**  should produce identical files.
*/

#include <malloc.h>
#include <stdio.h>
#include <string.h>

typedef struct _KEYACT {
	unsigned char bVk;
	unsigned int dwFlags;
} KEYACT;

#define VK_MAX  0x92
char *VKs[VK_MAX]={0};
char *flags[5]={"d",       // KEYDOWN
                "dx",      // KEYDOWN and EXTENDED
                "u",       // KEYUP
                "ux",      // KEYUP and EXTENDED
                "0x%04x"   // undefined
               };

int error(char *err) {
	fprintf(stderr,"%s\n",err);
	return -1;
}

int main(int argc, char **argv) {
	FILE *infile,*outfile;
	VKs[0x08]="back";
	VKs[0x09]="tab";
	VKs[0x0C]="clear";
	VKs[0x0D]="return";
	VKs[0x10]="shift";
	VKs[0x11]="control";
	VKs[0x12]="menu";
	VKs[0x13]="pause";
	VKs[0x14]="capital";
	VKs[0x15]="kana";
	VKs[0x17]="junja";
	VKs[0x18]="final";
	VKs[0x19]="hanja";
	VKs[0x19]="kanji";
	VKs[0x1B]="escape";
	VKs[0x1C]="convert";
	VKs[0x1D]="nonconvert";
	VKs[0x1E]="accept";
	VKs[0x1F]="modechange";
	VKs[0x20]="space";
	VKs[0x21]="prior";
	VKs[0x22]="next";
	VKs[0x23]="end";
	VKs[0x24]="home";
	VKs[0x25]="left";
	VKs[0x26]="up";
	VKs[0x27]="right";
	VKs[0x28]="down";
	VKs[0x29]="select";
	VKs[0x2A]="print";
	VKs[0x2B]="execute";
	VKs[0x2C]="snapshot";
	VKs[0x2D]="insert";
	VKs[0x2E]="delete";
	VKs[0x2F]="help";
	VKs[0x30]="0";
	VKs[0x31]="1";
	VKs[0x32]="2";
	VKs[0x33]="3";
	VKs[0x34]="4";
	VKs[0x35]="5";
	VKs[0x36]="6";
	VKs[0x37]="7";
	VKs[0x38]="8";
	VKs[0x39]="9";
	VKs[0x41]="a";
	VKs[0x42]="b";
	VKs[0x43]="c";
	VKs[0x44]="d";
	VKs[0x45]="e";
	VKs[0x46]="f";
	VKs[0x47]="g";
	VKs[0x48]="h";
	VKs[0x49]="i";
	VKs[0x4A]="j";
	VKs[0x4B]="k";
	VKs[0x4C]="l";
	VKs[0x4D]="m";
	VKs[0x4E]="n";
	VKs[0x4F]="o";
	VKs[0x50]="p";
	VKs[0x51]="q";
	VKs[0x52]="r";
	VKs[0x53]="s";
	VKs[0x54]="t";
	VKs[0x55]="u";
	VKs[0x56]="v";
	VKs[0x57]="w";
	VKs[0x58]="x";
	VKs[0x59]="y";
	VKs[0x5A]="z";
	VKs[0x5B]="lwin";
	VKs[0x5C]="rwin";
	VKs[0x5D]="apps";
	VKs[0x5F]="sleep";
	VKs[0x60]="numpad0";
	VKs[0x61]="numpad1";
	VKs[0x62]="numpad2";
	VKs[0x63]="numpad3";
	VKs[0x64]="numpad4";
	VKs[0x65]="numpad5";
	VKs[0x66]="numpad6";
	VKs[0x67]="numpad7";
	VKs[0x68]="numpad8";
	VKs[0x69]="numpad9";
	VKs[0x6A]="multiply";
	VKs[0x6B]="add";
	VKs[0x6C]="separator";
	VKs[0x6D]="subtract";
	VKs[0x6E]="decimal";
	VKs[0x6F]="divide";
	VKs[0x70]="f1";
	VKs[0x71]="f2";
	VKs[0x72]="f3";
	VKs[0x73]="f4";
	VKs[0x74]="f5";
	VKs[0x75]="f6";
	VKs[0x76]="f7";
	VKs[0x77]="f8";
	VKs[0x78]="f9";
	VKs[0x79]="f10";
	VKs[0x7A]="f11";
	VKs[0x7B]="f12";
	VKs[0x7C]="f13";
	VKs[0x7D]="f14";
	VKs[0x7E]="f15";
	VKs[0x7F]="f16";
	VKs[0x80]="f17";
	VKs[0x81]="f18";
	VKs[0x82]="f19";
	VKs[0x83]="f20";
	VKs[0x84]="f21";
	VKs[0x85]="f22";
	VKs[0x86]="f23";
	VKs[0x87]="f24";
	VKs[0x90]="numlock";
	VKs[0x91]="scroll";
  // If adding further elements change VK_MAX!

	if (argc<3||argc>4) return error("Wrong number of arguments: mode [infile] [outfile]\n"
	                                 "  mode is either -decode (from .macro file to text) or -encode (text to .macro).\n"
	                                 "  If decoding infile is a .macro file, outfile (optional) is the output textfile\n"
	                                 "  (if no outfile is given, readMacro writes to stdout).\n"
	                                 "  If encoding infile (optional) is a textfile, outfile is the output .macro file\n"
	                                 "  (if no infile us given, readMacro reads from stdin).\n");
	if (!stricmp(argv[1],"-decode")) {
		unsigned long fileLen,n=0;
		char flag[16];
		KEYACT *ka;
		if (!(infile=fopen(argv[2],"rb"))) return error("Unable to open infile");
		fseek(infile,0,SEEK_END);
		fileLen=ftell(infile);
		fseek(infile,0,SEEK_SET);
		ka=(KEYACT *)malloc(fileLen);
		if (!ka) {
			fclose(infile);
			return error("Memory allocation failed");
		}
		fread(ka,fileLen,1,infile);
		fclose(infile);
		if (argc==3) outfile=stdout;
		else if (!(outfile=fopen(argv[3],"w+"))) return error("Unable to open outfile");
		while (n<fileLen) {
			if (ka->dwFlags>3) sprintf(flag,flags[4],ka->dwFlags);
			else strcpy(flag,flags[ka->dwFlags]);
			if (VKs[ka->bVk]&&ka->dwFlags<4) fprintf(outfile,"%s %s\n",VKs[ka->bVk],flag);
			else fprintf(outfile,"# %i %s\n",ka->bVk,flag);
			ka++;
			n=n+sizeof(KEYACT);
		}
		if (argc==4) fclose(outfile);
		free(ka);
		fprintf(stderr,"Conversion successful, %i items converted.\n",n/sizeof(KEYACT));
	}
	else if (!stricmp(argv[1],"-encode")) {
		char buf[64];
		KEYACT ka;
		int j=0;
		if (argc==3) infile=stdin;
		else if (!(infile=fopen(argv[2],"r"))) return error("Unable to open infile");
		if (!(outfile=fopen(argv[argc-1],"wb"))) {
			fclose(infile);
			return error("Unable to open outfile");
		}
		while (fgets(buf,sizeof(buf),infile)) {
			char *delim=strchr(buf,'\n');
			int i;
			if (buf[0]=='#') continue;
			if (delim) *delim=0;
			if (!(delim=strchr(buf,' '))) {
				printf("warning: unrecognised input\n");
				continue;
			}
			*delim=0;
			delim++;
			memset(&ka,0,sizeof(ka));
			if (!stricmp(delim,flags[0])) ka.dwFlags=0;
			else if (!stricmp(delim,flags[1])) ka.dwFlags=1;
			else if (!stricmp(delim,flags[2])) ka.dwFlags=2;
			else if (!stricmp(delim,flags[3])) ka.dwFlags=3;
			else {
				printf("warning: unrecognised flag, entry skipped\n");
				continue;
			}
			ka.bVk=255;
			for (i=0;i<VK_MAX;i++) {
				if (VKs[i]&&(!stricmp(buf,VKs[i]))) {
					ka.bVk=(unsigned char)i;
					break;
				}
			}
			if (ka.bVk==255) {
				printf("warning: unrecognised VK, entry skipped\n");
				continue;
			}
			printf("%08x %08x\n",ka.bVk,ka.dwFlags);
			if (fwrite(&ka,sizeof(ka),1,outfile)!=1) {
				fclose(infile);
				fclose(outfile);
				error("Error while writing outfile");
			}
			j++;
		}
		if (argc==4) fclose(infile);
		fclose(outfile);
		fprintf(stderr,"Conversion successful, %i items converted.\n",j);

	}
	else return error("Unrecognised mode switch, use either -decode or -encode");
	return 1;
}

Offline
Posts: 147
Joined: Fri Feb 08, 2008 6:41 pm
Location: British Columbia, Canada

MacTool

Post by Surveyor »

Please see here. Compiler is complete - decompiler works - but only back to keystrokes, not to "source" language. Got little/no reponse to post, so decompiler may wait...

Offline
Posts: 60
Joined: Tue Aug 21, 2012 11:17 am
Location: UK

Re: MacTool

Post by tmsg »

Surveyor wrote:Please see here. Compiler is complete - decompiler works - but only back to keystrokes, not to "source" language. Got little/no reponse to post, so decompiler may wait...
Well... I did search the forum for something like this but found nothing:-/.

I agree that keyboard macros, if done well, are extremely flexible and often underrated. (In the old DOS days I used an editor with absolutely perfect record/replay capabilities... I've never found a macro-capable editor that good later on.)

Anyway, your attempt seems much more ambitious and more complete than my q-n-d fix. I'll have a look.

TM

Offline
Posts: 147
Joined: Fri Feb 08, 2008 6:41 pm
Location: British Columbia, Canada

Post by Surveyor »

tmsg wrote:I'll have a look.
I would greatly appreciate any/all comments or criticisms about MacTool, if you get a chance to look at it. The "normal decompile" (to source) is actually started, but needs some more work - hopefully, when done, it will generate at least strings, keypresses (and compound kepresses) from macros. Detection of REPEAT loops and SNIPPETs may come later, but this may not be necessary. The real power comes from just using a source language instead of memorization from the keyboard. MacTool source code is freely available on request, but it is written in Pascal (I am an OLD Dos Pascal programmer!).

In the Dos days, I used Turbo Pascal (3.0 and 5.5) a lot - they both had editors which responded to Wordstar commands, which I found very quick. For macros, I also used something called QEdit (by Semware?) which had great macro capability, but only with keyboard memorization, I think (at least that's all I used).

BTW, MacTool is a command-line app, but does a sort of drag-and-drop emulaton which is quite a bit easier than running from the command prompt. It's in the help file...

Cheers from Canada!
- Surveyor

Offline
Posts: 1
Joined: Tue Jan 14, 2014 10:05 pm

Re: MacTool

Post by ps281 »

Surveyor wrote:Please see here. Compiler is complete - decompiler works - but only back to keystrokes, not to "source" language. Got little/no reponse to post, so decompiler may wait...you may have to check here later.
So decompiler does work but not to source language?
Post Reply