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:

  1. It seriously does not take too long to learn the few easy and good tricks of XBasic that you can do in one line, you'll need multiple statements for in QB/VB. Rewriting the source code from scratch in XBasic has taught me that you can achieve the same functionality in a more efficient way and in a faster way than I ever did in QB/VB.
     
  2. Some parts like I/O communication and direct port access are not always direct convertible if not even in some cases not convertible at all, so all hardware calls that you do with default QB/VB statements or functions or even interrupt calls have to be translated to XB functions / statements or system calls from the platform's kernal library or some other imported libraries.

  3. XBasic is written to run platform independent or as platform independent as possible. For this reason, certain platform dependant system calls or external library calls are not implemented, so in this case you have to add this support by yourself and if you need a something from a third party vendor you can't get, you're out of luck.


For those who are not convinced to learn the XBasic basics and rewrite from scratch here is the info:


QB2XB


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% 

 

VB2XB

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.