+typedef struct _buttonrecord
+{
+ U16 id;
+ MATRIX matrix;
+ CXFORM cxform;
+ char set;
+} buttonrecord_t;
+
+typedef struct _button
+{
+ int endofshapes;
+ int nr_actions;
+ buttonrecord_t records[4];
+} button_t;
+
+static button_t mybutton;
+
+void s_button(char*name)
+{
+ tag = swf_InsertTag(tag, ST_DEFINEBUTTON2);
+ swf_SetU16(tag, id); //id
+ swf_ButtonSetFlags(tag, 0); //menu=no
+
+ memset(&mybutton, 0, sizeof(mybutton));
+
+ memset(&stack[stackpos], 0, sizeof(stack[0]));
+ stack[stackpos].type = 3;
+ stack[stackpos].tag = tag;
+ stack[stackpos].id = id;
+ stack[stackpos].name = strdup(name);
+ stack[stackpos].oldrect = currentrect;
+ memset(¤trect, 0, sizeof(currentrect));
+
+ stackpos++;
+ incrementid();
+}
+void s_buttonput(char*character, char*as, parameters_t p)
+{
+ character_t* c = dictionary_lookup(&characters, character);
+ MATRIX m;
+ int flags = 0;
+ char*o = as,*s = as;
+ buttonrecord_t r;
+ if(!stackpos || (stack[stackpos-1].type != 3)) {
+ syntaxerror(".show may only appear in .button");
+ }
+ if(!c) {
+ syntaxerror("character %s not known (in .shape %s)", character, character);
+ }
+ if(mybutton.endofshapes) {
+ syntaxerror("a .do may not precede a .show", character, character);
+ }
+
+ m = s_instancepos(c->size, &p);
+
+ r.id = c->id;
+ r.matrix = m;
+ r.cxform = p.cxform;
+ r.set = 1;
+
+ while(1) {
+ if(*s==',' || *s==0) {
+ if(!strncmp(o,"idle",s-o)) {mybutton.records[0]=r;o=s+1;}
+ else if(!strncmp(o,"shape",s-o)) {mybutton.records[0]=r;o=s+1;}
+ else if(!strncmp(o,"hover",s-o)) {mybutton.records[1]=r;o=s+1;}
+ else if(!strncmp(o,"pressed",s-o)) {mybutton.records[2]=r;o=s+1;}
+ else if(!strncmp(o,"area",s-o)) {mybutton.records[3]=r;o=s+1;}
+ else syntaxerror("unknown \"as\" argument: \"%s\"", strdup_n(o,s-o));
+ }
+ if(!*s)
+ break;
+ s++;
+ }
+}
+static void setbuttonrecords(TAG*tag)
+{
+ int flags[] = {BS_UP,BS_OVER,BS_DOWN,BS_HIT};
+ if(!mybutton.endofshapes) {
+ int t;
+
+ if(!mybutton.records[3].set) {
+ memcpy(&mybutton.records[3], &mybutton.records[0], sizeof(buttonrecord_t));
+ }
+
+ for(t=0;t<4;t++) {
+ if(mybutton.records[t].set) {
+ swf_ButtonSetRecord(tag,flags[t],mybutton.records[t].id,1,&mybutton.records[t].matrix,&mybutton.records[t].cxform);
+ }
+ }
+ swf_SetU8(tag,0); // end of button records
+ mybutton.endofshapes = 1;
+ }
+}
+
+void s_buttonaction(int flags, char*action)
+{
+ ActionTAG* a = 0;
+ if(flags==0) {
+ return;
+ }
+ setbuttonrecords(stack[stackpos-1].tag);
+
+ a = swf_ActionCompile(text, stack[0].swf->fileVersion);
+ if(!a) {
+ syntaxerror("Couldn't compile ActionScript");
+ }
+
+ swf_ButtonSetCondition(stack[stackpos-1].tag, flags);
+ swf_ActionSet(stack[stackpos-1].tag, a);
+ mybutton.nr_actions++;
+
+ swf_ActionFree(a);
+}
+
+static void setactionend(TAG*tag)
+{
+ if(!mybutton.nr_actions) {
+ /* no actions means we didn't have an actionoffset,
+ which means we can't signal the end of the
+ buttonaction records, so, *sigh*, we have
+ to insert a dummy record */
+ swf_SetU16(tag, 0); //offset
+ swf_SetU16(tag, 0); //condition
+ swf_SetU8(tag, 0); //action
+ }
+}
+
+static void s_endButton()
+{
+ SRECT r;
+ setbuttonrecords(stack[stackpos-1].tag);
+ setactionend(stack[stackpos-1].tag);
+ stackpos--;
+
+ swf_ButtonPostProcess(stack[stackpos].tag, mybutton.nr_actions);
+
+ r = currentrect;
+
+ tag = stack[stackpos].tag;
+ currentrect = stack[stackpos].oldrect;
+
+ s_addcharacter(stack[stackpos].name, stack[stackpos].id, stack[stackpos].tag, r);
+ free(stack[stackpos].name);
+}
+