D]3 P]00j:enhanceprint/JRTITLE P]01j:enhanceprint/JRFIGURE1 ]]P00 00 ]]P00 01 ]]P00 02 ]]P00 03 ]]P00 04 ]]P00 05 ]]P00 06 If you program in Basic you may have noticed how limited text output is, compared to programs written in C. Fortunately, many implementations of Basic allow the use of the Amiga's library functions. Both Amiga Basic and HiSoft Basic allow these powerful functions. In this tutorial, I will use the graphics library to enhance screen text. I offer a simple but very useful function you can put in your own programs to provide shadowed print. 3] To assist in reading ease of this document, program lines will be 3]displayed in this color to make them stand out from the descriptive text. 7]USING LIBRARY FUNCTIONS IN BASIC There are some things you should know about using library functions. Don't allow the idea to intimidate you. Using external functions, can be quite easy. Please try the examples in this tutorial. Learning to use these functions provides an excellent springboard to more sophisticated languages. Modula-2, C, and assembly language programmers rely on the library functions. So learning them now makes learning those languages that much easier. To use any of the Amiga's library functions in Basic, you must have the corresponding .bmap file in the libs directory of your boot disk. Since we will be using functions from the graphics library, you need to put the graphics.bmap file in the libs directory. The .bmap files are on the 1.3 Extras disk in the BasicDemos subdirectory. If you don't have these, you can make them by following the instructions in the AmigaBASIC book on pages 6-18 and 6-19. It is also important to know that library functions, unlike Basic functions, are case sensitive. This means that you must capitalize letters that are supposed to be capitalized, and must not capitalize those that are in lower case. One last thing to remember about using library functions is that you are much more prone to get Guru and Software Errors should you make a mistake. One of Basic's less heralded features is that it often insulates you from fatal programming errors. You won't be provided this insulation with library functions, so back up your work often. I usually save every time I attempt to run a modified version of the program. 7]LOCATION LIMITATIONS One of Basic's most restrictive aspects of text output is making horizontal and vertical increments. In Basic, text is placed vertically on lines, and horizontally in columns. This is done with the LOCATE function. What if you need text up two rows of pixels from the tenth line? Fortunately, the graphics library provides the Move function. This function sets the pixel cursor's location like the Basic LOCATE function, except instead of lines and columns, it expects x and y coordinates in pixels. This allows exact placement on the window. ] As example (see Figure 1), let's ]P01 00 ]say you want some text vertically ]P01 01 ]centered within a rectangle that has a ]P01 02 ]fixed position. Depending on the ]P01 03 ]needed location of the rectangle, you ]P01 04 ]may find that Basic's "hard-placed" ]P01 05 ]lines won't allow the text to be ]P01 06 ]centered in the rectangle. Since you ]P01 07 ]can specify any pixel with the Move ]P01 08 function, vertical centering is easy. You may also have this type of problem horizontally as well. In addition to the x and y pixel positions, the Move function requires a pointer to the window's rastport. You don't really need to understand what the window's rastport is, only that it is what lets the computer know on which window to place the pixel cursor. It is possible to place the pixel cursor on another program's window. The WINDOW(8) function provides the pointer to the window's rastport. As an example, if you want to place the pixel cursor 20 pixels from the left edge of the window, and 100 pixels from the top of the window, the function call would read: 3]Move WINDOW(8),20,100 At this point, the pixel cursor is properly set. Unfortunately, if it had been set with Move, Basic will still PRINT where its pixel cursor was left last time the PRINT or LOCATE functions were used. So a library function is needed to print the text. I use the Text function. The Text function expects a pointer to the window's rastport, followed by a pointer to the text to print, in turn followed by the number of characters to print. An example would be: 3]Text WINDOW(8),SADD("Programming in Basic is fun!"),28 If this line followed the previous Move example, the text "Programming in Basic is fun!" without the quotation marks would be printed starting 20 pixels from the window's left edge, and 100 pixels down from the window's top edge. The actual pixel cursor aligns with the leftmost bottom edge of the character. Actual coordinates will need tweaking to get them exactly where you want them. 7]WHAT COLOR IS THAT TEXT? Nowhere is color specified. It is necessary to understand the Amiga's drawing modes to fully understand the colors in which text will print. In this coverage, the concern is only with Jam1 and Jam2. Jam2 mode works like the PRINT function in Basic. When you print in Jam2 mode, every pixel within the character's area gets updated. In Jam1 mode, only the pixels that are on get updated. This means the background doesn't get cleared when you print. This can result in screen garbage interfering with characters or overlaying of text. In Jam1 mode, only the foreground pen is used. Both the foreground and background pens are used in Jam2 mode. The drawing mode can be set with the SetDrMd function. Use a 0 for Jam1 and a 1 for Jam2, in addition to the pointer to the window's rastport. For example, to set the draw mode to Jam2: 3]SetDrMd WINDOW(8),1 Now that we've covered which pens are used for which drawing modes, setting the text's color with the COLOR function is easy. In Jam1, only the foreground pen need be set. To set the text's color to color register 2, issue the command: 3]COLOR 2 In Jam2, foreground and background pens need to be set. For white text and a background to remain the same as the window color, use: 3]COLOR 2,0 Any other background color will result in the text appearing highlighted. This is not necessarily wrong; it doesn't suit the example. 7]LET'S START We now have all the components necessary to put text on the window using the Amiga's library functions. To recap: 1. Open the library 2. Set the drawing mode with SetDrMd 3. Set the foreground and background colors if necessary with COLOR 4. Set the text position with Move 5. Print the text with Text 6. Close the library The library is usually opened very near the top of the program, and it is closed at the end. Be sure that if you have an escape routine in case of an error, you close the library if you have already opened it. 7]SPRINT - A NICE FUNCTION YOU CAN USE Before examining the sample program, I will cover the subprogram called SPrint. SPrint is a function I wrote to allow easy text placement. I use it quite a bit in both my Basic programs as well as C versions. Since the graphics library is not opened in SPrint, it must be opened in the program that CALL(s) SPrint. I wanted a function that not only printed the text, but placed it on the window, set its colors, and shadow-printed it as well. To use SPrint, either copy it out of the source code included into your program, or type it in. Make sure you open the graphics library somewhere in your program before you call SPrint, and don't forget to close it as you exit your program. When you call SPrint, you need to pass it the arguments it needs to print the text. These arguments must be passed in the proper order, or you can count on garbage and possibly a Guru message. The first parameter passed is the actual text that needs to be printed. It must be enclosed in quotation marks. The next two parameters are the pixel coordinates. First comes the x coordinate, then the y coordinate. You should make an effort to ensure you don't provide coordinates that will allow text to print off the window. The next argument needing to be passed is the foreground text's color. This is the color register number as you would use in a COLOR statement. The next parameter is the text's shadow color. This could be any color, but black is often used for visual clarity. If you don't want shadowed print, send whatever register the background color is. This will usually be register 0 unless you have already placed some other graphics here. The first uncommented line in the program is: 3]SetDrMd WINDOW(8),0 This sets the drawing mode to Jam1, which is required so the overlying text does not blank out the underlying shadowed text. 3]COLOR BCOLOR% This sets the foreground color to the color in which the shadowed text will appear. Black or another dark color work best. 3]Move WINDOW(8),XPOSITION%+2,YPOSITION%+1 This sets the pixel cursor to the proper place for the shadowed text print. Two pixels are added to the x coordinate and 1 pixel to the y coordinate. This makes the shadowed text appear slightly down and to the right of the foreground text. 3]Text WINDOW(8),SADD(Txt$),LEN(Txt$) This is what actually prints the text. It provides the pointer to the window's rastport, followed by the pointer (SADD) to the text, followed by haw many characters that will be printed. The shadowed text is now printed. All that needs to be done is to print the main foreground text. 3]COLOR FCOLOR% Sets the color to the main color wanted for the main foreground text. 3]Move WINDOW(8),XPosition%,YPosition% Positions the text. The coordinates are not adjusted here. The main text prints where the SPrint function was set to print. 3]Text WINDOW(8),SADD(Txt$),LEN(Txt$) Prints the main foreground text. Next, end the subprogram. The entire SPrint function follows for easy reference. 3]SUB SPrint(Txt$,XPosition%,YPosition%,FColor%,BColor%) STATIC 3]'-------> This subprogram prints to any pixel location with/out shadows. 3]'-------> Txt$ = the string to be printed. 3]'-------> XPosition = how many pixels from the left edge to print. 3]'-------> YPosition = how many pixels from the top edge to print. 3]'-------> FColor = the main text color (foreground). 3]'-------> BColor = the shadow text color (background). 3] SetDrMd WINDOW(8),0 3] COLOR BColor% 3] Move WINDOW(8),XPosition%+2,YPosition%+1 3] Text WINDOW(8),SADD(Txt$),LEN(Txt$) 3] COLOR FColor% 3] Move WINDOW(8),XPosition%,YPosition% 3] Text WINDOW(8),SADD(Txt$),LEN(Txt$) 3]END SUB 7]NOW ON TO THE PROGRAM With the exception of the $OPTION Y+ comment, I will skip any mention of the commented lines. The first important line in the program is the $OPTION Y+ comment line. This line is for HiSoft Basic users. It disables the window HiSoft normally opens on Workbench. It will have no effect for AmigaBASIC users, so they can ignore it. 3]'$OPTION Y+ This is for HiSoft Basic. It disables the Workbench window. Now, open the graphics library. 3]LIBRARY "graphics.library" Next, open the screen, window, and set palettes. I am using a rather plain window to make this program both AmigaBASIC and HiSoft Basic compatible. HiSoft users should know they have many powerful additional window modes. Of special mention are the background and borderless options which AmigaBASIC lacks. These window options are essential for clean professional looking screens. 3]SCREEN 1,640,200,3,2 3]WINDOW 1," © 1991 by Joe Rattz, Jr. 3] JUMPDISK Magazine",,,1 3]PALETTE 0,.43,.5,.625 'Gray 3]PALETTE 1,0,0,0 'Black 3]PALETTE 2,1,1,1 'White 3]PALETTE 3,.125,.8125,.9375 'Lt. Blue 3]PALETTE 4,1,0,0 'Red 3]PALETTE 5,1,1,0 'Yellow With that completed, it's time to lay out the basic screen interface. CALL the subprogram SPrint to display a title at the top. The following LINE statements draw the dimensioned bars which divide the screen. All the vertical lines are doubled in thickness. This is necessary at this resolution (620 x 200), if you wish to have them appear relatively even in thickness. If the verticals are not doubled, these lines will be thinner than horizontal lines are tall. Then print the Click Mouse message at the bottom of the screen, and put some lines and arrows around it to get attention. 3]CALL SPrint("Enhanced Basic Text Output",200,15,3,1) 3]LINE (100,22) - STEP(400,0),2 ' 3D horizontal - white 3]LINE (100,23) - STEP(400,0),1 ' 3D horizontal - black 3]LINE (299,24) - STEP(0,100),2 ' 3D vertical - white 3]LINE (300,24) - STEP(0,100),2 ' 3D vertical - white 3]LINE (301,24) - STEP(0,100),1 ' 3D vertical - black 3]LINE (302,24) - STEP(0,100),1 ' 3D vertical - black 3]CALL SPrint("=================>",10,180,5,1) 3]CALL SPrint("Click Mouse Or Any Key To Continue",180,180,4,1) 3]CALL SPrint("<===============",480,180,5,1) Next, lay out the left side, which only uses native Basic printing commands. I hope you will notice how primitive these look compared to the pretty library function side of the screen. When you look at the actual running program, you can see one of the limitations Basic printing has. The normal Basic output title on the left side of the screen is jammed into the dimensioned line above it. The only option I have if the line must remain where it is, is to move the title down an entire line, which is too far. This is one of the exact reasons to use the library functions. With them, I could move that title down another pixel or two if I wanted. 3]LOCATE 4,16 3]COLOR 2 3]PRINT "Normal Basic Output" 3]LOCATE 6,20 3]COLOR 4 3]PRINT "Line 6" 3]LOCATE 7,20 3]COLOR 5 3]PRINT "Line 7" Lay out the Enhanced Basic Output side using the library functions. First, I title this side of the display. Then I set the draw mode to Jam1. I wouldn't need to do this if I were only using the SPrint subprogram, because it does this for me. Since I will do some simple printing without using SPrint, I must set it for the desired results. I am not using SPrint exclusively here, so you can see the steps necessary to print text with the library functions. After the title, the next two lines are equivalents for the two lines printed on the normal Basic side. These are to show what some plain text looks like with the library functions. There are no equivalents on the normal Basic side for the remainder of the enhanced Basic side's lines. That's because they aren't possible. 3]CALL SPrint("Enhanced Basic Output",321,32,2,1) 3]SetDrMd WINDOW(8),0 3]COLOR 4 3]Move WINDOW(8),356,46 3]Text WINDOW(8),SADD("Pixel Line 46"),13 3]COLOR 5 3]Move WINDOW(8),356,54 3]Text WINDOW(8),SADD("Pixel Line 54"),13 3]CALL SPrint("Isn't this pretty output?",310,70,5, 3]CALL SPrint("Raised print!",360,85,2,1) 3]CALL SPrint("Engraved print!",350,95,1,2) 3]CALL SPrint("P",330,122,5,1) 3]CALL SPrint("R",338,121,2,1) 3]CALL SPrint("I",346,120,3,1) 3]CALL SPrint("N",354,119,4,1) 3]CALL SPrint("T",362,118,5,1) 3]CALL SPrint("c",378,116,2,1) 3]CALL SPrint("a",386,115,3,1) 3]CALL SPrint("n",394,114,4,1) 3]CALL SPrint("'",402,113,5,1) 3]CALL SPrint("t",410,112,2,1) 3]CALL SPrint("d",426,112,3,1) 3]CALL SPrint("o",434,113,4,1) 3]CALL SPrint("t",450,115,5,1) 3]CALL SPrint("h",458,116,2,1) 3]CALL SPrint("i",464,117,3,1) 3]CALL SPrint("s",472,118,4,1) 3]CALL SPrint("!",480,119,5,1) With the enhanced side complete, the program maintains its display until you exit it. Like all good multitasking Basic programs, this one uses the SLEEP command. I can't stress how important this is, if you want programs that run well on the Amiga. SLEEP is what allows the program to wait for user interaction without hogging the CPU. For some reason, AmigaBASIC seems to require two consecutive SLEEPs to work properly, while HiSoft only needs one. Fortunately, HiSoft will work properly with two, allowing AmigaBASIC compatibility. 3]SLEEP 'HiSoft only needs one sleep, but Amiga Basic seems to need 2 3]SLEEP Close the library. This one statement will close all open libraries, so it need be executed only once. 3]LIBRARY CLOSE Close the window and screen, and shut down. 3]WINDOW CLOSE 1 3]SCREEN CLOSE 1 3]END The rest of the file is the SPrint subprogram, which has already been covered. 7]TIME TO QUIT The library functions can make Basic programs shine. While Basic is not the fastest or most powerful language available, it is one of the easier ones to get started with. I hope you can now go back to your Basic programs and implement some really gorgeous text. Don't think that SPrint is finished. It is just a start. I am sure you can add all kinds of additional features to it. For example, if you have more than one window open, you will need to pass it an argument to let it know in which window to print. Right now, it only assumes one window is open and prints to it. Perhaps you might want to allow for different fonts. 7]REGARDING HISOFT I would like to add one additional note. I wrote this original program in HiSoft in a matter of minutes. Unfortunately, it took quite a bit longer to make it AmigaBASIC-compatible as well. I felt compatibility to appeal to as many Basic programmers as possible. Having spent many hours programming in Basic on the Amiga, I can tell you that if you are even somewhat serious about Basic, get HiSoft Basic. If you have any questions write to: 6]Joe Rattz, Jr. 6]1051 Nottingham Drive 6]Sumter, SC 29153