INDEX Spanish characters (ASCII) Using modules General instructions Automatic search & replace Manual search & change Replacing GOSUB Debugging Spanish characters (ASCII) ee minscula () ee mayscula () a con tilde () A con tilde () (does not work on 64-bit) e con tilde () E con tilde () i con tilde () I con tilde () (does not work on 64-bit) o con tilde () O con tilde () (does not work on 64-bit) u con tilde () U con tilde () (does not work on 64-bit) u con diresis () U con diresis () abrir exclamacin () abrir interrogacin () ordinal masculino () ordinal femenino () abrir comillas dobles () cerrar comillas dobles () apstrofo (') tilde () (does not work on 64-bit) lnea horizontal () Using modules To add a module to your program, like LIBRARY.BAS, first use the File menu to create a project, then right-click on the top right area of FbEdit with the tab "Project" selected, then select "Add existing / Module" and select LIBRARY.BAS. To add a .bi file, do the same, but select Add new / File and then save it to give it a name. (N.B.: DO NOT select an existing .BAS or .BI file with the option Add new, because it will be overwritten with an empty file; use the option "Add existing / Module" instead). If you want to use a program previously written, then copy your program's code into the .BAS file with the same name as the project. General instructions to translate a program from QB to FB (see ayuda.htm for details on reformatting for FB). N.B.: All variables must be declared, either as SHARED variables (usually at the beginning of the program) or as local variables, usually at the beginning of each SUB/FUNCTION, and they do not have a type suffix like $ for strings or % for integers. They can also be declared in other places, for example at the beginning of a .bi include file which can be called from anywhere. Example: DIM AS STRING Archivo, ErrorMessage N.B.: Using capitals, initial capital, or lowercase for keywords is optional. You can configure your preference using the menu Options/Code editor/Case convert/Upper case, for example. Then press CTRL+F12 and all the keywords in your code will become capitals. When you are writing new code, they will be transformed as you finish writing each keyword and press ENTER or SPACE. If they aren't (because you are changing or correcting part of a line and do not "finish" writing the keyboard), just press CTRL+F12 again to update all keyboards. Names of variables can include low hyphens or middle capitals, for example: File_Line = 1 N.B.: Using 80-character-long lines is OK in QB, but in FB printing an 80-character-long line would leave an empty line after every line, so that 80 should be replaced by 79, as in DIM Lin(Registros) AS STRING * 79 N.B.: Using GOSUB is NOT ALLOWED (it is not recommended, because it "is considered bad programming practice as it can generate unreadable and untraceable code.") Therefore, it does not work in FB. See GOSUB at the end of the file for alternatives. Most of the changes below were enough for LEXIS to work, but it needed some heavy debugging because I replaced all GOSUBs and often wrote local DIM statements which turned variables into blanks or zeros and caused serious bugs in the program. Other changes which were not necessary in LEXIS but were required in MOUSE: CLEAR does not work in FreeBasic. I commented it out. SOUND and PLAY do not work in FreeBasic. I commented out all calls to SOUND. MONTH, MONTHNAME, DAY, YEAR, NEW, DIR are new keywords in FreeBasic. If you used them as variable names, replace them with, for example, Mes, Dia, Annum, NewX, DirName. Printing a positive number leaves a blank in front of it if linked by ; but not if + is used (see debugging 13). Some special keys do not work with Windows 10: ALT+T was replaced by CTRL+T, and F10 was replaced by F9. Automatic changes (search & replace) 1. Delete DEFINT A-Z (it requires compiling with a specific thing called fblite, and it is no longer useful because you have to DIM all variables anyway.) 2. Replace LCASE$, UCASE$, TRIM$, CHR$, RIGHT$, LEFT$, MID$, INKEY$, STRING$, SPACE$ with LCASE, UCASE, TRIM, CHR, RIGHT, LEFT, MID, INKEY, STRING, SPACE 3. Replace SLEEP 1 with SLEEP 1000 (it is advisable to do it manually, in case there are different values: in QB seconds are used, in FB it is milliseconds.) 4. Replace Color 0, 7 with Colour "black": Colour "bgrey" ' 0, 7 Replace COLOR 0, 3 with Colour "black": Colour "blightblue" ' 0, 3 Replace COLOR 7, 0 with Colour "grey": Colour "bblack" ' 7, 0 Replace COLOR , 0 with Colour "bblack" ' , 0 Replace COLOR 3, 0 with COLOUR "lightblue": COLOUR "bblack" ' 3, 0 Replace COLOR 2, 0 with COLOUR "lightgreen": COLOUR "bblack" ' 2, 0 Replace COLOR 10, 0 with COLOUR "higreen": COLOUR "bblack" ' 10, 0 Replace COLOR 11, 0 with COLOUR "hiblue": COLOUR "bblack" ' 11, 0 Manual changes (search & change) 1. Replace SCREEN 0 / SCREEN 9 with Screen 17, 32 Replace the first instance only; the rest must be deleted. Screen 17, 32 allows both text and graphics, with 32-bit color (RGB 255x255x225). N.B. Do not write any PRINT commands before the SCREEN declaration, otherwise the program will only compile in Windows Console mode, not in Windows GUI, which allows for fullscreen mode (the editor freezes, and the .EXE file generated continues running in memory and has to be stopped by pressing CTRL+ALT+SUPR and stopping it manually). 2. Replace COLOR X, Y Colour "X": Colour "bY" ' X, Y ' Use my FUNCTION Colour N.B. Check there aren't any COLOR left if you are using 32-bit color, otherwise the program will compile but may crash. 3. Replace FOR i = with FOR i AS INTEGER = Replace FOR j = with FOR j AS INTEGER = This can be done as an automatic change, but you will need to use DIM i AS INTEGER if you use i again outside the FOR ... NEXT loop, so it is better to change it manually if your program is not too big. There were 126 instances in the MOUSE program, which was 9076 lines long, plus 16 instances of FOR j ... NEXT j. 4. Replace IF M = "C" THEN Fondo = 3 ELSE Azul = 7 COLOR Azul, Fondo with IF M = "C" THEN Colour "blightblue" ELSE Colour "bgrey" \ 5. Reformat DECLARE SUBs & DECLARE FUNCTIONs \ \ Examples: Replace DECLARE SUB Leer (Texto$) with DECLARE SUB Leer (Texto AS STRING) Replace DECLARE FUNCTION Gist$ (Texto$) with DECLARE FUNCTION Gist (Texto AS STRING) AS STRING 6. Reformat first line in SUBs & FUNCTIONs Examples: Replace SUB Leer (Texto$) with SUB Leer (Texto AS STRING) Replace FUNCTION Gist$ (Texto$) with FUNCTION Gist (Texto AS STRING) AS STRING 7. Add DIM Letra$ AS STRING, Num AS INTEGER, etc. at the beginning of every SUB/FUNCTION for every variable that is not shared throughout the program. N.B. Remember not to DIM any variable that is already different from zero or null at the beginning of the SUB/FUNCTION. 8. Replace Variable$ with Variable It could be done automatically, but it helps you to remember to use DIM with every variable you use in every SUB or FUNCTION). You should also eliminate at this stage (see GOSUB): See also 3 above and 1 in the Debugging section below. N.B.: The changes above can be done as the whole code is revised for errors. / For errors caused by variables not being correctly dimensioned, see the changes below. / _______________________________________________________________________________/ 9. Replace DIM (SHARED) Variable1$, Variable2% with DIM (SHARED) Variable1 AS STRING, Variable2% AS INTEGER, etc. 10. Replace DIM STATIC Letra$, Num% with STATIC Letra AS STRING, Num AS INTEGER, etc. 11. Replace DIM (SHARED) Letra$, Num% with DIM (SHARED) Letra AS STRING, Num AS INTEGER, etc. 12. Reformat DIM SHARED Ayuda(10, 10) AS STRING replace with: DIM SHARED AS STRING Ayuda(10, 10) Reformat DECLARE SHOW (Lin(Limite)) replace with: DECLARE SHOW (Linea AS STRING) DIM SHARED Lin(Limite) AS STRING * 80 (OK) ... ... Show Lin(3) (OK) See valid examples: dim_array_1.bas, dim_array_2.bas, dim_array_3.bas 13. Replace ERASE NombreArchivo, Num ' NombreArchivo is an array, Num is an integer with ERASE NombreArchivo FreeBASIC does not erase simple variables, only arrays. 14. Replace REDIM Array(Num) ' In the middle of a SUB/FUNCTION with DIM AS STRING Array(Num) ' At the beginning of the SUB/FUNCTION + REDIM AS STRING Array(Num) ' In the middle of the SUB/FUNCTION Valid example: DIM NombreArchivo(Nombres) AS STRING * 8 ' At the beginning of the SUB/FUNCTION ... REDIM NombreArchivo(Nombres) AS STRING * 8 ' In the middle of the SUB/FUNCTION OPEN "AUXFILES\DIRS.IND" FOR INPUT AS #6 FOR i AS INTEGER = 1 TO Nombres LINE INPUT #6, NombreArchivo(i) NEXT i CLOSE #6 N.B. Using REDIM in the middle of a SUB/FUNCTION will not cause a compiling error, but will not dimension the array correctly, causing the variables to be the wrong length. Replacing GOSUB If you want to use GOSUB in your program, you must compile your program with the -lang qb option (selecting in the menu Options/Build options/QB GUI). I was able to compile MOUSE that way, but it jumped straight from the welcome screen to the exit one, and froze if I tried to continue, which meant a lot of debugging lay ahead, and as I do not know how to debug efficiently in FreeBASIC, in the end I decided to eliminate all GOSUBs. To get rid of GOSUB blocks of code the first thing you need to do is check how many times the GOSUB procedure is called, depending on which I found three possibilities: Replace them with the whole code (if they are used only once, or in only one place in a DO loop) Replace them with a SUB/FUNCTION (if they are used many times) Replace them with an #INCLUDE file (if you need to share a lot of variables). These three options are explained in more detail below. _________________________________________________________________________ SUBROUTINES WHICH ARE USED ONLY ONCE, or in only one place in a DO loop. DO...LOOP Replace a short GOSUB loop with the whole code if using SUBs / FUNCTIONs is too hard (because a lot of variables are required, f. ex., or if they are used only once because they were designed to integrate the flowchart at the beginning of a long, complex procedure). To minimise errors and keep your new code as similar to the original one in case you need to compare them when debugging, when you start translating your code you can replace your GOSUB line with one of these examples: ShowText: ' ________________________________________________ FOR i = FirstLine TO LastLine ' Shows the gapped text / [here go all the instructions] NEXT i ' _________________________________________/ ShowStatusBar: ' ____________________________________ DO ' Shows status bar / [here go all the instructions] EXIT DO LOOP ' _________________________________/ If you fold (i.e. "collapse", with one of the buttons under the number lines in FbEdit) the loop, they will look like this: ShowText: ' ________________________________________________ FOR i = FirstLine TO LastLine ' Shows the gapped text / NEXT i ' _________________________________________/ ShowStatusBar: ' ____________________________________ DO ' Shows status bar / LOOP ' _________________________________/ In these examples we have included a GOSUB chunk in a FOR ... NEXT loop and another one in a DO ... loop which runs only once, using comments to make the GOSUB loop clearly visible when expanded and self-explanatory when collapsed. However, for long loops which include others it can be hard to see where they end. In that case, you can use this other example, which also allows you to fold the whole procedure while leaving its name visible, to make code revision easier: ProcessFileNames: ' -------------------\ ' Separates file names. ' GOSUB ProcessFileNames \ (this is the original name) DO [here go all the instructions] EXIT DO LOOP ' / ' ___________________________/ This is what it looks like when folded: ProcessFileNames: ' -------------------\ ' Separates file names. ' GOSUB ProcessFileNames \ (this is the original name) DO LOOP ' / ' ___________________________/ _________________________________________________________________________ SUBROUTINES WHICH ARE USED SEVERAL TIMES, WITH FEW COMMON VARIABLES SUB / FUNCTION Replace GOSUB with a SUBs/FUNCTION. This is the best option if it is used several times and called from several points in the code, especially if it needs few or no variables that are common to other SUBs. It is also the best option if you are writing a new program, unless you need to share a lot of variables with the main SUB. The new procedures can include a prefix that relates them to the original procedure, f.ex., for a GOSUB CheckEnd chunk in SUB GapFilling you can use the FUNCTION GF_CheckEnd which returns a value for the variable Finished. That way, all new procedures will appear together in the editor's Functions index. When you start translating your code you can replace your GOSUB line with this: GF_ShowHelp ' GOSUB ShowHelpGF first time /==============\ SUB GF_ShowHelp replaces ' \______________/ GOSUB ShowHelpGF Unfortunately, it is often not easy to replace GOSUB subroutines with a SUB/FUNCTION: in recursive GOSUBs within a FOR ... NEXT loop, you will just have to copy the whole code in the GOSUB section inside the FOR ... NEXT loop, but for recursive GOSUBs which are called from different places in your program you might not be able to transform it into a FUNCTION easily because it changes several variables at the same time. Also, replacing GOSUB with a procedure often causes errors because it is easy to DIM a variable which is not null, which will cause the program to work badly, even if it can compile and run all right. Also, I haven't found out how to pass the data in an array with a SUB without using SHARE to make it available for the whole program. If you prefer a quick fix, use the #INCLUDE option described below. _________________________________________________________________________ SUBROUTINES WHICH ARE USED SEVERAL TIMES, WITH A LOT OF COMMON VARIABLES: #INCLUDE Replace GOSUB with an #INCLUDE file if it uses a lot of variables, share arrays with other new SUBs, or you are in a hurry. This is the less elegant solution, but it works and it avoids most of the problems and hard work described above. Examples: IF Finished = -1 OR Salir = "yes" THEN ' Closes .LOG file, clears arrays ======\ #INCLUDE "CT_Encode_Log.bi" END IF ' =====================================================/ SELECT CASE "MenuOption" CASE "help" ' Shows help screen ===============\ #INCLUDE "ShowHelp.bi" ' Replaces GOSUB MostrarAyuda =====/ END SELECT Then you will have to copy the code in GOSUB MostrarAyuda in a file called "ShowHelp.bi". This is what these examples look like when folded: IF Finished = -1 OR Salir = "yes" THEN ' Closes .LOG file, clears arrays ======\ END IF ' =====================================================/ SELECT CASE "MenuOption" CASE "help" ' Shows help screen ===============\ END SELECT N.B.: Be careful not to DIMension variables in the .bi file which are in use in order to avoid setting them to 0 / NULL accidentally. If you need a new variable, dimension it at the beginning of the main SUB so that you can keep track of them all. Debugging 0. Errors that can make a program crash: You have forgotten to state the result of a funaction (see #2). You have used COLOR X with a graphic screen. (see #7). You are giving an integer array a string value (see #8). You are giving a value to an undimensioned array (see #9). You are trying to read an array from a file which is not open for input. 1. Copy the list of the main SUBs in your program to have a clear idea of its structure. Organise them into a rough flowchart with indents to show which SUBs are called from others, and the order they should be debugged. If you can include all of them, so much the better. You should leave aside the "library" functions which are called from many different points in the code and are common to many of your programs. 2. Remember to state the result of a function at the end of it, otherwise you will get this warning message: warning 13(0): Function result was not explicitly set The program will compile and run, but it will crash. 3. Check you haven't used DIM in a SUB / FUNCTION with the name of a shared variable, or one which at that point has already some value, because it will be set to "" or 0. 4. Use SUB BR (breakpoint) when you want to set a break point in your code to find out the value of some variables: BR "", 0 ' Pauses the program and waits for a key. If ESC is pressed, stops the program. BR Word, Num ' Pauses the program, shows value of one or two variables. See SUB Breakpoint in LIBRARY.BAS for more details and examples. 5. "Error 41: Variable not declared" can be caused not only for using a variable not declared with DIM, but also by using a FUNCTION not declared with DECLARE, like LineaEstado in the following example: Error 41: Variable not declared, LineaEstado in 'LineaEstado (Num)' 6. If the program hangs or crashes after compiling, use BR to stop the program at different points until you find the conflicting instruction. 7. If you are translating, check you have not used COLOR with a graphic screen. It will cause the program to crash. 8. Error 20: Type mismatch, found 'THEN' in 'IF Respondido(NumGap) = "" THEN can mean that Respondido(NumGap) is DIMensioned as an integer, not a string. 9. If you give a value to an undimensioned array the program may crash, sometimes at varying points in the code. 10. MENSAJE "Leyendo" + STR(RegistroZ) + " lneas.", 23, 1, 1 In QB you need not write a space after "leyendo" because STR$ always leaves an empty space to the left of a number, but in FB it is the other way round. 11. FreeBasic does not seem to cause an error if you try to open for input an unexistent file, but of course that will cause a major bug in your program. Use FUNCTION Existe to make sure all your files are there! 12. In FreeBasic, using STR also LTRIMs the resulting string, so printing a positive number leaves a blank in front of it if linked by ; but not if + is used. Thus, the following two examples look the same: <0> PRINT "<"; Num; ">" PRINT "<" + STR(Num) + ">" In QB both ; and + left a blank for the - sign in front of a number. 13. Opening for input a file which is already open will not cause any error messages or stop your program. If you have problems with data not being read from files, check that the file you are trying to read is open. Using CLOSE with no file numbers is supposed to close all open files, but I think on occasion it is not enough, and you must use CLOSE #2, for example. 14. Avoid TABs in data files and text files that need to be read with SUB LEER. They tend to cause errors or show up badly aligned. Use spaces instead.