* This is a first step in the attempt to write a matrix editor. Clearly this * statement could easily be replaced by a function. However, when I tackle * 2-dimensional arrays, both row and column indices must be catered for. * This cannot be done with a function. At this stage I envisage that the * statement for matrices will have the syntax: * MCURSOR ,,,,, where riv is row index variable, * civ=column index variable, b=minimum index value, u1=row maximum and * u2=column maximum. Since it is not until the appropriate cursor key has * been pressed that we know whether row or column index is to change * only a statement can be used. I suppose that the ultimate goal is a full * binary program to handle the complete editor. Meanwhile, here is the first, * faltering start. LEX 'VCURSOR'* A statement to facilitate array index handling. ID #EC * Jack Elhay, 24/2/88. MSG 0 POLL 0 ENTRY vcurs CHAR #D * a statement, generally usable KEY 'VCURS' * Syntax: VCURS ,, TOKEN 128 * var=variable, n.e.=numeric expression ENDTXT * The 1st numeric expression is the minimum value that the variable will range * over, while the second is the maximum. The statement updates the variable * according to which key is pressed while TITAN waits, dozing. The endline * key leaves the variable unchanged, while the vertical cursor keys work as * follows: ^ decrements the var, v increments, g^ sets it to the minimum and * gv sets it to the maximum. Other keys are locked out. EXPEXC EQU #0F186 * evaluate expression, put value on mathstack RNDAHX EQU #136CB * pop,test and round to a HEX integer ARGERR EQU #0BF19 * invalid argument error exit SLEEP EQU #006C2 * light sleep function CKSREQ EQU #00721 * check for service requests POPBUF EQU #010EE * pop a key from the key buffer into B(B) DEST EQU #0F7B0 * save var. info for STORE (after EXPEXC) HDFLT EQU #1B31B * HEX integer to floating point number conversion STORE EQU #0F5F8 * store result into variable NXTSTM EQU #08A48 * normal exit for statements FIXDC EQU #05493 * FIX decompile FIXP EQU #02A6E * FIX parse SYNTXe EQU #02E2B * syntax error exit NUMCK EQU #0369D * check for numeric expression in parse COMCK+ EQU #032AE * check for comma in parse VARP EQU #0350E * variable parse NTOKEN EQU #0493B * output next token VCURSd GOVLNG FIXDC * decompile VCURSp GOSBVL VARP * parse the variable GONC Syntxe * carry clear means a string, set a numeric variable GOSBVL NTOKEN * output the comma token which follows GOSUB Comck+ * check that it is a comma GONC Syntxe * error if not GOSUB Numck * next must come a numeric expn or number GOSUB Comck+ * and another comma GOC fixp * FIXP takes care of the rest Syntxe GOVLNG SYNTXe * syntax error exit fixp GOVLNG FIXP * all OK Numck GOVLNG NUMCK Comck+ GOVLNG COMCK+ Expexc GOVLNG EXPEXC Rndahx GOVLNG RNDAHX Argerr GOVLNG ARGERR REL(5) VCURSd REL(5) VCURSp vcurs SETHEX * start in HEX mode CD0EX * save D0 in R3 D0=C R3=C Sleep GOSBVL SLEEP * go to sleep while awaiting a keystroke GONC KEY * a key pressed? GOSBVL CKSREQ * was it pressed by external keyboard? GOTO Sleep * no - back to sleep. KEY GOSBVL POPBUF * a key was pressed; pop it A=0 A * A(A) will be used to save info on which key it was C=0 W * need C clear to load bytes for valid keys LCHEX #26A3A23332 * each byte represents a valid key LOOP ?B=C B * does our key match the byte in C(B)? GOYES ON * leave the loop A=A+1 A * otherwise increment A(A) by 1 CSR W * 2 right shifts to bring the next byte into C(B) CSR W ?C#0 B * any more bytes? GOYES LOOP * try some more GOTO Sleep * otherwise go back to sleep, no valid key was pressed Err GOTO Argerr * jump extender ON D1=(5) #2F98B * this location is in reserved RAM for temporary DAT1=A 1 * storage of 1 nib defining which valid key it was C=R3 * pick up D0's value D0=C * and restore it GOSUB Expexc * evaluate the variable, put value on mathstack GOSBVL DEST * save identifying info for later storage D0=D0+ 2 * move past comma GOSUB Expexc * evaluate 2nd parameter (the minimum) D0=D0+ 2 * past comma GOSUB Expexc * evaluate last parameter GOSUB Rndahx * pop this parameter GONC Err * no negatives R2=A * save max. in R2 D1=D1+ 16 * want next parameter GOSUB Rndahx * pop it GONC Err R1=A * save min. in R1 C=R2 * recall max. C=C-A A * max.-min. C=C+1 A * add 1 to difference R3=C * save in R3 D1=D1+ 16 * point D1 to value of variable GOSUB Rndahx * pop it GONC Err R0=A * save variable's value in R0 A=0 W * we shall be using A to determine the action to take CD1EX * save D1 in C D1=(5) #2F98B * locate our defining nib A=DAT1 1 * read it D1=C * restore D1 A=A-1 A * decrement A(0) GOC DECR * our index was to decrease by 1 A=A-1 A * decrement A(0) GOC INCR * our index was to increase by 1 A=A-1 A * another decrement of A(0) GOC BOT * index to minimum A=A-1 A GOC TOP * index to maximum A=R0 * otherwise index unchanged GOTO OUT * out to exit routine BOT A=R1 * pick up minimum value GOTO OUT * and output it TOP A=R2 * pick up maximum GOTO OUT * output it INCR A=R0 * old var value +1 A=A+1 A * increment old value C=R2 * maximum ?C>=A A * is new value <= maximum? GOYES OUT * OK, output it C=R3 * otherwise wrap back into index range A=A-C A GOTO OUT * then out DECR A=R0 * old value var ?A#0 A * need this to avoid A(A)=FFFFF GOYES NOTZER * no problems C=R3 * otherwise we must first add (max-min+1) A=A+C A NOTZER A=A-1 A * now safe to decrement index C=R1 * the minimum ?C<=A A * is our index >= the min.? GOYES OUT * OK, we can finish C=R3 * otherwise, wrap again A=A+C A OUT GOSBVL HDFLT * convert to decimal floating point DAT1=A W * write to stack (NOTE: 1st 16 nibs must be in A) GOSBVL STORE * save the new value as dictated by info from DEST GOVLNG NXTSTM * and exit