SmallBASIC Language reference [09/08/2024] ░██████╗███╗░░░███╗░█████╗░██╗░░░░░██╗░░░░░██████╗░░█████╗░░██████╗██╗░█████╗░ ██╔════╝████╗░████║██╔══██╗██║░░░░░██║░░░░░██╔══██╗██╔══██╗██╔════╝██║██╔══██╗ ╚█████╗░██╔████╔██║███████║██║░░░░░██║░░░░░██████╦╝███████║╚█████╗░██║██║░░╚═╝ ░╚═══██╗██║╚██╔╝██║██╔══██║██║░░░░░██║░░░░░██╔══██╗██╔══██║░╚═══██╗██║██║░░██╗ ██████╔╝██║░╚═╝░██║██║░░██║███████╗███████╗██████╦╝██║░░██║██████╔╝██║╚█████╔╝ ╚═════╝░╚═╝░░░░░╚═╝╚═╝░░╚═╝╚══════╝╚══════╝╚═════╝░╚═╝░░╚═╝╚═════╝░╚═╝░╚════╝░ AT BEEP CAT CLS DEFINEKEY FORM INKEY INPUT LINEINPUT LINPUT LOCATE LOGPRINT NOSOUND PEN PLAY PRINT SOUND TAB APPEND ARRAY DATA DELETE DIM EMPTY ERASE INSERT ISARRAY ISDIR ISFILE ISLINK ISMAP ISNUMBER ISSTRING LBOUND LEN READ REDIM RESTORE SEARCH SORT SWAP UBOUND DATE DATEDMY DATEFMT JULIAN TICKS TIME TIMEHMS TIMER TIMESTAMP WEEKDAY ACCESS BGETC BLOAD BPUTC BSAVE CHDIR CHMOD CLOSE COPY DIRWALK EOF EXIST FILES FREEFILE INPUT INPUT KILL LOCK LOF MKDIR OPEN READ RENAME RMDIR SEEK SEEK TLOAD TSAVE WRITE ARC CHART CIRCLE COLOR DRAW DRAWPOLY IMAGE LINE PAINT PEN PLOT POINT PSET RECT RGB RGBF SHOWPAGE TEXTHEIGHT TEXTWIDTH TXTH TXTW VIEW WINDOW XMAX XPOS YMAX YPOS AND AS BAND BG BOR BYREF CALL CASE CATCH CONST DECLARE DEF DO ELIF ELSE ELSEIF END END TRY ENDIF EQV EXIT FALSE FI FOR FUNC GOSUB GOTO IF IFF IMP IN LABEL LET LIKE LOCAL LSHIFT MDL MOD NAND NEXT NOR NOT ON OR REM REPEAT RETURN RSHIFT SELECT STEP STOP SUB THEN THROW TO TRUE TRY UNTIL USE USG USING WEND WHILE XNOR XOR ABS ABSMAX ABSMIN ACOS ACOSH ACOT ACOTH ACSC ACSCH ASEC ASECH ASIN ASINH ATAN ATAN2 ATANH ATN CEIL COS COSH COT COTH CSC CSCH DEG DERIV DETERM DIFFEQN EXP EXPRSEQ FIX FLOOR FRAC INT INTERSECT INVERSE LINEQN LOG LOG10 M3APPLY M3IDENT M3ROTATE M3SCALE M3TRANS MAX MIN POLYAREA POLYCENT POLYEXT POW PTDISTLN PTDISTSEG PTSIGN RAD RND ROOT ROUND SEC SECH SEGCOS SEGLEN SEGSIN SEQ SGN SIN SINH SQR STATMEAN STATMEANDEV STATMEDIAN STATSPREADP STATSPREADS STATSTD SUM SUMSQ TAN TANH TRANSPOSE ASC BCS BIN CBS CHOP CHR DISCLOSE ENCLOSE FORMAT HEX INSTR JOIN LCASE LEFT LEFTOF LEFTOFLAST LOWER LTRIM MID OCT REPLACE RIGHT RIGHTOF RIGHTOFLAST RINSTR RTRIM SINPUT SPACE SPC SPLIT SPRINT SQUEEZE STR STRING TRANSLATE TRIM UCASE UPPER VAL CHAIN COMMAND CWD DELAY ENV ENV EXEC EXPORT FRE HOME IMPORT INCLUDE MAXINT NIL OPTION PAUSE PI PROGLINE RANDOMIZE RUN SBVER SELF STKDUMP TROFF TRON UNIT +========================================================================================+ | 1. (Console) AT | +========================================================================================+ AT x, y Moves the text cursor to the specified position [x, y]. x and y are in pixels. See LOCATE to move the text cursor in units of characters cells. Example at 100,100 print "This text starts at pixel 100,100" +========================================================================================+ | 2. (Console) BEEP | +========================================================================================+ BEEP Generates a beep sound. Example beep +========================================================================================+ | 3. (Console) CAT | +========================================================================================+ CAT (x) Returns an escape code to format a string. The values of x are listed in teh followin table: x format ---- --------------- 0 reset 1 bold -1 bold off 2 underline -2 underline off 3 reverse -3 reverse off For more information about escape codes please see the article “Escape codes”. Example Color 14, 1 print Cat(1); "This is Bold text"; Cat(-1) print print Cat(2); "This is Underline text"; Cat(-2) print print Cat(3); "This is Reverse text"; Cat(-3) print ' Cat(0) resets ALL attributes, including colors. print Cat(1); Cat(2); "This is Bold & Underline text"; Cat(0) print print Cat(2); Cat(3); "This is Underline & Reverse text (with default colors)"; Cat(0) +========================================================================================+ | 4. (Console) CLS | +========================================================================================+ CLS Clears the screen. Example print "Test" CLS +========================================================================================+ | 5. (Console) DEFINEKEY | +========================================================================================+ DEFINEKEY k,sub Binds a keycode k to a user defined sub routine sub. When the key is pressed, the coresponding sub routine will be called. To unbind the keycode definition pass 0 as the sub argument. Keycodes for PC keyboard Key Keycode ------------------ ------------------------------------------------ A to Z asc(“a”) to asc(“z”) 0 to 9 asc(“0”) to asc(“9”) Backspace 8 Delete 127 Break 3 Tab 9 Enter / Return 13 Space 32 Escape 27 Page Up / Prior 0xFF01 Page Down / Next 0xFF02 Left 0xFF04 Right 0xFF05 Up 0xFF09 Down 0xFF0A Insert 0xFF10 Home 0xFF11 End 0xFF12 Menu 0xFF1F F1 to F15 0xFFF0+1 to 0xFFF0+15 Ctrl + A to Z 0x71000000 + asc(“a”) to 0x71000000 + asc(“z”) Alt + A to Z 0x72000000 + asc(“a”) to 0x72000000 + asc(“z”) Shift + A to Z asc(“A”) to asc(“Z”) Examples Example 1: Bind keystroke for left and right arrow key defineKey 0xFF04, Increase 'Left arrow defineKey 0xFF05, Decrease 'Right arrow sub Increase x = x + 1 end sub Decrease x = x - 1 end while(1) t = ticks() at 0,0: print t + ": " + x + " " delay(50) wend Example 2: Unbind a keystroke DEFINEKEY 0xFF04, 0 Example 3: Etch-a-Sketch ' DEFINEKEY demo.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-30 'remember Etch-A-Sketch? 'definekey key,sub 'example: definekey 0xFF04, moveleft 'press left arrow definekey 0xFF05, moveright 'press right arrow definekey 0xFF09, moveup 'press up arror definekey 0xFF0A, movedown 'press down arrow definekey 99, togglecolor 'press c for color toggle black (erase), blue, red, white definekey 115, togglestepper 'press s for stepper 1,5,10,50 definekey 27, quit 'press esc to quit colr=15 stepper=1 tx=xmax/2 ty=ymax/2 pset tx,ty,0 while 1 color 0,0 locate 0,0:? spc(100) color colr,0 locate 0,0 if colr=0 then color colr,15 ?"tx= ";tx;" ty= ";ty;" c= ";colr;" s=";stepper; if colr=0 then color colr,0 lc=(lc+1) mod 2 if lc then pset step 0,0,14 else pset step 0,0,0 delay 60 wend sub moveleft pset step 0,0 if tx-stepper>=0 then tx-=stepper:line step -stepper,0 else beep end sub moveright pset step 0,0 if tx+stepper<=xmax then tx+=stepper:line step stepper,0 else beep end sub moveup pset step 0,0 if ty-stepper>=0 then ty-=stepper:line step 0,-stepper else beep end sub movedown pset step 0,0 if ty+stepper<=ymax then ty+=stepper:line step 0,stepper else beep end sub togglecolor select case colr case 0 : colr=9 case 9 : colr=12 case 12: colr=15 case 15: colr=0 end select end sub togglestepper select case stepper case 1 : stepper=5 case 5 : stepper=10 case 10: stepper=50 case 50: stepper=1 end select end sub quit stop end Example 4: This example is outdated and just a reference for buttons in PALM OS ' Note: ' * You may Include "definekey_const.bas" file in another file to make your code more clear. ' ' * Created using SmallBASIC version 0.12.2 (on Linux Mint 17.3). ' * More keys might be included in future/other versions of SmallBASIC. ' * Values for DEFINEKEY cannot be used for INKEY. ' * I could not verify all keys (especially CTRL & ALT seems not to work). ' * Key codes are from "keymap.h": https://sourceforge.net/p/smallbasic/code/HEAD/tree/trunk/smallbasic/src/keymap.h ' ' Demo - add these lines to another BAS file: ' ------------------------------------------ ' Include "definekey_const.bas" ' ' Definekey DK_LEFT, left_arrow ' ' Sub left_arrow: i++: ? i; " "; ' End Sub ' ' ? "Press Left-Arrow key, or Ctrl+B to stop...": Pause ' While 1: Wend ' ------------------------------------------ ' definekey_const.bas - DEFINEKEY key codes (keymap.h; 30/4/2010) ' Note: bind a regular character with 'DEFINEKEY Asc("a"), sub' Const IS_PALM_OS = (Left(OSNAME, 1) = "P") ' Else is_UNIX / is_Windows ' PalmOS - H/W keys: Const DK_PALM_PGUP = 0xFF01 Const DK_PALM_PGDN = 0xFF02 Const DK_PALM_BTN1 = 0xFF03 Const DK_PALM_BTN2 = 0xFF04 Const DK_PALM_BTN3 = 0xFF05 Const DK_PALM_BTN4 = 0xFF06 Const DK_PALM_FIND = 0xFF07 Const DK_PALM_CALC = 0xFF08 Const DK_BREAK = Iff(IS_PALM_OS, DK_PALM_BTN4, 0x3) ' MemoPad, Ctrl+C Const DK_DELETE = 127 ' (in keymap.h: DELETE = 8, BACKSPACE = 127) Const DK_BACKSPACE = 8 Const DK_TAB = 9 Const DK_ENTER = 13 ' 13 is CR (in keymap.h: ENTER = '\\n') ' Common with Handhelds (0xFF00 to 0xFF0F): Const DK_PGUP = 0xFF01 Const DK_PRIOR = DK_PGUP Const DK_PGDN = 0xFF02 Const DK_NEXT = DK_PGDN Const DK_LEFT = 0xFF04 Const DK_RIGHT = 0xFF05 Const DK_UP = 0xFF09 Const DK_DN = 0xFF0A Const DK_DOWN = DK_DN ' Common on PCs (0xFF10 to 0xFF1F): Const DK_INSERT = 0xFF10 Const DK_HOME = 0xFF11 Const DK_END = 0xFF12 ' Other application keys: Const DK_MENU = 0xFF1F ' Function keys (16 codes), e.g. Definekey DK_FUNC(1): Def DK_FUNC(x) = 0xFFF0 + x ' -- Verified with 1-12 (F1-F12) Def DK_SFUNC(x) = 0xFFE0 + x ' ( ...is it for F13-F16 ? ) ' Control keys, e.g. Definekey DK_CTRL(ASC("R")): Def DK_CTRL(x) = x - 64 ' x must be a capital character ' Alt keys, e.g. Definekey DK_ALT(ASC("r")): Def DK_ALT(x) = 0xFF20 + (x - Iff(x >= 97, 57, 31)) ' Keypad: Const DK_KP_DIV = 0xFFDA Const DK_KP_MUL = 0xFFDB Const DK_KP_MINUS = 0xFFDC Const DK_KP_PLUS = 0xFFDD Const DK_KP_ENTER = 0xFFDE Const DK_KP_HOME = 0xFFD7 Const DK_KP_UP = 0xFFD8 Const DK_KP_PGUP = 0xFFD9 Const DK_KP_LEFT = 0xFFD4 Const DK_KP_CENTER = 0xFFD5 Const DK_KP_RIGHT = 0xFFD6 Const DK_KP_END = 0xFFD1 Const DK_KP_DOWN = 0xFFD2 Const DK_KP_PGDN = 0xFFD3 Const DK_KP_INS = 0xFFD0 Const DK_KP_DEL = 0xFFDF ' Mouse: Const DK_MK_PUSH = 0xFFC0 Const DK_MK_DRAG = 0xFFC1 Const DK_MK_MOVE = 0xFFC2 Const DK_MK_RELEASE = 0xFFC3 Const DK_MK_WHEEL = 0xFFC4 Const DK_MK_FIRST = DK_MK_PUSH Const DK_MK_LAST = DK_MK_WHEEL +========================================================================================+ | 6. (Console) FORM | +========================================================================================+ FORM(map) Creates a form object f from a MAP variable formMap. Form object f gives access to the following GUI elements: - Push button - Label - Hyperlinked text - Listbox - Dropdown listbox - Single or multi-line text input - Image button In listboxes and dropdown listboxes press and hold mouse button to scroll through the items. Alternatively arrow keys can be used. Press return or space for selecting the highlighted item. The form object f = form(formMAP) provides access to the following sub-commands of the form object f: ----------------------------------------------------------------------- Sub-command Description -------------------- -------------------------------------------------- doEvents() Process system events for mouse and keyboard handling. close() Closes the active FORM. refresh(n) n = 1 copy the UI state into the FORM input variables f.inputs. n = 0 update the UI state using the FORM input variables f.inputs. ----------------------------------------------------------------------- The form object f may contain the following properties: Property Description ---------- ---------------------------------------- value The value from the active input field. inputs Array of inputs. focus Index to the focused input. Defining the input fields inputs is an array of type MAP, each element may contain the following attributes: ----------------------------------------------------------------------- Attribute Description ------------------------------------- --------------------------------- x X coordinate. y Y coordinate. width Width. height Height. value The internal value associated with the input. label The display label for the input. name The name of the input. type The type of input, see below. help Listbox or single line text input help text. backgroundColor Background color. color Forground color. isExit Whether clicking the input exits the current program. isExternal Whether the link field opens in an external browser. resizable Whether the field can be resized. visible Whether the input field is visible. selectedIndex The selected item in a listbox or choice. length Length of a TEXT input field in number of characters. noFocus The input cannot receive focus. onclick SUB to invoke when clicked. ----------------------------------------------------------------------- The type attribute can be one of the following: Type Description ----------- ---------------------------------- “button” Push button. “label” Display label. “link” Hyperlinked text. “listbox” Listbox. “choice” Dropdown listbox. “text” Single or multi-line text input. “image” Image button. Change or read the GUI elements Once the GUI elements are rendered on screen they can be changed for example to respond to user input. By calling f.refresh(1) the current state of the GUI elements will be copied to f. The content of f is rendered to screen, when calling f.refresh(0). f.inputs is an array of MAP variables. The first element of that array is the first GUI element added to formMap.inputs. For example the color of the first element can be changed: f.inputs[0].color = 12 f.refresh(0) To get a list of all available elements of the n-th GUI element, you can simply use print f.inputs[n]. Example 1: Creating a push button using callback function When using buttons in combination with callback functions, the doEvents() function is not necessary. Without this function the execution of the program will not be blocked. In the following example a number will be incremented in a while loop and printed to the screen. When the button is pressed, the callback function is executed and will block the program until the callback function ends. button.type = "button" button.x = 120 button.y = 120 button.label = "Button" button.backgroundcolor = rgb(60, 60, 60) button.onclick = @ButtonClicked ' Callback function, definition see below formMAP.inputs << button f = form(formMAP) while 1 ii++ locate 0,0: print ii delay(100) wend f.close() sub ButtonClicked() locate 1,0 Clicked++ print "Button clicked " + Clicked + " times" end Example 2: Creating a push button using doEvents result button.type = "button" button.x = 120 button.y = 120 button.label = "Button" button.backgroundcolor = rgb(60, 60, 60) button.value = 1 ' unique value to identify the button formMAP.inputs << button f = form(formMAP) while 1 f.doEvents() if(f.value == 1) then ii++ at 0,0 print "Button cklicked " + ii + " times." endif wend f.close() Example 3: Creating a label l.type = "label" l.x = 120 l.y = 120 l.label = "Label" l.color = rgb(255, 60, 60) f.inputs << l f = form(f) while 1 f.doEvents() wend f.close() Example 4: Creating a link to an external website l.type = "link" l.x = 120 l.y = 120 l.label = "Link to SmallBASIC website" l.value = "https://smallbasic.github.io" l.isExternal = true l.color = rgb(100, 100, 255) f.inputs << l f = form(f) while 1 f.doEvents() wend f.close() Example 5: Creating a listbox l.type = "listbox" l.x = 120 l.y = 120 l.height = 200 l.width = 100 l.value = "cats|dogs|fish|birds|insects" ' alternative way is to pass an array: ' l.value = ["cats", "dogs", "fish", "birds", "insects"] l.color = rgb(255, 255, 255) l.backgroundColor = rgb(100, 100, 100) f.inputs << l f = form(f) while 1 f.doEvents() ' Check for value of the active input field if (len(f.value) > 0) then at 0,0 print f.value; " " end if wend f.close() Example 6: Creating a dropdown listbox l.type = "choice" l.x = 120 l.y = 120 l.width = 100 l.value = "cats|dogs|fish|birds|insects" ' alternative way is to pass an array: ' l.value = ["cats", "dogs", "fish", "birds", "insects"] l.color = rgb(255, 255, 255) l.backgroundColor = rgb(100, 100, 100) f.inputs << l f = form(f) while 1 f.doEvents() ' Check for value of the active input field if (len(f.value) > 0) then at 0,0 print f.value; " " end if wend f.close() Example 7: Creating a text input field t.type = "text" t.x = 120 t.y = 120 t.width = 300 t.value = "Add more text" ' t.height = 100 ' if hight is not defined, single line field t.color = rgb(255, 255, 255) t.backgroundColor = rgb(100, 100, 100) t.length = 50 ' number of characters ' create additionally an OK-Button to update the form object ' otherwise the text field blocks loop b.type = "button" b.x = 120 + t.width + 10 b.y = 120 b.label = "OK" b.backgroundcolor = rgb(60, 60, 60) b.onclick = @OKButtonClicked f.inputs << t f.inputs << b f = form(f) while 1 f.doEvents() wend f.close() sub OKButtonClicked() f.refresh(1) ' Update the form object at 0,0 print f.inputs[0].value ' Text field is the first element added to the formMAP end Example 8: Image button using callback function In this example a callback function will be used. If you want to use the doEvents result instead, have a look at example 2. ' Create a simple button and save it as png ' If you have already an image for you button, ' this part is not necessary. circle 100,100,100 color 15 filled ButtonImage = image(0,0,200,200) ButtonImage.save("button.png") cls ' Define image button button.type = "image" button.name = "button.png" button.x = 120 button.y = 120 button.onclick = @ButtonClicked     ' Callback function, definition see below. formMAP.inputs << button f = form(formMAP) while 1   f.doEvents() wend f.close() sub ButtonClicked()   at 0,0   Clicked++   print "Button clicked " + Clicked + " times" end Example 9: One more example f.handleKeys = 0 ' create some buttons button1.y = 120 button1.label = "Button1" button1.value = "valueofButton1" button1.backgroundcolor = rgb(255,0,0) button1.onclick = @HelloWorld 'this prints on load button2.x = -1 button2.y = 120 button2.label = "Button2" button2.value = "valueofButton2" button3.value = "cats" button3.x = -1 button3.y = 120 button3.background = 223344 b4.type = "choice" b4.value = "cats|dogs|Fish|cats|dogs|Fish|cats|dogs|Fish|cats|dogs|Fish" b4.selectedIndex = 2 b4.x = -1 b4.y = 120 b5.type = "list" b5.value = "cats|dogs|Fish|cats|dogs|Fish|cats|dogs|Fish|cats|dogs|Fish|end|lol" b5.x = -1 b5.y = 120 b5.height = 120 b6.type = "text" b6.value = "cats" b6.length=30 b6.x = -1 b6.y = 120 b6.width = 50 b6.noFocus = 0 ' add buttons to the form f.inputs << button1 f.inputs << button2 f.inputs << button3 f.inputs << b4 f.inputs << b5 f.inputs << b6 f.backgroundcolor = "green" ' at this stage 'f' is just a plain user defined structure (map) ' after calling FORM, 'f' becomes a system form object with three special functions ' doEvents, close and refresh (see sokoban.bas for refresh) f = form(f) ' the string version of the form is JSON (see https://en.wikipedia.org/wiki/JSON) TSAVE "f.frm", f while 1 ' pump the system event queue f.doEvents() ' process the event in$ = inkey at 0,0 if len(in$)>1 then flag= asc(left(in$,1)) keychar =right(in$,1) n= asc(keychar) if (flag == 1) ? "Ctrl : ";keychar ; " " else if (flag == 2) ? "Alt : "; keychar else if (flag == 3) ? "Ctrl+Alt: "; keychar ; " " else ? "Arrow: "; n ; " " end if else vkey = asc(in$) if (vkey == 8) then ? "backspace!" else if (vkey == 127) then ? "delete !" else ? " key= "; in$; " "; vkey endif endif if b6.value <> "cats" then ? b6.value if (len(f.value) > 0) then print f.value; " " end if wend f.close() func HelloWorld ? "hello world" end +========================================================================================+ | 7. (Console) INKEY | +========================================================================================+ INKEY Returns the last key-code in keyboard buffer, or an empty string if there are no keys. Special key-codes like the function-keys are returned as 2-byte string. Example 1 WHILE(1) k = INKEY IF LEN(k) IF LEN(k)=2 ? "H/W #"+ASC(RIGHT(k,1)) ELSE ? k; " "; ASC(k) FI FI SHOWPAGE WEND Example 2 The following program will return the keycode and a string for every pressed key. The string can be used in an if-statement to querry if the key was pressed. See example 3 how to use the string. while(1) k = INKEY if len(k) if len(k) == 2 print "2-Byte key code : " + asc(mid(k,1,1)) + " " + asc(mid(k,2,1)); print " -> s = chr(";asc(mid(k,1,1));") + chr(";asc(mid(k,2,1));")" else if(asc(k) > 37) print "Printable key code: "; asc(k); " -> s = \"";k;"\"" else print "1-Byte key code : "; asc(k); print " -> s = chr(";asc(k);")" endif endif endif showpage wend Example 3: Querry if a key was pressed See example 2 to get the keycodes for the keys. const KeyUp = chr(27) + chr(9) const KeyDown = chr(27) + chr(10) const KeySpace = " " const KeyEsc = chr(27) const KeyReturn = chr(13) while(1) k = INKEY if len(k) select case k case KeyUp: print "Up" case KeyDown: print "Down" case KeySpace: print "Space" case KeyEsc: print "Esc" case KeyReturn: print "Return" case "a": print "a" case "A": print "A" case else: print "other key" end select endif showpage wend Example 4: Input form ' Key values: Const K_BKSP = Chr(0x08) ' BackSpace Const K_TAB = Chr(0x09) Const K_ENTER = Chr(0x0D) Const K_ESC = Chr(0x1B) ' Escape Const K_DELETE = Chr(0x7F) Const K_PGUP = K_ESC + Chr(0x01) ' Page Up Const K_PGDN = K_ESC + Chr(0x02) ' Page Down Const K_LEFT = K_ESC + Chr(0x04) ' Arrow Left Const K_RIGHT = K_ESC + Chr(0x05) ' Arrow Right Const K_UP = K_ESC + Chr(0x09) ' Arrow Up Const K_DOWN = K_ESC + Chr(0x0A) ' Arrow Down Const K_INSERT = K_ESC + Chr(0x10) Const K_HOME = K_ESC + Chr(0x11) Const K_END = K_ESC + Chr(0x12) ' Edit string: Def edit_char(txt, pos, char, ins_mode) = Replace(txt, pos, char, ins_mode = 0) Def delete_char(txt, pos) = Replace(txt, pos, "", 1) ' Initialize three demo fields: f_lbl = ["First Name:", "Last Name: ", "Your Hobby:"] ' field label f_row = [3, 5, 7] ' label row f_col = [1, 1, 1] ' label column f_len = [10, 10, 20] ' variable length f_var = ["", "", ""] ' variable value ' Index of fields: Const MIN_IX = Lbound(f_lbl) Const MAX_IX = Ubound(f_lbl) ix = MIN_IX ' Start on first field index ins_mode = 1 ' Start in insert character mode ' Main demo loop: While True ' Update variables: eol = Len(f_var(ix)) + 1 ' End Of Line If pos > eol Or pos < 1 Then pos = eol ' Adjust cursor pos on new field ' Update screen: For i = MIN_IX To MAX_IX ' Print all fields: s = Cat(0) + f_lbl(i) + " " s += Cat(3) + f_var(i) + Spc(f_len(i) - Len(f_var(i))) + " " ' + eol Locate f_row(i), f_col(i) Print s + Cat(0); ' Print the cursor: If i = ix Then If Not ins_mode Then Color 15 Locate f_row(i), f_col(i) + Len(f_lbl(i)) + pos Print Cat(2) + Mid(f_var(i) + " ", pos, 1); ' (+ " " for eol) Fi Next i ' Update status line: s = " (Esc=Stop) | " + Iff(ins_mode, "Insert ", "Replace") + Spc(3) s += Format("| 00:", ix) + Iff(pos = eol, "EOL", Format("000", pos)) + Spc(1) Locate 0, 0: Print Cat(0) + Cat(3) + s; Showpage ' SHOWPAGE makes INKEY works smoother (using SB 0.12.2) ' Wait for a key: Repeat: key = Inkey Until key <> "" ' Check key: Select Case key Case K_ESC: Stop Case K_INSERT: ins_mode = Not ins_mode Case K_ENTER, K_TAB: ix++: If ix > MAX_IX Then ix = MIN_IX Case K_DOWN: If ix < MAX_IX Then ix++ Case K_UP: If ix > MIN_IX Then ix-- Case K_PGDN: ix = MAX_IX Case K_PGUP: ix = MIN_IX Case K_HOME: pos = 1 Case K_END: pos = eol Case K_LEFT: If pos > 1 Then pos-- Case K_RIGHT: If pos < eol Then pos++ Case K_DELETE: If pos < eol Then f_var(ix) = delete_char(f_var(ix), pos) Case K_BKSP: If pos > 1 Then pos--: f_var(ix) = delete_char(f_var(ix), pos) Case Else If Len(key) = 1 And Asc(key) >= 32 Then ' Regular character? ins = ins_mode And (Len(f_var(ix)) < f_len(ix)) ' Insert mode rep = (Not ins_mode) And (pos <= f_len(ix)) ' Replace mode If ins Or rep Then f_var(ix) = edit_char(f_var(ix), pos, key, ins_mode) pos++ ' Move cursor to next character Fi Fi End Select Wend Example 5: A basic key code UNIT REM Language: SmallBASIC 0.12.6 (Linux 32-bit) REM Purpose: Special key values returned by INKEY. REM (Values returned by INKEY cannot be used for DEFINEKEY). REM File name: key.bas REM Unit name: key REM Version: 1.0.0 24/05/2016 REM Author: shian ' --- Start demo code ------------------------------------ ' 'Import key ' '? "Press Escape to stop..." 'Repeat: k = Inkey ' Select Case k ' Case Key.ENTER : ? "Key.ENTER" ' Case Key.TABK : ? "Key.TABK" ' Case Key.CLICK : ? "Key.CLICK" ' Case Key.FN(1) : ? "Key.FN(1)" ' Case Key.FN(12) : ? "Key.FN(12)" ' Case Key.CTRL("A"): ? "Key.CTRL(a)" ' Case Key.ALT("A") : ? "Key.ALT(a)" ' Case Key.CTRL(Key.Enter) : ? "Key.CTRL(Key.Enter)" ' Case Key.ALT(Key.Enter) : ? "Key.ALT(Key.Enter)" ' Case Key.SHIFT(Key.Enter): ? "Key.SHIFT(Key.Enter)" ' End Select 'Until k = Key.ESC ' ' --- End demo code ------------------------------------ Unit key ' Useful Constants: Export BKSP, TABK, ENTER, ESC, BLANK, DEL Export PGUP, PGDN, LEFTK, RIGHTK, UP, DOWN Export INS, HOMEK, ENDK, CLICK ' Useful Functions: Export FN, CTRL, ALT, SHIFT Export CTRL_ALT, ALT_SHIFT, CTRL_SHIFT ' (used by system) ' The left character of INKEY (Useful only for special cases): Export CTRL_CHR, ALT_CHR, SHIFT_CHR Export CTRL_ALT_CHR, ALT_SHIFT_CHR, CTRL_SHIFT_CHR Const CTRL_CHR = Chr(0x01) ' for Ctrl+Char Const ALT_CHR = Chr(0x02) ' for Alt+Char Const SHIFT_CHR = Chr(0x03) ' for Shift+Char Const CTRL_ALT_CHR = Chr(0x04) ' for Ctrl+Alt+Char (used by system) Const ALT_SHIFT_CHR = Chr(0x05) ' for Alt+Shift+Char (used by system) Const CTRL_SHIFT_CHR = Chr(0x06) ' for Ctrl+Shift+Char (used by system) Const BKSP = Chr(0x08) ' BackSpace Const TABK = Chr(0x09) ' Tab key Const ENTER = Chr(0x0D) Const ESC = Chr(0x1B) ' Escape Const BLANK = Chr(0x20) ' Space key Const DEL = Chr(0x7F) ' Delete Const PGUP = ESC + Chr(0x01) ' Page Up Const PGDN = ESC + Chr(0x02) ' Page Down Const LEFTK = ESC + Chr(0x04) ' Arrow Left key Const RIGHTK = ESC + Chr(0x05) ' Arrow Right key Const UP = ESC + Chr(0x09) ' Arrow Up Const DOWN = ESC + Chr(0x0A) ' Arrow Down Const INS = ESC + Chr(0x10) ' Insert Const HOMEK = ESC + Chr(0x11) ' Home key Const ENDK = ESC + Chr(0x12) ' End key Const CLICK = ESC + Chr(0xC0) ' Left Mouse Button Click Def FN(n) = ESC + Chr(0xF0 + n) ' FN(1) is F1 (up to 12). Def CTRL(c) = CTRL_CHR + Lcase(c) ' Ctrl+a, Ctrl+Enter, etc Def ALT(c) = ALT_CHR + Lcase(c) ' Alt+a, Alt+Enter, etc Def SHIFT(c) = SHIFT_CHR + c ' Shift+Enter, Shift+Tab, etc ' These are system shortcuts - so it's advisable NOT to use them at all! ' (however, it's possible to detect them when not used by the system). Def CTRL_ALT(c) = CTRL_ALT_CHR + Lcase(c) ' Ctrl+Alt+a, etc Def ALT_SHIFT(c) = ALT_SHIFT_CHR + Lcase(c) ' Alt+Shift+a, etc Def CTRL_SHIFT(c) = CTRL_SHIFT_CHR + Lcase(c) ' Ctrl+Shift+a, etc ' ' Use this code to test and print key codes as hexa: ' ' -------------------------------------------------- ' Print "Press Ctrl+B to stop..." ' While 1: k = Inkey: l = Len(k) ' If l Then ' ? "0x"; Right("00" + Hex(Asc(k)), 2); ' If l = 2 Then ? Right("00" + Hex(Asc(Mid(k, 2))), 2); ' Print ' Fi ' Wend +========================================================================================+ | 8. (Console) INPUT | +========================================================================================+ INPUT [prompt,|;] var[, var [, ...]] Reads text from keyboard and stores it in the variable var. The string prompt is printed on the screen. If promt is followed by a ;, a question mark and a space are printed additionally. If you want to input two or more variables, the input needs to be separated with ,. Example 1: Using a single var input "How old are you?", age print age Example 2: Using multiple vars input "Input three numbers: ", a, b, c ' Input i.e. 1,2,3 print a, b, c +========================================================================================+ | 9. (Console) LINEINPUT | +========================================================================================+ LINEINPUT [#fileN] var Reads a whole text line from file or console and stores it in the string var. If a file handle #fileN is specified, LINEINPUT will read from the corresponding file otherwise it will read from the console. Example 1: Read from console LINEINPUT S PRINT S Example 2: Read from file ' create a file open "File.txt" for output as #1 print #1, "First line" print #1, "Second line" close #1 ' open file and print content open "File.txt" for input as #1 LINEINPUT #1, S Print S LINEINPUT #1, S Print S close #1 +========================================================================================+ | 10. (Console) LINPUT | +========================================================================================+ LINPUT [#fileN] var Reads a whole text line from file or console and stores it in the string var. If a file handle #fileN is specified, LINPUT will read from the corresponding file otherwise it will read from the console. LINPUT has the same function as LINEINPUT. Example 1: Read from console LINPUT S PRINT S Example 2: Read from file ' create a file open "File.txt" for output as #1 print #1, "First line" print #1, "Second line" close #1 ' open file and print content open "File.txt" for input as #1 LINPUT #1, S Print S LINPUT #1, S Print S close #1 +========================================================================================+ | 11. (Console) LOCATE | +========================================================================================+ LOCATE y, x Moves the console (text-mode) cursor to the specified position. row and column are in text-mode character cells. See AT for positioning the cursor in pixel. Example 1: locate 5,7 print "text at row 5 and column 7" Example 2: Print text always in center of window ' Define functions to calculate lines and columns Def lines() = (Ymax + 1) \ Txth("x") ' maximum lines in window Def columns() = (Xmax + 1) \ Txtw("x") ' maximum columns in window ' Define functions to calculate position of text Def center_line() = lines \ 2 Def center_column(text) = (columns \ 2) - (Len(text) \ 2) ' attributes for printing text (ESCAPE codes): Const ESC = Chr(27) Const bold_on = ESC + "[1m" ' strong Const bold_off = ESC + "[21m" Const line_on = ESC + "[4m" ' underline Const line_off = ESC + "[24m" Const reve_on = ESC + "[7m" ' reverse Const reve_off = ESC + "[27m" ' colors for printing text: Const WHITE = 7 Const BLACK = 0 Const YELLOW = 14 Const BLUE = 1 Const HELLO = "* Hello World! *" ' text to print. ' loop until user press Esc key: While Inkey <> Chr(27) ' update screen if user resized the window: If (x <> Xmax) Or (y <> Ymax) Then Color WHITE, BLACK Cls Print Using "Please resize window (Esc=Stop) 000:0000"; lines(), columns(); ' Print hello world: l = center_line() c = center_column(HELLO) Color YELLOW, BLUE Locate l - 1, c: Print bold_on + HELLO + bold_off; Locate l , c: Print reve_on + HELLO + reve_off; Locate l + 1, c: Print line_on + HELLO + line_off; ' remember current windows size: x = Xmax y = Ymax Endif Wend Example 3: Print ASCII table ' LOCATE MOD CHR ASC.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-23 ' ' LOCATE row, column: sets the next print location on screen, ' rows down, columns across ' a MOD b : returns the remainder of a/b as integer 0 to b-1 ' for example odd number n mod 2 returns 1, whil ' even number n mod 2 returns 0 ' n mod 10 returns 0,1,2,3,4,5,6,7,8 or 9 ' we will use this in demo ' CHR(number) : returns the CHaRracter for the ASC number, ' for demo we will print a chart of CHR for ASC ' numbers 30-129 ' ASC(Character) : is a number code for a print characters, 32 is ' the code for a space ' ? : is shortcut for PRINT ' RIGHT(string,n) : returns right most n characters of string ' STR(n) : returns a number in string form ' : : code statement seperator often used with ' LOCATE row, column : ? string LOCATE 1, 16 : ? "ASC Table 30-129:" ' locate print spot, print title for our chart FOR column = 0 to 9 ' print a header, 10 numbers plus + (to add to row value) LOCATE 2, column * 5 + 4 : ? "+";column NEXT FOR row = 3 to 12 LOCATE row, 0 : ? RIGHT(" " + STR(row * 10) + ":", 4) NEXT FOR ASCnumber = 30 to 129 ' note ASC(32) = space so wont see anything in Table row = ASCnumber \ 10 ' \ rounds division down to integer column = (ASCnumber MOD 10) * 5 + 5 ' times 5 to space out the characters printed plus 5 for column labels LOCATE row, column : ? CHR(ASCnumber) '<=========== handy reference NEXT +========================================================================================+ | 12. (Console) LOGPRINT | +========================================================================================+ LOGPRINT ... Prints to stderr. The syntax is the same as the command PRINT. LOGPRINT can be used to print log messages to a different output. The nicely formated output of your program will not be messed up by the log messages. Example: logprint "Error message goes to stderr" print "Normal text goes to sdtout" stderr with sbasicg (SDL-version) When starting sbasicg or sbasicg.exe from a command line, this command line will be the stderr output. When using PRINT the text will be displayed in the program window. When using LOGPRINT the text will be printed to the the command line window and not displayed in the program window. stderr with sbasic (console version) The command line is usually stderr and stdout at the same time. Text printed with PRINT and text printed with LOGPRINT will be displayed in the command line window. Redirect stderr to a file (Linux) In Linux sdterr can be easily redirected to a file (i.e. error.txt): Start the basic-file from a command line: SDL-version : sbasicg test.bas 2>error.txt Console-version: sbasic test.bas 2>error.txt with test.bas: logprint "Error message goes to stderr" print "Normal text goes to sdtout" Afer running the program the file error.txt will appear with the content: Error message goes to stderr +========================================================================================+ | 13. (Console) NOSOUND | +========================================================================================+ NOSOUND Stop background sound and clear the sound queue. Example sound 1000, 5000, 50 BG ' 1000 Hz, 5000 ms, 50% volume, play in background delay(1000) ' Wait 1s and then cancel sound nosound pause +========================================================================================+ | 14. (Console) PEN | +========================================================================================+ PEN ON|OFF Enables/Disables the pen/mouse/tap mechanism. See function n = PEN(value) for information on how to read data from tap, mouse or pen. Example pen on print "Press left mouse button or tab screen. Press q to quit." while(1) if(pen(3)) then PosX = pen(4) PosY = pen(5) locate 1,0: print "Click/tap at position: " + PosX + " , " + PosY endif k = inkey() if(len(k) == 1 AND k == "q") then end showpage delay(20) wend pen off +========================================================================================+ | 15. (Console) PLAY | +========================================================================================+ PLAY string Play musical notes, a mp3 or ogg sound file. The music string is composed of the following building blocks: ----------------------------------------------------------------------- String Description ----------------------- ----------------------------------------------- A-G[- + On Octave n = 0..6, n = < moves down one octave, n = > moves up one octave Nn Play note n = 0..84 (0 = pause) Pn Pause n = 1..64 Ln Length of note n = 1..64 (1/nnn) Tn Tempo n = 32..255. Number of 1/4 notes per minute. MS Staccato (1/2) MN Normal (3/4) ML Legato Vn Volume n = 0..100 MF Play on foreground MB Play on background Q Clear sound queue ----------------------------------------------------------------------- To play a sound file use file://filename as string. When playing on background, program execution continuous. If the end of the program is reach, the playback will stop. Example 1: Play a note play "L2A" ' note A with length 1/2 Example 2: Play multiple notes ' Set volume to 50% play "V10" ' Play Menuet by J. Sebastian Bach play "T180L8O3MN O4D4O3MLGABO4C O4D4O3MNG4MLG4 O4MNE4MLCDEF# O4G4O3MNG4MLG4 O4MNC4MLDCO3BA O3MNB4MLO4CO3BAG O3MNA4MLBAGF# G2.MN" Example 3: Play notes on background play "MBL2A" ' note A with length 1/2 on background pause ' make sure, that program will not end Example 4: Play a sound file ' Copy a mp3 file to the working directory and name it test.mp3 play "file://test.mp3" pause ' make sure, that program will not end +========================================================================================+ | 16. (Console) PRINT | +========================================================================================+ PRINT [USING [format];] [expr|str [,|; [expr|str]] ... Display numbers, strings or values of expressions. The symbol ? can be used instead of keyword PRINT. You can use USG instead of USING. If a file handle #file is given, the output of print will be redirected to the corresponding file. See OPEN for more information on handling files. To gain more control of where your next PRINT statement will be placed on screen, see LOCATE and AT. Example 1: Basic usage print 1 ' Output: 1 print 1+1 ' Output: 2 print cos(pi) ' Output: -1 print "Text" ' Output: Text Example 2: Print strings and numbers print "abc" + "def" ' Output: adcdef print "abc" + " def" ' Output: abc def print "abc" + 1 + "def" + cos(pi) ' Output: abc1def-1 print "abc" + 1 + 2 + "def" ' Output: abc12def <- 1 and 2 are treated as strings Example 3: Print strings and variables a = 1 b = 2 c = a + b print "a = " + a ' Output a = 1 print "b = " + b ' Output b = 2 print "a + b = " + c ' Output c = 3 PRINT SEPARATORS ----------------------------------------------------------------------- Separator Description --------------- ------------------------------------------------------- TAB(n) Moves cursor position to the nth column. SPC(n) Prints a number of spaces specified by n. ; Separates numbers, expressions or strings , Separates numbers, expressions or strings and insert one TAB ----------------------------------------------------------------------- If ; and , are used as last character of a print command, carriage return/line feed (new line) will be suppressed after printing. In contrast to the + operator to concatenate the output as shown in the examples above, the , and ; operators can be used to concatenate the output and at the same time evaluate expressions. Example 1: Using , and ; a = 1 b = 2 print "a + b = " + a + b ' Output: a + b = 12 <- a and b treated as strings print "a + b = " ; a + b ' Output: a + b = 3 <- a + b was evaluated print "a + b = " , a + b ' Output: a + b = 3 <- a + b was evaluated Example 2: Suppress new line print "abc"; ' <- new line suppressed print "def" ' Output: abcdef Example 3: Using TAB and SPC print "1" + tab(5) + "2" ' Output 1 2 print "1" + spc(1) + "2" ' Output 1 2 PRINT USING PRINT USING uses the FORMAT function to display numbers and strings. Unlike FORMAT it can also include literals. When a PRINT USING command is executed the format will remain in memory until a new format is passed. Calling PRINT USING without a format string specifies that PRINT will use the format of the previous call. Using _ (underscore) will print the next character as a literal. The combination _#, for example, allows you to include a number sign as a literal in your numeric format. See FORMAT for more information on how to define the format string. Example 1: Basic usage a = 1000 b = 2000 PRINT USING "#,###.##"; a PRINT USING "#,###.## "; a; b ' <- Format is applied to all variables PRINT USING "a = #####.00 b = #####"; a; b ' <- One formated string with placeholders for two variables ' Output: 1,000. ' Output: 1,000. 2,000. ' Output: a = 1000.00 b = 2000 Example 2: Apply format multiple times a = 1000 b = 2000 PRINT USING "#,###.##" ' Store format string PRINT a ' Print without format PRINT USING; a ' Print with stored string PRINT USING; b ' Print with stored string PRINT USING "####.00"; a ' Print with new format string and store string PRINT USING; b ' Print with stored string ' Output: ' 1000 ' 1,000. ' 2,000. ' 1000.00 ' 2000.00 Print using VT100 codes Escape codes can be used with PRINT. For more information please read the article “Escape codes” More Examples Example 1: 3 ways to print hello ' 3 ways to print hello five time.bas 2016-03-05 SmallBASIC 0.12.2 [B+=MGA] 'It's all in the punctuation at the end of a print statement '1) no punctiation = whole print lines CR=carriage return and ' LF=line feed, ready to go on next line for i = 1 to 5 print "hello" next print : print '2 blank lines '2) a comma which tabs to next avaiable tab column and will stay ' on same line until run out of coloumns for i = 1 to 5 print "hello", next 'the first print will finish the print line, the 2 two are blank lines print "& this will finish the hello, line." print : print '3) a semicolon (and space after hello) for i = 1 to 5 print "hello";" "; 'or just print "hello "; next print "... this line needs to be finsihed." Example 2: Print to a file Open "PRINT.TXT" For Output As #1 Print #1, "hello" Close #1 +========================================================================================+ | 17. (Console) SOUND | +========================================================================================+ SOUND freq, dur_ms [, vol] [BG] Plays a sound with the frequency freg in Hz for a duration dur in milliseconds. The optional parameter vol controls the volume of the sound. Volume is in the range from 0 to 100, where 100 is maximum volume. If the optional parameter BG is given, the sound will play in the background: SmallBASIC will not wait with program execution until the sound has finished. Example1 : Play sound Sound 1000, 800, 50 ' 1000 Hz, 800 ms, 50% volume Example 2: Play sound in background Sound 1000, 800, 50 BG ' 1000 Hz, 800 ms, 50% volume print "This line will be printed immediately" pause +========================================================================================+ | 18. (Console) TAB | +========================================================================================+ TAB (n) Moves cursor position to the nth column. the return value s contains the escape sequence for moving the cursor. Example print tab(1); "1 tab" print tab(2); "2 tabs" s = tab(3) print s; "3 tabs" +========================================================================================+ | 19. (Data) APPEND | +========================================================================================+ APPEND a, val [, val [, ...]] Inserts the values var1 to varN at the end of the array a. var1 to varN can be any data type. Instead of APPEND the << Operator can be used. Example 1: Append single number a = [1,2,3] print "Before APPEND: "; a APPEND a, 4 print "After APPEND : "; a ' Output: ' Before APPEND: [1,2,3] ' After APPEND : [1,2,3,4] Example 2: Append multiple numbers a = [1,2,3] APPEND a, 4, 5 print a ' Output: [1,2,3,4,5] Example 3: Append an array a = [1,2,3] APPEND a, [4,5,6] print a ' Output: [1,2,3,[4,5,6]] Example 4: Append a string a = ["a", "b", "c"] APPEND a, "d" print a ' Output: [a,b,c,d] Example 5: Using << operator a = [1,2,3] a << 4 print a ' Output: [1,2,3,4] +========================================================================================+ | 20. (Data) ARRAY | +========================================================================================+ ARRAY [var | expr] Creates a ARRAY or MAP variable from the given string s or expression expr. The ARRAY command supports JSON (Javascript object notation) syntax. The MAP provides value-key pair access along with array or dotted notation. See STR for converting a MAP variable into a JSON string. Example 1: JSON string to MAP a = array("{Name: Alice, Age: 20}") print a print a.Name + " is " + a.Age + " years old" ' Output: ' {"Age":20,"Name":"Alice"} ' Alice is 20 years old Example 2: JSON with nested MAP a = Array("{x:1, y:3, down:{x:4, y:7}}") print a ' Output: {"down":{"y":7,"x":4},"x":1,"y":3} Example 3: Array string to array a = Array("[1,2,3]") print a ' Output: [1,2,3] +========================================================================================+ | 21. (Data) DATA | +========================================================================================+ DATA constant1 [,constant2]... Stores one or more constants, of any type, for subsequent access via READ command. DATA commands are non executable statements that supply a stream of data constants for use by READ commands. All the items supplied by all the DATA commands in a program make up one continuous “string” of information that is accessed in order by your program’s READ commands. Use RESTORE to specify which data block should be read next. Example 1 FOR I = 1 TO 3 READ v PRINT v NEXT END DATA 1,2,3 Example 2: Using several data commands. FOR I = 1 TO 6 READ v PRINT v NEXT END DATA 1,2 DATA 3,4,5 DATA 6 Example 3: Specify which data block should be read. RESTORE MyDataBlock FOR I = 1 TO 3 READ v PRINT v NEXT END DATA 1,2,3 LABEL MyDataBlock DATA 4,5,6 ' Output: 4 5 6 +========================================================================================+ | 22. (Data) DELETE | +========================================================================================+ DELETE a, idx [, count] Deletes count elements at position idx of array A. Example 1: Delete element at position 2 a = [1, 2, 3, 4, 5] print a ' Output: [1,2,3,4,5] delete a, 2 print a ' Output: [1,2,4,5] Example 2: Delete two elements starting at position 2 b = [1, 2, 3, 4, 5] print b ' Output: [1,2,3,4,5] delete b, 2, 2 print b ' Output: [1,2,5] +========================================================================================+ | 23. (Data) DIM | +========================================================================================+ DIM var([lower TO] upper [, ...]) [, ...] Reserves storage space for an array. The array will have (upper-lower)+1 elements. If lower is not specified, and OPTION BASE hasn’t used, elements start at 0. Example 1: One dimensional arrays REM One dimensional array of 7 elements, starting from 0 REM with elements A(0), A(1), ... , A(6) DIM A(6) REM One dimensional array of 7 elements, starting from 3 REM with elements A(3), A(4), ... , A(9) DIM A(3 TO 9) REM One dimensional array of 6 elements, starting from 1 REM with elements A(1), A(2), ... , A(6) option base 1 DIM A(6) Example 2: Multi dimensional arrays REM Two dimensional array DIM A(3, 4) REM Three dimensional array DIM A(2 TO 6, 5 TO 9, 1 TO 8) Example 3: Empty array REM Allocating zero-length arrays: DIM z() Example 4: Creating and accessing arrays Option Base 1 ' Set default lower bound of arrays to 1 ? "Showing x,y,z elements of index 5:" ? ' Reserve space for a single 1-dimensional array: x = 0 y = 10 z = 20 Dim a(1 To 30) For i = 1 To 10 a(i + x) = i a(i + y) = i + 10 a(i + z) = i + 100 Next ? a(5 + x), a(5 + y), a(5 + z),, "(1-dimensional array)" ' Reserve the same space for three 1-dimensional arrays: Dim a_x(1 To 10), a_y(1 To 10), a_z(1 To 10) For i = 1 To 10 a_x(i) = i a_y(i) = i + 10 a_z(i) = i + 100 Next ? a_x(5), a_y(5), a_z(5),, "(three 1-dimensional arrays)" ' Reserve the same space for a single 2-dimensional array: x = 1 y = 2 z = 3 Dim a(1 To 10, x To z) For i = 1 To 10 a(i, x) = i a(i, y) = i + 10 a(i, z) = i + 100 Next ? a(5, x), a(5, y), a(5, z),, "(2-dimensional array)" ' Reserve the same space for a single nested array: Dim a(1 To 10) For i = 1 To 10 a(i) = [,,] ' convert this element to nested array a(i)(x) = i a(i)(y) = i + 10 a(i)(z) = i + 100 Next ? a(5)(x), a(5)(y), a(5)(z),, "(nested array)" ' Reserve the same space for a single map array (see also: ARRAY, ISMAP): Dim a(1 To 10) For i = 1 To 10 a(i).x = i a(i).y = i + 10 a(i).z = i + 100 Next ? a(5).x, a(5).y, a(5).z,, "(map array)" +========================================================================================+ | 24. (Data) EMPTY | +========================================================================================+ EMPTY (x) Returns true if x is - a zero length array - an empty string - a number with the value 0. Example s = "" a = [] dim b i = 0 if(empty(s)) then print "s is empty" if(empty(a)) then print "a is empty" if(empty(b)) then print "b is empty" if(empty(i)) then print "i is empty" +========================================================================================+ | 25. (Data) ERASE | +========================================================================================+ ERASE var[, var[, ... var]] Deallocates the memory used by the specified arrays or variables. After that these variables turned to simple integers with zero value. Example DIM x(100) x(1) = 1 x(2) = 2 ERASE x PRINT x(1) ' This will create an error +========================================================================================+ | 26. (Data) INSERT | +========================================================================================+ INSERT a, idx, val [, val [, ...]]] Inserts the values to the specified array at the position idx. - a - An array-variable. - idx - Position in the array. - val - Any value or expression. Example 1: Insert one variable a = [1,2,3,4,5] print a insert a, 3, 6 print a ' Output: ' [1,2,3,4,5] ' [1,2,3,6,4,5] Example 2: Insert several variables a = [1,2,3,4,5] print a insert a, 3, 6, 7, 8 print a ' Output: ' [1,2,3,4,5] ' [1,2,3,8,7,6,4,5] Please be aware, that multiple variables will be sequentially inserted each at position 3. This leads to a reverse order. Example 3: Insert an array a = [1,2,3,4,5] print a insert a, 3, [6,7] print a ' Output: ' [1,2,3,4,5] ' [1,2,3,[6,7],4,5] Example 4: Insert a map variable a = [1,2,3,4,5] b = {x:6, y:7} print a insert a, 3, b print a ' Output: ' [1,2,3,4,5] ' [1,2,3,{"y":7, "x":6},4,5] Example 5: Append a variable (insert at last position) a = [1,2,3,4,5] print a a << 6 print a ' Output: ' [1,2,3,4,5] ' [1,2,3,4,5,6] +========================================================================================+ | 27. (Data) ISARRAY | +========================================================================================+ ISARRAY (x) Returns true if x is an array. Example A = [1,2,3] print IsArray(A) ' Output 1 A = {"x":1, "y":2} print IsArray(A) ' Output 0 (is a map) A = 1 print IsArray(A) ' Output 0 (is a number) A = "abc" print IsArray(A) ' Output 0 (is a string) +========================================================================================+ | 28. (Data) ISDIR | +========================================================================================+ ISDIR (x) Returns true if the string dir is a directory. Example print IsDir("C:\users") ' Output 1 on Windows, otherwise 0 print IsDir("/home") ' Output 1 on Linux, otherwise 0 +========================================================================================+ | 29. (Data) ISFILE | +========================================================================================+ ISFILE (x) Returns true if the string “f” is a regular file. Example print IsFile("C:\windows\EXPLORER.EXE") ' Output 1 on Windows, otherwise 0 print IsFile("/etc/passwd") ' Output 1 on Linux, otherwise 0 +========================================================================================+ | 30. (Data) ISLINK | +========================================================================================+ ISLINK (x) Returns true if string link is a link. Works only in Linux and Android. In Windows ISLINK will return false. +========================================================================================+ | 31. (Data) ISMAP | +========================================================================================+ ISMAP (x) Returns true if x is a MAP variable. Example A = {"x":1, "y":2} print IsMap(A) ' Output 1 A = [1,2,3] print IsMap(A) ' Output 0 (is an array) A = 1 print IsMap(A) ' Output 0 (is a number) A = "abc" print IsMap(A) ' Output 0 (is a string) +========================================================================================+ | 32. (Data) ISNUMBER | +========================================================================================+ ISNUMBER (x) Returns true if x is a number or can be converted to a number. Example print ISNUMBER(12) ' Output 1 print ISNUMBER("12") ' Output 1 print ISNUMBER("12E+2") ' Output 1 print ISNUMBER("abc") ' Output 0 print ISNUMBER("1+2") ' Output 0 print ISNUMBER("int(2.4)") ' Output 0 +========================================================================================+ | 33. (Data) ISSTRING | +========================================================================================+ ISSTRING (x) Returns true if x is a string and cannot be converted to a number. Example print ISSTRING(12) ' Output 0 print ISSTRING("12") ' Output 0 print ISSTRING("12E+2") ' Output 0 print ISSTRING("abc") ' Output 1 print ISSTRING("1+2") ' Output 1 print ISSTRING("int(2.4)") ' Output 1 +========================================================================================+ | 34. (Data) LBOUND | +========================================================================================+ LBOUND (array [, dim]) Returns the lower bound lb of an array array. dim can be used to specifiy, at which dimension the lower bound should be returned if array is a multi-dimensional array. If dim is not used the lower bound of the first dimension will be returned. See UBOUND for upper bound of an array. Example 1: Lower bound of one-dimensional arrays dim A(5) dim B(5 to 10) print lbound(A) ' Output: 0 print lbound(B) ' Output: 5 Example 2: Lower bound of multi-dimensional arrays dim A(5,6,7) dim B(5 to 10, 7 to 12, 9 to 14) print lbound(A, 2) ' Output: 0 print lbound(B, 2) ' Output: 7 Example 3: Using option base 1 option base 1 dim A(5) dim B(5 to 10) print lbound(A) ' Output: 1 print lbound(B) ' Output: 5 +========================================================================================+ | 35. (Data) LEN | +========================================================================================+ LEN(d) Returns the length of the variable x. The return value d depends on the type of the variable x: Type Return Value -------- ------------------------ number length of the STR(x) string length of the string array number of the elements map number of the elements Example i = 10 f = 1.234 s = "abc" dim a1(9) ' Array with 10 elements dim a2(9,9) ' Array with 10x10 elements m = {x:1, y:2, z:3} ' Map variable with 3 elements print len(i) ' Output: 2 print len(f) ' Output: 5 print len(s) ' Output: 3 print len(a1) ' Output: 10 print len(a2) ' Output: 100 print len(m) ' Output: 3 +========================================================================================+ | 36. (Data) READ | +========================================================================================+ READ var[, var ...] Assigns values in DATA items to the specified variables var1 to varN. Unless a RESTORE command is executed, SmallBASIC moves to the next DATA item with each READ assignment. If SmallBASIC runs out of DATA items to read, an run-time error occurs. See DATA and RESTORE for more information. Example 1: READ with one variable FOR c = 1 TO 6 READ x PRINT x NEXT DATA "a,b,c", 2 DATA 3, 4 DATA "fifth", 6 Example 2: READ with two variables FOR c = 1 TO 3 READ x, y PRINT x, y NEXT DATA "a,b,c", 2 DATA 3, 4 DATA "fifth", 6 +========================================================================================+ | 37. (Data) REDIM | +========================================================================================+ REDIM x Reshape the array var while preserving the contents of the array. The array will have (upper - lower) + 1 elements. If lower is not specified, and OPTION BASE 1 hasn’t been used, elements start at 0. Redim can be used to add more elements to an array, to reshape a row-vector to a column-vector or reshape to a matrix. Examples A = [1, 2, 3, 4, 5, 6, 7, 8, 9] ' Row vector (1D array) with 9 elements print A ' Output: [1,2,3,4,5,6,7,8,9] redim A(12) ' Reshape to row vector with 13 elements print A ' Output: [1,2,3,4,5,6,7,8,9,0,0,0,0] redim A(8, 0) ' Column vector with 9 elements print A ' [1;2;3;4;5;6;7;8;9] redim A(2, 2) ' Reshape to 2D-matrix with 3x3 elements print A ' Output: [1,2,3;4,5,6;7,8,9] redim A(2, 5) ' Reshape to 2D-matrix with 3x6 elements print A ' Output: [1,2,3,4,5,6;7,8,9,0,0,0;0,0,0,0,0,0] +========================================================================================+ | 38. (Data) RESTORE | +========================================================================================+ RESTORE label Specifies the position of the next data to be read. See DATA for more information. Example 1: RESTORE MyDataBlock FOR I = 1 TO 3 READ v PRINT v NEXT END DATA 1,2,3 LABEL MyDataBlock DATA 4,5,6 ' Output: 4 5 6 +========================================================================================+ | 39. (Data) SEARCH | +========================================================================================+ SEARCH A, key, BYREF ridx [USE cmpfunc] Scans an array A for the key key and returns the position idx of the element. If the key is not found idx contains the value (LBOUND(A)-1). In default-base arrays (starting with element zero) -1 will be returned. The optional compare function cmpfunc takes 2 vars var1 and var2. var1 contains the value of the actuell element and var2 is equal to key. The compare function must return 0 or 1 (false or true). When it returns 1, the search will stop and the current element position is returned in idx. Example 1: 1D array of numbers option base 1 A = [1,9,6,4,5,3,7,8,2] ' 1D array with 9 elements SEARCH A, 3, ElementID print "Element: "; ElementID ' Output: Element: 6 Example 2: 2D array of numbers option base 1 A = [1,9,6;4,5,3;7,8,2] ' 2D matrix with 3x3 elements SEARCH A, 3, ElementID print "Element: "; ElementID ' Output: Element: 6 Example 3: Get the element position of the maximum value of an 1D array option base 1 A = [1,9,6,4,5,3,7,8,2] m = max(A) SEARCH A, m, ElementID PRINT "Element: "; ElementID ' Output: Element: 2 Example 4: 1D array of strings option base 1 A = ["car", "dog", "house", "paper"] SEARCH A, "house", ElementID PRINT "Element: "; ElementID ' Output: Element: 3 Example 5: Compare function, find first element greater than the key option base 1 func findgreater(x,y) findgreater = !(x > y) end A = [1,2,3,4,5,6,7,8,9] search A, 5, ElementID USE findgreater(x,y) PRINT "Element: "; ElementID ' Output: Element: 6 Example 6: Compare function, find first element which can be divided by the key option base 1 func FindFirstDivider(x,y) FindFirstDivider = ( (x mod y) > 0 ) end A = [1,5,7,4,5,6,7,8,9] search A, 3, ElementID USE FindFirstDivider(x,y) PRINT "Element: "; ElementID ' Output: Element: 6 Example 7: Compare function, find first element with string length given by the key func FindFirstStringWithLenght(x,y) FindFirstStringWithLenght = ( len(x) != y ) end A = ["car", "dog", "house", "paper"] SEARCH A, 5, ElementID use FindFirstStringWithLenght(x,y) PRINT "Element: "; elementID ' Output: Element: 3 +========================================================================================+ | 40. (Data) SORT | +========================================================================================+ SORT array [USE cmpfunc] Sorts an array A in ascending order. The sorted array is return as A, therefore overwriting the initial array. If a compare function cmpfunc is specified, this function will be used for comparision. The compare function takes two elements of A as x, y to compare and must return: - -1 if x is to be placed before y - 1 if y is to be placed before x - 0 if it doesn’t matter which is placed first (which is usually the case when the elements are equal) Example 1: Sorting in ascending order A = [5, 3, 8, 2, 1, 7, 9] sort A print A ' Output [1,2,3,5,7,8,9] Example 2: Sorting in ascending order using a compare function func cmpfunc_ascending(x, y) if x == y return 0 elseif x > y return 1 else return -1 endif end A = [5, 3, 8, 2, 1, 7, 9] sort A use cmpfunc_ascending(x, y) print A ' Output [1,2,3,5,7,8,9] Example 3: Sorting in descending order using a compare function func cmpfunc_descending(x, y) if x == y return 0 elseif x < y return 1 else return -1 endif end A = [5, 3, 8, 2, 1, 7, 9] sort A use cmpfunc_descending(x, y) print A ' Output [9,8,7,5,3,2,1] +========================================================================================+ | 41. (Data) SWAP | +========================================================================================+ SWAP a, b Exchanges the values of the two variables a and b. a and b may be variables of any type. Example 1: Swap numbers a = 1 b = 2 print "Before: "; a, b ' Output: Before: 1 2 swap a,b print "After: "; a, b ' Output: Before: 2 1 Example 2: Swap strings s1 = "abc" s2 = "xyz" print "Before: "; s1, s2 ' Output: Before: abc xyz swap s1, s2 print "After: "; s1, s2 ' Output: After: xyz abc Example 3: Swap arrays A = [1,2,3] B = [7,8,9] print "Before: "; A, B ' Output: Before: [1,2,3] [7,8,9] swap A, B print "After: "; A, B ' Output: After: [7,8,9] [1,2,3] +========================================================================================+ | 42. (Data) UBOUND | +========================================================================================+ UBOUND (array [, dim]) Returns the upper bound ub of an array array. dim can be used to specifiy, at which dimension the upper bound should be returned if array is a multi-dimensional array. If dim is not used the upper bound of the first dimension will be returned. See LBOUND for lower bound of an array. Example 1: Upper bound of one-dimensional arrays dim A(5) dim B(5 to 10) print ubound(A) ' Output: 5 print ubound(B) ' Output: 10 Example 2: Upper bound of multi-dimensional arrays dim A(5,6,7) dim B(5 to 10, 7 to 12, 9 to 14) print ubound(A, 2) ' Output: 6 print ubound(B, 2) ' Output: 12 Example 3: Using option base 1 option base 1 dim A(5) dim B(5 to 10) print ubound(A) ' Output: 5 print ubound(B) ' Output: 10 +========================================================================================+ | 43. (Date) DATE | +========================================================================================+ DATE Returns the current date as string with format “DD/MM/YYYY”. See DATEDMY for splitting a date-string to integers. Example DateString = date datedmy DateString, d, m, y print DateString + " -> Day: " + d + " Month: " + m + " Year: " + y +========================================================================================+ | 44. (Date) DATEDMY | +========================================================================================+ DATEDMY dmy| julian_date, BYREF d, BYREF m, BYREF y Returns the day, month and the year as integers. See also DATE. DateString = date datedmy DateString, d, m, y print DateString + " -> Day: " + d + " Month: " + m + " Year: " + y +========================================================================================+ | 45. (Date) DATEFMT | +========================================================================================+ DATEFMT (format, dmy| (d,m,y)| julian_date) Returns a formatted date string. The input date can be given as a date-string returned by DATE, as the integers d for day, m for month and y for year, or as a julian date. format is a string specifying the format of the date: Format Desription -------- -------------------------- D one or two digits of Day DD 2-digit day DDD 3-char day name DDDD full day name M 1 or 2 digits of month MM 2-digit month MMM 3-char month name MMMM full month name YY 2-digit year (2K) YYYY 4-digit year See also DATE and DATEDMY. Example PRINT DATEFMT("ddd dd, mm/yy", 23, 11, 2001) ' Output: Fri 23, 11/01 PRINT DATEFMT("mm.dd.yy" , "23/11/2001") ' Output: 11.23.01 PRINT DATEFMT("dd.mm.yyyy" , DATE) ' Output: 19.10.2023 PRINT DATEFMT("dddd" , JULIAN("23/11/2001")) ' Output: Friday +========================================================================================+ | 46. (Date) JULIAN | +========================================================================================+ JULIAN (dmy| (d,m,y)) Returns the Julian date. Dates must be greater than 1/1/100 AD. The date can be passed as the string dmy with the format DD/MM/YYYY. Alternatively the date can be given by specificing the parameters d for days, m for months and y for years. Example 1: Basic usage PRINT Julian("31/12/2001") PRINT Julian(31, 12, 2001) PRINT Julian(DATE) Example 2: Difference in days between two dates today = Julian(Date()) past = Julian(31, 12, 2001) print today - past; " days past since 31/12/2001" +========================================================================================+ | 47. (Date) TICKS | +========================================================================================+ TICKS Returns the number of milliseconds that have elapsed since start of the operating system. Example 1: t = ticks() print t Example 2: Game with constant frame rate ' ticks() can be used to let your game ' run with a constant frame rate FramesPerSecond = 20 for xx = 1 to 200 StartTime = ticks() 'Put your heavy computions here cls rect 10 + xx, 10, 50+xx, 50 showpage 'Delay the execution of the for-loop StopTime = ticks() ElapsedTime = StopTime - StartTime if(ElapsedTime < 1000 / FramesPerSecond) delay(1000 / FramesPerSecond - ElapsedTime) endif next +========================================================================================+ | 48. (Date) TIME | +========================================================================================+ TIME Returns the current time as string “HH:MM:SS”. Example print time() ' Output: 16:10:17 +========================================================================================+ | 49. (Date) TIMEHMS | +========================================================================================+ TIMEHMS hms| timer, BYREF h, BYREF m, BYREF s Converts a time-value hms or timer to hours h, minutes m and seconds s integer values. Time-value can be: - a string with the format “hh:mm:ss” as returned by TIME - a number of seconds from midnight as returned by TIMER See also TIME and TIMER. Example 1: Time string returned by TIME() t = time() TIMEHMS t, h, m, s print "Hours : "; h print "Minutes: "; m print "Seconds: "; s ' Output: ' Hours : 16 ' Minutes: 15 ' Seconds: 22 Example 2: Seconds returned by TIMER() t = timer() TIMEHMS t, h, m, s print "Hours : "; h print "Minutes: "; m print "Seconds: "; s ' Output: ' Hours : 16 ' Minutes: 15 ' Seconds: 22 +========================================================================================+ | 50. (Date) TIMER | +========================================================================================+ TIMER Returns the number of seconds from midnight. Example print timer() ' Output 41595 +========================================================================================+ | 51. (Date) TIMESTAMP | +========================================================================================+ TIMESTAMP filename Returns the file filename last modified date and time as a string. The returned string s has the format “YYYY-MM-DD hh:mm AM|PM”. Example ' Create a file open "timetest.txt" for output as #1 print #1, 1 close #1 ' Get time stamp print timestamp("timetest.txt") ' Output: 2023-09-03 11:36 AM +========================================================================================+ | 52. (Date) WEEKDAY | +========================================================================================+ WEEKDAY (dmy| (d,m,y)| julian_date) Returns the day of the week as a number between 0 and 6. Sunday is 0. WEEKDAY accepts a string dmy as returned by DATE, a number julian_date as returned by JULIAN or a date given by the three numbers d for day, m for month and y for year. Example 1 PRINT WeekDay(DATE) ' Output: 3 -> Wednesday PRINT WeekDay(Julian(31, 12, 2023)) ' Output: 0 -> Sunday PRINT WeekDay(31, 12, 2023) ' Output: 0 -> Sunday Example 2 SPLIT "Sun Mon Tue Wed Thu Fri Sat", " ", wd print "Today is " + wd(WEEKDAY(DATE)) + " " + DATE ' Output: Today is Wed 13/09/2023 +========================================================================================+ | 53. (File) ACCESS | +========================================================================================+ ACCESS (file) Returns the access rights of a file. The string file follows OS file naming conventions. The returned file permission number n follows the permission pattern of the chmod() and stat() system calls. The bits of n (in octal) are: Bits Permission -------- --------------------------- 0o4000 set user ID on execution 0o2000 set group ID on execution 0o1000 sticky bit 0o400 read by owner 0o200 write by owner 0o100 execute/search by owner 0o40 read by group 0o20 write by group 0o10 execute/search by group 0o4 read by others 0o2 write by others 0o1 execute/search by others Example IF ACCESS("/bin/sh") AND 0o4 THEN PRINT "Others can read the file" ENDIF +========================================================================================+ | 54. (File) BGETC | +========================================================================================+ BGETC (fileN) Reads and returns a byte from file or device in binary mode. See BPUTC for writing bytes to a file or device. Example ' create a binary file open "BinaryFile.txt" for output as #1 for c = 0 to 255 bputc #1, c next close #1 ' open binary file and print content open "BinaryFile.txt" for input as #1 for i = 0 to 255 c = bgetc(1) print CHR(c); next close #1 +========================================================================================+ | 55. (File) BLOAD | +========================================================================================+ BLOAD filename[, address] Loads a specified memory image file into memory. +========================================================================================+ | 56. (File) BPUTC | +========================================================================================+ BPUTC# fileN; byte Writes a byte byte on file or device in binary mode. See BGETC for reading bytes from a file or device. Example ' create a binary file open "BinaryFile.txt" for output as #1 for c = 0 to 255 bputc #1, c next close #1 ' open binary file and print content open "BinaryFile.txt" for input as #1 for i = 0 to 255 c = bgetc(1) print CHR(c); next close #1 +========================================================================================+ | 57. (File) BSAVE | +========================================================================================+ BSAVE filename, address, length Copies a specified portion of memory to a specified file. +========================================================================================+ | 58. (File) CHDIR | +========================================================================================+ CHDIR dir Changes the current working directory to dir. In Windows \ needs to be replaced by \\ See CWD to get the current working directory. Example 1: Linux print cwd chdir "/usr/bin" print cwd Example 2: Windows print cwd chdir "C:\\" print cwd +========================================================================================+ | 59. (File) CHMOD | +========================================================================================+ CHMOD file, mode Change permissions of a file. The string file holds the file name and follows OS file naming conventions. mode provides the file permission and must be compatible with system call chmod()‘s ’mode’ parameter. See ACCESS to get information on file permissions. Linux mode is a number best represented in octal: 0oUGO with U: User; G: Group; O: Other U, G and O are each defined the following way: Value Permission ------- ------------- 0 no 1 x (execute) 2 w (write) 3 w + x 4 r (read) 5 r + x 6 r + w 7 r + w + x Example ' Make myfile available to anyone (read/write) CHMOD "myfile.bas", 0o666 ' Make myfile available to anyone (execute/read/write) CHMOD "myfile.bas", 0o777 ' Make myfile available to user (read/write) ' All others only read CHMOD "myfile.bas", 0o644 Windows in Windows the read-only flag can be set with mode = 1 and unset with mode = -1 Example ' Make myfile read-only CHMOD "myfile.bas", 1 ' Make myfile read and write CHMOD "myfile.bas", -1 +========================================================================================+ | 60. (File) CLOSE | +========================================================================================+ CLOSE #fileN Close a file or device with file-handle #fileN. See OPEN for more information on how to read or write files. Example ' create a text file open "MyDemoFile.txt" for output as #1 for i = 1 to 10 print #1, i next close #1 ' open text file and print content line by line open "MyDemoFile.txt" for input as #1 while(!eof(1)) ' eof works only without # input #1, c print c wend close #1 +========================================================================================+ | 61. (File) COPY | +========================================================================================+ COPY \"file\", \"newfile\" Makes a copy of file file to the file newfile. Example copy "test.txt", "test_backup.txt" +========================================================================================+ | 62. (File) DIRWALK | +========================================================================================+ DIRWALK directory [, wildcards] [USE ...] Walk through the specified directory dir and its subdirectories. The user defined function f(x) takes x as a parameter. x contains information about the current file. f(x) must return zero to stop the process. wildcards can be used to filter the files. Example 1: Print all files FUNC PRNF(x) ? x PRNF=TRUE END DIRWALK "." USE PRNF(x) Example 2: Create a list of all files FUNC ListFiles(x) FileList << x return true END DIRWALK "." USE ListFiles(x) for n in FileList print n.path, n.name next Example 3: Search for a certain file using wildcards FUNC ListFiles(x) FileList << x return true END DIRWALK ".", "scratch.bas" USE ListFiles(x) for n in FileList print n.path next Example 4: Search a certain file using user defined function func SearchFile(x) if(x.name == "scratch.bas") path = x.path return false ' file found, stop dirwalk endif return true ' file not found yet, continue dirwalk end DIRWALK "." USE SearchFile(x) print path Example 5: Using wilcards FUNC ListFiles(x) FileList << x return true END DIRWALK ".", "*.bas" USE ListFiles(x) for n in FileList print n.path, n.name next Example 6: File list utility ' Note: this demo is also a useful utility (version 2) ' -------------------- Start of Demo search --------------------- ' "." = Start search in current directory: dir = "." ' Exclude some binary files to speed up search (it's not case sensitive): exclude_ext = "jpeg jpg png gif mp3 mp4 zip 7z exe dat" ' Search this "string": word = "FUNC " ' 0 = Not case sensitive search; 1 = Case sensitive search: case_sensitive = 0 ' Search it! search_word dir, exclude_ext, word, case_sensitive ' ' Demo only for dir_list(): ' a = dir_list(dir, exclude_ext) ' For i In a Do ? i ' ? " - Length of list: "; Len(a) ' -------------------- End of Demo search --------------------- ' Purpose: return sorted array of directory files-list (including files in ' sub-directories, but not directory-names). ' Details: "dir" is the top directory to start search from (default = "."); ' "exclude_ext" is a Not case sensitive string of file-extension(s) ' to exclude from list (default = ""), For example: ' "jpeg jpg zip z7 gif wav mp3" ' Space delimited extensions. ' Example: ' a = dir_list("", "") ' a is all files in current dir (and its sub-dirs). ' a = dir_list("..", "bak zip") ' a is files in upper dir, exclude .bak .zip Func dir_list(dir, exclude_ext) Local a, ext ' Verify "dir" ("." is current directory): dir = Trim(dir): If dir = "" Then dir = "." ' ' Exclude extension in Any case (for Windows): ext = Enclose(Lcase(Squeeze(exclude_ext)), " ") ' Make the dir list (DIRWALK): Func make_list(f) Local e ' File Extension (without ".") If Isfile(f) Then ' Don't add directory-names to list e = Enclose(Lcase(Rightoflast(f, ".")), " ") If Not (e In ext) Then a << f ' Exclude extension? or append file Fi make_list = True ' (True = Continue to walk) End Func Dirwalk dir Use make_list(x) ' (Note: parameter name must be 'x') ' Sort dir list and ignore case (SORT): Func no_case(x, y) x = Lcase(x) y = Lcase(y) Select Case 1 Case x = y: no_case = 0 Case x > y: no_case = +1 Case Else : no_case = -1 End Select End Func Sort a Use no_case(x, y) dir_list = a End Func ' Purpose: search for a "word" in "dir" (and its sub-dirs), and print results. ' Details: for "dir" and "exclude_ext" details - See dir_list() function. ' "word" is the string to search for. ' 'cs' is case sensitive search - True or False. Sub search_word(dir, exclude_ext, word, cs) Local w, file, list, l, lines, p ' For Searching Local c_page, c_line ' Counters Local t_lines, t_files, old_t_lines ' Totals (for sum) Local LINES_PER_PAGE, attr = 3 LINES_PER_PAGE = 10 ' How many lines to print before pause? list = dir_list(dir, exclude_ext) ' Get the list of all files w = Iff(cs, word, Ucase(word)) ' Case sensitive search? ? Cat(0); Chr(12); Cat(attr); ' Clear console attributes and screen ' Load and search in each file: For file In list Tload file, lines c_line = 0 ' Search in each line: For l In lines c_line++ ' Keep line # for [print the line] ' Look for the word in this line: If cs Then p = Instr(l, w) Else p = Instr(Ucase(l), w) Fi ' If word found then print the line: If p Then ? Cat(2); file + " [" + c_line + "]"; Cat(-2); " "; Mid(l, p) c_page++ If c_page = LINES_PER_PAGE Then c_page = 0: Pause t_lines++ ' Keep total lines # for sum Fi Next l If t_lines > old_t_lines Then old_t_lines = t_lines attr = -attr: ? Cat(attr); ' Change color on new file t_files++ ' Keep total files # for sum Fi Next file ' Print sum: If c_page <> 0 Then Pause ? Cat(0) ' Clear all console attributes Color 15 ? "- Search in: "; Enclose(dir) ? "- Exclude file-extension(s): "; Enclose(Squeeze(exclude_ext)) ? "- Search "; Iff(cs, "IS", "is NOT"); " case sensitive." ? "- Found "; Enclose(word); & " in "; t_lines; " lines, in "; t_files; " files "; & "(out of "; Len(list); " files)." ? Color 7 ? "Done. Press Backspace key..."; While Inkey <> Chr(8): Wend End Sub +========================================================================================+ | 63. (File) EOF | +========================================================================================+ EOF (fileN) Returns true if the file pointer is at end of the file. For serial port (RS232) and TCP/IP socket connection EOF returns true if the connection is broken. For socket connection the return value ofEOF will be updated every time data is recieved or send. Example 1: Reading data from a file ' create a text file open "MyDemoFile.txt" for output as #1 for i = 1 to 10 print #1, i next close #1 ' open text file and print content line by line open "MyDemoFile.txt" for input as #1 while(!eof(1)) ' eof works only without # input #1, c print c wend close #1 Example 2: Reading from a TCP/IP socket rem Print a date string like '29 SEP 2018 09:31:49 ACST' func get_time local today = julian(date) local start = timer local t_hour, t_min, t_sec, t_str timehms start, t_hour, t_min, t_sec rem TODO, format should support multiple arguments t_str = format(" ##:", t_hour) + format("##:", t_min) + format("##", t_sec) return datefmt("dd mmm yyyy", today) + t_str end while 1 open "SOCL:8080" as #1 while (not eof(1)) lineinput #1, s if (s == "time") print #1, get_time else print #1, "unknown command" endif wend close #1 wend +========================================================================================+ | 64. (File) EXIST | +========================================================================================+ EXIST (file) Returns true if file exists. Example if(exist("test.bas")) then print "test.bas exists" endif +========================================================================================+ | 65. (File) FILES | +========================================================================================+ FILES (wildcards) Returns an array with the filenames. If there are no files, FILES returns an empty array. exp can contain the wildcards * and ?. exp can include a path. Example 1: List all files in the current directory FileNames = files("*.*") for f in FileNames print f next Example 2: List all files matching search string FileNames = files("t?st.bas") for f in FileNames print f next Example 3: Using a path FileNames = files("/usr/bin/*") ' Linux ' FileNames = files("C:\*.*") ' Windows for f in FileNames print f next +========================================================================================+ | 66. (File) FREEFILE | +========================================================================================+ FREEFILE Returns an unused file handle. Example ' create a text file f = freefile() open "MyDemoFile.txt" for output as #f for i = 1 to 10 print #f, i next close #f ' open text file and print content line by line f = freefile() open "MyDemoFile.txt" for input as #f while(!eof(f)) ' eof works only without # input #f, c print c wend close #f +========================================================================================+ | 67. (File) INPUT | +========================================================================================+ INPUT #fileN; var1 [,delim] [, var2 [,delim]] ... Reads data from file #fileN and stores the values in var1, var2 to varN. Specify a delimiter if necessary. Example: Read a comma-separated-value file (csv) ' Create a csv-file open "test.csv" for output as #1 for x = 1 to 10 print #1, x + "," + x^2 + "," + x^3 next close #1 ' Open the file and read the values open "test.csv" for input as #1 while(!eof(1)) input #1; x, ",", x2, ",", x3 print x, x2, x3 wend close #1 +========================================================================================+ | 68. (File) INPUT | +========================================================================================+ INPUT (len [, fileN]) Reads ‘len’ bytes from file or console (if fileN is omitted) and returns the result as sting s. This function does not convert the data or remove spaces. Example 1: Read from a file ' Create a file and write 10 bytes open "test.txt" for output as #1 for byte = 100 to 110 bputc #1, byte next close #1 ' Open the file open "test.txt" for input as #1 ' Read the first 5 byte A = input(5, 1) print A ' Read the second 5 byte A = input(5, 1) print A close #1 Example 2: Read from console ' Read three characters from keyboard A = input(3) print A +========================================================================================+ | 69. (File) KILL | +========================================================================================+ KILL \"file\" Deletes the file specified by FileName. Example kill "test.txt" +========================================================================================+ | 70. (File) LOCK | +========================================================================================+ LOCK Lock a record or an area (not yet implemented). +========================================================================================+ | 71. (File) LOF | +========================================================================================+ LOF (fileN) Returns the length l of a file with the file handle fileN in bytes. For other devices, returns the number of available data. Example 1: Length of a file ' create a text file open "MyDemoFile.txt" for output as #1 for i = 1 to 10 bputc #1, i next close #1 ' open text file and print content byte by byte open "MyDemoFile.txt" for input as #1 FileLength = LOF(1) ' lof works only without # for ii = 1 to FileLength c = bgetc(1) print c next close #1 Example 2: Get available data for a socket connection open "SOCL:10000" as #1 ' Open socket at port 10000 while (eof(1)) ' Loop until connection is closed l = lof(1) ' Querry how much data is in the queue if(l) then ' if data is available s = INPUT(l, #1) ' get all data print s endif wend close #1 +========================================================================================+ | 72. (File) MKDIR | +========================================================================================+ MKDIR dir Creates the directory dir. dir is a string representing a valid directory name. dir can additionally contain a path. Without a path, the directory will be created in the current working directory. Errors can be catched using TRY … CATCH. Example 1 mkdir "test" mkdir "C:\\test" ' In Windows use \\ instead of \ Example 2: Use TRY … CATCH ' Run this program two times to get the error messege "FILE EXISTS" try mkdir "test" catch err print err end try +========================================================================================+ | 73. (File) OPEN | +========================================================================================+ OPEN file [FOR {INPUT|OUTPUT|APPEND}] AS #fileN Makes a file, device or network connection available for sequential input, sequential output. - file - A string expression that follows OS file naming conventions. - fileN - A file-handle (integer 1 to 256). Open a file open "test.txt" for INPUT as #1 Expression Description ------------ --------------------------------------------- INPUT Sequential input (reading from file) OUTPUT Sequential output ( writing to file) APPEND Sequential output, beginning at current EOF If an existing file is opened for output, the file will be deleted and an empty file will be created. The files are always opened as shared. You can use FREEFILE to get the next unused file-handle. Use PRINT, INPUT, BGETC and BPUTC to read from or write to a file or device. Open a COM port (RS232) You can open a connection to a device using the serial port with open "COMn:speed" AS #1, where n is the number of the port and speed is the baud rate. To open the first serial port with a baud rate of 19200 use: open "COM1:19200" as #1. In Windows COM1 and in Linux /dev/ttys1 would be opened. Open a TCP/IP socket You can open a connection to a device using a TCP/IP socket with open "SOCL:IP:PORT" AS #1, where IP is a valid host name or IP address and port is an open port. open "SOCL:192.168.178.76:8080" as #1 If you omit the host name or IP address in the SOCL: string passed to the OPEN command, SmallBASIC will listen for connections from another host/process. open "SOCL:8080" as #1 Open an image Use the prefix HTTP: with the OPEN command to open an image file over the network. You can then pass the file number to the IMAGE command. This returns an system object which can then be used to manipulate images in the graphical version of SmallBASIC. open "http://img2.wikia.nocookie.net/__cb20150113215904/farmville/images/9/92/Lumberjack_Gnome-icon.png" as #1 Open a HTTP connection Use the prefix HTTP: with the OPEN command to open a network HTTP connection. You can then use the file number with the TLOAD command to read the data. open "http://api.duckduckgo.com/?q=Cars&format=json" as #1 Example 1: Open a file: ' create a text file open "MyDemoFile.txt" for output as #1 for i = 1 to 10 print #1, i next close #1 ' open text file and print content line by line open "MyDemoFile.txt" for input as #1 while(!eof(1)) ' eof works only without # input #1, c print c wend close #1 Example 2: Open a socket for listening (server) open "SOCL:10000" as #1 ' Open socket at port 10000 while (!eof(1)) ' Loop until connection is closed l = lof(1) ' Querry how much data is in the queue if(l) then ' if data is available s = INPUT(l, 1) ' get all data print s endif wend close #1 Example 3: Open a socket as client open "SOCL:192.168.1.10:10000" as #1 ' Connect to server print #1, "Hello world" ' Send string to server close #1 Example 4: Open a COM port (RS232) open "COM1:19200" as #1 ' Open COM1 with 19200 bauds while (!eof(1)) ' Loop until connection is closed l = lof(1) ' Querry how much data is in the queue if(l) then ' if data is available s = INPUT(l, 1) ' get all data print s endif wend close #1 Example 5: Open an image over network ' open some random image I found on the net open "http://img2.wikia.nocookie.net/__cb20150113215904/farmville/images/9/92/Lumberjack_Gnome-icon.png" as #1 i = image(#1) i.show(100,50) Example 6: Connect to an HTTP server print "DuckDuckGo Search" while 1 print '<=== when cycle around need to isolate input prompt input "(Just enter quits) Term? ", queryTerm if trim(queryTerm)="" then ? "Cheers!":end '<=== need a way out url = "http://api.duckduckgo.com/?q=" + trim(queryTerm) + "&format=json" open url as #1 if (eof(1)) then throw "Connection failed: " + url fi dim results tload #1, results json = array(results) num_results = len(json.RelatedTopics) for i = 0 to num_results - 1 if (isarray(json.RelatedTopics(i).topics)) then num_topics = len(json.RelatedTopics(i).Topics) for t = 0 to num_topics - 1 print cat(1); " "; json.RelatedTopics(i).Topics(t).FirstURL; cat(0) print " "; json.RelatedTopics(i).Topics(t).text next t else print cat(1); " "; json.RelatedTopics(i).FirstURL; cat(0) print " "; json.RelatedTopics(i).Text endif next i Close #1 '<===== oh this helps! wend +========================================================================================+ | 74. (File) READ | +========================================================================================+ READ #fileN; var1 [, ...] Read variables var1 to varN from a binary data file. Variables can be numbers, strings and arrays. See WRITE for writing variables to a file. Example a = 12.3 b = "test" c = [1,2,3,4] ' Write variables to file open "text.bin" for output as #1 write #1, a, b, c close #1 ' Read variables from file open "text.bin" for input as #1 read #1, a, b, c close #1 print a print b print c +========================================================================================+ | 75. (File) RENAME | +========================================================================================+ RENAME \"file\", \"newname\" Renames the specified file file to newfile. Example: ' Create a file A = 1 tsave "test.txt", A ' Rename file rename "test.txt", "test_renamed.txt" +========================================================================================+ | 76. (File) RMDIR | +========================================================================================+ RMDIR dir Removes directory dir. Example mkdir "testdirectory" ' Create directory rmdir "testdirectory" ' Delete directory +========================================================================================+ | 77. (File) SEEK | +========================================================================================+ SEEK #fileN; pos Sets file position to pos for the next read/write for file with the ID #fileN. The file position starts with 0. Example ' create a file open "testseek.txt" for output as #1 print #1, "abcdefghijk" close #1 ' open file open "testseek.txt" for input as #1 seek #1, 4 ' file position set to 4 c = input(1,1) ' read one character from file print c ' Output: e close #1 +========================================================================================+ | 78. (File) SEEK | +========================================================================================+ SEEK (fileN) Returns the current file position of file with ID fileN. The file position start with 0. Example ' create a file open "testseek.txt" for output as #1 print #1, "abcdefghijk" close #1 ' open file open "testseek.txt" for input as #1 c = input(3,1) ' read three character from file print seek(1) ' Output: 3 close #1 +========================================================================================+ | 79. (File) TLOAD | +========================================================================================+ TLOAD file, BYREF var [, type] Loads a text file file into the array variable var. Each text-line is an array element. The optional variable type defines the type of var: - 0: load into array (default) - 1: load into string Example 1 ' Create an array with some data A << 1 A << "test" A << 2 print A ' Output: [1,test,2] ' Save the array. This will create the file myfile.txt in ' the same directory as your BASIC file tsave "myfile.txt", A ' Load the file tload "myfile.txt", B print B ' Output: [1,test,2,] Example 2: Reading json data ' Create an array with some json data A << {name: "Ben", age: 20} A << {name: "Alice", age: 22} ' Save the array. This will create the file myfile.txt in ' the same directory as your BASIC file tsave "myfile.txt", A ' Load the file tload "myfile.txt", B ' Convert B to map variable for element in B M << array(element) next print M print M[1].age ' Output: ' [{"age":20,"name":"Ben"},{"age":22,"name":"Alice"},0] ' 22 Example 3: Read as string ' Create an array with some data A << 1 A << "test" A << 2 print A ' Output: [1,test,2] ' Save the array. This will create the file myfile.txt in ' the same directory as your BASIC file tsave "myfile.txt", A ' Load the file tload "myfile.txt", B, 1 print "->"; B ; "<-" ' Output: ->1 ' test ' 2 ' <- +========================================================================================+ | 80. (File) TSAVE | +========================================================================================+ TSAVE file, var Writes the array or string var to the text file file. Each array element is a text-line in the file. Every line of the string will be one line in the text file. Use \n in the string to separate lines. See TLOAD for loading data from a text-file. Example 1: Save an array ' Create an array with some data A << 1 A << "test" A << 2 print A ' Output: [1,test,2] ' Save the array. This will create the file myfile.txt in ' the same directory as your BASIC file tsave "myfile.txt", A ' Load the file tload "myfile.txt", B print B ' Output: [1,test,2,] Example 2: Save a string ' Create a string with some data A = "line 1\nline 2\nline 3" print A ' Output: line 1 ' line 2 ' line 3 ' Save the string. This will create the file myfile.txt in ' the same directory as your BASIC file tsave "myfile.txt", A ' Load the file tload "myfile.txt", B print B ' Output: [line 1,line 2,line 3] +========================================================================================+ | 81. (File) WRITE | +========================================================================================+ WRITE #fileN; var1 [, ...] Store variables var1 to varN to a file as binary data. Variables can be numbers, strings and arrays. See READ for reading variables from a file. Example a = 12.3 b = "test" c = [1,2,3,4] ' Write variables to file open "text.bin" for output as #1 write #1, a, b, c close #1 ' Read variables from file open "text.bin" for input as #1 read #1, a, b, c close #1 print a print b print c +========================================================================================+ | 82. (Graphics) ARC | +========================================================================================+ ARC [STEP] x,y,r,astart,aend [,aspect [,color]] [COLOR color] Draws an arc: - [x, y]: center point - r: radius in pixel - astart, aend: first anf last angle in radians - aspect: aspect ratio - color: line color If STEP is used x and y are a step from the last position of the graphics cursor. Example 1 x = 100 y = 100 r = 50 astart = 0 aend = rad(90) ARC x, y, r, astart, aend Example 2: Using STEP x = 50 y = 50 r = 50 astart = 0 aend = rad(90) pset(100,100) ' Draw point at 100,100 and set the graphics cursor to 100,100 ARC STEP x, y, r, astart, aend ' make a step from 100,100 by 50 pixels in x and 50 pixels in y +========================================================================================+ | 83. (Graphics) CHART | +========================================================================================+ CHART LINECHART|BARCHART, array() [, style [, x1, y1, x2, y2]] Draws a chart of array values in the rectangular area given by the points [x1, y1] and [x2, y2]. The array A stores y-values only: [y1, y2, y3, … yn]. The x-axis of the chart has the values 1,2,3,…n. charttype is a number with the following values: Charttype Value ----------- ------- Linechart 1 Barchart 2 style is a number with the following values: Style Value ---------------------- ------- simple 0 with marks 1 with ruler 2 with marks and ruler 3 See PLOT for plotting functions. Example 1: Linechart with marks and ruler demo = [1.5,2,3.5,4,5,6.5,7,8,9.5,10,11,12.5] Color 0, 15 cls Chart 1, demo, 3, 150, 150, 750, 550 Example 2: All charttypes and styles in one glance Const LINE_CHART = 1 Const BAR_CHART = 2 demo = [1.5,2,3.5,4,5,6.5,7,8,9.5,10,11,12.5] Color 0, 15 For type = LINE_CHART To BAR_CHART ' 1 to 2 text = Iff(type = LINE_CHART, "LINE_CHART", "BAR_CHART") For style = 0 To 3 Cls Print " Chart Type: "; type; " ("; text; ")" Print " Chart Style: "; style Print Print "Press any key..."; Chart type, demo, style, 150, 150, 750, 550 Pause Next style Next type +========================================================================================+ | 84. (Graphics) CIRCLE | +========================================================================================+ CIRCLE [STEP] x,y,r [,aspect [, color]] [COLOR color] [FILLED] Draws a circle (or an ellipse if the aspect is specified). The point [x, y] defines the center and r the radius of the circle in pixel. To set the aspect ration use aspect. An aspect ratio of 1 will draw a circle. color defines the line color of the circle. If FILLED is used, the circle will be filled with the color color. If STEP is used x, y are a step in pixel from the actual graphics cursor position. By default CIRCLE draws with anti-aliasing. For details, see: Fast, Antialiased Circles and Ellipses To turn off anti-aliasing use option predef antialias off Example 1: Draw a filled white circle circle 200, 200, 150 COLOR 15 FILLED Example 2: Draw a ellipse with aspect ration 1:2 circle 200, 200, 150, 0.5 Example 3: Draw a flower ' Aspect ratio is relation between width-height of a circle, ' for example: ' aspect = 1 = Perfect circle; ' aspect = 1.5 = Stretch circle vertically (ellipse); ' aspect = 0.5 = Stretch circle horizontally (ellipse); ' let's draw perfect circles for the flower: Const ASPECT_RATIO = 1 ' define parameters for main circle: Const CENTER = [150, 150] ' [x, y] define the center point to draw a circle Const RADIUS = 50 ' radius in pixels (pixel is a single point) Const TEXT = "Smile!" ' text to print in the middle of main circle ' define parameters for leafs: Const LEAF_RADIUS = 30 ' using smaller circles for leafs ' center point for straight leafs (distance from main circle's center): Const LEAF_CENTER_STRAIGHT = RADIUS + LEAF_RADIUS ' rotate center point for transverse leafs (distance as above): Const LEAF_CENTER_TRANSVERSE = LEAF_CENTER_STRAIGHT * Sin(Rad(45)) ' Start the program: Print " Press any key to draw leaf by leaf..."; Pause Cls ' draw one invisible point to set the 'current position': Pset CENTER Color 0 ' let's use shorter variable names (easier to read): a = ASPECT_RATIO r = LEAF_RADIUS ' draw the straight leafs (relative to the 'current position'): c = LEAF_CENTER_STRAIGHT Circle Step 0, -c, r, a Color 15 FILLED: Pause ' top Circle Step 0, +c, r, a Color 14 FILLED: Pause ' down Circle Step -c, 0, r, a Color 13 FILLED: Pause ' left Circle Step +c, 0, r, a Color 12 FILLED: Pause ' right ' draw the transverse leafs (relative to the 'current position'): c = LEAF_CENTER_TRANSVERSE Circle Step -c, -c, r, a Color 11 FILLED: Pause ' top-left Circle Step +c, +c, r, a Color 8 FILLED: Pause ' down-right Circle Step +c, -c, r, a Color 10 FILLED: Pause ' top-right Circle Step -c, +c, r, a Color 9 FILLED: Pause ' down-left ' draw the main circle: Circle CENTER, RADIUS, ASPECT_RATIO Color 14 ' print text in the middle of main circle: At CENTER(0) - (Txtw(TEXT) \ 2), CENTER(1) - (Txth(TEXT) \ 2) Color 15: Print TEXT; Example 4: Smiley Face ' SmallBASIC 0.12.2 [B+=MGA] 2016-03-16 ' Smiley Face cx = xmax/2 cy = ymax/2 rface = 250 reye = 50 xle = cx - 100 xre = cx + 100 dir = 1 while 1 cls circle cx, cy, rface, 1, 14 filled circle xle, cy, reye, 1 - a, 9 filled circle xre, cy, reye, 1 - a, 9 filled circle cx, cy + 130 - a * 50, 100 + a * 50, .21 + 2 * a, 12 filled circle cx, cy + 100 - a * 50, 100 + a * 50, .21 + a, 14 filled showpage delay 1 a+= .002 * dir if a = .26 then dir = dir * -1 if a = -.1 then dir = dir *-1 wend Example 5: Turn off anti-aliasing option predef antialias off +========================================================================================+ | 85. (Graphics) COLOR | +========================================================================================+ COLOR foreground-color [, background-color] Specifies the foreground color foreground-color and the optional background color background-color. See RGB and RGBF to create colors. Example 1 color 14, 1 print "Yellow text on blue background" Example 2: Assigning SmallBASIC standard colors to text For back = 0 To 7 Do text = back Xor 15 ' count down text color (15 to 8) Color text, back Print Using " FG and BG COLOR: ##, ## "; text, back; Color back, text ' reverse colors Print Using " FG and BG COLOR: ##, ## "; back, text Next Example 3: Assigning RGB-colors to text Print "Try color printing with some RGB shades" Print For shade = 0 To 10 text = rgb(shade * 25, 0, 0) back = rgb(255 - shade * 25, 255 - shade * 25, 255 - shade * 25) Color text, back Print "Here is black to red on white to black "; shade * 25; ","; 255 - 25 * shade Color back, text ' reverse colors Print "Here is reverse white to black on black to red." print Next Example 4: Using RGB and RGBF to draw a magenta filled rectangle with white boarder color rgb(255, 67, 133) rect 10, 10, 100, 100 filled ' filling always with foreground color color rgbf(1, 1, 1) rect 10, 10, 100, 100 Example 5: Chart of the 16 SmallBASIC standard colors and their numbers ' Color chart of the 16 SmallBASIC standard colors ' for 0 = black to 15 = bright white dy = ymax / 16 for i = 0 to 15 rect 0, i * dy, xmax, i * dy + dy, i filled at 0, i * dy : print i; next Example 6 You may include “color_const.bas” file in another file to make your code more clear. ' demo - add these lines to another BAS file: ' ------------------------------------------ ' Include "color_const.bas" ' actuall filename must be lower case for Linux. ' ' Circle 200, 200, 50, 1, YELLOW FILLED ' Color BRIGHT_MAGENTA, BLUE: ? "Bright Magenta on Blue" ' ------------------------------------------ ' color_const.bas - COLOR values for characters and pixels: Const BLACK = 0 Const BLUE = 1 Const GREEN = 2 Const CYAN = 3 Const RED = 4 Const MAGENTA = 5 Const BROWN = 6 Const WHITE = 7 Const GRAY = 8 Const BRIGHT_BLUE = 9 Const BRIGHT_GREEN = 10 Const BRIGHT_CYAN = 11 Const BRIGHT_RED = 12 Const BRIGHT_MAGENTA = 13 Const YELLOW = 14 Const BRIGHT_WHITE = 15 +========================================================================================+ | 86. (Graphics) DRAW | +========================================================================================+ DRAW \"commands\" Draw lines as specified by the given CommandString. The CommandString is created using commands from the Graphics Definition Language. The start point for drawing can be defined using the PSET command. COLOR can be used to change the color of the lines. Graphics Definition Language In the movement instructions below, n specifies a distance to move in pixel. ----------------------------------------------------------------------- Command Description ----------------------------------- ----------------------------------- Un Move up. Dn Move down. Ln Move left. Rn Move right. En Move diagonally up and right. Fn Move diagonally down and right. Gn Move diagonally down and left. Hn Move diagonally up and left. Mxy Move to coordinate x,y. If x is preceded by a + or -, the movement is relative to the last point referenced. B A prefix command. Next movement command moves but doesn’t plot. N A prefix command. Next movement command moves, but returns immediately to previous point. ----------------------------------------------------------------------- Example 1: Let’s draw a house COLOR 9 PSET 80,80 DRAW "R50D70L25U25L15D25NR15" ' House part 1 DRAW "L10U70E25F25" ' House part 2 PSET 118,105 COLOR 3 DRAW "R8U16L16D16R8U10NR8U6" ' Window +========================================================================================+ | 87. (Graphics) DRAWPOLY | +========================================================================================+ DRAWPOLY array [,x-origin,y-origin [, scalef [, color]]] [COLOR color] [FILLED] [FILLED] Draws a polyline. The array contains all the vertices of the polyline and can be defined as follow: - [[x1,y1], [x2,y2], … ,[xn,yn]] - [x1,y1, x2,y2, … , xn,yn] Scaling factor scalef is applied after moving to the x- and y-origin. Example 1: Polygon array with points P = [[0,50], [50,0], [100,50], [0,50]] drawpoly P ' Draw poly drawpoly P, 200,200 ' Draw poly with offset drawpoly P, 200,200, 1.5 COLOR 4 ' Draw poly with offset, scaling and color Example 2: Polygon array without points P = [0,50, 50,0, 100,50, 0,50] ' Even elements -> x ' Uneven elements -> y drawpoly P ' Draw poly drawpoly P, 200,200 ' Draw poly with offset drawpoly P, 200,200, 1.5 COLOR 4 ' Draw poly with offset, scaling and color +========================================================================================+ | 88. (Graphics) IMAGE | +========================================================================================+ IMAGE [#handle | fileName | http://path-to-file.png | image-var | array of pixmap data] array of pixmap data] The IMAGE statement provides access to extended support for image manipulation. There are two supported image formats: PNG and XPM (see below). Image access Create via open file handle Open "circle.png" For Output As #1 i = Image(#1) Create via file name i = Image("circle.png") Create via URL (note only works with HTTP not HTTPS) i = Image("http://pngimg.com/uploads/tesla_car/tesla_car_PNG26.png") Create via screen scrape (x, y, width, height) i = Image(10, 10, 100, 100) Create via another image variable k = Image(...) i = Image(k) Create via 2D array 'Create image array a1 without transparency dim a1(100, 200) For y = 0 To 99 For x = 0 To 199 r += 5: g += 10: b += 15 a1(y, x) = rgb(r%255, g%255,b%255) Next Next 'Create image array a2 with transparency 'Transparency is a value between 0 and 255 '0 is fully transparent; 255 is solid dim a2(100, 200) r = 255: g = 255: b = 255 For y = 0 To 99 alpha = 5 For x = 0 To 199 alpha += 0.1 transparency = round(alpha) * 10 a2(y, x) = (transparency lshift 24) - rgb(r,g,b) Next Next 'Create and display images i1 = Image(a1) i2 = Image(a2) i1.show(20,20) i2.show(0,0) Create via array of X_PixMap data im << "16 18 4 1" im << "@ c #547B43" im << " c #ffffff" im << "+ c none" im << "x c #ff0000" im << "@@@@@@@+++++++++" im << "@ @++++++++++" im << "@ @+++++++++++" im << "@ @++@++++++++" im << "@ @@+++++++++" im << "@ @+++@+++++" im << "@ @++@@++++@" im << "@ xxx @@ @++@@" im << "@ xxx xx@@ @" im << "@ xxx xxx @" im << "@ xxxxxx @" im << "@ xxxx @" im << "@ xxxxxx @" im << "@ xxx xxx @" im << "@ xxx xxx @" im << "@ xxx xxx @" im << "@ @" im << "@@@@@@@@@@@@@@@@" i = Image(im) Show command zIndex controls whether the image will be displayed over or under another image. Images with higher zIndex values are drawn over the top of images with lower zIndex values. Opacity controls whether to display the image as solid or semi-transparent. Opacity values range from 1-100, with higher opacity values making the image less transparent. The default is 100 resulting in a solid image. When calling the show command a second time with new coordinates, the image will move to the new position. i.show([x,y [,zindex [,opacity]]]) Hide command The hide command hides the image from display i.hide() Draw command The draw command draws the image immediately to the screen. Calling the draw command a second time with new coordinates, will draw the same image a second time at the new position to the screen. i.draw([x,y [,opacity]]) Save command The save command saves the image data into the given file handle, file name or array dim png i.save(png) Clip command Clips the image. Next draw or show command will display only this part of the image. On the same image a new clip can be set. i.clip(left, top, width, height) Filter command (console version only) Calls the supplied callback function on each pixel func colorToAlpha(x) return x end png.filter(use colorToAlpha(x)) Paste command (console version only) Paste the given image into this image at the given x, y location png2 = Image(w, h) png2.paste(png1, x, y) Example 1 Const CSI_EL = Chr(27) + "[K" ' EL - Erase in Line (clear to end of line). Sub title(txt) Locate 0, 0: Color 7, 0: ? CSI_EL; txt; End Sub ' Draw a demo image with text on screen: title("Draw a demo image") Pset 100, 100 Circle Step 0, 0, 50 Color 7 Filled Circle Step 0, 0, 35 Color 1 Filled text = "Hello" At Point(0) - Txtw(text) \ 2, Point(1) - (Txth(".") \ 2) Color 14, 1: Print text; Pause title("Create image from screen") i = Image(50, 50, 102, 102) ' Create image from screen (x, y, width, height) i.Show(350, 50) ' Show the image at location (x, y) Pause title("Hide the image") i.Hide() ' Hide the image Pause title("Save the image to 2-D array (y, x) of pixels") i.Save(a) ' Save the image to 2-D array (y, x) of pixels i2 = Image(a) ' Create a new image from the 2-D array i2.Show(200, 90) ' Show the new image at location (x, y) Pause title("Modify the colors of the 2-D array (y, x)") For y = 0 To Ubound(a, 1) ' Modify the colors of the 2-D array (y, x) For x = 0 To Ubound(a, 2) a(y, x) += 100 Next Next i2 = Image(a) ' Create a new image from the modified 2-D array i2.Show(350, 50) ' Show the new image at location (x, y) Pause title("Copy the top-left of the 2-D array (y, x)") half_y = Ubound(a, 1) / 2 ' Copy the top-left of the 2-D array (y, x) half_x = Ubound(a, 2) / 2 Dim a2(half_y, half_x) For y = 0 To half_y For x = 0 To half_x a2(y, x) = a(y, x) Next Next i2 = Image(a2) ' Create a new image from the top-left 2-D array i2.Show(200, 90) ' Show the new image at location (x, y) Pause ' Note: 'zindex' is probably order of layers - above/under other image(s). title("Show original image using zindex & opacity") i.Show(400, 100, 1, 50) ' Show original image (x, y, zindex, opacity) Pause i3 = Image(i) ' Create a new image from original image i3.Show(440, 130, 0) ' Show the new image (x, y, zindex) Pause ' Note: file name is case sensitive on Linux. title("Save & Load original image as a PNG file") Open "circle.png" For Output As #1 i.Save(#1) ' Save original image as a PNG file Close #1 Open "circle.png" For Input As #1 i4 = Image(#1) ' Load image from a PNG file Close #1 i4.Show(600, 20) ' Show loaded image (x, y) Pause Example 2 ' Notes: ' 1. Using POINT and PSET is a much slower option then using: ' i = IMAGE(x, y, width, height) and i.Show(x, y) - (See Part-1). ' ' 2. The 2-D array that holds the image, a(y, x), must be equilateral, e.g. ' a(2 To 6, 1 To 5), etc; Using a(1 To 5, 1 To 6), for example, is wrong. ' ' 3. It's possible to use POINT or RGB commands (alpha is not supported ' in this case) to create the 2-D array that holds the image, a(y, x). Const CSI_EL = Chr(27) + "[K" ' EL - Erase in Line (clear to end of line). Sub title(txt) Locate 0, 0: Color 7, 0: ? CSI_EL; txt; End Sub ' Draw a demo image with text on screen: title("Draw a demo image") Pset 100, 100 Circle Step 0, 0, 50 Color 7 Filled Circle Step 0, 0, 35 Color 1 Filled text = "Hello" At Point(0) - Txtw(text) \ 2, Point(1) - (Txth(".") \ 2) Color 14, 1: Print text; Pause title("Create 2-D image array from screen using POINT") Dim a(49 To 152, 48 To 151) ' Create 2-D image array from screen using POINT For y = 49 To 152 For x = 48 To 151 a(y, x) = Point(x, y) Next Next Pause title("Show the 2-D array (slow) using PSET") For y = 49 To 152 ' Show the 2-D array (slow) using PSET For x = 48 To 151 Pset x + 150, y + 85, a(y, x) Next Next Pause title("Show the image (fast) using SHOW") i = Image(a) ' Convert the 2-D array (y, x) of pixels to image i.Show(350, 230) ' Show the image (fast) at location (x, y) Pause Example 3 ' Notes: ' 1. You may load an existing XPM image file, the same way you load PNG image ' file; Or you may store the XPM data within the source code (DATA keyword ' can help with this...). ' ' 2. XPM is a text image file, as opposed to PNG which is a binary image file. ' XPM supports high quality images, for more details and options see: ' https://en.wikipedia.org/wiki/X_PixMap ' In this example we use the simple and handy XPM2 format (as opposed to the ' latter and more standard C format, XPM3); ' Create the XPM image array: ' a << "! XPM2" ' (We Don't use this header line in SmallBASIC 0.12.6) a << "110 200 3 1" ' Width=110, Height=200, Colors=3, Character-Per-Pixel=1 a << "a c #FF0000" ' Character "a" is RGB(0xFF, 0x00, 0x00) - RED a << "b c NONE" ' Character "b" is transparency color (NONE) a << "c c #0000FF" ' Character "c" is RGB(0x00, 0x00, 0xFF) - BLUE For i = 1 To 200 ' Create an image of exactly 110x200 (x,y) pixels a << String(30, "a") + String(50, "b") + String(30, "c") Next i Color 1, 7: Cls i = Image(a) ' Convert the XPM array to image i.Show(150, 50) ' Show the image at location (x, y) At 150 - 100, 50 - 30 Print "This is XPM image with transparency!" Pause ' More about XPM2 - from https://en.wikipedia.org/wiki/X_PixMap: ' -------------------------------------------------------------- ' XPM2 simplifies the format by removing all C codes. An example: ' ! XPM2 ' 48 4 2 1 ' a c #FFFFFF ' b c #000000 ' abaabaababaaabaabababaabaabaababaabaaababaabaaab ' abaabaababaaabaabababaabaabaababaabaaababaabaaab ' abaabaababaaabaabababaabaabaababaabaaababaabaaab ' abaabaababaaabaabababaabaabaababaabaaababaabaaab ' This is an XPM2 file with width 48, height 4, 2 colors, and 1 character per ' pixel. ' One tool is known to use only a to p for 16 colors, switching to aa up to dp ' for 64 colors, but still reading single character encodings for 64 colors; ' compare Base64. ' ' With more colors the codes use more characters, e.g. aa up to pp for ' 16 x 16 = 256 colors. This is less useful for text editors, because a string ' ab could be actually the middle of two adjacent pixels dabc. ' Spaces are allowed as color code, but might be a bad idea depending on the ' used text editor. ' Without control codes, space, and quote (needed in XPM1 and XPM3) ' 128 - 33 - 2 = 93 ASCII characters are available for single character color ' codes. ' ' Simplified example: 90 US-ASCII characters could be arranged into nine ' non-overlapping sets of 10 characters. Thus unambiguous strings of nine ' characters could set the color of each pixel by its XPM palette index with ' up to 109 = 1000000000 colors (compare to GIF, which supports only 256). ' For XPM2 it is clear how many lines belong to the image - two header lines, ' the second header line announcing the number of color codes (2 lines in the ' example above) and rows (height 4 in the example above), ' e.g. 2 + 2 + 4 = 8 lines. Example 4 Color 7, 1: Cls ' (for recognizing transparency color) ' --- [1] Restore Demo_XPM_Image ' Create a demo XPM image array For i = 1 To 12 Read s a << s Next i i = Image(a) ' Convert the XPM array to image i.Show(10, 10) ' [1] Show the image at location (x, y) Open "SB.png" For Output As #1 i.Save(#1) ' Save XPM image as a PNG file Close #1 ' --- [2] i = Image("SB.png") ' Load image from PNG file, using a "file name" i.Show(30, 30) ' [2] Show loaded image (x, y) ' --- [3] Open "SB.png" For Input As #1 i = Image(#1) ' Load image from PNG file, using a file number Close #1 i.Show(50, 50) ' [3] Show loaded image (x, y) ' --- [4] Open "SB.png" For Input As #1 ' Load image from PNG file into 1-D array of l = Lof(1) ' PNG byte data (integers) Dim a(1 To l) ' (It's much faster to allocate space first) For i = 1 To l Do a(i) = Bgetc(1) Close #1 i = Image(a) ' Create an image from the 1-D array i.Show(80, 80) ' [4] Show loaded image (x, y) ' --- [5] Import Base64 ' (See Base64 Encoder/Decoder UNIT above, or ' in: Home -- Code library -- Units section) Restore Base64_encoded_PNG ' Load image from Base64 encoded PNG data s = "" ' into 1-D array of PNG byte data (integers) For i = 1 To 3 Read d s += d Next i a = base64.Decode_Base64(s) ' Decode Base64 PNG string to 1-D array i = Image(a) ' Create an image from the 1-D array i.Show(100, 100) ' [5] Show loaded image (x, y) ' --- [6] Restore Demo_XPM_Image ' Save XPM image array as XPM file Dim a(1 To 12) For i = 1 To 12 Do Read a(i) Tsave "SB.xpm", a Tload "SB.xpm", a2 ' Load image from XPM file into array of strings i = Image(a2) ' Convert the XPM array to image i.Show(120, 120) ' [6] Show loaded image (x, y) ' --- [7] Open "http://smallbasic.sourceforge.net/images/logo.png" For Input As #1 i = Image(#1) ' Load PNG image from web (you must be on-line) Close #1 i.Show(150, 150) ' [7] Show loaded image (x, y) Pause End ' Note: you may use the Base64 Encoder/Decoder UNIT above to convert PNG file ' into Base64 encoded string (large file takes time to convert!). ' It allows you to store the PNG file within the source code. Label Base64_encoded_PNG ' (With transparency color) Data "iVBORw0KGgoAAAANSUhEUgAAABUAAAAJAQAAAAD1eFrbAAAAAnRSTlMAAHaTzTgAAAA" Data "oSURBVHgBHcdBAQAwDMJA6qI/LLSOkDU5kzZYXhck8mKPMK3vsvOxe3i6Bu6pAW2gAA" Data "AAAElFTkSuQmCC" Label Demo_XPM_Image Data "21 9 2 1" ' Width=21, Height=9, Colors=2, Character-Per-Pixel=1 Data ". c NONE" ' Character "." is transparency color (known as "NONE") Data "o c #FFFFFF" ' Character "o" is RGB(0xFF, 0xFF, 0xFF) - WHITE Data "....................." Data "...ooooo...ooooooo..." Data "..oo...oo..oo....oo.." Data "..oo.......oo....oo.." Data "...ooooo...ooooooo..." Data ".......oo..oo....oo.." Data "..oo...oo..oo....oo.." Data "...ooooo...ooooooo..." Data "....................." Example 5 ' Dedicated to johnno56 Const CSI_EL = Chr(27) + "[K" ' EL - Erase in Line (clear to end of line). Sub title(txt) Locate 0, 0: Color 7, 0: ? CSI_EL; txt; End Sub ' Draw a demo image with text on screen: title("Draw a demo image") Pset 100, 100 Circle Step 0, 0, 50 Color 7 Filled Circle Step 0, 0, 35 Color 1 Filled text = "Hello" At Point(0) - Txtw(text) \ 2, Point(1) - (Txth(".") \ 2) Color 14, 1: Print text; Pause i = Image(50, 50, 102, 102) ' Create image from screen (x, y, width, height) Color 7, 0: Cls ' Erase the demo image. ' Note: ' 1. zIndex parameter is used for the IMAGE sub-command SHOW, its syntax is: ' SHOW([x,y [,zindex [,opacity]]]) ' ' 2. 'zindex' is the order of layers, i.e. under or above other image layers. ' I'm not aware of any limits for how many image layers can be used. ' ' 3. Using 'zindex' is simple, for example: layer 0 is above layer -1; ' layer -8 is below layer -7; layer 11 is above layer 10; etc. ' In this example we show 9 images on different layers: Dim i2(1 To 9) For layer = 1 To 9 i2(layer) = Image(i) ' Copy the demo image to new image t = i2(layer) ' Use temporay variable to hold image (for Show) ' Change the 'x' and 'y' properties of t image: t.x = 50 + layer * 35 t.y = 50 + layer * 25 At t.x + 100, t.y: Color 7, 0 ' (for display text info) ' Change the 'zIndex' property of t image: Select Case layer Case 1: t.zIndex = 0 : ? " Using layer # 0" Case 2: t.zIndex = -2 : ? " Using layer # -2 (below layer -1)"; Case 3: t.zIndex = -1 : ? " Using layer # -1 (below layer 0)"; Case 4: t.zIndex = 3 : ? " Using layer # 3 (above layer 2)"; Case 5: t.zIndex = 2 : ? " Using layer # 2 (above layer 1)"; Case 6: t.zIndex = -9 : ? " Using layer # -9 (below layer -8)"; Case 7: t.zIndex = -7 : ? " Using layer # -7 (below layer -6)"; Case 8: t.zIndex = -3 : ? " Using layer # -3 (below layer -2)"; Case 9: t.zIndex = 4 : ? " Using layer # 4 (above layer 3)"; End Select title("IMAGE # " + layer + ": " + Str(t)) ' Print image properties t.Show() ' Show image (x, y, zindex) Pause Next layer Base64 decoder for example 4 REM Purpose: A Base64 Encoder/Decoder UNIT. REM File name: base64.bas REM Unit name: base64 REM Version: 1.0.1 21/05/2016 REM Author: Christian d'Heureuse; shian (See License below) ' Notes: ' 1. Translated from VBasic to SmallBASIC (shian). ' ' 2. Useful for IMAGE keyword, and for any binary-to-text encoding/decoding. ' Base64 is often used to embed binary data in source code. ' ' 3. Since this is a translated code, I did not add much comments about the ' encoding/decoding method... So for more details about it see: ' https://en.wikipedia.org/wiki/Base64 ' ' 4. License: ' - A Base64 Encoder/Decoder. This module is used to encode and decode data ' in Base64 format as described in RFC 1521. ' - Home page: www.source-code.biz. ' - Code from: http://www.source-code.biz/snippets/vbasic/12.htm ' - License: GNU/LGPL (www.gnu.org/licenses/lgpl.html). ' - Copyright 2007: Christian d'Heureuse, Inventec Informatik AG, Switzerland. ' - This module is provided "as is" without warranty of any kind. ' ' -- Start Demo code --- --- --- --- --- --- --- --- --- --- --- ' ' Import base64 ' (Import from another .bas file) ' ' Const FILE = "SB.png" ' (Change it to any other file name) ' ' ' Example using a "file name": ' s = base64.Encode_Base64(FILE) ' Encode 1-D bytes-array to Base64-string ' a = base64.Decode_Base64(s) ' Decode Base64-string to 1-D bytes-array ' ' i = Image(a) ' Convert 1-D bytes-array to image ' i.Show(10, 10) ' Show image at location (x, y) ' Showpage ' ' ' Example using a file # (opened for input): ' Open FILE For Input As #1 ' s = base64.Encode_Base64(1) ' Encode 1-D bytes-array to Base64-string ' Close #1 ' a = base64.Decode_Base64(s) ' Decode Base64-string to 1-D bytes-array ' ' i = Image(a) ' Convert 1-D bytes-array to image ' i.Show(30, 30) ' Show image at location (x, y) ' Showpage ' ' ' Example using 1-D bytes-array (a): ' s = base64.Encode_Base64(a) ' Encode 1-D bytes-array to Base64-string ' a = base64.Decode_Base64(s) ' Decode Base64-string to 1-D bytes-array ' ' i = Image(a) ' Convert 1-D bytes-array to image ' i.Show(50, 50) ' Show image at location (x, y) ' Showpage ' ' Pause ' ' -- End Demo code --- --- --- --- --- --- --- --- --- --- --- --- Unit base64 Export Encode_Base64, Decode_Base64 ' Initialize the helper maps (this code executes only once at load time). Dim Map1(0 To 63) Dim Map2(0 To 127) i = 0 ' Set Map1 For c = 65 To 90: Map1(i) = c: i++: Next ' Asc("A") To Asc("Z") For c = 97 To 122: Map1(i) = c: i++: Next ' Asc("a") To Asc("z") For c = 48 To 57: Map1(i) = c: i++: Next ' Asc("0") To Asc("9") Map1(i) = 43 : i++ ' Asc("+") Map1(i) = 47 : i++ ' Asc("/") ' Set Map2 For i = 0 To 127 Do Map2(i) = 255 For i = 0 To 63 Do Map2(Map1(i)) = i ' Encodes a 1-D bytes array (integers) into Base64 format string. ' No blanks or line breaks are inserted. ' Parameters: ' InData 1-D bytes array containing the data bytes to be encoded; ' or, "File_Name" string to load into 1-D bytes array; ' or, File-Number (opened-for-input) to load into 1-D bytes array. ' Returns: a string with the Base64 encoded data (that you can embed in ' your source code). Func Encode_Base64(InData) Local Out ' (As Byte) Local ODataLen, OLen, ILen ' (As Long) Local ip0, ip, op ' (As Long) Local i0, i1, i2 ' (As Byte) Local o0, o1, o2, o3 ' (As Byte) Local s, i, fn, f ' as SmallBASIC... If Isarray(InData) Then ' 1-D bytes array (integers) supplied ILen = Len(InData) ' Make life easier by loading 1-D bytes array from file: Else f = Isnumber(InData) ' Set flag to close file If f Then ' An opened file # (For Input) supplied fn = InData Else ' A "filename" supplied fn = Freefile Open InData For Input As #fn Fi ILen = Lof(fn) Dim InData(1 To ILen) ' (It's much faster to allocate space first!) For i = 1 To ILen Do InData(i) = Bgetc(fn) If Not f Then Close #fn ' (Don't close file if File # supplied) Fi If ILen = 0 Then Encode_Base64 = "": Exit Func ODataLen = (ILen * 4 + 2) \ 3 ' Output length without padding OLen = ((ILen + 2) \ 3) * 4 ' Output length including padding Dim Out(0 To OLen - 1) ip0 = LBound(InData) ' Encode base64 bytes array (See Wikipedia for this...): While ip < ILen i0 = InData(ip0 + ip): ip++ If ip < ILen Then i1 = InData(ip0 + ip): ip++ Else i1 = 0 If ip < ILen Then i2 = InData(ip0 + ip): ip++ Else i2 = 0 o0 = i0 \ 4 o1 = ((i0 Band 3) * 0x10) Bor (i1 \ 0x10) o2 = ((i1 Band 0xF) * 4) Bor (i2 \ 0x40) o3 = i2 Band 0x3F Out(op) = Map1(o0): op++ Out(op) = Map1(o1): op++ Out(op) = Iff(op < ODataLen, Map1(o2), 61): op++ ' 61 is Asc("=") Out(op) = Iff(op < ODataLen, Map1(o3), 61): op++ ' 61 is Asc("=") Wend s = "": For i In Out Do s += Chr(i) ' Bytes-to-String Encode_Base64 = s End Func ' Decodes a string from Base64 format. ' Parameters ' s a Base64 String to be decoded. ' Returns: a 1-D array containing the decoded data bytes (integers). Func Decode_Base64(s) Local IBuf, Out ' (As Byte array) Local i0, i1, i2, i3 ' (As Byte) Local b0, b1, b2, b3 ' (As Byte) Local o0, o1, o2 ' (As Byte) Local OLen, ip, op ' (As Long) Local ILen = Len(s) ' (As Long) Local i ' as SmallBASIC... If (ILen Mod 4) Or (ILen = 0) Then ' Data error Throw "Length of Base64 encoded input string is not a multiple of 4." Fi Dim IBuf(0 To ILen - 1) For i = 1 To ILen Do IBuf(i - 1) = Asc(Mid(s, i, 1)) ' String-to-Bytes While ILen > 0 If IBuf(ILen - 1) <> 61 Then Exit Loop ' 61 is Asc("=") ILen-- Wend OLen = (ILen * 3) \ 4 Dim Out(0 To OLen - 1) ' 1-D bytes array ' Decode base64 bytes array (See Wikipedia for this...): While ip < ILen i0 = IBuf(ip): ip++ i1 = IBuf(ip): ip++ If ip < ILen Then i2 = IBuf(ip): ip++ Else i2 = 65 ' 65 is Asc("A") If ip < ILen Then i3 = IBuf(ip): ip++ Else i3 = 65 ' 65 is Asc("A") If i0 > 127 Or i1 > 127 Or i2 > 127 Or i3 > 127 Then Throw "Illegal character in Base64 encoded data." ' Data error Fi b0 = Map2(i0) b1 = Map2(i1) b2 = Map2(i2) b3 = Map2(i3) If b0 > 63 Or b1 > 63 Or b2 > 63 Or b3 > 63 Then Throw "Illegal character in Base64 encoded data." ' Data error Fi o0 = (b0 * 4) Bor (b1 \ 0x10) o1 = ((b1 Band 0xF) * 0x10) Bor (b2 \ 4) o2 = ((b2 Band 3) * 0x40) Bor b3 Out(op) = o0: op++ If op < OLen Then Out(op) = o1: op++ If op < OLen Then Out(op) = o2: op++ Wend Decode_Base64 = Out End Func You may create a PNG image + transparency color with an external image editor, and then you may also decode it as a Base64 PNG string (to store it within the source code). Another useful option is to use XPM image format (See Part-3 above) with transparency color, instead of color number you just write NONE, like this: a << "x c NONE" ' Character "x" is transparency color Console version example The following creates a plist file and composite sprite sheet which can be used with cocos2d development const backgnd = 0xFF5A5D39 const shadow = 0xFF080c08 const alpha = 0x5a5d39 const alphaShadow = 0x80080c08 dim tileset tileset << ["eating e0000.png", 13] tileset << ["eating n0000.png", 13] tileset << ["eating ne0000.png", 13] tileset << ["eating nw0000.png", 13] tileset << ["eating s0000.png", 13] tileset << ["eating se0000.png", 13] tileset << ["eating sw0000.png", 13] tileset << ["eating w0000.png", 13] tileset << ["headshaking e0000.png", 11] tileset << ["headshaking n0000.png", 11] tileset << ["headshaking ne0000.png", 11] tileset << ["headshaking nw0000.png", 11] tileset << ["headshaking s0000.png", 11] tileset << ["headshaking se0000.png", 11] tileset << ["headshaking sw0000.png", 11] tileset << ["headshaking w0000.png", 11] tileset << ["running e0000.png", 11] tileset << ["running n0000.png", 11] tileset << ["running ne0000.png", 11] tileset << ["running nw0000.png", 11] tileset << ["running s0000.png", 11] tileset << ["running se0000.png", 11] tileset << ["running sw0000.png", 11] tileset << ["running w0000.png", 11] tileset << ["stopped0000.png", 7] tileset << ["walking e0000.png", 11] tileset << ["walking n0000.png", 11] tileset << ["walking ne0000.png", 11] tileset << ["walking nw0000.png", 11] tileset << ["walking s0000.png", 11] tileset << ["walking se0000.png", 11] tileset << ["walking sw0000.png", 11] tileset << ["walking w0000.png", 11] func colorToAlpha(x) if (x == backgnd) then return alpha if (x == shadow) then return alphaShadow return x end sub print_include() local j, pattern, count, out, varname out << "#pragma once" for j = 0 to len(tileset) - 1 x = 0 y = 0 [pattern, count] = tileset[j] varname = translate(pattern, "0000.png", "") varname = translate(varname, " ", "_") varname = upper(varname) pattern = translate(pattern, "0000", "%04d") out << "const char *" + varname + "_PNG = \"" + pattern + "\";" out << "const int " + varname + "_PNG_SIZE = " + count + ";" next j tsave "Classes/horse.h", out end sub print_plist(byref images) local plist, i dim plist plist << "" plist << "" plist << "" plist << "" plist << " texture" plist << " " plist << " width" plist << " " + w + "" plist << " height" plist << " " + h + "" plist << " " plist << " frames" plist << " " for i = 0 to len(images) - 1 png = images[i] plist << " " + png.name + "" plist << " " plist << " x" plist << " " + png.x + "" plist << " y" plist << " " + png.y + "" plist << " width" plist << " " + png.width + "" plist << " height" plist << " " + png.height + "" plist << " offsetX" plist << " 0" plist << " offsetY" plist << " 0" plist << " originalWidth" plist << " " + png.width + "" plist << " originalHeight" plist << " " + png.height + "" plist << " " next i plist << " " plist << " plist << " tsave "Resources/horse.plist", plist tsave "linux-build/bin/Debug/MobileCup/Resources/horse.plist", plist end sub main(byref tileset) local i, j, x, y, pattern, count, images, composite, width, height dim images width = 0 height = 0 for j = 0 to len(tileset) - 1 x = 0 y = 0 [pattern, count] = tileset[j] for i = 0 to count png = image("images/horse/" + format(pattern, i)) png.clip(5, 5, 5, 5) png.filter(use colorToAlpha(x)) png.name = format(pattern, i) png.x = x png.y = height x += png.width + 1 y = iff(png.height > y, png.height, y) images << png next i width = iff(x > width, x, width) height += y next j composite = image(width, height) for i = 0 to len(images) - 1 png = images[i] composite.paste(png, png.x, png.y) next i composite.save("Resources/horse.png") composite.save("linux-build/bin/Debug/MobileCup/Resources/horse.png") print_plist(images) print_include() end main(tileset) +========================================================================================+ | 89. (Graphics) LINE | +========================================================================================+ LINE [STEP] x,y [,|STEP x2,y2] [, color| COLOR color] Draws a line from the point (x,y) to the point (x2,y2). If STEP is used, the graphics cursor is moved by a step of x and y pixels. When color is specified, instead of the actual foreground color the line will be drawn with the color color. By default LINE draws with anti-aliasing. For details, see: Xiaolin Wu’s line algorithm. To turn off anti-aliasing, add this to the start of your program: option predef antialias off Example 1: Line defined by two points line 20, 20, 100, 100 Example 2: Line defined using STEP line 20, 20, STEP 80,80 ' Line starts at point (20,20) ' and ends at point (20+80, 20+80) -> (100,100) line STEP -80, -70, STEP 80,80 ' Line starts at last graphics cursor position ' plus step values (100-80,100-70) -> (20,30) ' and ends at last graphics cursor position ' plus step values (20+80, 30+80) -> (100,110) line STEP -80, -70, 100, 120 ' Line starts at last graphics cursor position ' plus step values (100-80,110-70) -> (20,40) ' and ends at the point (100,120) Example 3: Using colors line 20, 30, 100, 110 color 2 line 20, 40, 100, 120, 3 line 20, 50, 100, 130, rgb(0,255,0) line 20, 60, 100, 140 color rgb(0,255,255) +========================================================================================+ | 90. (Graphics) PAINT | +========================================================================================+ PAINT [STEP] x, y [,fill-color [,border-color]] Fills an enclosed area on the graphics screen with the color fill-color. x and y are screen coordinates within the area that is to be filled. If border-color is specified then PAINT will fill outwards until is meets the specified border-color. If the border-color is not specified then PAINT will fill the area until it meets a color which is not the original color at [x,y]. Please note that border-color needs to be specified using the functions RGB or RGBF. If the keyword STEP is used, x and y move the graphics cursor in pixel. The area will be filled starting from this new position of the graphics cursor. Example 1: Fill without specified border-color ' draw a diamond shaped polygon polygon = [[100,100], [150,50], [200,100], [150,200], [100,100]] color 14 drawpoly polygon ' draw a rectangle on top of the diamond color 13 rect 120,60,180,180 ' fill area inside color 12 paint 150,130 Example 2: Fill with specified fill-color and border-color ' draw a diamond shaped polygon polygon = [[100,100], [150,50], [200,100], [150,200], [100,100]] color 14 drawpoly polygon ' draw a rectangle on top of the diamond RectColor = rgb(255,0,255) color RectColor rect 120,60,180,180 ' fill area inside rect paint 150,130, 11, RectColor ' Border color needs do be set with RGB(...) +========================================================================================+ | 91. (Graphics) PEN | +========================================================================================+ PEN (0..14) Returns pen, mouse or tap data depending on value. ----------------------------------------------------------------------- Value Desription -------- -------------------------------------------------------------- 0 True (non zero) if there is a new pen or mouse event 1 x position of last pen down, tap, mouse button down 2 y position of last pen down, tap, mouse button down 3 True if pen is down, mouse left button is pressed or tap 4 Pen, tap: last/current x position, MOUSE: the current x position only if the left mouse button is pressed 5 Pen, tap: last/current y position, MOUSE: the current x position only if the left mouse button is pressed 10 current mouse x pos 11 current mouse y pos 12 true if the left mouse button is pressed 13 true if the right mouse button is pressed 14 true if the middle mouse button is pressed ----------------------------------------------------------------------- PEN must be enabled prior to use of this function with Pen ON|OFF Most important values are 3, 4 and 5. With PEN(3) you will know, if the left mouse button was pressed or the screen was tapped. With PEN(4) and PEN(5) you will get the coordinates of that click or tap. See example 2 and 3. Example 1: Overview Print " Move and click the Pen or Mouse [press Esc to stop]..." Print Pen On Print Using " ####x, ####y"; ' Format for x,y position While Inkey <> Chr(27) Do ' Press Esc key to exit loop Locate 3, 0 print "Pen|Mouse new event: "; Pen(0) print print "Pen last down|Mouse down:";: ? Usg; Pen(1), Pen(2) print print "Pen down|Mouse Left down: "; Pen(3) print print "Pen last/current|Mouse Left down:";: ? Usg; Pen(4), Pen(5) print print "Mouse current:";: ? Usg; Pen(10), Pen(11) print print "Mouse Left, Middle, Right down: ", Pen(12), Pen(14), Pen(13); Wend Example 2: Get position of tap or mouse click pen on print "Press left mouse button or tab screen. Press q to quit." while(1) if(pen(3)) then PosX = pen(4) PosY = pen(5) locate 1,0: print "Click/tap at position: " + PosX + " , " + PosY endif k = inkey() if(len(k) == 1 AND k == "q") then end showpage delay(20) wend DELAY 20 ms saves CPU and battery in a loop. Example 3: Press a button pen on print "Press left mouse button or tab screen. Press q to quit." ' Define button button.x = 100 button.y = 100 button.w = 100 button.h = 100 while(1) ' Draw button in dark yellow rect button.x, button.y STEP button.w, button.h color 6 filled if(pen(3)) then PosX = pen(4) PosY = pen(5) ' Check if the click or tap is inside the button area if( (PosX > button.x) and (PosX < button.x + button.w) and (PosY > button.y) and (PosY < button.y + button.h) ) ' Draw button in red rect button.x, button.y STEP button.w, button.h color 12 filled endif endif k = inkey() if(len(k) == 1 AND k == "q") then end showpage delay(20) wend +========================================================================================+ | 92. (Graphics) PLOT | +========================================================================================+ PLOT xmin, xmax USE f(x) Plots the graph of f(x) in the range from xmin to xmax. The variable must be x. Example ' Set wite background and drawing color to red color rgb(255,0,0), rgb(255,255,255) cls ' Define function and plot def f(x) = sin(x) plot 0, 2*pi USE f(x) +========================================================================================+ | 93. (Graphics) POINT | +========================================================================================+ POINT (x [, y]) Returns the color of the pixel at x,y. If the y-argument is not specified, x specifies the following info-code: - 0: returns the current graphics cursor X-position - 1: returns the current graphics cursor Y-position Example 1: Get color print point(100,100) ' Output: -2038815 Example 2: Get graphics cursor position x = point(0) y = point(1) print "Initial position: "; x, y ' Output: 0,0 line STEP 50,50 STEP 50,50 x = point(0) y = point(1) print "Position after STEP: "; x, y ' Output: 100,100 Example 3 This demonstrates saving a screen section and redrawing it at different places on screen, a tiling and a moving across the screen. ' POINT demo.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-07 for objects = 1 to 300 if rnd > 0.5 then circle rnd*xmax\1, rnd*ymax\1, rnd*50\1, rnd*5, rnd*16/1 else rect rnd*xmax\1, rnd*ymax\1 step rnd*50\1, rnd*50\1, rnd*16/1 end if next at 0, ymax - 2*txth("Q") : print " press any..." showpage pause xw = 350 yh = 250 bottle 0, 0, xw, yh cls for y = 0 to ymax step yh for x = 0 to xmax step xw pour x, y, xw, yh showpage next next at 0, ymax - 2*txth("Q"): print " press any..." showpage pause cls for x = 0 to xmax step 25 cls pour x, ymax\2 - yh\2, xw, yh showpage delay 10 next at 0, ymax - 2*txth("Q") : print "done, press any... " showpage pause sub bottle(xleft, ytop, xwidth, yheight) local x, y dim screensection(xwidth, yheight) for y = ytop to (ytop + yheight - 1) for x = xleft to (xleft + xwidth - 1) screensection(x, y) = POINT(x, y) next next end sub pour(xoff, yoff, xwidth, yheight) local x, y for y = 0 to yheight for x = 0 to xwidth colr = screensection(x, y) pset x + xoff, y + yoff, colr next next end Example 4: Get graphics cursor and color ' Note: POINT(x, y) returns the color of the pixel at x,y. But it's ' also possible to use POINT(0) and POINT(1) to return the current ' X,Y graphics position...: ' Draw a little circle at the current graphics x,y position: Sub show_point Local x = Point(0) ' This is where the last graphics command left us... Local y = Point(1) Local c c = Point(x, y) ' Now we know also the color of that point... Circle x, y, 3 Color c FILLED ' (CIRCLE does not change current X,Y) End Sub ' Draw a box and show the corners with a circle: Line 50, 50, 360, 50 Color 15: show_point Line STEP 0, +40 Color 14: show_point Line STEP -(360 - 50), 0 Color 15: show_point Line STEP 0, -40 Color 14: show_point Showpage ' Print text inside the box and change its colors: x = Point(0) + 45 y = Point(1) + 8 text = "That's the POINT !" x_dot = x + Txtw(text) - 6 y_dot = y + Txth(text) - 5 For b = 7 To 1 Step -1 ' b = Background color c = b Xor (16 - b) ' c = Reversed Foreground color Color c, b: At x, y: Print "That's the POINT !" Circle x_dot, y_dot, 3 Color c FILLED ' Print a point under '!' Paint x - 2, y - 2, b ' Paint the rest of the box Pause 1 Showpage Next Pause +========================================================================================+ | 94. (Graphics) PSET | +========================================================================================+ PSET [STEP] x,y [, color| COLOR color] Draws a pixel at coordinate x,y with color color. If color is not defined, the current foreground color will be used. If STEP is used, the graphics cursor will be moved by x pixels in x-direction and y pixel in y-direction and then the pixel will be drawn. Example: color 10 ' Set foreground color 10 PSET 50,50 ' Point at 50,50 with foreground color PSET 60,60, 11 ' Point at 60,60 with color 11 PSET 70,70 COLOR 12 ' Point at 70,70 with color 12 PSET 80,80, rgb(255,255,0) ' Point at 80,80 with color yellow PSET STEP 10,10 COLOR 13 ' Point at 90,90 with color 13 +========================================================================================+ | 95. (Graphics) RECT | +========================================================================================+ RECT [STEP] x,y [,|STEP x2,y2] [, color| COLOR color] [FILLED] Draws a rectangle from point x1,y1 to point x2,y1. If STEP is used, start point and/or end point are relative to the current graphics cursor position. The line color of the rectangle will be color. If color is omitted then the current foreground color will be used as line color. When using FILLED, the rectangle will be filled with color color or with the current foreground color. Example 1: Draw rectangles ' Draws a rectangle: rect 200, 100 ' at point [0,0], width 200, height 100 rect 10, 10, 210, 110 ' from proint [10,10] to point [210,110] rect 20, 20, STEP 200, 100 ' at point [20,20], width 200, height 100 rect STEP 10,10, 420, 220 ' from last graphics cursor position + [10,10] ' to point [420,100] rect STEP 10,10, STEP 200, 100 ' from last graphics cursor position + [10,10], ' width 200, height 100 Example 2: Draw rectangles with color rect 10, 10, STEP 200, 100, 12 rect 20, 20, STEP 200, 100 COLOR 13 rect 30, 30, STEP 200, 100, rgb(50,255,20) rect 10, 140, STEP 200, 100, 12 FILLED rect 20, 150, STEP 200, 100 COLOR 13 FILLED rect 30, 160, STEP 200, 100, rgb(50,255,20) FILLED color 11 rect 10, 270, STEP 200, 100 rect 20, 280, STEP 200, 100 FILLED +========================================================================================+ | 96. (Graphics) RGB | +========================================================================================+ RGB (r, g, b) Returns the RGB color code for the specified color values. r, g and b are the three color channels red, green and blue and take integer values from 0 to 255 for each of the color. Values outside that range will be clamped. The return value is a negative 24bit value to be used by the drawing functions. See also Colors Tutorial. Additionally see the CSS color names unit in the article section, to use all 140 standard CSS colors in an easy way. Example 1 c = rgb(12, 123, 240) rect 10, 10, 50, 50 color c filled rect 60, 10, 100, 50 color rgb(212,123,240) filled Example 2: Clamping of values c1 = rgb(-12, 1023, 240.4) ' same as rgb(0, 255, 240) c2 = rgb(0, 255, 240) rect 10, 10, 50, 50 color c1 filled rect 60, 10, 100, 50 color c2 filled Example 3: Fading colors Def txt(t) = " " + t + " " For c = 0 to 255 Color 15, Rgb(c, 0, 0): At 10, 0: Print txt("1. RED"); Color 15, Rgb(0, c, 0): At 10, 30: Print txt("2. GREEN"); Color 15, Rgb(0, 0, c): At 10, 60: Print txt("3. BLUE"); Color 15, Rgb(0, c, c): At 10, 90: Print txt("4. CYAN"); Color 15, Rgb(c, c, 0): At 10, 120: Print txt("5. YELLOW"); Color 15, Rgb(c, 0, c): At 10, 150: Print txt("6. MAGENTA"); Color 15, Rgb(c, c, c): At 10, 180: Print txt("7. GRAY"); Color 15, Rgb(c, c\2, 0): At 10, 210: Print txt("8. ORANGE"); Color 15, Rgb(c\2, c\2, 0): At 10, 240: Print txt("9. OLIVE"); Color 15, Rgb(c\2, c\4, 0): At 10, 270: Print txt("A. BROWN"); Color 15, Rgb(c, 0, c\2): At 10, 300: Print txt("B. PINK"); Color 15, Rgb(0, 0, c\3): At 10, 330: Print txt("C. NAVY"); Color 15, Rgb(c\3, c\2, c): At 10, 360: Print txt("D. SKY"); Delay 20 Next +========================================================================================+ | 97. (Graphics) RGBF | +========================================================================================+ RGBF (r, g, b) Returns the RGB color code for the specified color values. r, g and b are the three color channels red, green and blue and take floating point values from 0 to 1 for each of the colors. Values outside that range will be clamped. The return value is a negative 24bit value to be used by the drawing functions. See also Colors Tutorial. Additionally see the CSS color names unit in the article section, to use all 140 standard CSS colors in an easy way. Example 1 c = rgbf(0.047, 0.48, 0.94) rect 10, 10, 50, 50 color c filled rect 60, 10, 100, 50 color rgbf(0.047, 0.48, 0.94) filled Example 2: Clamping of values c1 = rgbf(-0.55, 2.5, 0.94) ' same as rgbf(0, 1, 0.94) c2 = rgbf(0, 1, 0.94) rect 10, 10, 50, 50 color c1 filled rect 60, 10, 100, 50 color c2 filled Example 3: Fading colors Def txt(t) = " " + t + " " For c = 0 to 1 step 0.01 Color 15, Rgbf(c, 0, 0): At 10, 0: Print txt("1. RED"); Color 15, Rgbf(0, c, 0): At 10, 30: Print txt("2. GREEN"); Color 15, Rgbf(0, 0, c): At 10, 60: Print txt("3. BLUE"); Color 15, Rgbf(0, c, c): At 10, 90: Print txt("4. CYAN"); Color 15, Rgbf(c, c, 0): At 10, 120: Print txt("5. YELLOW"); Color 15, Rgbf(c, 0, c): At 10, 150: Print txt("6. MAGENTA"); Color 15, Rgbf(c, c, c): At 10, 180: Print txt("7. GRAY"); Color 15, Rgbf(c, c\2, 0): At 10, 210: Print txt("8. ORANGE"); Color 15, Rgbf(c\2, c\2, 0): At 10, 240: Print txt("9. OLIVE"); Color 15, Rgbf(c\2, c\4, 0): At 10, 270: Print txt("A. BROWN"); Color 15, Rgbf(c, 0, c\2): At 10, 300: Print txt("B. PINK"); Color 15, Rgbf(0, 0, c\3): At 10, 330: Print txt("C. NAVY"); Color 15, Rgbf(c\3, c\2, c): At 10, 360: Print txt("D. SKY"); Delay 20 Next +========================================================================================+ | 98. (Graphics) SHOWPAGE | +========================================================================================+ SHOWPAGE This command is used to display pending graphics operations allowing for smooth animations. If SHOWPAGE is used, the internal SmallBASIC graphics update mechanism is set to manual mode. To enable automatic mode again, call SHOWPAGE with the optional parameter n = 1. This is useful, if the FORM command is used to display GUI elements. Example for x = 10 to 100 cls rect x, 10, x + 200, 200 filled showpage delay(20) next +========================================================================================+ | 99. (Graphics) TEXTHEIGHT | +========================================================================================+ TEXTHEIGHT (s) Returns the text height of string s in pixel. TXTH is equivalent to TEXTHEIGHT. Example print txtheight("Hello world") ' Output: 19 +========================================================================================+ | 100. (Graphics) TEXTWIDTH | +========================================================================================+ TEXTWIDTH (s) Returns the text width of string s in pixel. TXTW is equivalent to TEXTWIDTH. Example print textwidth("Hello world") ' Output: 88 +========================================================================================+ | 101. (Graphics) TXTH | +========================================================================================+ TXTH (s) Returns the text height of string s in pixel. TXTHEIGHT is equivalent to TXTH. Example print txth("Hello world") ' Output: 19 +========================================================================================+ | 102. (Graphics) TXTW | +========================================================================================+ TXTW (s) Returns the text width of string s in pixel. TEXTWIDTH is equivalent to TXTW. Example print txtw("Hello world") ' Output: 88 +========================================================================================+ | 103. (Graphics) VIEW | +========================================================================================+ VIEW [x1,y1,x2,y2 [,color [,border-color]]] Defines a viewport with starting point (upper left corner)) [x1,y1] and end point (lower right corner) [x2,y2]. The optional parameters color and border-color define the background color and the border color of the viewport, respectively. VIEW without parameters will disable the last set viewport. Example view ' Disable viewport rect 100,100, STEP 100,100 color 4 filled ' Draw a rectangle in dark red view 150,150, 300,300, 0, 13 ' Set new viewport with black background and magenta border rect 100,100, STEP 100,100 color 14 filled ' Draw same rectangle in yellow +========================================================================================+ | 104. (Graphics) WINDOW | +========================================================================================+ WINDOW [x1,y1,x2,y2] Specifies “world” coordinates for the screen. The WINDOW command allows you to redefine the corners of the display screen as a pair of “world” coordinates. The coordinates of the upper-left corner of the screen is given by [x1, y1], the lower-left corner by [x2, y2]. The world space defined by WINDOW is disabled by a WINDOW command without parameters. Example ' Coordinate system with corners: ' upper-left = [-20,-10] ' lower-right= [ 20, 10] x1 = -20 y1 = -10 x2 = 10 y2 = 20 window x1, x2, y2, y1 rect -20, -10 STEP 1, 1, 14 filled ' Yellow: upper-left rect 19, -10 STEP 1, 1, 13 filled ' Magenta: upper-right rect 19, 9 STEP 1, 1, 12 filled ' Red: lower-right rect -20, 9 STEP 1, 1, 10 filled ' Green: lower-left circle 0, 0, 1, 1, 15 filled ' White: center WINDOW sub-commands (non-standard) WINDOW is also overloaded as a function, returning a system object which provides access to the following sub-commands. alert(message, title) Display an alert window. The title of the window is title and the context is message. w = window() w.alert("This is an alert", "title") ask(message, title) Display a prompt window to retrieve a user selection. The choices are “Yes” and “No”. The title of the window is title and the context is message. The answer is stored in the window-object variable answer: 0 for “Yes” and 1 for “No”. w = window() w.ask("Yes or no?", "Question") if w.answer == 0 then print "Yes" else print "No" endif graphicsScreen1(), graphicsScreen2() Select graphics mode screen 1 or 2 for output. When switching to a different screen, the context of the previous screen is stored in RAM. When switching back to the previous screen, the context will be restored. w = window() w.graphicsScreen1() ' Set output to screen 1 rect 100,100 STEP 100,100, 15 filled w.graphicsScreen2() ' Set output to screen 2 rect 150,150 STEP 100,100, 14 filled ' Switch between both screens, no need to redaw the rectangles while 1 b = !b if b then w.graphicsScreen1() else w.graphicsscreen2() endif delay(500) wend insetTextScreen(x1, y1, x2, y2) Insert an area for text output from position [x1, y1] to position [x2, y2] w = window() ? "How does this look?" w.insetTextScreen(5,10,90,90) for i = 0 to 200 ? "This is in the text screen" next i pause menu(option1 [, option2, …, optionN) Displays a popup menu with the entries option1 to optionN. INKEY will return the number of the selected option starting with 0. w = window() w.menu("option1", "option2", "option3") select case asc(inkey) case 0 print "one" case 1 print "two" case 2 print "three" case else print "unk" end select message(str) Displays a status message str at the bottom of the screen. w = window() w.message("Click to continue. ") setFont(size, unit, bold, italic) Sets the font size to size. unit can be set to “em” to make size relative to the existing size. Any other value will cause size to be avaluated as pixels. bold can be set to 0 or 1 to enable or disable bold font style. italic can be set to 0 or 1 to enable or disable italic font style. w = window() w.setFont(15, "px", 0, 0) print "Fixed size 15px" w.setFont(2, "em", 0, 0) print "Relative size 15px * 2" w.setFont(15, "px", 1, 0) print "Fixed size 15px bold" w.setFont(15, "px", 0, 1) print "Fixed size 15px italic" w.setFont(15, "px", 1, 1) print "Fixed size 15px bold italic" setLocation(x, y) Sets the location of the window on the screen. The upper-left corner of the window will be at position [x, y] in pixel. w = window() w.setLocation(100, 100) setSize(w, h) Sets the width w and height h in pixel of the SmallBASIC window. w = window() w.setSize(800, 680) showKeypad() Raises the virtual keypad on android. w = window() w.showKeypad() hideKeypad() Hides the virtual keypad on android. w = window() w.hideKeypad() textScreen() Select the text mode for output. Text mode can display more text but is slow. w = window() w.textScreen() for i = 0 to 1000 ? "hello " + i next for theme Returns the active window colour theme. w = window() const theme = w.theme const colBkGnd = theme.background const colText = theme.text5 const colFile = theme.text2 const colDir = theme.text3 const colText2 = theme.text4 const colNav = theme.text1 const colNav2 = theme.text6 +========================================================================================+ | 105. (Graphics) XMAX | +========================================================================================+ XMAX Returns the screen width in pixels. See YMAX for screen height. Example print "This window has " + XMAX + "x" + YMAX + " pixels" ' Output: This window has 640x480 pixels +========================================================================================+ | 106. (Graphics) XPOS | +========================================================================================+ XPOS Returns the current X-position of the text cursor in “characters”. See YPOS for Y-position. Example locate 10,5 print XPOS, YPOS ' Output 5 10 +========================================================================================+ | 107. (Graphics) YMAX | +========================================================================================+ YMAX Returns the screen height in pixels. See XMAX for screen width. Example print "This window has " + XMAX + "x" + YMAX + " pixels" ' Output: This window has 640x480 pixels +========================================================================================+ | 108. (Graphics) YPOS | +========================================================================================+ YPOS Returns the current Y-position of the text cursor in “characters”. See XPOS for X-position. Example locate 10,5 print XPOS, YPOS ' Output 5 10 +========================================================================================+ | 109. (Language) AND | +========================================================================================+ a AND b Logical AND. Right side is not evaluated if left side evaluates to FALSE. Truth table: a b a AND b --- --- --------- 0 0 0 0 1 0 1 0 0 1 1 1 Example 1 a = 1 b = 0 print a and b ' Output: 0 Example 2: Using AND in an if-statement a = 1 b = 0 if(a == 1 and b == 0) then print "if statement 1" if(a == 1 and b == 1) then print "if statement 2" c = "test" if(a == 1 and c == "test") then print "if statement 3" if(a == 1 and c == "test2") then print "if statement 4" ' Output: ' if statement 1 ' if statement 3 Example 3: Truth table for logical and bitwise operators ? " < SmallBASIC - Truth Table > " ? ? " OUTPUTS (0=False, 1=True) " ? " +---------------+---------------------------------------------+" ? " | Logical (per | Bitwise |" ? " INPUTS | expression) | (for each bit in result) |" ? " +---------+---------------+---------------------------------------------+" ? " | a b | AND OR NOT(b)| BAND BOR ~(b) NAND NOR XOR XNOR EQV IMP |" ? " +---------+---------------+---------------------------------------------+" ' Display table (0 and 1 equivalent to 0b0 and 0b1): For a = 0 To 1 For b = 0 To 1 ? Usg " | 0 0 |"; a, b; ? Usg " 0 "; ' Logical (result compared to False): ? Usg; (a AND b) <> 0; ? Usg; (a OR b) <> 0; ? Usg; ( NOT b) <> 0; ? "|"; ' Bitwise (result is in bit-0): ? Usg; (a BAND b) Band 1; ? Usg; (a BOR b) Band 1; ? Usg; ( ~ b) Band 1; ? Usg; (a NAND b) Band 1; ? Usg; (a NOR b) Band 1; ? Usg; (a XOR b) Band 1; ? Usg; (a XNOR b) Band 1; ? Usg; (a EQV b) Band 1; ? Usg; (a IMP b) Band 1; ? "|" Next b Next a ? " +---------+---------------+---------------------------------------------+" ? " * For Logical operators 0 is False and any other value is True." ? " * NOT, ~ (Bitwise NOT), operators using only right side value/expression." ? " * XNOR and EQV is the same gate (both return the same result)." For experts: The Sign-Bit Bug (part 2): Ways to workaround this bug: 1. It is Safe to manipulate the lower bits, 0 to 30. If your program don’t need to manipulate whole 32-bits of integer, then you can safely BAND numbers with 0x7FFFFFFF to create 31-bit unsigned integers (bit-31+ are cleared). But you must make sure when using math functions or bitwise NOT (~) that the sign bit (bit-31) always remains intact, i.e. = 0. 2. A slower way, but safe, is to manipulate 32 bits using BIN() function. In this way you can temporarily convert a number to binary string of 32-bits, manipulate whole 32 bits using regular string manipulation, and then convert the binary string back to number, for example: assuming that BIN() returns 32-bits binary string (as it should): s = Bin(number) ' convert number to binary string s = Replace(s, 1, "1") ' set bit-31 s = Replace(s, 32, "0") ' reset bit-0 number = Val(s) ' convert binary string back to number This code will work the same way on both 64-bit and 32-bit systems. It allows you to Shift/Rotate 32-bit numbers safely. So if you don’t need the speed of bitwise operators, then this is easy and safe way. 3. If you still need to manipulate whole 32 bits, using fast bitwise operators, in a safe way that will give the same results on 32-bit and 64-bit systems, then it’s possible. Just be aware of the following: - Never change the sign bit (bit-31 of integer) by using Math operators or function; or by using bitwise NOT (~). This leads to arithmetic result as opposed to bitwise result. - Trim double number to integer using ‘n = n BAND 0xFFFFFFFF’; save the sign-bit using ‘save_sign = n BAND 0x80000000’; then mask the lower 31 bits using ‘n = n BAND 0x7FFFFFFF’; then manipulate Only these 31 bits; then restore the sign-bit using ‘n = n BOR save_sign’. - To shift bits left: clear the upper bits including the sign bit; then multiply by POW(2, bits) to shift left Only bits-0..30; then set the sign bit (bit-31) using ‘n = n BOR bit’. - To shift bits right: clear the upper bits including the sign bit; then divide by POW(2, bits). REM SmallBASIC REM created: 11/03/2016 REM I'm using smallbasic_0.12.2, 32-bit and 64-bit versions for Linux. ' The Sign-Bit Bug: ' ----------------- ' The Sign Bit, (or the "Most Significant Bit", or the "Leftmost Bit", ' or bit-31 of SmallBASIC integer) - is a bit in a signed number that ' indicates the sign of a number. ' If you write a Bit Manipulation code, be aware that SmallBASIC is ' interpreting your code differnetly on 32-bit or 64-bit system: ' For example, run the following code on 32-bit and 64-bit systems: ? "Assigning hexadecimal number to variable or constant:" n = 0xFFFFFFFF ? n ' On 32-bit system n is: -1 ' On 64-bit system n is: 4294967295 ? ? "Bitwise NOT (~) a number:" n = ~0xFFFFFFFF ? Bin(n) ' On 32-bit system n is: 00000000000000000000000000000000 ' On 64-bit system n is: 10000000000000000000000000000000 ? ? "Raising to power of 32+ bit number:" n = Pow(2, 32) - 1 ? Bin(n) ' On 32-bit system n is: 10000000000000000000000000000000 ' On 64-bit system n is: 11111111111111111111111111111111 ? ? "Using 64-bit double number instead of 32-bit integer:" n = 0xFFFFFFFF ? Bin(n) ' The same result on both systems: ' On 32-bit system n is: 11111111111111111111111111111111 ' On 64-bit system n is: 11111111111111111111111111111111 ? ? "Using hexadecimal number *in-line*:" n = 0xFFFFFFFF Band 0x7FFFFFFF ? n ' The same result on both systems: ' On 32-bit system n is: 2147483647 ' On 64-bit system n is: 2147483647 The code above produces different results on 32-bit and 64-bit systems; Therefore it leads to subtle bug with no run-time error, and no other indication. The reason for this inconsistency is the fact that SamllBASIC determine the type of variables on the fly. And while the sign bit in a 64-bits register is bit-63 - in a 32-bits register is bit-31. SmallBASIC integers are 32-bit signed integers. The sign bit of SmallBASIC integer is bit-31 (base 0). It is Safe to manipulate only bits 0 to 30, on both 64-bit and 32-bit systems. But it is Not safe to manipulate the sign bit, bit-31. +========================================================================================+ | 110. (Language) AS | +========================================================================================+ AS #fileN Used in combination with OPEN to open a file using a file number. See: OPEN Example: ' create a text file open "MyDemoFile.txt" for output as #1 for i = 1 to 10 print #1, i next close #1 ' open text file and print content line by line open "MyDemoFile.txt" for input as #1 while(!eof(1)) ' eof works only without # input #1, c print c wend close #1 +========================================================================================+ | 111. (Language) BAND | +========================================================================================+ a BAND b Bitwise AND. Truth table: a b a BAND b --- --- ---------- 0 0 0 0 1 0 1 0 0 1 1 1 See AND for the logical operator. Example 1 print "1011 AND 1101 = "; bin(0b1011 band 0b1101) ' Output: 1011 AND 1101 = 1001 Example 2 The following example will first pack a date into a single integer and then unpack the integer to get the original date using bitwise operations. Def shl(n, c) = n * Pow(2, c) ' shift-left c bits in n Def shr(n, c) = n \ Pow(2, c) ' shift-right c bits in n Def mask(c) = Pow(2, c) - 1 ' return a mask of c bits ' get the current date as three integers: now = Date ' now is "dd/mm/yyyy" day = Left(now, 2) * 1 month = Mid(now, 4, 2) * 1 year = Right(now, 4) * 1 ' pack the date in one integer: p = day ' packing 5 bits (days 1..31) p = shl(p, 4) Bor month ' packing 4 bits (months 1..12) p = shl(p, 12) Bor year ' packing 12 bits (years 0..4095) Print Using "The current date : 00/00/0000"; day, month, year; Print " -> Packed as: "; p; " (0x"; Hex(p); ")" ' unpack the date from one integer: p_day = shr(p, 12 + 4) ' packed in bits 16..20 p_month = shr(p, 12) Band mask(4) ' packed in bits 12..15 p_year = p Band mask(12) ' packed in bits 0..11 Print Using "The Unpacked date: 00/00/0000"; p_day, p_month, p_year; +========================================================================================+ | 112. (Language) BG | +========================================================================================+ SOUND frq, dur [, vol] [BG] Play sound in the background. BG prevents the program from blocking while the sound plays. See SOUND. Example SOUND 1000, 1000 BG pause +========================================================================================+ | 113. (Language) BOR | +========================================================================================+ a BOR b Bitwise OR. Truth table: a b a BOR b --- --- --------- 0 0 0 0 1 1 1 0 1 1 1 1 See OR for logical or. Example print "1001 BOR 1110 = "; bin(0b1001 BOR 0b1100) ' Output: 1001 BOR 1110 = 1101 +========================================================================================+ | 114. (Language) BYREF | +========================================================================================+ BYREF Sub/func argument declaration. Changes to the variable will be passed back to the caller. Equivalent syntax to the @ character. Example sub Increment(BYREF i) i = i + 1 end x = 1 Increment(x) print x ' output: 2 +========================================================================================+ | 115. (Language) CALL | +========================================================================================+ CALL (fp) Invoke a sub or func by address pointer p. Optional var1 to varN variables of every SmallBASIC data type can be passed to function or sub, the address pointer points to. Example 1: CALL with a subroutine pointer sub MyPrint(i) print i end a = @MyPrint call a, "test" ' when using CALL for subroutines, ' please use CALL without brakets Example 2: CALL with a function pointer func Increment(i, b) return i + b end x = 1 a = @Increment y = call(a,x,2) ' when using CALL for functions, ' please use CALL with brakets print y Example 3: CALL with a subroutine pointer and BYREF: sub Increment(byref i, b) i = i + b end x = 1 a = @Increment call a,x,2 print x Example 4: Passing function pointer to a function func Increment(i) return i + 1 end func Decrement(i) return i - 1 end func MyFunc(f, i) return call(f,i) end a = @Increment b = @Decrement x = 2 x = MyFunc(a,x): print x x = MyFunc(b,x): print x +========================================================================================+ | 116. (Language) CASE | +========================================================================================+ CASE expr Branch condition for a SELECT statement. See SELECT for more information and examples. Example x = 1 ' Change to see what happens select case x case 1 print "x is 1" case 2,3,4 print "x is 2,3 or 4" case else print "x is not 1, 2, 3 or 4" end select +========================================================================================+ | 117. (Language) CATCH | +========================================================================================+ CATCH [var | expr] The CATCH statement is used to catch a run-time error. This is typically used with errors raised when calling a file system command that cannot be completed, for example attempting to open a non-existent file. The CATCH statement has two modes. You can supply a variable argument to store the error string. Alternatively you can supply an expression. When the raised error matches the (String) expression, the error will be caught. When using the expression mode, you can supply a succession of CATCH statements to handle various error messages separately. For more information see TRY. Example try ' DON'T use existing file for demo. open "try demo.tmp" for input as #1 catch err print err ' Some error handling could be implemented here ' i.e: if(err = "...") then ... end try print "This point is reach, even if opening the file was not possible" +========================================================================================+ | 118. (Language) CONST | +========================================================================================+ CONST name = expr Declare a variable name who’s value does not change during program execution. name follows the rules for naming SmallBASIC variables. expr is an expression consisting of literals, with or without operators, only. Example CONST G = 6.67259E-11 CONST PISQUARE = PI^2 +========================================================================================+ | 119. (Language) DECLARE | +========================================================================================+ DECLARE FUNC xxx Forward declare SUB or FUNC. Obsolete QB compatibility +========================================================================================+ | 120. (Language) DEF | +========================================================================================+ DEF name[(par1[,...])] = expression Defines a single line function with the function name name and the parameters par1 to parN. expression is a valid SmallBASIC expression returning a value. See FUNC for multiline functions and SUB for multiline subroutines. Example 1: Function with one parameter def f(x) = 2*x+3 print f(3) Example 2: Function with two parameters def f(x,y) = 2*x + 3*sin(y) print f(1,2) Example 3: Random number between low and high ' A function for random integer numbers between low and high (inclusive) DEF randi(lo, hi) = (RND * (hi - lo + 1))\1 + lo ' A function for random float numbers between low and high (inclusive) DEF randf(lo, hi) = (RND * (hi - lo + 1)) + lo print randi(0, 100) print randf(0, 100) Example 4: DEF and LOCAL ' DEF and LOCAL.bas SmallBASIC 0.12.2 [B+=MGA] 2016-04-06 'can I use DEF locally in a sub without interfering with main variable or DEF names def aboutMe() = "I am texting from main code." ? "Hi, ";aboutMe mySub ? "Goodbye, ";aboutMe pause sub mySub() 'local def aboutMe() = "I am texting from mySub." '<=== note: this did not work local aboutMe def aboutMe() = "I am texting from mySub." ? "Hi, ";aboutMe end +========================================================================================+ | 121. (Language) DO | +========================================================================================+ DO This keyword is used to declare single-line commands. It can be used with WHILE and FOR-family commands. Example 1 For i = 1 to 10 do print i Example 2 FOR f IN files("*.txt") DO PRINT f Example 3 While(i < 10) do i++ +========================================================================================+ | 122. (Language) ELIF | +========================================================================================+ ELIF Short for ELSEIF. Example 1 foo = 2 if foo == 1 print "one" ELIF foo == 2 print "two" fi Example 2: using IF … ELSE … IF instead of ELIF foo = 2 if foo == 1 print "one" else if foo == 2 print "two" fi fi +========================================================================================+ | 123. (Language) ELSE | +========================================================================================+ ELSE Part of an if … then … else statement. For more information see IF. Example foo = 2 if foo == 1 print "one" else print "not one" fi +========================================================================================+ | 124. (Language) ELSEIF | +========================================================================================+ ELSEIF Alternative condition in an IF statement. Example 1 foo = 2 if foo == 1 print "one" ELSEIF foo == 2 print "two" endif Example 2: using IF … ELSE … IF instead of ELSEIF foo = 2 if foo == 1 print "one" else if foo == 2 print "two" endif endif +========================================================================================+ | 125. (Language) END | +========================================================================================+ END Declares the END of a SUB, a FUNC or the program. Example 1: Sub sub MySub(a) print a + 10 end MySub(10) Example 2: Func func MyFunc(a) return a + 10 end Result = MyFunc(10) print Result Example 3: End of the program while(1) ii = ii + 1 print ii if(ii == 5) then end ' end program endif delay(500) wend +========================================================================================+ | 126. (Language) END TRY | +========================================================================================+ END TRY The END TRY statement marks the end of a TRY/CATCH block. For more information see TRY. Example try ' DON'T use existing file for demo. open "try demo.tmp" for input as #1 catch err print err ' Some error handling could be implemented here ' i.e: if(err = "...") then ... end try print "This point is reach, even if opening the file was not possible" +========================================================================================+ | 127. (Language) ENDIF | +========================================================================================+ ENDIF ENDIF ends an if statement. For more information see IF. Example foo = 1 if foo == 1 then print "one" endif +========================================================================================+ | 128. (Language) EQV | +========================================================================================+ a EQV b Bitwise equivalence. Truth table: a b a EQV b --- --- --------- 0 0 1 0 1 0 1 0 0 1 1 1 Example 1: Print truth table print "0 eqv 0 = " + bin(0 eqv 0) print "0 eqv 1 = " + bin(0 eqv 1) print "1 eqv 0 = " + bin(1 eqv 0) print "1 eqv 1 = " + bin(1 eqv 1) Example 2: Bitwise equivalence of two numbers a = 0b110010011111000010101011 b = 0b101010010101011100010101 print " " + bin(a) print "EQV " + bin(b) print "----------------------------" print " " + bin(a eqv b) ' Output: ' ' 110010011111000010101011 ' EQV 101010010101011100010101 ' ---------------------------- ' 100111110101100001000001 +========================================================================================+ | 129. (Language) EXIT | +========================================================================================+ EXIT [FOR|LOOP|SUB|FUNC] Exits a multi line function definition, a loop, or a subprogram. By default (if no parameter is specified) exits from last command block (loop, for-loop or routine). - FOR - Exit from the last FOR-NEXT loop - LOOP - Exit from the last WHILE-WEND or REPEAT-UNTIL loop - SUB - Return from the current routine - FUNC - Return from the current function Example 1: for for i = 1 to 100 print i exit for next ' Output: 1 Example 2: while while(i) i++ print i exit loop wend ' Output: 1 Example 3: sub sub MySub(a) exit sub print a end MySub(10) ' No output, because print in MySub will not be reached Example 4: func func MyFunc(a) exit func return a + 10 end print MyFunc(10) ' Output: 0, because return command in MyFunc will not be reached +========================================================================================+ | 130. (Language) FALSE | +========================================================================================+ FALSE Boolean FALSE. Example 1: Assign FALSE to a variable a = true b = false print a ' output: 1 print b ' output: 0 Example 2: Use in a while loop IsRunning = true while(IsRunning) i++ print i if(i == 5) then IsRunning = false wend 'Output: 1 2 3 4 5 Example 3: Use in a if statement ButtonPressed = false ' replace false with true if(ButtonPressed) then print "Button was pressed" +========================================================================================+ | 131. (Language) FI | +========================================================================================+ FI FI ends an if statement. Same as ENDIF. For more information see IF. Example foo = 1 if foo == 1 then print "one" fi +========================================================================================+ | 132. (Language) FOR | +========================================================================================+ FOR expr FOR element IN array (or map) … NEXT Defines a FOR/NEXT loop. - counter - A numeric variable to be used as the loop counter. - start - A numeric expression; the starting value of counter. - end - A numeric expression; the ending value of counter. - incr - A numeric expression; the value by which counter is incremented or decremented with each iteration of the loop. The default value is 1. - element - A variable to be used as the copy of the current element. - array - An array or map variable FOR counter = start TO end [STEP incr] … NEXT SmallBASIC begins processing of the FOR/NEXT block by setting counter equal to start. Then, if ‘incr’ is positive and counter is not greater than end, the commands between the FOR and the NEXT are executed. When the NEXT is encountered, counter is increased by ‘incr’, and the process is repeated. Execution passes to the command following the NEXT if counter is greater than end. If increment is negative, execution of the FOR/NEXT loop is terminated whenever counter becomes less than end. FOR/NEXT loops may be nested to any level of complexity, but there must be a NEXT for each FOR. FOR element IN array … NEXT The commands-block will be repeated for LEN(array) times. Each time the ‘element’ will holds the value of the current element of the array. FOR/NEXT loops may be nested to any level of complexity, but there must be a NEXT for each FOR. Example 1 for i = 1 to 9 print i next ' Output 1 2 3 4 5 6 7 8 9 Example 2 for i = 1 to 9 Step 2 print i next ' Output: 1 3 5 7 9 Example 3 for i = 9 to 1 Step -1 print i next ' Output 9 8 7 6 5 4 3 2 1 Example 4 a = [12, 6, 23, -4] for i in a print i next ' Output 12 6 23 -4 Example 5 a = ["car", "tree", "house"] for i in a print i next ' Output car tree house Example 6 a = {x:1, s:"test1"} b = {x:2, s:"test2"} c = {x:3, s:"test3"} MapVar = [a,b,c] for i in MapVar print i.x, i.s next ' Output: 1 test1 ' 2 test2 ' 3 test3 Example 7 a = {x:1, y:2, s:"test1"} for i in a print i + " = " + a(i) next ' Output: y = 2 ' x = 1 ' s = test1 Example 8: Changing counter inside the loop for i = 1 to 10 i = i + 1 print i next ' Output: 2 4 6 8 10 Example 8: Changing stop parameter inside the loop e = 10 for i = 1 to e e = 5 print i next ' Output: 1 2 3 4 5 +========================================================================================+ | 133. (Language) FUNC | +========================================================================================+ FUNC foo (a, b) Declares a function. Return a value by assigning a variable with the same name as the function or by using RETURN. Example 1: ' Main program print MyAddFunction(10,20) ' Function definition FUNC MyAddFunction(a,b) local c 'c is just known inside this function c = a + b MyAddFunction = c END Example 2: Using return ' Main program print MyAddFunction(10,20) ' Function definition FUNC MyAddFunction(a,b) local c 'c is just known inside this function c = a + b return c END +========================================================================================+ | 134. (Language) GOSUB | +========================================================================================+ GOSUB label Causes program execution to branch to the specified label; when the RETURN command is encountered, execution branches to the command immediately following the most recent GOSUB command. GOSUB should be used with caution. Using subroutines is more versatile and much easier to read. See ON for ON n GOSUB Label1 for branching depending on a number n. Example 1: Using GOSUB while(ii < 20) gosub Inc wend end ' ends the program label Inc ii++ print ii return Example 2: Same as example 1, but using a subroutine instead of GOSUB while(ii < 20) Inc() wend sub Inc() ii++ print ii end +========================================================================================+ | 135. (Language) GOTO | +========================================================================================+ GOTO label Causes program execution to branch to a specified position (label). GOTO is known to create “spaghetti code”, i.e. winding code which is hard to follow, to understand, and to maintain. IF…THEN, SELELCT CASE, SUB, FUNC and DEF are much better ways to write branching code. See ON for ON n GOTO Label1 for branching depending on a number n. Example 1 label FirstLine ii++ print ii if(ii == 10) then goto LastLine goto FirstLine label LastLine Example 2 randomize While True x = Rnd tries++ While True If x < 0.05 Then Print "x < 0.05 (after "; tries; " tries)." Goto exitLoops ' here we exit all loops unconditionally. Elif tries = 10 Then Print "missed! (after "; tries; " tries)." Goto exitLoops ' here we exit all loops unconditionally. Else Exit Loop ' here we exit only the inner WHILE loop Fi Wend Wend Label exitLoops Print Print "Out of loops now." +========================================================================================+ | 136. (Language) IF | +========================================================================================+ IF expr Tests the expression and if it evaluates to a non-zero value, program flow will resume after the following THEN statement. Block-style IF IF expression1 [THEN] . . [commands] . [ [ELSEIF| ELIF] expression2 [THEN] . . [commands] . ] [ELSE . . [commands] . ] ENDIF| FI Causes SmallBASIC to make a decision based on the value of an expression. - expression - An expression; 0 is equivalent to FALSE, while all other values are equivalent to TRUE. - commands - One or more commands. Each expression in the IF/ELSEIF construct is tested in order. As soon as an expression is found to be TRUE, then its corresponding commands are executed. If no expressions are TRUE, then the commands following the ELSE keyword are executed. If ELSE is not specified, then execution continues with the command following the ENDIF. IF, ELSE, ELSEIF, and ENDIF must all be the first keywords on their respective lines. THEN is optional, but if its defined it must be the last keyword on its line; if anything other than a comment follows on the same line with THEN, BASIC thinks it’s reading a single-line IF/THEN/ELSE construct. IF blocks may be nested. Single-line IF IF expression THEN [num-label]|[command] [ELSE [num-label]|[command]] Causes SmallBASIC to make a decision based on the value of an expression. - expression - An expression; 0 is equivalent to FALSE, while all other values are equivalent to TRUE. - command - Any legal command or a numeric label. If a number is specified, it is equivalent to a GOTO command with the specified numeric-label. Example 1: Block-style IF x = 1 IF x = 1 THEN PRINT "true" ELSE PRINT "false" ENDIF ' Alternate syntax: x = 1 IF x = 1 PRINT "true" ELSE PRINT "false" FI Example 2: Single-line IF x = 1 IF x = 1 THEN PRINT "true" ELSE PRINT "false" IF x = 1 THEN 1000 end ' ends the program 1000 PRINT "true" Example 3: Nested IF x = 1 y = 2 IF x == 1 THEN PRINT "x equals 1" if y == 2 THEN PRINT "y equals 2" ELSE PRINT "y not 2" ENDIF ELSE PRINT "x not 1" ENDIF Example 4: IF … ELSEIF … ELSE foo = 1 ' change value to 1,2,3 IF foo == 1 PRINT "one" ELSEIF foo == 2 PRINT "two" ELSE PRINT "something else" ENDIF +========================================================================================+ | 137. (Language) IFF | +========================================================================================+ IFF expr Inline version of IF. Example 1 animal = "cat" fur = IFF( animal == "cat", "yes", "no") print fur Example 2 Eq = "sin" x = 5 ans = iff(Eq == "sin", sin(x), cos(x)) print ans ' Alternative syntax: if(Eq == "sin") then ans = sin(x) else ans = cos(x) endif print ans Example 3 x = 4 ans = iff(x <= 5, 0, 10) print ans +========================================================================================+ | 138. (Language) IMP | +========================================================================================+ a IMP b Perform a logical implication on two expressions. IMP is equivalent to (NOT a) OR b. Truth table a b a IMP b --- --- --------- 0 0 1 0 1 1 1 0 0 1 1 1 Example 1 print "Truth table" print print "0 IMP 0 = "; 0 IMP 0 print "0 IMP 1 = "; 0 IMP 1 print "1 IMP 0 = "; 1 IMP 0 print "1 IMP 1 = "; 1 IMP 1 Example 2 a = 0b10011101 b = 0b11010011 print " "; bin(a) print "IMP "; bin(b) print "------------" print " "; bin(a IMP b) ' output: ' 10011101 ' IMP 11010011 ' ------------ ' 11110011 +========================================================================================+ | 139. (Language) IN | +========================================================================================+ a IN b - b is an array: Returns the index (1 based) of the first matching element. If no matching element, IN returns FALSE. - b is a string: Returns TRUE if the value is contained within b. - for loop: FOR i IN array will cycle through all elements of array, i contains the element. Example 1: array print 1 in [-2,-1,1,2] ' Output 3 print "b" in ["a", "b", "c", "d"] ' Output 2 Example 2: string print "a" in "car" ' Output 1 print "ar" in "car" ' Output 1 print "d" in "car" ' Output 0 Example 3: for loop a = [4,8,2,3,9] for i in a print i next 'Output 4 8 2 3 9 a = ["duck", "dog", "cat"] for i in a print i next ' Output duck dog cat Example 4: Count files myFiles = FILES("*") for fl IN myFiles if ".bas" IN fl then NumBasFiles++ if ".txt" IN fl then NumTxtFiles++ next print "Number of .bas files: " + NumBasFiles print "Number of .txt files: " + NumTxtFiles Example 5 ' IN keyword is 1-Based, so using "Option Base 1" makes code more consistent: Option Base 1 Def q(text) = " " + Enclose(text) + " " ' Enclose text with quotation marks, "" Def rev(text) = Cat(3) + text + Cat(-3) ' reverse colors of text Sub title(text) Color 14: Print text: Color 7 ' print title in color End Sub title "Use IN to check if sub-string exists within string (see also INSTR):" s = "Hello 5" ? rev(" s =" + q(s)) ? " "; q("ll") + "In s? "; "ll" In s,, ' (0=FALSE; 1=TRUE) ? " "; q("LL") + "In s? "; "LL" In s ? " "; q("l") + " In s? "; "l" In s,, ? " 5 In s? "; 5 In s title "Use IN to return the index of matching element in array (1-Based):" Dim a() a << "Hello" ' append (<<) three elements to a array a << "World" a << 123 'a << [4,"x",6] ' nested array conflicts with the other types. ? rev(" a = " + Str(a) + " ") ? " "; q("Hello") + "In a: "; "Hello" In a,, ? " "; q("ello") + " In a: "; "ello" In a ? " "; q("HELLO") + "In a: "; "HELLO" In a,, ? " "; q("World") + "In a: "; "World" In a ? " 123 In a: "; 123 In a,, ? " 12 In a: "; 12 In a '? "[4,\\"x\\",6] In a: "; [4,"x",6] In a ' (nested array) title "Use IN to flatten multi-dimension array:" a = [1, 2, 3; 4, 5, 6; 7, 8, 9, 10, 11; "Hello", "World"] ? rev(" a = " + Str(a) + " ") ? " "; For i In a ? i; ", "; ' i is used as pointer to a array element inside FOR loop Next ? title "Use IN to print nested arrays:" a = [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10, 11], ["Hello", "World"]] ? rev(" a = " + Str(a) + " ") ? " "; For i In a ? i; ", "; ' i is used as pointer to a(i) inside FOR loop Next ? title "Use IN to print map array:" a = Array("{x:100, y:300, point:Top-Left}") ? rev(" a = " + Str(a) + " ") ? " "; For i In a ? i; ":"; a(i); ", "; ' i is used as pointer inside FOR loop Next ? title "Use IN to test equality of numbers:" n = 10.5 ? rev(" n = 10.5 ") ? " n In 10 : "; n In 10 ' (0=FALSE; 1=TRUE) ? " n In 10.5 : "; n In 10.5 +========================================================================================+ | 140. (Language) LABEL | +========================================================================================+ LABEL name Defines a label with name LabelName. A label marks a position in the code. Use GOTO or GOSUB to continue program execution at that label. Example label FirstLine ii++ print ii if(ii == 10) then goto LastLine goto FirstLine label LastLine +========================================================================================+ | 141. (Language) LET | +========================================================================================+ LET var=expr Assigns a value or expression expr to the variable var. LET is used mainly for compatibility reasons and not necessary for programming in SmallBASIC. Example LET x = 4 +========================================================================================+ | 142. (Language) LIKE | +========================================================================================+ a LIKE b Regular-expression operator. Compares the left part a of the expression with the right side regex pattern b and returns true or false. - * matches any sequence of characters (zero or more) - ? matches any character - [SET] matches any character in the specified set - [!SET] or [^SET] matches any character not in the specified set A set is composed of characters or ranges. A range is defined by character - hyphen - character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of characters allowed in the [..] pattern construct. To suppress the special syntactic significance of any of "[]*?!^-\, and match the character exactly, precede it with a \\. For more information about regular-expressions please see http://www.regular-expressions.info/examples.html. Option for matching algorithm OPTION MATCH PCRE [CASELESS]|SIMPLE PCRE sets as default matching algorithm to (P)erl-(C)ompatible (R)egular (E)xpressions library or back to simple one with SIMPLE. Example 1 print "Hello" LIKE "*[oO]" ' Output 1 print "Hello" LIKE "He??o" ' Output 1 print "Hello" LIKE "hello" ' Output 0 print "Hello" LIKE "[Hh]*" ' Output 1 print "-[Hello]-" Like "\\-\\[?*\\]\\-" ' Output 1 +========================================================================================+ | 143. (Language) LOCAL | +========================================================================================+ LOCAL Declare local variables inside a SUB or FUNC. Local variables are independent of global variables of the same name. If inside a sub or a function a local variable with the same name as an already existing global variabale is declared, the global variable can’t be accessed inside that function or sub. Changing the local varibale will not change the global variable. Local variables no longer exist once the SUB or FUNC has returned. Use local variables insides subs or functions to make sure, that global variables with the same names are not accidentally changed. Example: A = 1 ' global variable print "Global variable before sub: A="; A MySub() print "Global variable after sub : A="; A sub MySub() local A ' Comment this line to see the effect of a local variable A = 2 print "Local variable inside sub : A="; A end +========================================================================================+ | 144. (Language) LSHIFT | +========================================================================================+ result = LSHIFT number, amount Performs a bitwise operation that shifts all the bits of x to the left by an amount of n. Example 1: print 1 lshift 2 ' Output 4 Example 2: x = 1 print bin(x) ' Output: 1 print bin(x lshift 1) ' Output: 10 print bin(x lshift 2) ' Output: 100 print bin(x lshift 3) ' Output: 1000 +========================================================================================+ | 145. (Language) MDL | +========================================================================================+ MDL Returns the modulus. The difference to MOD and % is, that MDL works also with float numbers instead of only integers. Example print 2.3 MDL 1 ' Output: 0.3 +========================================================================================+ | 146. (Language) MOD | +========================================================================================+ a MOD b Calculates the Modulus. Returns the remainder of a/b as integer. Equivalent syntax to % and MDL. Example 1 print 5 mod 2 ' Output 1 print 12 mod 5 ' Output 2 Example 2: ASCII table ' LOCATE MOD CHR ASC.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-23 ' ' LOCATE row, column : sets the next print location on screen, rows down, columns across ' a MOD b : returns the remainder of a/b as integer ' CHR : returns the CHaRracter for the ASC number ' for demo we will print a chart of CHR for ASC numbers 32-128 ' ASC(Character) : is a number code for a print characters, 32 is the code for a space ' ? : is shortcut for PRINT ' RIGHT(string,n) : returns right most n characters of string ' STR(n) : returns a number in string form ' : : code statement seperator often used with LOCATE row, column : ? string LOCATE 1,16 : PRINT "ASC Table 30-129:" ' locate print spot, print title for our app FOR column = 0 to 9 ' print a header, 10 numbers plus + (to add to row value) LOCATE 2, column * 5 + 4 : PRINT "+"; column NEXT FOR row = 3 to 12 LOCATE row, 0 : ? RIGHT(" " + STR(row * 10) + ":", 4) NEXT 'main table FOR ASCnumber = 30 to 129 ' note ASC(32) = space so wont see anything in Table row = ASCnumber \ 10 ' \ rounds division down to integer column = (ASCnumber MOD 10) * 5 + 5 ' times 5 to space out the characters printed plus 5 for column labels LOCATE row, column : ? CHR(ASCnumber) NEXT Example 2: Prime or lowest divisor table ' more MOD.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-23 ' ' n MOD m - returns the remainder of n divided by m, if 0 then m divides n perfectly ' another way to do MOD in SmallBASIC is to use symbol %, n%m is same as n MOD m ' MOD is great to tell if a number is divisible by another (leaves no remainders) ' a number not divisible by any number less to it other than 1, is called a prime number ' here we will list first 100 numbers and tell if prime or give the lowest divisor 'table setup: title header and row labels LOCATE 0,0 : PRINT "P=Prime or Lowest Divisor Table" FOR column = 0 to 9 ' print a header, 10 numbers plus + (to add to row value) LOCATE 2, column * 2 + 7 : PRINT "+"; column NEXT FOR row=3 to 12 LOCATE row, 0 : PRINT RIGHT(" "+STR(row * 10 - 30) + ":", 6) NEXT 'main table data FOR n= 1 to 99 IF n = 1 THEN report = " O" ' one is one, neither prime nor not prime ELSE report = " P" ' letter code for Prime FOR i = 2 TO n - 1 IF n % i = 0 THEN ' <== if n MOD i=0 or n%i=0, THEN i divides n perfectly report = " " + STR(i) EXIT ' we found lowest divisor get out of loop END IF NEXT ENDIF row = n \ 10 + 3 ' n\10 is our number divided by 10 and rounded down, ' call it the tens row offset 3 rows down for title and header and blank line column = n % 10 * 2 + 7 ' <== use MOD to LOCATE the column (*2 column width + 7 row label offset) LOCATE row, column : ? report ' ? short for print NEXT ?:? "O=one is neither prime nor not prime" ' ?:?"..." print blank line first +========================================================================================+ | 147. (Language) NAND | +========================================================================================+ a NAND b Bitwise exclusive NOT AND. Truth table: a b a NAND b --- --- ---------- 0 0 1 0 1 1 1 0 1 1 1 0 Example 1 The NOT-operation as part of NAND performs a bitwise inversion on all bits of a number. This leads to the following (maybe unexpected) result: print 1 NAND 1 ' Output: 11111111111111111111111111111110 Example 2: Operate NAND only on last n bits If you want to operate NAND only on the last n bits of the numbers, you can use the following code: n = 4 a = 0b1101 b = 0b1001 print bin((a NAND b) BAND ((1 lshift n ) - 1)) ' Output 110 Example 3: Two’s complement Two’s complement is a mathematical operation to reversibly convert a positive binary number into a negative binary number with equivalent negative value. (Wikipedia) ' Two's complement is the standard way of representing negative integers in binary. ' The sign is changed by inverting all of the bits and adding one. Def invsgn(n) = ((n Nand n) + 1) - Frac(n) ' invert the sign of n While True Do Input "Enter a number (Enter empty to stop) : ", n If Isstring(n) Then Stop Endif Print "This is the number with inverted sign: "; invsgn(n) Print Wend +========================================================================================+ | 148. (Language) NEXT | +========================================================================================+ NEXT Ends the code block of a FOR … NEXT loop. See FOR for more information. Example for i = 1 to 5 print i next +========================================================================================+ | 149. (Language) NOR | +========================================================================================+ a NOR b Bitwise NOT OR. Truth table: a b a NOR b --- --- --------- 0 0 1 0 1 0 1 0 0 1 1 0 Example 1 The NOT-operation as part of NOR performs a bitwise inversion on all bits of a number. This leads to the following (maybe unexpected) result: print 1 NOR 1 ' Output: 11111111111111111111111111111110 Example 2: Operate NOR only on last n bits If you want to operate NOR only on the last n bits of the numbers, you can use the following code: n = 4 a = 0b1010 b = 0b1000 print bin((a NOR b) BAND ((1 lshift n ) - 1)) ' Output 101 Example 3: Set a bit Def Bnot(n) = n Nor n ' Bnot inverts all bits in n (it's very useful for inverting a mask). Def mask(i) = Pow(2, i) ' return a mask of only bit-i set (base 0) Def set_bit(n, i) = n Bor mask(i) ' set bit-i in n (base 0) Def reset_bit(n, i) = n Band Bnot(mask(i)) ' reset bit-i in n (base 0) Def get_bit(n, i) = (n Band mask(i)) <> 0 ' return bit-i status: 0 or 1 Color 15,0 cls Print "* Set/Reset bit is useful for storing boolean data efficiently." Print "* The rightmost bit of binary number is bit-0, then bit-1, etc." Print "* This SB version supports "; Len(Bin(0)); " bits binary numbers." Print While True Do Color 15,0 Input " Enter a number (Enter empty to stop): ", n If isstring(n) Then Stop Endif Print Color 14, 0: Print " In Binary is: "; Bin(n) Color 7, 0: Print " Bit-3 status: "; get_bit(n, 3) If get_bit(n, 3) Then Color 11, 0: Print " Reset bit-3: "; Bin(reset_bit(n, 3)) Else Color 15, 0: Print " Set bit-3: "; Bin(set_bit(n, 3)) Endif Print Wend +========================================================================================+ | 150. (Language) NOT | +========================================================================================+ a NOT b Logical operator to invert variable or expression result. Equivalent syntax to y = !a. NOT returns true if variable or expression result is false or zero. Otherwise it returns false. For bitwise NOT use the ~ operator. Example 1: print not true ' Output: 0 print not 100 ' Output: 0 print not false ' Output: 1 print not 0 ' Output: 1 Example 2: NOT in an if statement IsRunning = false ' Replace with true if(NOT IsRunning) then print "Program is not running" a = 0 ' Replace i.e. 10 if(NOT a) then print "Value is zero" Example 3: Bitwise NOT using ~ The NOT-operation performs a bitwise inversion on all bits of a number. This leads to the following (maybe unexpected) result: print bin(~0b1001) ' Output: 11111111111111111111111111110110 Example 4: Operate bitwise NOT only on last n bits If you want to operate NOT only on the last n bits of the numbers, you can use the following code: n = 4 a = 0b1010 print bin((~a) BAND ((1 lshift n ) - 1)) ' Output 101 +========================================================================================+ | 151. (Language) ON | +========================================================================================+ ON GOTO|GOSUB label1 [, ..., labelN] Causes a branch of the program to one of the labels label1 to labelN. n defines the number of the label. If n = 1 the first label is used; with n = N the Nth label is used. n must be in the range 0 to 255. Example 1: ON … GOTO n = 1 ' Change to 1,2,3 or other value ON n GOTO label1, label2, label3 print "Nothing happend" end label label1 print "Goto label 1" end label label2 print "Goto label 2" end label label3 print "Goto label 3" end Example 2: ON … GOSUB n = 1 ' Change to 1,2,3 or other value ON n GOSUB label1, label2, label3 print "After GOSUB" end label label1 print "Gosub label 1" return label label2 print "Gosub label 2" return label label3 print "Gosub label 3" return +========================================================================================+ | 152. (Language) OR | +========================================================================================+ a OR b Logical OR. Right side is not evaluated if left side evaluates to True. Truth table: a b a OR b --- --- -------- 0 0 0 0 1 1 1 0 1 1 1 1 See BOR for bitwise OR. Example: a = 1 ' Change value to 1,2 or other if (a == 1) OR (a == 2) then print "a is 1 or 2" endif +========================================================================================+ | 153. (Language) REM | +========================================================================================+ REM comment Code comments. Comments can also be introduced using #, single quote character '. The # character can only be used as remarks if it is the first character of the line. Example 1: ' That text-line is just a few remarks REM another comment # one more comment Example 2: ' Although the code is very short (less then thousands of lines...), it's ' almost impossible to decode it... - That's why comments are so useful: ' to remind *yourself* and others what you did and why. ' Let's try to analyze "Curlie borealis.bas" code and add few comments to it: ' --- Start of "Curlie borealis.bas" + Comments: ' Initialize variables for the main loop: Randomize ' - I'm not sure why do we need it here... (MGA?) ff = 440.03 ' Factor for defining x,y location to draw point maxi = 25000 ' Maximum points to draw in each shape maxi2 = maxi \ 2 ' Factor for defining two different color schemes in shape b = Rgb(40, 20, 30) ' Background color Color 0, b Cls ' Run program in an endless loop (Press Ctrl+B or Ctrl+C to stop): While 1 ff += 9.444 ' Move the next shape to different x,y location ' Draw a single shape using two color schemes, or draw an invisible shape: For i = 0 To maxi ' Define location (x,y) to draw a single point: f += ff x = Min(xmax, -x + Cos(f * i)) ' (MIN makes sure location is within screen) y = Min(ymax, -y + Sin(f * i)) ' Define nice color to draw a point: If cc Mod 6 = 0 Then If i < maxi2 Then ' One color scheme c = Rgb(255 - 255 * i \ maxi2, 255 * i \ maxi2, 0) Else ' Second color scheme c = Rgb(0, 255 - 255 * (i - maxi2) \ maxi2, 255 * (i - maxi2) \ maxi2) Fi Else c = b ' Use background color to draw invisible shape Fi ' Draw a single point (pixel): Pset x, y, c If i Mod 5000 = 0 Then Showpage ' Update screen each 5000 points (smoother) Next cc++ ' Counter for drawing invisible shape (using background color) Wend ' --- End of "Curlie borealis.bas" + Comments ' To sum up: ' Whether you write a short program or long, comments will help you ' and others to understand, debug and improve your program later on; i.e. ' comments make your code useful! REM "Curlie borealis.bas" code example taken from: REM http://smallbasic.sourceforge.net/?q=comment/1184#comment-1184 REM Without explicit permission from MGA... +========================================================================================+ | 154. (Language) REPEAT | +========================================================================================+ REPEAT ... UNTIL expr Begins the definition of a REPEAT/UNTIL loop. SmallBASIC starts executing the commands between the REPEAT and UNTIL commands. When SmallBASIC encounters the UNTIL command, it evaluates the expression parameter expr. If that parameter is zero (false), the process will be repeated; otherwise, execution continues at the next command. The REPEAT/UNTIL loop evaluates the expression at the end of the loop. Therefore at least one loop is performed. REPEAT/UNTIL loops may be nested to any level of complexity, but there must be an UNTIL for each REPEAT. See WHILE…WEND loop if you want to evaluate the expression at the begin of the loop. Example C = 1 REPEAT PRINT C C = C + 1 UNTIL C == 10 ' Output: 1 2 3 4 5 6 7 8 9 +========================================================================================+ | 155. (Language) RETURN | +========================================================================================+ RETURN RETURN {var|expr} When used with GOSUB: Execution of the program branches to the command immediately following the most recent GOSUB command. RETURN is used without var or expr. When used with FUNC: Set the return value of a function to the value var or the result of the expression expr. Example 1: GOSUB GOSUB my_routine PRINT "RETURN sent me here" END LABEL my_routine PRINT "I am in my routine" RETURN Example 2: Function Result = MyAddFunction(10, 20) print Result func MyAddFunction(a, b) return a + b end +========================================================================================+ | 156. (Language) RSHIFT | +========================================================================================+ result = RSHIFT number, amount Performs a bitwise operation that shifts all the bits of x to the right by an amount of n. Example n = 0b1100 rshift 2 print bin(n) ' Output: 11 n = 0b1100 rshift 3 print bin(n) ' Output: 1 +========================================================================================+ | 157. (Language) SELECT | +========================================================================================+ SELECT CASE expr Perform multiple tests on the expression expr. Offers a more concise syntax to writing successive IF tests. Once a case statement is fullfilled the select-case structure will be exited and all following case statements will not be tested anymore. See also IF … THEN … ELIF … ELSE … FI structure. Example 1: Basic select-case expression x = 12 ' Change value to see what happens select case x case 12 print "x is 12" case 13,14,15 print "x is 13,14,or 15" case else print "x is not 12,13,14,15" end select Example 2: Exit of a select structure once a test was successful x = 2 select case x case 2 print "x is 2" case 2 print "This will never be printed" end select Example 3: Use IFF to check a range x = 4 ' Change value to see what happens select case x case iff(x <= 4, x, x + 1) print "x <= 4" case iff(x > 4 AND x < 12, x, x + 1) print "4 < x < 12" end select Example 4: Using functions func even(x) local r if(x mod 2 == 0 AND x != 0) r = x else r = x + 1 endif return r end func uneven(x) local r if(x mod 2 != 0) r = x else r = x + 1 endif return r end x = 2 ' Change value to see what happens select case x case even(x) print "x is even" case uneven(x) print "x is uneven" case else print "x is 0" end select +========================================================================================+ | 158. (Language) STEP | +========================================================================================+ FOR t = 1 TO 10 STEP 2 Specifies the loop counter increment s in a FOR loop. The variable i will be increased in every loop by amount s. s can be a positive or negative number. See FOR for more information. Example 1: Positive step for t = 1 to 10 step 2 print t next ' Output: 1 3 5 7 9 Example 2: Negative step for t = 10 to 1 step -2 print t next ' Output: 10 8 6 4 2 +========================================================================================+ | 159. (Language) STOP | +========================================================================================+ STOP [error] Terminates execution of a program, closes all files opened by the program, and returns control to the operating system. The optional number error will be returned to the operating system; if not specified SmallBASIC returns 0. On Windows, the error value is known as ERRORLEVEL. Example 1 print "Hello world" stop print "This will never be printed" Example 2 print "Type exit to stop program" while (true) input "INPUT: ", s if(s == "exit") then stop print "You typed: ";s wend +========================================================================================+ | 160. (Language) SUB | +========================================================================================+ SUB foo (a, b) Declare a sub procedure foo. The optional parameters var1 to varN can be all data types supported by SmallBASIC. Sub procedures do not return a value but can return argument values when declared as BYREF. A sub procedure ends with the keywords END or END SUB. The keyword LOCAL can be used to restrict the scope of a variable to the sub procedure only. Sub procedures can be nested within a sub procedure. With SUB (and FUNC) you can divide your program into many logical, independent and reusable blocks, instead of writing a long “spaghetti code”. Instead of using GOSUB and GOTO you should prefere to use sub procedures or functions. For more information, see FUNC, LOCAL and BYREF. Example 1: Passing x by value (default) x = 9 routine1(x) ' Output: 9 Sub routine1(x) Print x End Example 2: Passing x by reference (BYREF x) x = 9 Print x ' Output: 9 routine2(x) ' Output: 9 Print x ' Output: 10 Sub routine2(Byref x) Print x x = 10 End Example 3: Passing x by reference (@x) x = 9 Print x ' Output: 9 routine3(x) ' Output: 9 Print x ' Output: 10 Sub routine3(@x) Print x x = 10 End Example 4: Use the LOCAL keyword for local variables x = 9 routine4(x) ' Output: 9 Print x ' Output: 9 Sub routine4(y) Local x Print y x = 12 ' x is local, the global variable x will not be changed End Sub Example 5: Nested sub procedures x = 9 routine5(x) ' Output: 100 (Passing 'x' by value to nested procedures) Print x ' Output: 9 Sub routine5(x) local x x = 100 routine6(x) Sub routine6(x) Print x End Sub End Sub +========================================================================================+ | 161. (Language) THEN | +========================================================================================+ THEN part of an if-statement. For more information see IF. Example 1: Multi-line block a = 1 if(a == 1) then print "one" endif Example 2: Single-line a = 1 if(a == 1) then print "one" +========================================================================================+ | 162. (Language) THROW | +========================================================================================+ THROW [info [, ...]] The THROW command is used to initiate a catch-able error. If there is no surrounding TRY/CATCH block, THROW can be used to abort the program. Optional a string info can be used to create an error message. Example 1: Abort a program throw("Error") Example 2: Initial a catch-able error try a = 1 if(a == 1) then throw("a == 1") if(a == 2) then throw("a == 2") catch err print "Error: "; err end try +========================================================================================+ | 163. (Language) TO | +========================================================================================+ FOR t = 1 TO 10 Specifies the loop counter end in a FOR loop. For more information see FOR. Example for t = 1 to 10 print t next +========================================================================================+ | 164. (Language) TRUE | +========================================================================================+ TRUE Boolean TRUE. Example 1: Assign TRUE to a variable a = true b = false print a ' Output: 1 print b ' Output: 0 Example 2: Use in a while loop IsRunning = true while(IsRunning) i++ print i if(i == 5) then IsRunning = false wend ' Output: 1 2 3 4 5 Example 3: Use in a if statement ButtonPressed = true ' replace true with false if(ButtonPressed) then print "Button was pressed" +========================================================================================+ | 165. (Language) TRY | +========================================================================================+ TRY The TRY statement introduces a TRY/CATCH block. A try/catch block consist of the following structure: TRY The TRY statement starts a block of commands which might create a run-time error. CATCH [var | expr] The CATCH statement is used to catch a run-time error of one of the commands in the try-block. This is typically used with errors raised when calling a file system command that cannot be completed, for example attempting to open a non-existent file. The CATCH statement has two modes. You can supply a variable argument to store the error string. Alternatively you can supply an expression. When the raised error matches the (String) expression, the error will be caught. When using the expression mode, you can supply a succession of CATCH statements to handle various error messages separately. END TRY The END TRY statement marks the end of a TRY/CATCH block. Example 1: Opening a non-existing file for reading try ' DON'T use existing file for demo. open "try demo.tmp" for input as #1 catch err print err ' Some error handling could be implemented here ' i.e: if(err = "...") then ... end try print "This point is reach, even if opening the file was not possible" Example 2: Open COM-Port try open "com2000:" AS #1 catch err print "open failed: ";err end try Example 3: Using error expressions try ' DON'T use existing file for demo. open "demo.tmp" for input as #1 ' Replace "demo.tmp" by "?.tmp" catch "FS(2): NO SUCH FILE OR DIRECTORY" print "File not found" ' Some error handling could be implemented here goto aftertrycatch catch "FS(22): INVALID ARGUMENT" print "Filename not allowed" ' Some error handling could be implemented here end try label aftertrycatch print "end of program" Example 4: Advanced error handling for opening files ' See also: Home -- Articles -- TRY / CATCH Const FILE_NAME = "try demo.tmp" ' -- DON'T use existing file for demo. ' OPEN file or device safely: Func opens(filename, mode) Local fn = Freefile Try Select Case Lcase(mode) Case "input" : Open filename For Input As #fn Case "output": Open filename For Output As #fn Case "append": Open filename For Append As #fn Case Else: ? "opens(): Bad open mode at line " + Progline: Stop End Select opens = fn ' file opened, return file-handle (integer 1 to 256) Catch err ? err; " "; opens = 0 ' cannot open file, return 0 (FALSE) End Try End Func ' helper for demo: Func demo(demo_number, open_mode) Local fn Color 14 ?: ? Using " Demo #: "; demo_number; Color 7 fn = opens(FILE_NAME, open_mode) ' Open file safely If fn Then ? "File-handle is: "; fn; " "; demo = fn ' return file-handle or 0 if error. End Func Kill FILE_NAME ' delete file before demo fn = demo(1, "INPUT") If fn Then Close #fn fn = demo(2, "OUTPUT") If fn Then ? #fn, "Demo 2 Works!" Close #fn Fi fn = demo(3, "APPEND") If fn Then ? #fn, "Demo 3 Works!" Close #fn Fi fn = demo(4, "APPEND") If fn Then lines = ["Demo 4 Works!"] Tsave #fn, lines Close #fn Fi fn = demo(5, "INPUT") If fn Then Tload #fn, lines ? lines; Close #fn Fi fn = demo(6, "INPUTX") If fn Then Tload #fn, lines ? lines; Close #fn Fi +========================================================================================+ | 166. (Language) UNTIL | +========================================================================================+ UNTIL Ends a REPEAT … UNTIL loop. See REPEAT for more information. Example C = 1 REPEAT PRINT C C = C + 1 UNTIL C == 10 ' Output: 1 2 3 4 5 6 7 8 9 +========================================================================================+ | 167. (Language) USE | +========================================================================================+ USE Used with various commands for passing a user-defined expression expr. Example: Split s = "/etc/temp/filename1.ext " ' additional spaces at the end of the string SPLIT s, "/", v, "temp" USE TRIM(x) ' trim(x) will remove spaces at the beginning ' and the end of the splitted strings; ' try the example without "USE TRIM(x)" FOR i = 0 TO UBOUND(v) PRINT i;" [";v(i);"]" NEXT ' displays ' 0 [] ' 1 [etc/temp] ' 2 [filename1.ext] +========================================================================================+ | 168. (Language) USG | +========================================================================================+ PRINT USG PRINT USG uses the FORMAT function to display numbers and strings. See PRINT for more information. USG and USING are equivalent. Example a = 1000 b = 2000 PRINT USG "#,###.##"; a PRINT USG "#,###.## "; a; b ' <- Format is applied to all variables PRINT USG "a = #####.00 b = #####"; a; b ' <- One formated string with placeholders for two variables ' Output: 1,000. ' Output: 1,000. 2,000. ' Output: a = 1000.00 b = 2000 +========================================================================================+ | 169. (Language) USING | +========================================================================================+ PRINT USING PRINT USING uses the FORMAT function to display numbers and strings. See PRINT for more information. USG and USING are equivalent. Example a = 1000 b = 2000 PRINT USING "#,###.##"; a PRINT USING "#,###.## "; a; b ' <- Format is applied to all variables PRINT USING "a = #####.00 b = #####"; a; b ' <- One formated string with placeholders for two variables ' Output: 1,000. ' Output: 1,000. 2,000. ' Output: a = 1000.00 b = 2000 +========================================================================================+ | 170. (Language) WEND | +========================================================================================+ WEND End of a WHILE … WEND loop. See WHILE for more information. Example c = 1 WHILE c < 10 PRINT c c = c + 1 WEND ' Output: 1 2 3 4 5 6 7 8 9 +========================================================================================+ | 171. (Language) WHILE | +========================================================================================+ WHILE expr Starts a WHILE … WEND loop. A While-loop loops as long as the test condition expr evaluates to true. SmallBASIC starts by evaluating the expression. If the expression is nonzero (true), the next command in the loop is executed. If the expression is zero (false), control passes to the first command following the next WEND command. When SmallBASIC encounters the WEND command, it reevaluates the expression parameter to the most recent WHILE. If that parameter is still nonzero (true), the process is repeated; otherwise, execution continues at the next command. WHILE/WEND loops may be nested to any level of complexity, but there must be a WEND for each WHILE. See EXIT to exit a while-loop, even when expression is true. Example c = 1 WHILE c < 10 PRINT c c = c + 1 WEND ' Output: 1 2 3 4 5 6 7 8 9 +========================================================================================+ | 172. (Language) XNOR | +========================================================================================+ a XNOR b Bitwise exclusive NOT OR. Truth table: a b a XNOR b --- --- ---------- 0 0 1 0 1 0 1 0 0 1 1 1 Example 1 The NOT-operation as part of XNOR performs a bitwise inversion on all bits of a number. This leads to the following (maybe unexpected) result: print bin(0 xnor 0) ' Output: 11111111111111111111111111111111 Example 2: Operate XNOR only on last n bits If you want to operate NOR only on the last n bits of the numbers, you can use the following code: n = 4 a = 0b1100 b = 0b1010 print bin((a XNOR b) BAND ((1 lshift n ) - 1)) ' Output 1001 +========================================================================================+ | 173. (Language) XOR | +========================================================================================+ a XOR b Bitwise exclusive OR. Truth table: a b a XOR b --- --- --------- 0 0 0 0 1 1 1 0 1 1 1 0 Example print 0 xor 1 ' Output: 1 print bin(0b1100 xor 0b1010) ' Output: 110 +========================================================================================+ | 174. (Math) ABS | +========================================================================================+ ABS (x) Returns the absolute value of x. Example a = 1 b = -1 print abs(a) ' Output: 1 print abs(b) ' Output: 1 +========================================================================================+ | 175. (Math) ABSMAX | +========================================================================================+ ABSMAX (...) Returns the absolute maximum value of var1 to varN. var1 to varN can be numbers and arrays of numbers. See ABSMIN for absolute minimum value. Example 1: ABSMAX of several numbers a = -3 b = -1 c = 2 print absmax(a, b, c) ' Output: 3 Example 2: ABSMAX of an array a = [-3,-1,2] print absmax(a) ' Output: 3 Example 3: ABSMAX of mixed parameters a = [-3,-1,2] b = -2 print absmax(a, b) ' Output: 3 +========================================================================================+ | 176. (Math) ABSMIN | +========================================================================================+ ABSMIN (...) Returns the absolute minumum value of var1 to varN. var1 to varN can be numbers and arrays of numbers. See ABSMAX for absolute maximum value. Example 1: ABSMIN of several numbers a = -3 b = -1 c = 2 print absmin(a, b, c) ' Output: 1 Example 2: ABSMIN of an array a = [-3,-1,2] print absmin(a) ' Output: 1 Example 3: ABSMIN of mixed parameters a = [-3,-1,2] b = -2 print absmin(a, b) ' Output: 1 +========================================================================================+ | 177. (Math) ACOS | +========================================================================================+ ACOS (x) Inverse cosine of x. Example a = cos(pi) print acos(a) ' Output: 3.14159265358979 +========================================================================================+ | 178. (Math) ACOSH | +========================================================================================+ ACOSH (x) Inverse hyperbolic cosine of x Example a = cosh(pi) print a ' Output: 11.59195327552152 b = acosh(a) print b ' Output: 3.14159265358979 +========================================================================================+ | 179. (Math) ACOT | +========================================================================================+ ACOT (x) Inverse cotangent of x. Example a = cot(1) print a ' Output: 0.64209261593433 b = acot(a) print b ' Output: 1 +========================================================================================+ | 180. (Math) ACOTH | +========================================================================================+ ACOTH (x) Inverse hyperbolic cotangent of x. Example a = coth(pi) print a ' Output: 1.00374187319732 b = acoth(a) print b ' Output: 3.14159265358979 +========================================================================================+ | 181. (Math) ACSC | +========================================================================================+ ACSC (x) Inverse cosecant of x. Example a = csc(0.1) print a ' Output: 10.01668613163478 b = acsc(a) print b ' Output: 0.1 +========================================================================================+ | 182. (Math) ACSCH | +========================================================================================+ ACSCH (x) Inverse hyperbolic cosecant of x. Example a = csch(0.1) print a ' Output: 9.9833527572961 b = acsch(a) print b ' Output: 0.1 +========================================================================================+ | 183. (Math) ASEC | +========================================================================================+ ASEC (x) Inverse secant of x. Example a = sec(0.1) print a ' Output: 1.00502091840046 b = asec(a) print b ' Output: 0.1 +========================================================================================+ | 184. (Math) ASECH | +========================================================================================+ ASECH (x) Inverse hyperbolic secant of x. Example a = sech(0.1) print a ' Output: 0.99502074895323 b = asech(a) print b ' Output: 0.1 +========================================================================================+ | 185. (Math) ASIN | +========================================================================================+ ASIN (x) Inverse sine of x. Example a = sin(0.5) print a ' Output: 0.4794255386042 b = asin(a) print b ' Output: 0.5 +========================================================================================+ | 186. (Math) ASINH | +========================================================================================+ ASINH (x) Inverse hyperbolic sine of x. Example a = sinh(0.5) print a ' Output: 0.52109530549375 b = asinh(a) print b ' Output: 0.5 +========================================================================================+ | 187. (Math) ATAN | +========================================================================================+ ATAN (x) Inverse tangent of x. Example 1 a = tan(0.5) ' Output: 0.54630248984379 print a b = atan(a) print b ' Output: 0.5 +========================================================================================+ | 188. (Math) ATAN2 | +========================================================================================+ ATAN2 (x, y) Returns the angle a in radians of a right-angled triangle, where x is the opposite side and y is the adjacent side. Example 1 x = 10 ' Opposite side of right-angled triangle y = 100 ' Adjacent side of right-angled triangle print deg( atan2(x, y) ) ' Output: 5.71059313749964 Example 2: Graphics demo ' Both atan(n) and atan2(y, x) return an angle measured in radians. ' The return measure is from -pi to pi. In demo below it is converted ' to angle between 0 and 360 degrees. ' atan2 is better for detecting angle's quardrant because ' x and y are given separartely. ' y the vertical change is given first. centerX = xmax / 2 centerY = ymax / 2 pen on while asc(inkey) <> 27 cls locate 0,20: print "ATAN2 demo, used to detect angle of mouse to screen center." at centerX + 210, centerY - 10 : Print "0 degrees (or radians)" line centerX, centerY, centerX + 200, centerY mouseX = pen(4) mouseY = pen(5) line centerX, centerY, mouseX, mouseY, 15 'draw line from center to mouse differenceX = mouseX - centerX differenceY = mouseY - centerY a = atan2(differenceY, differenceX) ' < notice y difference is listed first if a < 0 then a += 2 * pi ' atan2 returns neg number for angles > 180 arc centerX, centerY, 100, 0, a 'draw the arc from 0 to angle s = "Angle of mouse to center of screen ~ " + deg(a)\1 + " degrees" locate 30, 20 : print s showpage delay 10 wend +========================================================================================+ | 189. (Math) ATANH | +========================================================================================+ ATANH (x) Inverse hyperbolic tangent of x. Example a = tanh(0.5) print a ' Output: 0.46211715726001 b = atanh(a) print b ' Output: 0.5 +========================================================================================+ | 190. (Math) ATN | +========================================================================================+ ATN (x) Inverse tangent of x. Equivalent to ATAN. Example a = tan(0.5) print a ' Output: 0.54630248984379 b = atan(a) print b ' Output: 0.5 c = atn(a) print c ' Output: 0.5 +========================================================================================+ | 191. (Math) CEIL | +========================================================================================+ CEIL (x) Smallest integer value not less than x. For smallest integer value less then x see FLOOR. Example print "ceil(1.1) = "; ceil(1.1) print "ceil(1.5) = "; ceil(1.5) print "ceil(1.9) = "; ceil(1.9) print "ceil(-1.1) = "; ceil(-1.1) print "ceil(-1.5) = "; ceil(-1.5) print "ceil(-1.9) = "; ceil(-1.9) ' Output: ' ceil(1.1) = 2 ' ceil(1.5) = 2 ' ceil(1.9) = 2 ' ceil(-1.1) = -1 ' ceil(-1.5) = -1 ' ceil(-1.9) = -1 +========================================================================================+ | 192. (Math) COS | +========================================================================================+ COS (x) Cosine of x. x is in radians. Example 1 a = cos(0.5) print a ' Output: 0.87758256189037 b = acos(a) print b ' Output: 0.5 Example 2 'TRIG lesson one.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-12 'note: the lines in the diagram have been thickened to help see and identify the color const green=rgb(0,128,0) 'never liked QB color for green sub drawTRIGtri '3 points make a triangle, one point requires an x,y coordinate xp1=xmax-100-.25*ymax : yp1=ymax-100 'bottom left angle of triangle xp2=xmax-100 : yp2=ymax-100 'bottom right corner with right angle xp3=xmax-100 : yp3=ymax-100-.433*ymax 'upper corner 'green botton line is called side adjacent the yellow angle at the base of this triangle (not the 90 degree right angle) line xp1,yp1,xp2,yp2,green line xp1-1,yp1+1,xp2+1,yp2+1,green line xp1-2,yp1+2,xp2+2,yp2+2,green 'blue vertical line is call side opposite the yellow angle at the base of this triangle (not the 90 degree right angle) line xp2,yp2,xp3,yp3,9 line xp2+1,yp2+1,xp3+1,yp3-1,9 line xp2+2,yp2+2,xp3+2,yp3-2,9 'red diagonal line always the longest of a right triangle is called the hypotenuse for i=0 to 6 line xp1,yp1+.5*i,xp3,yp3+i,12 next 'mark the 90 degree angel rect xp2-50,yp2-50 step 48,48,15 at xp2-50+10,yp2-50+15:?"90" 'the yellow angle: ARC x,y,r, start radians, stop radians[, aspect [, color]] note: start clockwise to stop radians arc xp1,yp1,.2*ymax/2,2*pi-pi/3,0,1,14 arc xp1,yp1,.18*ymax/2,2*pi-pi/3,0,1,14 'note: here 0 degrees is due east and the angle advances clockwise end while 1 cls drawTRIGtri at 0,0 ?"A man put up a pole (blue) and attached a 100 foot wire (red)" ?"from top to ground. Now he needs to know the height of the" ?"pole. He doesn't have a ladder nearly that high but he" ?"can use a first lesson in trignometry to get the height of" ?"the pole." ? ?"Trignometry means right triangles. A right triangle is one ?"that contains a 90 degree angle, the same angle a proper ?"pole makes with the ground." ? ?"Trig has made a study of right triangles and made one big ?"discovery: The RATIO of the sides of a right triangle are ?"always the same if the ANGLES of the sides (AKA legs and ?"hypotenuse) are the same." ?"That is trig in a nutshell. Notice I said RATIO of lengths." ? ?"press any when ready... pause cls drawTRIGtri at 0,0 ?"The two main RATIOs of Trig are SIN and COS." ?"COS (AKA COSINE) is the RATIO of the green side (next to" ?"the yellow ANGLE) to the hypotenuse (red diagonal) AKA" ?"(adjacent leg) / (hypotenuse) shortened to (adj/hyp)" ?"or here (green line length) / (red line length)." ?"That's it! COS is the leg length next to the angle in" ?"question divided by the diagonal length." ? ?"So the man measures the distance from the pole to where" ?"the wire meets the gound and gets 50 feet. This is the" ?"green leg next to the angle we want to figure out for the" ?"COS RATIO (adj/hyp). In this case it is 50 ft along the" ?"ground divided by 100 ft the diagonal red wire, 50/100=.5" ?"So that means COS of the angle is .5 the man says." ? ?"So the man goes to some trig tables and finds what angle" ?"makes a COS ratio of .5, he is looking up the Arc COS of" ?"the ratio(.5) = the angle whose adj-leg/hypotenuse is .5" ?"Oh! he says that is a 60 degree angle the wire is making" ?"with the ground, the yellow angle is 60 degrees." ? ?"Press any key when ready..." Pause cls drawTRIGtri at 0,0 ?"Now that he knows the angle is 60 degrees he can use the" ?"SIN ratio to calculate the height of the pole. The SIN" ?"RATIO is opp/hyp, the (opposite leg length)/(hypotenuse)" ?"The pole/wire = SIN of 60 degrees = .8660" ?"or pole/wire=.866." ? ?"Multiply both sides of this equation by wire length and" ?"get pole=.866*wire." ?"Since the wire is 100, pole = .866*100 = 86.6 feet." ? ?"press any for first screen again..." pause wend Example 3 At an angle around a given point, SIN and COS and radius (or distance) can locate the absolute screen x,y coordinate. ' Diagrammed SIN and COS.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-16 ' ah finally got diagramed analysis built into single quote commented code!!! ' the color codes match original Trig lesson one ' reminder XMAX, YMAX and PI are built in constants CONST green =RGB(0,128,0) ' a central point cx,cy around which to draw cx=XMAX/2:cy=YMAX/2 'again cx,cy can be anywhere on screen so dont make them constant ' highlight center CIRCLE cx,cy,2,1,15 r=200 'the radius or distance in pixels from cx,cy desired CIRCLE cx,cy,r,1,8 'we want a point somewhere on this circle, radius = constant distance away from point ' locate point 30 degrees and r distance from cx,cy 30 degrees = PI/6 radians ' here is 30 degrees in tiny purple circle around x=r*cos(rad(30),y=r*sin(rad(30) CIRCLE cx + r*COS(RAD(30)), cy + r*SIN(RAD(30)), 3, 1, 13 'x,y,r=3,aspect=1,color 13 legend LINE cx,cy,cx+r*COS(RAD(30)),cy,green 'adjacent leg in red LINE cx+r*COS(RAD(30)),cy,cx+r*COS(RAD(30)),cy + r*SIN(RAD(30)),9 'leg opposite in blue LINE cx,cy,cx+r*COS(RAD(30)),cy + r*SIN(RAD(30)),12 RECT cx+r*COS(RAD(30))-11,cy+2 step 9,9,15 ' V there are 12, 30 degree angles in circle (2*PI) so 2*PI/12 or PI/6 ARC cx,cy,30,0,PI/6,1,14 ARC cx,cy,35,0,RAD(30),1,14 sub legend at 0,0 ?"green = leg adj, blue =leg opp, red = hypotenuse = radius" ?"white square is where the right angle is, yellow arcs mark angle in question ?"COS(yellow) = adj/hyp = green/red, red is radius of circle ?"SIN(yellow) = opp/hyp = blue/red, red is radius of circle end +========================================================================================+ | 193. (Math) COSH | +========================================================================================+ COSH (x) Hyperbolic cosine of x. Example a = cosh(pi) print a ' Output: 11.59195327552152 b = acosh(a) print b ' Output: 3.14159265358979 +========================================================================================+ | 194. (Math) COT | +========================================================================================+ COT (x) Cotangent of x. Example a = cot(pi) print a b = acot(a) print b +========================================================================================+ | 195. (Math) COTH | +========================================================================================+ COTH (x) Cotangent hyperbolicus of x. Example a = coth(pi) print a b = acoth(a) print b +========================================================================================+ | 196. (Math) CSC | +========================================================================================+ CSC (x) Cosecant of x. Example a = csc(0.1) print a b = acsc(a) print b +========================================================================================+ | 197. (Math) CSCH | +========================================================================================+ CSCH (x) Hyperbolic cosecant of x. Example a = csch(0.1) print a b = acsch(a) print b +========================================================================================+ | 198. (Math) DEG | +========================================================================================+ DEG (x) Converts radians x to degrees. Example a = deg(pi) print a b = rad(a) print b +========================================================================================+ | 199. (Math) DERIV | +========================================================================================+ DERIV x, maxtries, maxerr, BYREF result, BYREF errcode USE expr Calculation of derivative. - x: value of x - maxtries: maximum number of retries - maxerr: tolerance - errcode: 0 for success; otherwise calculation error - result: the result - expr: the function f(x) Example 1 ' What is the derivative of f(x) for a given x def f(x) = 2*x^2+2 x = 3 result = 0 errcode = 0 deriv x, 10, 0.01, result, errcode USE f(x) def d(x) = 4*x ' Exact derivative of f(x) for comparision print "Result of DERIV at x = "; x; " : "; result print "Exact derivative at x = "; x; " : "; d(x) Example 2 ' What is the derivative of f(x) for a given x def f(x) = x^3 + 2 * exp(2*x) x = 3 result = 0 errcode = 0 deriv x, 10, 0.000001, result, errcode USE f(x) def d(x) = 3*x^2 + 4*exp(2*x) ' Exact derivative of f(x) for comparision print "Result of DERIV at x = "; x; " : "; result print "Exact derivative at x = "; x; " : "; d(x) +========================================================================================+ | 200. (Math) DETERM | +========================================================================================+ DETERM (A[, toler]) Determinant of A. toler is the tolerance number. It is equivalent to the absolute value of the lowest acceptable number. Default value is 0. Example A = [ 0, 1, 2; 3, 2, 1; 1, 1, 0] print determ(A) ' Output: 3 +========================================================================================+ | 201. (Math) DIFFEQN | +========================================================================================+ DIFFEQN x0, y0, xf, maxseg, maxerr, BYREF yf, BYREF errcode USE expr Solving first-order differential equations using Runge-Kutta method. - expr : f(y,x) = dy/dx with start condition: y(x = x0) = y0 - x0, y0 : initial x, y - xf : final x - yf : result - maxseq : equivalent to precision - maxerr : maximum allowed error - errcode : 0 for success; otherwise calculation error Example 1 ' Solving dy/dx = 7*y^2 * x^3 with start condition y(2) = 3 def f1(x,y) = 7*y^2 * x^3 y0 = 3 x0 = 2 yf = 0 xf = 1 maxseg = 10000 maxerr = 0.001 errcode = 0 diffeqn x0, y0, xf, maxseg, maxerr, yf, errcode USE f1(x,y) ' Exact solution for comparision def g1(x) = -1 / (7/4 * x^4 - 85/3) print "g1(xf) = "; g1(xf) print "yf(xf) = "; yf if(errcode != 0) then print "Error solving equation" print "Increasing maxseg might help" endif Example 2 ' Defining the differential equation for a stiffness system def f2(y,t) = -1000*y + 3000 - 2000 * exp(-t) ' Solving equation at time tf = 0.001 seconds with y(0) = 0 y0 = 0 t0 = 0 yf = 0 tf = 0.001 maxseg = 1000 maxerr = 0.001 errcode = 0 diffeqn t0, y0, tf, maxseg, maxerr, yf, errcode USE f2(y,t) ' Exact solution for comparision def g2(t) = 3 - 0.998*exp(-1000*t) - 2.002 * exp(-t) print "g2(tf) = "; g2(tf) print "yf(tf) = "; yf if(errcode != 0) then print "Error solving equation" print "Increasing maxseg might help" endif +========================================================================================+ | 202. (Math) EXP | +========================================================================================+ EXP (x) Returns the value of e raised to the power of x. a = exp(2) print a b = log(a) print b +========================================================================================+ | 203. (Math) EXPRSEQ | +========================================================================================+ EXPRSEQ BYREF array, xmin, xmax, count USE expression Returns an array with ‘count’ elements. Each element has the ‘y’ value of its position as it is returned by the expression. def f(x) = 2*x EXPRSEQ v1, 0, 1, 5 USE f(x) print v1 'same as v2 = [f(0), f(0.25), f(0.5), f(0.75), f(1)] print v2 +========================================================================================+ | 204. (Math) FIX | +========================================================================================+ FIX (x) Rounds x upwards to the nearest integer. print "fix(1.1) = "; fix(1.1) print "fix(1.5) = "; fix(1.5) print "fix(1.9) = "; fix(1.9) print "fix(-1.1) = "; fix(-1.1) print "fix(-1.5) = "; fix(-1.5) print "fix(-1.9) = "; fix(-1.9) ' Difference to ceil with negative numbers print "ceil(1.1) = "; ceil(1.1) print "ceil(1.5) = "; ceil(1.5) print "ceil(1.9) = "; ceil(1.9) print "ceil(-1.1) = "; ceil(-1.1) print "ceil(-1.5) = "; ceil(-1.5) print "ceil(-1.9) = "; ceil(-1.9) +========================================================================================+ | 205. (Math) FLOOR | +========================================================================================+ FLOOR (x) Largest integer value not greater than x. For largest integer value greater then x see CEIL(x) print "floor(1.1) = "; floor(1.1) print "floor(1.5) = "; floor(1.5) print "floor(1.9) = "; floor(1.9) print "floor(-1.1) = "; floor(-1.1) print "floor(-1.5) = "; floor(-1.5) print "floor(-1.9) = "; floor(-1.9) +========================================================================================+ | 206. (Math) FRAC | +========================================================================================+ FRAC (x) Fractional part of x. print frac(71.901) ' Output: 0.901 +========================================================================================+ | 207. (Math) INT | +========================================================================================+ INT (x) Rounds x downwards to the nearest integer. x\1 will convert x to an integer in less keystrokes than INT, they both round down for positives and up for negatives. They both drop the fractional part of the number. Example 1 print int(3.3) ' Output 3 print int(3.7) ' Output 3 print int(-3.3) ' Output -3 print int(-3.7) ' Output -3 Example 2 'INT or alternate.bas 2016-03-06 SmallBASIC 0.12.2 [B+=MGA] 'I think number\1 is eqivalent to INT(number) in less keystrokes ' both of these convert a number to an integer and both round down to do it. for i = 1 to 20 'which coin should I use if rnd<.5 then TF=int(rnd*2) else TF=rnd*2\1 ? TF, if TF then ? "It is true now."; else ? "Now it's false."; ?spc(3)+"press a key or click for next..." next for i=0 to -10 step -1 'they seem to behave the same for negatives too test=i+rnd ? " test = ";test ? " test\1 = " ;test\1 ? "int(test) = ";int(test) ? next +========================================================================================+ | 208. (Math) INTERSECT | +========================================================================================+ INTERSECT Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, BYREF type, BYREF Rx, BYREF Ry Ry Calculates the intersection of two line segments AB and CD given by the point Ax, Ay, Bx, By and Cx, Cy, Dx, Dy. Returns: - Rx, Ry = coordinates of crossing point. - type = cross-type: - 0: No cross (R = external cross) - 1: One cross - 2: Parallel - 3: Parallel (many crosses) - 4: The cross is one of the line segments edges. Example ' Line segment AB Ax = 50 Ay = 50 Bx = 100 By = 100 ' Line segment CD Cx = 100 Cy = 50 Dx = 50 Dy = 100 intersect Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, type, Rx, Ry print "Intersection at x = "; Rx; ", y = "; Ry ' Draw lines and a circle at the calculated crossing point line Ax, Ay, Bx, By color 5 line Cx, Cy, Dx, Dy color 8 circle Rx,Ry, 5 color 12 +========================================================================================+ | 209. (Math) INVERSE | +========================================================================================+ INVERSE (A) Returns the inverse matrix I of matrix A. Example A = [ 1, -1, 1; 2, -1, 2; 3, 2, -1] print INVERSE(A) +========================================================================================+ | 210. (Math) LINEQN | +========================================================================================+ LINEQN (a, b [, toler]) Solves linear equations using the Gauss-Jordan method. - A equation coefficience as a matrix - B results of the equations as a column-vector - C result as a Nx1 matrix with the values of the unknowns - toler tolerance number (the absolute value of the lowest acceptable number). Default value is 0 (tolerance not applied). One possible problem is numerical instability, caused by the possibility of dividing by very small numbers. If, for example, the leading coefficient of one of the rows is very close to zero, […] one would need to divide by that number. This means that any error existed for the number that was close to zero would be amplified. Wikipedia The tolerance number can be used to ensure, that no division by numbers smaller than toler will be performed. Example ' Solve: ' x - y + 2z = 6 ' 2x + 3y + 2z = 11 ' 3x + 2y + z = 8 A = [1,-1,2; 2,3,2; 3,2,1] B = [6; 11; 8] C = LINEQN(A, B) print "x = "; C(0,0) print "y = "; C(0,1) print "z = "; C(0,2) ' Output: x = 1; y = 1; z = 3 +========================================================================================+ | 211. (Math) LOG | +========================================================================================+ LOG (x) Returns the natural logarithm of x. Example: a = exp(2) print a ' Output: 7.389.... b = log(a) print b ' Output: 2 +========================================================================================+ | 212. (Math) LOG10 | +========================================================================================+ LOG10 (x) Returns the base-10 logarithm of x. Example: a = 10^2 print a ' Output: 100 b = log10(a) print b ' Output: 2 +========================================================================================+ | 213. (Math) M3APPLY | +========================================================================================+ M3APPLY m3x3, BYREF poly Apply 2D transformation matrix M to poly-line poly. Transformation matrix M is a 3x3 matrix. Example DIM M(2,2) Rectangle = [-1,-1, 1,-1, 1,1, -1,1, -1,-1] ' Create a rectangular polygon M3IDENT M ' Create Identity Matrix M3Trans M, 100,100 ' Move rectangle to position (100,100) M3SCALE M, 0, 0, 50, 50 ' Scale rectangle by factor 50 in x and y M3ROTATE M, 45*pi/180 ' Rotate by 45° M3APPLY M, Rectangle ' Transform the rectangle DRAWPOLY Rectangle M3TRANS, M3SCALE and M3ROTATE perform a matrix multiplication. When performing matrix multiplication, then last matrix is applied first. In the example above, the rectangle is first rotated, then scaled and in the last step translated. If the order is changed, the outcome might be different. +========================================================================================+ | 214. (Math) M3IDENT | +========================================================================================+ M3IDENT BYREF m3x3 Creates a 3x3 Identity matrix M: |1 0 0| M = |0 1 0| |0 0 1| The Identy matrix can be used with M3TRANS, M3SCALE, M3ROTATE and M3APPLY to perform 2D transformations of a poly-line. Example DIM M(2,2) Rectangle = [-1,-1, 1,-1, 1,1, -1,1, -1,-1] ' Create a rectangular polygon M3IDENT M ' Create Identity Matrix M3Trans M, 100,100 ' Move rectangle to position (100,100) M3SCALE M, 0, 0, 50, 50 ' Scale rectangle by factor 50 in x and y M3ROTATE M, 45*pi/180 ' Rotate by 45° M3APPLY M, Rectangle ' Transform the rectangle DRAWPOLY Rectangle +========================================================================================+ | 215. (Math) M3ROTATE | +========================================================================================+ M3ROTATE BYREF m3x3, angle [, x, y] Multiply the 2D transformation matrix M by a rotation matrix with an angle angle and a rotation center x,y. M is a 3x3 matrix. If x = 0 and y = 0 the rotation matrix has the form: | cos(angle) -sin(angle) 0 | MRot = | sin(angle) cos(angle) 0 | | 0 0 1 | else: | cos(angle) -sin(angle) (1 - cos(angle))*x + sin(angle) * y | MRot = | sin(angle) cos(angle) (1 - cos(angle))*y - sin(angle) * x | | 0 0 1 | Example DIM M(2,2) Rectangle = [-1,-1, 1,-1, 1,1, -1,1, -1,-1] ' Create a rectangular polygon M3IDENT M ' Create Identity Matrix M3Trans M, 100,100 ' Move rectangle to position (100,100) M3SCALE M, 0, 0, 50, 50 ' Scale rectangle by factor 50 in x and y M3ROTATE M, 45*pi/180 ' Rotate by 45° M3APPLY M, Rectangle ' Transform the rectangle DRAWPOLY Rectangle M3TRANS, M3SCALE and M3ROTATE perform a matrix multiplication. When performing matrix multiplication, then last matrix is applied first. In the example above, the rectangle is first rotated, then scaled and in the last step translated. If the order is changed, the outcome might be different. +========================================================================================+ | 216. (Math) M3SCALE | +========================================================================================+ M3SCALE BYREF m3x3, x, y, Sx, Sy Multiply the 2D transformation matrix M by a scale matrix. Sx and Sy are the scaling factors in x and y direction. Ox and Oy define the position of the origin. If Ox = 0 and Oy = 0 then the scaling matrix M has the form: |Sx 0 0| MScale = |0 Sy 0| |0 0 1| else: |1 0 Ox| |Sx 0 0| |1 0 -Ox| |Sx 0 (1 - Sx) * Ox| MScale = |0 1 Oy| * | 0 Sy 0| * |0 1 -Oy| = | 0 Sy (1 - Sy) * Oy| |0 0 1| | 0 0 1| |0 0 1| | 0 0 1| Example DIM M(2,2) Rectangle = [-1,-1, 1,-1, 1,1, -1,1, -1,-1] ' Create a rectangular polygon M3IDENT M ' Create Identity Matrix M3Trans M, 100,100 ' Move rectangle to position (100,100) M3SCALE M, 0, 0, 50, 50 ' Scale rectangle by factor 50 in x and y M3ROTATE M, 45*pi/180 ' Rotate by 45° M3APPLY M, Rectangle ' Transform the rectangle DRAWPOLY Rectangle M3TRANS, M3SCALE and M3ROTATE perform a matrix multiplication. When performing matrix multiplication, then last matrix is applied first. In the example above, the rectangle is first rotated, then scaled and in the last step translated. If the order is changed, the outcome might be different. +========================================================================================+ | 217. (Math) M3TRANS | +========================================================================================+ M3TRANS BYREF m3x3, Tx, Ty Multiply the 2D transformation matrix M by a translation matrix. Tx and Ty are the translations in x and y direction. M is a 3x3 matrix. The translation matrix has the form | 1 0 Tx | MTrans = | 0 1 Ty | | 0 0 1 | Example DIM M(2,2) Rectangle = [-1,-1, 1,-1, 1,1, -1,1, -1,-1] ' Create a rectangular polygon M3IDENT M ' Create Identity Matrix M3Trans M, 100,100 ' Move rectangle to position (100,100) M3SCALE M, 0, 0, 50, 50 ' Scale rectangle by factor 50 in x and y M3ROTATE M, 45*pi/180 ' Rotate by 45° M3APPLY M, Rectangle ' Transform the rectangle DRAWPOLY Rectangle M3TRANS, M3SCALE and M3ROTATE perform a matrix multiplication. When performing matrix multiplication, then last matrix is applied first. In the example above, the rectangle is first rotated, then scaled and in the last step translated. If the order is changed, the outcome might be different. +========================================================================================+ | 218. (Math) MAX | +========================================================================================+ MAX (...) MAX returns the maximum value of the given parameters var1 to varN. Parameters can be numbers, arrays or strings. Example print MAX(3, 4, 8) ' Output: 8 print MAX("abc","def") ' Output: def x = [-1, 5, 8] print MAX(x) ' Output: 8 print MAX(x, 2, 9) ' Output: 9 +========================================================================================+ | 219. (Math) MIN | +========================================================================================+ MIN (...) Returns the minimum value of the given parameters var1 to varN. Parameters can be numbers, arrays or strings. Example print MIN(3, 4, 8) ' Output: 3 print MIN("abc","def") ' Output: abc x = [-1, 5, 8] print MIN(x) ' Output: -1 print MIN(x, 2, -9) ' Output: -9 +========================================================================================+ | 220. (Math) POLYAREA | +========================================================================================+ POLYAREA (poly) Returns the area of the polyline poly. The algebraic sign of the area is positive for counterclockwise ordering of vertices in x-y plane; otherwise negative. See DRAWPOLY for more information on how to define the polyline. Example polygon = [ [50,50], [100,50], [100,100], [50,100], [50,50]] drawpoly polygon color 12 Area = abs(polyarea(polygon)) ' absolute value of the area, because ' we are not interested in the ' ordering of the vertices. print "Polyarea() returns: "; Area print "Exact area is 50x50 = 2500" +========================================================================================+ | 221. (Math) POLYCENT | +========================================================================================+ POLYCENT returns the centroid of a polygon poly as an array. The first element contains the x- the second element contains the y-coordinate of the centroid. POLYCENT will return an empty array if the area of the polygon is zero and the centroid is undefined. POLYCENT is based on code from the article “Centroid of a Polygon” by Gerard Bashein and Paul R. Detmer. See DRAWPOLY for more information on how to define the polygon. Example: polygon = [[50,50], [100,50], [100,100], [50,100], [50,50]] ' Calculate centroid centroid = polycent(polygon) print "Centroid is at: "; centroid ' Draw polygon and a circle at position of the centroid drawpoly polygon color 12 circle centroid(0), centroid(1) , 5 color 5 +========================================================================================+ | 222. (Math) POLYEXT | +========================================================================================+ POLYEXT poly(), BYREF xmin, BYREF ymin, BYREF xmax, BYREF ymax Returns the extents of the polyline poly. xmin and xmax are extents in x-direction and ymin and ymax are the extents in y-direction. See DRAWPOLY on how to define a polyline. Example polygon = [ [30,50], [100,70], [120,90], [50,100], [30,50]] polyext(polygon, PolyXmin, PolyYmin, PolyXmax, PolyYmax) ' Draw polygon and a rectangle for indicating the extents drawpoly polygon color 12 rect PolyXmin, PolyYmin, PolyXmax, PolyYmax color 5 +========================================================================================+ | 223. (Math) POW | +========================================================================================+ POW (x, y) returns x raised to power of y. Example print pow(5,2) ' same as 5^2 = 25 +========================================================================================+ | 224. (Math) PTDISTLN | +========================================================================================+ PTDISTLN (Bx,By,Cx,Cy,Ax,Ay) Distance of point A from line B, C. Point A is given by the coordinates (Ax, Ay), B by (Bx, By) and C by (Cx, Cy) Example 1 ' Define line Bx = 100 By = 100 Cx = 200 Cy = 150 ' Define point Ax = 150 Ay = 50 Distance = ptdistln(Bx, By, Cx, Cy, Ax,Ay) print "Distant between line and point is "; Distance ;" pixel" Example 2: Interactive example to illustrate the geometry of PTDISTLN ' Interactive example to illustrate the geometry of PTDISTLN Bx = 200 By = 300 Ax = 300 Ay = 100 pen on while(!pen(12)) cls print "Move Mouse. Press Left Mouse Button to exit" Cx = pen(10) Cy = pen(11) Distance = PTDISTLN (Bx,By,Cx,Cy,Ax,Ay) print "Distant between line and point is "; Distance ;" pixel" Lx = Cx - Bx Ly = Cy - By if(Lx != 0 AND Ly != 0) then ' Calculate projection vector V using dot-product Px = Ax - Bx Py = Ay - By Vx = Bx + (Lx * Px + Ly * Py) / (Lx^2 + Ly^2) * Lx Vy = By + (Lx * Px + Ly * Py) / (Lx^2 + Ly^2) * Ly endif ' Draw line Bx, By, Cx, Cy color 10 ' Line line Ax, Ay, Vx, Vy color 2 ' Distant between line and point circle Ax, Ay, 5 color 11 ' Cirlce at position of the point showpage delay(50) wend +========================================================================================+ | 225. (Math) PTDISTSEG | +========================================================================================+ PTDISTSEG (Bx,By,Cx,Cy,Ax,Ay) Distance of point A from line segment B-C. Point A is given by the coordinates (Ax, Ay), B by (Bx, By) and C by (Cx, Cy). Example 1 ' Define line segment Bx = 100 By = 100 Cx = 200 Cy = 300 ' Define point Ax = 150 Ay = 50 Distance = PTDISTSEG (Bx,By,Cx,Cy,Ax,Ay) print "Distant between line and point is "; Distance ;" pixel" Example 2: Interactive example to illustrate the geometry of PTDISTSEG ' Interactive example to illustrate the geometry of PTDISTSEG Bx = 200 By = 300 Ax = 300 Ay = 100 pen on while(!pen(12)) cls print "Move Mouse. Press Left Mouse Button to exit" Cx = pen(10) Cy = pen(11) Distance = PTDISTSEG (Bx,By,Cx,Cy,Ax,Ay) print "Distant between line and point is "; Distance ;" pixel" Lx = Cx - Bx Ly = Cy - By if(Lx != 0 AND Ly != 0) then ' Calculate projection vector V using dot-product Px = Ax - Bx Py = Ay - By Vx = Bx + (Lx * Px + Ly * Py) / (Lx^2 + Ly^2) * Lx Vy = By + (Lx * Px + Ly * Py) / (Lx^2 + Ly^2) * Ly ' Test if V is on the line segment t = (Vx-Bx)/Lx if(t < 0) then Vx = Bx Vy = By elseif(t > 1) then Vx = Cx Vy = Cy endif endif ' Draw line Bx, By, Cx, Cy color 10 ' Line line Ax, Ay, Vx, Vy color 2 ' Distant between line and point circle Ax, Ay, 5 color 11 ' Cirlce at position of the point showpage delay(50) wend +========================================================================================+ | 226. (Math) PTSIGN | +========================================================================================+ PTSIGN (Ax,Ay,Bx,By,Qx,Qy) The sign of point Q from line segment A->B. Point Q is given by the coordinates (Qx, Qy), A by (Ax, Ay) and B by (Bx, By). Example 1: ' Define line Bx = 100 By = 100 Cx = 200 Cy = 150 ' Define point Ax = 150 Ay = 50 Sign = PTSIGN(Bx, By, Cx, Cy, Ax,Ay) print "Sign of point relative to the line "; Sign Example 2: Interactive example to illustrate the geometry of PTDISTLN ' Interactive example to illustrate the geometry of PTDISTLN Bx = 200 By = 300 Ax = 300 Ay = 100 pen on while(!pen(12)) cls print "Move Mouse. Press Left Mouse Button to exit" Cx = pen(10) Cy = pen(11) Sign = PTSIGN (Bx,By,Cx,Cy,Ax,Ay) print "Sign of point relative to the line "; Sign ' Draw line Bx, By, Cx, Cy color 10 ' Line circle Ax, Ay, 5 color 11 ' Cirlce at position of the point showpage delay(50) wend +========================================================================================+ | 227. (Math) RAD | +========================================================================================+ RAD (x) Converts x in degrees to radians. Example: a = deg(pi) print a ' Output: 180 b = rad(a) print b ' Output: 3.14.. +========================================================================================+ | 228. (Math) RND | +========================================================================================+ RND Returns a random floating point number in the range 0 to 1. Example 1 RANDOMIZE print "Number between 0 and 1 : "; RND() print "Number between 5 and 12 : "; (12 - 5) * RND() + 5 print "Number between -5 and -12: "; (-12 - -5) * RND() - 5 Example 2: Random true/false; random integer between low/high ' random true/false, subst 0 or 1 (or -1) DEF randbin() = IFF(rnd<.5,"True ","False ") ' random integer number between low and high DEF randlohi(lo, hi) = (RND * (hi - lo + 1))\1 + lo RANDOMIZE print randbin() print randlohi(10,20) +========================================================================================+ | 229. (Math) ROOT | +========================================================================================+ ROOT low, high, segs, maxerr, BYREF result, BYREF errcode USE expr Roots of f(x). ROOT will find the first x-intercept of the given function ( where f(x) = 0 ) in the interval [low, high] - low: the lower limit - high: the upper limit - segs: the number of segments (spaces) - maxerr: tolerance (IF ABS(f(x)) < maxerr THEN OK) - errcode: 0 for success; otherwise calculation error - result: the result - expr: the given function Example 1 def f1(x) = x - 2 ' Theory: x - 2 = 0 -> x = 2 ROOT 0, 5, 500, 0.001, result, errcode USE f1(x) if(errcode) then print("No root found") else print "Root at "; result endif ' Output: Root at 1.99951171875 Example 2 def f2(x) = x^2 - 2 ' Theory: x^2 - 2 = 0 -> x^2 = 2 -> x = +/-sqr(2) = +/-1.41 ROOT -1, 2, 500, 0.001, result, errcode USE f2(x) if(errcode) then print("No root found") else print "Root at "; result endif ' Output: Root at 1.4140625 +========================================================================================+ | 230. (Math) ROUND | +========================================================================================+ ROUND (x [, decs]) Rounds x to the nearest integer or number with decs decimal digits. decs is an optional parameter. Example 1: Round to nearest integer A = 12.3456 print round(A) ' Output: 12 Example 2: Round integer numbers A = 123456 print round(A/10) * 10 ' Output: 123460 print round(A/100) * 100 ' Output: 123500 print round(A/1000) * 1000 ' Output: 123000 Example 3: Round to decimal digits A = 12.3456 print round(A) ' Output: 12 print round(A, 1) ' Output: 12.3 print round(A, 2) ' Output: 12.35 +========================================================================================+ | 231. (Math) SEC | +========================================================================================+ SEC (x) Secant of x. Example a = sec(0.1) print a ' Output: 1.00502 b = asec(a) print b ' Output: 0.1 +========================================================================================+ | 232. (Math) SECH | +========================================================================================+ SECH (x) Hyperbolic secant of x. a = sech(0.1) print a ' Output: 0.99502074895323 b = asech(a) print b ' Output: 0.1 +========================================================================================+ | 233. (Math) SEGCOS | +========================================================================================+ SEGCOS (Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) Cosine of the two line segments AB and CD. Start and end of the first line segment are given by the points (Ax,Ay) and (Bx, By). For the second line by (Cx, Cy) and (Dx, Dy). Example 1: ' Line 1 Ax = 50 Ay = 50 Bx = 50 By = 100 ' Line 2 Cx = 100 Cy = 100 Dx = 50 Dy = 100 print "SEGCOS: "; SEGCOS(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) print "SEGSIN: "; SEGSIN(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) print "Angle between the lines: "; deg(acos(SEGCOS(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy))); "°" Example 2 ' Interactive example to illustrate the geometry ' of SEGCOS and SEGSIN ' Line 1 Ax = 280 Ay = 250 Bx = 250 By = 200 ' Line 2 Cx = 400 Cy = 300 Dx = 210 Dy = 300 pen on while(!pen(12)) cls print "Move Mouse. Press Left Mouse Button to exit" Dx = pen(10) Dy = pen(11) ResultCos = SEGCOS(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) ResultSin = SEGSIN(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) print "SEGCOS between the two segments: "; ResultCos ;" print "SEGSIN between the two segments: "; ResultSin ;" print "Angle between the two segments : "; DEG(ACOS(ResultCos)); " DEG" 'Calc intersecton of both lines 'f1(x) = a1*x+b1 'f2(x) = a2*x+b2 'f1 = f2 '-> x0 = (b2-b1) / (a1-a2) '-> y0 = f1(x0) ' if( (Bx - Ax) != 0 AND (Dx - Cx) != 0) then a1 = (By - Ay) / (Bx - Ax) a2 = (Dy - Cy) / (Dx - Cx) b1 = Ay - a1 * Ax b2 = Cy - a2 * Cx X0 = (b2-b1) / (a1-a2) Y0 = a1*X0 + b1 endif ' Draw line X0, Y0, Ax, Ay color 2 ' Line segment 1 line X0, Y0, Cx, Cy color 2 ' Line segment 2 line Ax, Ay, Bx, By color 10 ' Line 1 line Cx, Cy, Dx, Dy color 10 ' Line 2 showpage delay(50) wend +========================================================================================+ | 234. (Math) SEGLEN | +========================================================================================+ SEGLEN (Ax,Ay,Bx,By) Length of line segment AB. The starting and ending point of the line segment is given by (Ax, Ay) and (Bx, By). Example Ax = 150 Ay = 50 Bx = 50 By = 100 print "SEGLEN: "; SEGLEN(Ax, Ay, Bx, By); " pixel" ' Outut: SEGLEN: 111.8 Pixel +========================================================================================+ | 235. (Math) SEGSIN | +========================================================================================+ SEGSIN (Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) Sinus of 2 line segments AB and CD. Start and end of the first line segment are given by the points (Ax,Ay) and (Bx, By). For the second line by (Cx, Cy) and (Dx, Dy). Example 1 ' Line 1 Ax = 50 Ay = 50 Bx = 50 By = 100 ' Line 2 Cx = 100 Cy = 100 Dx = 50 Dy = 100 print "SEGCOS: "; SEGCOS(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) print "SEGSIN: "; SEGSIN(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) print "Angle between the lines: "; deg(acos(SEGCOS(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy))); "°" Example 2 ' Interactive example to illustrate the geometry ' of SEGCOS and SEGSIN ' Line 1 Ax = 280 Ay = 250 Bx = 250 By = 200 ' Line 2 Cx = 400 Cy = 300 Dx = 210 Dy = 300 pen on while(!pen(12)) cls print "Move Mouse. Press Left Mouse Button to exit" Dx = pen(10) Dy = pen(11) ResultCos = SEGCOS(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) ResultSin = SEGSIN(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy) print "SEGCOS between the two segments: "; ResultCos ;" print "SEGSIN between the two segments: "; ResultSin ;" print "Angle between the two segments : "; DEG(ACOS(ResultCos)); " DEG" 'Calc intersecton of both lines 'f1(x) = a1*x+b1 'f2(x) = a2*x+b2 'f1 = f2 '-> x0 = (b2-b1) / (a1-a2) '-> y0 = f1(x0) ' if( (Bx - Ax) != 0 AND (Dx - Cx) != 0) then a1 = (By - Ay) / (Bx - Ax) a2 = (Dy - Cy) / (Dx - Cx) b1 = Ay - a1 * Ax b2 = Cy - a2 * Cx X0 = (b2-b1) / (a1-a2) Y0 = a1*X0 + b1 endif ' Draw line X0, Y0, Ax, Ay color 2 ' Line segment 1 line X0, Y0, Cx, Cy color 2 ' Line segment 2 line Ax, Ay, Bx, By color 10 ' Line 1 line Cx, Cy, Dx, Dy color 10 ' Line 2 showpage delay(50) wend +========================================================================================+ | 236. (Math) SEQ | +========================================================================================+ SEQ (xmin, xmax, count) Returns an array with count elements of evenly spaced points between xmin and xmax. The spacing between the points is (xmax - xmin) / (n - 1). Example print SEQ(2,10,5) 'Output: [2,4,6,8,10] +========================================================================================+ | 237. (Math) SGN | +========================================================================================+ SGN (x) Sign of x. Return values are +1 for positive x, -1 for negative x and 0 for zero. SGN cannot accept a numeric string, such as “24”, as an argument. Example PRINT SGN(2), SGN(-2), SGN(0) ' Output is: 1 -1 0 PRINT SGN(INT("-2")) ' Output is: -1 +========================================================================================+ | 238. (Math) SIN | +========================================================================================+ SIN (x) Calculate the Sine of x. x is in radians. Example 1 a = sin(0.5) print a ' Output: 0.4794255386042 b = asin(a) print b ' Output: 0.5 Example 2: Using RAD The RAD function can be used to convert an angle in degrees to radians. alpha_in_degrees = 90 a = sin(rad(alpha_in_degrees)) print a ' Output: 1 Example 3: Drawing a spiral ' Drawing spiral around point.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-13 ' using SIN and COS in a most common situation drawing at an angle from a point cx = xmax\2 : cy = ymax\2 for degree = 0 to 360 step 10 'zero is due East line cx, cy step 10 * (degree^.5) * cos(rad(degree)), 10 * (degree^.5) * sin(rad(degree)), rgb(128,128,degree/360 * 128 + 127) at 0,0: print spc(100) at 0,0 if degree = 0 then print " 0 degrees don't worry, you haven't seen nothing yet! press any key ..." else print degree;" degrees press any key ..." end if pause next print "Notice how the the drawing started due East for 0 degrees and" print "as the angle increased the drawing went around clock-wise." pause cls ' now I am doing a LOGO like program and I want 0 degrees to be due North ' due North is -90 degrees for clock-wise rotation so subtract 90 from degrees for degree = 0 to 360 step 10 line cx, cy step 10 * (degree^.5) * cos(rad(degree - 90)), 10 * (degree^.5) * sin(rad(degree - 90)), rgb(250,0,degree/360 * 128 + 127) at 0,0: print spc(100) at 0,0 if degree = 0 then print " 0 degrees don't worry, you haven't seen nothing yet! press any key ..." else print degree;" degrees press any key ..." end if pause next print "Notice how the drawing started due North because of the -90 adjustment made in SIN and COS calls" Example 3: Draw a polygon ' sin and cos use.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-15 ' SIN and COS work as a team ' ' SIN and COS are used most for drawing points in circle around a central point. ' Here we are going to divide a circle into n sections to draw an n sided polygon, ' for instance, divide a circle into 3 equal parts and you get equilateral triangle (all sides =) ' divide by 4 and get a square, by 5 a pentagon, 6 a hexagon.... all equal sides ' I have to spend some time explaining why this works and a triangle diagram is really needed ' but here goes, imagine a pie sitting on top of a given center point cx,cy ' it is cut into n equal slices each piece has a central angle of 360/n or in radians 2*pi/n ' a polygon just cuts the round parts off with straight lines to each end at outer edge. ' remember COS is the leg adjacent to the angle in question divide by hypotenuse ' or COS(inner angle) = adj/hyp ' x is the adjacent side, the hypotenuse is the radius ' so COS(inner angle) = x/radius ' or radius * COS(angle) = x multiple each side by radius ' x = radius * COS(angle) ' but remember this is distance relative to center point not a screen coordinate ' to make absolute screen point it is: x = cx + radius*COS(angle) ' SIN works out similar ' SIN(inner angle) = opposite/hyp ' and again y is opposite side (of inner angle) and the hypotenuse is the radius of circle ' SIN(angle) = y/radius multiply each side by radius ' radius*SIN(angle) = y ' y = radius * SIN(angle) ' to make absolute screen point it is y = cy + radius*SIN(angle) ' So going around a central point x=cx+radius*COS(angle),y=cy+radius*SIN(angle) ' will locate points equal distance from center for equal sided polygon cx = xmax / 2: cy = ymax / 2 ' here's our center move it anywhere on screen 'cx=100 : cy = 500 ' <== try different center points radius = 150 while 1 cls circle cx, cy, 3, 1, 14 'this shows the central point in small yellow circle ' what polygon shall we draw? print "A regular polygon is a many sided figure with equal sides." print "A triangle is a 3 sided polygon, a square 4, a pentagon 5..." input "(<=2 quits) Enter the number of sides for a polygon to draw "; n if n < 3 then end ' need at least 3 sides ' make the first point 0 degrees or directly East of center point (offset 0) ' you can off set the first point by some degree amount to spin the polygon by the offset offset = 0 ' play with this to spin polygon ' offset = pi / 10 ' offset = pi / 18 ' offset = pi / 36 for centralAngle = offset to 2*pi + offset step 2*pi / n '2*pi is a circle (360 degrees) divide by n get inner angles of pie slices that's our step 'radius * cos(centralAngle) = our needed x coordinate to center point so add cx for absolute screen coordinate 'radius * sin(centralAngle) = our needed y coordinate to center point so add cy for absolute screen coordinate if centralAngle=0+offset then 'first point location xstart = cx + radius * cos(centralAngle) ystart = cy + radius * sin(centralAngle) 'get the ball rolling by recording first point else line xstart, ystart, cx + radius * cos(centralAngle), cy + radius * sin(centralAngle) xstart = cx + radius * cos(centralAngle) ystart = cy + radius * sin(centralAngle) end if delay 300 'to show the progress of draw next s="press any key ..." at cx - txtw(s) / 2, cy - txth(s) / 2:print s 'this puts cue right where you will see it pause wend 'you are just a few simple steps away from spinning these polygons! Example 4: Plot sin, cos and tan ' sin-cos-tan.bas from FLTK samples cls at 0, ymax / 2 + txth("Q") color 1: print "sin(x)" color 8: print "cos(x)" color 12: print "tan(x)" line 0, ymax/2, xmax, ymax/2 'central or x axis, ymax/4 is multiplier scaled to 1/4 of ymax for i = 0 to xmax pset i, ymax/2 - sin(i * 2*pi / ymax) * ymax/4 color 1 pset i, ymax/2 - cos(i * 2*pi / ymax) * ymax/4 color 8 pset i, ymax/2 - tan(i * 2*pi / ymax) * ymax/4 color 12 next +========================================================================================+ | 239. (Math) SINH | +========================================================================================+ SINH (x) Hyperbolic sine of x. Example a = sinh(0.5) print a ' Output: 0.52109530549375 b = asinh(a) print b ' Output: 0.5 +========================================================================================+ | 240. (Math) SQR | +========================================================================================+ SQR (x) Square root of x. Example: print sqr(2) ' Output: 1.4142135623731 +========================================================================================+ | 241. (Math) STATMEAN | +========================================================================================+ STATMEAN (...) Arithmetical mean (average). var1 to varN can be single numbers or arrays. Example 1: Using an array A = [2,2,3,4,14] print statmean(A) ' same as: sum(A) / len(A) ' Output: 5 Example 2: Using two arrays A = [2,2,3,4,14] B = [7,9,7] print statmean(A, B) ' Output: 6 Example 3: Using array and number A = [2,2,3,4,14] B = 5 print statmean(A, B) ' Output: 5 Example 4: Using numbers A = 3 B = 5 C = 4 print statmean(A, B, C) ' Output: 4 +========================================================================================+ | 242. (Math) STATMEANDEV | +========================================================================================+ STATMEANDEV (...) Mean absolute deviation around arithmetic mean. var1 to varN can be single numbers or arrays. See: https://en.wikipedia.org/wiki/Average_absolute_deviation Example A = [2,2,3,4,14] print statmeandev(A) ' Output: 3.6 +========================================================================================+ | 243. (Math) STATMEDIAN | +========================================================================================+ STATMEDIAN (...) The median of a finite list of numbers is the “middle” number, when those numbers are listed in order from smallest to greatest. var1 to varN can be single numbers or arrays. see: Wikipedia - Median Example a = [1, 3, 3, 6, 7, 8, 9] print statmedian(a) ' output: 6 +========================================================================================+ | 244. (Math) STATSPREADP | +========================================================================================+ STATSPREADS (...) Biased sample variance. var1 to varN can be single numbers or arrays. See: https://en.wikipedia.org/wiki/Variance#Sample_variance Example A = [1,2,3,4,6] print "Biased sample variance: "; statspreadp(A) print "Unbiased sample variance: "; statspreads(A) ' Output: ' Biased sample variance: 2.96 ' Unbiased sample variance: 3.7 +========================================================================================+ | 245. (Math) STATSPREADS | +========================================================================================+ STATSPREADP (...) Unbiased sample variance. var1 to varN can be single numbers or arrays. See: https://en.wikipedia.org/wiki/Variance#Sample_variance Example A = [1,2,3,4,6] print "Biased sample variance: "; statspreadp(A) print "Unbiased sample variance: "; statspreads(A) ' Output: ' Biased sample variance: 2.96 ' Unbiased sample variance: 3.7 +========================================================================================+ | 246. (Math) STATSTD | +========================================================================================+ STATSTD (...) (Corrected sample) standard deviation. var1 to varN can be single numbers or arrays. see: Wikipedia - Standard Deviation Example 1: Using an array A = [2,2,4,4,14] print statstd(A) ' Output: 5.09901951359278 Example 2: Using two arrays A = [2,2,3,4,14] B = [7,9,7] print statstd(A, B) ' Output: 4.14039335605413 Example 3: Using an array and a number A = [2,2,3,4,14] B = 5 print statstd(A, B) ' Output: 4.56070170039655 Example 4: Using numbers A = 3 B = 5 C = 4 print statstd(A, B, C) ' Output: 1 +========================================================================================+ | 247. (Math) SUM | +========================================================================================+ SUM (...) Sum of value(s) var1 to varN. var1 to varN are single numbers or arrays. Example A = [1, 2, 3] print sum(1, 2, 3) ' Output: 6 print sum(A) ' Output: 6 print sum(A, 1, 2, 3) ' Output: 12 +========================================================================================+ | 248. (Math) SUMSQ | +========================================================================================+ SUMSQ (...) Sum of square value(s) var1 to varN. var1 to varN are single numbers or arrays. Example A = [1, 2, 3] print sumsq(1, 2, 3) ' 1^2 + 2^2 + 3^2 -> Output: 14 print sumsq(A) ' Output: 14 print sumsq(A, 1, 2, 3) ' Output: 28 +========================================================================================+ | 249. (Math) TAN | +========================================================================================+ TAN (x) Tangent of x. x is in radian. See also COS, SIN, TAN and ATAN. Example 1 a = tan(0.5) print a ' Output: 0.54630248984379 b = atan(a) print b ' Output: 0.5 Example 2 ' Short TAN use.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-14 ' in the following example it is important to keep in mind ' x,y when used in TAN are relative positions to x1,y1 and not ' absolute screen coordinates ' you can move x1,y1 anywhere on screen!!!! x1 = 250 y1 = 150 angle = 60 ' degree ' highlight start point with a circle in yellow with radius 2 circle x1, y1, 2, 1, 14 ' circle x,y,r,aspect,c 'aspect 1 is circle, !1=ellipse ' say you want to make a line 60 degrees from x1,y1 and ' you need the x2 100 greater than x1 or x2 = x1+100 ' since we know TAN=y/x (though you need a diagram to see it) ' then TAN(RAD(60)) = y/100 ' then 100*TAN(rad(60) = y by algebraic mult 100 both sides ' so y2=y1+100*TAN(rad(60) line x1, y1, x1 + 100, y1 + 100*TAN(RAD(angle)) ' <== HERE IS TAN ' so here we used TAN to calculate the y change in height ' from y1 to create a 60 angle from point x1,y1 and x2,y2 AND ' AND make it so x2=100 more than x1 ' check draw arc at x1,y1 with 100 radius ' for 0 degrees start to 60=2*pi/6 radians end arc, 1=aspect arc x1, y1, 100, 0, RAD(angle), 1, 14 ' 14 = color yellow Trigonometry lesson Review: Trigonometry is the study of right triangles, those that have one 90 degree angle AKA Pi/2 in radians. These right triangles are infinite in a rectilinear coordinate system with x,y referring to screen position in relation to an origin point (0,0). In SmallBASIC the y axis increases from top to bottom and in SmallBASIC the angle measures used for arguments to SIN and COS and the other Trig Angles are expected to be in radian measure as opposed to degree measure. This is a standard conflict and source of confusion from what you might learn in math class and doing stuff on a computer. For all triangles that have all 3 angles the same, their legs will have exactly the same ratios between themselves. Feed a trig function an angle and it will return the special ratio between the sides of the triangle that is universal to all triangles that have the same equal angle measures. Feed the COS function an angle and it will return the universal ratio for the leg adjacent divided by the hypotenuse. ( Adjacent means next to or attached in the case of angles.) Some more information gained from study or right angles: The COS for one acute angle in a right triangle is the SIN for the other acute angle. For 45 degree angle (Pi/4 radians) the two legs are the same therefore SIN(RAD(45 degrees)) = COS(RAD(45 degrees)) = .7071… notice if that is squared =.5 exactly 1-COS(angle)^(2=SIN(angle))2 As the angle size approaches 0, COS(angle) > 1 and SIN(angle) >0 At angle = 0 you have more a line segment than a triangle. Similarly as angle approaches 90 degrees = Pi/2 radians, the COS(angle) ratio approaches> 0 and SIN(angle) >1 Trig functions are Unary Operators, they take one argument, an angle expressed in Radians, and return to you the ratio of the triangle sides involved. The COS returns the ratio of the leg adjacent the angle divided by the hypotenuse. adj/hyp The SIN function returns the leg opposite the angle fed the function divided by the hypotenuse. opp/hyp The third main trig function is TAN, tangent. opp/adj The TAN(angle in radians) returns the ratio of the opp side divided by the adjacent side. In SmallBASIC this is very handy because side opposite/ side adjacent is the same as y/x the same two items that define a point location! Can you see what this means? Does a chill of revelation run up and down your spine? Oh! that means for any point x,y on the screen, I can find the angle it is from the origin! It is the ATAN(y/x) We are almost ready now to play pin the tail on the donkey! Hang in there… The A before the TAN, the A before the SIN, COS… means ARC ATAN is pronounced ARC TANGENT; ACOS is pronounced ARC COSINE; ASIN is pronounced ARC SIN. In each the ARC means The Angle whose Trig Ratio is: (ratio of two sides) so ATAN is the Angle whose TAN ratio is (opp leg lentgh/adj leg length) We feed ATAN a leg ratio argument and it tells what angle that ratio came from. ARC in the Language reference is referred to as “the inverse” If TAN( an angle) = ratio then ATAN( ratio=opp/adj ) = an angle (in radians) DEG(ATAN(opp/adj) = an angle in degrees You can think or the A in front of TAN or COS or SIN as give me “An Angle” without the A you get side ratios. +========================================================================================+ | 250. (Math) TANH | +========================================================================================+ TANH (x) Hyperbolic tangent. a = tanh(0.5) print a b = atanh(a) print b +========================================================================================+ | 251. (Math) TRANSPOSE | +========================================================================================+ TRANSPOSE (A) Calculates the transpose A of a 2D matrix or a vector M. Example 1: Transpose of a vetor A = [1;2;3;4] print transpose(A) ' output: [1,2,3,4] Example 2: Transpose of a matrix A = [1,2; 3,4; 5,6] print transpose(A) ' output: [1,3,5;2,4,6] +========================================================================================+ | 252. (String) ASC | +========================================================================================+ ASC (s) Returns the ASCII code of first character of the string s. See CHR for converting a ASCII code to a character. Example 1 print "ASCII value of A is "; ASC("A") ' Output: ASCII value of A is 65 Example 2: Create an ASCII table. LOCATE 1,16 : ? "ASC Table 30-129:" ' locate print spot, print title for our app FOR column = 0 to 9 ' print a header, 10 numbers plus + (to add to row value) LOCATE 2, column * 5 + 4 : ? "+"; column NEXT FOR row = 3 to 12 LOCATE row, 0 : ? RIGHT(" " + STR(row * 10) + ":", 4) NEXT 'main table FOR ASCnumber = 30 to 129 ' note ASC(32) = space so wont see anything in Table row = ASCnumber \ 10 ' \ rounds division down to integer column = (ASCnumber MOD 10) * 5 + 5 ' times 5 to space out the characters printed plus 5 for column labels LOCATE row,column : ? CHR(ASCnumber) NEXT +========================================================================================+ | 253. (String) BCS | +========================================================================================+ BCS (s) Converts the BASIC-style string s to C-style string by masking escape codes. Escape codes in the string will not be applied to format the string when printed on the screen. Instead escape codes will be printed as they are. See CBS to unmasked a c-style string, and see article “Escape codes” for more information about escape codes. Example ' define some escape codes const NORMAL = "\e[0m" ' = Cat(0) const BOLD = "\e[1m" ' = Cat(1) const BOLD_OFF = "\e[21m" ' = Cat(-1) const BG_CYAN = "\e[46m" const TB = "\t" ' Create a string with escape codes BasicStyleString = BOLD + "BOLD" + BOLD_OFF + TB + TB + BG_CYAN + "COLORFULL BG" + NORMAL CStyleString = bcs(BasicStyleString) BackConverted_BasicStyleString = cbs(CStyleString) print "Basic-style string : "; BasicStyleString print "C-style string : "; CStyleString print "Back conversion to basic style: "; BackConverted_BasicStyleString ' Output will be (with colors and in bold) ' Basic-style string : BOLD COLORFULL BG ' C-style string : \e[1mBOLD\e[21m\t\t\e[46mCOLORFULL BG\e[0m ' Back conversion to basic style: BOLD COLORFULL BG +========================================================================================+ | 254. (String) BIN | +========================================================================================+ BIN (x) Returns the binary value of x as string. Example print hex(255) ' output: FF print bin(8) ' output: 1000 print oct(16) ' output: 20 +========================================================================================+ | 255. (String) CBS | +========================================================================================+ CBS (s) Converts C-style string s to BASIC-style string by unmasking escape codes. Escape codes in the string will be applied to format the string when printed on the screen. See BCS to masked a BASIC-style string, and see article “Escape codes” for more information about escape codes. Example ' define some escape codes const NORMAL = "\e[0m" ' = Cat(0) const BOLD = "\e[1m" ' = Cat(1) const BOLD_OFF = "\e[21m" ' = Cat(-1) const BG_CYAN = "\e[46m" const TB = "\t" ' Create a string with escape codes BasicStyleString = BOLD + "BOLD" + BOLD_OFF + TB + TB + BG_CYAN + "COLORFULL BG" + NORMAL CStyleString = bcs(BasicStyleString) BackConverted_BasicStyleString = cbs(CStyleString) print "Basic-style string : "; BasicStyleString print "C-style string : "; CStyleString print "Back conversion to basic style: "; BackConverted_BasicStyleString ' Output will be (with colors and in bold) ' Basic-style string : BOLD COLORFULL BG ' C-style string : \e[1mBOLD\e[21m\t\t\e[46mCOLORFULL BG\e[0m ' Back conversion to basic style: BOLD COLORFULL BG +========================================================================================+ | 256. (String) CHOP | +========================================================================================+ CHOP (source) Chops off the last character of the string source. Example s = "Test" print chop(s) ' Output: Tes +========================================================================================+ | 257. (String) CHR | +========================================================================================+ CHR (x) Returns an one-char string of character with ASCII code x. See ASC to convert a character to ASCII code. Example 1 print "ASCII code 65 is '" + chr(65) + "'" ' Output ASCII code 65 is 'A' Example 2: Get escape character The CHR command is useful for obtaining and printing the escape character (ASCII 27). For more information about escape codes see article “Escape Codes” PRINT CHR(27) + "[1mTHIS IS BOLD" + CHR(27) + "[0m" PRINT CHR(27) + "[3mThis is italic" + CHR(27) + "[0m" PRINT CHR(27) + "[4mThis is underline" Example 3: Print ASCII table REM display the ASCII and the extended tables For n = 0 To 255 If n = 0 Then Color 15, 0: Locate 1, 1 Print "Standard 7-bit ASCII table (character codes 0 - 127):"; Elseif n = 128 Then print print Input "Press return to see nonstandard table", k Color 15, 0: Cls: Locate 1, 1 Print "Nonstandard 8-bit Extended table (character codes 128 - 255):"; Endif If n <= 31 Then ' control characters (e.g. new-line, tab, etc). Read c Elseif n = 32 Then ' regular space (invisible...) c = "sp" Elseif n = 127 Then ' lonesome control character "del" c = "del" Else c = Chr(n) ' ASCII code --> character Endif Locate (n Mod 16) + 3, (((n \ 16) Mod 8) * 9) + 1 Color 7: Print Using "000 "; n; ' ASCII code Color 14: Print c; ' ASCII (or ANSI) character Next Color 7, 0: Print: Print Print " * Nonstandard characters might look different on another system." End ' nonprintable control characters (ASCII codes 0..31): Data "nul", "soh", "stx", "etx", "eot" ' 0..4 Data "enq", "ack", "bel", "bs" , "tab" ' 5..9 Data "lf" , "vt" , "np" , "cr" , "so" ' 10..14 Data "si" , "dle", "dc1", "dc2", "dc3" ' 15..19 Data "dc4", "nak", "syn", "etb", "can" ' 20..24 Data "em" , "eof", "esc", "fs" , "gs" ' 25..29 Data "rs" , "us" ' 30..31 +========================================================================================+ | 258. (String) DISCLOSE | +========================================================================================+ DISCLOSE (str[, pairs [, ignore-pairs]]) Discloses the string str. pairs is a string of 2n characters. Two consecutive characters form a pair. The characters of str which are positioned between the first matching pair of pairs will be returned. ignore-pairs is a string with 2n characters. Two consecutive characters form a ignore-pair. All characters of str between an ignore-pair will be ignored (not returned). if pairs and ingnore-pairs are not given, the following default pairs and ignore pairs will be used: First non white-space character Check Ignore --------------------------------- ------- --------- ” ” ” ’ ’ ’ ’ ’ ” ” ( () ” ” ’ ’ [ [] ” ” ’ ’ { {} ” ” ’ ’ < <> ” ” ’ ’ Example 1: Disclose default pairs s = "(abc)" print disclose(s) ' Output: abc Example 2: Disclose non-default pairs s = "_abc_" print disclose(s, "__") ' Output: abc s = "([abc])" print disclose(s, "[]") ' Output: abc s = "([abc])" print disclose(s, "[)") ' Output: abc] s = "[(abc)]" print disclose(s, "()[]") ' Output: (abc) s = "abc (def)" print disclose(s, "()") ' Output: def s = "abc (d(ef))" print disclose(s, "()") ' Output: d(ef) Example 3: Disclose with ignore-pairs s = "abc [d(ef)] (gh)" print disclose(s, "()", "[]") ' Output: gh +========================================================================================+ | 259. (String) ENCLOSE | +========================================================================================+ ENCLOSE (str[, pair]) Encloses a string using the two characters in string pair. ENCLOSE defaults to double quotes if pair is not used. Example 1: Enclose brackets print enclose("abc", "()") ' output: (abc) Example 2: Enclose quotes using default setting test=10 myStr="myStr" print enclose(test) ' output: "10" print enclose(myStr) ' output: "myStr" Example 2: Enclose letters test = 10 print enclose(test, "aB") ' output: a10B +========================================================================================+ | 260. (String) FORMAT | +========================================================================================+ FORMAT (format, val) Returns a formated string. Numbers: Format Description -------- ----------------------------------------- # Digit or space 0 Digit or zero ^ Stores a number in exponential format. . The position of the decimal point. , Separator - Stores minus if the number is negative. + Stores the sign of the number. Strings: ----------------------------------------------------------------------- Format Description --------------------------- ------------------------------------------- & Stores a string expression without reformatting it. ! Stores only the first character of a string expression. \\ \\ Stores only the first n + 2 characters of a string expression, where n is the number of spaces between the two pairs of backslashes. ----------------------------------------------------------------------- When using \\ \\, literals can be inside the \\ \\. These literals are inserted in the final string. Example 1 PRINT FORMAT("####.##", 1920.64) ' output 1920.64 PRINT FORMAT("#######", 1920.64) ' output 1921 PRINT FORMAT("#,###.##", 1920.64) ' output 1,920.64 PRINT FORMAT("#,###.00", 1920.6 ) ' output 1,920.60 PRINT FORMAT("#,###", 1920.6 ) ' output 1,921 PRINT FORMAT("###,###.00", 1920.6 ) ' output 1,920.60 PRINT FORMAT("00#,###.00", 1920.6 ) ' output 001,920.60 PRINT FORMAT("#####^", 1920.6 ) ' output 1,9E+3 PRINT FORMAT("+#,###.00", 1920.6 ) ' output +1,920.60 PRINT FORMAT("+#,###.00", -1920.6 ) ' output -1,920.60 PRINT FORMAT("-#,###.00", 1920.6 ) ' output 1,920.60 PRINT FORMAT("-#,###.00", -1920.6 ) ' output -1,920.60 PRINT FORMAT("!", "Test") ' output T PRINT FORMAT("\\\\", "Test") ' output Te PRINT FORMAT("\\ \\", "Test") ' output Tes PRINT FORMAT("\\ X \\", "abcde") ' output abcXde PRINT FORMAT("\\ X Y \\", "abcde") ' output abXcYde PRINT FORMAT("&\\ X Y \\", "abcde") ' output abcde Example 2: Printing numbers in columns for y = 1 to 10 for x = 1 to 5 print format("#,###.00 ", (rnd*200000 - 100000)/100); next print next Example 3 PRINT USING and FORMAT use same or similar character codes, here are some practical examples of use, including the creating of a reusable money function that returns a flexible length string for a money amount (dollars and cents format). ' USING FORMAT Money.bas 2016-03-06 SmallBASIC 0.12.2 [B+=MGA] ' PRINT USING is excellent for columns of numbers ' A problem with PRINT USING is that it needs a whole statement to itself, ' unlike PRINT that can print a list of expressions in a single statement (with ; , or +) ' another problem with USING, # is that they are place holders which is nice ' for column of numbers but not in following: currency = "$-###,###,###,###,###,###.00" bignumber = "###,###,###,###,###,###" onetrillion = 1000000000000 workers = 150000000 ? "First version:" ? using currency; onetrillion; ? " divided by "; ? usg bignumber; workers; '<=== usg is short for using ? " working people is "; ? usg currency; onetrillion / workers; ? " per working person." ?:? ' Yuck! we need to trim things up, FORMAT works nicely with TRIM division = "$ " + trim(format(bignumber, onetrillion / workers)) onetrillion1 = "$ " + trim(format(bignumber, onetrillion)) workers1 = trim(format(bignumber, workers)) ? "Second version with trim:" ? onetrillion1 + " divided by " + workers1; " working people is "; division; " per working person." ?:? ' lets use what we learned here and make a reusable function: money ? "Third version as a function:" ? money(onetrillion); " divided by "; workers1; " working people is " + money(onetrillion/workers) + " per working person." ?:? ' Print money as columns like in a table. We need to have the same length strings use RIGHT and SPACE ? "Money table:" for i = 1 to 50 if rnd > .5 then posneg = 1 else posneg = -1 endif print right(space(15) + money(rnd*10000000000/1000*posneg), 20); if i mod 5=0 then print '<== after printing 5 numbers in one line use print to start next line next func money(dollarsandcents) money = "$ " + trim(format("###,###,###,###,###,###.00", dollarsandcents)) end +========================================================================================+ | 261. (String) HEX | +========================================================================================+ HEX (x) Returns the hexadecimal value of x as string. Example print hex(255) ' output: FF print bin(8) ' output: 1000 print oct(16) ' output: 20 +========================================================================================+ | 262. (String) INSTR | +========================================================================================+ INSTR ([start,] s1, s2) Returns the position pos of the first occurrence of the string s2 in string s1 (starting from the position start). If there is no match, INSTR returns 0. Example 1: Get position starting a the beginning of the string s1 = "abcdef" s2 = "cd" print instr(s1, s2) ' Output 3 Example 2: Get position using a starting point s1 = "abcdefabcd" s2 = "ab" print instr(3, s1, s2) ' Output: 7 (instead of 1) +========================================================================================+ | 263. (String) JOIN | +========================================================================================+ JOIN words(), delimiters, string Join the elements of the array words with the delimiter delimiter and return the result as string s. Example ' Create an array words << "etc" words << "temp" words << 1 words << "filename.ext" ' Join then array elements JOIN words, "/", s PRINT s ' Output: etc/temp/1/filename.ext +========================================================================================+ | 264. (String) LCASE | +========================================================================================+ LCASE (s) Converts the string s to a lower case string ls. See UCASE for converting a string to upper case. Example s = "ABC" print lcase(s) ' Output: abc +========================================================================================+ | 265. (String) LEFT | +========================================================================================+ LEFT (s [,n]) Returns the n number of leftmost chars of string s as string ls. If n is not specified then n = 1. Example s = "abcdef" print LEFT(s) ' Output: a print LEFT(s, 3) ' Output: abc +========================================================================================+ | 266. (String) LEFTOF | +========================================================================================+ LEFTOF (s1, s2) Returns the left part of s1 at the position of the first occurrence of the string s2 in string s1. If s2 does not occure in string s1, an empty string will be returned. Example s1 = "abcdef" s2 = "de" print LEFTOF(s1, s2) ' Output: abc +========================================================================================+ | 267. (String) LEFTOFLAST | +========================================================================================+ LEFTOFLAST (s1, s2) Returns the left part of s1 at the position of the last occurrence of the string s2 in string s1. If s2 does not occure in s1, an empty string will be returned. Example s1 = "abcdefdeg" s2 = "de" print LEFTOFLAST(s1, s2) ' Output: abcdef +========================================================================================+ | 268. (String) LOWER | +========================================================================================+ LOWER (s) Converts the string s to the lower-case string lc. Example: s = "TeSt-STrinG" print lower(s) ' Output: test-string +========================================================================================+ | 269. (String) LTRIM | +========================================================================================+ LTRIM (s) Removes leading white-spaces from string s. Example: s = " test " t = ltrim(s) print "-" + s + "-" print "-" + t + "-" ' Output: ' - test - ' -test - +========================================================================================+ | 270. (String) MID | +========================================================================================+ MID (s, start [,length]) Returns the substring of string s starting from the position start with length length. If the length parameter is omitted, MID returns the whole string from the position start. Example s = "abcd" print MID(s, 3) ' Output: cd print MID(s, 3, 1) ' Output: c +========================================================================================+ | 271. (String) OCT | +========================================================================================+ OCT (x) Returns the octal value of x as string. Example: print hex(255) ' output: FF print bin(8) ' output: 1000 print oct(16) ' output: 20 +========================================================================================+ | 272. (String) REPLACE | +========================================================================================+ REPLACE (source, pos, str [, len]) Writes the string str into string source at position pos and returns the new string. This function replaces len characters. The default value of len is the length of str. Example 1: print replace("abcdef", 3, "1") ' Output: ab1def print replace("abcdef", 3, "12") ' Output: ab12ef print replace("abcdef", 3, "123") ' Output: ab123f print replace("abcdef", 3, "1234") ' Output: ab1234 print replace("abcdef", 3, "1234", 0) ' Output: ab1234cdef <- inserted, no replacement print replace("abcdef", 3, "1234", 1) ' Output: ab1234def <- only c was replaced print replace("abcdef", 3, "1234", 2) ' Output: ab1234ef <- only cd was replaced print replace("abcdef", 3, "", len("abcdef")) ' Output: ab <- cut Example 2: Const TEXT = "Red Green Blue" ' Text to replace: Const Len_TEXT = Len(TEXT) Const BLANKS = Len_TEXT - Len(Translate(TEXT, " ", "")) ' number of blanks in TEXT Const ESCS = Chr(27) + "[" Const BG_BLACK = ESCS + "40m" Const BG_RED = ESCS + "41m" Const BG_GREEN = ESCS + "42m" Const BG_BLUE = ESCS + "44m" Const BG_YELLOW = ESCS + "43m" ' Helper to print the "name of color" with its color: func colors(s) s = Translate(s, "Red", BG_RED + "Red" + BG_BLACK) s = Translate(s, "Green", BG_GREEN + "Green" + BG_BLACK) s = Translate(s, "Blue", BG_BLUE + "Blue" + BG_BLACK) s = Translate(s, "Yellow", BG_YELLOW + "Yellow" + BG_BLACK) s = Translate(s, " ", "_") colors = s End Func Def lset(s) = Replace(Space(30), 1, s + ": ") ' left justify s in buffer color 15,0 cls ' Syntax: REPLACE (source, pos, str [, len]): ? lset("TEXT is"); colors(TEXT) ? ? lset("Replace Green with Yellow"); colors(Replace(TEXT, 5, "Yellow", 5)) ? lset("Append Yellow"); colors(Replace(TEXT, Len_TEXT + 1, " Yellow")) ? lset("Prepend Yellow"); colors(Replace(TEXT, 1, "Yellow ", 0)) ? lset("Insert Yellow after Red"); colors(Replace(TEXT, 5, "Yellow ", 0)) ? ? lset("Delete Green"); colors(Replace(TEXT, 5, "", 6)) ? lset("Chop Red"); colors(Replace(TEXT, 1, "", 4)) ? lset("Chop Blue"); colors(Replace(TEXT, Instr(TEXT, " Blue"), "", Len(" Blue"))) ? ? lset("Left justify TEXT in buffer"); colors(Replace(Space(30), 1, TEXT)) ? lset("Right justify TEXT in buffer"); colors(Replace(Space(30), 30 - Len_TEXT + 1, TEXT)) ? lset("Center TEXT in buffer"); colors(Replace(Space(30), 15 - (Len_TEXT \ 2) + 1, TEXT)) ? lset("(Justify TEXT in buffer)"); colors(Translate(TEXT, " ", Space((30 + BLANKS - Len_TEXT) / BLANKS))) ? ? lset("Replace TEXT with Yellow"); colors(Replace(TEXT, 1, "Yellow", Len_TEXT)) ? lset("Override TEXT with Yellow"); colors(Replace(TEXT, (Len_TEXT / 2) - 3 + 1, "Yellow")) ? lset("Delete TEXT"); colors(Replace(TEXT, 1, "", Len_TEXT)) ? lset("Create TEXT"); colors(Replace("", 1, TEXT)) +========================================================================================+ | 273. (String) RIGHT | +========================================================================================+ RIGHT (s[,n]) Returns the n number of rightmost chars of string s. If n is not specified n = 1. Example s = "abcdef" print right(s) ' Output: f print right(s,2) ' Output: ef print right(s,10) ' Output: abcdef +========================================================================================+ | 274. (String) RIGHTOF | +========================================================================================+ RIGHTOF (s1, s2) Returns the right part of string s1 at the position of the first occurrence of string s2 in s1. If s2 does not occure in s1 RIGHTOF returns an empty string. Example s = "abcdef" print rightof(s, "cd") ' Output: ef print rightof(s, "a") ' Output: bcdef print rightof(s, "f") ' Output: print rightof(s, "xx") ' Output: +========================================================================================+ | 275. (String) RIGHTOFLAST | +========================================================================================+ RIGHTOFLAST (s1, s2) Returns the right part of string s1 at the position of the last occurrence of string s2 in s1. If s2 does not occure in s1 RIGHTOFLAST returns an empty string. Example s = "abcdefcd123" print rightoflast(s, "cd") ' Output: 123 print rightoflast(s, "a") ' Output: bcdefcd123 print rightoflast(s, "3") ' Output: print rightoflast(s, "xx") ' Output: +========================================================================================+ | 276. (String) RINSTR | +========================================================================================+ RINSTR ([start,] s1, s2) Returns the position of the last occurrence of string s2 in string s1 starting from the position start. If there is no match, RINSTR returns 0 Example s = "ab12ab34" print rinstr(s, "ab") ' Output: 5 print rinstr(6, s, "ab") ' Output: 0 +========================================================================================+ | 277. (String) RTRIM | +========================================================================================+ RTRIM (s) Removes trailing white-spaces from string s. Example s = " abcd " print ">" + s + "<" ' Output: > abcd < print ">" + rtrim(s) + "<" ' Output: > abcd< +========================================================================================+ | 278. (String) SINPUT | +========================================================================================+ SINPUT src; var [, delim] [,var [, delim]] ... Splits the string src into substrings which are separated by delimiters delim1 to delimN and returns the substrings as var1 to varN. Delimiters can be single characters, numbers or strings. Example 1: Split string with delimiter “,” src = "1456,Peter,8" SINPUT src; id, ",", name, ",", age print "ID : " + id print "Name: " + name print "Age : " + age ' Output: ' ID : 1456 ' Name: Peter ' Age : 8 Example 2: Split string with complex delimiters src = "if x>1 then y" SINPUT src; vif, " ", vcond, "then", vdo print vif, vcond, vdo ' Output: if x>1 y +========================================================================================+ | 279. (String) SPACE | +========================================================================================+ SPACE (n) Returns a string of n spaces. SPACE is identical to SPC. Example 1: print "A" + space(5) + "B" ' Output: A B Example 2: Insert string into a buffer ' s is a string ("" or longer); l is length of buffer (0+); Def lset(s, l) = Left(s + Space(l), l) ' left justify text Def rset(s, l) = Right(Space(l) + s, l) ' right justify text Const buffer = 10 ' length of buffer While True Do Color 7, 0: Cls Print "[ Using a buffer of "; buffer; " spaces ]" Print Input "Enter text into buffer (Enter 'S' to stop): ", text IF text = "S" Or text = "s" Then Stop Endif Color 7, 0: Locate 5, 0: Print "Left justified: "; Color 0, 7: Print lset(text, buffer); Color 7, 0: Locate 7, 0: Print "Right justified: "; Color 0, 7: Print rset(text, buffer); Pause Wend +========================================================================================+ | 280. (String) SPC | +========================================================================================+ SPC (n) Returns a string of n spaces. SPC is identical to SPACE. Example 1: print "A" + spc(5) + "B" ' Output: A B Example 2: Insert string into a buffer ' s is a string ("" or longer); l is length of buffer (0+); Def lset(s, l) = Left(s + Spc(l), l) ' left justify text Def rset(s, l) = Right(Spc(l) + s, l) ' right justify text Const buffer = 10 ' length of buffer While True Do Color 7, 0: Cls Print "[ Using a buffer of "; buffer; " spaces ]" Print Input "Enter text into buffer (Enter 'S' to stop): ", text IF text = "S" Or text = "s" Then Stop Endif Color 7, 0: Locate 5, 0: Print "Left justified: "; Color 0, 7: Print lset(text, buffer); Color 7, 0: Locate 7, 0: Print "Right justified: "; Color 0, 7: Print rset(text, buffer); Pause Wend +========================================================================================+ | 281. (String) SPLIT | +========================================================================================+ SPLIT string, delimiters, words() [, pairs] [USE expr] Splits the string s at the position of the given delimiters delim and returns an array words with the splitted substrings. The optional parameter pairs can be used to group words. The optional Use expr is applied to every splitted substring. If delim contains more than one character, each character representing a delimiter. See SINPUT for an alternative command to split a string. Example 1: Split a string using two delimiters s = "/etc/temp/filename.ext" SPLIT s, "/.", v ' Splits the string using the delimiters "/" and "." FOR i = 0 TO UBOUND(v) PRINT i; " ["; v(i); "]" NEXT ' Output: ' 0 [] ' 1 [etc] ' 2 [temp] ' 3 [filename] ' 4 [ext] Example 2 : Using the argument “pairs” s = "/etc/temp/filename.ext" SPLIT s, "/", v, "temp" FOR i = 0 TO UBOUND(v) PRINT i;" [";v(i);"]" NEXT ' Display 0 [] 1 [etc/temp] 2 [filename.ext] Example 3: Using “USE expr” s = "/etc/temp/filename1.ext " ' additional spaces at the end of the string SPLIT s, "/", v, "temp" USE TRIM(x) ' trim(x) will remove spaces at the beginning ' and the end of the splitted strings; ' try the example without "USE TRIM(x)" FOR i = 0 TO UBOUND(v) PRINT i;" [";v(i);"]" NEXT ' displays ' 0 [] ' 1 [etc/temp] ' 2 [filename1.ext] +========================================================================================+ | 282. (String) SPRINT | +========================================================================================+ SPRINT var; [USING...;] ... Create a formated string and storing it to string s. SPRINT supports all features of PRINT. See PRINT for detailed information. USG can be used instead of USING. Example a = 1000 b = 2000 SPRINT s1; USING "a = #####.00 b = ##,###"; a; b SPRINT s2; "a + b = "; a; " + "; b; " = "; a + b print s2 ' Output a = 1000.00 b = 2,000 print s1 ' Output: a + b = 1000 + 2000 = 3000 +========================================================================================+ | 283. (String) SQUEEZE | +========================================================================================+ SQUEEZE (s) Removes all leading, trailing and duplicated white-space from string s. Example: s = " Hi there " print "["; s ; "]" print "["; SQUEEZE(s); "]" 'Output: ' [ Hi there ] ' [Hi there] +========================================================================================+ | 284. (String) STR | +========================================================================================+ STR (n) Converts the number n into a string. Example n = 1.123 s = str(n) +========================================================================================+ | 285. (String) STRING | +========================================================================================+ STRING ( count [,start | s] ) Creates a new string, which repeats the string str count times. If instead of a string a number chr is given, chr will be interpreted as an ASCII-code and the corresponding character will be repeated count times. Example print string(4, "A") ' Output: AAAA print string(4, "AB") ' Output: ABABABAB print string(4, 65) ' Output: AAAA +========================================================================================+ | 286. (String) TRANSLATE | +========================================================================================+ TRANSLATE (source, what [, with]) Translates all occurrences of the string what found in string source with the string with and returns the new string. If with is not given, all occurrences of what will be removed. Example 1: Replace s1 = "ab_cd_ef" s2 = translate(s1, "_", "!") print s1 + " -> "; s2 ' Output: ab_cd_ef -> ab!cd!ef Example 2: Remove s1 = "ab_cd_ef" s2 = translate(s1, "cd") print s1 + " -> "; s2 ' Output: ab_cd_ef -> ab__ef +========================================================================================+ | 287. (String) TRIM | +========================================================================================+ TRIM(s) Removes all leading and trailing white-space from string s. Example s = " test " t = trim(s) print "->" + s + "<-" print "->" + t + "<-" ' Output: ' -> test <- ' ->test<- +========================================================================================+ | 288. (String) UCASE | +========================================================================================+ UCASE (s) Converts the string s to a upper case string us. See LCASE for converting a string to lower case. UCASE and UPPER are equivalent. Example s = "abc" print ucase(s) ' Output: ABC +========================================================================================+ | 289. (String) UPPER | +========================================================================================+ UPPER (s) Converts the string s to a upper case string us. See LCASE and LOWER for converting a string to lower case. UPPER and UCASE are equivalent. Example s = "abc" print upper(s) ' Output: ABC +========================================================================================+ | 290. (String) VAL | +========================================================================================+ VAL (s) Returns the numeric value of string s. If s cannot be converted to a number, VAL will return 0. VAL does not evaluate the string. Example print val("123") ' Output: 123 print val("123e2") ' Output: 12300 print val("0xFF") ' Output: 255 print val("123*2") ' Output: 123 print val("123abcd") ' Output: 0 print val("seven") ' Output: 0 +========================================================================================+ | 291. (System) CHAIN | +========================================================================================+ CHAIN source Compile and run the given source. source can be a file name, a line of code or an array of code. Use ENV to share variables with the parent process. Example 1: Using constants Note: \" is used to create a quote inside the string Chain "? \"100 + 50 is: \"; 100 + 50" ' Output: 100 + 50 is: 150 Example 2: Using variables Env "SB1=6" Env "SB2=2" Chain "? Env(\"SB1\") ^ Env(\"SB2\")" ' Output: 36 Example 3: Using an array Env "SB1=3" Dim a() a << "x = Env(\"SB1\")" a << "For i = 1 To 5" a << "? i * x; Spc(1);" a << "Next i" Chain a ' Output: 3 6 9 12 15 Example 4: Using a file and returning a value ' First we have to create a bas-file to show how chain works with files ' Create an array Env "SB1=4" Dim a() a << "x = Env(\"SB1\")" a << "For i = 1 To 5" a << "? i * x; Spc(1);" a << "Next i" a << "Env \"SB1=\" + Str(i):" ' Return value using SB1 ' Write array to file tsave("chaindemo.bas", a) ' Peparations are done. Now a bas-file can be chained Chain "chaindemo.bas" print print "Return value SB1 is: "; Env("SB1"); ' Output: ' 4 8 12 16 20 ' Return value SB1 is: 6 Example 5: ' Create demo bas file (could be any SmallBASIC file): Open "chaindemo.bas" For Output As #1 ? #1, "Sub count10(n)" ? #1, " Local i" ? #1, " Color 14" ? #1, " For i = n To 10 ? #1, " Print i; " + Enclose(", ") + ";" ? #1, " Next i" ? #1, " Env " + Enclose("SB1=") + " + Str(i) ' return value to parent ? #1, "End Sub" ? #1, ? #1, "Color 7: ? " + Enclose("I'm The Child Program...! I can count!") + ": ?" ? #1, ? #1, "n = Val(Env(" + Enclose("SB1") + ")) ' get value from parent" ? #1, ? #1, "count10 n ' run sub-routine to count n to 10" ? #1, ? #1, "?:?" Close #1 ' Load demo bas file into array: Tload "chaindemo.bas", lines Env "SB1=2" ' Set value for child program (1..10) ' Execute the demo bas file (the array): Chain lines ' now print the return value from child program: Color 7: ? "I'm The Parent Program..." ? Color 15: ? "Child program returned value: "; Env("SB1") Example 6: Creating an eval function ' Dedicated to MGA. ' s is any legal SmallBASIC Math Expression as String, e.g. "1 + 2 / 4" Func eval(s) Chain "Env " + Enclose("SBEVAL=") + " + Str(" + s + ")" eval = Val(Env("SBEVAL")) End Func ' now run few demos: ? eval("1+2") ? eval("Rad(45) * 2") ? eval("PI / 2 + PI") ? eval("0b1111 * Pow(2, 4)") ? eval("Sin(2) * Tan(4) / Cos(6)") ? eval("1 + 2 / 4") ? eval("6 * (Pow(2, 4) * 8)") ? eval("Rad((45 * 3) - 20) * 2") +========================================================================================+ | 292. (System) COMMAND | +========================================================================================+ COMMAND Returns a string s containing the SmallBASIC startup command line options. Example 1: SDL version (GUI) Running the following line from the command line: LINUX: sbasicg -r test.bas abc xyz fileName WINDOWS: sbasicg.exe -r test.bas abc xyz fileName When “test.bas” is: PRINT COMMAND Will print “abc xyz fileName” Note: When using the paramter -r in the above shown example, sbasicg will from now on always start the programm. If you want, that sbasicg starts again in edit-mode, please use the parameter -e LINUX: sbasicg -e test.bas WINDOWS: sbasicg.exe -e test.bas Example 2: Non-graphical console version (cygwin or linux) Running the following line from the command line: LINUX: sbasic test.bas abc xyz fileName WINDOWS: sbasic.exe test.bas abc xyz fileName When “test.bas” is: PRINT COMMAND Will print “abc xyz fileName” Example 3: Use SPLIT to separate parameters LINUX: sbasicg -r test.bas abc xyz fileName WINDOWS: sbasicg.exe -r test.bas abc xyz fileName When “test.bas” is: s = COMMAND() split s, " ", parameters print "First parameter : "; parameters[0] print "Second parameter: "; parameters[1] print "Third parameter : "; parameters[2] ' Output: ' First parameter : abc ' Second parameter: xyz ' Third parameter : fileName +========================================================================================+ | 293. (System) CWD | +========================================================================================+ CWD Gets current working directory. Example print cwd +========================================================================================+ | 294. (System) DELAY | +========================================================================================+ DELAY ms Delay for a specified amount of milliseconds ms. Note DELAY depends on the system clock. Example print "Wait 1000ms..." delay(1000) print "done" +========================================================================================+ | 295. (System) ENV | +========================================================================================+ ENV expr Adds a variable to the current environment variable-table. ENV can be used as SUB for setting and deleting Environment Variables and ENV can be used as a FUNCtion for returning a particular Environmet Variable or the whole set of them into an array. Example 1: Setting and getting Evironment Variables SB1 = 5 SB2 = "My evironment variable" 'Set Environmet Variables ENV("SB1=" + SB1) ENV("SB2=" + SB2) ENV("SB3=6") ENV("SB4=\"test\"") ' Get Environment Variables print ENV("SB1") print ENV("SB2") print ENV("SB3") print ENV("SB4") Example 2: Querry all Environment Variables AllEnv = ENV("") for a in AllEnv print a next Example 3: (Linux) Querry DESKTOP_SESSION print ENV("DESKTOP_SESSION") 'i.e will print "plasma" if using KDE Example 4: Delete a Environment Variable (doesn’t work in Linux) ENV("SB1=") ' Deletes SB1 Example 5: Using ENV and CHAIN to create a eval-function ' Dedicated to MGA. ' s is any legal SmallBASIC Math Expression as String, e.g. "1 + 2 / 4" Func eval(s) Chain "Env " + Enclose("SBEVAL=") + " + Str(" + s + ")" eval = Val(Env("SBEVAL")) End Func ' now run few demos: ? eval("1+2") ? eval("Rad(45) * 2") ? eval("PI / 2 + PI") ? eval("0b1111 * Pow(2, 4)") ? eval("Sin(2) * Tan(4) / Cos(6)") ? eval("1 + 2 / 4") ? eval("6 * (Pow(2, 4) * 8)") ? eval("Rad((45 * 3) - 20) * 2") General suggestions using Environment Variables 1. Never use names which are already used by the system or another process, such as “PATH”, “HOME”, “PWD”, etc. You should check which variable names are already in use. 2. Use short and unique names, such as: “SB1”, SB2” or “SBv1”, “SBv2”, etc. It will keep the environment-variables-table readable, and will save space in the table. 3. Don’t create more variables then you need. Reuse any variable which is not used. i.e. if “SB1” is unused anymore, then reuse it. 4. On some systems the environment-variables-table is unique for each session (Linux for example) and this may be a bit confusing. 5. Environment variables may or may not be case sensitive, i.e. “SB1” may be different then “sb1” on some systems (Linux for example). +========================================================================================+ | 296. (System) ENV | +========================================================================================+ ENV expr Reads an Environment Variable from the current environment variable-table. ENV can be used as SUB for setting and deleting Environment Variables and ENV can be used as a FUNCtion for returning a particular Environmet Variable or the whole set of them into an array. Example 1: Setting and getting Evironment Variables SB1 = 5 SB2 = "My evironment variable" 'Set Environmet Variables ENV("SB1=" + SB1) ENV("SB2=" + SB2) ENV("SB3=6") ENV("SB4=\"test\"") ' Get Environment Variables print ENV("SB1") print ENV("SB2") print ENV("SB3") print ENV("SB4") Example 2: Querry all Environment Variables AllEnv = ENV("") for a in AllEnv print a next Example 3: (Linux) Querry DESKTOP_SESSION print ENV("DESKTOP_SESSION") 'i.e will print "plasma" if using KDE Example 4: Delete a Environment Variable (doesn’t work in Linux) ENV("SB1=") ' Deletes SB1 Example 5: Using ENV and CHAIN to create a eval-function ' Dedicated to MGA. ' s is any legal SmallBASIC Math Expression as String, e.g. "1 + 2 / 4" Func eval(s) Chain "Env " + Enclose("SBEVAL=") + " + Str(" + s + ")" eval = Val(Env("SBEVAL")) End Func ' now run few demos: ? eval("1+2") ? eval("Rad(45) * 2") ? eval("PI / 2 + PI") ? eval("0b1111 * Pow(2, 4)") ? eval("Sin(2) * Tan(4) / Cos(6)") ? eval("1 + 2 / 4") ? eval("6 * (Pow(2, 4) * 8)") ? eval("Rad((45 * 3) - 20) * 2") General suggestions using Environment Variables 1. Never use names which are already used by the system or another process, such as “PATH”, “HOME”, “PWD”, etc. You should check which variable names are already in use. 2. Use short and unique names, such as: “SB1”, SB2” or “SBv1”, “SBv2”, etc. It will keep the environment-variables-table readable, and will save space in the table. 3. Don’t create more variables then you need. Reuse any variable which is not used. i.e. if “SB1” is unused anymore, then reuse it. 4. On some systems the environment-variables-table is unique for each session (Linux for example) and this may be a bit confusing. 5. Environment variables may or may not be case sensitive, i.e. “SB1” may be different then “sb1” on some systems (Linux for example). +========================================================================================+ | 297. (System) EXEC | +========================================================================================+ EXEC file Transfers control to the program file. Control returns to the calling bas-file immediately and the program is executed parallel and independent to SmallBASIC. File name is case sensitive in Linux. Enclose the string file with quotation marks to start a program with parameters. See run for starting an external program and wait until program finished execution. Example 1 ' Select your editor for testing exec "kate" ' Editor KDE 'exec "gedit" ' Editor Gnome 'exec "Notepad" ' Editor Windows print "This line will be printed immediately without delay" Example 2: Execute with parameters ' Call shutdown in Linux exec(enclose("shutdown -h now")) +========================================================================================+ | 298. (System) EXPORT | +========================================================================================+ EXPORT thing Export a SUB, FUNC or variable from a UNIT to be used by the unit consumer. See UNIT for more information. Example: Create an unit UNIT MyTestUnit export const my_pi = 3.145 export my_two_pi = 6.29 export MyFunc export MySub func MyFunc(a) return a + 10 end sub MySub(a) print a + 10 end +========================================================================================+ | 299. (System) FRE | +========================================================================================+ FRE (x) Returns system memory information. eg, 0 = free memory. If a value is not supported by the operating system, fre will return 0. fre() without a parameter returns the free physical memory. Windows x Description ----- --------------------------- 0 free memory -1 largest block of integers -2 free stack -3 largest free block -12 free memory same as 0 LINUX and ANDROID x Description ----- -------------------------------- 0 free memory -10 total physical memory -11 used physical memory -12 free physical memory same as 0 Alternative for LINUX with kernel > 3.x and ANDROID fre can be used to read the values of the file /proc/meminfo. In a console please type cat /proc/meminfo. Output should look similar to this (but more lines): MemTotal: 3630512 kB MemFree: 117204 kB MemAvailable: 601308 kB Buffers: 52680 kB Cached: 1002608 kB SwapCached: 58640 kB Active: 857224 kB Inactive: 1781244 kB To querry with fre the value of the first line, use fre(0), for second line fre(1), and so on. Example print "Free memory: "; fre() print "Total RAM: "; fre(-10) print "Used RAM: "; fre(-11) print "Free RAM: "; fre(-12) +========================================================================================+ | 300. (System) HOME | +========================================================================================+ HOME Returns the user home folder. Example 1: Get user home folder print home() ' output i.e: C:\Users\j7m Example 2: Change working directory to home directory h = home() chdir(h) print cwd +========================================================================================+ | 301. (System) IMPORT | +========================================================================================+ IMPORT Import an exported UNIT or a module with the name UnitName using the namespace MyName. See UNIT for an example on how to import an unit. Additionally, modules can be imported using IMPORT. Several modules are part of the release version. For more information on available modules and how to use them see the articels in the article section. Example 1: Import raylib module import raylib as r +========================================================================================+ | 302. (System) INCLUDE | +========================================================================================+ INCLUDE source-file.bas Inserts code from SourceFile when the program is compiled. INCLUDE can be used to split a large file into smaller parts. If you want to use include to create a library, then you should consider to use an UNIT instead. Example Create first file and save it as part1.bas. Print "This is part1.bas" for i = 1 to 5 print i next Create second file wich will include part1.bas. include part1.bas print "This is part2.bas" for i = 5 to 1 step -1 print i next ' Output: ' This is part1.bas ' 1 2 3 4 5 ' This is part2.bas ' 5 4 3 2 1 +========================================================================================+ | 303. (System) MAXINT | +========================================================================================+ MAXINT Returns the maximum value for an integer. The value depends on whether you are using a 32 or 64 bit build of SmallBASIC. Example print MAXINT ' Output 9223372036854775807 +========================================================================================+ | 304. (System) NIL | +========================================================================================+ NIL Sets a variable to nil. NIL is used to mean ‘not set’ as distinct from having a number set to 0. Example 1 b = NIL print b ' Output: Nil Example 2 b = NIL if(b == NIL) then print "b is not set" ' Output: b is not set +========================================================================================+ | 305. (System) OPTION | +========================================================================================+ OPTION keyword Used to pass parameters to the run-time environment. ----------------------------------------------------------------------- Option Description ----------------------------------- ----------------------------------- OPTION BASE 0,1 Set lowest allowed index of arrays to 0 or 1 OPTION PREDEF ANTIALIAS on,off Set anti-aliasing for drawing lines or circles OPTION MATCH PCRE [CASELESS]SIMPLE Set matching algorithm to (P)erl-(C)ompatible (R)egular (E)xpressions library or back to simple one for LIKE and FILES OPTION PREDEF QUIET Sets the quiet flag (-q option) OPTION PREDEF COMMAND cmdstr Sets the COMMAND$ string to cmdstr (useful for debug reasons) OPTION PREDEF GRMODE Sets the graphics mode flag (-g [WIDTHxHEIGHT[xBPP]] option) or sets the preferred screen resolution. Example: OPTION PREDEF GRMODE 320x320x16 OPTION PREDEF TEXTMODE Sets the text mode flag (-g- option) OPTION PREDEF CSTR Sets as default string style the C-style special character encoding (\) ----------------------------------------------------------------------- +========================================================================================+ | 306. (System) PAUSE | +========================================================================================+ PAUSE [secs] Waits for a key press, a mouse click or the optional amount of seconds secsbefore executing next statement. PAUSE may interfere with INKEY or PEN events. Example 1 print "Before PAUSE - press a key, mouse button or wait 5s" pause 5 print "After PAUSE" Example 2 ' ribbons.bas SmallBASIC 0.12.2 [B+=MGA] 2016-03-24 ' new and improved update of SB and Bpf posts 2015-04-16 B+ at 80,610: ? "Wait 8 secs or press any for next screen..." const a = 127 while 1 for i = 0 to 9 b = rnd^2 c = rnd^2 d = rnd^2 for x = 1 to 600 cl = RGB(a + a * sin(b * x), a + a * sin(c * x), a + a * sin(d * x)) line x, i * 60 + 1 step 0, 60, cl next x next i pause 8 '<=========== pause waits 8 secs or key press wend +========================================================================================+ | 307. (System) PI | +========================================================================================+ PI Returns PI. See: Wikipedia Example print PI ' Output: 3.1415... print cos(2*PI) ' Output: 1 +========================================================================================+ | 308. (System) PROGLINE | +========================================================================================+ PROGLINE Returns the current program line number. Print "first line of program" print PROGLINE ' Output: ' first line of program ' 2 +========================================================================================+ | 309. (System) RANDOMIZE | +========================================================================================+ RANDOMIZE [int] Seeds the random number generator. An optional integer number can be provided as the seed seed. If no seed is given, then the amount of clock ticks elapsed since the program was launched is used as the seed. Example: randomize randomize 15 +========================================================================================+ | 310. (System) RUN | +========================================================================================+ RUN cmdstr Loads a secondary copy of the system shell and executes a program or a shell command given by the string cmdstr. The execution of the calling BASIC program will be stoped and control returns to the BASIC program once the system command has completed. If RUN is called as a function, the return value s holds the text output of the executed command as a string. System commands, especially on Linux, are very powerful, and can add lots of valuable features to a SmallBASIC program. With system commands you can configure the COM port, send email (Linux at least), get lots of information about the environment, etc. In the Android version you can use s = RUN to look at information in the /proc file system. See EXEC if control should return to the BASIC program immediately. Use RUN in Windows In Windows (tested with Win10) you have to call the programm cmd which opens a command line window. The command you want to execute will be a parameter of cmd. Additional the parameter /C needs to be added to quit the command line window after execution of the command. Example 1: RUN as a function s = run("cmd /C dir") ' Execute DIR and print s ' print a list of files in the current directory s = run("cmd /C copy rename.txt rename1.txt") ' Copy a file (please create the file rename.txt before testing) print s ' Prints the text output of copy Example 2: RUN as procedure run("cmd /C copy rename.txt rename1.txt") ' Copy a file (please create the file rename.txt before testing) run("cmd /C notepad.exe") ' Start Notepad and wait until Notepad was closed Use RUN in Linux Commands to execute are case sensitive in Linux. Each command shell has an unique environment-variables-table; which means that you cannot always share environment variables with commands executed by RUN. Example 1: RUN as a function s = Run("ls") ' Execute ls and print a list of files in the print s ' current directory s = run("cp rename.txt rename1.txt") ' Copy a file (please create the file rename.txt before testing) print s ' Prints the text output of cy Example 2: RUN as procedure run("cp rename.txt rename1.txt") ' Copy a file (please create the file rename.txt before testing) run("gedit") ' Start gedit (if installed) and wait until gedit was closed Other Examples Example 1: Querry whether Linux or Windows is used const IS_LINUX = (Left(HOME, 1) = "/") ' Check if it's a Linux system const IS_WINDOWS = Not IS_LINUX print "LINUX: " + IS_LINUX print "Windows: " + IS_WINDOWS +========================================================================================+ | 311. (System) SBVER | +========================================================================================+ SBVER Shows version and build information. Example print SBVER ' Output: 12.26 Console Unix_64 Tue, 06 Jun 2023 +========================================================================================+ | 312. (System) SELF | +========================================================================================+ SELF Pseudo class instance variable The SELF variable works with MAP variables. You can assign a reference to a FUNC or SUB to a MAP variable. When you call the SUB or FUNC the SELF variable provides access to values from the enclosing MAP variable. This provides pseudo class/object functionality. Note: ‘MAP’ is the name given to the dictionary/hashmap variable variant. Example 1: SELF and MAP variable SUB hello print "hello " + self.world END a.world = "world" a.foo = @hello a.foo() Example 2: Simple Class func SimpleClass(i) sub Increment(i) self.x = self.x + i end sub Decrement(i) self.x = self.x - i end func GetX() return self.x end local temp temp.x = i temp.Increment = @Increment temp.Decrement = @Decrement temp.GetX = @GetX return temp end A = SimpleClass(1) print A.GetX() A.Increment(5) : print A.GetX() A.Decrement(4) : print A.GetX() +========================================================================================+ | 313. (System) STKDUMP | +========================================================================================+ STKDUMP Display internal execution stack. +========================================================================================+ | 314. (System) TROFF | +========================================================================================+ TROFF Turns off the trace mechanism. When trace mechanism is ON, SmallBASIC displays each line number as the program is executed. See TRON to switch on the trace mechanism. Example tron for ii = 1 to 5 next troff for ii = 1 to 5 next <2><3><3><3><3><3><5> +========================================================================================+ | 315. (System) TRON | +========================================================================================+ TRON Turns on the trace mechanism. When trace mechanism is ON, SmallBASIC displays each line number as the program is executed. See TROFF to switch off trace mechanism. Example tron for ii = 1 to 5 next ' Output: <2><3><3><3><3><3> +========================================================================================+ | 316. (System) UNIT | +========================================================================================+ UNIT name Declares the source module as a unit. Units are a set of procedures, functions, constants or variables that can be used by another program or unit. - UNIT supports ‘namespace’ (Namespaces allow reuse of same names in different contexts. e.g. BitLib.Set(x) and StrLib.Set(x) are both using a function with the same name, “Set”, but in different contexts). - While UNIT can be used as a collection of sub-routines for your own program, UNIT is particularly useful for creating a general-purpose library. General purpose libraries can be useful for many programs or projects, the same way the internal routine “PRINT” is useful for many programs, and not only for specific one. Use EXPORT to export procedures, functions, constants or variables. Only exported names can be accessed in the main program. Example 1: Simple Unit First, an example of the unit. Please save it with the filename “MyTestUnit.bas” UNIT MyTestUnit export MyFunc export MySub export MyConst = 3.1415 export MyVar = 5 func MyFunc(a,b) return a + b end sub MySub(a,b) print "a + b = "; a + b end Second, an example on how to use the unit. import MyTestUnit as u u.MySub(1,2) print u.MyFunc(2,3) print u.MyConst u.MyVar = u.MyVar + 5 print u.MyVar Example 2: An unit for using strings The UNIT file. Please save as strlib.bas. ' File: strlib.bas ' ------------ ' In this demo we are using UNIT to add more useful String commands to ' SmallBASIC, by carefully creating our own String-Library: strlib.bas ' ' This demo includes only two useful functions, Lset() and Rset(); You ' can add more useful functions, subs, constants - but make sure that ' they are all String commands (not Array, File, Data, etc). ' ' Write your code carefully and efficiently, because you will use these ' commands frequently in other projects. And don't forget to debug the ' code and to add clear documentation, for you and for others. ' ' See also Home-->Article-->Welcome to SmallBASIC-->Units. ' ------------ ' ' Here we declare that this file is a UNIT file. ' Note: Keep file-name and unit-name the same. That helps the SB to ' automatically recompile the required units when it is needed (i.e. ' to create strlib.sbu file). ' The actual file name must be in lower case for Linux OS. Unit strlib ' (without .bas extension) ' Here we allow other SmallBASIC files to use some of our library keywords: Export Lset, Rset ' Left justify string s in buffer of length b. ' example: x = Lset(" SmallBASIC ", 15) ' --> x is " SmallBASIC " Func Lset(s, b) Local l = Len(s) If l >= b Then Lset = Left(s, b) Else Lset = s + Space(b - l) Fi End ' Right justify string s in buffer of length b. ' example: x = Rset(" SmallBASIC ", 15) ' --> x is " SmallBASIC " Func Rset(s, b) Local l = Len(s) If l >= b Then Rset = Right(s, b) Else Rset = Space(b - l) + s Fi End Demo file, demo.bas, which is using strlib.bas above: ' Here we declare that this file is using another UNIT file. ' Note: The actual file name must be in lower case for Linux OS. Import strlib ' (without .bas extension) ' Note: To access a member of a UNIT we must use the unit-name, a point ' and the name of the member, e.g. Strlib.Lset("Hello", 10). ' demo: Color 14, 1 Locate 4, 30 Print Strlib.Lset(" -->>", 25) Locate 5, 30 Print Strlib.Lset(Strlib.Rset("This way...", 18), 25) Locate 6, 30 Print Strlib.Rset("-->> ", 25) Pause