Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -1632,10 +1632,14 @@ Key ( -- number ) During the input phase, the key input. During other phases, zero. During the input phase of coordinate input, this value will be 1. +,Key ( -- number true | false ) + If the key (as for Key command) is '1 to '9 or 'A to 'Z then it will be + the corresponding array index (as for %Q) and true, otherwise false. + land ( in1 in2 -- out ) Logical AND. le ( in1 in2 -- bool ) Test if first input is less or equal to second input (unsigned). @@ -1892,10 +1896,22 @@ string to contain substitution codes; see the section below about what substitution codes are allowed in popup messages. Each substitution code consumes some number of arguments, from bottom to top. The number of arguments must be 0 to 32. +Quiz ( -- ) ** + If used after PopUp, makes dismissing the popup message to send a KEY + message to this object instead of any other one. + +,Quiz ( any -- ) ** + If used after PopUp, makes dismissing the popup message to send a KEY + message to the specified object instead of any other one. If you specify + a class, then it will create an object of that class and use that one. + If you specify a message, then it will send that message to the Control + object, similar to specifying the Control object itself but will use the + specified message instead of KEY. + Rel ( dir -- dir ) Resolves a relative direction to an absolute direction. ,Rel ( obj dir -- dir ) Resolves a relative direction to an absolute direction, using the @@ -2242,10 +2258,15 @@ Display a picture. Consumes two arguments, being first a class and then the image number. If either argument is not valid, displays nothing. The picture may take up multiple lines of space; the lines will be moved farther apart to make room if necessary. +%Q + Display a quiz button from 1 to 9 or A to Z, depending on the current + array index. This is only valid inside of a %[ ... %] block, and it does + not itself consume any argument. + %R Display a roman number. %s Display a string. If the value is not a string, it will display it as @@ -2279,10 +2300,22 @@ Unconsume one argument. (Does not produce any output.) %> Skip one argument. (Does not produce any output.) +%[ + Consumes one argument, which must be an array; no further arguments can + be accessible in this case. If it is not an array then all further output + is suppressed (even past the end of this block, too). This cannot occur + more than once. The second dimension is the number of records, and the + first is the fields within that record; all further data accessed by the + substitution codes are the data within the array. + +%] + End of an array block; if there are any more records in the array then it + will access the next record and go back to the beginning of this block. + === Messages === This section describes when the various standard messages are sent to objects, and what return values are expected. (Do not confuse CREATE with Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -1984,10 +1984,13 @@ const unsigned char*t; const unsigned char*u; sqlite3_str*s; Value v; int argi=1; + const unsigned char*at=0; + int ax; + Value av; if(argc>32 || argc<0) Throw("Too many arguments"); vstackptr-=argc; v=Pop(); if(quiz_text) return; if(argc) { @@ -2028,10 +2031,15 @@ int n=vstack[vstackptr+argi+1].u&255; if(nnimages) sqlite3_str_appendf(s,"\x0E\x07:%d\\",c->images[n]&0x7FFF); } argi+=2; break; + case 'Q': + if(!at) break; + sqlite3_str_appendchar(s,1,16); + sqlite3_str_appendchar(s,1,ax<10?ax+'0':ax+'A'-10); + break; case 'R': if(argi==argc) break; v=vstack[vstackptr+argi++]; if(v.t==TY_NUMBER) { static const char*const r1000[10]={"","M","MM","MMM","MMMM","MMMMM","MMMMMM","MMMMMMM","MMMMMMMM","MMMMMMMMM"}; @@ -2095,10 +2103,31 @@ case '<': if(argi>0) --argi; break; case '>': if(argi>26)&0x3F)+1; + if(vstackptr+argc>=VSTACKSIZE) { + sqlite3_free(sqlite3_str_finish(s)); + Throw("Stack overflow"); + } + at=t; + // fall through + case ']': + if(!at) break; + if(ax>((av.u>>16)&0x3FF)) break; + for(argi=0;argi>26)&0x3F)*ax]; + t=at; + argi=0; + ax++; break; default: if(main_options['t'] || main_options['v']) fprintf(stderr,"Unrecognized %% code in (PopUp)\n"); break; } @@ -2105,10 +2134,11 @@ } else { sqlite3_str_appendall(s,t); break; } } + end: sqlite3_str_appendchar(s,1,0); quiz_text=sqlite3_str_finish(s); } else { switch(v.t) { case TY_STRING: case TY_LEVELSTRING: @@ -2135,10 +2165,21 @@ quiz_obj.u=from; } if(*t==31 && t[1]) t+=2; else t+=1; } } + +static void v_set_quiz(Uint32 from,Value v) { + if(v.t==TY_CLASS) { + from=create(from,v.u,objects[from]->x?:1,objects[from]->y?:1,0,objects[from]->dir); + if(from==VOIDLINK) Throw("Error creating object"); + quiz_obj=OVALUE(from); + } else { + if(v.t!=TY_MESSAGE) v_object(v); + quiz_obj=v; + } +} static int v_dispatch(const Uint16*code) { int i=msgvars.arg1.u; if(msgvars.arg1.t!=TY_NUMBER) Throw("Type mismatch"); if(!i || (msgvars.arg1.u&~0xFF) || !code[i]) { @@ -3161,10 +3202,11 @@ case OP_JUMPTO: NoIgnore(); StackReq(2,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); Push(NVALUE(jump_to(obj,obj,t2.u,t3.u))); break; case OP_JUMPTO_C: NoIgnore(); StackReq(3,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); i=v_object(Pop()); Push(NVALUE(jump_to(obj,i,t2.u,t3.u))); break; case OP_JUMPTO_D: NoIgnore(); StackReq(2,0); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); jump_to(obj,obj,t2.u,t3.u); break; case OP_JUMPTO_CD: NoIgnore(); StackReq(3,0); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); i=v_object(Pop()); jump_to(obj,i,t2.u,t3.u); break; case OP_KEY: StackReq(0,1); Push(NVALUE(current_key)); break; + case OP_KEY_C: StackReq(0,2); i=current_key; if((i>='1' && i<='9') || (i>='A' && i<='Z')) Push(NVALUE(i&64?i+9-'A':i-'1')),Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_KEYCLEARED: StackReq(0,1); if(o->oflags&OF_KEYCLEARED) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_KEYCLEARED_C: StackReq(1,1); GetFlagOf(OF_KEYCLEARED); break; case OP_KEYCLEARED_E: StackReq(1,0); if(v_bool(Pop())) o->oflags|=OF_KEYCLEARED; else o->oflags&=~OF_KEYCLEARED; break; case OP_KEYCLEARED_EC: StackReq(2,0); SetFlagOf(OF_KEYCLEARED); break; case OP_LAND: StackReq(2,1); t1=Pop(); t2=Pop(); if(v_bool(t1) && v_bool(t2)) Push(NVALUE(1)); else Push(NVALUE(0)); break; @@ -3267,10 +3309,12 @@ case OP_QN: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t==TY_NUMBER) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_QO: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t>TY_MAXTYPE) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_QOZ: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t>TY_MAXTYPE || (t1.t==TY_NUMBER && !t1.u)) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_QS: StackReq(1,1); t1=Pop(); NotSound(t1); if(t1.t==TY_STRING || t1.t==TY_LEVELSTRING) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_QUEEN: StackReq(0,1); Numeric(msgvars.arg1); i="\x06\x01\x07\x05\x03\x04\x02\x00"[msgvars.arg1.u&7]; Push(NVALUE(i)); break; + case OP_QUIZ: NoIgnore(); if(quiz_text) quiz_obj=OVALUE(obj); break; + case OP_QUIZ_C: NoIgnore(); StackReq(1,0); t1=Pop(); if(quiz_text) v_set_quiz(obj,t1); break; case OP_REL: StackReq(1,1); t1=Pop(); Numeric(t1); i=resolve_dir(obj,t1.u); Push(NVALUE(i)); break; case OP_REL_C: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); i=v_object(t1); i=(i==VOIDLINK?t2.u:resolve_dir(i,t2.u)); Push(NVALUE(i)); break; case OP_REPLACE: NoIgnore(); StackReq(5,1); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); Push(v_replace(obj,t1,t2,t3,t4,t5)); break; case OP_REPLACE_D: NoIgnore(); StackReq(5,0); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_replace(obj,t1,t2,t3,t4,t5); break; case OP_RET: return; @@ -3749,16 +3793,24 @@ i=classes[objects[n]->class]->cflags; if(i&CF_INPUT) v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),v,NVALUE(0)); if(i&CF_PLAYER) m=n; n=objects[n]->prev; } + } else if(quiz_obj.t==TY_MESSAGE) { + n=quiz_obj.u; + quiz_obj=NVALUE(0); + if(control_obj!=VOIDLINK) v=send_message(VOIDLINK,control_obj,n,NVALUE(key),NVALUE(0),NVALUE(1)); } else { n=quiz_obj.u; - if(objects[n]->generation!=quiz_obj.t) n=VOIDLINK; - quiz_obj=NVALUE(0); - if(classes[objects[n]->class]->cflags&CF_COMPATIBLE) all_flushed=1; - v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),NVALUE(0),NVALUE(1)); + if(!objects[n] || objects[n]->generation!=quiz_obj.t) { + quiz_obj=NVALUE(0); + all_flushed=1; + } else { + quiz_obj=NVALUE(0); + if(classes[objects[n]->class]->cflags&CF_COMPATIBLE) all_flushed=1; + v=send_message(VOIDLINK,n,MSG_KEY,NVALUE(key),NVALUE(0),NVALUE(1)); + } } } else if(has_xy_input && key>=0x8000 && key<=0x8FFF) { x=((key>>6)&63)+1; y=(key&63)+1; if(x>pfwidth || y>pfheight) return "Illegal move"; current_key=KEY_XY; Index: instruc ================================================================== --- instruc +++ instruc @@ -200,11 +200,11 @@ =Arg1 =Arg2 =Arg3 =MoveNumber Level -Key +,Key =Finished ; Top level definitions -Background -CodePage @@ -213,11 +213,11 @@ -LevelTable -InputXY ; Class definitions -Input --Quiz +,Quiz -InPlace -DefaultImage -Help -EditorHelp -Others Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -298,10 +298,11 @@ #define OP_ARG3_E 36998 #define OP_MOVENUMBER 32903 #define OP_MOVENUMBER_E 36999 #define OP_LEVEL 32904 #define OP_KEY 32905 +#define OP_KEY_C 34953 #define OP_FINISHED 32906 #define OP_FINISHED_E 37002 #define OP_BACKGROUND 32907 #define OP_CODEPAGE 32908 #define OP_ORDER 32909 @@ -308,10 +309,11 @@ #define OP_CONTROL 32910 #define OP_LEVELTABLE 32911 #define OP_INPUTXY 32912 #define OP_INPUT 32913 #define OP_QUIZ 32914 +#define OP_QUIZ_C 34962 #define OP_INPLACE 32915 #define OP_DEFAULTIMAGE 32916 #define OP_HELP 32917 #define OP_EDITORHELP 32918 #define OP_OTHERS 32919 @@ -640,11 +642,11 @@ {"JumpTo",10584247}, {"KEWEL",8389421}, {"KEY",8389129}, {"KLECK",8389387}, {"KLINKK",8389385}, -{"Key",8421513}, +{"Key",8487049}, {"KeyCleared",8618099}, {"L",9437194}, {"LASTIMAGE",8389126}, {"LB",9437195}, {"LF",9437193}, @@ -702,11 +704,11 @@ {"POUR",8389377}, {"POWER",8389386}, {"Player",8487037}, {"PopUp",8421582}, {"Queen",8683772}, -{"Quiz",8683666}, +{"Quiz",8487058}, {"R",9437198}, {"RATCHET1",8389417}, {"RATCHET2",8389411}, {"RATTLE",8389402}, {"RB",9437197},