Introduction Meetings Members Magazine Articles Programs

SQLUG

SCOTTISH QL USERS GROUP

Programming Hello World with TPTR

JOHN SADLER

Introduction

The TPTR suite of programs have been developed by George Gwilt to enable programmers to create pointer environment programs using the Turbo dialect of Superbasic. Besides extending Turbo so that it can cope with TPTR, George has created a set of extensions TPTR, a set of basic extensons TPTR_BAS, and programs Setf to create Pointer Windows, and Alter to change.

However the pointer environment is not an easy one to use and neither is the TPTR a GUI IDE (Graphics User Interface Integrated Development Environment) so it was thought helpful to write this guide to help users with TPTR.

Pointer Environment

The Pointer Environment does not operate in mode 8. SuperBasic in mode 8 runs in its own mode 8 screen. It is possible to create pointer environment programs suitable for mode 8 but they still run in the pointer screen. For such programs it is necessary to specify csize as 2,0 and allow more room for icons with words. For example Esc occupies 40 pixels. When a program starts up, it starts in the mode current at the time and so if the display has been designed for mode 4, and it is started in mode 8 you may get error messages as it cannot display the windows properly. (You get the same problem with Superbasic programs but as we normally run in mode 4 we do not notice it.) The function mode% returns the mode and can be use to set the mode before any windows are opened.

Windows

Before comencing the coding of the program it is necessary to design your windows. There is no alternative to planning them beforehand as this is not an IDE and you are advised to use Setf. Each main window has a size and if it is resizable a minimum size which should be big enough to hold any other information windows, application windows and loose items. Loose items can be considered as buttons, icons etc for user inputs such as mouse clicks and key presses to initiate user requests. Information windows are for displaying messages. There are also application windows and menu items.

Hello_bas

We will demonstrate setting up a pointer program with hello_bas which is the standard demonstration program "Hello World" complete with resize, move, sleep and close buttons. There is also button to initiate the greeting.

Creating the Window Definition File

Creating the window definition file is explained in Using SETF in the TPTR Suite to create Hello World Window Definition File.
Please follow this article before continuing with writing the porgram.

The Basic Program

The basic program will run in basic and it is good idea to run it in basic to ensure the program is correct. It has been found that programs will compile but not run in Superbasic. These programs may have an error in them. To start load the window definition file and then merge the basic routines tptr_bas. Line 1 contains the global integer variables for the routines. The turbo extensions now contain compiler directives.

 TURBO_objfil 'ram1_hello_TASK' 
defines the name of the compiled program as ram1_hello_task.
 TURBO_taskn 'hello v0.1' 
defines the task name of the program and the name which appears in the sleep button.
 TURBO_objdat 100 
defines the data size of the compiled program.
 TURBO_repfil 'ram1_err' 
defines the file for the compilation error reports.
 TURBO_struct 1 
defines the program shall be structured.
 TURBO_windo 0 
defines the channel the compiled program runs.
 TURBO_buffersz 300 
defines the buffer size for compilation.
Now ensure the program does not run in mode 8 with
 IF MODE% = 8 THEN MODE 4
Now we can define the windows and open them. If the program is compiled open channel 0, set the ink to a colour (so that it runs under smsq) and set the wch% to 100, else call BOUTL which makes channel 0 suitable for pointer programs and set wch% to 0 with the lines
IF COMPILED: OPEN#0,con:INK#0,GREEN%: wch%=100
ELSE: BOUTL: wch%0=0: END IF.
Now create the window definition. If it fails exit with the lines
IF NOT Set_Win: PRINT#0,"I can't open windows!": Stip: END IF
Now produce the working window definition pointed to by wwd with the line
 wwd=MSETUP(#wch%, wd(0), 0) 
where wd(0) is the channel of the application window. The address of compiled primary window or pull down application window if in basic with the lines
IF COMPILED: chid=M_PROS(wwd,-1)
ELSE: chid=M_PULLD(wwd,-1): END IF
Now we open channel 4 and set it as the first information window with the line
SET_CHANNEL#4,SWIN(0,1,wdd)
Next we can run the loop which reads the pointer until we quit the program. get_x% retrives the most significant part which is 255 for loose items, 254 for events or else the number of the application window. get_y% retrieves least significant part for the action with the lines
REPEAT lp
   k=WRPTR(wwd): r=255&&get_x%(k)
   SELect ON r 
     =255: IF NOT do_loose%(get_y%(k)):EXIT lp 
     =254: IF NOT do_event%(get_y%(k)):EXIT lp 
     =REMAINDER: IF NOT do_app%(r, get_y%(k)): EXIT lp 
   END SELect lp 
END REPeat lp 
If in basic reset the windows and print a message so we know what has happened and STOP the program with the lines
IF NOT COMPILED: WTV: PRINT#0,"Program Finished": STOP 
We can now write the procedures for handling the actions. First the procedure finish to terminate the program cleanly. Then BUNST unsets the working definition or closes the window if complied, BRCHP returns its space to the heap, if compiled CLOS closes the channel for the window else use CLOSE. BRECHP returns the space allocated to the window definition. So the procedure is
DEFine PROCedure finish 
   BUNST wwd: BRCHP wwd 
   IF COMPILED: CLOSE chid
   ELSE: CLOSE #4: BRECHP 
END DEFine finish
Now the procedure to handle the buttons or loose items labeled 0 to 4 in the order we created them for the window. When returning from sleeping we have to open channel #4 with SET_CHANNEL again. ALso the loose item must be available again with D_LDRW except when finishing the program. So we have the lines
DEFine FuNction do_loose%(num%)
   LOCal k, bool% 
   k=num%: bool%=1 
   SELect on k
     =0: mve =1: do_size 
     =2: Do_Sleep wwd, chid, wch%: SET_CHANNEL#4,SWIN(0, 1,wwd) 
     =3: do_finish: bool%=0: RETurn bool% 
     =4: do_greeting 
   END SELect 
   IF NOT k=3: D_LDRW num%, wdd 
   RETurn bool% 
END DEFine do_loose% 
The events returned are signalled by 2 for quit, 8 for move, 16 for resize and 32 for sleep. This function is handled by the lines.
DEFine FuNction do_event%(num%) 
   LOCal bool% bool%=1 
   IF 2&&num%: do_finish: bool%=0: RETurn bool% 
   IF 8&&num%: mve IF 16&&num%: do_size 
   IF 32&&num% : Do_Sleep wwd, chid, wch%: SET_CHANNEL#4, SWIN(0, 1, wwd) 
   RETurn bool% 
END DEFine do_event%
Now we can define the functions called. do_app% just returns success with the lines
DEFine FuNction do_app%(wind%, num%) 
   RETurn 1 
END DEFine do_app% 
For mve the cursor position in channel 4 has to be saved before moving with BCHWIN and reinstated with the lines
DEFine PROCedure mve
   LOCal cur_pos 
   cur_pos=GETCU(CHANNEL_ID(#4)) 
   BCHWIN wwd SET_CHANNEL#4, SWIN(0, 1,wd): AT#4, get_y%(cur_pos),
   get_x%(cur_pos) 
END DEFine mve 
The do_size function is more complicated. First the position of the current window located at the working definition wwd+$24 plus its origin located at wd(0)+$4 has to be stored for use in reforming the windows with PRPOS or PULLD. The change in size is obtained with BCHSZ and its x & y components extracted. This is obtained with the lines

DEFine FuNction do_size LOCal mv, xmv%, ymv%, newx%, newy%, optr optr=PEEK(wwd+36)+PEEK(wd(0)+4) mv=BCHSZ(wwd) xmv%=get_x%(mv): ymv%+get_y%(mv)
These must be no smaller than the minimum size in wd(0)+$30 and no bigger than the maximum size located in the location pointed to by wwd+$4. The actual size is in the location wwd+$20. Allowance must be made for the scaling flags $4000 and finally the x value must be even. The long words can be split into their words by PEEK_W for the x location and adding 2 for the y location. This is obtained with the lines
   newx%=ev%(min%(PEEK_W(PEEK_L(wwd+4)), max%(PEEK_W(wd(0)+48)&&4095, PEEK_W(wwd+32)-xmv%))) 
   newy%=(min%(PEEK_W(PEEK(wwd+4+2)), max%(PEEK_W(wd(0)+48+2)&&4095, PEEK_W(wwd+32+2)-ymv%)) 
We now unset the working definition with BUNST close it with CLOS if not compiled, return the area to the heap with BRCHP , set up the new window with the new x & y combined into a long word with M_SETUP, set up a new window if compiled using M_PRPOS or pull it down with M_PULLD and set the channel 4 with SET_CHANNEL to the application window found with SWIN in the lines
BUNST wwd: BRCHP wwd 
   IF NOT COMPILED: CLOS chid wwd=M_SETUP(#wch%, wd(0), 2^16*newx% + newy%) 
   IF COMPILED: chid=M_PROS(wwd, optr): ELSE:chid=M_PULLD (wwd, optr) 
   SET_CHANNEL#4, SWIN(0, 1, wwd) 
END_DEFine do_size 
Finally the greeting is displayed with the lines
DEFine PROCedure greeting 
   PAPER#4, RED%: INK#4, WHITE% PRINT#4, "Hello World!" 
END DEFine greeting 

This completes the hello_bas program and provides the minimum facities for a pointer environment program using tptr.

Resizing

It will be noticed that the program actually destroys the window when resizing and redraws it completely, so that all the contents are lost. Thus it is not possible to retain the contents on resizing, without printing all the information to the window again.

Here is the source code for Hello_bas before tptr_bas is added.

Introduction Meetings Members Magazine Articles Programs