BAPI/CC

Copyright 2005 - 2009, Stuart Udall

overview
important bits
installation
configuration and startup
controls and methods
issues and limitations
planned improvements
revision history
download

version 1.00: February 6, 2009


 
  overview next section top of page

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.


 
  important bits next section top of page

  • requires PowerBASIC Console Compiler 4.0 or higher

  • the following points are this program's terms and conditions of use:
  1. This program is hereinafter known as "the Software".
  2. The Software comes with no warranty and is used at your own risk.
  3. The Software is not (and will never be) complete and as such may behave strangely.
  4. The Software is the copyrighted property of the author.
  5. The Software may be distributed freely.
  6. The Software may NOT be incorporated into a commercial work without prior written permission from the author.
  7. 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.


 
  installation next section top of page
  1. run the self-extracting archive
That's it. :-)


 
  configuration and startup next section top of page

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.


 
  controls and methods next section top of page

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
mainline 16function index
purpose set program variables, call boot, browser, restart or exit
features 
expects..to contain..
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))
returns..containing..
DOS errorlevela 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
abort 7function index
purpose graceful abandoning of ship.
featureswill display errormessage if there is one; wait for keypress
expects..to contain..
a_err%error code
a_msg$error message
returns..containing..
notes
  • A table of runtime errors is here.


function
addmenu 1function index
purpose adds menu items to the menu array
features
expects..to contain..
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)
returns..containing..
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
anykey 3function index
purpose wait for user keypress, return keypress and keycode
features
expects..to contain..
s_msg$string to display in status bar
returns..containing..
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
appendfile 4function index
purpose append a line to a text file
featuresif the file does not exist, it will be created
expects..to contain..
appef_name$* name of file to append to
appef_s$string to append
returns..containing..
appef_err$error message (if appropriate)
notes


function
auth 3function index
purpose gets a password from the user
featurescan ask for re-entry to confirm
expects..to contain..
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.
returns..containing..
auth_pw$the password entered
notes
  • All text entered in the auth field is starred out.


function
boot 16function index
purpose pre-define environment, arrays, load DOS vars, INI file
featuressets up screen, tests critical variables, detects operating system, recovers DOS environment variables, sets TEMP directory, reads INI file
expects..to contain..
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
returns..containing..
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
changeini 3function index
purpose changes the value of an INI setting in the INI file
featureswill create an INI file if it does not exist; will add the setting if it does not exist**
expects..to contain..
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
returns..containing..
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
copyblock 4function index
purpose copy a range of lines from one file to another file
features 
expects..to contain..
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)
returns..containing..
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
copymove 3function index
purpose copy or move a file from one location to another
featurescan copy or move across UNC paths, drives and directories
expects..to contain..
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)
returns..containing..
movef_err$error message (blank if none)
notes


function
csv2dim 3function index
purpose converts a comma-separated-string to an array
features 
expects..to contain..
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)
returns..containing..
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
deltree 1function index
purpose silently deletes a directory tree
features
expects..to contain..
delt_name$the name of the directory to delete
returns..containing..
delt_err$result string (blank if none)
notes
  • supports W9X and W2K and above


function
dialog 9function index
purpose show alert/question, get keypress/answer; log to file
featurescan also display buttons; can log messages to file; updates statusbar; returns action
expects..to contain..
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)
returns..containing..
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
dim2csv 1function index
purpose parse the tmp array into a CSV-delimited string
features 
expects..to contain..
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)
returns..containing..
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
drawbox 9function index
purpose draw a box onscreen, with optional title, note, status, content, buttons, getconfirmation, anykey and vanish
features 
expects..to contain..
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)
returns..containing..
d_b_pressed$character value of pressed button (empty if not pressed)
action%0=NO; 1=YES (if dialog was a question)
notes


function
epochdate 1function index
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
expects..to contain..
ed_source$the date (in MM-DD-YYYY format) or epochtime to convert
returns..containing..
ed_converted$converted date (either an epochtime, or in MM-DD-YYYY format)
notes
  • Currently requires EPOCHDAY.EXE


function
findrule 2function index
purpose returns rule number, given rule name
features
expects..to contain..
findr_name$name of module to find
returns..containing..
findr_num%number of found of module
notes
  • do not supply [square brackets] around the modulename


function
findsetting 3function index
purpose returns value of a specified setting in INI file
features 
expects..to contain..
lookin$* name of setting to query
returns..containing..
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
findss 5function index
purpose find the next or previous occurence of a substring in a string
features 
expects..to contain..
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
returns..containing..
foundat%starting character position of found substring in string (0 if not found)
notes


function
findssarray 3function index
purpose find the next occurence of a substring in infile array
features 
expects..to contain..
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)
returns..containing..
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
freespace 4function index
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)
expects..to contain..
frees_driveletter$the letter of the drive to work with
frees_sizeinmegs%return size in megabytes (Mb) (0=no (default); 1=yes)
returns..containing..
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
getaltkey 2function index
purpose returns ASCII character from alt-keycode
features 
expects..to contain..
alt_code%* raw extended keycode
returns..containing..
alt_key$letter of keypress
notes


function
getdate 6function index
purpose returns date in "Month Daynumber, 4DigitYear" format
features also returns the number of days since January 1, 1900
expects..to contain..
getdate_this$date to process (in mm-dd-yyyy format)
returns..containing..
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
getdaynum 1function index
purpose returns the number of days since year start, or since a pre-specified date
features
expects..to contain..
getday_date$date to process (in mm-dd-yyyy format)
returns..containing..
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
getdosvar 1function index
purpose returns value of specified DOS environment variable
features 
expects..to contain..
getvar_name$* name of variable to query
returns..containing..
getvar_val$value of variable (blank if not found)
notes


function
getform 9function index
purpose get multiple data items from user in dialog box
featurescursor 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
expects..to contain..
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
returns..containing..
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
getHTTP 1function index
purpose download a file with HTTP
features 
expects..to contain..
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))
returns..containing..
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
getmodele 5function index
purpose retrieve all elements from a module in memory or in INI file
features 
expects..to contain..
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
returns..containing..
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
getNTLMinfo 1function index
purpose returns NT Lan Manager configuration
features
expects..to contain..
returns..containing..
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
getosver 2function index
purpose returns operating system and version
features 
expects..to contain..
returns..containing..
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
getrand 6function index
purpose generate a unique 16-digit string and filename
featurescan return string as a tempfilename; can prepend a prespecified string to the generated string
expects..to contain..
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.
returns..containing..
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
getregkey 3function index
purpose returns the contents of a specified Windows registry key
features 
expects..to contain..
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)
returns..containing..
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
hex2dec 1function index
purpose converts a hexadecimal number to decimal
features 
expects..to contain..
h2d_in$* string containing number to convert
returns..containing..
h2d_out!the input number, expressed in decimal
notes


function
hostlookup 1function index
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
expects..to contain..
hostl_address$the hostname or IP address to resolve
returns..containing..
hostl_resolved$the resolved hostname or IP address
notes
  • supports IPv4 only


function
ifexist 8function index
purpose detect the presence of a file or directory on disk
featureswill use default drive and/or directory if not supplied
expects..to contain..
ifexist_name$* filename to test for
returns..containing..
ifexist_found%1=file exists; 0 if not exists
ifexist_name$fully-qualified path to file
ifexist_err$error message (if any)
notes
  • fully supports wildcards


function
ifinmod 3function index
purpose to see whether a given string is contained within a given module
featuresThis 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.
expects..to contain..
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)
returns..containing..
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
nukebox 1function index
purpose erase current dialog box
features 
expects..to contain..
returns..containing..
notes


function
openforappend 1function index
purpose opens a file for appending, with full errorhandling
features
expects..to contain..
appeof_name$the name of the file to open
appeof_handle%the filehandle to use
returns..containing..
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
printfile 1function index
purpose print a file on a printer
features
expects..to contain..
printf_name$the name of the file to print
printf_printer$the name of the printer to print on
returns..containing..
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
progress 6function index
purpose show progress bar onscreen
featurescan display a second progress bar underneath
expects..to contain..
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
returns..containing..
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
putFTP 1function index
purpose upload a file with FTP
features 
expects..to contain..
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
returns..containing..
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
readdir 16function index
purpose obtain directory contents from FAT-16, FAT-32, NTFS or UNC volumes
featuresif not supplied, will resolve default drive and/or directory
expects..to contain..
readd_name$name of directory to read
readd_noinfo%if set to 1, enables high-speed mode
returns..containing..
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
readfile 7function index
purpose read a range of lines from a text file into infile array
featureswill set buffer overflow flag if file is too big for available memory
expects..to contain..
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)
returns..containing..
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
refresh 1function index
purpose restores the screen to a virgin state
features
expects..to contain..
returns..containing..
notes
  • this routine restores the screen to its state when the program starts - a blank screen with the titlebar across the top


function
runfromdir 1function index
purpose runs specified command from within a specified directory
features
expects..to contain..
runf_dir$* directory to execute command within
runf_cmd$* command to execute
returns..containing..
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
runlongcmd 5function index
purpose runs specified commandline
featurescommandline can be longer than the QBASIC limit of 127 characters - up to 255 characters; also returns errorlevel
expects..to contain..
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)
returns..containing..
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
safekill 1function index
purpose deletes file, with errorhandling
features
expects..to contain..
safef_name$the name of the file to delete
returns..containing..
safef_err$result string (blank if none)
notes


function
scanfile 5function index
purpose find the next or previous occurence of a string in a text file
features 
expects..to contain..
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
returns..containing..
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
sendmail 4function index
purpose send an email with SMTP
features 
expects..to contain..
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)
returns..containing..
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
showline 3function index
purpose displays a formatted line onscreen
featurescan also erase the line
expects..to contain..
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
returns..containing..
notes
  • output is in the form prompt: [data]
  • valid numbers for showl_datacol% range between 1 and 15


function
showlistbox 1function index
purpose displays a table of data onscreen, allows selection
features
expects..to contain..
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
returns..containing..
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
showmenu 4function index
purpose display scrollable menu, wait for cursor-based selection, parse user response
featuresautosizing, returns selection, updates status
expects..to contain..
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
returns..containing..
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
showmsg 10function index
purpose display or erase statusbar
features 
expects..to contain..
s_msg$string to display in status bar
s_nuke%toggle to erase statusbar instead (1=erase, 0=don't (default))
returns..containing..
notes
  • the statusbar is displayed on the bottom line of the screen


function
showtitle 2function index
purpose display titlebar
features 
expects..to contain..
p_name$* name of program
p_ver$* program version number
p_copy$copyright information
returns..containing..
notes
  • the titlebar is displayed on the top line of the screen


function
sift 1function index
purpose convert all instances of a given string in a given string to another given string
features 
expects..to contain..
sift_s$* string to sift
sift_c$* string to convert from
sift_to$string to convert sifted characters to
returns..containing..
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
split 4function index
purpose chop a string in two at first, next, previous or last delimiter, or character position
features 
expects..to contain..
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
returns..containing..
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
SQLdelete 1function index
purpose remove a record from an SQL database
features
expects..to contain..
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
returns..containing..
sd_err$result string (blank if none)
notes
  • currently requires the MySQL client, MYSQL.EXE


function
SQLinsert 1function index
purpose add a record to an SQL database
features
expects..to contain..
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
returns..containing..
si_err$result string (blank if none)
notes
  • currently requires the MySQL client, MYSQL.EXE


function
SQLquery 2function index
purpose query an SQL database
features
expects..to contain..
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
returns..containing..
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
SQLupdate 1function index
purpose change a record in an SQL database
features
expects..to contain..
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
returns..containing..
su_err$result string (blank if none)
notes
  • currently requires the MySQL client, MYSQL.EXE


function
strip 2function index
purpose strip leading/trailing spaces from a string, and sub-ASCII 32 characters
features 
expects..to contain..
strip_s$* string to strip
returns..containing..
strip_s$stripped string
notes
  • improve: strip any character


function
table2csv 1function index
purpose convert a MySQL table to a CSV file
features
expects..to contain..
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
returns..containing..
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
tail 1function index
purpose returns the last line of a text file
features
expects..to contain..
tail_file$the name of the file containing the template
returns..containing..
tail_line$the contents of the last line
notes
  • Currently requires DTAIL.EXE


function
template 3function index
purpose generates a file from a template and a datasource
features
expects..to contain..
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
returns..containing..
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
testint 1function index
purpose tests that a number stored as a string is less than 32767
features 
expects..to contain..
testint_s$* string containing number to query
returns..containing..
testint_ok%0=number greater than 32767; 1=number less than or equal to 32767
notes


function
trunc 1function index
purpose returns a number with x decimal points
features 
expects..to contain..
trunc_num!* number to truncate
trunc_points%* number to decimal points to truncate to
returns..containing..
trunc_s$the number truncated to the required number of decimal places
notes


function
unix2dos 2function index
purpose convert a LF-terminated file to CR/LF
features
expects..to contain..
u2d_source$the name of the file to convert
u2d_target$the name of the file to contain the converted text
returns..containing..
u2d_err$result string (blank if none)
notes


function
URLdecode 1function index
purpose convert a string from URL-encoded format to ASCII
features
expects..to contain..
URLdecode_s$the string to convert
returns..containing..
URLdecode_d$the converted string
notes
  • this routine decodes from URL- or percent-encoded format - see http://en.wikipedia.org/wiki/Url_encode


function
URLencode 1function index
purpose convert a string to URL-encoded format from ASCII
features
expects..to contain..
URLencode_s$the string to convert
returns..containing..
URLencode_d$the converted string
notes
  • this routine encodes into URL- or percent-encoded format - see http://en.wikipedia.org/wiki/Url_encode


function
writebuf 4function index
purpose buffered write to text file
features 
expects..to contain..
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)
returns..containing..
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:
    1. initialise the buffer:
         writf_name$ = outputfilename$
         writf_append% = t%
         writf_backup% = f%
         writb_init% = t%
         writb_head% = 0
         header_length% = 0
         Call writebuf
      
    2. write to the buffer (repeat this until the file is ready to be closed):
         writb_s$ = outputstring$
         Call writebuf
      
    3. flush the buffer
         writb_flush% = t%
         Call writebuf
      


function
writefile 16function index
purpose write a range of lines to a text file from infile array, with optional backup and append
featureswill create file if it does not exist; can append or overwrite, can make .BAKfiles
expects..to contain..
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)
returns..containing..
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:

namesize set bydescription
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:

    1. long filenames, or filenames with embedded spaces, may not be used
    2. the INI file can have any name and extension, and can be in any directory
    3. 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

  1. open a new file using a text editor (such as Notepad)
  2. choose a modulename, start a new line of INI file, at the first character position, type the modulename enclosed in square backets, eg:
    [modulename]
    

  3. 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
    

  4. 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 :)

  1. write the INI file
  2. set p_loadmod%=1 in the program header - this tells the INI loader to load all modules in the INI file at boot
  3. 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]
    

  4. 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.

  1. write the INI file
  2. tell the INI loader NOT to load all modules in the INI file at boot - set p_loadmod%=0 in the program header
  3. 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]
    
  4. 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.

  5. 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.

handleused by
255readdir
254scanfile
253readfile
252writefile
251appendfile
250writebuf
249copyblock
248getmodele
247unix2dos
246template
245tail
244SQLquery
243epochdate
242runlongcmd
241template
240freespace

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.

codemeaning
1TEMP 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.

2temporary directory [directoryname] inaccessible

The directory specified by the TEMP environment variable cannot be accessed - does it exist, and are permissions granted?

3function [functionname] missing parameter [parametername]

A call was made to a BAPI function without supplying a required parameter.

4[unused]
5INI file not found

The program's INI file is required, and is missing from the current directory.

6this program requires Win32

The program must be executed under a 32-bit Windows environment (eg. Windows 95, 98, 98SE, ME, NT4, 2000 or XP).

7tempfiles left in [directoryname]

The program has failed to clean up its tempfiles.

8this program requires Win9x

The program must be executed under a Windows 9x environment (eg. Windows 95, 98 or 98SE).

9unable to write to logfile [logfilename]

Is the path to the logfile valid? Are permissions granted?

10environment variable not set [variablename]

Is the variable set in AUTOEXEC, or in the shell environment?

11unique 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.


 
  issues and limitations next section top of page

  • no direct support for graphics, sound or mice

 
  planned improvements next section top of page

  • not listed here

 
  revision history next section top of page

These routines are an enhanced port of my BAPI QBASIC library.

September 2005version 0.01initial port from QBASIC
March 2006version 0.02numerous fixes and repairs
2007 - 2008version 0.03numerous new routines and tweaks
February 2009version 1.00ported and improved documentation; public release

 
  download top of page

bapicc.exe  library