Reference Manual for Macintosh version of Chipmunk Basic

       <a href="#Index">INDEX</a>


    Program Manipulation
    Program Execution
        Matrix Arithmetic
        Extended Precision
    String Manipulation
    Data File Access
    Data Input
    Data Output
        Machine Language
        Custom Menu
    Internal Stack
    Dynamic Storage
    Console Window
    Graphics Window
    Scripting and IAC
    Reserved Words and Symbols
    Authors and Acknowledgements

INTRODUCTION Chipmunk Basic for the Macintosh is an impressively powerful and versatile Basic interpreter. It features several modes of file I/O, a customizable pull-down menu, multiple graphics extensions including sprites and buttons, object-oriented type and class definition, matrix arithmetic, Fast Fourier Transform, many system services, and the flexible string handling that is one of Basic's traditional strengths. As is to be expected of non-commercial software, CB has its share of bugs, but nothing serious enough to impede the construction of useful programs, especially since the core of standard Basic elements works dependably. People who learned Basic in a high school or college course will find this freeware easy to use for recreational projects. Making its many features accessible to such people is one of the main purposes of this manual. As an interpreted language, Chipmunk Basic is bound to run slower than some compiled versions, but with the speed of today's machines that is almost never a problem. And the price is right. * * * * This document is intended primarily as a reference manual rather than an introduction or tutorial. It includes a lot more details than the man page or Quick Reference, but they were the starting point for it, so you will find most of the material from those documents reproduced here, except for the version history and the FAQ section of the Quick Reference. If you notice other details about CB's behavior that you think should be included in this manual, please send them to Steve Wise ( Bugs that are not already described here should be reported to CB's author, Ronald Nicholson ( CAUTION: This manual is based on Chipmunk Basic version 3.5.0. It includes descriptions of many features that are still in development and thus subject to revision. If you are using a different version of Chipmunk Basic, you will find that it disagrees with some parts of this manual. CONVENTIONS EXPR an expression that evaluates to a number. STRINGEXPR an expression that evaluates to a string. VAR a numeric variable. INTEGERVAR% a 16-bit variable. Name must end with a "%". STRINGVAR$ a string variable. Name must end with a "$". [ | ] Choose exactly one of these alternatives. { } The contents of these brackets are optional. { , ... } Optional additional arguments with the same syntax. For some commands the formal syntax is followed by a more colloquial paraphrase. Chipmunk Basic is frequently abbreviated "CB". PROGRAMS Multiple statements may be given on one line, separated by colons: input X : print X : stop : rem X must be a number Comments can be placed on the same line with code: input X : print X : stop 'X must be a number However, as of version 3.5.0 that doesn't work when the last statement on the line ends with a quote. In that case a colon must be included to make the comment a separate statement: on error goto handlerror input X : print "Input was successful." :'X must be numeric Real numbers can be entered in exponential form like 3E-7. Hexadecimal numbers can be entered by preceding them with a "0x" as in 0x02ae, or by "&h" as in &h0172. String literals can be delimited by either single or double quotes (but not curly quotes): print "Rome wasn't built in a daze." ^ print '"Possessions are nine tenths of the load."' cmd$ = 'print "exec() lets your program program!"' exec(cmd$) Variable names are case-insensitive. Variable names can be up to 31 significant characters, consisting of letters, digits, underscores, and an ending dollar sign ($) or percent (%). If a variable name ends with a "$" it holds strings of up to 254 characters. If a variable name ends with a "%" it holds 16-bit integer values. Other variable names hold 64-bit real numbers (IEEE double). At run time, all program lines must begin with a line number. Using spaces (indentation) between the line number and program statements is legal. Line numbers can be between 1 and 2147483647. Programs lines must not exceed 254 characters in length. Even though line numbers are required at the time a program executes, a program can be written in a more modern style without line numbers and still be run under Chipmunk Basic, because CB adds line numbers to any un-numbered lines it encounters while loading the program from a text file. Note that unlike a line number, a line label must be followed by a colon: 100 rem no colon needed on this line 200 Top: rem colon after label PROGRAM MANIPULATION A built-in line number based editor allows for program input from the console keyboard. Lines already entered and loaded lines displayed with the LIST command can be edited by clicking at the desired edit position. Once the line is modified, hitting <return> registers it, or executes it immediately if it lacks a line number. new Erase the program in memory. All files are closed and all variables are cleared. All buttons are removed. LINENUM { TEXT } Enters a program line. If a program line with the same line number already exists, it is replaced. If no TEXT is given, the program line with line number LINENUM is deleted. Line entry can be cancelled by typing control-U. load STRINGEXPR load filespec$ Loads a program into memory from the named file, which must be of type 'TEXT', and makes the file the current accessory source for resources. The program previously in memory is erased. All files are closed and all variables are cleared. filespec$ is the name of a file (not an alias) in the default folder, or a complete file path starting with the disk name. In the loaded file, blank lines are ignored, and lines beginning with # are treated as comments (also ignored, except for #cbas commands). Line numbers do not need to be in ascending order (although they will be executed in ascending order). A file may contain both numbered and un-numbered lines. Each un-numbered line is assigned a number, counting up in steps of 2 from the preceding line. Line numbers must be unique; loading terminates with an error message if a duplicate line number is encountered or assigned. The Chipmunk Basic package includes a BBEdit extension, "Chipmunk Basic Load Contents", that can be used to load a program without first saving it in a file. However, this routine simply feeds lines to CB the same as if you had copied the text in BBEdit and then pasted it into the console window. It does not invoke the interpreter's LOAD routine, so loading a program by this method requires that all program lines already be numbered. (Another BBEdit extension can add and remove line numbers for you.) Open (in the File menu) will put up a dialog to allow selection of a program file to load. The menu is normally restricted to files that end in ".bas", but if you hold down the option key when selecting "Open", all files of type 'TEXT' will be displayed. save STRINGEXPR { , "NLN" } save filespec$ Saves the current program to the named file in the default folder, or at the location specified by a complete path that starts with the disk name. When a modified program is saved to an existing source file, only its data fork is replaced, so its resources (if any) are preserved. However, when a modified program is saved in a new file, needed resources from the old version must be copied over with the help of ResEdit. If the optional argument is included, the program is saved without line numbers. This option should be used only if the program does not contain any line number references as in GOTO, SELECT CASE etc. (Line numbers are also suppressed if the NoLineNums mode is in effect.) Save As (in the File menu) saves the current program to a file using a standard dialog. In other respects it is the same as the "save" command described above. Save (in the File menu) saves the current program to the file that was loaded last; the file's data fork is replaced, but its resources (if any) are not affected. This command works only for program files that end in ".bas". It becomes available when the current program has been modified since it was last loaded. Trivial bug: as of version 3.5.0, if the program's name ends in ".bas", the keyboard equivalent Command-S works even when the menu option is dimmed because the program has not been modified. call "NoLineNums", [ 0 | 1 ] Turns line numbering on (0) or off (1) in list & save. Initially it is on. list List the whole program. list 10 List line 10. list 1-30 List lines 1 to 30. list -30 List lines up to 30. list 20- List lines from 20 on. Bug: As of version 3.5.0, line numbers above 999999999 will not list. merge STRINGEXPR merge FILE Load a program into memory. The previous program remains in memory; if a line exists in both programs, the newly loaded line replaces the old one. renum { VAL { , VAL { , VAL { , VAL } } } } renum { new, step, old, to } Renumber program lines. By default, the new sequence is 10,20,30... The optional first argument is a new initial line number; the second is the increment between line line numbers. The last two arguments are old line numbers: if the third argument is present, renumbering will start at that line instead of at the beginning, and if the fourth argument is supplied, renumbering will end at that line instead of continuing to the end of the program. RENUM can be used to move non-overlapping blocks of code. edit LINENUM Edit a single line. If the exit from the edit is via a cntrl-c then do not change the line. i insert till <return> x delete one char A append to end of line It's hard to see why anyone would want to use this relic of cpm days because as of version 3.5.0 it does not support the arrow keys for moving the cursor to the desired edit position. Clicking there with the mouse risks triggering a conflict with the graphics-based line editor. To escape, hit the window close box, then "Cancel". del [ LINENUM | LINENUM1-LINENUM2 ] { , ... } Delete a line if it exists, or lines in a specified range of line numbers. The starting and ending line numbers need not exist: lines inside the range will be deleted anyway. A line can also be deleted simply by entering the line number by itself. PROGRAM EXECUTION Basic commands and statements can be entered and interpreted in immediate mode or executed as program statements when the Basic program is run. run { LINENUM } run { STRINGEXPR { , LINENUM } } run FILE Begin execution of the program at the first line, or at the specified line. All variables are cleared and all files are closed. If a STRINGEXPR is given, the Basic program with that file name is loaded into memory first. Program lines are executed in line number order. Can be used to chain programs, but since variables are cleared the data needs to be transferred by saving it in a temporary file. But with today's multi-megabyte RAM, chaining is rarely needed any more. The Chipmunk Basic package includes a BBEdit extension, "Chipmunk Basic Run Contents", that can be used to load and run a program without first saving it in a file. However this routine simply feeds lines to CB the same as if you had copied the text in BBEdit and then pasted it into the console window. Unlike the RUN command, it does not invoke the interpreter's LOAD routine, so running a program by this method requires that all program lines already be numbered. (Another BBEdit extension can add and remove line numbers for you.) Minor bug: as of version 3.5.0 the program text must be longer than 32 characters for the "Run Contents" command to work. goto [ LINENUM | LABEL ] This statement will transfer control to the line specified. When it is issued from the keyboard (in immediate mode), this command will begin execution at the specified line without clearing the variables. An "Undefined line" error will occur if LINENUM or LABEL doesn't exist in the program. on error goto [ LINENUM | LABEL ] LINENUM or LABEL identifies the line to which control is transferred if an error occurs. A GOTO or CONT statement can be used to resume execution. An error inside a named SUB subroutine cannot be resumed from or CONTinued. Some errors can be caught by the user program using this command. An error handler can retrieve the offending line number in ERL, and the nature of the error in ERRORSTATUS$. If no error trapping routine has been designated with this command, when an error occurs the program execution is terminated and a message reporting these two values is printed to the console. exec ( STRINGEXPR ) exec( statement$ ) Executes STRINGEXPR as a statement or command. e.g. exec ("print " + "x") will print the value of x. Pressing a graphics button is equivalent to this command since it executes a string that is assigned to the button, such as a subroutine call. Similarly, selecting an item from the custom menu executes a string assigned to that item. doevents() Suspends execution while CB responds to pending menu or button events as well as to Apple Event messages addressed to it. If the user clicks on a button or attempts to pull down the custom menu while CB is busy executing your program, the interpreter may not notice the user's request until this command tells it to check for such events. Therefore to ensure that the computer responds promptly to user actions, your program should execute this command frequently if it has created a custom menu or a graphics button that is supposed to be active during execution, or if eval() messages that need a prompt response will be sent to CB while your program is executing. On the other hand, this command is not needed for buttons that are only intended to be used while the interpreter is in immediate mode. Note: This command does not work when it is cast as a function, as in x = doevents(). call "wait", N Suspends program execution for N seconds. Background processes continue. stop Stops the execution of the program and returns to the command prompt. Prints a "Break..." message. Execution can also be stopped by typing Command-period, or equivalently by selecting Stop from the Control menu. end Terminates program execution and returns to the command prompt. Not required. cont CONTinue execution of the program on the next statement after the statement on which the program stopped execution due to a STOP command or an error. As of version 3.5.0, CB cannot CONTinue after an error inside a named SUB subroutine. clear All variables are cleared. All arrays and string variables are deallocated. All files are closed. exit bye quit Terminates the basic interpreter, ending program execution and closing all files. OPERATORS The following operators are available: mathematical operators: ^ exponentiation * multiplication / division mod remainder + addition - subtraction logical operators: not logical not Any non-zero value is interpreted as true. bitwise operators: and bitwise and or bitwise or xor bitwise exclusive-or comparison operators: = equal to <> not equal to > greater than >= greater than or equal to < less than <= less than or equal to The comparison operators can be used to compare numeric expressions or string expressions. The result of a comparison is 1 if true, 0 if false. Operator precedence (highest to lowest): ( ) - (unary minus) functions ^ * / mod + - = < > <= >= <> not and or xor To give "not" a high precedence, on the same level with functions and unary minus, enter "#cbas#non_ansi_not" or put it at the beginning of a program. This is a one-way trip: the only way to restore the default ANSI rule is to quit CB and restart it. This feature is included to support programs written under earlier versions of Chipmunk Basic that used the non-ANSI scheme (up to 3.4.6). To test which mode is in effect, print not 1 - 1. ASSIGNMENT { let } VAR = EXPR Assign a value to a variable. If a statement starts with a variable name, an implied LET is assumed. When a real value is assigned to an integer variable, it is rounded to the nearest integer. When a numerical value is assigned to a string variable, it is converted into a string representation. Example: s$ = 12.34 The opposite is not true: x = "12.34" gives an error. Instead use x = val("12.34"). { let } mid$ ( STRINGVAR$, EXPR1, EXPR2 ) = STRINGEXPR mid$(a$,i,n) = STRINGEXPR Replace n characters of a$, starting at character number i, with the first n characters of STRINGEXPR. If STRINGEXPR evaluates to a string too short to supply the requested number of characters, the remaining characters in a$ are not modified. If the substitution string extends past the end of a$, the surplus characters are appended, lengthening a$. { let } field$ ( STRINGVAR$, N { ,STRINGVAL } ) = STRINGEXPR field$(a$,n,char$) = STRINGEXPR Replace the n'th field of a$ with STRINGEXPR. If the optional string is present, use its first character as the field separator. The default separator is a space. Array assignment statements are described in the math section. MATH Math is done using the built-in double-precision IEEE math. All trigonometric functions express angles in radians. sgn (x) Returns the sign of the parameter value. Returns 1 if the value is greater than zero , zero if equal to zero. -1 if negative. abs (x) Returns the absolute value of x. int (x) Returns the integer value of x. Truncates toward zero. The absolute value of x must be less than 2^31-1. floor (x) Returns the integer value of x. Truncates toward negative infinity. sqr (x) Returns the square root of x. log (x) Returns the natural logarithm of x. log10 (x) Returns the base 10 logarithm of x. exp(x) Returns e^x. e=2.7182818... sin (x) cos (x) tan (x) Trigonometric functions sine, cosine and tangent. asin (x) acos (x) atn (x) Inverse trigonometric functions arcsine, arccosine, arctangent sinh (x) cosh (x) tanh (x) Hyperbolic sine, cosine, and tangent pi Returns 3.141592653589793... (unless you assign a different value to it, in case you want to open up a whole new field of geometry) rnd (EXPR) Briefly, rnd(N) gives a random integer between 0 and N-1, while rnd(1) gives a random fraction between 0 and 1. (Thus rnd(N) has N possible values, and analogously rnd(1) has a unit range of values.) More precisely, rnd(EXPR) returns a pseudo-random number in a range that depends on the value of i, where i = abs(int(EXPR+0.5)). If i > 1, rnd(EXPR) returns an INTEGER between 0 and i-1. i > 1 when EXPR >= 1.5 or EXPR < -1.5. Thus rnd(100) ranges from 0 to 99, while rnd(2) = 0 or 1. If i = 1, rnd(EXPR) returns a FRACTION between 0 and 1. i = 1 when EXPR is in the range [0.5,1.5) or [-1.5,-0.5). If i = 0, rnd(EXPR) always returns zero. i = 0 when EXPR is in the range [-0.5,0.5). If EXPR is negative, rnd(EXPR) seeds the random number generator and returns the first value in the resulting sequence. randomize EXPR Seeds the random number generator with EXPR rounded to the nearest integer. The pseudo-random number generator should always return the same sequence when seeded with the same start value. The actual sequence may be system-dependent. val ( STRINGEXPR | EXPR ) Numeric value of the expression contained in a STRINGEXPR or EXPR. STRINGEXPR may be a literal, variable, function, or expression. For example, val("1 + sqr(4)") yields 3. mat origin { 0 | 1 } Sets the matrix index origin to either 0 or 1 for all MAT statements, including fill. Defaults to 0. mat ARRAY_VAR = EXPR Fills a 1 or 2 dimensional array with a constant value defined by EXPR. ARRAY_VAR is unsubscripted. Example: dim a(10,10) mat a = 1 mat ARRAY_VAR = ARRAY_VAR Copies a 2-dimensional array. The dimensions must match. mat ARRAY_VAR = transpose ARRAY_VAR Transposes a 2-dimensional array. The dimensions of the first array must match the transpose of the dimensions of the second array. The source and destination can be the same array, if it is square. mat ARRAY_VAR = ARRAY_VAR [ + | * ] [ EXPR | ARRAY_VAR ] Adds or multiplies a 2-dimensional array by either an expression or another array. The dimensions must be valid for matrix addition or multiplication. call "fft_polar", D(0), amp(0), phase(0) , N Calculates the Fast Fourier Transform (FFT) of N data points stored in array D, and returns N amplitude and phase values in the other two arrays (elements 0 through N-1). N must be an exact power of 2. If you have T data points, the largest sample you can use is 2^int(log(T)/log(2)). If the sampling rate is R samples/sec, output element k describes frequency kR/N. call "fft_inv", amp(0), phase(0), D(0) , N Reconstructs a signal from discrete frequency components. N must be an exact power of 2. Note that the arguments are supplied in a different order than above. call "math$", op$, result$, a$, b$ Performs simple integer arithmetic operations on very large numbers. a$ and b$ are two decimal integers in string form (a string can be up to 254 characters). The numbers can be negative. op$ can be "add$", "sub$", "mul$", "div$", or "mod$". Note that in this case $ is the last character of the op$ string, not just the last character of its name. STRING MANIPULATION lcase$ ( STRINGEXPR ) Returns STRINGEXPR in all lower case characters. ucase$ ( STRINGEXPR ) Returns STRINGEXPR in all upper case characters. x$ + y$ String concatenation. String concatenation (and the MID$, LEN and INSTR functions) can handle strings of up to 32766 characters in length, if the memory available to the program permits. len ( STRINGEXPR ) Returns the length of the string STRINGEXPR. asc ( STRINGEXPR ) Returns the ASCII code integer for the first character of STRINGEXPR. A null string returns zero. chr$ ( EXPR ) Returns the character defined by EXPR interpreted as an ASCII code. When EXPR does not evaluate to an integer in the range 0 to 255, the value used is EXPR modulus 256 rounded to the nearest integer. str$ ( EXPR { , EXPR2 } ) str$( EXPR, minlength) Returns a string representation of the numeric value of EXPR. If EXPR2 is present, the string is padded to that length, but the representation is not truncated if it exceeds EXPR2 digits. hex$ ( EXPR { , EXPR2 } ) bin$ ( EXPR { , EXPR2 } ) Returns the hexadecimal or binary string representation of the numeric value of INT(EXPR). If EXPR2 is present the string is padded with zeros as needed to make it that length, but the representation is not truncated if it exceeds EXPR2 digits. instr ( a$, b$ { , VAL } ) instr (text$, model$, start) Returns the position of the substring b$ in the string a$ or returns zero if b$ is not a substring. The search is case-insensitive. VAL is an optional search start position in a$ (preceding characters are ignored even if they match). right$ ( a$, EXPR ) Returns the rightmost EXPR characters of a$. left$ ( a$, EXPR ) Returns the leftmost EXPR characters of a$. mid$ ( a$, i { , n } ) Returns a substring of a$ starting at the i'th position and n characters in length. If the length is not specified, or if n exceeds the available characters of a$, the substring is taken from the start position to the end of a$. a$ can be a STRINGVAR$ or STRINGEXPR. { let } mid$( a$, i, n ) = STRINGEXPR Replace n characters of a$, starting at character i, with the first n characters of STRINGEXPR. If STRINGEXPR evaluates to a string too short to supply the requested number of characters, the remaining characters in a$ are not modified. If the substitution string extends past the end of a$, the surplus characters are appended, lengthening a$. field$ ( a$, i { , b$ } ) Returns the i-th field of a$. If the optional string is present, use its first character as the field separator. The default separator is a space. Adjacent separator characters count as one separator. Similar to UNIX 'awk' fields. Example: field$("1 22 333 4 555", 3) returns "333" If i is -1, field$() returns the first N characters of a$, where N is the number of separators found in a$, i.e. one less than the number of fields. Example: field$("1 22 333 4 555", -1) returns "1 22" { let } field$ ( a$, i { , b$ } ) = STRINGEXPR Replace the i-th field of a$ with STRINGEXPR. If the optional string is present, use its first character as the field separator. The default separator is a space. DATA FILE ACCESS open STRINGEXPR for [ input | output | append ] as # FILENUM ¬ { else goto [ LINENUM | LABEL ] } Open a file. Example: open "rough draft" for input as #1 else goto errout STRINGEXPR evaluates to the name of a file (not an alias) in the default folder, or a complete file path starting with the disk name. The input|output|append parameter specifies whether the file is to be read, written or appended. If FILENAME is "stdin" for input or "stdout" for output, the console will be used instead of a file. A "file not found" error will occur if a nonexistent file is specified in an OPEN FOR INPUT statement. FILENUM must be an integer value between 0 and 8. If the optional ELSE clause is included, control will transfer to the indicated line if the file open fails, and the variable ERL will be set to the line number of this OPEN FILE command. If the file to be opened contains text, it must be in Macintosh format, viz. each line ended by <CR>. If the file is in Unix or DOS format, use the "open for data input" version described below. open "SFGetFile" for input as # FILENUM open "SFPutFile" for output as # FILENUM Puts up a standard file dialog for the file name. open STRINGEXPR for data input as # FILENUM open file$ for data input as #n Use this version of OPEN for binary files to be read with GETBYTE or written with PUTBYTE. Also use this version to access text files that are in Unix or DOS format, but not for regular Macintosh text files. fseek # FILENUM, EXPR fseek #n, byte Reposition the file pointer. Bytes are numbered from zero. open STRINGEXPR for random as # FILENUM len = VAL open file$ for random as #n len = length Opens a random-access file. Only GET and PUT statement are allowed to read and write random-access files. LENGTH is the record length in bytes. It must agree with the size of the typed data. Note that the size of a typed variable can be retrieved using len(). close # FILENUM Close a file. Releases the file descriptor and flushes out all buffered data. open STRINGEXPR for data input open filespec$ for data input Designates a file as the source for accessory resources. filespec$ is the name of a file (not an alias) in the default folder, or a complete file path starting with the disk name. Makes the file the current accessory source for resources of types 'ICN#', 'cicn', 'PICT', 'snd ', 'DLOG', and 'BCMD', supplementing the ones included in CB's resource fork. Note that after a "load" or "run" command the program file becomes the current accessory source, superceding any file opened with this command. 'ICN#'/'cicn' IDs 128-160 are reserved by Chipmunk Basic. To avoid conflicts, create a new file in ResEdit and copy resources into it, giving them higher ID numbers in that file. Alternatively, resources can be pasted into the CB application or into a program file. Each accessory file resource needs to be assigned an ID that is not duplicated in the CB application. Commands that access resources by ID: 'DLOG' inputbox ( prompt$, title$, default$, ID ) 'PICT' graphics PICT x,y, ID 'snd ' sound 0, ID 'ICN#'/'cicn' sprite ID on x,y sprite n, x,y, ID (These commands are described in other sections.) DATA INPUT peek ( ADDR { , [ 2 | 4 | 8 ] } ) peek (ADDRESS { , BYTES } ) With just the address argument, PEEK returns the value of the single byte at that address. If BYTES is 2 or 4, PEEK returns the value of the 16-bit or 32-bit word respectively (if correctly aligned). If BYTES is 8, PEEK returns the value of the numeric variable located at the specified address. peek(varptr(x),8) equals x. fgetbyte (FILENUM) Reads one byte from the file specified by FILENUM and reports it as an integer between 0 and 255. get STRINGVAR$ Gets one character from the console keyboard. Blocking. (I.e. execution pauses until a character is available.) inkey$ Returns one character from the keyboard if input is available. Returns a zero-length string ("") if no keyboard input is available. Non-blocking; can be used for keyboard polling. input$ ( EXPR { , FILENUM } ) input$ (chars) input$ (chars, file#) Returns EXPR characters from file FILENUM. If no FILENUM is given, input is taken from the console keyboard in blocking mode, but without any prompt, so a prompt should usually be printed first. macfunction("getclipstr") Returns the text currently in the system clipboard, or null if the current clipping is not text. inputbox ( prompt$ { , title$ { , default$ { , ID } } } ) Displays a string input dialog box with options "OK" (item 1 in the 'DLOG' resource) and "Cancel" (item 2). title$, if supplied, appears in the title bar. Use a null title$ if you need default text but don't need a title. Example: name$ = inputbox("What is your name?") By default (with ID omitted or zero) this function uses CB's "inputbox" 'DLOG' resource, but you can invoke an alternative 'DLOG' by including an ID argument greater than 1024. One approach is to use ResEdit to duplicate the built-in resource, and then edit the copy. input {"prompt"; | #FILENUM,} [ VAR | STRINGVAR$ ] {, SAME_TYPE } input a,b,c input "What is your name? "; name$ input #1, a,b,c input #1, a$,b$,c$ Input from the console or from the text file specified by FILENUM. The input variables must all be of the same type, either string or numeric. (A numeric list can mix real and integer types.) For numeric input from a file, all the numbers to be read must be on one line. The number of comma-separated numbers on the input line must be less than or equal to the number of numeric variables in the INPUT statement; surplus variables will be zeroed, and any remaining non-numeric text on that line, such as comments, will be ignored. For string input, a whole line will be read into each string variable, so the data must be on successive lines. If input is from the console, a literal prompt string can optionally be printed. Note that a semicolon must follow the prompt string. *** NOTE *** This implementation of INPUT differs from other versions of Basic. Minor bug: As of version 3.5.0, when multiple lines of text are read from a file into successive string variables by a single input statement in immediate mode, the interpreter prints a prompt for each succeeding line on the console even though it is not getting the data from there. This seems to be harmless, however. eof ( FILENUM ) Returns true if the the last INPUT statement, INPUT$, or FGETBYTE function call which referenced the text file specified by FILENUM tried to read past the end of file. Note that reading the last line of a file will not read past the eof mark. A subsequent read is needed to set the EOF flag to true. Reading past the end-of-file will not report an error. read [ VAR | STRINGVAR$ ] { , ... } Read from DATA statements contained in the program. List items can be either string or numeric variables, but must match the type of data to be read. Reading past the end of the last DATA statement generates an error. data ITEM { , ... } DATA statements contain the data used in the READ statements. Items must be separated by commas. The items may be either numeric or string expressions, corresponding to the type of variable receiving the input. Strings must be encapsulated with quote marks. Reading the wrong kind of object produces a "Type mismatch" error. restore { LINENUM } The RESTORE statement causes the next READ to use the first DATA statement in the program. If a LINENUM is given, the DATA statement on or after that particular line is used next. peek ( ADDR, 8 ) Returns the number stored at ADDR, regardless whether it is actually 8 bytes (on some hardware it differs). See the complete PEEK description at start of this section. get # FILENUM, N, TYPED_VAR Reads record N of a random-access file into TYPED_VAR. Records are numbered starting with 1. macfunction ( "rsrcload",filespec$,rtype$,ID,A%(0),sizelim,2 ) Loads a resource into an integer array and returns its size as the function value. filespec$ is the name of a file (not an alias) in the default folder, or a complete file path starting with the disk name. rtype$ is the four-character resource type, and ID specifies which resource of that type to load. Sizelim should be set to the array size in bytes (two bytes per element) to avoid corrupting memory by loading a resource that turns out to be larger. The returned value is the number of bytes actually loaded. If the complete resource was loaded, that value will be less than sizelim and greater than zero. Zero indicates that the resource was not located. mouse (0) Returns 1 (true) if the mouse button is down, otherwise zero. Other mouse() functions are described in the graphics section. macfunction ("keydown",k) Returns 1 (true) if key k is currently pressed, otherwise zero. Each key has an identifier that is distinct from the ASCII code of the character (if any) that the key maps to. It is independent of the shift key (which has its own code). Identifiers (a.k.a. "virtual key codes"): Letters: A 0 B 11 C 8 D 2 E 14 F 3 G 5 H 4 I 34 J 38 K 40 L 37 M 46 N 45 O 31 P 35 Q 12 R 15 S 1 T 17 U 32 V 9 W 13 X 7 Y 16 Z 6 Digits on main keyboard: 0-29 1-18 2-19 3-20 4-21 5-23 6-22 7-26 8-28 9-25 Numeric keypad: 0-82 1-83 2-84 3-85 4-86 5-87 6-88 7-89 8-91 9-92 Modifier keys: shift 56 control 59 option 58 command 55 Arrow keys: up 126 down 125 left 123 right 124 Function keys: F1 -122 F2 -120 F3 - 99 F4 -118 F5 - 96 F6 - 97 F7 - 98 F8 -100 F9 -101 F10-109 F11-103 F12-111 F13-105 F14-107 F15-113 And here is the complete list: 0 A 32 U 64 96 F5 1 S 33 [ 65 . (num) 97 F6 2 D 34 I 66 98 F7 3 F 35 P 67 * (num) 99 F3 4 H 36 return 68 100 F8 5 G 37 L 69 + (num) 101 F9 6 Z 38 J 70 102 7 X 39 ' 71 clear 103 F11 8 C 40 K 72 104 9 V 41 ; 73 105 F13 10 42 \ 74 106 11 B 43 , 75 / (num) 107 F14 12 Q 44 / 76 enter 108 13 W 45 N 77 109 F10 14 E 46 M 78 - (num) 110 15 R 47 . 79 111 F12 16 Y 48 tab 80 112 17 T 49 space 81 = (num) 113 F15 18 1 50 ` 82 0 (num) 114 help 19 2 51 delete 83 1 (num) 115 home 20 3 52 84 2 (num) 116 page up 21 4 53 85 3 (num) 117 fwd delete 22 6 54 86 4 (num) 118 F4 23 5 55 command 87 5 (num) 119 end 24 = 56 shift 88 6 (num) 120 F2 25 9 57 caps lock 89 7 (num) 121 page down 26 7 58 option 90 122 F1 27 - 59 control 91 8 (num) 123 left arrow 28 8 60 92 9 (num) 124 right arrow 29 0 61 93 125 down arrow 30 ] 62 94 126 up arrow 31 O 63 95 127 power* *The power key stays set once it is pressed post startup. DATA OUTPUT poke ADDR_EXPR, DATA_EXPR Poke a byte into a memory location. Unreasonable addresses can cause bus or segmentation errors. fputbyte EXPR, # FILENUM Writes one byte, CHR$(EXPR), to the file specified by FILENUM. call "putstr2clip", s$ Copies a string to the system clipboard. Does not work if CB is running in the background. print EXPR | STRINGEXPR { [ , | ; ] ... } { ; } ? EXPR | STRINGEXPR { [ , | ; ] ... } { ; } print # FILENUM, EXPR ... Each comma in the parameter list generates a tab in the output; to suppress the tab use a semicolon instead of a comma. The print output is terminated with a carriage return unless the parameter list ends with a semicolon. If a file descriptor is given, output is redirected to the given file. If a tab(EXPR); is found in a print statement, print output will skip to the horizontal position specified by EXPR. print { # FILENUM, } using STRINGVAL ; EXPR { [ , | ; ] EXPR ...} print { #n } using form$; EXPR... Prints formatted numbers. Legal characters for the format string are: # . * $ + E+ and trailing spaces. Examples: print using "###.##"; 2.12345 -> 2.12 print using "**$###.##"; 1.23 -> ****$1.23 print using "+++###.##"; 1.23 -> +1.23 print using "+++$##.##"; 1.23 -> +$1.23 print using "#.##E+##"; -2345.6 -> 2.35E+03 Note that using the last format above, a negative number will be printed as positive, because no space is provided for the minus sign. To be safe, use "##.##E+##" instead. Also note that in spite of the + in E+, the actual printed exponent can be positive or negative. As of version 3.5.0, the PRINT USING format string does not recognize comma's, underscores and many other common format characters found in other versions of Basic. format$ ( EXPR , STRINGEXPR ) format$ (EXPR,form$) Returns the string representation of EXPR formatted according to the format string STRINGEXPR, which uses the same formatting syntax as the PRINT USING statement. msgbox STRINGEXPR msgbox ( STRINGEXPR ) Displays a short one-line message in a dialog button. Examples: msgbox "Now at point 5, x = " + str$(x) msgbox "All done!" call "printText" Sends the printer the last ~66 lines displayed in the console window. (In a non-graphics environment, 66 lines = 1 page.) Does not work on all printers. put # FILENUM, N, TYPED_VAR Write record N of a random-access file from TYPED_VAR. Records are numbered from 1. When the file is closed, unwritten records are omitted, so for example if record 2 is never written, data that was written as record 3 would be become record 2 in the closed file. saved = macfunction ("rsrcsave", filespec$, rtype$, ID, A%(0), size) Saves the contents of an integer array as a resource, and returns the number of bytes saved. filespec$ is the name of a file (not an alias) in the default folder, or a complete file path starting with the disk name. rtype$ is the four-character resource type, and ID is the identification number to be assigned to the new resource. Size is the number of bytes to save, starting at A%(0). The specified file is created if it does not already exist at that location. A resource fork is created if the file does not already have one. If the file already contains a resource of the specified type with the same ID, CB apparently attempts to replace it with the new one, but as of version 3.5.0 it fails and leaves a corrupt resource fork. The reciprocal command macfunction("rsrcload"...) can be used to check for the existence of a conflicting resource before saving. Value -1 signifies failure, such as a locked file. CONDITIONALS if EXPR then STATEMENT { :... } { : else STATEMENT { :... } } if EXPR then LINENUM if EXPR The IF statement. If the condition is true, the statements after THEN are executed and the statements after ELSE are skipped. If the condition is false, the statements after ELSE are executed instead. If the item after THEN is a line number, a goto is executed. If the condition is false and there is no THEN on the same line, statements are skipped until the first line containing an ENDIF. (block IF() ... ENDIF) EXPR must be numeric. It's logical value is TRUE iff its numerical value is non-zero. on EXPR goto [ LINENUM | LABEL ] { , ... } on EXPR gosub [ LINENUM | LABEL ] { , ... } This command will execute either a GOTO or a GOSUB to the specified line as indexed by the value of EXPR. If int(EXPR+0.5) is not the number of a list element, control passes to the following statement. select case EXPR Multi-way branch. Executes the statements after the first CASE statement which matches the SELECT CASE expression, then skips to the END SELECT statement. If a CASE ELSE statement is included, the statements that follow it will be executed if none of the preceding cases matched. Example: 200 select case x 210 case 2 ... 230 case 3, 4 ... 240 case EXPR1, EXPR2 ... 270 case else ... 290 end select LOOPS for VAR = EXPR to EXPR { step EXPR } Beginning of a FOR-NEXT loop. It takes a starting value, a limit and an optional step argument. If the step value is negative, the variable counts down. The body of the loop is not executed if the end condition is true initially. Example: for i=1 to 10 : print i, : next i rem prints the numbers from 1 through 10 next { VAR } End of a FOR-NEXT loop. If the termination conditions are met, execution falls through to the following statement, otherwise execution returns to the statement following the FOR statement with the corresponding index variable. If there no index variable parameter, the innermost FOR loop is used. exit for Exits the current FOR-NEXT loop. while { EXPR } Start of a WHILE loop. The loop is repeated until EXPR is false. If EXPR is false at loop entry, the loop is not executed. A WHILE loop must be terminated by a balancing WEND statement. wend { EXPR } Terminating statement of a WHILE loop. Control exits the loop if EXPR is true. Only one WEND is allowed for each WHILE. A WHILE-WEND loop can have a condition at either end or at both ends. A WHILE-WEND loop without a condition will loop forever. exit while Exits the current WHILE-WEND loop. SUBROUTINES gosub LINENUM Transfers command to a line number. Saves the return address so that the program can resume execution at the statement after the "gosub" command. The recursion depth is limited only by available memory. return Returns from the most recently activated subroutine call (which must have been called by GOSUB). def fnNAME ( VAR { , VAR } ) = EXPR def fnNAME$ ( VAR { , VAR } ) = STRINGEXPR Define a function. Example: 10 def fnplus(x,y) = x + y 20 print 2 * fnplus(3,5) : rem prints 16 *** NOTE *** DEF functions might not be supported in future versions of Chipmunk Basic, so it is better to get in the habit of using SUB routines, which can be invoked within expressions in the same way as DEF functions. { call } NAME ( { ARG { , ... } } ) call mysub(a,b,c$) Call to a SUB subroutine. To capture a return value, use the function syntax (omit "call"). Example: result = 1 + mysub(a,b,c$) Each argument must match the type of the corresponding parameter in the sub's VAR list, but the call can omit arguments from the end of the list when their value is zero (or null in the case of strings). String and numeric arguments are passed by value; array arguments must be dimensioned before the call and are passed by reference. To supply array A as a calling argument, put "A" in the argument list, not "A(0)", which is an expression and so would be evaluated and passed by value. (Note that this rule refers only to SUB subroutines; some built-in routines such as "record" that are also called with a CALL statement require array arguments to be in the form A(0).) sub [ NAME | NAME$ ] ( { VAR | STRINGVAR$ { , ... } } ) Subroutine entry. May be called by a CALL statement or by NAME. As illustrated in the example below, a subroutine can return a value when it is called with the function syntax like y = mysub(x). If the subroutine does not assign a value to its name, the value returned is zero, or null if it has a string name. Names starting with "fn" are reserved for the DEF fn___ functions. String and numeric arguments are passed by value; array arguments are passed by reference. In the VAR list an array is represented by its name without any subscript. The variables in the VAR list become local variables. To make additional variable names local even though they are also used in the main program, tack them on at the end of the VAR list after the ones that match to the calling arguments. Because of this feature, a given subroutine can be called with a varying number of arguments. Any surplus variables in the VAR list are initialized to zero (or null for strings) at each subroutine entry. There are three ways to get results back to the main program: 1) Assign a value to the subroutine name, and call it with the function syntax, i.e. result = NAME(args). 2) Assign a value to a global variable (one that is not local to the subroutine). Any variable that is not in the VAR list is global, even if it has never been used yet in the main program. 3) Place results in an array from the VAR list that matches to one of the calling arguments. What you *cannot* do is to pass a result back through a scalar variable from the VAR list, even when the calling argument is also a variable. A SUB subroutine must be exited by a RETURN or END SUB. There should be only one RETURN or END SUB statement per SUB definition. Subroutine definitions may not be nested. Example: 100 dim a(100) 110 for j = 1 to 100 120 z = 100 / j 130 x = 10 * foo (7,a,j) ' Pass 7 and j by value. 140 y = bar (y,z) 150 next j ... 2000 sub foo (x,v,y,z) 'x, v, y and z are local variables 2010 print x,y 'prints 7 and j 2020 z = sqr(x) 'does not affect z in main program 2030 v(y) = z + x 'return result in an array 2040 g = sin(z) 'return result in a global variable ... 2080 foo = y+z 'set return value of sub name 2090 end sub call varptr(a%(0)) Calls 68k code located in array a%. Under System 7, 68k code works even on a PPC. You can also use this method to execute PPC code if it is encapsulated as a "safe fat code fragment". The array must be of integer type. Macfunction("rsrcload"...) can be used to load a code resource into an array. menu 4, Title$, Items$, Commands$ call "menu", Title$, Items$, Commands$ Installs a custom pull-down menu in the menubar. Title$ specifies the menu name to appear in the menubar. Items$ is the series of option names to appear in the menu. Commands$ is a series of commands to implement the menu: selecting an item from the menu causes the corresponding command to be executed. Elements in both lists are separated by semicolons. You can give an option a command-key equivalent by putting a slash after the option name, followed by the key, as in the example below. You can put a separator between different groups of options by putting a hyphen in the item name list, and a null string at the corresponding position in the command list, as in the example below. After the user selects an item from the menu, the item number can be retrieved as menuitem mod 256, in case a single routine handles more than one option. The custom menu remains active only as long as your program is executing, or until the menu is removed (see below). To ensure that CB responds promptly when the user clicks on the custom menu even though it is busy executing your program, your program must frequently execute a "doevents()" command, which tells CB to handle pending menu events. Example: 100 items$ = "Reset;Invert;Erase;-;Done/D" 110 actions$ = "goto 500;flip();cls;;stop" 120 menu 4,"Options",items$,actions$ 130 doevents() 140 goto 130 menu 4, "" Removes the current custom menu, if any. Only one custom menu can be active at a time. This command must be used to remove the current one before a substitute custom menu can be installed. INTERNAL STACK push EXPR { , ... } push VAR { , ... } Pushes one or more expressions or variables onto an internal stack. Expression values can be recovered by using the POP function; variables can be restored by using the POP statement. pop { N } POP statement (see also POP function, and discussion below). Pops N variables off the internal stack, restoring them to their pushed values. The default for N is 1. Example: push x push y .... pop 2 'restore y, then x pop POP function (see also POP statement, and discussion below). Pops one pushed value off the stack and returns that value (string or numeric). Example: x = pop + 2 In Chipmunk Basic, POP can be used either as a statement (with an optional parameter) or as a function (no parameter). The POP function, unlike the POP statement, does not restore the value of the variable pushed, but only returns the pushed value. (This POP implementation is different from the Applesoft usage.) Each stack element consists of a value (string or numeric) plus a pointer to the variable that was pushed. The POP function returns just the value, discarding the associated pointer. The POP statement, on the other hand, restores a variable to its pushed value by storing that value at the location indicated by the pointer. When the PUSH argument is not simply a variable but rather a more complicated expression like a+b, y(7), or mid$(s$,3,4), the saved pointer instead references a scratch area, so the POP statement does not restore anything and the stack element is simply discarded. To retrieve the saved value of an expression, use the POP function instead. DYNAMIC STORAGE dim VAR ( d { , d { , d { , d } } } ) { , ... } dim a(d), b(d1,d2,d3,d4), c$(d1,d2) ... Dimension an array or list of arrays (string or numeric). d can be a constant or a numeric expression. A maximum of 4 dimensions can be used. The maximum dimension size is limited by available memory. (If you need to compute the memory needed for an array, note that real arrays may use from 4 to 12 bytes per element depending on hardware, so test e.g. varptr(a(1)) - varptr(a(0)).) Legal array subscripts are from 0 up to and including the dimension specified; d+1 elements are allocated. All arrays must be dimensioned before use. Examples: 10 n = val(inputbox("How many powers?","","5")) 20 dim p(n) 30 for j = 0 to n 40 p(j) = 2^j 50 next 10 dim ans$(1) 20 ans$(0) = "Guess again" 30 ans$(1) = "Right" 40 print ans$( 2 * 2 = 4 ) 50 print ans$( 2 + 2 = 22 ) erase [ ARRAY_VAR | TYPED_VAR ] Un-dimensions a dimensioned array or dynamic record. Frees memory. isarray ( VAR ) Returns 1 (true) if the variable is an array, returns 0 (false) if it is a scalar or if it is not defined. ubound ( VAR ) If VAR is an array, returns the maximum legal subscript of its first dimension, otherwise returns 0. type TYPENAME Creates a structure definition type. Each field requires a separate line. Legal types are string, integer, longint, and double. The definition must conclude with an END TYPE statement. Use the DIM AS NEW statement to create records containing the structure specified by a TYPE statement. Example: 300 type person 310 name as string * 32 ' max 31 characters 320 age as integer ' 2 bytes 330 height as longint ' 4 bytes 340 weight as double ' 8 bytes 350 end type 400 dim friend1 as new person 410 = "Mark" : friend1.age = 13 420 print, friend1.age class CLASSNAME { extends SUPERCLASSNAME } Creates a class definition. Class definitions can then be used to create objects with member functions (also called methods.) Classes inherit members from superclasses (single inheritance.) Example: CLASS bar y AS integer z AS PRIVATE double ' private data s AS PUBLIC string ' public keyword optional SUB blah(v) ' public member function this.y = v + 7 END SUB END CLASS DIM b AS NEW bar ' create object b CALL b.blah(1) ' send message "blah(1)" to b CLASS and TYPE definitions are global, and cannot be nested inside other class definitions or subroutines. dim VAR { ( INT ) } as new [ TYPENAME | CLASSNAME ] Create a record (TYPED_VAR) or object using a previously defined structure definition type created by TYPE...END TYPE or CLASS..END CLASS. Optionally creates an array of records or objects. Typed arrays are erased when execution terminates, so they are not accessible in immediate mode. Typed scalar variables remain available. len ( TYPED_VAR ) Returns the length, in bytes, of a typed record (one created by DIM AS NEW). CONSOLE WINDOW The initial dimensions of the console window are governed by the Prefs file, which you can edit. The first line after "text window size" is the width measured in columns of text, and the second is the height in lines of text. When the Prefs setting is too small, a default value is used instead. window x, y, char_cols, char_lines Change the text console window position and size. call bigfont call "bigfont" Toggle the BIGFONT console output status, making the displayed text bigger or smaller. The font, size, and style for big text are defined in the Chipmunk Basic Prefs, which is a text file you can edit. call "putPref", K$, 7 Revise the preference setting for the size of CB's scrollback buffer (line 7 in the Prefs file). K$ is a string expression that evaluates to an integer. The setting is initially 256K. Each added 1K provides space for about 10 more lines of scrollback. For a substantial increase, you may also need to raise CB's memory settings in the Get Info window. Example: To make the buffer size 512K, call "putPref", "512", 7 Alternatively, you can revise the setting with a text editor. cls Clear the terminal screen and the graphics window. Leaves the cursor in the upper left corner. For Applesoft Basic fans, the "home" command does the same thing. gotoxy H,V Set the horizontal and vertical location of the text output cursor. (0,0) is the upper left corner. pos (VAL) Returns the horizontal position of the text cursor, or the vertical position if VAL is negative. home Same as cls. GRAPHICS WINDOW NOTE: All graphics commands in version 3.x are in the beta test stage of development. They may or may not work dependably on your machine. Graphics may require that CB's preferred memory setting be increased in the "Get Info" window. It may also help to reduce the number of colors in the Monitors control panel. In graphics commands x = 0 identifies the first column of pixels inside the working area at the left; x = width-2 is the last column on the right. Similarly y = 0 is the top row and the bottom row has y = height-2. Print (in the File menu) prints the graphics window if it is the frontmost window. Only the graphics window can be printed. graphics [ 0 | -1 ] Show or hide graphics window. Graphics 0 also refreshes the graphics window. cls home Clears the graphics window as well as the console window. Does not remove buttons. graphics refreshtime t Sets the target refresh rate for the graphics window to every t ticks. Controls whether an animation is choppy or smooth: decreasing t makes movement look smoother provided that the machine is fast enough to actually refresh the window as often as requested. call wintitle, newname$ call "wintitle", newname$ Renames the graphics window, which is initially named "graphics" The window does not need to be displayed at the time. The routine name is case sensitive. call "hideMenuBar" Hides the menubar. The routine name is case-sensitive. Frees up more screen space for the graphics window. (May also have some non-graphics applications.) "graphics -1" restores the menubar as well as hiding the graphics window. graphics (-34) Returns the pixel depth of the graphics window, i.e. how many bitplanes in each layer (?). graphics (-38) Returns the maximum width available for the graphics window, and displays the graphics window at the front. The visible display is smaller, so if you want the window to just fill the screen, subtract 128 (?) from the returned value. The value returned is constrained by the setting in the Prefs file. (The window width preference is always set to 640 when the Prefs file is created, but you can edit it.) However the size of the graphics window is not limited by that preference figure. Bug: As of version 3.5.0, this call seems to return a maximum of 640 regardless of the actual screen dimensions and available memory, even when the value in the Prefs file is larger. graphics (-39) Returns the maximum height available for the graphics window, and displays the graphics window at the front. The visible display is smaller, so if you want the window to just fill the screen, subtract 128 (?) from the returned value. The value returned is constrained by the setting in the Prefs file. (The window height preference is always set to 480 when the Prefs file is created, but you can edit it.) However the size of the graphics window is not limited by that preference figure. Bug: As of version 3.5.0, this call seems to return a maximum of 480 regardless of the actual screen dimensions and available memory, even when the value in the Prefs file is larger. graphics window width, height Adjusts the graphics window's dimensions without moving it, and displays it at the front. Too small a "Preferred Size" (as set from the application's Get Info window) may limit the maximum graphics window size. graphics window x, y, width, height Adjust the graphics window's position and size, and display it at the front. x and y are screen coordinates (not window coordinates) and define the screen position of the top left corner of the window's title bar. 0,0 puts the window at the top left of the visible display, with its title bar hidden behind the menubar (unless that is hidden). "width" and "height", on the other hand, define the dimensions of the actual working area, not the entire window. However, "width" and "height" include the lines that border the working area, so to get N usable rows or columns, set the height or width to N+2. Because of the scroll bars and title bar, the entire window will be 15 pixels wider and 35 pixels taller than the dimensions stated in this command. graphics PICT x,y, [ ID | file$ ] Draw the specified 'PICT' resource or PICT file in the background layer at location (x,y). call "savepicture", file$ Save the graphics window to a PICT file as it is currently displayed (including the sprite layers). sprite ID on x,y Draw an 'ICN#' resource (or 'cicn' if available) in the background layer at location (x,y). As of version 3.5.0, this works a little strange on a monochrome monitor: in the case of resources 128 and 142, it paints white pixels instead of an outline, apparently because those two resources have associated 'ic18's. Hint: on a color monitor, the command displays the sprite in color even when the 'ic18' resource is deleted. Apparently CB invokes the 'cicn' version automatically. graphics window -1,-1, x, y, 2 Scroll the graphics background to put location x,y at the top left of the window. x and y should be positive. This command does not move sprites or buttons, only the background. Moreover sprite coordinates remain the same as they were before. Thus in effect there are two coordinate systems, one for the background layer and one for the layers above it. When the background is scrolled away from 0,0, these two systems don't match. As of version 3.5.0 this command doesn't seem to work unless one or both of the offsets is negative. graphics color r,g,b Set the ink color as a combination of red, green and blue. Each component intensity can range from 0 to 100. 0,0,0 makes the ink black. graphics color i Set RGBForeColor to index i. Initially it is 255 (black). Some basic colors: white 0 black 255 brown 137 red 34 orange 23 yellow 4 green 225 blue 210 violet 66 graphics pensetup width, height { , mode, pattern } Sets up the parameters that govern the trail created by drawing. The pen "point" is initially a one-pixel "rectangle" but you can make it larger with this command. The pen position is the top left corner of its footprint. The patterns supplied with Chipmunk Basic are numbered from 1 to 38. They are stored in the 'PAT#' resource, where you can use ResEdit to inspect them as well as to add more patterns, replace the existing ones, or edit them. modes: 8 copy the pattern into the background 9 OR the pattern with the existing background 10 XOR the pattern with the existing background - with pattern 1 (solid black), this inverts the background 11 Bic ("bit clear"): clear every background bit that is set in the pattern 12 copy the inverse of the pattern into the background 13 OR the background with the inverse of the pattern 14 XOR the background with the inverse of the pattern 15 clear every background bit that corresponds to a clear bit in the pattern { graphics } moveto x,y Move the graphics pen to location (x,y) without leaving any trail. { graphics } pset x,y Plot one point at location (x,y), leaving the pen positioned there. { graphics } lineto x,y Draw a straight line from the current pen location to (x,y). graphics circle x { , y } Draw a circle of diameter x. First use "moveto" to place pen at center, where it remains after drawing. With the optional second argument, an oval is drawn instead. (The keywords "circle" and "oval" are equivalent.) graphics oval x { , y } Draw an oval (ellipse) x pixels wide and y pixels high, centered on the current pen position, where it remains after drawing. If the second argument is omitted, a circle is drawn instead. graphics oval x1,y1, x2,y2 Draw an oval to fit a box with top left (x1,y1) and bottom right (x2,y2). The pen position is not affected. graphics rect x1,y1, x2,y2 Draw a box. Requires x1 < x2 and y1 < y2. When the pen's footprint is larger than one pixel, its trail is drawn along the inside of the rect. graphics triangle x1,y1, x2,y2, x3,y3 { , r,g,b } Draw a triangle and fill it with the specified color or the current ink color. The pen ends up back at the first vertex. This may have some application in 3D rendering. graphics fillrect x1,y1, x2,y2, [ N | -1 ] Fill a box with pattern number N, or erase it. To clear the entire graphics window, try 0,0,1000,1000,-1 (superceded by CLS as of version 3.5.0) graphics filloval x1,y1, x2,y2, N Fill an oval region with pattern N. Pattern 20 is clear, so it can be used to erase. Requires x1 < x2 and y1 < y2. graphics textsetup font, size { , mode } Set up text style. The font number can be obtained from its name: f = macfunction("GetFNum","monaco") graphics textsetup f,14,0 Each character is defined by a rectangular bit pattern. The text mode defines how that pattern is applied to the existing background: modes: 0 Copy the entire rectangle into the background. - This can be used to surround the text with a clear margin to ensure that it is legible. 1 OR the rectangle with the existing background. - This copies just the character itself, if it is black on white. 2 XOR with the existing background. - For inverse characters make both background and ink dark. 3 Bic (bit clear): for each set bit in the rectangle, clear the corresponding bit in the background. 4 Copy the entire rectangle into the background, but inverted. 5 OR the background with the inverse of the rectangle. 6 XOR the background with the inverse of the rectangle. 7 For each clear bit in the rectangle, clear the corresponding bit in the background. The specified style is applied to existing button names, so if you don't want them to be affected switch the style back right after drawing text. graphics drawtext a$ Paint text into the graphics window. First use "moveto" to place the pen at the bottom left corner of the text region. After drawing, the pen is positioned at bottom right (thus ready to add more text). sprite N { , } x, y { , ID } Display sprite N at location (x,y) without leaving any trail of its movement. With the fourth parameter, the 'ICN#' resource with that ID is loaded and displayed at location (x,y) in layer N, with its "pen" down so that subsequent moves will leave a trail. A 'cicn' color sprite is loaded if available, provided that there is also a matching 'ICN#' with the same ID. ID = 0 gives an invisible sprite. Fourteen 'ICN#'/'cicn' images are included in CB's resource fork, with IDs 128-141. To use other images, see the discussion in the section headed "Data File Access". N can range from 1 to 15, corresponding to the 15 available layers, with 15 topmost. Only one sprite can occupy a given layer at one time. (Layer 0 is for background and drawing, as described earlier in this section.) sprite n [ UP | DOWN ] x Moves sprite n up or down by x pixels, and optionally reports the new vertical position. Examples: sprite 3 down 25 ypos = sprite 3 down 0 'just gets current location sprite n [ LEFT | RIGHT ] x Moves sprite n up or down by x pixels, and optionally reports the new horizontal position. Note that this usage differs from Logo. Each sprite has a direction, by default the direction of its last movement, initially 0 (due east). The TURN commands aim it in a new direction without any actual movement: sprite n TURNTO d Sets the direction to d degrees counterclockwise from the positive x axis. sprite n [ TURN | TURNLEFT ] d Changes the direction by d degrees counter-clockwise. sprite n TURNRIGHT d Changes the direction clockwise by d degrees. sprite n FORWARD x Advance sprite n by x pixels in its current direction. sprite n [ PENUP | PENDOWN ] When a sprite's pen is down, it leaves a trail governed by the PENSETUP parameters. sprite n COLLISION Returns the number of a sprite that currently overlaps sprite n, regardless if it is on top or underneath. If more than one sprite overlaps n, the one that collided first is reported. Once that one moves away, the next arrival that still overlaps will be reported. Examples: cruncher = sprite 5 collision '0 if no collision if sprite 5 collision then say "ouch!" graphics button name$, x, y, width, height, Command$ | key_code Installs a plain button at location x,y in the graphics window with the specified dimensions and name. (x,y) is the top left corner of the button's rectangular field. Buttons are displayed above sprites. In addition, when a button is pressed it moves above any overlapping buttons (unless it is invisible). The button name is displayed in the current text style (see TEXTSETUP, above). If name$ is a null string, an invisible button is created instead. If the last argument is a string variable, it is executed whenever user hits the button. (Hint: command$ = "gosub 250" or command$ = "handler()") The argument must be a string variable, not a string literal or expression. It must already be defined when the button is created, and must not be modified afterward as long as the button is active. If the last argument is a number, hitting the button is equivalent to typing the key with the same ASCII code. The argument can be a numeric variable or expression, but the expression is evaluated at the time the button is created, not when it is pressed, so the button always produces the same key code. Buttons remain active even when execution is stopped. If you create buttons to be used during execution, your program must frequently execute a "doevents()" command, which checks for pending button and menu events. graphics button "", x,y, ID, key_code, -4 Creates a button represented by an image loaded from an 'ICN#' resource (or 'cicn' if available) instead of a standard button outline. As of version 3.5.0, when a built-in resource is used one of the other built-in icons is used as the highlighted version that is displayed while the button is held down. When an accessory resource is loaded, the highlighted version is its inverse. In other respects this command is the same as the key code version of the preceding command. graphics button "",-1 Removes all buttons. mouse (0) Returns 1 (true) if the mouse button is down, otherwise zero. mouse (1) mouse (2) Returns the horizontal (1) or vertical (2) position of the cursor in window coordinates, which are based on the top left corner of the inside of the active window (even if the cursor is not inside that window). For graphics applications, coordinates need to refer to the graphics window, but typing in the console window makes it current even when the graphics window is at the front. In a running program the returned coordinate should safely refer to the graphics window as long as the mouse() function follows a graphics window command without any intervening console window command (and without any errant mouse clicks in the interval). mouse (3) mouse (4) Returns the horizontal (3) or vertical (4) position of the last mouse click (where the cursor was sitting when the mouse button was pressed) in window coordinates of the current window. Also resets the value to -1 until the next click, so you can use this for polling. SOUND call "beep", N Plays the system beep N times. sound frequency, duration, volume Plays a tone. The units are: frequency in Hz (cycles per second), duration in seconds, volume {0..100} sound 0, ID Plays a 'snd ' resource. call "record", A(0), N Record sound into N elements of array A at 11100 elements per second. sound -1, A(0), N Play back N sound samples from array A. 11100 elements contain one second of sound. sound -2, voice, key, velocity, seconds { , channel } Plays Quicktime midi synthesizer, requires Quicktime >= 2.0 say STRINGEXPR { , rate , pitch , voice# } Speaks STRINGEXPR if the Speech Manager is present. Rate = 100 gives a normal speed. For faster speech try rate = 200. Pitch = 45 is a good starting point. say Speaks the last 12 lines of text in the console window. N = macfunction("numSpeakers") Returns the number of voices. V$ = macfunction("getSpeaker") Returns the name of the current voice. Morse STRINGEXPR { , dot-speed , volume , word-speed , frequency } Plays Morse code through the speaker. The units are: dot speed in wpm, volume {0..100}, word speed in wpm, frequency in Hz (cycles per sec). Dot-speed governs the length of both the tones and gaps between tones within a single character code; word-speed governs the length of pause between characters (code "words"), but a given value for word-speed yields a longer pause than the same value for dot-speed. Typical values: Morse msg$,15,50,15,700. COMMUNICATIONS Well-mannered serial port access requires the Serial Tool extension, which is part of the Communications Toolbox. First open "COM1:" for input, then for output. The errorstatus$ string variable will return a string you can use instead of "COM1:" when you don't want the CTB setup dialog box. The port names (COM1 etc) are case-sensitive. Try the following snippet: 100 rem *** Using the CTB serial ports *** 110 on error goto 200 120 open "COM1:" for input as #3 130 altsetup$ = "COM1: "+errorstatus$ 140 open altsetup$ for output as #4 150 while not mouse(0) 160 if not eof(3) then i = fgetbyte(3) : print chr$(i); 170 c$ = inkey$ : if len(c$) > 0 then print #4,c$; 180 wend 190 print " closing serial ports" : close #4 : close #3 200 print errorstatus$ : goto 190 You can also talk directly to the serial port, bypassing the Communications Toolbox, by using the COM3 port, e.g. open "COM3: 19200" for input as #3 but this should be attempted only if the Serial Tool is not available. call "sendbreak", n Sends a break signal of duration n ticks (1 tick = 1/60 sec) provided the channel is already open for output. ipaddr = macfunction("dnr2num", domain_name$) Fetches the numerical equivalent of an Internet domain name. The four numbers are returned in successive bytes of ipaddr. So far this is only supported on 68K machines. call "fetchHTTP", ipaddr, httpcmd$, filename$ MacTCP HTTP file transfer, to or from a local file. Here is a sample http command definition: httpcmd$ = "GET /index.html HTTP/1.0"+chr$(10)+chr$(10) SCRIPTING AND INTER-APPLICATION COMMUNICATION call "launch", STRINGEXPR call "launch", filespec$ Launches an application if it is not already running, and switches it to the front. Your program continues executing in the background, allowing it to issue messages addressed to the foreground application. filespec$ is the name of a file (not an alias) in the default folder, or a complete file path starting with the disk name. call "applescript", script$ Compiles and executes a script. If the script won't fit onto one line, put it in a string array with a null element to terminate the script. Example: dim t$(10) t$(0) = "beep" t$(1) = "beep" t$(2) = "" t$(3) = "beep" call "applescript",t$ 'no subscript If the argument above were t$(0) only one beep would result since it is an expression that evaluates to a single string. call "doscript", appname$, script$ Sends another scriptable application a script to execute. Use the alternative form below when a reply is needed. reply$ = macfunction("doscript", appname$, script$) Sends another scriptable application a script to execute, and returns the reply string. call "doscript", sig$, dirObj$, class$, ID$ Sends an event to another application, together with a "directObject" argument. sig$ is the application's four-character signature, class$ is the Apple Event class, and ID$ is the Apple Event ID. To send Netscape(tm) a "Get URL" event, call "doscript", 'MOSS', url$, "GURL", "GURL" To drive Chipmunk Basic from outside, send it a string of the form "DoScript "CMD"" or "DoScript "val(EXPR)"" or "DoScript "eval EXPR"" CB must already be running at the time the message is sent. Note that the command or function is in quotes in addition to the ones that here delimit the message as a whole. In some scripting applications the inner quotes can be escaped as in send 'cBaS' "DoScript \qCMD\q" Apple's Script Editor handles the encapsulation automatically so there the script looks like tell application "Chipmunk Basic" to DoScript "CMD" DoScript "CMD" CB executes the command after echoing it in the console window the same as if it had been typed in, and indeed CB must be in immediate mode (stopped) in order to respond to this type of message. CMD is any command that would be valid to submit in immediate mode. DoScript "val(EXPR)" DoScript "eval EXPR" CB evaluates the expression and returns the result to the calling application without any reflection in the console window. CB can handle this type of message even while it is executing a program. However, the response may be slow unless the Basic program frequently calls doevents(). An eval() message can be used to check the status of execution such as how far CB has progressed through a loop: tell application "Chipmunk Basic" to DoScript "eval(k)" Similarly your program can set state variables so that other applications can coordinate with it. MISCELLANEOUS rem or "'" A remark or comment statement. Ignored by the program during execution, however a REM statement (of either form) can be the target of a GOTO or GOSUB. Example: 100 goto 300 200 rem This line is skipped. 300 'target of goto 400 print "This line is executed." varptr ( VAR | STRINGVAR$ ) Returns the memory address of a variable. files { [ EXPR, EXPR | STRINGEXPR { , STRINGEXPR } ] } files With no argument, FILES displays a listing of the contents of the default folder. The default folder is the last one displayed in one of the standard file dialogs (Open, Save), or the one set explicitly (see below). Initially, when Chipmunk Basic launches, the default folder is the one containing the CB application. files folderpath$ With one string argument, FILES reports the contents of the specified folder. The folder path must start with the disk name. files folder$, dummy$ With the optional dummy argument, FILES sets the default folder. In this case no listing is printed. If the folder argument does not contain a colon, it is interpreted as the name of a folder located in the current default folder. If that folder exists, it becomes the new default, otherwise the default does not change. On the other hand if the folder argument contains a colon, it is interpreted as a path, but as of version 3.5.0 the routine seems to be buggy because the default is not set to that path as one would expect, instead it is set to the top level of the disk specified at the beginning of the path. From there to make the default a particular folder it seems to be necessary to move down one step at a time using the subfolder argument method. files VREF, PAR This version also sets the default folder, but using integers returned by macfunction("lastVRefNum") and macfunction("lastParID"), which are described below. macfunction ("lastVRefNum") Returns the volume reference of the last SFGetFile or of the current program file if it was dropped onto CB (System 7 only). Each disk or partition has a volume reference number, apparently assigned in order of mounting, which makes the startup disk -1. macfunction ("lastParID") Returns the ParID of the last SFGetFile or of the current program file if it was dropped onto CB (System 7 only). The ParID identifies a directory (i.e. a folder or the top level of a disk). macfunction ("prefVRefNum") Returns the volume reference of the Preferences folder (and thus of the System folder). macfunction ("prefParID") Returns the ParID of the Preferences folder, which includes the "Chipmunk Basic Prefs" file. call "setfiletype", filespec$, type$ Sets the type of a file. filespec$ is the name of a file (not an alias) in the default folder, or a complete file path starting with the disk name. If type$ is longer than four characters, only the first four are used. Minor bug: As of version 3.5.0, if type$ is shorter than four characters, it is not padded. fre Returns the amount of heap memory available for program use. If this gets much below 32K, you should increase the Preferred size in the Finder's Get Info window, then restart CB. reply$ = macfunction("Gestalt",param$) Returns information about the available hardware and software. Both arguments are case-sensitive. There are many possible values for param$; see "Inside Macintosh". erl Returns the line number of the last error. Zero if the error was in immediate mode. erl cannot be used to test for success of a command because it retains the offending line number until the next error. Use "on error" to detect problems. errorstatus$ Returns the error message for the last error. Also returns the full path name of the program and files opened by SFGetFile (under System 7 and only if the name fits in a string variable). Obscure bug: Like other variables, errorstatus$ is not case sensitive. ERRORSTATUS$ and Errorstatus$ are equivalent to the lower-case version. However, as of version 3.5.0, errorStatus$ is not equivalent. date$ Returns a string representation of the current date. time$ Returns a string representation of the current time. timer Returns the number of seconds since the last startup, to the nearest tick (1/60th of a second). call -151 Drops into MacsBug. Type G or EA to continue (?). If MacsBug is not installed, don't try this. RESERVED WORDS AND SYMBOLS abs acos and append as asc asin atn bload break bsave call case chr$ class clear close# cls cont cos cosh data date$ def degrees dialog dim do doevents double draw each else end endif eof eqv erase erl errorstatus$ exec exit exp extends false fgetbyte# field$ files floor fn for format$ fputbyte fre fseek# function get gosub goto gotoxy graphics home htab if imp inkey$ input inputbox input$ int integer is isarray key lcase$ left$ len let lineto load loc local lof log log10 longint loop mat max memstat menu menuitem method mid$ min mod morse mouse move moveto msgbox new next not open option or output peek pi play poke pop pos print private pset public push put quit radians random read redim rem renum restore resume return right$ rnd run save say scrn select set sgn sin single sinh sound sprite sqr static step stop str$ string sub swap tan tanh then this time$ timer to true type ubound ucase$ until usr val varptr vtab wend while width window xor + - * / ^ > < >= <= <> = ( ) BUGS Many, perhaps competitive with African swamps. Integer variables (like i%) won't work as indexes in FOR-NEXT statements. Integer arrays can only have one dimension and will only work in assignment (LET) statements. All arithmetic on integer variables is done in floating point. DIM AS DOUBLE and DIM AS INTEGER statements are ignored. Many string functions (except +, MID$, LEN and INSTR) silently truncate their results to 254 characters (i.e. without any notification). All string function may silently truncate strings longer than 32766 characters. Any operation on strings longer than 254 characters will cause the program to run slower. Any variables used as a CLASS, or TYPE, globally overide all local variables of the same names. Named SUBroutines are slower than GOSUBs. The combined length of a SUBroutine name and any local variables declared STATIC must be less than 29 characters. Macintosh screen editing will only recognise the last line modified before a RETURN or ENTER key. The EDIT command and Mac screen editing are incompatible. Many other bugs are reported in the preceding sections. AUTHORS AND ACKNOWLEDGEMENTS David Gillespie wrote basic.p 1.0 and the p2c lib. Ron Nicholson ( added file i/o, graphics and did the Unix, Macintosh and PowerMac port. (1990-1995Nov) Thanks to: - Dave Gillespie for writing the original Pascal version of this Basic. - Dave Betz for ideas from the original XLisp 1.6 Mac port. - many folks from Apple Dev support, Metrowerks, c.s.m.p, etc. - John Norstad for making available the Newswatcher TCP source code. - Jim Stout for making available "Jim's CDEFs" with source code. INDEX A B <a href="#CD">C D</a> <a href="#EFGH">E F G H</a> <a href="#IJKLM">I J K L M</a> <a href="#NOPQ">N O P Q</a> <a href="#RS">R S</a> <a href="#TUVW">T U V W</a> Note: This is not an exhaustive index, so you may find a string search equally helpful, or pick a likely section from the Table of Contents. If you notice other terms that belong in the index, please notify Steve Wise ( accessory resources animation speed, adjusting argument passing array operations arrays: deallocating (deallocate, dispose, release, erase) dimensioning (dimension, declare, define) getting info about existing arrays assignment statements background layer beep break signal buttons: creating removing case conversion class definition Clipboard: reading from writing to clock: ticks (in seconds) time of day code: calling code stored in an array loading machine code into an array comments communications computed GOTO concatenation conditionals console window conventions used in this manual coordinating applications custom menu data input data output DATA statements date default folder default folder, designating drawing layer dynamic storage dynamic storage: allocating releasing end-of-file status error handling error info event handling EXEC() extended precision fast Fourier transform file access file pointer, positioning file type, changing folder contents, listing folder, default font ID number formatted output functions, user-defined Gestalt info, getting graphics window heap memory hexadecimal numbers ink color, setting default INPUT statement Internet: address translation file transfer key codes, table launching an application listing folder contents loops MacsBug (debugger) matrix operations memory: available needed: for arrays for graphics menu, custom menubar, hiding message dialog Morse code, playing mouse: button status cursor position last click location NoLineNums not, precedence object-oriented data structures object structure definition operators patterns pause peek pen modes physical address pixel depth poke pop, function versus statement precedence, operator PRINT statement programs programs, loading push-down stack random access files random numbers record files record input record output record structure definition remarks (see also "comments") reserved words and symbols resources, accessory scripting (driving) other applications scripting Chipmunk Basic scrollback buffer, augmenting serial ports sound sound, recording and playing speech sprites sprite movement stack, built-in string delimiters string length string manipulation string substitution: by field by position structured data structured records, defining subroutines text, drawing text drawing modes ticks time of day trigonometry type conversion: implicit explicit: str$(number) val(string) type definition variable types voices WHILE-WEND loops DISCLAIMER There is no warranty that this document is accurate. Portions Copyright (C) 1989 Dave Gillespie Portions Copyright (C) 1994,1996 Ronald H. Nicholson, Jr. (, all rights reserved. Copyright (C) 1996,1997 Stephen A. Wise (, all rights reserved. "Applesoft" is a trademark of Apple Computer, Inc., etc.

Chipmunk Basic Reference - version Mac 3.5.0-3, 1/97 / Stephen Wise