hBasic > hManual > Commands

hBasic Manual
Command changes

FN.IMPORT Imports global variables into functions
ROUND Fix for ROUND function for precise input values
GR.BITMAP.CLR / BLOT Clear a bitmap with transparency
GR.HIDE / GR.SHOW
Accept Multiple Input
BUNDLE.PUT / GET Accept Multiple Input
Bundle 'auto' Mode. (convenience loading for tags and variables)
REDIM
Re-Dimension existing arrays
SQL.PING Ping a database, table or column for existence
GR.CLIP.START / END Replacement for GR.CLIP
FILE.SAF commands
Provides read/write access for external sdcards
SMS commands
All SMS commands removed since v2.60 (playstore compliance)
DEVICE.OS Gets the android version string without needing permission

FN_IMPORT

This command imports 'global' (main) variables into the function's local variable list as referenced variables with the same name.

Effectively, you can import main variables into the function with read/write access.


FN.IMPORT <exp>,{<exp>}...


e.g     FN.IMPORT a, foo$, b[], c$[]    % imports main variables a,foo$,b[] and c$[]

And here are the rules;

    1. You can only use FN.IMPORT inside a function.
    2. You can use the FN.IMPORT command anywhere inside a function, and even more than once.
    3. The import will only take effect after the fn.import command (not before).
    4. Variable(s) given will ONLY be searched in the main program namespace (no where else).
    5. Any changes to an imported variable will also change the main variable.
    6. You must import at least one variable.
    7. You cannot repeat variables during import or have the same name local variable in the function.
    8. You can only import variables, not functions nor any other literals.

Example
    fn.def test()
        % fn.import a,a     % error: var Duplicate: a

        fn.import b
        % fn.import b       % error: var Duplicate: b

        b=3
    fn.end

    a=1 : b=2
    test()
    print b
    end

Output:
3

ROUND

Fix for ROUND function for precise input values

The math function ROUND (<value_nexp>{, <count_nexp>{, <mode_sexp>}})

uses java BigDecimal for rounding BUT the input values were still binary64 leading to precision errors.

Fix was to use BigDecimal(String) instead of BigDecimal(double).

Clear a bitmap area with transparency

GR.BITMAP.CLR <bitmap_ptr_nexp> {,paint}

Fills a bitmap with transparency without destroying it.
Anything already on the bitmap is cleared. There is no alpha blending.
An optional paint object can be supplied for a fill otherwise it will be transparent.

This is approximately 10x faster than deleting and re-creating a bitmap.

GR.BITMAP.BLOT <bitmap_ptr_nexp>, x, y, width, height {,paint}

Same as gr.bitmap.clr but fills a rectangle within bitmap.

This is slower than delete+create but faster for small areas less than a half the area of the whole bitmap.


Accept Multiple Input

These are enhancements made to accept multiple input parameters instead of just one with the same command.

GR.HIDE <object_number_nexp> {, <object_number_nexp> }...
hides multiple objects.
e.g
gr.hide cat, dog, mouse


BUNDLE.PUT <pointer_nexp>, <key_sexp>, <value_nexp>|<value_sexp> {, <exp>}...

puts multiple objects in a bundle.
e.g
bundle.put mybundle, "Key1",99, "Key2","RED", "Key3","Balloons"

BUNDLE.GET
<pointer_nexp>, <key_sexp>, <nvar>|<svar> {, <exp>}...

gets multiple objects from a bundle.
e.g
bundle.get mybundle, "Key1",k1, "Key2",k2$

Bundle 'auto' Mode

This enhancement made to get or put variables with the same named tag as a convenience.
For 'auto' mode, you only have to specify the variable (the tag is matched with the variable).

'auto' mode starts with a ' { ', followed by a list of comma separated variable names.
 and ends with a ' } '.

Variables must be numeric or strings. They cannot be arrays, array cells, literal numbers nor literal strings or you will get a syntax error.

The matching tags will be lower case with no spaces.    (Basic will always lower case all variable names)
The matching tags which are strings will also have the ending ' $ '.
 e.g'

BUNDLE.PUT mybundle, { v1, v2$, v3 }
puts tags "v1", "v2$", "v3"  and loads the bundle with content from variables v1,v2$,v3

BUNDLE.GET mybundle, { v1, v2$, v3 }
gets content from bundle using tags "v1","v2$","v3" into variables v1,v2$,v3

'auto' mode can also be mixed in with 'normal mode;

BUNDLE.PUT mybundle, "mytag0", v0,  { v1, v2$, v3 },  "mytag4", 44

REDIM

Re-Dimensions an existing array with optional 'preserve contents' flag.

REDIM
{preserve_nexp}, Array[<nexp>{, <nexp> } ... ] ...

e.g

REDIM a[2,3]
REDIM b[4] , c$[5]
REDIM
1,d[6]            % ( with preserve )

Any references to a REDIMed array will be intact, e.g an array passed into a function
that executes a REDIM will not be un-dimmed, i.e it will still be the same array but re-dimensioned.
Arrays must exist before REDIMing.

If the preserve flag is zero, the array will be full of 0's or "".
If the preserve flag is non-zero, the old contents will be preserved to the size
of the old or new array, whichever was smallest. Any cells left-over will be 0's or "".
If there are no preserve flags, the default is to not preserve (0).

Preserve flags may be inserted anywhere in the arguments list.
Arrays following a preserve flag will honor that preserve flag until the next preserve flag.
e.g
REDIM 1,a[2,3],   0,b[4],   1,c[5],  d$[6]    %  b[]  will not be preserved.

Preserve flags may be numeric literals or numeric variables but they cannot be numeric array values e.g p[3] would be mis-interpreted as an array to be re-dimmed.


SQL.PING

SQL.PING <result_nvar>, <DB_pointer_nvar> {,<table_name_sexp> {,<column_name_sexp>}}

Ping a database, table or column for some info.

This is mainly used to test for existence of tables.

e.g
A) SQL.PING result, db         
% ping only the database
(B) SQL.PING result, db, "mytable"

% ping a table
(C) SQL.PING result, db, "mytable", "col1"
% ping a table and column

Returns the size (number of rows) of a database or table to result.
In case (A), this is the total number of user tables in the db.

The result code is as follows;

-1 = table name does not exist
-2 = table name exists but column does not exist in the table
  >=0 = The total number of tables in the database or rows in the table.
            In case (C), this also means both table and column exists.


GR.CLIP.START and GR.CLIP.END


GR.CLIP.START <object_ptr_nexp>, <left_nexp>, <top_nexp>, <right_nexp>, <bottom_nexp>{, 
<RO_nexp>}

GR.CLIP.END <object_ptr_nexp>


GR.CLIP.START replaces GR.CLIP

Google does not allow for a clip region to expand since Android Pie (API-28). Because of that
4 out of the original 6 Region Operators are not supported;


Region OP
Allowed for API-28
0 Intersect
yes
1 Difference 
yes
2 Replace
no
3 Reverse Difference
no
4 Union   no
5 XOR
no

thus GR.CLIP.START only accepts 0 ro 1 for the region code.

GR.CLIP.END restores the canvas to the state (and region size) before the last clip.
It is strongly advised to use GR.CLIP.END after your objects are clipped.
Previously this was acheivable with Region Op 2, but since API 28, GR.CLIP.END is the only way to restore the canvas size.

<object_ptr_nexp> is the marker object returned if needed for display list manipulation ( similar to GR.ROTATE).

You may nest clips as long as each block is properly GR.CLIP.ENDed.

These commands use the same canvas stack as GR.ROTATE.{start / end}. Therefore you cannot interwine CLIP STARTs with ROTATE ENDs (and vice versa).

i.e, Always match the correct END type with the last used START.
e,g GR.CLIP.START...  GR.ROTATE.START.... GR.CLIP.START... GR.CLIP.END...GR.ROTATE.END..  GR.CLIP.END


DEVICE.OS

DEVICE.OS (<svar>)

Gets the android version string without needing the READ_PHONE_STATE permission.

This is a string, and needs to be converted to a number if needed.
Note that the string might be something like e.g "4.0.3" and may fail the IS_NUMBER or VAL functions.