The MXPM Format

Xzewd can now understand a home-grown format for animated snapshots, the MXPM format. This is a technical description of what you put in an MXPM file to make an animated snapshot. Install it like you would any other snapshot.

Note that MXPM is an unstable format! I'm not sure how good the parser I wrote is. The only way to find out is to try using it, so bang on it, and write me mail if you have problems.

This is gonna get technical, but bear with me.

The first thing in an MXPM file is the preamble, which should look exactly like this:

/* MXPM */
Other comments /* */ can be freely sprinkled throughout the file, most anywhere a space would be accepted.

Following the preamble comes a set of #defines, which determine the direction the file will be played and the number of frames in the file. The number of frames is mandatory; the direction is optional.

The number of frames is given by a line that looks like this:

#define <name>_frames 2
where <name> is replaced by some name, consisting of letters, numbers, and spaces. THIS NAME IS IMPORTANT!! The first <name> that the parser finds will be assumed to be the name for the entire file. Thus, any later information which contains a <name> must match the first <name> encountered.

The direction is given by something like this:

#define <name>_direction MXPM_WHATEVER
where MXPM_WHATEVER can be one of MXPM_FORWARD, MXPM_BACKWARD, MXPM_ALTERNATE, and MXPM_RANDOM. (These directions are the same as the directions the drumming fingers can go in the sender window.)

Following the #defines is however many comments and C statements you like. Each C statement must be terminated by a semicolon. A good use of C statements is to declare XPM's to be defined later on in the MXPM file; see the example below for how to do that.

After all this comes the MXPM definition itself. It looks like this:

static MXPMSequenceItem <name>_items[] = {
   /* comment comment comment if you want one */
   < one item definition for each frame >
   };
Each item definition looks like this:
    { <number of ticks>,
      <either &<name of in-file XPM> or NULL>,
      <either "<name of external file>" or NULL>
    },
The <number of ticks> is the number of ticks that xzewd will display that frame of the sequence for. Normally, one tick equals one second, but the user can change that tick value for herself with the xzewd-snapshots*tickTime resource (value in milliseconds).

The next thing is either NULL if the picture for that frame is in an external file, or &<name-of-XPM> if the picture for that frame is an XPM file contained later on in the MXPM file.

The next thing is either NULL if the picture for that frame is in an internal XPM, or "<pathname>" if the picture for that frame is an external file.

Following the MXPM definition itself comes, optionally, definitions for any internal XPM's specified in the MXPM section. They can come in any order; xzewd matches frame to XPM by the name. This does mean, though, that the <name-of-XPM> specified in the MXPM sequences must match the name of the XPM. To find the name of an XPM file, just look for a line that looks like this near the top of the XPM file:

static char * this_is_the_name_of_the_xpm[] = {
To stick an XPM file into an MXPM file, just insert it at the end. Nothing more special is needed.

As for external files, xzewd can understand any of the formats it normally understands for snapshots. If the pathname of an external file doesn't begin with a "/", xzewd will append it to the directory it found the MXPM file in.

Here's a sample MXPM file. Note that all 3 frames of the animation are stored within the file itself.

/* MXPM */

#define thing_direction MXPM_RANDOM
#define thing_frames 3

extern char *thing1[], *thing2[], *thing3[];
/* That line was optional. So is this one. */

static MXPMSequenceItem thing_items[] = {
	/* ticks, */
	{ 1, &thing1, NULL},
	{ 1, &thing2, NULL},
	{ 1, &thing3, NULL}};
	

/* I had to write everything above by hand.
   Everything below here, though, was copied
   straight from XPM's generated by xpaint. */
 
/* XPM */
static char *thing1[] = {
"20 20 11 1",
" 	c #000000000000",
".	c #F9006900A700",
"X	c #9A000000FF00",
"o	c #FF00FF00FF00",
"O	c #FF0000009A00",
"+	c #00000000DE00",
"@	c #B2002900F900",
"#	c #FF00FF003300",
"$	c #FF0000000000",
"%	c #14002900F900",
"&	c #0000FF000000",
" ..XoooooooooooooOoo",
"...oooXooooo++oooooo",
"..  oXoooooo++oooooo",
". @  oooooooooo#####",
" @@@ ooooooooooooooo",
"  @@@ oooo$ooo$oooXo",
"   @@@  o$ooo$ooooXo",
"  % @@@   oo$oooooXo",
" %%% @@@ ..$ooooooXo",
"%%%   @ ... ooooooXo",
"%%     ...  oooooooo",
"% &   ... @  ooo+ooo",
" &&& ... @@@ oooo+oo",
"  &&& .   @@@ oooo+o",
"   &&&     @@@  ooo+",
"  . &&&   % @@@  ooo",
" ... &&& %%% @@@ .oo",
"...   & %%%   @ ..+o",
"..     %%%     ... +",
". @   %%% &   ... @o"};

	
/* XPM */
static char * thing2[] = {
"20 20 3 1",
" 	c #FFFF00000000",
".	c #00000000FFFF",
"X	c #FFFF0000FFFF",
"             .......",
"            ........",
"            ........",
"            ........",
"           .........",
"           .........",
"           .........",
"          ..........",
"          ..........",
"    XXXX ...........",
"  XXXXXXXX..........",
" XXXXXXXXXXX........",
"XXXXXXXXXXXXXX......",
"XXXXXXXXXXXXXXX.....",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX"};

/* XPM */
static char * thing3[] = {
"20 20 3 1",
".	c #FFFF00000000",
"X	c #00000000FFFF",
" 	c #FFFF0000FFFF",
"             .......",
"            ........",
"            ........",
"            ........",
"           .........",
"           .........",
"           .........",
"          ..........",
"          ..........",
"    XXXX ...........",
"  XXXXXXXX..........",
" XXXXXXXXXXX........",
"XXXXXXXXXXXXXX......",
"XXXXXXXXXXXXXXX.....",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXX"};
Enjoy. Write if you have any questions.