Welcome to BAPI/CC - a library of PowerBASIC Console Compiler (PBCC) subroutines intended to simplify and accelerate the development of PBCC programs. BAPI/CC can read and write text files of any size, display popup alerts, questions and input forms, search for strings of text in files or other strings, read and write INI files, and connect to SMTP, FTP, HTTP and MySQL servers, among other things.
Including this library into any PBCC program will allow the program to make use of all the functions of the library.
Programs written with BAPI/CC can run on Windows 9x/NT/2000/XP.
BAPI/CC is a port of my BAPI QBASIC library to PBCC. BAPI/CC leverages the Windows-based nature of PBCC and can thus utilise STDIN/STDOUT, long filenames, gigabytes of RAM, etc.
If you're familiar with BAPI, take a look at the changes between BAPI and BAPI/CC. If you're porting BAPI code to BAPI/CC, check out the porting how-to. Also available are general notes on porting QBASIC code to PBCC.
This is not rocket science. Rocket scientists should head toward the booth with the Java signage. The library exists because I don't have time to learn a new programming language, I want to write programs quickly that work and that do what I want. I'm not writing word-processors or flight simulators... but my programs can read and write logfiles, webpages, scripts and sourcecode, for example. It's possible to create a working 200k EXE in a day, pretty blue windows, INI file and all!
Note: BAPI/CC is not at all related to SAP's Business API.
 
- requires PowerBASIC Console Compiler 4.0 or higher
- the following points are this program's terms and conditions of use:
- This program is hereinafter known as "the Software".
- The Software comes with no warranty and is used at your own risk.
- The Software is not (and will never be) complete and as such may behave strangely.
- The Software is the copyrighted property of the author.
- The Software may be distributed freely.
- The Software may NOT be incorporated into a commercial work without prior written permission from the author.
- The Software is "donateware" - you can choose your amount, and pay with Paypal! Donating will encourage me to create more tools. If you do decide to donate, thankyou in advance; the form is here.
There is a feedback form here.
 
- run the self-extracting archive
That's it. :-)
 
To use BAPI/CC, include it into your program. An example of a minimalist BAPI/CC-enabled program is below.
' * compiler control statements
#Include "\dev\bapicc\bapicc.inc" ' use BAPI/CC
' * begin mainline
Function PBMain () As Long
' initialise program settings
p_name$ = "galgen"
p_ver$ = "0.11"
p_copy$ = "(c) 2002-2009 Stuart Udall"
' pass control to BAPI/CC
Call mainline
If a_err% > 0 Then
Function = a_err% ' return errorlevel
End If
End Function
' * end mainline
' * begin program-specific subroutines
' * readuserini: get and set any program-specific settings
Sub readuserini
' define your variables here
End Sub
' * user interface
Sub userface
' insert your core loops here
End Sub
This code first includes the library, then creates the PBMain() function (required in each PBCC program). It then sets a few
BAPI/CC settings and calls mainline, a BAPI/CC subroutine that initialises BAPI/CC. When mainline exits, PBMain() exits also,
and the program closes.
The two subroutine stubs visible are readuserini and userface. readuserini is used to define variables
used by your code, and load INI settings from file. userface is where the bulk of your code goes, this is where you display data
onscreen, get user input, read/write files, branch to your own subroutines, etc. As many additional subroutines as required can be added below userface.
Note: BAPI/CC initialisation is not complete until AFTER readuserini has exited. This means, for example, it's not possible for
readuserini to call dialog (a BAPI/CC messagebox routine) to display errors. To display errors encountered by readuserini,
call dialog with code in the userface.
 
function reference
* denotes required field
| mainline 16 | call boot, browser, restart or exit |
| abort 7 | graceful abandoning of ship. |
| addmenu 1 | adds menu items to the menu array |
| anykey 3 | wait for keypress, return it |
| appendfile 4 | append a line to a text file |
| auth 3 | gets a password from the user |
| boot 16 | pre-define environment, arrays, load DOS vars, INI file |
| changeini 3 | changes the value of an INI setting in the INI file |
| copyblock 4 | copy a range of lines from one file to another file |
| copymove 3 | copy or move a file from one location to another |
| csv2dim 3 | parse a comma-separated-string into tmp array |
| deltree 1 | silently deletes a directory tree |
| dialog 9 | display alert/question dialog box, get keypress/answer; log to file |
| dim2csv 1 | parse the tmp array into a CSV-delimited string |
| drawbox 9 | draw a box onscreen |
| epochdate 1 | converts dates in MM-DD-YYYY format to/from unix epochtime |
| findrule 2 | returns rule number, given rule name |
| findsetting 3 | returns value of a specified setting in INI file |
| findss 5 | find the next or previous occurence of a substring in a string |
| findssarray 3 | find the next occurence of a substring in infile array |
| freespace 4 | returns volume label, total space and free space on the specified volume |
| getaltkey 2 | returns ASCII character from alt-keycode |
| getdate 6 | returns epochday, and date in "Month Daynumber, 4DigitYear" format |
| getdaynum 1 | returns number of days since year start, or since prespecified date |
| getdosvar 1 | returns value of specified DOS environment variable |
| getform 9 | get multiple data items from user in dialog box |
| getHTTP 1 | download a file with HTTP |
| getmodele 5 | retrieve all elements from a module in memory or in INI file |
| getNTLMinfo 1 | returns NT Lan Manager configuration |
| getosver 2 | returns operating system and version |
| getrand 6 | generate a unique 16-digit string and tempfilename |
| getregkey 3 | retrieve a registry key from Windows' registry |
| hex2dec 1 | converts a hexadecimal number to decimal |
| hostlookup 1 | resolve a host either by name or by IP |
| ifexist 8 | detect the presence of a file or directory on disk |
| ifinmod 3 | find an element in a module in memory |
| nukebox 1 | erase current dialog box |
| openforappend 1 | opens a file for appending, with full errorhandling |
| printfile 1 | print a file on a printer |
| progress 6 | display progress indicator, with optional dualbar |
| putFTP 1 | upload a file with FTP |
| readdir 16 | obtain directory contents from FAT-16, FAT-32, NTFS or UNC volumes |
| readfile 7 | read a range of lines from a text file into infile array |
| refresh 1 | restores the screen to a virgin state |
| runfromdir 1 | run a DOS command from within a specified directory |
| runlongcmd 5 | run a DOS commandline up to 255 characters long, returns errorlevels |
| safekill 1 | deletes file, with errorhandling |
| scanfile 5 | find the next or previous occurence of a string in a text file |
| sendmail 4 | send an email with SMTP |
| showline 3 | displays a formatted line onscreen |
| showlistbox 1 | displays a table of data onscreen, allows selection |
| showmenu 4 | display scrollable menu, wait for cursor-based selection, parse user response |
| showmsg 10 | display or erase statusbar |
| showtitle 2 | display titlebar |
| sift 1 | check for char, convert if found |
| split 4 | chop a string in two at first, next, previous or last delimiter, or character position |
| SQLinsert 1 | add a record into an SQL database |
| SQLdelete 1 | remove a record from an SQL database |
| SQLquery 2 | query an SQL database |
| SQLupdate 1 | change a record in an SQL database |
| strip 2 | strip leading/trailing spaces from a string, and any sub-ASCII 32 characters |
| table2csv 1 | convert a MySQL table to a CSV file |
| tail 1 | returns the last line of a text file |
| template 3 | generates a file from a template and a datasource |
| testint 1 | tests that a number stored as a string is less than 32767 |
| trunc 1 | returns a number with x decimal points |
| unix2dos 2 | convert a LF-terminated file to CR/LF |
| URLdecode 1 | convert a string from URL-encoded format to ASCII |
| URLencode 1 | convert a string to URL-encoded format from ASCII |
| writebuf 4 | buffered write to text file |
| writefile 16 | write a range of lines to a text file from infile array; can backup and/or append |
|
| function | |
| purpose | set program variables, call boot, browser, restart or exit |
| features | |
| p_name$ | * name of program |
| p_ver$ | * program version number |
| p_copy$ | copyright information |
| p_abort% | 0=continue execution without reinitialisation; 1=end execution, displaying error in a_msg$ if it exists |
| p_noini% | flag to ignore INI file (1=ignore, 0=don't (default)) |
| p_needini% | flag to require INI file (1=require, 0=don't (default)) |
| p_loadmod% | flag to load [modules] at boot (1=load, 0=don't (default)) |
| p_ininoclear% | flag to retain INI file in memory after boot (1=retain, 0=don't (default)) |
| p_needwin% | flag to require execution under Win32 or Win9x (0=don't require Win32 (default); 1=require Win32; 2=require Win9x) |
| p_ourvar$ | environment variable to load |
| p_needvar% | flag to require environment variable (0=don't require variable (default); 1=require variable) |
| p_usevardir% | flag to use the environment variable as a path to the INI file (0=don't (default); 1=use variable as INI directory) |
| p_quiet% | flag to suppress signon screen (1=suppress, 0=don't (default)) |
| p_debug% | flag to enable debug mode (1=debug, 0=normal (default)) |
| p_debugstep% | flag to 1=enable step-by-step debug mode (1=step-by-step, 0=don't (default)) |
| DOS errorlevel | a number designating a runtime error (0=no error) |
| | notes |
- click here for more on controlling memory allocation
- click here for more infomation about p_needini%, p_loadmod% and INI files
- click here for more infomation about the runtime errors generated if a required execution condition is not met
- to return an errorlevel to a script, allow the mainline routine to exit with a_err% set to the errorlevel to return
- setting p_debugstep%=1 without also setting p_debug%=1 will have no effect
- p_abort% is set true by the boot routine if an error occurs, and would not normally be used outside this context
|
| function | |
| purpose | graceful abandoning of ship. |
| features | will display errormessage if there is one; wait for keypress |
| a_err% | error code |
| a_msg$ | error message |
| | notes |
- A table of runtime errors is here.
|
| function | |
| purpose | adds menu items to the menu array |
| features | |
| addm_p$ | the item text (the text that is displayed in the menu itself) |
| addm_m$ | the item description (the text that is displayed on the statusbar when the cursor is on the menu item) |
| addm_d$ | the item key (the value that is returned if this item is selected) |
| addm_refresh% | if set, sets the m_items% to 0 (this has the effect of deleting the old menu, however, the old menu items are not actually erased, they are still in the array) |
| m_items% | incremented |
| m_p$() | populated |
| m_m$() | populated |
| m_d$() | populated |
| | notes |
- this routine is for use with showmenu, and simplifies adding/removing items to/from a large menu, in that the programmer does not have to increment m_items% manually
|
| function | |
| purpose | wait for user keypress, return keypress and keycode |
| features | |
| s_msg$ | string to display in status bar |
| keyb$ | key pressed by user |
| kb_code% | keycode of key pressed by user |
| | notes |
- if the user presses an extended key (eg. Alt-B), the keycode returned will have 500 added to it
|
| function | |
| purpose | append a line to a text file |
| features | if the file does not exist, it will be created |
| appef_name$ | * name of file to append to |
| appef_s$ | string to append |
| appef_err$ | error message (if appropriate) |
| | notes |
|
| function | |
| purpose | gets a password from the user |
| features | can ask for re-entry to confirm |
| auth_verify% | if set to 1, the messagebox presented will say "verification" instead. However no verification is performed. It is up to the calling application to call auth twice, the second time with auth_verify set, and compare the passwords itself. |
| auth_pw$ | the password entered |
| | notes |
- All text entered in the auth field is starred out.
|
| function | |
| purpose | pre-define environment, arrays, load DOS vars, INI file |
| features | sets up screen, tests critical variables, detects operating system, recovers DOS environment variables, sets TEMP directory, reads INI file |
| readim_s$ | a comma-separated list of modules to load from the INI file |
| readim_e$ | a comma-separated list of elements to load from each module |
| p_bapi$ | BAPI/CC's internal revision level |
| p_abort% | 1=error during boot; 0=no error |
| a_msg$ | error message (empty if none) |
| p_temp$ | name of temporary directory for use by this program |
| p_os% | operating system the program is executing under: 0=unknown; 1=DOS; 2=Win9x; 3=WinNT4; 4=Win2000; 5=WinME; 6=WinXP |
| getos_ver$ | operating system the program is executing under (descriptive string) |
| p_ourvarval$ | value of environment variable set by p_ourvar$ |
| p_ourdir$ | directory set by p_ourvar$ (if p_usevardir% is true) |
| p_cmd$ | commandline used to call the program (if available) |
| inifilename$ | full name and path of INI file (if available) |
| numsettings% | number of settings read from main section of INI file (if available) |
| cfg$(x,numsettings%) | two-dimensional array containing settings from main section of INI file (if available) |
| | notes |
- boot also sets a number of internal variables, and allocates memory to the various arrays (such as infile, lst, tmp, etc)
- boot also runs the readuserini subroutine, and loads the INI file (in that order)
- the values returned by the INI loader are the same to those output by getmodele
- click here for more infomation about readim_s$, readim_e$, numsettings% and INI files
- the internal revision level is useful for determining the BAPI revision used to compile a particular EXE: view the EXE and search on "revision" or simply "rev" - the first match should be the BAPI/CC revision number
|
| function | |
| purpose | changes the value of an INI setting in the INI file |
| features | will create an INI file if it does not exist; will add the setting if it does not exist** |
| ini_target$ | * name of setting to change |
| ini_module$ | name of module containing this setting (blank to disable module support) |
| ini_change$ | * value of new setting |
| cini_err$ | error message (blank if none) |
| | notes |
- preserves comments no the INI line, if there are any
- ** auto-creation of settings is not supported if the setting is in a module. You must create a blank setting= line.
- the name of the INI file is determined by BAPI/CC.
|
| function | |
| purpose | copy a range of lines from one file to another file |
| features | |
| copyb_source$ | * file to copy from |
| copyb_target$ | * file to copy to |
| copyb_start% | row upon which to start copying (0 for start of file) |
| copyb_stop% | row upon which to stop copying (0 for 'until end') |
| copyb_noflush% | 0=flush enabled; 1=don't flush when end-of-block or end-of-file is reached |
| lst$() | array containing strings to insert as a header into target |
| header_length% | * number of rows of strings to export from list array as header (0 to disable) |
| writf_append% | 1=append to target file; 0=overwrite (default) |
| writf_backup% | 1=create .BAKfile before write; 0=don't (default) |
| copyb_bytes! | number of bytes copied |
| copyb_err$ | error message (blank if none) |
| | notes |
- this routine will overwrite the contents of the infile array
- if the target does not exist, it will be created
- if the target already exists, it will be overwritten, unless writf_append% is true
|
| function | |
| purpose | copy or move a file from one location to another |
| features | can copy or move across UNC paths, drives and directories |
| mf_from$ | name of file to move |
| mf_to$ | name of file to move to |
| mf_movefile% | 0=copy file (default); 1=move file |
| mf_checkfirst% | 0=overwrite if target exists; 1=make backup, prompt to overwrite or abort if target exists |
| mf_cycle% | 1=silently affirm .BAKfile overwrite prompt; 0=prompt before overwriting .BAKfile (default) |
| movef_err$ | error message (blank if none) |
| | notes |
|
| function | |
| purpose | converts a comma-separated-string to an array |
| features | |
| c2d_s$ | * string to convert |
| c2d_d$ | delimiter string - if not set, defaults to , (a comma) |
| c2d_undelimit% | if set to 1, will strip the first and last character from each data item (useful for stripping 'quotes' around dataitems) |
| c2d_quoted% | if set to 1, enables "string quoted" dataitems (embedded commas permitted) |
| c2d_quotemark$ | quote delimiting character - if not set, defaults to " (a double-quote, ASCII 34) |
| c2d_found% | number of detected items |
| tmp$() | array containing each detected item as a separate row |
| | notes |
- as the delimiting character can be set, this routine is not confined to processing CSV data. The routine could be used to break a sentence into an array, by changing the delimiting character to a space (ASCII 32).
|
| function | |
| purpose | silently deletes a directory tree |
| features | |
| delt_name$ | the name of the directory to delete |
| delt_err$ | result string (blank if none) |
| | notes |
- supports W9X and W2K and above
|
| function | |
| purpose | show alert/question, get keypress/answer; log to file |
| features | can also display buttons; can log messages to file; updates statusbar; returns action |
| d_title$ | the title of the dialog box |
| d_msg$ | the string to display in the dialog box |
| q_msgs% | number of lines of multiline prompt to display |
| q_msg$() | array containing multiline prompt lines |
| d_type% | 0=message box (OK only); 1=question (Yes/No); 2=message but don't wait for keypress; 3=log only, no screen output; 4=screen only, no log output |
| d_buttons% | number of buttons to display (0=no buttons) |
| d_b_l$() | array containing button labels |
| d_b_h%() | array containing character position of label to highlight and capitalise |
| d_b_c$() | array containing character to return if user presses this button |
| p_logging% | 0=don't log messages; 1=log messages to errorlog |
| p_errlog$ | name of logfile - by default, this is p_name$ plus ".log" |
| p_auto% | automatic mode; 0=display messages; 1=don't display, only log to file |
| d_flag$ | this string is inserted at the beginning of the logfile entry. If empty, it is set to ! (exclamation mark) |
| d_b_pressed$ | character value of pressed button (empty if not pressed) |
| action% | 0=NO; 1=YES (if dialog was a question) |
| | notes |
- if d_title$ is empty, a default is supplied
- if d_type%=4 (screen only) but p_auto%=1 (automode enabled) then automode will take precedence
- if q_msgs% contains a value, d_msg$ is discarded, and the contents of q_msg$() are displayed instead
- the contents of q_msg$() are not logged to disk, even if logging is enabled.
|
| function | |
| purpose | parse the tmp array into a CSV-delimited string |
| features | |
| tmp$() | array containing each item as a separate row |
| d2c_num% | number of items to convert |
| d2c_d$ | delimiter string - if not set, defaults to , (a comma) |
| c2d_s$ | converted string |
| | notes |
- as the delimiting character can be set, this routine is not confined to processing CSV data. The routine could be used to break an array into a sentence, by changing the delimiting character to a space (ASCII 32).
|
| function | |
| purpose | draw a box onscreen, with optional title, note, status, content, buttons, getconfirmation, anykey and vanish |
| features | |
| b_strings% | number of lines of text to display |
| b_str$() | array containing lines of text to display |
| b_title$ | title of box |
| b_note$ | subtitle of box |
| s_msg$ | text to display in statusbar |
| b_h% | height of box (in characters) |
| b_len% | length of box (in characters) |
| b_xpos% | x-position of upper-left-hand corner of box |
| b_ypos% | y-position of upper-left-hand corner of box |
| b_text_for_col% | the foreground colour of the text in the box |
| d_buttons% | number of buttons to display (0=no buttons) |
| d_b_l$() | array containing button labels |
| d_b_h%() | array containing character position of label to highlight and capitalise |
| d_b_c$() | array containing character to return if user presses this button |
| b_wait% | wait for keypress (0=don't wait (default), 1=wait) |
| b_confirm% | get confirmation (0=don't (default), 1=wait for Y or N) |
| d_b_pressed$ | character value of pressed button (empty if not pressed) |
| action% | 0=NO; 1=YES (if dialog was a question) |
| | notes |
|
| function | |
| purpose | converts dates in MM-DD-YYYY format to/from unix epochtime |
| features | autodetects whether a date or an epochtime is to be converted, and returns the opposite of what was supplied |
| ed_source$ | the date (in MM-DD-YYYY format) or epochtime to convert |
| ed_converted$ | converted date (either an epochtime, or in MM-DD-YYYY format) |
| | notes |
- Currently requires EPOCHDAY.EXE
|
| function | |
| purpose | returns rule number, given rule name |
| features | |
| findr_name$ | name of module to find |
| findr_num% | number of found of module |
| | notes |
- do not supply [square brackets] around the modulename
|
| function | |
| purpose | returns value of a specified setting in INI file |
| features | |
| lookin$ | * name of setting to query |
| cfgval$ | value of setting (blank if not found) |
| | notes |
- this routine is usually used in readuserINI; it's not used anywhere else by BAPI/CC
|
| function | |
| purpose | find the next or previous occurence of a substring in a string |
| features | |
| lookin$ | * string to search |
| lookfor$ | * string to search for |
| foundat% | * starting position (0 for beginning or end) |
| f_last% | 0 = search from beginning of string; 1 = search from end of string |
| foundat% | starting character position of found substring in string (0 if not found) |
| | notes |
|
| function | |
| purpose | find the next occurence of a substring in infile array |
| features | |
| infile$() | * array of strings |
| infilelines% | * length of array of strings |
| lookfor$ | * string to search for |
| findsa_y% | * row in array to start searching on (0 for start) |
| findsa_y% | row in array containing string (0 if not found) |
| findsa_x% | starting character position of string in row containg string (0 if not found) |
| | notes |
- ensure that infilelines% does not become corrupted between when the file is loaded, and when findssarray is called
- improve: search backwards?
|
| function | |
| purpose | returns volume label, total space and free space on the specified volume |
| features | compatible with Windows 9x/ME/2K/XP/2K3 and mapped network volumes (NT4 not supported) |
| frees_driveletter$ | the letter of the drive to work with |
| frees_sizeinmegs% | return size in megabytes (Mb) (0=no (default); 1=yes) |
| frees_vol$ | the volume label |
| frees_total&& | total space on the volume, in megabytes |
| frees_size&& | free space on the volume, in megabytes |
| frees_err$ | result string (blank if none) |
| | notes |
|
| function | |
| purpose | returns ASCII character from alt-keycode |
| features | |
| alt_code% | * raw extended keycode |
| alt_key$ | letter of keypress |
| | notes |
|
| function | |
| purpose | returns date in "Month Daynumber, 4DigitYear" format |
| features | also returns the number of days since January 1, 1900 |
| getdate_this$ | date to process (in mm-dd-yyyy format) |
| epochday! | number of days since January 1, 1900 |
| ourdate$ | date in "Month Daynumber, 4DigitYear" format, eg., September 21, 2000 |
| | notes |
- Leave getdate_this$ blank to process the current date
- Y2K compliant
- epochday does not return correct values for dates prior to 1582 AD
|
| function | |
| purpose | returns the number of days since year start, or since a pre-specified date |
| features | |
| getday_date$ | date to process (in mm-dd-yyyy format) |
| getday_num% | number of days since the date specified |
| | notes |
- Leave getday_date$ blank to return the number of days since the beginning of the current year
- Y2K compliant
- does not return correct values for dates prior to 1582 AD
|
| function | |
| purpose | returns value of specified DOS environment variable |
| features | |
| getvar_name$ | * name of variable to query |
| getvar_val$ | value of variable (blank if not found) |
| | notes |
|
| function | |
| purpose | get multiple data items from user in dialog box |
| features | cursor key-based editing; insert/overtype; scrolling if input overlength; simulated cursor; titlebar; footerbar; blank field if first key is backspace; filters non-displayable characters; auto-positioning and sizing dialog box; displays buttons with hi-lit alt-keys |
| g_title$ | contents of title |
| g_note$ | contents of note |
| g_items% | number of input items on form |
| g_focus% | default selected item |
| g_automin% | minimum size for any input field *
| g_p$(n) | prompt for item n |
| g_m$(n) | status line for item n |
| g_d$(n) | default setting for item n |
| g_c%(n) | default cursor position for item n |
| g_l%(n) | length of on-screen input field |
| g_lmax%(n) | maximum length of input |
| g_hide%(n) | enable/disable output masking (1=ON, 0=OFF) |
| g_buttons% | number of buttons on form |
| g_b_l$(n) | label for button n |
| g_b_c$(n) | character returned by button n |
| g_b_h%(n) | character position in label to highlight |
| g_abort% | 1 = user aborted; 0 = did not abort |
| g_i$(n) | response from user for item n |
| g_b_pressed$ | character of pressed button (empty if none pressed) |
| g_c_y% | form item selected when form exited |
| | | notes |
- set g_c%(n) to -1 to have the cursor default to the end of the input field
- set g_lmax%(n) to -1 to use max input size for field (250 characters)
- set g_l%(n) to -1 to autosize the length of the input field
- to set the above three automatically, plus the hide setting to OFF, for each menu item, place a value in g_automin%. * If g_automin% contains a value, the settings in g_c%(n), g_l%(n), g_lmax%(n) and g_hide%(n) will be ignored
- hiding is not possible when autosizing
- cursor position 0 is the first character of the input field
- improve: true/false fieldtype
- uses: getaltkey (and others..)
|
| function | |
| purpose | download a file with HTTP |
| features | |
| gh_url$ | the URL of the file to download |
| gh_destfile$ | the name of the file to save the downloaded file as |
| gh_quiet% | suppress CURL output (1=suppress, 0=don't (default)) |
| gh_error% | result status (1=error; 0=no error) |
| gh_result$ | result string (returned on success as well as failure) |
| | notes |
- Currently requires CURL.EXE
|
| function | |
| purpose | retrieve all elements from a module in memory or in INI file |
| features | |
| getmod_file$ | * the name of the file containing the module to load |
| getmod_name$ | * the name of the module to load - this will be one of the modules listed in readim_s$ |
| getmod_num% | * the column number of the module array to fill with module data |
| p_noinistrip% | default is 0 (false/off); if set to 1 (true/on), the INI loader will not strip comments or whitespace from the elements as they are loaded |
| inimod$() | two-dimensional array containing loaded values
| inimodnum% | number of modules loaded
| inielenum% | number of structured elements loaded
| orphanele% | number of orphaned elements loaded
| inioverflow% | set TRUE if number of loaded elements exceeded available module memory space (in this case, the as many elements as possible are loaded). |
| getmod_err$ | error message if unable to open INI file
| | | | | | | notes |
- the INI loader will overwrite any existing data in the column with new data from the module being loaded
- for more information on inimod$(), modules and INI files, see general INI pointers
- for more information on orphans, see working with orphans/freeform elements
- the side-effect of using p_noinistrip% is that any comments in the INI file will be interpreted. For this reason, avoid using comments in INI files used by programs with p_noinistrip% enabled. The only exception is at the end of [modulenames], where ; comments are still permitted (and ignored) if p_noinistrip% is enabled.
|
| function | |
| purpose | returns NT Lan Manager configuration |
| features | |
| net_cname$ | the name of this computer |
| net_uname$ | the name of the currently logged-in user |
| net_wgroup$ | the name of the workgroup this computer is a member of |
| net_domain$ | the name of the domain this computer is a member of |
| | notes |
- these settings are used for Windows-based networking, such as file-and-print sharing
|
| function | |
| purpose | returns operating system and version |
| features | |
| p_os% | OS detected: 0=unknown; 1=DOS; 2=Win9x; 3=WinNT; 4=Win2000; 5=WinME; 6=WinXP |
| getos_ver$ | version string returned by operating system |
| | notes |
|
| function | |
| purpose | generate a unique 16-digit string and filename |
| features | can return string as a tempfilename; can prepend a prespecified string to the generated string |
| gr_prefix$ | if provided, getrand will prepend this string to the beginning of the generated string it returns. |
| gr_seq% | if set to 1, getrand will allocate filenames in a sequential, rather than pseudo-random manner. |
| gr_forceshort% | if set to 1, getrand will return an 8-character string, instead of 16 characters. |
| uniquename$ | string of 16 random numbers |
| uniquetemp$ | fully qualified drive:\path\filename.tmp (uses p_temp$ variable allocated by boot) |
| | notes |
- The use of gr_prefix$ is recommended, as it reduces the chances of a tempfile collision.
- Use gr_seq% if there's a chance more than one unique string will be generated per second. The pseudo-random algorithm (which is based on the time of day) is in fact designed for this, but prolonged testing on fast computers has revealed it's simply not random enough. gr_seq% answers this problem by forcing the unique strings to increment in sequence. It is thus suitable for generating a large number of unique strings very quickly.
|
| function | |
| purpose | returns the contents of a specified Windows registry key |
| features | |
| getrk_key$ | * name of registry key to query |
| getrk_decode% | flag to decode directory key (0=no (default), 1=yes) |
| getrk_read% | flag to read key (0=no (default), 1=yes) |
| getrk_file$ | name of file containing key (blank if decoding is enabled) |
| getrk_val$ | data associated with value within key (blank if key not found, or if reading or decoding are disabled) |
| getrk_err$ | error message (blank if no error) |
| | notes |
- If getrk_decode% is specified, the directoryname is decoded and the keyfile deleted.
- If getrk_read% is specified, the key is read and the keyfile deleted.
- getrk_decode% and getrk_read% cannot be used together. getrk_decode% will execute if both settings are enabled.
- If neither getrk_decode% or getrk_read% are specified, the key is not analysed, the keyfile is not deleted by getregkey, and the name of the keyfile is returned in getrk_file$. This file must be deleted later by your program - it is not deleted automatically, and will cause a "tempfiles left in tempdir" error on exit if not deleted.
|
| function | |
| purpose | converts a hexadecimal number to decimal |
| features | |
| h2d_in$ | * string containing number to convert |
| h2d_out! | the input number, expressed in decimal |
| | notes |
|
| function | |
| purpose | resolve a host either by name or by IP |
| features | autodetects whether a name or an IP address is to be resolved, and returns the opposite of what was supplied |
| hostl_address$ | the hostname or IP address to resolve |
| hostl_resolved$ | the resolved hostname or IP address |
| | notes |
|
| function | |
| purpose | detect the presence of a file or directory on disk |
| features | will use default drive and/or directory if not supplied |
| ifexist_name$ | * filename to test for |
| ifexist_found% | 1=file exists; 0 if not exists |
| ifexist_name$ | fully-qualified path to file |
| ifexist_err$ | error message (if any) |
| | notes |
|
| function | |
| purpose | to see whether a given string is contained within a given module |
| features | This search can look for partial match, or an exact match, for the first x number of
characters in the string. This search only looks for the first match at present. |
| ifinm_num% | * module number to search |
| ifinm_s$ | * string to search for |
| ifinm_left% | 1=enable exact match from left; 0=match anywhere in string (default) |
| ifinm_exact% | 1=enable exact match; 0=permit a match on a substring (default) |
| ifinm_found% | set TRUE if the string was found within the elements of the module |
| ifinm_foundin$ | the string the match was found in |
| ifinm_foundat% | the row the match was found in |
| | notes |
- If ifinm_exact% is set true, ifinmod checks whether the supplied string *exactly* matches any string in the module (it's still case-INsensitive, however). Previously, it matched exactly from the left ("starts with.."), or matched anywhere ("contains..").
|
| function | |
| purpose | erase current dialog box |
| features | |
| | notes |
|
| function | |
| purpose | opens a file for appending, with full errorhandling |
| features | |
| appeof_name$ | the name of the file to open |
| appeof_handle% | the filehandle to use |
| appeof_err$ | error (if any, blank if none) |
| | notes |
- Note: this routine does not close the file, it only opens it. If many lines of text are being appended to the same file, leaving a file open for appending,
instead of opening and closing it for each append, is more efficient. The calling routine must close the file itself, however.
|
| function | |
| purpose | print a file on a printer |
| features | |
| printf_name$ | the name of the file to print |
| printf_printer$ | the name of the printer to print on |
| printf_err$ | result string (blank if none) |
| | notes |
- currently supports HTML files only
- the printer name must match the printer as seen in the control panel, for example, "HP Laserjet 5M" (don't include the quotes)
- this routine pops up Windows' Print dialog box, which requires a click of OK before the print is done. To automate this, a program such as
WKIX32 is needed, to send the Enter key to the Print dialog box.
|
| function | |
| purpose | show progress bar onscreen |
| features | can display a second progress bar underneath |
| p_done% | percentile complete |
| p_showdone% | 0=don't show; 1=show percentile complete in the progress bar |
| p_update% | 0=draw whole box; 1=draw only progress bar (faster) |
| p_updatefreq% | 0=draw every %; >0=update at that frequency |
| p_dualbar% | 0=single progress bar only; 1=draw dual progress bars |
| p_dualdone% | percentile of second progress bar complete |
| p_reset% | 0=don't reset; 1=reset all progress counters |
| | notes |
- update will draw the box, but only if it has not already been drawn
- p_updatefreq% is used to update the display only every x%. For example, setting p_updatefreq% to 5 would update the display when the percentage complete was 5%, 10%, 15% and so on. This results in a chunkier bar movement, but usually speeds program execution (due to reduced screen updates).
- p_reset% is used to tell the routine to reset its counters and begin a new progress bar. This is required if repeatedly using the routine with the p_updatefreq% parameter set to on. p_reset% will be automatically set to FALSE when the bar is reset.
|
| function | |
| purpose | upload a file with FTP |
| features | |
| pf_ftpserver$ | the hostname of the FTP server to use (eg. ftp.yourdomain.com) |
| pf_targetdir$ | the fully-qualified path to upload to (eg. /htdocs/) |
| pf_sourcefile$ | the name of the file to upload |
| pf_username$ | the name of the user to log in as |
| pf_pw$ | the password to use |
| pf_error% | result status (1=error; 0=no error) |
| pf_result$ | result string (returned on success as well as failure) |
| | notes |
- Currently requires CURL.EXE
|
| function | |
| purpose | obtain directory contents from FAT-16, FAT-32, NTFS or UNC volumes |
| features | if not supplied, will resolve default drive and/or directory |
| readd_name$ | name of directory to read |
| readd_noinfo% | if set to 1, enables high-speed mode |
| readd_name$ | fully qualified path to target directory |
| readd_files% | number of files and directories in target directory |
| dirinfo$(n) | CSV-formatted array of file information |
| readd_err$ | error message, if any - blank if no error |
| | notes |
- the format of dirinfo array is drive:,\full\path\name,filename,extension,date,time,size
- fully supports wildcards
- high-speed mode does not return file date/time/size, but also doesn't display a "File Not Found" error on empty directories (unlike low-speed mode)
|
| function | |
| purpose | read a range of lines from a text file into infile array |
| features | will set buffer overflow flag if file is too big for available memory |
| readf_name$ | * name of file to read |
| readf_start% | * line in file to start reading from (0 for start) |
| readf_length% | * number of lines to read (0 for all) |
| infile$() | array containing lines read |
| infilelines% | number of lines read |
| readf_bytes! | number of bytes read |
| readf_size! | total size of file |
| readf_err$ | error message (blank if none) |
| readf_bufstat% | 0=complete file in RAM; 1=partial file in RAM |
| readf_bufline% | line at which RAM filled (0 if complete file in RAM) |
| | notes |
|
| function | |
| purpose | restores the screen to a virgin state |
| features | |
| | notes |
- this routine restores the screen to its state when the program starts - a blank screen with the titlebar across the top
|
| function | |
| purpose | runs specified command from within a specified directory |
| features | |
| runf_dir$ | * directory to execute command within |
| runf_cmd$ | * command to execute |
| runf_err$ | errormessage (if any) |
| | notes |
- The command is started minimised and execution waits until the command exits before it resumes.
- Calls to runfromdir under NT4 with will fail unless START.EXE is in the path.
|
| function | |
| purpose | runs specified commandline |
| features | commandline can be longer than the QBASIC limit of 127 characters - up to 255 characters; also returns errorlevel |
| longcmd$ | * commandline to execute |
| rl_quiet% | attempt to suppress all output (0=no (default), 1=yes) |
| rl_newwin% | run this command in a new window (0=no (default), 1=yes) |
| rl_newwinshow% | minimise new window (0=no (default), 1=yes) |
| rl_nowait% | don't wait for this command to finish before continuing (0=wait (default), 1=don't wait) |
| longcmd_err% | errorlevel returned from command |
| | notes |
- Starting processes in their own window usually provides more memory to the child process.
- rl_newwin% is not available under Windows NT4, as that operating system has no START.EXE command by default. It is possible to pass a START command directly to runlongcmd by placing it in the command string longcmd$. However if the system executing the program is Windows NT, the function will fail (for the same reason - START.EXE not included). The same is also true if using START with a SHELL command under NT4 - it won't work. Either place START.EXE on the system (and in the path) or don't use it, if under NT4. The BAPI provides the operating system type in the variable p_os%.
- Calls to runlongcmd under NT4 with rl_newwin% enabled will be executed, but in the same window as the calling process.
- rl_newwinshow% does nothing if rl_newwin% is set to 0
|
| function | |
| purpose | deletes file, with errorhandling |
| features | |
| safef_name$ | the name of the file to delete |
| safef_err$ | result string (blank if none) |
| | notes |
|
| function | |
| purpose | find the next or previous occurence of a string in a text file |
| features | |
| scanf_name$ | * name of file to scan |
| lookfor$ | * string to search for |
| scanf_start% | * line upon which to start searching (0 for first line) |
| scanf_stop% | * line upon which to stop searching (0 to search whole file) |
| scanf_last% | 0=find next occurence of string; 1=find previous occurence of string |
| foundin$ | line containing found string (blank if not found) |
| foundline% | line number of found string (0 if not found) |
| scanf_err$ | error message (blank if no error) |
| scanf_size! | total size of scanned file (o if not found) |
| scanf_bytes! | bytes scanned before string was found (0 if not found) |
| | notes |
|
| function | |
| purpose | send an email with SMTP |
| features | |
| sm_messagefile$ | the name of the file containing the message body |
| sm_recipient$ | the email address to send the message TO |
| sm_subject$ | the string to place in the subjectline of the email |
| sm_fromaddr$ | the email address to send the message FROM |
| sm_replyto$ | the email address the recipient should reply to |
| sm_smtpserver$ | the hostname of the SMTP server to use |
| sm_cc$ | the email address to CC (carbon-copy) the message to (optional) |
| sm_attach$ | a list of files to attach to the email, separated by commas (optional) |
| sm_htmlflag% | set to true to enable HTML mail (specify the filename in sm_messagefile$ as usual) |
| sm_alttext$ | the file to contain non-HTML (alternate) text (optional/HTML only) |
| sm_embedlist$ | a list of files to embed in the email, separed by commas (optional/HTML only) |
| sm_error% | result status (1=error; 0=no error) |
| sm_result$ | result string (returned on success as well as failure) |
| | notes |
- Currently requires BLAT.EXE
|
| function | |
| purpose | displays a formatted line onscreen |
| features | can also erase the line |
| showl_l% | the screenline upon which output is to appear (Y) |
| showl_t% | the tabline (column position) upon which the data is to appear (X) |
| showl_promptx% | the tabline (column position) upon which the prompt is to appear (X) (default=1, first column) |
| showl_datacol% | the foreground colour of the displayed data (default=15, bright white) |
| showl_p$ | the prompt to display |
| showl_d$ | the data to display |
| showl_x% | if set to 1, the line specified in showl_l% will be erased |
| | notes |
- output is in the form prompt: [data]
- valid numbers for showl_datacol% range between 1 and 15
|
| function | |
| purpose | displays a table of data onscreen, allows selection |
| features | |
| lst$() | array containing the data to display, in CSV format |
| lb_listitems% | the number of items in the array |
| lb_pagestart% | the line number where the list starts |
| lb_pageend% | the line number where the list ends |
| lb_fieldnames$ | the names of the fields to display, in CSV format |
| lb_fieldlengths$ | the lengths of the fields to display, in CSV format |
| lb_actionitem% | the item upon which to place the cursor |
| lb_datastyle% | the format of the data in lst$(); 0=CSV, 1=TSV |
| lb_startat% | the line of data upon which to place the cursor |
| lst$() | contents of table, in TSV format |
| lb_action% | keypress (1=Esc; 2=enter; 3=delete; 4=question mark; 5=spacebar; 6=insert) |
| lb_actionitem% | the line number of the item upon which to perform the returned action |
| lb_exitat% | the line of data upon which the cursor was on, when the routine exited |
| | notes |
- this routine is a bit developmental.. ;)
|
| function | |
| purpose | display scrollable menu, wait for cursor-based selection, parse user response |
| features | autosizing, returns selection, updates status |
| m_title$ | contents of title |
| m_items% | number of list items on menu |
| m_maxlines% | maximum number of list items to display |
| m_focus% | default selected item |
| m_p$(n) | prompt for item n |
| m_m$(n) | status line for item n |
| m_d$(n) | unique listitem ID |
| d_buttons% | number of buttons to display (0=no buttons) |
| d_b_l$() | array containing button labels |
| d_b_h%() | array containing character position of label to highlight and capitalise |
| d_b_c$() | array containing character to return if user presses this button |
| m_abort% | 1 = user aborted; 0 = did not abort |
| m_focus% | number of item selected |
| m_action$ | unique listitem ID of selected response from user |
| d_b_pressed$ | character value of pressed button (empty if not pressed) |
| | notes |
- If the number of list items exceeds m_maxlines%, or if the number of list items is too large to fit onscreen, a scrollbar will appear. Excess items can be accessed by scrolling down the menu with the cursor keys.
|
| function | |
| purpose | display or erase statusbar |
| features | |
| s_msg$ | string to display in status bar |
| s_nuke% | toggle to erase statusbar instead (1=erase, 0=don't (default)) |
| | notes |
- the statusbar is displayed on the bottom line of the screen
|
| function | |
| purpose | display titlebar |
| features | |
| p_name$ | * name of program |
| p_ver$ | * program version number |
| p_copy$ | copyright information |
| | notes |
- the titlebar is displayed on the top line of the screen
|
| function | |
| purpose | convert all instances of a given string in a given string to another given string |
| features | |
| sift_s$ | * string to sift |
| sift_c$ | * string to convert from |
| sift_to$ | string to convert sifted characters to |
| sift_s$ | sifted string |
| | notes |
- if sift_to$ is left blank, then sift will delete the nominated string (sift_c$) from the string, replacing it with nothing. This will change the length of the string.
- sift can sift either single or multiple characters.
- if sift_to$ is a different length to sift_c$, then the returned string will be of a different length.
|
| function | |
| purpose | chop a string in two at first, next, previous or last delimiter, or character position |
| features | |
| split_s$ | * string to split |
| split_d$ | delimiter to find (may be more than one character) |
| split_last% | 0 = search from start; 1 = search from end |
| split_start% | character position to start search at |
| split_c% | character position to split at |
| split_l$ | left half of split string |
| split_r$ | right half of split string |
| | notes |
- if both a delimiter and a character position are provided, the string will be split at the character position, and will not be searched for the delimiter.
- this routine does NOT return the delimiting characters themselves, or the character at the character position, in EITHER split_l$ or split_r$ - it is discarded.
|
| function | |
| purpose | remove a record from an SQL database |
| features | |
| sd_path$ | the full path to the MySQL client |
| sd_user$ | the database username |
| sd_pw$ | the database password |
| sd_host$ | the database server address |
| sd_db$ | the database containing the record |
| sd_table$ | the table containing the record |
| sd_keyfield$ | the field name used to identify the record |
| sd_value$ | the field value used to identify the record |
| sd_err$ | result string (blank if none) |
| | notes |
- currently requires the MySQL client, MYSQL.EXE
|
| function | |
| purpose | add a record to an SQL database |
| features | |
| si_path$ | the full path to the MySQL client |
| si_user$ | the database username |
| si_pw$ | the database password |
| si_host$ | the database server address |
| si_db$ | the database containing the record |
| si_table$ | the table containing the record |
| si_items% | the number of fields |
| twod$(x,y) | 2D array of fieldnames and fieldvalues, x=1 for fieldnames, x=2 for fieldvalues, y=field number |
| si_err$ | result string (blank if none) |
| | notes |
- currently requires the MySQL client, MYSQL.EXE
|
| function | |
| purpose | query an SQL database |
| features | |
| sq_path$ | the full path to the MySQL client |
| sq_user$ | the database username |
| sq_pw$ | the database password |
| sq_host$ | the database server address |
| sq_db$ | the database to contain the record |
| sq_table$ | the table to contain the record |
| sq_keyfield$ | (optional) the field name searched for a match (if not provided, all records in the table are returned) |
| sq_value$ | the query string to match on |
| sq_query$ | the query string to match on - if provided, causes a LIKE search instead of an exact match search; in this case, sq_value$ is ignored |
| sq_err$ | result string (blank if none) |
| sq_results% | number of results |
| lst$() | results (in TSV format) |
| | notes |
- if sq_keyfield$ is provided, either sq_value$ or sq_query$ must also be provided
- currently requires the MySQL client, MYSQL.EXE
|
| function | |
| purpose | change a record in an SQL database |
| features | |
| su_path$ | the full path to the MySQL client |
| su_user$ | the database username |
| su_pw$ | the database password |
| su_host$ | the database server address |
| su_db$ | the database containing the record |
| su_table$ | the table containing the record |
| su_items% | the number of fields |
| su_keyfield$ | the field name used to identify the record |
| su_value$ | the field value used to identify the record |
| twod$(x,y) | 2D array of fieldnames and fieldvalues, x=1 for fieldnames, x=2 for fieldvalues, y=field number |
| su_err$ | result string (blank if none) |
| | notes |
- currently requires the MySQL client, MYSQL.EXE
|
| function | |
| purpose | strip leading/trailing spaces from a string, and sub-ASCII 32 characters |
| features | |
| strip_s$ | * string to strip |
| strip_s$ | stripped string |
| | notes |
- improve: strip any character
|
| function | |
| purpose | convert a MySQL table to a CSV file |
| features | |
| sq_path$ | the full path to the MySQL client |
| sq_user$ | the database username |
| sq_pw$ | the database password |
| sq_host$ | the database server address |
| sq_db$ | the database containing the table to export |
| sq_table$ | the table to export |
| t2c_name$ | the file to export to |
| t2c_err$ | result string (blank if none) |
| | notes |
- warning: this routine overwrites the lst and infile arrays
- currently requires the MySQL client, MYSQL.EXE
|
| function | |
| purpose | returns the last line of a text file |
| features | |
| tail_file$ | the name of the file containing the template |
| tail_line$ | the contents of the last line |
| | notes |
- Currently requires DTAIL.EXE
|
| function | |
| purpose | generates a file from a template and a datasource |
| features | |
| template_file$ | the name of the file containing the template |
| template_output$ | the name of the file to contain the generated output |
| lst$() | array containing dataitems, in the format itemname=itemvalue |
| template_err$ | result string (blank if none) |
| | notes |
- currently, a maximum of 50 dataitems are supported
- the template must contain variables assigned like this: $$variable .. this must be on a new line, in the first column.. and the lst$() array must be populated with itemnames that match the variablenames (but not including the $$)
|
| function | |
| purpose | tests that a number stored as a string is less than 32767 |
| features | |
| testint_s$ | * string containing number to query |
| testint_ok% | 0=number greater than 32767; 1=number less than or equal to 32767 |
| | notes |
|
| function | |
| purpose | returns a number with x decimal points |
| features | |
| trunc_num! | * number to truncate |
| trunc_points% | * number to decimal points to truncate to |
| trunc_s$ | the number truncated to the required number of decimal places |
| | notes |
|
| function | |
| purpose | convert a LF-terminated file to CR/LF |
| features | |
| u2d_source$ | the name of the file to convert |
| u2d_target$ | the name of the file to contain the converted text |
| u2d_err$ | result string (blank if none) |
| | notes |
|
| function | |
| purpose | convert a string from URL-encoded format to ASCII |
| features | |
| URLdecode_s$ | the string to convert |
| URLdecode_d$ | the converted string |
| | notes |
- this routine decodes from URL- or percent-encoded format - see http://en.wikipedia.org/wiki/Url_encode
|
| function | |
| purpose | convert a string to URL-encoded format from ASCII |
| features | |
| URLencode_s$ | the string to convert |
| URLencode_d$ | the converted string |
| | notes |
- this routine encodes into URL- or percent-encoded format - see http://en.wikipedia.org/wiki/Url_encode
|
| function | |
| purpose | buffered write to text file |
| features | |
| writf_name$ | * name of file to write to |
| writb_s$ | string to write (empty will write a blank line) |
| writb_init% | 0=don't initialise (default); 1=initialise buffer and write first portion of file to disk |
| writb_flush% | 0=don't flush (default); 1=flush buffer to disk |
| writb_head% | number of lines already in infile array to write as start of file (0 to disable) |
| infile$() | array of strings to write as start of file |
| lst$() | array containing strings to insert as a header into target |
| header_length% | * number of rows of strings to export from list array as header (0 to disable) |
| writf_append% | 1=append to target file; 0=overwrite (default) |
| writf_backup% | 1=create .BAKfile before write; 0=don't (default) |
| writb_err$ | error message (blank if none) |
| | notes |
- the file will not be closed until the buffer is flushed
- a header in the lst$() array will precede a header in the infile$() array when written to file
- How to use:
- initialise the buffer:
writf_name$ = outputfilename$
writf_append% = t%
writf_backup% = f%
writb_init% = t%
writb_head% = 0
header_length% = 0
Call writebuf
- write to the buffer (repeat this until the file is ready to be closed):
writb_s$ = outputstring$
Call writebuf
- flush the buffer
writb_flush% = t%
Call writebuf
|
| function | |
| purpose | write a range of lines to a text file from infile array, with optional backup and append |
| features | will create file if it does not exist; can append or overwrite, can make .BAKfiles |
| writf_name$ | * name of file to write |
| writf_start% | * line in infile array to start writing from (0 for start) |
| writf_stop% | * line in infile array to stop writing at |
| infile$() | array containing strings to write |
| lst$() | array containing strings to insert as a header into target |
| header_length% | * number of rows of strings to export from list array as header (0 to disable) |
| writf_append% | 1=append to target file; 0=overwrite (default) |
| writf_backup% | 1=create .BAKfile before write; 0=don't (default) |
| writf_cycle% | 1=silently affirm .BAKfile overwrite prompt; 0=prompt before overwriting .BAKfile (default) |
| writf_err$ | error message (blank if none) |
| | notes |
|
general-purpose scratch arrays
BAPI/CC defines a number of arrays, for the purpose of data sharing between your program and itself, and also for general use. These are as follows:
| name | size set by | description |
| infile$() | p_size% | holds files read into memory by readfile; holds the data to be written by writefile; is scanned by findssarray; is used by changeINI, writebuf, table2csv |
| lst$() | p_size% | holds data to display for listbox; holds header data to write for writefile; holds template data; holds SQL query results |
| tmp$() | p_size% | holds exploded data for CSV2dim; used by various routines as a scratch array |
| twod$() | inielemax% | a two-dimensional scratch array used by SQLinsert and SQLupdate |
Care must be taken when storing data in these arrays, as it may be either used, or overwritten, by various BAPI/CC routines. However, with a
little skill, manipulating the contents of these arrays in between calls to BAPI/CC functions permits the making of very precise changes to the
data being processed, often with a minimal amount of arbitrary code.
see also: memory usage
debug mode
A verbose troubleshooting mode is available, to assist in development and debugging. Many routines now have debug code built-in;
setting p_debug%=1 activates it. Define this along with your p_name$, p_ver$ settings at the top of your program, before the
BAPI/CC mainline is called.
Whilst in debug mode, the API will operate normally, however "fancy" screen functions (such as showline, showmsg and dialog) instead
produce "simple" output consistent with the rest of the debug mode. This stops cursor positioning calls scrambling the debug output.
showmenu and getform work as usual, however (this can get messy onscreen).
Also available is a "step-by-step" debug option, p_debugstep%. Setting this to true causes BAPI/CC to request a keypress at
various stages of execution, if p_debug%=1 is also set. This allows you to step through startup and execution, to ensure everything
is working as intended.
Note: debug messages may be truncated to fit on one line.
INI how-to: general INI pointers
- the INI file must be a text file (editable with Notepad)
- the INI file must have the same filename as your program file (eg. yourprog.ini)
- the INI file must have a .INI extension
- the INI file must be in the current directory at runtime, unless on startup, p_ourvar$ contains an alternative
location, and p_usevardir% is set true; ... OR... the INI file can be pointed to by using as the FIRST parameter on
the commandline, like this:
C:\>programname /INI:full_name_and_path\to_ini_file.ext
If the INI file is set via the commandline, the following notes apply:
- long filenames, or filenames with embedded spaces, may not be used
- the INI file can have any name and extension, and can be in any directory
- this parameter is removed from the commandline once it is processed by the boot routine, and is thus invisible to BAPI-based programs. The name of the INI file is returned as the variable inifilename$.
- any text after a semicolon (";") is considered a comment and is NOT loaded - except if p_noinistrip$ is set to true
- settings take the general format
setting=value
- don't use = or ; in settingnames
- settingnames are not case-sensitive
- the INI loader strips the variablenames from the left side of the equals sign; an INI entry elementname1=value1 is loaded into the array as simply value1
- the INI file has two parts - a main section and a module section (which can contain up to 100 modules)
- the main section is read automatically each time your program starts; the modules can also, as an option, be loaded automatically at startup, or manually during execution
- modulenames are delimited by [square brackets]
- modules end on the first blank line after the [modulename]
- the names of modules to load are defined by you in the variable readim_s$
- the names of elements to load are defined by you in the variable readim_e$
- free-format elements (with no name) can also be loaded
- data from the main section is stored in cfg$(numsettings%) where numsettings% is the number of settings loaded from the main section
- loaded module elements are placed into a two-dimensional array called inimod$() - each column of the array contains the contents of each module loaded
- each module can be referred to by its column number in the array; module 1 is the module contained in the first column. Thus, inimod$(1,3) contains element 3 of module 1; inimod$(3,5) contains element 3 of module 3
- the first row of each column of inimod$() contains the modulename; the second row contains the total number of loaded elements (including both structured and freeform elements). The other rows contain the elements themselves. Eg.,
[modulename]
6
value1
value2
value3
- to require the INI file, set p_needini%=1 in the program header
- if you have problems, try temporarily setting p_debug%=1 and p_debugstep%=1 (in the program header) - this will show debug
information
INI how-to: writing an INI file
- open a new file using a text editor (such as Notepad)
- choose a modulename, start a new line of INI file, at the first character position, type the modulename enclosed in square backets, eg:
[modulename]
- define elements for the module - these can be either freeformat or structured - a combination is acceptable. Freeformat is simply a list of lines of text. Structured are variables defined as such:
elementname1=value1
elementname2=value2
- save the file as programname.ini where programname matches the name defined in p_name$, in the same directory as your BAS and EXE files.
Note: a different name and location can be used, however the full path and name of the INI file will need to be provided on the commandline in that case.
INI how-to: loading modules automatically at startup
The simplest way to load data from modules is to have the INI loader load them automatically at startup. If you don't do this, you'll need to load the module manually during execution, which can have advantages.
Note: modules loaded at boot are done so AFTER readuserini has executed - don't try and use a module element in readuserini, as it will be empty :)
- write the INI file
- set p_loadmod%=1 in the program header - this tells the INI loader to load all modules in the INI file at boot
- define the modulenames to load in readuserini. set the variable readim_s$ to contain a list of modulenames to load. this is a comma-delimited string, eg.,
[modulename1],[modulename2],[modulename3]
- define the elementnames in readuserini. set the variable readim_e$ to contain a list of elementnames to load. this is also a comma-delimited string, eg.,
elementname1,elementname2,elementname3
This step is optional. If readim_e$ is left blank, all elements will be loaded, in the order they appear in the INI file. They will be treated as orphans/freeform elements in this case.
If readim_e$ is completed, elements named will be loaded into the array *first*, in the order they are listed in readim_e$. Any other elements found in the module will be loaded into the array last, in the order they appear in the INI file, and treated as orphans/freeform elements.
[modulename]
elementname1=value1
elementname2=value2
elementname3=value3
extrasetting=rock
extrasetting=scissors
extrasetting=paper
The module(s) will then be loaded when the program starts up.
INI how-to: loading modules manually during execution
Loading modules automatically at startup is simpler, however loading modules manually during execution can conserve memory, and/or boost performance, allow you to repeatedly load different sets of options, and allow you to read settings from another INI file.
- write the INI file
- tell the INI loader NOT to load all modules in the INI file at boot - set p_loadmod%=0 in the program header
- define each modulename you intend to use in readuserini - set the variable readim_s$ to contain a list of modulenames to load. this is a comma-delimited string, eg.,
[modulename1],[modulename2],[modulename3]
- define the elementnames to load in readuserini. set the variable readim_e$ to contain a list of elementnames to load. this is a comma-delimited string, eg.,
elementname1,elementname2,elementname3
This step is optional. If readim_e$ is left blank, all elements will be loaded, in the order they appear in the INI file. They will be treated as orphans/freeform elements in this case.
If readim_e$ is completed, elements named will be loaded into the array *first*, in the order they are listed in readim_e$. Any other elements found in the module will be loaded into the array last, in the order they appear in the INI file, and treated as orphans/freeform elements.
- At the appropriate point in your code, call the INI loader. Do this as such:
GOSUB getmodele
See getmodele for more information.
INI how-to: including a modulelist and moduledata in one INI file
The modules must be loaded at execution, not at boot. Ensure that p_loadmod%=0.
Attempting to load them at boot will not work. This is because the INI loader tries to load the module elements from the line immediately following the modulelist. For example, a modulelist might look as such:
modulelist=[lsi],[mirror],[spacenet],[pickle-2],[test]
with each module being defined lower down in the INI file. The INI loader searches for the name of the module, and finds the modulelist line before it finds the module itself. It then attempts to load the module as usual, however because in reality it has only found the list of modules, not the module itself, the module is not loaded.
INI how-to: working with orphans/freeform elements
Orphans/freeform elements are those found in a module but not defined in readim_e$.
Orphans/freeform elements are NOT stripped of any leading settingname (unlike structured elements). For instance, a element which appears
in an INI module like this:
amalgamate=dancetrax,[dead links]
Will be loaded verbatim (unchanged) into inimod, IF "amalgamate" is NOT listed in readim_e$. If, however it is a structured element
(that is, if "amalgamate" IS listed in readim_e$), it will be loaded into inimod like this:
dancetrax,[dead links]
Freeform elements need not have a leading settingname at all. A list of email addresses, for example, if included as a module in an INI
file, can be loaded as freeform elements.
Freeform elements can be loaded automatically at startup, or manually during execution.
Processing freeform elements is complicated because the first two rows of the module's column in the inimod array are not elements, but the name and number of elements. So, to read any freeform elements from the inimod array, one must remember to allow for these...
- freeform elements start at inielenum% + 3
- freeform elements end at VAL(inimod$(modulenumber%,2)) + 4
reserved file handles
These filehandles are used internally by the BAPI, and should not be used by your programs.
If you attempt to use one of these reserved filehandles, you may hang your program, lose data, or experience other abnormal program behavior.
| handle | used by |
|---|
| 255 | readdir |
| 254 | scanfile |
| 253 | readfile |
| 252 | writefile |
| 251 | appendfile |
| 250 | writebuf |
| 249 | copyblock |
| 248 | getmodele |
| 247 | unix2dos |
| 246 | template |
| 245 | tail |
| 244 | SQLquery |
| 243 | epochdate |
| 242 | runlongcmd |
| 241 | template |
| 240 | freespace |
runtime error codes
These messages may appear during program execution, and result in immediate termination of the program.
They are produced by the abort routine.
| code | meaning |
|---|
| 1 | TEMP environment variable not set add the line SET TEMP=directoryname to your AUTOEXEC.BAT and reboot - where directoryname is a directory to be used for tempfiles. |
| 2 | temporary directory [directoryname] inaccessible The directory specified by the TEMP environment variable cannot be accessed - does it exist, and are permissions granted? |
| 3 | function [functionname] missing parameter [parametername] A call was made to a BAPI function without supplying a required parameter. |
| 4 | [unused] |
| 5 | INI file not found The program's INI file is required, and is missing from the current directory. |
| 6 | this program requires Win32 The program must be executed under a 32-bit Windows environment (eg. Windows 95, 98, 98SE, ME, NT4, 2000 or XP). |
| 7 | tempfiles left in [directoryname] The program has failed to clean up its tempfiles. |
| 8 | this program requires Win9x The program must be executed under a Windows 9x environment (eg. Windows 95, 98 or 98SE). |
| 9 | unable to write to logfile [logfilename] Is the path to the logfile valid? Are permissions granted? |
| 10 | environment variable not set [variablename] Is the variable set in AUTOEXEC, or in the shell environment? |
| 11 | unique temp counter overflow Your program attempted to create more than 9999999 tempfiles. |
internal variables
| p_size% | the maximum length of the infile, directory, list, and tmp arrays. |
| p_cfgsize% | the maximum number of settings permitted in the main section of the INI file. |
| p_cfgsize% | this setting is also multiplied by 2 to determine the maximum number of DOS environment variables to be cached. |
| d_max% | the maximum height of a dialog box. On a 25-line screen, it's 21 lines. |
| inimodmax% | the maximum number of modules permitted in the INI file. |
| inielemax% | the maximum number of elements permitted in each module of the INI file. |
| p_errlog$ | the name of the logfile (if any). |
| p_bufsize% | the size in bytes of the readfile/writefile buffer. |
memory usage
BAPI memory allocation is controlled by a small number of internal variables. Although making changes to any of these can reduce memory consumption, the three primary memory-hogs are p_size%, inimodmax%, and inielemax%.
There are two ways to control these variables, both of which are accomplished by editing the boot subroutine near the top of BAPI/CC's code. The first is to change the hardcoded numeric assignments made to either variable. For example, change p_size%=2000 to p_size%=1000 or p_size%=1500.
The second way is to change the multipliers used to increase the size of these variables when the BAPI runs in compiled mode. To change the multipliers, find the code in the boot routine that resizes the variables in question:
p_size% = p_size% * 4: inimodmax% = inimodmax% * 4: inielemax% = inielemax% * 4
...and change one, two, or all three numeric values. The bigger the number, the more memory is used. These values are multiplied with the variables to determine the final size of the arrays the BAPI uses internally in compiled mode. Example change:
p_size% = p_size% * 2: inimodmax% = inimodmax% * 2: inielemax% = inielemax% * 2
Although p_size% may at first be the obvious target, inimodmax% and inielemax% are actually multiplied together to form a two-dimensional array. If inimodmax% is set to 200 (allowing 200 modules in the INI) and inielemax% is also set to 200 (allowing 200 elements per module), that's 40000 data items allocated! In this case, reducing inimodmax% to 100 would only permit 100 modules in the INI, but would reduce INI memory allocation by half. If your program might only ever have five or ten modules, you can safely reduce this number.
 
- no direct support for graphics, sound or mice
 
 
These routines are an enhanced port of my BAPI QBASIC library.
| September 2005 | version 0.01 | initial port from QBASIC
| | March 2006 | version 0.02 | numerous fixes and repairs
| | 2007 - 2008 | version 0.03 | numerous new routines and tweaks
| | February 2009 | version 1.00 | ported and improved documentation; public release
|
 
bapicc.exe  library
|