How far is Q(uick)Basic / Visual Basic compatible
to XBasic?
To be honest, there are a
few keywords that match to Q(uick)Basic / Visual Basic but if it comes to communicating
with hardware and involving graphic statement calls there are quite some differences.
XBasic has a better approach towards Visual Basic than towards Q(uick)Basic
so let me teach you to learn one particular and important thing about
XBasic:
XBasic is oriented on a Windows environment, this can be Win32(Win'95/'98/2000),
XWindows (Linux, Unix), or any other windows that has an emulation environment
of one of the previous two named.
You notice I don't mention DOS or Unix Console.
That's correct, you can forget about that. XBasic has no primary DOS or Linux
console support. Even though you need the console mode to compile your work
in, it has no primary support to display particular graphics in this Linux console-box
or DOS-box under windows.
Unless you find libraries that can do certain things for you in this console
mode, you have to rely on the implemented console feature that comes XBasic
itself.

Xbasic implemented Console-mode
You can do anything in that console window, even graphics but for that you also
need to know some delicate features which I will not treat here but in the right
spot.
How far can I translate Q(uick)Basic / Visual Basic to XBasic?
I will start with an advise here:
If you truly want to convert your QB/VB project, make sure the code really is
valuable to convert and I tell you this because:
For those who are not convinced to learn the XBasic basics and rewrite from
scratch here is the info:
There are a couple of QB2XB projects also online like Max Reason's QB2XB project
which is also added to the XBasic examples that come with the main XBasic zipfile
you downloaded and a here's another partly
developed project.
Both projects are unfinished but supply a small begin that you can build up.
Max's project will convert a lot of statements from QB to XB but not all and
the other one only neats up the code.
There are besides those few projects also some steps supplied how to translate
your QB code to XB code:
XBasic
program development environment
- PDE -
QuickBasic to XBasic
copyright 1988-1999
June 1, 1999
introduction
The following notes were written by an XBasic programmer
who converted a 10,000 line
QuickBASIC 4.5 console-mode program to XBasic in two
long days of intense work. He added
and integrated a GUI in another day with the interactive
GuiDesigner built into the XBasic
program development environment.
Also see the work-in-progress QuickBasic keywords
to XBasic equivalents table in the XBasic
web-site.
general comments
I made most changes with a "monitored"
wildcard replace, which means you view and confirm
each replace. I burned myself a few times with
unmonitored wildcard replaces. With XBasic,
you can do monitored find and replace quickly with the
F11 / F12 function keys.
Load your QuickBasic program as a text file, otherwise
XBasic will not be able to figure out
what's up. After all, XBasic understands
XBasic syntax, not QuickBASIC.
Save a new copy of the file you're converting every
5 minutes as a separate file. You should
end up with a series of files like prog0000.x, prog0001.x,
prog0002.x, ... prog0025.x when you
finish. That way if you royally screw up
some step you can go back to the most recent good
working copy. Doing this saved me hours of work
and possibly suicide.
Type .h in the upper text area to get a list of shortcut
"dot commands" including find/replace
examples. Entering dot commands in the upper
text area is often much faster than working
pulldown menus.
By the way, most of the find and replace work goes
much faster and smoother if you set the find
and replace to be case sensitive, which you only need
to do once. Just select "Edit" then "Find"
and depress the toggle button labeled "Case Sensitive".
Hold the shift key down to do reverse
find/replace with F11/F12.
Remember, the XBasic programming language is case
sensitive. So FOR is a keyword, and
for, For, foR, and FoR are all different variables.
If you don't find an equivalent for something fundamental,
check the XBasic standard function
library. Check the "\xb\doc\library.doc"
manual, or better yet, select "Help" +
"StandardLibrary" from the menu bar in the
main XBasic window. For graphics, read the whole
"\xb\doc\graphics.doc" manual first.
step by step process
step 1 : Replace all occurrences of SUB with
FUNCTION. You need to monitor this process,
otherwise you'll accidentally change all occurrences
of GOSUB into GOFUNCTION. A
QuickBasic function that does not return an argument
is called a SUB, while every XBasic
function is called a FUNCTION, whether they return an
argument or not. This frees up the
SUB keyword for "subroutines" within functions.
step 2 : Go through your entire program and
find all subroutines, which means every location
your program GOSUBs to. Find the beginning and
end of each subroutine and do the
following:
Put a SUB keyword before the subroutine
name and remove the trailing colon from the
name. For example, if the beginning
of a subroutine is a line dothis:, change the line to SUB
dothis.
Replace the RETURN keyword at the end of the subroutine with END SUB.
Find all RETURN keywords within the subroutine and change them to EXIT SUB.
step 3 : Make sure no RETURN keywords remain in
your program.
step 4 : In every context, XBasic functions
require parentheses after the function name, even
if the function takes no arguments. Find every
occurrence of functions that take no arguments
and add () after the function name. For example,
change funcname to funcname().
step 5 : As I recall, in QuickBASIC you return
a value from a function by assigning a value to a
variable with the same name as the function. In
XBasic, you simply write RETURN (value). In
XBasic, a function named a() can contain a variable
named a that works just like every other
variable in the function and has nothing whatever to
do with returning values from the function.
step 6 : XBasic array names are always followed
by square brackets, as in array[n] vs
array(n). One reason XBasic programs are easier
to read is because you can always tell when
something is a variable, an array, or a function. So
go find all your arrays and change their
parentheses to square brackets.
step 7 : Execution of XBasic programs always
begins with the first declared function. The
PROLOG of XBasic programs is for type declarations,
function declarations, and constant
declarations - nothing else. If you have
any executable code before your first function, put it
in an Entry() function and make sure it's the first
function declared in the PROLOG.
step 8 : I don't remember the scope rules for
QuickBASIC very well any more, but all XBasic
variables are automatic and local to the function they're
in unless they're declared otherwise
after the beginning of the function. If you want
to share a variable with another function you
need to put the variable in a SHARED statement in both
functions, or add a # prefix to the
variable name everywhere it appears. XBasic supports
the following scopes:
AUTO
local
& automatic - may live in a CPU register
AUTOX
local
& automatic - never lives in a CPU register
STATIC
local
& permanent - value retained between function calls
SHARED
shared
& permanent - share with functions that declare it SHARED
EXTERNAL
shared
& permanent - shared with static-linked modules that declare it
EXTERNAL
step 9 : Shared constants must be defined in the
PROLOG, and have a $$ prefix, as in
$$MyConstant. So CONST MyConstant = 32 in QuickBASIC
becomes $$MyConstant =
23 in XBasic.
step 10 : Local constants defined within a
function must begin with a $ prefix, as in
$ThisConstant. So CONST ThisConstant = 11 in QuickBASIC
becomes $ThisConstant
= 11 in XBasic.
step 11 : In QuickBasic, to convert strings to numbers you write:
value# = VAL (string$) ' VAL returns double precision
In XBasic you can convert strings to any data type you want:
value = SBYTE (string$) ' signed byte
(16-bits)
value = UBYTE (string$) ' unsigned byte
(16-bits)
value = SSHORT (string$) ' signed short
(16-bits)
value = USHORT (string$) ' unsigned short
(16-bits)
value = SLONG (string$) ' signed long (32-bits)
value = ULONG (string$) ' unsigned long
(32-bits)
value = XLONG (string$) ' native long (signed
32-bits)
value = GIANT (string$) ' signed giant (64-bits)
value = SINGLE (string$) ' 32-bit IEEE floating
point
value = DOUBLE (string$) ' 64-bit IEEE floating
point
value$ = STRING (string$) ' character string
value$ = STRING$ (string$) ' character string
To exactly duplicate the QuickBasic VAL(), replace it with DOUBLE().
step 12 : To make a string of several of the
same character, QuickBASIC has the STRING$()
intrinsic. But STRING$() in XBasic converts any
data type to a string representation. To
generate a series of the same character with XBasic,
change STRING$() to the two argument
form of CHR$(). For example, change QuickBASIC
a$ = STRING$("a",5) to an XBasic a$
= CHR$('a',5).
step 13 : To create formatted strings for printing or other purposes, see FORMAT$().
step 14 : XBasic replaces MID$() on the left side of the assignment operator with STUFF$().
step 15 : By default, XBasic passes function
arguments by-value, while QuickBASIC passes
function arguments by-reference. To make XBasic
pass an argument by-reference, prefix the
argument with @, as in a=func(@a,@b,@c$). When
called functions do not change an
argument, by-value and by-reference are functionally
equivalent. Note: pass-by-value is faster
for numeric variables and pass-by-reference is faster
for string, array and composite variables.
step 16 : The default data type of XBasic variables & arrays is XLONG integer, not SINGLE.
step 17 : Please send additional steps that
will help others convert QuickBasic to XBasic. Some
steps must be performed after some steps and before
others, so please consider this issue
carefully and state where your new steps belong.
Here's another extract from another source that supplies more important info
related to converting QB2XB:
#############################################################################
Nice
to know as a QB programmer:
#############################################################################
QB2XB DOCS
~~~~~~~~~~
There are separate documents published: A .DOC package and a .HTML package. The DOC version requires MS-Word and is too out of date that I would not suggest anyone downloading those.
The HTML version you can find online
here
OR you can download the packed version of the HTML pages here
The QB2XB project explains 17 steps to convert your true QB source to XB
source,(http://www.maxreason.com/software/xbasic/qbtoxb.html) there are still
a few things you need to know which are not mentioned inside these documents:
COMMON SHARED VS #, Main code routine VS PROLOG
In quickbasic you declare shared variables and routines in the primary
code-window.
In Xbasic you do the declarations and everything simular in the PROLOG.
Though you are not allowed to add ANY statement or command execution inside
the PROLOG.
Xbasic does not know COMMON SHARED, the equivalent for that global variable
is using the # sign.
A couple of examples:
SSHORT #Finance% ' Signed integer
SLONG #Long& ' Signed Long
STRING #MyString$
STRING #MyArray$[] ' The array is declared common here,
'
it is NOT dimensioned yet!
TYPE MY_COMPOSITE_TYPE
STRING*40 .Name
SSHORT .Age
END TYPE
MY_COMPOSITE_TYPE #Compositerecord ' A global composite record
MY_COMPOSITE_TYPE #CompositeArray[] ' A global composite array
When defining the composite type, you are required to add the "dot"
in front
of the component in contradiction what you were used to do in Quickbasic!
#############################################################################
IMPORTANT NOTICES when processing
your QB file in XB-text mode:
#############################################################################
The "END"-equivalent:
~~~~~~~~~~~~~~~~~~~~~
The Equivalent table(http://www.maxreason.com/software/xbasic/qbkeywords.html)
mentions the meaning of the "END" instruction being exactly compatible.
This is partly true,but if you use an END instruction to terminate your program,
you HAVE to comment it out or replace it for a QUIT(0) instruction.
A Single "END" instruction is interpreted by XBasic as an "END
PROGRAM".
You have to load your QuickBasic program as a textfile into the PDE.
If you change your text-mode to program mode, all code-lines that comes
behind an "END" instruction will be cut off.
FUNCITON x() / SUB x() vs. FUNCTION
x / SUB x:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Check your sourcecode if it has any function or subroutines without
parentheses "()"
These functions or subroutines will NOT be put in the function-list of Xbasic
when switching from text-mode to program mode.
So:
FUNCTION SetBit
ABit% = ABit% - 1
END FUNCTION
becomes:
FUNCTION SetBit()
ABit% = ABit% - 1
END FUNCTION
OPEN and CLOSE
~~~~~~~~~~~~~~
As a QuickBasic freak you are used to open files with filehandles that start
at #1 and higher.
In Xbasic these handles start from (i believe) 3.
Actually it is never wise to code with such convention in quickbasic:
OPEN File$ FOR INPUT AS #1
but use of FREEFILE will be much more comprehensive and controllable.
In all cases the convertion will go like this:
(QB):
ReadFile% = FREEFILE
OPEN File$ FOR INPUT AS #ReadFile%
(XB):
ReadFile% = OPEN(File$,$$RD)
- ReadFile% :Filehandle, returns -1 if error
- File$ :filename to open
- $$RD :file mode, $$RD
stands for read only and $$RW is for ReadWrite (BINARY in QB)
IF you close the file, you close with the handle that was supplied to the
file:
[error = ] CLOSE(ReadFile%)
In Quickbasic you can close all files with one simple CLOSE command.
In Xbasic you do this with the value -1:
[error = ] CLOSE(-1)
Beware because you also close the console window if you have your file
compiled to an executable!
Filehandles 0 to 2(or 3) are reserved for the console window.
The documents describe that you can startup your executable with the parameter
-noconsole but you can also implement a simple CLOSE(1) in the Entry.
I believe that there is even a constant ($$Console) you can use for that.
CLOSE($$Console) but you have to browse through the xst.dec file to find it's
true name (i don't keep myself too much busy with that)
If you want your records to be loaded you can use the following QB equivalents:
QB XB
LOF() LOF()
LOC() POF()
SEEK()
'is used to set the new binary position
Reading records is not completely the same as what you do with the
GET #x,pos,var
in Quickbasic
Though Xbasic has room where you can make a copy of this function that does
exactly the same since it is not a known function.
Max interpreted only the graphical statement of QuickBasic and totally forgot
about the Filestatement. The graphical GET statement is not supported either.
But here is a small example of how you can do a small random or binary record
read
Note, the XstLoadStringToArray() does not work if your records do not
end with any form of line feed, carriage return or combination, that's why
i calculate record length and read it byte-oriented:
#SysDB% = OPEN(SystemDB$,$$RW) 'Open
database file.
HUsedBound& = LOF(#SysDB%) \ 174 'Calculate
lines in the database
'
This is the total of bytes each
'
record takes (174 in this case)
DIM #HDB[HUsedBound&-1] 'Dimension the amount of lines
PRINT "Loading System database Records:"; HUsedBound&
FOR I% = 0 TO (HUsedBound&-1)
BinString1$ = NULL$(8) '
Fill with null-ascii chars
BinString2$ = NULL$(80)
BinString3$ = NULL$(80)
BinString4$ = NULL$(6)
READ [#SysDB%], BinString1$,BinString2$,BinString3$,BinString4$
#HDB[I%].Code = BinString1$
#HDB[I%].SType = BinString2$
#HDB[I%].Groep = BinString3$
#HDB[I%].Rcode = BinString4$
NEXT I%
There is unfortunately no
VB2XB converter neither have I noticed people who want start a project like
this.
Another unfortunately, I'm not working with VB every day, I'm more a QB guru
than I can be specific about VB. I have played with it for a couple of days
and then abandoned it when discovering XB.
It's not that VB was not good enough, XB offers portability to Linux which I
can't say about VB and I could rewrite my QB programs quicker from scratch in
XB than in VB simply because XB does not know memory limits and have simpler
functions to achieve goals than monkey-business algorithms that are necessary
to shift with large databases in VB will ever do.
As for the general purpose source-code the same rules will apply to the upper
QB2XB tips since VB does has a lot of similarities to QB with a few exceptions
and the graphical exceptions are again one of them.
Basicly there might be a few intresting things you want to know about similarities
between Visual Basic and XBasic:
As well as in VB as in XB you can save your GUI window layout.
Visual Basic saves this as a ".frm" file and in Xbasic the file is
called ".win" (you do have to save it WITH the typed extension!)
Both files contain data like
Ofcourse there are differences, but you can compare them easily with eachother
if you prepare the same window in the GUI-designer in XBasic and then save the
window-file.
This is good material to know if you want to write a converter.
Converting windows manually just require a visual rewrite in the GUI anyway
but take care you name your buttons and labels as exact as you call them in
your VB main-code, it saves a lot of name conversion.
Also VB works with a lot of direct system call methods (API calls), most of
them are supported by XB but if no equivalent exist in XB add the function into
the specific ".dec" file where also the system library is imported.
If you want to know if an API function called in your source is supported in
XB, open the related ".dec" file and try to seek the function in the
exports list, eg. here's a small extract from the "USER32.DEC":
'
' ###############################
' ##### declare functions #####
' ###############################
'
EXTERNAL FUNCTION AdjustWindowRectEx (rect, style, menu, moreStyle)
EXTERNAL FUNCTION BeginPaint (hwnd, addrPAINTSTRUCT)
EXTERNAL FUNCTION BringWindowToTop (hwnd)
EXTERNAL FUNCTION ClientToScreen (hwnd, point)
EXTERNAL FUNCTION CloseClipboard ()
EXTERNAL FUNCTION CreateWindowExA (styleEx, className, windowName, style,
x, y, w, h, owner, menu, inst, param)
EXTERNAL FUNCTION DefWindowProcA (hwnd, message, wParam, lParam)
EXTERNAL FUNCTION DestroyWindow (hwnd)
EXTERNAL FUNCTION DispatchMessageA (msg)
EXTERNAL FUNCTION DrawIcon (hdc, x, y, hIcon)
EXTERNAL FUNCTION EmptyClipboard ()
EXTERNAL FUNCTION EnableWindow (hwnd, enable)
EXTERNAL FUNCTION
EndPaint (hwnd, addrPAINTSTRUCT)
EXTERNAL FUNCTION FillRect (hdc, rect, hbrush)
EXTERNAL FUNCTION FindWindowA (addrClassName, addrWindowName)
EXTERNAL FUNCTION GetActiveWindow ()
EXTERNAL FUNCTION GetAsyncKeyState (key)
EXTERNAL FUNCTION GetCapture ()
EXTERNAL FUNCTION GetClassLongA (hwnd, offset)
EXTERNAL FUNCTION GetClientRect (hwnd, addrRect)
EXTERNAL FUNCTION GetClipboardData (format)
EXTERNAL FUNCTION GetCursorPos (point)
EXTERNAL FUNCTION GetDC (hwnd)
EXTERNAL FUNCTION GetKeyState (key)
EXTERNAL FUNCTION GetQueueStatus (flags)
EXTERNAL FUNCTION GetSystemMetrics (nIndex)
EXTERNAL FUNCTION GetUpdateRect (hwnd, rect, erase)
EXTERNAL FUNCTION GetWindowTextA (hwnd, lpText, nMaxCount)
EXTERNAL FUNCTION GetWindowTextLengthA (hwnd)
EXTERNAL FUNCTION InvalidateRect (hwnd, rect, erase)
EXTERNAL FUNCTION IsClipboardFormatAvailable (format)
EXTERNAL FUNCTION IsIconic (hwnd)
As you can notice most of the system API "Aliases" are used instead
of the direct system-name ("FindWindowA" instead of "FindWindow")
so beware when you call such functions and get a runtime or compiler error when
trying to test your program!
Most of the functions are supported by the Xbasic libraries (X##:Xst, Xgr, Xma,
Xui, Xetc.), try to pick out an XBasic statement / function that really meets
your needs, the less functions you need to add and the more functions you can
substitute by XBasic general functions means you can be sure that the portability
rate of your source-code remains high.
When doing API calls or extended calls, VB requires that arguments are
supported by passing-state like "ByRef" (address) or "ByVal"(the
value as is);
In XBasic you supply ByRef (address) either by prefix the argument with an "@"
or with a "&".
Passing by value is very easy in XBasic, it does not require any prefix.
For most platform libraries you don't need to pass anything by reference but
when you acquire third party libraries, the chances are very likely appearing
that you do need it.
In this case I would just like to reference you to a document that explains third party library
interfacing.