XBasic FAQ

XBasic is a comprehensive program development environment that integrates a powerful editor, compiler, debugger, and GuiDesigner into a seamless working environment encompassing the whole process of creating fast, efficient, reliable programs.

The XBasic language is clean, readable, powerful, and complete.  The XBasic compiler translates programs from source form into fast, compact, binary machine instructions in memory where it is executed and debugged. After they're debugged, XBasic programs can be translated into assembly language to assemble and link with conventional tools to make standalone EXE programs and DLL libraries.

XBasic is as well suited to novices as programming wizards, and is appropriate for virtually all programming tasks.  For science and engineering XBasic has extensive math libraries, built-in complex number arithmetic and function library, and very extensive graphics.  For business, XBasic has a 64-bit integer data type, user-defined types optimized for database I/O.  For system programs, XBasic has high level language replacements for low level programming features that are much easier to read, understand, and maintain.  For all applications, XBasic designed to support rapid development of compact, efficient, reliable, readable, portable, well structured programs.

XBasic Features

Online XBasic Resources

Description: The original XB site for XB as published by Max Reason. It contains info on the development of XBasic as well as a place to download v6.0022  for Windows and  Linux.
Maintained by: Max Reason

Description: The XBasic development page. Download the most recent version of XB from this site. Here you can also  find information about new XBasic releases, file bug reports and read news concerning XB.
Maintained by: Eddie Penninkhof

Description: The official XBasic Website. Check here for news and links on XBasic.
Maintained by: Vic Drastik

Description: German/Austrian non-commercial software site, most/all progs written in XBasic. This is a german-speaking site.
Maintained by: Rene Schickbauer

Description: European XB Mirror-Site download Server. Download the most recent version of XB from this site.
Maintained by: Rene Schickbauer

Description: Contains a lot of info to get you started with XBasic, including several tutorials geared for newbies.
Maintained by:  Vincent Voois

Description: The online file depository for Yahoo XBasic message group members. You can download the current version of XBasic from the downloads section at  http://groups.yahoo.com/group/xbasic/files/downloads/
Maintained by: Vic Drastik

XBasic Reference Manual
Description: This HTML reference manual contains information on each of the functions in the XBasic libraries.  It was designed to be a standard x-reference guide in a simple, printable format. The direct download:
Maintained by: Tom Stout

Description: XBasic Mailing List on Yahoo Groups.
Maintained by: Vic Drastik
Post message: xbasic@yahoogroups.com
Subscribe:    xbasic-subscribe@yahoogroups.com
Unsubscribe:  xbasic-unsubscribe@yahoogroups.com
List owner:   xbasic-owner@yahoogroups.com

The most current FAQ may be found at:
Description: The XBasic Frequently Asked Questions FAQ. This FAQ is a collaborative effort on the part of the Xbasic mailing list.
Maintained by: David Szafranski dszafranski@infonie.fr

Last modified:
October 2001

Index of Sections

Index of Questions:

Section A - Program Development Environment (PDE)

Section B - General Programing

Section C - Graphics

Section D - Text

Section E - External DLLs

Section F - Printing

Section G - Mailing List

Section H - Open Source

Section I - Misc.

Section J - Installation

Section K - GUI Programming

Section L - File and Database Processing

Section M - Multimedia & Game Support

Section A - Program Development Environment (PDE)

Q.A1- Why can't I see the icons on the toolbar?

This usually happens when you install XBasic wrong.
You can install XBasic on any hard-drive (c: d: e: etc), but you must install into the \ root directory and select the "recreate subdirectories" option.
For v6.0022, you should have the following directories (the c: can be d: or e:)
While for v6.2, the images are stored in c:\program files\xbasic\images .

If not, you installed improperly and the only solution is to remove everything you installed already and install XBasic again.

Assuming you didn't delete the file you downloaded, you don't need to download it again.

Q.A2- Are the default font and default colors settable in a dialog?

Default colors are set by XgrSetDefaultColors().

The default font for XBasic, or any other XBasic application, is chosen when the application starts up.  First XBasic creates an xxx/fonts.xxx file that contains a list of bitmap fonts that may be appropriate as the default font.  Then XBasic reads in file xxx/font.xxx and sets the default font to the first font name not preceded by a ' comment character that is known to the system.  If no xxx/font.xxx file exists, XBasic chooses the default font it thinks best.

You can select a larger font for the development environment and console windows with Option Misc.

Q.A3- Is there an "autosave" feature in the event of crashes?

When crashes occur the PDE saves the current application code as file xb.sav.  Only rarely is the PDE unable to save the current application.  Look for xb.sav !!!

Q.A4- When a fatal runtime error occurs, can I change a value and continue running?

Yes.  You can change the values of variables and/or change where the program will continue executing.  Consider the divide by zero and segment violation errors in the following function as examples.
' ######################
' ##### Entry () #####
' ######################
x = 0  
y = 11
z = 0
a = y \ z ' a = 11 divided by 0 - divide by zero error>
b = XLONGAT(x) ' b = contents of memory at address 0x00000000 - invalid memory address
PRINT x,y,z,a,b ' print results
Execute this entry function to cause a divide by zero runtime error at a = y \ z since z = 0 as set by the previous line. But you can now display the variables window (F8) and make z non-zero and continue program execution.  Alternatively, you can set the text cursor on a later line and select Run Jump to move the execution line past the error line, then continue execution.

Q.A5- Why do bitmap files have to stay in the same place as during development?

Bitmap files can be located anywhere they can be opened.  Perhaps you are referring to the fact that images selected for grids with the GuiDesigner AppearanceWindow generate full path file names when design windows are converted into grid functions by Window ToFunction .  If you do not change these names, the locations of the bitmap image files are in fact fixed, just as you say.  To change to a relative path name, edit the grid function as in this example:

XuiSendMessage (g, #SetImage, 0, 0, 0, 0, 0, @"\\xb\\xxx\\xstart.bmp")
XuiSendMessage (g, #SetImage, 0, 0, 0, 0, 0, @"xxx\\xstart.bmp")

The second example skips the leading " \\xb\\ " part of the filename, which loads xstart.bmp from the xxx subdirectory of any current directory.

Of course the name of the bitmap file can be changed to a variable or expression:

XuiSendMessage (g, #SetImage, 0, 0, 0, 0, 0, @imageStart$)
XuiSendMessage (g, #SetImage, 0, 0, 0, 0, 0, imagePath$ + "start.bmp")

Q.A6- Why don't the accelerator key sequences appear to function (eg Alt-e, g etc)?

The "accelerator" hot-keys for menus are currently disabled in the PDE environment. But they will work fine in your programs. This is a known problem.

Q.A7- How do I get rid of the "report messages" screen when I run my program?

When you select "Window ToFunction", GuiDesigner converts the window you designed into two functions - a grid function that creates and operates the window, and a callback function or xxxCode() function that gets sent callback messages when something important happens.

GuiDesigner puts an XuiReportMessage() at the top of all those xxxCode() functions it generates so you can easily see what kind of messages the xxxCode() is receiving. If you comment out that XuiReportMessage() line, your program will stop reporting messages to you, both in the development environment and in standalone programs.

When you are developing GuiDesigner programs, remember you can always add one of these XuiReportMessage() calls to the top of ANY grid-function or xxxCode() function to "see what's happening".

Q.A8- Why do I sometimes I get unresolved external symbol errors when I shouldn't?

When the PDE compiles more than one program, it sometimes looks for symbols that existed in a previous compilation. This rare bug has not yet been tracked down and exterminated. For now you'll have to exit the PDE and restart it.

Q.A9- Is there a command to clear the console window of all text?

Do you know you can double/triple/quadruple click in GuiDesigner text grids to select word/paragraph/all-text? That makes it LOTS quicker to highlight all text, then a simple "delete" keystroke will do the trick.

In your program, make sure you have IMPORT "xst" in your PROLOG, then you can use

XstClearConsole ( )

Q.A10- How do I compile my application to an executable? I don't see any option in the PDE that does this.

You don't see an option there, because there are actually three steps to making an executable program or a DLL.

1. Debug program in PDE
2. Create an assembly language file
3. Compile the assembly language file

Step 1.
Before you attempt to create a standalone executable or library, completely debug your program in the program development environment.

Step 2.
To convert your program into a standalone executable or library, select R un A ssembly or R un L ibrary from the PDE main menu. The PDE compiles your source program into an assembly language file of the same name, except with a .s suffix. At the same time, the PDE creates a .DEC file, a .def file, and a .mak file.

prog .x   - your source program (replace prog with its real name)
prog .s   - source program compiled into assembly language
prog .dec - type, function, constant declaration file
prog .def - import/export definition file required by library manager
prog .mak - makefile directs tools to create standalone .exe or .dll

You can also compile a program directly from a DOS window with the following command lines:

xb prog.x      ' for standalone executable program
xb prog.x -lib ' for standalone executable library

Step 3.
To create your standalone program or library with Win32 tools:

Click the MS-DOS icon to start a DOS window or: Start > Programs > MS-DOS Prompt .
Then, enter in the DOS window...

cd \xb                         'for v6.0022
cd c:\progra~1\xbasic\myDir\   'for v6.1+

with v6.1+, you need to set the environment variables (if you haven't already set them in your autoexec.bat file) by calling a batch file. So at the prompt enter:


to set the current directory to the program development directory or the directory where your program resides. Then type

nmake -f prog .mak

(where prog is the name of your program) to create a standalone executable prog.exe or a library prog.dll .

You can rename standalone executables, but never copy a standalone executable into the /xb development directory or your /bin directory and attempt to run it there. It will runtime link to the wrong xb.dll and the program development environment will start instead of your program !!!

prog.exe/prog.dll is your standalone executable program/library. They contain everything specific to your program/library, but not any of the XBasic library functions in xst, xui, xgr, or xma. The Xbasic library functions are contained in the XBasic runtime dll  in \xb\run\xb.dll or \windows\xb.dll.

Q.A11- Why does the text I enter in any TextLine box in the Appearance Setup Window clear the value when I press the on screen "Enter" button?

After you type some text into any TextLine box in the Appearance Setup Window, eg, HintString, HelpString, or TextString, you need to press your keyboard Enter key for the data to be entered correctly. If you click on the Enter PushButton first, before hitting the Enter key, then your text string will be lost. Sorry, but it's just the way it works...

Q.A12- Is there any way to reopen the console window after you've closed it?

In your PROLOG, make sure you have IMPORT "xst" uncommented. Then use any of the console functions in your program to hide or display the console:

XstDisplayConsole()   'display a previously hidden console
XstHideConsole()      'hide console window
XstShowConsole()      'show console window

Q.A13- How do I keep the PDE window from re-sizing after program execution?

Go to the property.xxx file in your xxx directory, and put these lines of code in that file.

XBasic reads the property file on startup, and if it finds code like this it will run full screen down to the sys tray in windows9x. The 1015, and 706 are the window size for my 17" monitor, if yours is a different size then change these numbers accordingly. The font line will change the PDE fonts. Use whatever your system has that you want.

xb   Environment   XuiSendMessage (*, #ResizeWindow, 4, 23, 1015, 706, 0, 0)
xb   Environment   XuiSendMessage (*, #SetFont, 280, 400, 0, 0, 1, @"courier new")

Q.A14- Why don't any of the help items in the help-menu work properly? Why doesn't the instant help feature work either?

If you are using Windows, and starting Xbasic with shortcut icon. it may not be set up properly. You must spesifically name the startup directory of the shortcut, (ususally "c:\xb") Now everything should work fine .

Q.A15- How can I copy and paste Xbasic text program results from the console window (eg. into notepad)? The usual Ctrl-c Ctrl-v doesn't work.

Try the old fashioned DOS method CTRL-INS and SHIFT-INS.

Q.A16- How do I  keep the console window from appearing in my program?

In your PROLOG, make sure you have IMPORT "xst" uncommented. Then use any of the console functions in your program to hide or display the console:

XstDisplayConsole()   'display a previously hidden console
XstHideConsole()      'hide console window
XstShowConsole()      'show console window

One way console can be disabled is by adding the following code into your InitProgram( ) function:

XstGetApplicationEnvironment (@standalone, @reserved)
IF standalone THEN XstHideConsole()

It won't prevent the console from popping up, but it will hide the console as soon as XstHideConsole ( ) is executed. XstGetApplicationEnvironment ( ) will look if your program is running stand-alone executable or within the PDE. If it is in the PDE, it won't hide the console so that you can still use commands to display debug output. 

Two command-line switches affect the console-window, "-HideConsole" and  "-NoConsole".  When applications are launched by clicking desktop icons,   a simulated command-line is executed, so either of these switches can  eliminate the console during application startup.  "-HideConsole" has a  major advantage - it can be printed-to even while hidden, and your code can display and hide it anytime.  For example, you might want to print  a running record of the steps the user and application take, but make  it visible only if and when the user so request.  Or you might only display disasterous error messages.

If you truly want the console eliminated, the "-NoConsole" switch  makes XBasic never create the console grid/window.  But then the console is permanently unavailable.

Q.A17- Is there a way to permanently set the cursor color in TextArea grids?

You can add a line to your xbasic/templates/property.xxx file.  The property.xxx file contains the various grid function properties to be used on start-up. To change the cursor color, you would change the dull color property for all XuiTextArea grids, including the PDE lower TextArea.

xb XuiTextArea   XuiSendMessage (TextLower, #SetColorExtra, $$White, -1, -1, -1, 0, 0)

The color is XORed to the screen backgound color, so the color you see will be different from what you specify.  I use a blue background, and a $$White cursor is actually yellow while a $$LightYellow value will display a blue cursor on a white background.

Q.A18- How can I prevent the XBasic Information window from appearing at start-up?

The "About" start-up window normally only appears the first 10 times you start the program, plus once every 16 times after that. If you edit C:\windows\xb.ini to include the line

about = 0

the about window will only diplay if you select help|about from the PDE menu. If you make it "about = -1", the window always appears. Normally it is a positive number which increases each time you run the PDE.

Q.A19- How do I prevent the PDE windows from being smudged and distorted when moved off the display area or over another window?

XB windows aren't using controls called from the Win32 APIs. The grids/widgets/controls in a XBasic window are drawn by XBasic. The XBasic windows do not automatically redraw its contents when it is dragged around or off the screen. To fix this problem while using the PDE:

Right click anywhere on the main Windows desktop display.
From the popup window, select Properties.
In the Display Properties dialogue, select the Effects tab.
Deselect the Show Window Contents While Dragging property and hit the Apply button.

To fix  this problem in your own GUI programs, try modifying the Entry ( ) function as follows:

DO                           ' the message loop
XgrPeekMessage (@wingrid, @message, @v0, @v1, @v2, @v3, r0, r1)  IF message = #WindowResized THEN
XgrGetWindowGrid (wingrid, @grid)
  XuiSendMessage (grid, #Redraw, 0, 0, 0, 0, 0, 0) END IF XgrProcessMessages (1) ' process one message LOOP UNTIL terminateProgram ' and repeat until program is terminated

Q.A20- How do I recompile Xbasic from the source code?

To be able to compile XBasic itself you need the following things
 - A working XBasic compiler (note: XBasic is largely written in XBasic itself)
 -  The XBasic source code found on SourceForge  ( http://sourceforge.net/project/showfiles.php?group_id=1657&release_id=11540 )
 - The Cygwin utilities. This can be the full distribution (available from http://sources.redhat.com/cygwin/ ) or a 'light' distribution (available from http://groups.yahoo.com/group/xbasic/files/files/Cygwin%20Files/ ) or from the the XBasic SourceForge file page shown above, look for xbasic-Util-1.0.exe

To compile XBasic:
  1. Unpack the sources into a separate directory from the XBasic binary directory (usually C:\xbasic-6.2.1 by default)
  2. In a DOS window, change to that directory (at prompt type cd xbasic-6.2.1)
  3. xbvars
  4. make
  5. make install
The installer for the Cygwin utilities added a couple of lines to C:\windows\xbvars.bat to specify where you installed them.
The source files do have a path included in the ZIP archive, same applies if you had downloaded the binary files as a ZIP. You MUST tell your unzip program to restore the original directory structure, it won't work otherwise. So if you tell it to extract to C:\, it will create a directory C:\xbasic-6.2.1 along with several subdirectories.
To recompile XBasic under Windows, open a DOS prompt. Change to the directory the source files are in
  cd xbasic-6.2.1
then run xbvars.bat, and then just type "make".
The Cygwin make utility (which is a Windows version of the Linux make utility) automatically looks for a file named "Makefile" in the current directory, and then follows the instructions in that file. You'll see the XBasic Console window open and close several times as it compiles the files in the source directory, and quite a few lines printed after you originally typed "make".
That only builds the files though, to actually install them to your current XBasic directory you then need to type
  make install
If for some reason you wanted to install to a different directory (say you want to be sure your new version works before overwriting the old one), you'd have to reset the environment variable XBDIR to your new directory, as in
  set XBDIR=C:\XBasic-Test
 make install

After executing "make install", you may wish to replace the old runtime dll (C:\windows\xb.dll) with the new one which has been copied to the \bin directory as xbrun.dll.

copy %XBDIR%\bin\xbrun.dll C:\windows\xb.dll

(And answer yes when it asks if you want to overwrite the old file.)

Provided you didn't make any errors in your changes to the source code, that should be all there is to it.
(Since XBasic is mostly written in XBasic, you need a working XBasic to compile the files. The same would apply if you were rebuilding a C compiler, which would itself be written in C).
If you are running Linux rather than Windows, you already have the Linux versions of the Cygwin utilities and there is no "xbvars.bat". You'd just switch to the source directory, type "make" followed by "make install" and that would be it.

Section B - General Programing

Q.B1- How does one call Win32 API functions from XBasic?  

The functions for Win32 are declared in user32.dec, gdi32.dec, kernel32.dec, and shell32.dec. Each .dec file corresponds to a Windows dynamic link library (.dll) file that exports the various API functions: user32.dll, gdi32.dll, kernel32.dll, and shell32.dll. In order to use an API function, you first need to know which dll library the function is included in.

For example, the function Rectangle (hdc, x, y, w, h) is in gdi32.dll and is listed in gdi32.dec. In order to use this function, you must IMPORT the gdi32.dll library using the IMPORT statement in the beginning of your PROLOG:

IMPORT "gdi32"

Once imported, all the functions in the dll are available to use just like any other XBasic function. See the example program api.x.

The *.dec files to not list EVERY available Win32 API function call. If the function you wish to use is not shown in the appropriate *.dec file, then simply add it to the *.dec file.

Call Win32 API functions exactly the same way that you call any function within a DLL.

[1] Determine the library's name and location.

It should be called *.dll and be on your path , ideally in the current directory (while testing) or in c:\windows\system\ (for general use)

[2] Determine the exact name of the function you wish to call. 

This can either be found in reference information, or directly with an appropriate program - I use the great freeware file manager PowerDesk 4 for this, from http://www.ontrack.com . Powerdesk displays this information automatically , but it occasionally doesn't work, so then I use the MS freeware DLL utility called Dependency Walker , from http://www.dependencywalker.com . This is simple to use , and does a recursive descent , listing all the functions and DLLs used by a given DLL and the functions and DLLs used by them, and so on. Highly recommended.

[3] You now need to know how to pass information (commands , parameters ,etc.) to the DLL

You could get this by disassembling the DLL , but a much easier way is to look it up. There are many references on the Net giving this information for various languages like C, and these are easily adapted to Xbasic. Using this information , you must create a header file of the form dllname.dec , where dllname corresponds to dllname.dll . For examples , just look in your c:\xb\
directory and model your .dec file on these.

[4] Finally , you need to add this information to your program.

Put the statement

IMPORT "dllname"

in the prolog of your XB programme , and you can then use the functions in the DLL as if you had included the source code of the DLL directly into your program.

Q.B2- How can I add message queue asynchronous timer interrupts to my program?

Normal programs, and especially GUI programs, are synchronized by the message queue. When a message is processed by XgrProcessMessages() , all actions caused by processing the message are performed in the expected order before the next message is processed. Programs can therefore assume that program variables will not be unexpectedly modified during message processing. This reduces the complexity of programs enormously.

Most programs with asynchronous aspects simulate asynchronous behavior by setting and starting GraphicsDesigner grid timers which add TimeOut messages to the message queue when they expire. When these TimeOut messages are subsequently processed by XgrProcessMessages() , a grid function receives the TimeOut message and can process the asynchronous timer event in the normal straightforward manner because the asynchronous timer has been synchronized by its passage through the message queue.

Programs with asynchronous aspects that cannot be simulated by timers often employ a similar technique. One line is added to the message processing loop in their Entry() function to call a function that performs asynchronous activity. Again, apparently asynchronous activity is processed in a synchronous manner.

  XgrProcessMessages (0)
  Asynchronous ()    ' check/process asynchronous program aspects

Though there are many other methods to handle asynchronous activity in a synchronous way, some programs require some true asynchronous processing. Consider a program that needs to respond to certain conditions within a limited period of time, but also contains one or more functions that may take longer to complete than the response interval. The synchronous way to handle this situation is to add a line that calls an asynchronous processing function in as many places as necessary to assure adequate response time. The shorter the response interval gets, however, the more places the asynchronous processing function must be called. Furthermore, the length of time required to execute various parts of a program depends on computer speed, and is therefore not portable unless written for the slowest possible machine.

The standard function library contains two functions that support fully asynchronous processing, namely XstStartTimer() and XstKillTimer() . Timers created by XstStartTimer() are not associated with GraphicsDesigner or the message queue. When they expire, the function associated with the timer is called immediately, potentially between ANY two machine instructions. Program variables can thus be in any state, and its even possible for these timers to interrupt programs between machine instructions that update the two 32-bit parts of GIANT and DOUBLE variables! Therefore the program must be written to anticipate all possible adverse interactions and avoid them. As long as asynchronous processing functions are not themselves interrupted and do not read variables that are altered elsewhere in the program, they can be fairly simple. Otherwise careful and detailed design of handshaking is required to avoid disastrous interaction between the normal and asynchronous parts of programs.


Q.B3- How can I make my process take less CPU time under certain circumstances?

XstSleep(msec) causes a process to yield to other processes for a specified number of milliseconds.  As a convenience, msec = 0 tells the process to yield the rest of its time slice, and be activated again the next time it is it's turn.

Note that Windows and some versions of UNIX automatically give the process that created the selected window a higher priority than all others.  Many XBasic programs run visibly slower when none of its windows are selected.

One way to conditionally lower the priority of an XBasic process follows:
' message processing loop at bottom of Entry()
  XuiProcessMessages (1)
  IF condition THEN XstSleep (msec) ' add this line
LOOP UNTIL terminateProgram


Q.B4- How do I put timers into my GuiDesigner application?

One of the sample applications is xgrids.x.  This file is a collection of grid functions that implement many basic grid types. The XuiPressButton() grid function exercises the grid timer in all ways.  Timer related messages include:

 XuiSendMessage (grid, #GetTimer, @msec, 0, 0, 0, kid, 0)
 XuiSendMessage (grid, #SetTimer, msec, 0, 0, 0, kid, 0)
 XuiSendMessage (grid, #StartTimer, 0, 0, 0, 0, kid, 0)

Note that running timers are disabled by #SetTimer with msec = 0 .

Q.B5- How do I call a callback function and have it execute a particular subroutine.

When you select Window ToFunction in the toolkit, GuiDesigner converts the currently displayed design window into a pair of functions, a "grid function" and a "callback function".  When your program is running and something important happens in the window, the grid function calls XuiCallback() , which in turn calls the callback function with a #Callback message, and the real message in r1 .   Usually the original message is #Selection .

But your programs can call callback functions too.  You can arrange arguments to simulate a callback, or you can arrange the arguments in any other way you wish.   Near the top of most callback functions, you'll find something like the following:

FUNCTION TestCode (grid, message, v0, v1, v2, v3, kid, r1)
$MenuBar = 1    ' kid #1
$TextLine = 2   ' kid #2
$Button = 3     ' kid #3
$Custom = 100   ' custom kid #
IF (message = #Callback) THEN
callback = r1
message = r1

CASE #Selection  : GOSUB Selection  ' normal #Selection message
CASE #Custom     : GOSUB Custom
' or custom code right here
SUB Selection
CASE $MenuBar  : ' code to handle MenuBar selections

CASE $TextLine : ' code to handle TextLine selections
CASE $Button   : ' code to handle Button0 selections
CASE $Custom   : ' code to handle custom capability
The following three lines were added to the GuiDesigner generated code to prepare the callback function for special purpose messages from your program:
$Custom = 100 ' custom kid #

CASE #Custom : GOSUB Custom ' or custom code right here

CASE $Custom : ' code to handle custom capability

To invoke the CASE #Custom : GOSUB Custom line, your program calls:
TestCode (grid, #Custom, v0, v1, v2, v3, kid, r1)
To invoke the CASE $Custom line, your program calls:
TestCode (grid, #Selection, v0, v1, v2, v3, $Custom, r1)

Sample applications acircle.x and ademo.x contain an example.  Also make sure you
XgrRegisterMessage (@"Custom", @#Custom)
in InitProgram().

Q.B6- Can I send messages to functions whose windows don't have focus?

Programs can call grid functions and callback functions without regard to keyboard or mouse focus. Everything works the same with or without focus. The only thing focus does is route keyboard input to the focus window. Your program can set the keyboard focus to a particular grid by sending the grid a #SetKeyboardFocus message.


Q.B7- Why aren't EXTERNAL variables visible between programs?

EXTERNAL variables are shared between statically linked programs, not libraries.  In other words, if three programs declare EXTERNAL trouble, and the object files of the three programs are linked together into a single executable, a single trouble variable is referenced by all three programs, and trouble is therefore shared by all three programs.   The executable can be a .EXE or a .DLL .

If three programs are linked into three executables, however, all three programs has its own trouble .
XuiSendMessage (g, #SetImage, 0, 0, 0, 0, 0, dir$ + "my.bmp") .

Q.B8- How do I get a Random Number, ie. a =RND(5)+1?

XBasic does not have a built-in random number generator (RNG). There is a random number library available, as a DLL and as source code. It can be found on the XBasic Yahoo web site file vault. Go here:


and click on xbrandom.zip, or here is the direct URL :


The instructions are included.

Q.B9- Does XBasic support basic parallel port I/O functions?

No it does not, but it is fairly easy to use an external DLL for port access. First you find one, figure out the lib command and make a .lib file for it if it didn't come with one, create .dec and .def files for it, declare external in your code and after that its use is transparent. I used Fred Bulback's IO.DLL file. A VB example for using this DLL is found at I/O Control Using Using Visual Basic .

IO.DLL can be downloaded from http://www.southwest.com.au/~jfuller/bulback/
or directly from http://www.southwest.com.au/~jfuller/bulback/io.dll

Otherwise, there's a whole page of similar DLLs listed here:

Also, you should see the post under DLLs, How can I read/write to the parallel or serial ports in XB?

Here's what I did to make IO.DLL work, I'm sure the others are fairly similar:

Create the io.dec and  io.def  files as shown below.

------------ io.dec file -------------------------
EXTERNAL CFUNCTION PortOut (ioPort%%, ioValue@@)
EXTERNAL CFUNCTION SetPortBit (ioPort%%, ioBit@@)
EXTERNAL CFUNCTION ClrPortBit (ioPort%%, ioBit@@)
EXTERNAL CFUNCTION NotPortBit (ioPort%%, ioBit@@)
EXTERNAL CFUNCTION GetPortBit (ioPort%%, ioBit@@)
------------ io.def file -------------------------
I made the IO.LIB file, required for linking to standalone, with the following dos command:
LIB /def:io.def
In PROLOG section of application source...
IMPORT  "io"
Commands used to call DLLs would vary depending on the DLL. The IO.DLL uses the following commands:
x = PortIn(portadr%%)
PortOut(portadr%%, byte@@)

Q.B10- Are STATIC arrays supported in XBasic?

I have zillions of static arrays all over the place!  The easiest and best way to dimension and initialize them is like the following:

  STATIC USHORT  array[]

  IFZ array[] THEN GOSUB Initialize
' body of the function
' *****  Initialize  *****
SUB Initialize
  DIM array[65535]
  FOR i = 0 TO 65535
    array[i] = i
  NEXT i

 This works correctly because XBasic arrays  are always empty until they are DIMensioned.
   IFZ array[] THEN
 is all it takes.  The dimensions [and contents] of static arrays  never change unless code in the function does it.

Q.B11- How do I make command line arguments work the same in the environment and a standalone executable?

Programs call XstGetCommandLineArguments (@argc, @argv$[]) to get command line arguments. But the command line arguments a standalone executable will receive are not available to the program when it is run in the environment. To test the effect of various command line arguments on a program in the environment, you need code like the following:
'  ...
XstGetApplicationEnvironment (@standalone, 0)
IF standalone THEN
XstGetCommandLineArguments (@argc, @argv$[])
argc = 3
DIM argv$[2]
argv$[0] = "progname.exe"
argv$[1] = "foobar.dat"
argv$[2] = "-flag"
' code that processes command line arguments in argv$[]
This code executes the first part of the IF block when the program is run as a standalone executable, and the second part when the program is run in the PDE. A standalone program will thus take its command line arguments from the command line, while the same program run in the environment will take its command line arguments from those explicitly defined in the second part of the IF block. If you'll be doing lots of command line argument testing, you could write a fancier second part of the IF block to input accept a variable number of arguments from the console each time the program is run.

Alternatively XstSetCommandLineArguments (argc, @argv$[]) sets the command line arguments.

The following code returns the original command line arguments, even after they have been changed.

argc = -1
XstGetCommandLineArguments (@argc, @argv$[])
The following code reinstates the original command line arguments after they have been changed.
argc = -1
XstGetCommandLineArguments (@argc, @argv$[])
XstSetCommandLineArguments (argc, @argv$[])

Q.B12- Is there a command at the beginning of every program that will make all variables double, or do you have to specify each and every variable?

You have to specify your variables IF they have to be of any other type than XLONG.

Variables are automaticly XLONG unless you specify otherwise.

You can specify types of variables in groups if you don't want to use loads of define lines:

DOUBLE #InterDouble1, #InterDouble2, #InterDouble3, ##GlobalDouble4
SSHORT #InterShort%, ##GlobalShort2%, LocalShort3%
STRING ##GlobalA$, LocalB$, LocalC$
The examples also show the prefix used to stamp variables as local, internally global and environmentally global.

Q.B13- How do I round off numbers in Xbasic?

If you want to round off a float variable to the nearest integer, just convert to an integer using ULONG ( ) or SLONG ( ):

x# = 5.51
x  = ULONG(x#)

Here is a function that will round any value to any number of decimal places desired.

FUNCTION Entry ( )
a# = Round(10512.3456#, -3)
b# = Round(10512.3456#, -2)
c# = Round(10512.3456#, -1)
d# = Round(10512.3456#, 0)
e# = Round(10512.3456#, 1)
f# = Round(10512.3456#, 2)
PRINT a#; b#; c#;,d#; e#; f#;

FUNCTION  DOUBLE Round (DOUBLE number, power)
 pTen# = 10# ** power
 RETURN INT(number / pTen# + .5#) * pTen#

Running the above example gives these results:
10512.346   10512.35  10512.3   10512   10510   10500

Q.B14- What is the correct way to show the path for a file using OPEN function?

This is incorrect:
filenum% = OPEN ("c:\TEST.DB", $$RW)
These are correct:
filenum% = OPEN ("c:/test.db", $$RW)
filenum% = OPEN ("c:\\TEST.DB", $$RW)
It is suggested that every XBasic programmer ALWAYS choose the / "forward slash" as the path/directory separator. This works for filenames on Linux and Windows and internet-addresses. That's because every path/filename argument in every XBasic intrinsic and library function converts path separators to the appropriate character.

Furthermore, the \ "backslash character" is a confusing path separator because in literal strings the \ "backslash character" is an "escape" character that needs to be \\ doubled-up to produce a single backslash.

To always select the / "forward slash" path separator is ALWAYS easier and more reliable.

Q.B15- How do I put a double quote " character inside of a string variable?

Special characters can be embedded in strings by using the "escape" backslash character "\".  You can't type a newline
inside a string, so you can type \n instead. But this means any backslash you actually want to type must itself be escaped, in order to PRINT a single backslash you'd actually have to say PRINT "\\".

So, to add double quote characters to your string, you would use \" instead.
s$ = "some characters and \"this is in quotes\"."

The complete list of backslash codes (as we call them) is as follows:

\a alarm (bell)
\b backspace
\d ASCII DELETE (CHR$(127)), not the Delete key
\e escape (CHR$(27))
\f formfeed (CHR$(12))
\n newline (CHR$(10))
\r return (CHR$(13))
\t tab
\v vertical tab
\z CHR$(255)
\0 through \9, CHR$(0) through CHR$(9)
\A through \V, ASCII codes 10 through 31
\" a quote (since you can't otherwise put a quote inside a string)
\\ a backslash
\xnn (where the n's are hexadecimal characters),
     the character whose ASCII code has the hex value nn

With any other character (say, !), the code \! will just be translated as ! (with the backslash removed).

These codes - and the general note about backslash - apply to literal string, strings you type on program lines. Strings read from files or by user input do not use backslash codes unless you were to use the library function XstBackStringToBinString$(string$) to convert them.

Q.B16- How can I assign individual values to arrays without the use of READ/DATA like in previous Basic languages?

Here are some ideas:

Just assigning simple values to an array in a sorted order is pretty simple:

FOR X = 0 TO 10
Array[X] = X + 1
' Array[0] - Array[10] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
ArrayStepper = 0
FOR X = 0 TO 100 STEP 10
Array[ArrayStepper] = X
INC ArrayStepper
' Array[0] - Array[10] = 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
When your data is not an ordered series.
'Data stored in a string where each piece of data is 4 characters long
'       123412341234123412341234
data$= "123 23  4   138934  3   "
'find out how long the data$ is
upper = UBOUND(data$)
'same as INT(upper\4)
numberOfDataPieces = upper/4
DIM dataArray[numberOfDataPieces]
pointer = 1
FOR i = 0 TO numberOfDataPieces
'DOUBLE will return the value of the string
dataArray[i] = DOUBLE(MID$(data$,pointer,4))
pointer = pointer + 4
FOR i = 0 TO numberOfDataPieces
PRINT dataArray[i]
This would work of course with string information too like:
month$ = "January  Febuary  March    April    September"
MID$ is slower than Data${i} but if you want to convert it's ascii-value back to a string-value to display it probably doesn't matter that much...

For storage (from memory to disk) using the Var${pos} is the quickest way.

Another method:

Data$ = "496967496740947676496749505038264807"
FOR i = 0 TO UBOUND(Data$)
  PRINT i , Data${i}
You can enter byte data into a string using escape hex notation thus :
s = "\x41\x42\x43\x61\x62\x63"
FOR i = 0 TO UBOUND(s)
  PRINT i , s{i}
This prints
0   65
1   66
2   67
3   97
4   98
5   99
You can enter nybble data using a string which can then be processed into bytes or higher data types - here is a simple example using XB escapes :
s = "\0\1\2\3\4\5\6\7\8\9\A\B\C\D\E\F"
FOR i = 0 TO UBOUND(s)
  PRINT i , s{i}
with output
0   0
1   1
2   2
3   3
4   4
5   5
6   6
7   7
8   8
9   9
10  10
11  11
12  12
13  13
14  14
15  15
Another favorite method is pseudo-hex notation , as follows :
s = "0123456789:;<=>?"
FOR i = 0 TO UBOUND(s)
  PRINT i , s{i} & 0xF
- output as above.

Or you can use ordinary hex(here the conversion is a little more tricky):

s = "0123456789ABCDEF"
FOR i = 0 TO UBOUND(s)
  PRINT i , (s{i} - 48 + 7 * ( s{i}>57 ))
The 4-bit nibbles you extract from the DATA string can then be built up into higher data types using the usual XB intrinsics , or directly , as in:
  c0 = s{i} & 0xF
  c1 = s{i+1} & 0xF
  c2 = s{i+2} & 0xF
  c3 = s{i+3} & 0xF
  xlongvariable = (c3<<24) OR (c2<<16) OR (c1<<8) OR (c0)
If you want to read them from files this can be done even easier, yet depending on what kind of binary structure the file and your data has...

Does it has multiple type keys?
Are the types 32-bit aligned?

If your elements are aligned in 32-bit dividable blocks, you can read the whole slug in one pass....

DIM MyArray[256]
FileHandle = OPEN(file$, $$RD)
READ [FileHandle], MyArray[]
' 256 * 4 bytes = 1024 bytes are just read into the array
Here's an example displaying the reading of a user / composite type reading an aligned range of various typed elements into a whole array:
'This is an aligned TYPE:
TYPE MyRecordStructure
UBYTE  .Byte1 '-|
UBYTE  .Byte2 ' four byte
UBYTE  .Byte3 ' aligned block = 32 bit block 1
UBYTE  .Byte4 '-|
ULONG  .Long1 ' one four byte block = 32 bit block 2
SSHORT .Short1' two 2 byte
SSHORT .Short2' blocks = 32 bit block 3
' Now declare the array:
MyRecordStructure RecordData[256]
FileHandle = OPEN(file$, $$RD)
READ [FileHandle], RecordData[]
' 256 * 12 bytes (3072 bytes) are read into the array.
' Now what can you do with an unaligned type?
TYPE MyRecordStructure
UBYTE  .Byte1 '-|
UBYTE  .Byte2 ' four byte
UBYTE  .Byte3 ' aligned block = 24 bit block!
ULONG  .Long1 ' one four byte block = 32 bit block 2
SSHORT .Short1' two 2 byte
SSHORT .Short2' blocks = 32 bit block 3
If your data-file has an non-32 bit aligned format like above the following would happen if you would try to read data in one pass to the array:

The first four bytes are read, the first three will be put in the three ubytes, the fourth will be discarded then the ULONG will contain the four bytes of which the last one supposed to belong in the first byte of the first short and also the byte of short2 is shifted downwards...

To make a long story short...

Unaligned data reading can only be done this way:

'This is an UNaligned TYPE:
TYPE MyRecordStructure
UBYTE  .Byte1 '-|
UBYTE  .Byte2 ' four byte
UBYTE  .Byte3 ' aligned block = 24 bit block!
ULONG  .Long1 ' one four byte block = 32 bit block 2
SSHORT .Short1' two 2 byte
SSHORT .Short2' blocks = 32 bit block 3
' Now declare the array:
MyRecordStructure RecordData[256]
FileHandle = OPEN(file$, $$RD)
FOR X = 0 TO UBOUND(RecordData[])
  READ [FileHandle], RecordData[X].Byte1,RecordData[X].Byte2,
  RecordData[X].Byte3, RecordData[X].Long1
  READ [FileHandle], RecordData[X].Short1, RecordData[X].Short1
' 256 * 11 bytes (2816 bytes) are read into the array per element.

Q.B17-How can I play a WAVE .wav sound file?


Q.B18-What is the difference between passing values by reference and sharing variables with SHARE?

You can pass arguments in functions by value or by reference.  Arguments that are passed by reference must use the @  prefix. All strings and arrays MUST be passed by reference.

MyFunction (v0, @v1, @string$, @array[])

v0 is passed by value
v1, string$, and array are passed by reference

If v1, string$, or array[] are modified within MyFunction ( ), then on the return of the function, these arguments will hold their new values and be available to the calling program.

Shared variables are globally available to all functions within your program. However, you must declare the shared variables within each function that uses them.

FUNCTION Entry ( )
  SHARED v0, v1, string$, array[]
  MyFunction ( )
  PRINT v0, v1, string$, array[0], array[1]

FUNCTION MyFunction ( )
  SHARED v0, v1, string$, array[]
  v0 = 5 : v1 = 10 : string$ = "a string"
  REDIM array[1]
  array[0] = 15 : array[1] = 20

Q.B19- How does one enter a negative DOUBLE/SINGLE constant in XB?

 It takes a little work to determine the value, but you would enter it as a "DOUBLE image" preferably. A DOUBLE image is more accurate than entering the decimal anyway. It is written as the prefix "0d" followed by 16 hex digits.

A good example can be found in the xma.dec file (which is the file you see in the PDE by selecting help|math). Towards the end of that file, after the function declarations, mathematical constants such as $$PI and $$E are declared.

$$PI = 0d400921FB54442D18

In order to determine the representation of a particular DOUBLE value, you would have to use DHIGH and DLOW to convert the binary representation into two XLONG values, then convert those into two hex strings. Example:

FUNCTION DoubleImage$ (DOUBLE x)
  xhigh = DHIGH(x)
  xlow = DLOW(x)
  RETURN ("0d"+HEX$(xhigh, 8)+ HEX$(xlow, 8))

x# = -1.2345
d$ = DoubleImage$ (x#)
PRINT  x#, d$, DOUBLE(d$)

This gives us the following results:
-1.2345 0dBFF3C083126E978D  -1.2345

So we can define our constant for -1.2345 as:
$$neg = 0dBFF3C083126E978D

The DOUBLE image doesn't need a negative sign since the highest order bit IS the sign bit.

A SINGLE image is "0s" followed by 8 hex digits. For that, you'd use XMAKE to read the 32-bit SINGLE as if it were an XLONG, and convert the result to hex with HEX$, prefixing the required "0s" to it. (Note, that's a number zero followed by s, not a letter O; similarly double image was number zero followed by d.)

Q.B20- How do I pass an array to a C function?

Cfunction (&myarray[])

 1. In XBasic, arrays can only be passed by reference which requires a @ prefix, or passed by address for  passing to C functions which requires the & prefix.

 2. In XBasic, arrays are always followed by their []  square-brackets, in every context.  In XBasic,




 are entirely independent; myarray is a variable,  myarray[] is an array, myarray[n] is an array element.

 By the way, the same goes for function names,  which ALWAYS must be followed by ( ) parentheses.
 So if you want to pass the address of an XBasic function func() as a callback function, you need




 &func is the address of a variable, while &func()   is the address of a function.

Q.B21- How do I determine the path of the executing XBasic program?

XstGetProgramFileName$() retrieves the full path and file-name of the executing program. You can use one of the 'path-splitting' functions like XstGetPathComponents() to retrieve the directory path. It's both implemented on Win32 and Linux, but only in 6.1.x and higher.

Q.B22- What is the best way to determine if a string variable a$ is a number?

There is a function in the standard library xst XstStringToNumber() that can check this for you. This function will convert the string to the appropriate type. It returns -1 if the string is not a valid number.

Q.B23- How can arrays be made global?

What do you mean by "global"?

 If you mean "shared by all functions in the same program/module",  then they can - in at least two ways:

   SHARED [TYPENAME]  array[]

 inside every function that wants to share the array,  where data-type is XLONG unless specified in the  variable declaration by TYPENAME, or


 Note: the # in #array[] is part of the name, so


 are entirely separate arrays.

 Arrays that start with # are automatically SHARED  everywhere they appear in the module/program.

 If  #array[] is XLONG, then you need not declare  #array[] in the PROLOG, because the default data-type  is XLONG.  Also, you need not declare arrays whose data-type is made explicit by a type suffix, like:


 Other arrays made SHARED by virtue of starting with an # character must be declared in the PROLOG like:

  SHARED  SINGLE  #array[]
  SINGLE  #array[]           ' i think this works

 If "global" means "shared by all statically linked  modules", then replace SHARED with EXTERNAL in the above discussion, or the # prefix with ## prefix.  But the ## prefix only works to share with modules created with XBasic, since the ## is part of the name and C/C++ doesn't support that.  So to make this work with C/C++ modules, the EXTERNAL declaration in the PROLOG is the only workable way, as in:

   EXTERNAL  array[]

 What also won't work is:

   EXTERNAL  array![]

 because the ! is part of the array name in XBasic,  not just a data-type specifier.

Q.B24- Is there a timer that has 1 millisec or better resolution?

You can use the function XstGetDateAndTime as a simple timer but it
is misleading to think that it can achieve nanosec resolutions.
In using nanos in XstGetDateAndTime, Max was thinking ahead to a time
when future processors can achieve such a thing. But as it stands now,
this function at its best can only do 55 msecs between calls to itself.

Listed below are the various results I got for various Win9x and XB
timing functions while trying to time a 1 msec interval:

XstGetDateAndTime 55 msec
XstGetSystemTime 5 msec (which uses GetTickCount)
GetTickCount 5 msec (kernel32.dll)
timeGetTime 1 msec (winmm.dll)
QueryPerformanceCounter 4 microsec (kernel32.dll)

QueryPerformanceCounter which is found in kernel32.dll is used in conjunction
with QueryPerformanceFrequency. These two functions are not currently in the
XB kernel32.dec file so you would need to add them to that file in order to use them.

For more information on timing functions and for a test program, see the
following posts:


Section C - Graphics

Q.C1- Does GraphicsDesigner support three or five coordinate systems?

For purposes of coordinate conversion, there are five coordinate systems:

display  XgrGetGridBoxDisplay (grid, @x1Disp, @y1Disp, @x2Disp, @y2Disp)
window   XgrGetGridBoxWindow (grid, @x1Win, @y1Win, @x2Win, @y2Win)
local    XgrGetGridBoxLocal (grid, @x1, @y1, @x2, @y2)
grid     XgrGetGridBoxGrid (grid, @x1Grid, @y1Grid, @x2Grid, @y2Grid)
scaled   XgrGetGridBoxScaled (grid, @x1#, @y1#, @x2#, @y2#)

For purposes of drawing, there are three coordinate systems:

local   XuiDrawLine (grid, color, x1, y1, x2, y2)
grid    XuiDrawLineGrid (grid, color, x1Grid, y1Grid, x2Grid, y2Grid)
scaled  XuiDrawLineScaled (grid, color, x1#, y1#, x2#, y2#)

The name of every GraphicsDesigner drawing function determines the coordinate system the function draws in, as follows:

Drawing functions that do not specify a coordinate system, like XgrDrawLine() , draw in local coordinates and manipulate the local coordinate drawpoint.

Drawing functions that end with " Grid ( ", like XgrDrawLineGrid() , draw in grid coordinates and manipulate the grid coordinate drawpoint.

Drawing functions that end with " Scaled ( ", like XgrDrawLineScaled() , draw in scaled coordinates and manipulate the scaled coordinate drawpoint.


Q.C2- How do I keep my graphics in my grid from being erased when it is covered by another window or when I minimize/maximize my window? How do I create an "image or buffer" grid to make my images "stick"?

When an XBasic GuiDesigner grid is resized or uncovered, it's contents are lost. If the contents are graphics understands, like background color, border graphics and text strings, BMP images, then GuiDesigner typically automatically redraws the grid - unless you prevent it from doing so.

Sometimes you want to draw program-specific graphics into a grid - like the charts in my futures programs or optical design cross-sections in my optics programs. In the XBasic samples, you'll find a sample called "acircle.x" that draws a pretty circular picture made of line segments. When that window is uncovered, or minimized and redisplayed, GuiDesigner has no record of all the lines the program has drawn, so it cannot redraw them. But GuiDesigner has a convenient way to deal with these situations with so-called "image grids" and "buffer grids".

An "image grid" is just like a regular grid except it is invisible and cannot be displayed. You can do anything to an "image grid" as any other grid, including set color, border, text & other properties, resize, redraw, etc. Though programs can't display an "image grid", they can copy their contents onto normal grids, and thereby display their images.

GuiDesigner supports the notion "buffer grid" to make capturing images very, very simple. A "buffer grid" is just an "image grid" that is "attached" to a regular grid. Once attached, the "buffer grid" captures a copy of everything drawn onto the normal grid it's attached to. Whenever a grid is exposed or displayed, GuiDesigner sees if a buffer grid is attached to the grid, and if so, draws the image in the buffer grid onto the normal grid, and thereby restores the image.

Once you create and attach an "image grid" to a normal grid, the grid is redrawn properly for you automatically by GuiDesigner and your program can forget it even exists, except if and when the grid it's attached to is resized. Then you need to resize the buffer grid too.

For illustration, the sample program "acircle.x" has exactly the "problem" you describe. If you click the "Pause" button to pause drawing, then cover-and-uncover the drawing grid, the image is not restored. By adding a few lines of code to the "SUB Resize" subroutine, you can solve the problem with a buffer grid.

Below I reproduce "SUB Resize" in the Circle() function, with a marked section of code added to create and manage the buffer grid. This is the only change to the program. Obviously the code for a grid in a non-resizable window is even simpler - just create and attach the image grid once, with no calculations to decide the sizes and positions of grids.

#####  modified Resize subroutine  #####
' *****  Resize  *****
SUB Resize
v2Entry = v2
v3Entry = v3
GOSUB GetSmallestSize
v2 = MAX (v2, v2Entry)
v3 = MAX (v3, v3Entry)
XuiPositionGrid (grid, @v0, @v1, @v2, @v3)
innerWidth = v2 - bw - bw
innerHeight = v3 - bw - bw
gw = innerWidth
gh = innerHeight - h
bw0 = innerWidth / 3
bw1 = bw0
bw2 = innerWidth - bw1 - bw0
bx0 = bw
bx1 = bx0 + bw0
bx2 = bx1 + bw1
by = v3-h-bw
XuiSendMessage (grid, #Resize,  bw, bw,  gw, gh, 1, 0)
XuiSendMessage (grid, #Resize, bx0, by, bw0,  h, 2, 0)
XuiSendMessage (grid, #Resize, bx1, by, bw1,  h, 3, 0)
XuiSendMessage (grid, #Resize, bx2, by, bw2,  h, 4, 0)
XuiResizeWindowToGrid (grid, #ResizeWindowToGrid, 0, 0, 0, 0, 0, 0)
' #####  start new code : create buffer grid first time through this
XuiGetValues (grid, #GetValues, @g, @i, 0, 0, 0, 0)
XuiSendMessage (grid, #GetGridNumber, @g, 0, 0, 0, $DrawingArea, 0)
XgrCreateGrid  (@i, 1, 0, 0, v2, v3, r0, g, 0)
XgrSetGridBuffer (g, i, 0, 0)
XgrClearGrid (g, 0)
XuiSetValues (grid, #SetValues, g, i, 0, 0, 0, 0)
XgrSetGridPositionAndSize (i, 0, 0, gw, gh)
' #####  end new code : buffer grid resized same as $DrawingArea kid
XuiGetSize (grid, #GetSize, 0, 0, @width, @height, 0, 0)
XuiCallback (grid, #Resized, 0, 0, width, height, 0, 0)

Q.C3- How can I prevent the drawing functions from drawing outside the boundaries of the target grid?

Fundamentally, grids are "fictions". The programmer may think there are subwindows everywhere there's a grid, but in fact there is only the outer window (or the whole screen potentially). The only "reality" to grids are coordinates in the main window (screen). So when you clear a grid or draw text in a grid or whatever, all that's happening is that the GraphicsDesigner function adds the x,y position of the grid to the coordinates you specify and clear/draw/whatever.

This works perfectly fine for the vast, vast, vast majority of situations. For example, when you clear a grid, graphicsDesigner clears just that part of the window that is allocated to the grid. When you draw grid borders, GraphicsDesigner draws in the grids boundaries. Since grids (in the GuiDesigner sense) draw themselves - and GraphicsDesigner does the 'right thing' in all the simple and normal situations - only people drawing graphics ever find out grids are just "smoke and mirrors"! :-)

Anyway, Linux XBasic has REAL subwindows so drawing outside grids does not happen in Linux. Anywhere you might have this problem, which means where you draw graphics of a type that might spill outside the grid, send a #SetClipGrid message to the "dangerous" grid with its own grid #. This will clip drawing outside the boundary of the grid itself.

XuiSendMessage (grid, #SetClipGrid, grid, 0, 0, 0, 0, 0)
will normally do the trick if you have the grid number of the grid, but if you need to send this message to a kid grid, you'll have to get the grid number of the kid grid first, like this:
XuiSendMessage (grid, #GetGridNumber, @kkkk, 0, 0, 0, 0, $TheKid, 0)
XuiSendMessage (kkkk, #SetClipGrid, kkkk, 0, 0, 0, 0, 0)
Where you know your graphics will not spill outside a grid, like in my math function and the circle in ademo.x and acircle.x - you don't need to clip. There is a slight overhead, but not much.

Q.C4- I have added a BMP image resource to my EXE, how do I use it from within XBasic?

You can add BMP or icon, or cursor resources to your standalone EXE and then access them from within your program. The following posts discuss how this is accomplished:

Q.C5-  How do I load JPG images?

XBasic can only load BMP format images. However, you can use just about any image format with XB by using an imaging library. There are several OpenSource imaging libraries available that can enable XBasic to use not only the JPEG format, but also, TIFF, PNG, PGM, TARGA and others.

FreeImage - Version 1.44 of this OpenSource imaging library works great with Win32 XBasic. It can load BMP, ICO, JPEG, KOALA, PCD, PCX, PNM, PNG, RAS, TARGA, and TIFF format files. It can save images in BMP, JPEG, PNG, PNM, and TIFF formats.  If you are interested in this version of the library, the author of this FAQ can send you the dll, lib, and dec files, and  an XB demo program.

Intel JPG Library - A Win32 library for only JPEG images. This library can save and load JPG images and has been tested with XBasic. If you are interested in the lib and dec files, email the author of this FAQ.
ftp://download.intel.com/design/perftool/perflibst/ijl/exes/ijl15.exe   (1851 kb)

DevIL - Developers Image Library (DevIL) is a cross-platform image library utilizing a simple syntax to load, save, convert, manipulate, filter and display a variety of images with ease, including JPEG and PNG. This library is currently untested with XB but looks very promising!






Section D - Text

Q.D1- Why do null bytes and backslash characters like \t and \n in text strings display as little blobs or images in grid text?

Many fonts have images for more than common or standard ASCII characters. ASCII values from 0x20 to 0x7E represent a reliable set of standard characters. But many fonts contain character images for most or all extended characters from 0x00 to 0x1F , and from 0x80 to 0xFF . The font images for these extended characters are not consistent between fonts. Nonetheless, the images for these characters can be displayed, and in certain circumstances they are.

In most circumstances, the vast majority of extended characters display whatever image the font contains for the specified character value. But a few of these extended characters like null=0x00 , tab=0x09 , return=0x0D , newline=0x0A have common meanings. For example, when you press an enter or newline key, you usually don't expect to insert the image the font contains for the newline character ( 0x0A ), you expect the text cursor to move to the next line without drawing a character.

The only reason characters like null , tab , and newline don't display images is that input functions check for these characters and execute alternate actions. But most output/drawing functions draw the font image for every character.

For example, XgrDrawText (grid, $$Black, @"A\tB\nC") draws five characters at the current drawpoint, which will usually look something like:

A Yð B Wð C or A § B © C

The character images the font contains for tab and newline are displayed. The tab does not cause blank space between the A and B , and the newline does not place the C on a separate line. When a program draws text and needs to interpret certain characters as something other than their font images, the program must perform multiple operations to draw the text. To draw the A § B © C example with tab and newline characters interpreted as space control characters takes three XgrDrawText() calls to draw the ABC characters, separated by two XgrSetDrawpoint() calls for tab and newline space.

Software that wants tab , newline , and possibly other extended characters to be interpreted as non-visible spacing commands or anything other than font images, must watch for these characters and take appropriate actions. A number of GuiDesigner grid types take alternate actions in response to extended characters. For example, XuiTextLine and XuiTextArea grids expand tab characters into variable width horizontal space to support alignment of text into columns. On the other hand, XuiTextLine and XuiTextArea display the font image for the other extended characters, including the newline characters. Each string in the string array assigned to the TextArray property of an XuiTextArea grid is displayed on a separate line. Any newline character in the TextArray is displayed as the 0x0A font image within the line and does not break the line.

Q.D2- How can I create neat columns of text with proportional fonts?

Two grid properties relate to tabs, namely TabWidth, and TabArray.  Unfortunately, many grid types ignore TabWidth and TabArray at this time, generally because they display the font 0x09 character image instead of space.

Common grid types that recognize TabWidth and/or TabArray include:


The following functions get and set TabArray and TabWidth .

XuiGetTabArray (grid, #GetTabArray, 0, 0, 0, 0, 0, @tab[])
XuiSetTabArray (grid, #SetTabArray, 0, 0, 0, 0, 0, @tab[])
XuiGetTabWidth (grid, #GetTabWidth, @width, 0, 0, 0, 0, 0)
XuiSetTabWidth (grid, #SetTabWidth, width, 0, 0, 0, 0, 0)

TabArray takes precedence over TabWidth .  If TabArray is not empty, its contents contain tab stop locations.  If a line of text has more tabs than TabArray has elements, TabWidth becomes active for the rest of the line.

TabArray must be an XLONG array.

TabArray and TabWidth specify pixel tab stops.

Q.D3- Why does SPACE$(1) create a different width space with different fonts?

SPACE$(n) creates a string containing n space characters. When strings are displayed by a GuiDesigner grid, the character width of every character, including the space character is determined by the font - by typeface, size, boldness, italic. In monospace typefaces, the width of the space character is the same as the width of all other characters in the same font. In proportional typefaces, the width of every character varies by design, so no characters, including the space character, is necessarily the same width as any other character. In addition, when proportionally spaced text is "full justified", meaning a straight left and right margin, the apparent width of space characters is varied to flush the margins.

Q.D4- Sometimes it's a little hard to find the text cursor in a large XuiTextArea?

The color of the text cursor in XuiTextArea and XuiTextLine grids can be globally changed with OptionTextCursor in the Main Window.  The text cursor is drawn in XOR drawing mode, so depending on the number of bits per pixel and whether a system is palette or direct map, the text cursor will not be the same color on all systems.  To change the color of the text cursor in a XuiTextArea or XuiTextLine grid in a design window, change its DullColor property with the AppearanceWindow.  Remember, the cursor color is not the DullColor itself, but the XOR of the DullColor and whatever the cursor is written over in the grid.  For example, a yellow text cursor might be created by setting DullColor to $$LightBlue.

Q.D5- How do I show special language characters (i.e. ANSI) in the internal text editor of Xbasic?

That's a simple matter of changing the font the editor uses. The font you're using is what Windows calls an OEM font - it uses the original IBM PC character set. You'll have to choose a font which has the characters you want in it. Go into the file \xb\xxx\font.xxx, comment out "OEM_FIXED_FONT" and choose another (say, ANSI_FIXED_FONT), or to only change in the editor there edit \xb\xxx\property.xxx, adding a line to set the font in any xuiTextArea of xb to your chosen font.

Most functions of XBASIC require characters be between 32 and 127. You could enter it as hexadecimal (\xE9, like above) or as octal (\351). There's a command to do the conversion called XstBinStringToBackString$, and of course a command which does the opposite as well. GUI Designer has to use this function to convert embedded quotes to \", and your characters were converted as well. It should work properly as a string with backslash codes, if not then you'll have to convert it back with the opposite function XstBackStringToBinString$..

Q.D6- How can I load a text file for viewing?

Well loading a text file needs two important things:

1 - a grid with a text area
2 - a statement to load the text.

Assuming you have one already designed and steady:

filename$ = "C:\\my documents\\word2txt.txt"
XstLoadStringArray(filename$, @text$[])
'[kid] should contain the TextAreaKidNumber of the grid you want to send the text to.
XuiSendMessage(grid, #SetTextArray, 0, 0, 0, 0, kid, @text$[])
XuiSendMessage(grid, #RedrawText, 0, 0, 0, 0, kid, 0)
There are also a few sample-files in the XBasic package, they all start with "a", try the examples: aedit.x and aeditors.x 

Q.D7- How do I send or retrieve text from the clipboard?

The functions that set or get text from the clipboard are in Xgr,:

XgrGetClipboard (clipboard, clipType, @text$, @image[])
XgrSetClipboard (clipboard, clipType, @text$, @image[])

There are 8 possible clipboards, where clipboard 0 is shared with windows , and 1 thru 7 are internal clipboards. The clipType 1 is for text and 2 is for BMP images. To set or get a BMP image from the clipboard, set the clipType to 2 and make sure you assign a type UBYTE to your image array.

To send text to the windows clipboard:

UBYTE image[]                                                     ' a null array
yourText$ = "Send this text to clipboard"                ' text to send
XgrSetClipboard (0, 1, @yourText$, @image[])




Section E - External DLLs

Q.E1- Can I use Dlls written in any language or do I have to use Dlls created in C/C++?

It doesn't matter in which language a .DLL is written; it's just a compiled, binary piece of code with a fixed 'interface'. As long as you (are able to) use that interface you can call any language from any language.

Q.E2- How can I read/write to the parallel or serial ports in XB?

There is not currently a built-in x-platform library for port communications. There are direct APIs that can be called from Win9x API functions. The following are the Win9x API functions used with communications resource (kernel32.dll). A communications resource is a physical or logical device that provides a single bidirectional, asynchronous data stream. Serial ports, parallel ports, fax machines, and modems are examples of communications resources. See kernel32.dec.


The file input and output (I/O) functions (CreateFile, CloseHandle, ReadFile, ReadFileEx, WriteFile, and WriteFileEx) provide the basic interface for opening and closing a communications resource handle and for performing read and write operations.

Otherwise, you a free to use any external I/O dll that provides you with the necessary port functions.

Port I/O resources:

Two 3rd party DLLs that will work with XBasic are:

WinIO.dll - Version 1.3 allows direct I/O port and physical memory access under Windows 9x, ME, NT and  2000 http://www.internals.com/

DLPortIO.DLL - Simple user mode DLL and NT kernel driver to allow direct hardware I/O access.
 http://www.sstnet.com/ - go to the Download page and download the "Windows 95/NT Port I/O Driver".

WinIO is simpler and smaller, but DLPortIO is faster.  The LIB file that comes with WinIO is not compatible with XBasic, so if you want to make a standalone EXE from your XBasic program you need a new LIB. See this post on the XBasic YahooGroups ML for instructions and .lib files http://groups.yahoo.com/group/xbasic/message/7240

 PC Interfaces and Controlling Devices - General information and links

Programming The Parallel Port In Visual Basic

Windows 95 I/O DLL [32-bit] - This tiny DLL allows port input and output under Windows 95. Note that there are limitations to this technique due to limitations in Win32, and that this DLL will not work under NT. The included documentation describes these limitations.

IBM-PC Parallel Printer Port Reading & Writing Data

Q.E3- How do I know if an external 3rd party DLL will work with XBasic?

If the library was created from a C program, then it will probably be compatible with XBasic. There is a utility program called dllGuide that can help you determine if any particular DLL is compatible.

dllGuide is a program to help in the process of preparing a third-party DLL for use by an XBasic program.

This program will work only in Windows, and only with XBasic 6.2.0 or above.
Download it from http://groups.yahoo.com/group/xbasic/files/members/dllGuide.zip
(size about 70kb)

Q.E4-Is somebody working on implementing the OpenGL libs?

 The OpenGL libraries are (c) (tm) by Silicon Graphics. They are not OpenSource, however, they can be used by gaming programmers freely...and are routinely included as part of the OS distribution for Windows, MacOS, and for LINUX. The OpenGL v1.1 library for Windows can be downloaded from


Yes, there is some activity on implementing OpenGL with XBasic. The necessary .dec and .lib files along with a test program can be found in the YahooGroups XBasic file vault http://groups.yahoo.com/group/xbasic/files/    Look for the file openglxb.zip .

 Some tutorials for using OpenGl can be found at NeHe Productions

 The best starting points for OpenGL is The OpenGl Web Site







Section F - Printing

Q.F1- How can a program send text to the printer?

There is a printer library for XB Windows called xpr.x which can be found in the XB YahooGroups file library:


The following line worked fine on WindowsNT 3.51:

a = SHELL ("READ C:\xb\test.txt") ' print file "test.txt"

You can also try printing directly to "lpt1" as follows:

 linesPerPage = 66
 XstLoadStringArray (fileName$, @text$[])

 prt$ = "LPT1"
 pfile = OPEN(prt$, $$WR)

 IF pfile > 0 THEN
  FOR i = 0 TO UBOUND(text$[])
'Print to console
   PRINT text$[i]
'Print to LPT1
   text$ = text$[i]
   IF text$ THEN
    PRINT[pfile], text$
   INC count
   IF count > linesPerPage THEN
    PRINT[pfile], CHR$(12)
    count = 0
  NEXT i

'Print form feed to eject last page
  PRINT[pfile], CHR$(12)

  error = CLOSE(pfile)










Section G - Mailing List

Q.G1- How do I unsubscribe to the Xbasic Mailing list?

In order to unsubscribe to the YahooGroups XBasic group, you can send an e-mail to the list with a subject of Unsubscribe:

Unsubscribe:  xbasic-unsubscribe@yahoogroups.com

Or you can sign into your YahooGroups account and go to your My Groups page on YahooGroups:


Then on the right side press the button Edit My Groups. Then under the Membership column dropbox for the xbasic group,  select unsubscribe. Then click on Save Changes button.

Q.G2- How do I get to My Groups in the YahooGroups mailing list?

When you sign in, the first page displayed is My Groups. You can get to My Groups by clicking the MyGroups link at the top of every page. 

Q.G3- How do I remove groups from the My Groups page at the YahooGroups site?

To remove a group from appearing on the My Group page, you must unsubscribe from that group. Simply choose "Unsubscribe" from the drop-down box to the right of the group name. Unsubscribe will remove the group from My Groups, and you will stop receiving messages from other members. 








Section H - Open Source

Q.H1- What are the guidelines for XBasic features and bug fixes?

There are 3 different 'releases' of XBasic:

- Stable releases. Stable releases all have an even sub-version number, e.g. 6.0.0, 6.0.8, 6.2.0, 6.4.0, 7.0, ... As a general rule only bugfixes will be added to this version(s), no new features. The latest available stable version is 6.0.8 (a.k.a. 6.008). Bugs in this version will be treated with a high priority. Bugfixes for the 6.0 version should be sent to max (please respect his conditions: i.e. "The ONLY way I can put any changes into the releases is if all the work has been done already and all I have to do is replace files & recompile."). Bugfixes for versions 6.2 (not yet available) and up should be sent to me.

- Unstable (or 'beta') releases: Unstable releases all have an odd sub-version number, e.g. 6.1.0, 6.1.1, 6.3.0, 7.1.0. In this versions new features are added. To be able to introduce fundamental changes without breaking many installations these releases should ONLY be used by beta-testers and/or experienced XBasic users. Bugs in this version will be treated with a lower priority. After a while a 'feature freeze' will be announced during which time only bugs will be fixed. After that the unstable version will become the next stable version. There is no unstable release version available yet. I hope to release version 6.1.0 within the next few weeks. All bugfixes for unstable releases should be sent to me.

- CVS snapshots: These are the current sources the XBasic developers are working on. These are only usefull for people working on new features. There is no need to sent in bugreports/fixes for this version because bugs in it are probably already known by the developers. For details on how to retrieve a CVS snapshot see the XBasic project page on SourceForge:


Q.H2- How do I make an XBasic build from the Xbasic source files?

The source for Xbasic v6.0022 can be downloaded from either the XBasic web site:


Select either the Windows or LINUX download page, then select the appropriate sourcecode zip. For windows, you can download the from this url:


Or, you can download the CVS (current version source) for XBasic at the XB SourceForge site. These are the current sources the XBasic developers are working on. These are only useful for people working on new features. For details on how to retrieve a CVS snapshot see the XBasic project page on SourceForge:


Note: The following directions apply only to XBasic v6.0022. The newest version of Xbasic v6.2+ requires the installation of a few Cygwin utility programs. To recompile v6.2+, see either README.linux or README.win32 files in the sourcecode files.

After you download the source file zip, unzip the files into your \xb directory. If you have the following files in your \xb directory, then move them to xb\lib xlib.s xstart.s xzzz.s You should only have to do this once.

To recompile XBasic, start a DOS window, Start >> Programs >> MS-DOS Prompt, get into your XBasic directory by typing the following at the prompt:

cd \xb

If you have previously compiled XBasic, then you should delete all of the previous .s and .o files so at the prompt, type:

del *.o
del *.s

and then build Xbasic by entering the following:

nmake -f xb.mak

If you want to rebuild the runtime XB dll (the xb.dll found in \xb\run) then type:

nmake -f xbrun.mak

Q.H3- If I want to help with the development of XBasic how(where) do I start?

The best way to start is to read / write in the XBasic mailinglist. There are a lot of tasks that can be done but you should check on the mailinglist, chances are somebody else is already working on something. 

Q.H4- Is XBasic open source?

Yes. All source of the XBasic compiler, development environment and runtime library is available. The source of the compiler and development environment is released under the GPL license and the source of the runtime library under the LGPL license. For more info on the GPL and LGPL licenses, see:


Q.H5- Why is the runtime library released under a different license from the compiler/development environment?

The GPL (amongst other things) obliges you to make your sourcecode available if you use any part of a GPL sourcecode. It means that if the runtime library was released under the GPL every program linked with it (that is, in fact, every program compiled by the XBasic compiler) would be subject to the GPL too. That would prohibit closed source programs to be written in XBasic and that's not what we want. So the runtime library is released under the LGPL.

Q.H6- What does open source mean?



(sorry, there is no short description and there are many different kinds of 'open source').

Q.H7- What is the procedure for reporting and fixing bugs?

1. Submit a bug report to the XBasic mailinglist ( xbasic@egroups.com ). Be brief, but as complete as possible. Preferably: add a short (the shortest possible) program that demonstrates the bug.

Do not immediately submit the bug in the bug-tracking system. Something that might seem a bug to you might not be a bug after all, or someone might already have a solution or workaround for it.

Do not submit the bug to any of the XBasic developers directly. These bug-reports will be ignored.

2. If there comes no solution from the mailinglist: add the bug to the bug-tracking system at https://sourceforge.net/project/?group_id=1657 . You (the first submitter of the bug) are responsible for this. If you don't submit the bug to the bug-tracking system changes are the bug will be forgotten. In general noone else will submit the bug to the bugtracking system.

3. If you have fixed a bug: please send the modifications you made to eddie@xbasic.org . You may as well send it to the mailing-list but don't send it to the mailinglist only, because I might miss it.

Patches should be send preferably as 'context diffs' (diff -U4) or the changed functions/subs. If that's not possible: you can send the complete sourcefile.

Patches should preferably be zipped or gzipped.

Q.H8- Do my XBasic programs have to released under LPGL?

Of course not. You can write anything you want with XBasic and release it under any terms or license as you want, be it open source, freeware, shareware, commercial ware, public domain, LPGL, etc.

The XBasic runtime library is covered by the LGPL, not the GPL. You can't charge for XBasic or for the library (other than a reasonable distribution cost), but your program (commercial, shareware, or otherwise) can use the runtime library without any change in the status of your program.

What you may not do is incorporate any part of the PDE or compiler into your program and then sell that - even as shareware. The PDE and compiler are the portions covered by the GPL, the runtime libraries are not.

Q.H9- What is Xbasic's SourceForge address?


Q.H10- What is SourceForge?

SourceForge is a website that donates resources (webspace, CVS repositories, mailinglists, ...) to Open Source projects. See:







Section I - Misc.

Q.I1- Messages sent with Windows API function SendMessage() disappear. Why?

Windows messages are not the same as GraphicsDesigner or GuiDesigner messages. They have different names, different values, and different arguments. They are utterly and totally incompatible. But that's not all by a long shot !!!!!!!!

Any name similarities between Windows and GraphicsDesigner are coincidence! A Windows window handle is not a GraphicsDesigner window or grid number. A Windows window procedure is not a GuiDesigner window or grid function.

Windows API function SendMessage() is totally incompatible with XgrSendMessage() or XuiSendMessage() . SendMessage() calls a Windows "window procedure". This window procedure is not the same as any GraphicsDesigner window function or grid function.

The Windows message queue is not the GraphicsDesigner message queue !!! These message queues are completely independent, separate, and different. GraphicsDesigner processes some of the messages from the Windows message queue, and discards the rest. Sometimes GraphicsDesigner adds one of its own messages to its own message queue as a result of a Windows message, but your program never, ever sees or deals with the Windows messages. Programs should never call SendMessage() to deal with a GraphicsDesigner window or grid.


Q.I2- How can I make Windows standard cut/grab/paste work in XuiTextArea?

Here is how cut/grab/paste works in Windows vs XuiTextArea and XuiTextLine :

Windows XuiTextArea operation performed
Ctrl+X Ctrl+X or Delete      cut selected text and put in clipboard
Ctrl+C Ctrl+C or Ctl+Insert  copy selected text and put in clipboard
Ctrl+V Ctrl+V or Insert      paste clipboard text at text cursor position

Applications can process the TextEvent callback message from text grids like XuiTextArea and XuiTextLine to implement new keystroke conventions.  Related messages recognized by these text grids include:

#GetTextCursor : #SetTextCursor
#TextDelete : #TextInsert : #TextReplace

Q.I3- What about differences between HelpGuiDesigner and the manuals?

The differences between the software and manuals sometimes occur. When you request help on one of the libraries from the Help menu in the main window, the PROLOG of the library is displayed in the HelpWindow. Since these .dec files contain the actual declaration of types, functions, and constants from the libraries, these files are correct - unless you didn't install a new release correctly.

Trust the .DEC files (and HelpLibraryName) over printed documentation.

Q.I4-Does XBasic have any encryption algorithms?

There are not any encryption functions built into XBasic, but there have been quite a few posts about various encryption
algorithms on the XBasic YahooGroups mailing list. They include encryption by TEA, 3-way, and ARC4 techniques. See the following posts:


Q.I5- Why doesn't XstSleep() sleep when my programs runs on Windows 3.1?

To implement XstSleep() , the standard library calls the Windows API Sleep().  Under WindowsNT, Sleep() works as expected.  Under Windows 3.1, however, Sleep() only sleeps if other processes are actively executing instructions.  To make XstSleep() sleep for the requested time, it calls Sleep() repeatedly until the actual elapsed time equals or exceeds the requested sleep.

Q.I6- Why do .mak files work with WindowsNT version 3.5 but not version 3.1?

Microsoft changed some of its development tools and procedures between version 3.1 and 3.5, and they will probably do so from time to time in the future. In anticipation of such changes, the PDE creates .mak files from template files \xb\xxx\xapp.xxx and \xb\xxx\xdll.xxx .<

When you compile a file with R un A ssembly or R un L ibrary , the PDE reads in xapp.xxx or xdll.xxx , changes the line that defines the name of the program or library and saves the result as prog .mak , where prog is the name of your program.

Since xapp.xxx and xdll.xxx are simple text files, you can edit them in accordance with the requirements of new and improved development tools. Subsequent .mak files generated by the PDE will then work properly. Be sure to keep a copy of the original xapp.xxx and xdll.xxx files.

Q.I7- Why do filenames that work on the Windows version sometimes don't work on UNIX?

The path separator character is a backslash character "\" on Windows and a foreslash aka divide character "/" on UNIX.  So "\\xb\\xxx\\entry.xxx" and "/xb/xxx/entry.xxx" are valid filenames for Windows and UNIX respectively.  Remember, a single backslash character is represented by two backslashes in literal strings.

To make source programs as portable as possible, standard library functions and the OPEN() intrinsic accept filenames with either separator.   These functions call XstPathString$() to convert every improper separator to the proper separator before they continue.

To make sure you avoid potential filename problems, however, substitute the $$PathSlash$ constant defined in the standard library for every occurrence of the literal separator character.  Alternately, call XstPathString$() to convert filename strings into the correct format.  This function takes either form and returns a valid path string for the current system.  XstPathString$() also expands environment variables.   "$HOME/research/lens0034.dat" and "$(HOME)\\research\\lens0034.dat" are thus acceptable arguments - $HOME or $(HOME) are replaced by the HOME environment variable string.

  Not Portable:    "\\xb\\circle.x" ...or... "/xb/circle.x"
 Portable:        $$PathSlash$ + "xb" + $$PathSlash$ + "circle.x"
 Portable:        "$(XBDIR)" + $$PathSlash$ + "circle.x"

 Not Portable:    "\\xb\\circle.x" ...or... "/xb/circle.x"
 Portable:        path$ = XstPathString$ ("$XBDIR/circle.x")
 Portable:        path$ = XstPathString$ ("\\xb\\circle.x")
 Portable:        path$ = XstPathString$ ("/xb/circle.x")

Functions that return a path or file name return the path separator character appropriate to the system the program is running on.  Programs that search for path separator characters in path or file name strings should therefore search for $$PathSlash$ instead of "\\" or "/" .

 Not Portable:    slash = INSTR (path$, "\\")
 Not Portable:    slash = INSTR (path$, "/")
 Portable:      slash = INSTR (path$, $$PathSlash$)

A shared constant is also defined in the standard library for the binary form of the path separator.

 Windows:      $$PathSlash = '\\'
 UNIX:       $$PathSlash = '/'

Q.I8- Why does windows tell me "The C:\xb\*.hlp file is not a Windows Help file, or the file is corrupted."

The XB help files have an *.hlp extension but they are NOT windows compiled helpfiles. Rather, they are text files with a .hlp extension. If you want to view the XB .hlp files outside of XB, just open them in a standard text program like NotePad or WordPad.

Q.I9- The runtime DLL for XBasic is too large!  How can I reduce its size?

You could use a PE compression program like UPX (the Ultimate Packer for Executables)
to compress the xb.dll file to a more reasonable size. See http://upx.sourceforge.net/

Q.I10- Where can I find additional documentation, tutorials, and/or example programs?

We have set up an YahooGroups XB vault for XB files and documents which can be found at:


Q.I11- The FAQ says that XBasic is written in XBasic. But in which language was the first version of XBasic written?

The first real version of XBasic was written in XBasic.

But I'll try to answer the question you're trying to ask. The first XBasic was developed in 1987-1988 and ran on a Motorola 88100 RISC CPU and UNIX.

Some core code was written in 88100 assembly language. That code is in xlib.s and later grew larger.

A stripped down semi-compiler written in QuickBasic that takes micro-XBasic source-code and emits 88100 assembly.

Once that compiler emits 88100 assembly that works, hand-modify the XBasic compiler from QuickBasic source into XBasic source.

Compile the XBasic version with the QuickBasic version to produce 88100 assembly that IS the XBasic compiler. From then on, everything further is pure XBasic.

Note that this first version of XBasic compiler written in QuickBasic was VERY, VERY minamalist and supported only those language features absolutely necessary to implement a compiler. I shudder to even CALL it an XBasic compiler, the language was so stripped down. For example, this initial compiler did not support structures (composite variables). Unfortunately, the compiler was never re-written with structures and many other later-added XBasic capabilities, which explains why the compiler is somewhat "a mess". If you look at the partial complete qbtoxb.x code, you'll see how much cleaner real XBasic is.

Q.I12- How can I make my xbasic programs run faster?

Get a faster computer  :-)

Seriously though , that depends on why the programmes are running slowly. It could be due to the OS , or the compiler or the algorithm or sloppy coding , etc. etc.

One easy way to speed up any programme , not just XB , is to tweak the operating system parameters. Windows allows you to change the time-slice given to foreground/background processes , thus if you run your programme in the background , you could set Windows to favour background processes etc. Run time also depends on the number of  windows/processes/applications you have running. If you close down all unnecessary processes , run the programme in the foreground and favour foreground processes , I guess this might improve run time by 5% to 10%.

The next thing to try is the XB compiler which runs in two modes - standalone and PDE. If you run your code as standalone , it will execute much faster than it does in the PDE , because the PDE version is frequently checking for user input which can result in a 50% - 100% performance penalty.

The next thing to check is the algorithm you are using. For example, if you are sorting data , it is OK to use ripple sort or bubble sort for small data sizes , but if you are sorting a long list ( say , more than 100 items ) , you should change the sorting algorithm to quicksort.

These three ideas will give you the biggest , easiest performance improvements , but if you still want more speed , there are a host of tricks/methods to try.

[1] Profiling. Time various parts of your code to see which sections are consuming the most time. The famous 80/20 rule usually applies here - 20% of the code takes up 80% of the CPU time , so it is not necessary to speed up all of your programme , just to concentrate on the 20% which is chewing up the most cycles. Find a bottleneck , say a nested loop , and try to find ways to improve it or even eliminate it if possible.

[2] Write clean , simple code. This is often faster than convoluted code anyway , and it is easier to see how to improve things if the code is easy to read. For example ,

IF x THEN x=0

can be simply rewritten as x=0 .

[3] Know the approximate cost of various statements. For example , function calls are much more expensive than subroutine calls. Consider the following test :

PROGRAM "test"
IMPORT "xst"

FUNCTION  Entry ()
n = 100000000

FOR i = 1 TO n
  GOSUB Test1
PRINT "Sub      takes " ; (b-a)/DOUBLE(n)*1d6 ; " nanoseconds."

FOR i = 1 TO n
PRINT "Function takes " ; (b-a)/DOUBLE(n)*1d6 ; " nanoseconds."

SUB Test1
FUNCTION  Test2 ()

When I compile and run this , it prints :

Sub      takes   9.92 nanoseconds.
Function takes  23.33 nanoseconds.

so if you have a subprogramme that does not take parameters , consider coding it as a subroutine rather than a function. ( Yes , I know I should have subtracted the time taken by an empty loop , but that was too much work [:-)] )

A corollary to this is that you can trade time for space - instead of a loop like this :

FOR i = 0 TO 4
  Jiggle( @x[] , i)

You write
  Jiggle( @x[] , 0)
 Jiggle( @x[] , 1)
 Jiggle( @x[] , 2)
 Jiggle( @x[] , 3)
 Jiggle( @x[] , 4)

Then you can do inlining , which is explicitly including the source code of  Jiggle() 5 times , instead of writing it once as a function.

Here is another example :

FUNCTION  Entry ()
XLONG i ,a ,b

n = 100000000

FOR i = 0 TO n
' something
PRINT (b-a)

IF i THEN GOTO start
PRINT (b-a)



This prints

so the loop overhead in the second case is much less. It is also much less readable , so you have to decide if the small gain in speed is worth the loss of readability.

[4] Strength reduction. This is the replacement of an expression by a different expression that yields the same value but is cheaper to compute.
An example :

x = w MOD 8
y = POW(x , 2)
z = y * 33
FOR i = 0 TO 99
  h = 14 * i
  s = s + h

could be replaced with  :

x = w & 7
y = x * x
z = (y << 5) + y
FOR i = 0 TO 99
  s = s + h
  h = h + 14

[5] Loop-invariant expressions :

FOR i = 0 TO 99
  s = s + i + n*n*n

could be written

FOR i = 0 TO 99
  s = s + i + m

[6] Straight line coding. IF's , SELECT's and GOTO's were fine on older chips like the 386 , but modern CPUs with long instruction pipelines and multiple ALUs are much happier with long lists of unconditional code. A man's got to IF when a man's got to IF , but try to keep the idea of straight line coding in mind when programming.









Section J - Installation

Q.J1- What is the best procedure to install a newer version of XBASIC?

Rename \xb to \xbold (/xbasic to /xbasicold) before installing a new release of XBasic is best. That way if you modified any of the sample programs or anything else (like /xb/xxx/property.xxx) you can put any changes you want to keep into the files in the new release. But make sure you install per the directions - you should not create a new \xb directory manually, you should extract into the \ root directory with "recreate subdirectories" selected, which automatically creates all XBasic directories properly, including "/xb" "/xb/app" "/xb/xxx" and any others required by XBasic.

Q.J2- Why can't Xbasic find the *.dec files?

This usually happens when you install XBasic wrong.
You can install XBasic on any hard-drive (c: d: e: etc), but you must install into the \ root directory and select the "recreate subdirectories" option.
For v6.0022, see if you have the following directories (the c: can be d: or e:)
For v6.20, the .dec files are installed in /xbasic/include.

If not, you installed improperly and the only solution is to remove everything you installed already and install XBasic again.
Assuming you didn't delete the file you downloaded, you don't need to download it again.









Section K - GUI Programming

Q.K1- How can a create a simple "Hello World" GUI Window?

XBasic has several built-in grid functions that create a window with just one function. They are called GuiDesigner Convenience Functions. Convenience functions are one line functions that enable one to create very simple GUI windows. The simplest one is shown below:

FUNCTION  Entry ( )
  message$ = "[Greetings]\nHello world!"

In the above example, message$ has two parts. The first part [Greetings] is inside brackets. This sets the window titlebar to "Greetings". This is followed by \n. Newline characters ("\n") in the message string break the message into multiple lines. The second part, "Hello world!" is the message displayed in the center of the window.

So XuiMessage (message$) is basically the GUI equivalent of PRINT "Hello world!".

Q.K2- How do I use the GUI Designer Toolkit to layout my GUI windows?

Run the PDE, and select file|new or the New button, and choose gui program. The skeleton of a standard GUI program appears. Now click the Toolkit button (the one with a window and a hammer on it). A window appears labeled Toolkit.

From the window menu, select New. A window will appear. In the text box of the Toolkit window, type a name for your new
window. Note, the name must be valid as a function name - start with a letter and contain only letters, numbers and underline characters (no spaces). That will be the name assigned to your window's function later. It will also be set as your window's title, but you can change that later. Resize your window and put it where you want it to appear.

Now in the Toolkit, click on the button for a type of grid to put in your window. A drag handle (an outlined box) will appear in your window, drag it and resize it to the size and location you want.

To change the properties of any tool in your window, select the tool, then from the Toolkit window's grid menu, select Appearance. You can also just double-click the tool in your new window. Now another window will appear next to
the Toolkit window, where you can set all the major properties of your  window - colors, border, text, hint, help text or file, limits on numeric values, etc.

You can also name individual grids for your own convenience, they will start off with a standardized name like PushButton1379 but it may be easier for you to write the code for the actions if you give them descriptive names (again no spaces or punctuation).

Among the grids you'll see in the toolkit are standard text areas and text boxes, three kinds of push buttons, radio buttons, drop down lists, scrollable lists, even a standard "combo box". Add as many grids (or tools, or widgets) as you like.

You can even insert bitmap images into your grids if you wish - select the "image" property button in from the Appearance window. Then select a .bmp image file from the file selection window. You can add bmp images to label grids, push buttons and a few other grids.

If a grid has "kids", like the scroll bars of a text area or list, you can change them too by selecting them in the kids menu of the Appearance window.

Some grids have multiple "styles", like a push button with no border until the mouse hovers over it, or the size and how the arrow buttons are drawn on a scroll bar.

After you've designed your window's appearance and contents, go to the Toolkit's window menu and select "To function". Two additional functions are added to your program, one with the name you typed earlier and one with that name plus "Code". If you later decide you'd like to change the appearance of you window, you can display the Toolkit window and select window|from function rather than window|new. Just make sure that you have the window's function or callback function "...Code ( )" displayed in the PDE.

Then comes the hard part, coding how the window should act. Most of that will be done in the "...Code ( )" function, there will be sections there for if a button, menu item or whatever is selected. There will also be a section labeled "TextEvent", that's if you have a text line or text area and you want to handle special key events.

A window call "Test" was created with a menu grid, a text area grid, and two push buttons. The resulting callback function for Test ( )  is called TestCode ( ) and is shown below:

FUNCTION  TestCode (grid, message, v0, v1, v2, v3, kid, r1)
 $Test              =   0  ' kid   0 grid type = Test
 $XuiMenu728        =   1  ' kid   1 grid type = XuiMenu
 $XuiTextArea731    =   2  ' kid   2 grid type = XuiTextArea
 $XuiPushButton735  =   3  ' kid   3 grid type = XuiPushButton
 $XuiPushButton736  =   4  ' kid   4 grid type = XuiPushButton
 $UpperKid          =   4  ' kid maximum
 XuiReportMessage (grid, message, v0, v1, v2, v3, kid, r1) 'comment out to hide message window
 IF (message == #Callback) THEN message = r1
 SELECT CASE message
  CASE #Selection  : GOSUB Selection    ' most common callback message
'  CASE #TextEvent  : GOSUB TextEvent   ' KeyDown in TextArea or TextLine
'  CASE #CloseWindow : QUIT (0)         ' close main window and no cleanup needed
  CASE #CloseWindow : XuiSendMessage (grid, #HideWindow, 0, 0, 0, 0, 0, 0)
' *****  Selection  *****
SUB Selection
  CASE $Test              :
  CASE $XuiMenu728        :
  CASE $XuiTextArea731    :
  CASE $XuiPushButton735  :
  CASE $XuiPushButton736  :

One detail - for debugging purposes the Toolkit automatically adds a call to XuiReportMessage to your "Code" callback function, so you'll be able to see what message was actually sent at the same time as seeing what happened in your window. When you're done, you'll want to either remove this line or comment it out, otherwise any time the user clicks a button or enters text you'll get the Report window displayed saying what message was sent.

Q.K3-Can I use colors not shown in the Appearance window for my grids/tools/widgets?

XBasic has 125 predefined colors (numbered 0 to 124) that can be selected in the Appearance window. Many of these colors have names like $$Black for 0.  The standard color names can be seen in the help file for xgr, in the PDE select from the menu help|graphics library.

You can however use 24-bit color anywhere you want, but the Appearance window only shows the standard 125 colors for you to choose from. If you want to select a 24-bit color, you'll have to enter it into the #SetColor, #SetColorExtra, #SetFocusColor or #SetFocusColorExtra message yourself in the code for your window function.

XuiSendMessage ( g, #SetColor, $$BrightViolet, 56, 87, 122, 0, 0)

In hexadecimal (the easiest way), a 24-bit color is 0xRRGGBB00, where RR is two hex digits for the red component, GG is green, and BB is blue. The zeroes at the end are required so that XBasic knows this isn't one of its predefined colors, and 0x at the start identifies this as a hexadecimal number. Each rgb color component can range from 0 to 255, or in hex, 0x00 to 0xFF.

XuiSendMessage ( g, #SetColor, 0xA545F500, $$White, $$Black, 0x00F86900, 0, 0)

Or, If you don't like hexadecimal, then you can convert from hex to integer using

color = red<<24 +green <<16 + blue<<8
where  "<<" is an unsigned shift left, the same as multiplying by 2 to that power except faster.

Q.K4- How can change the window title?

The window title can be changed - but not in the GUI Designer toolkit. The only attribute of a window the GUI Designer tookit displays is the window name, which serves as a valid FUNCTION name. Thus, it cannot have spaces or special characters.

If this is a GUI window, just go ahead and design your window and select Window|ToFunction. After you've designed your window, look at the generated function  CreateWindows ( ) . At the top of that function you'll find a message that says #CreateWindow,  and has the name of your window as the first grid argument. Below that you can add a #SetWindowTitle message.

FUNCTION  CreateWindows ()
 Test           (@Test, #CreateWindow, 0, 0, 0, 0, 0, 0)
 XuiSendMessage ( Test, #SetWindowTitle, 0, 0, 0, 0, 0, "My Window_Title~.")
 XuiSendMessage ( Test, #SetCallback, Test, &TestCode(), -1, -1, -1, 0)
 XuiSendMessage ( Test, #Initialize, 0, 0, 0, 0, 0, 0)
 XuiSendMessage ( Test, #DisplayWindow, 0, 0, 0, 0, 0, 0)
 XuiSendMessage ( Test, #SetGridProperties, -1, 0, 0, 0, 0, 0)
' #Test = Test

In the above example, the window title is set to "My Window_ Title ~." .

Q.K5- How can I create a window that is full-screen without any border or titlebar?

You can achieve the appearance you want quite easily and conveniently. You have two main requirements:

#1. Your window must have no border around the edges and no title-bar at the top.

#2. Your window must be the size of the display.

You can create windows like this very easily in XBasic as follows. If you apply these very minor changes to the "acircle.x" demo program that comes with XBasic, you'll see the proof.

#1. XBasic programs typically create all their windows in CreateWindows() when they start. For example, the "acircle.x" demo program creates and displays its window with the following lines in CreateWindows():

Circle (@Circle, #CreateWindow, 0, 0, 0, 0, 0, 0)
Circle ( Circle, #SetCallback, Circle, &CircleCode(), -1, -1, -1, -1)
XuiSendMessage (Circle, #DisplayWindow, 0, 0, 0, 0, 0, 0)
The next-to-last argument in the first line is the "window-type" argument that tells the GuiDesigner routines what you want the window to look like. For convenience, 0 = default. If you select "Help GraphicsLibrary" in the XBasic main window, then go down a ways to find the "window type" constants, you'll see you can select the kind of window you want, including $$WindowTypeNoFrame.
So you can accomplish objective #1 by changing the first line to:
Circle (@Circle, #CreateWindow, 0, 0, 0, 0, $$WindowTypeNoFrame, 0)
#2. To make a window fill the whole display is easy too - just send a #MaximizeWindow message when the window is visible. So just add the following line after the three above.
XuiSendMessage (Circle, #MaximizeWindow, 0, 0, 0, 0, 0, 0)
So there you have it - a window with no borders that fills the display screen. But the window does not "own" the display, so if you move the mouse cursor to the bottom of the display screen, Windows will raise the "start-bar" or whatever they call it - and you can select other windows to display above it. Of course you can also select your full-screen window there too, in which case it fills the display screen again.

Q.K6- Why doesn't the little "X" box/button that usually closes a window or program and located in the far upper right hand corner close the selected window?

If you are creating a GuiDesigner program using the toolkit, then the code generated from the toolkit will create Main() and MainCode() functions. IF you take a look at the MainCode() function, you will see some stuff that looks like this:
XuiReportMessage (grid, message, v0, v1, v2, v3, kid, r1)
IF (message = #Callback) THEN message = r1
  CASE #Selection         : GOSUB Selection     ' most common callback message
' CASE #TextEvent         : GOSUB TextEvent     ' KeyDown in TextArea or TextLine
' CASE #CloseWindow       : QUIT (0)            ' close main window and no cleanup needed
  CASE #CloseWindow       : XuiSendMessage (grid, #HideWindow, 0, 0, 0, 0, 0, 0)
This SELECT CASE processes all of the messages generated by the grids you have created and which are shown in your Main() function. You can see all of these messages in the XuiReportMessage window that pops up when you run a program. You can show or hide this function by commenting out the line above -

XuiReportMessage (grid, message, v0, v1, v2, v3, kid, r1).

So, any window messages that relate to maximizing, minimizing, or closing the main window are reported as messages such as #CloseWindow.  If you enable the line CASE #CloseWindow, the the program will quit when the window close button is pressed  (in QUIT(0) ,  0 refers to the main window). If you send the message #HideWindow on receiving the #CloseWindow message, then you can open it again at a later time with a #DisplayWindow message.

If the above #CloseWindow messages are not shown in your code (earlier versions of XB), then you must add them manually.

Q.K7- Why do my programs always display the ReportMessage window?

When you convert a design window into a grid function and callback function, GuiDesigner puts

XuiReportMessage (grid, message, v0, v1, v2, v3, kid, r1)

at the top of the window callback function.  Whenever the callback function receives a message, the ReportMessage window appears and displays the message arguments. Remove or disable this line to stop this window from appearing.

Q.K8- I see taskbar icons when hint-strings pop up, why and how can I remove them?

The reason why you see taskbar-icons for hintstrings is because the original author Max, never noticed them due to the fact he always had his "taskbar" hidden. You can update to the latest version of XBasic.
This problem has been solved since v6.0012.

Q.K9- Can I remove taskbar icons for every window I want?

You can hide the taskbar icon only for frameless windows by OR'ing it with "$$WindowTypeNoIcon":

Test (@Test, #CreateWindow, 0, 0, 0, 0, $$WindowTypeNoFrame OR $$WindowTypeNoIcon, 0)

 By hiding it from the taskbar does however not mean that it will be removed from the taskmanager list!

Q.K10- How can I allow the user to use the tab key to move between user textline grids?

The default grid-shift method is inherited from the unix/linux-world: ALT-Left arrow key or ALT- right arrow-key. That's why tab does not shift to the next grid. 

Q.K11- How is text and text cursor position controlled in XuiTextArea grids?

Send a #SetTextCursor message to XuiTextArea grids to position the text cursor within the body of text and to position the text within the grid, as follows:

 XuiSendMessage (grid, #SetTextCursor, v0, v1, v2, v3, kid, 0)

   v0 = cursorPos = set text cursor to this character # on the cursor line.
   v1 = cursorLine = set text cursor to this line #.
   v2 = leftIndent = horizontal pixel # to start displaying line.
   v3 = topLine = top line of displayed text.

  any argument can be -1 to say don't change current value.

Whenever one or more of these values is changed with #SetTextCursor, a check is performed to make sure the values are reasonable and consistent.  So it is not possible to place the text cursor outside the text region, set the top line such that the cursor is not in the displayed portion of text, etc.  Reasonable values are assigned.

Incidently, #SetTextCursor is also recognized by:

XuiDropBox - v0 sets cursorPos in the XuiTextLine kid
v1 sets cursorLine in the XuiPullDown kid

XuiDropButton - v1 sets cursorLine in the XuiPullDown kid

XuiListBox - v0 sets cursorPos in the XuiTextLine kid
v1 sets cursorLine in the XuiList kid

XuiListButton - v1 sets cursorLine in the XuiList kid

In XuiList and XuiPullDown grids, cursorLine means the selected line. Send #SetTextCursor to the indicated grids, not directly to the kids.










Section L - File & Database Processing

Q.L1- How does one randomly access fixed-length records

With just a few features, XBasic provides core support for random access of fixed-length records. The most important features are probably the READ and WRITE statements, and the POF() and SEEK() intrinsics. The following illustrates how to random access fixed-length records with these features.

The following illustrates a fictional fixed-length data-type. This type-declaration must be in the PROLOG.

 XLONG     .id
 XLONG     .ssn
 USHORT    .birthYear
 UBYTE     .birthMonth
 UBYTE     .birthDay
 USHORT    .mmHeight
 USHORT    .kgWeight
 STRING*16 .nameFirst
 STRING*16 .nameMiddle
 STRING*16 .nameFamily

Assume you have a function that needs to random access information on a particular human, the variable "id" is the human-number AKA record-number, variable "file" is the filenumber of the already open file, and variable "data" is type HUMAN.

FUNCTION UpdateMiddleName (id)
HUMAN data                         ' declare variable "data" to be type HUMAN

 file = OPEN("humandata.dat", $$RW)' open the file
 offset = id * size(HUMAN)         ' offset to desired record
 SEEK (file, offset)               ' move file pointer to record
 READ [file], data                 ' read fixed-length record

 IF (id != data.id) THEN PRINT "disaster - wrong record" : RETURN

 a$ = TRIM$(data.nameMiddle)
  data.nameMiddle = "[none]"        ' replace empty string with "[none]"
  SEEK (file, offset)               ' move file offset back to same entry
  WRITE [file], data                ' update record
 CLOSE(file)                        ' close the file










Section M - Multimedia & Game Support

Q.M1- How can I play a WAVE .wav sound file? 

Playing mulitmedia files requires system dependent libraries. XBasic does not currently support cross-platform support for multimedia files for sound. On Win9x systems, you can use various Win32 libraries to play wave files or to make a standard BEEP notification sound. Some sound related functions include Beep(), MessageBeep(), and  sndPlaySoundA() . More multimedi functions are available in the winmm.dll.

 IMPORT "xst"   ' Standard library : required by most programs
'########## NOTE : IMPORT these dlls #############
 IMPORT "user32"
 IMPORT "kernel32"
 IMPORT "winmm"



'play Beep (frequency, duration) from kernel32.dll
'Windows95/98 ignore frequency and duration arguments.

 Beep (10, 100)
 XstSleep (2000)

'play MessageBeep (type) from user32.dll
'from the Win32 Ref guide, these are the
'sound type constants available:

' Sound Type Constant   Sound
' ==============================================
' $$MB_ICONASTERISK     SystemAsterisk    - 0x40
' $$MB_ICONEXCLAMATION  SystemExclamation - 0x30
' $$MB_ICONQUESTION     SystemQuestion    - 0x20
' $$MB_ICONHAND         SystemHand        - 0x10
' $$MB_OK               SystemDefault     - 0x0

 MessageBeep ($$MB_ICONHAND)
 XstSleep (1500)
 MessageBeep ($$MB_OK)
 XstSleep (1000)

'assign wav file and path to sound$

' Note: XBasic understands "/" as directory separators,
' but if you prefer "\" characters, you must double up,
' as in "c:\\windows\\media\\tada.wav". If this wave
' file is not available, then select another one of your
' choice.

 sound$ = "c:/windows/media/tada.wav"

'call sndPlaySoundA (wavAddr, flags) from winmm.dll

'note that you must use the & address prefix on sound$
'to send the address of the string, not the string itself

'there several flag constants that can be used - see winmm.dec
'$$SND_SYNC    default flag - synchronous play
'$$SND_ASYNC   asynchronous play
'$$SND_LOOP    repeat the sound until another sound event occurs
'$$SND_NOSTOP  wait for current sound to finish before playing

'play three tada sounds
 result = sndPlaySoundA (&sound$, sync)
 result = sndPlaySoundA (&sound$, sync)
 result = sndPlaySoundA (&sound$, sync)


Q.M2- How can I access the Game Port (JoyStick) using xbasic

There is not currently a x-platform multimedia library for XB for sound,  joystick, video or highspeed graphics (DirectX or OpenGL).

If you are using Win32s, then you could try the winmm.dll multimedia library functions for the joystick. For more information, see:


However, you would also need to implement the windows joystick messages in order to handle joystick button events.
The joystick functions in winmm.dll are:

EXTERNAL FUNCTION joyGetDevCapsA (id, lpCaps, uSize)
EXTERNAL FUNCTION joyGetThreshold (id, lpuThreshold)
EXTERNAL FUNCTION joyReleaseCapture (id)
EXTERNAL FUNCTION joySetCapture (hwnd, uID, uPeriod, bChanged)
EXTERNAL FUNCTION joySetThreshold (id, uThreshold)

Be warned that there are a lot of errors in the constants section of winmm.dll since XB cannot do any calculations for determining shared constants. If someone has the time, this needs to be corrected.

There's a M$ sample program for VB here: 
(get joystick.exe - self extracting archive)

One could also download the Win9x SDK MMedia.hlp file.

Also, take a look at these previous posts on joystick functions which might be useful: http://groups.yahoo.com/group/xbasic/message/4738

Q.M3- How do I play MIDI sound files?

You can play MIDI sound file by using Win32 API  multimedia functions contained in winmm.dll.

Follow these posts for some examples programs and discussion:

Q.M4- Is there a gaming multimedia library for XBasic?

One possible gaming library is Simple DirectMedia Layer or SDL.

There was a short discussion about SDL wrt XBasic.  http://www.egroups.com/message/xbasic/818

From the SDL website: "This library is designed to make it easy to write games that run on Linux, Win32 and BeOS using the various native high-performance media interfaces, (for video, audio, events, etc) and presenting a single source-code level API to your application. This is a fairly low level API, but using this, completely portable applications can be written with a great deal of flexibility. The library is loaded as a dynamically linked library on its native platform, and is currently compiled natively for Linux, compiled for Win32 using a Linux hosted GCC cross-compilation environment, and compiled using the EGCS C++ compiler under BeOS." An introduction to SDL can be found online at: http://www.libsdl.org/intro/