Introduction Meetings Members Magazine Articles Programs

SQLUG

SCOTTISH QL USERS GROUP

Programming Example 4 for Xmenu with CPTR

JOHN SADLER

Introduction

In Vol 7 Issue 4 of QL Today George Gwilt described the "orthodox" way of writing PE programs with TurboPTR or CPTR. This article is to show you how easy it is with CPTR, using as an example test4 from Part 4 of Jerome Grimbert's articles on XMENU in Vol 7 Issue 4 of QL Today.

If you have not installed CPTR, the first step is to unzip the program files for CPTR. The programs setz, spr and seewinf should be put in a suitable directory or floppy. The file libcptr_a should be put in the C68 LIB directory or floppy. The file wdef_h should be put in the C68 INCLUDE directory or floppy.

So that setz works properly set PROGD$ with prog_use "Location of CPTR" and DATAD$ with data_use ram1_

We are now ready to go through the process of producing the program "test4".

I have taken this step by step so that even a new QL user can easily achieve the final result.

A. Producing the Window by Using setz

The program setz follows the same course as setf whose operations are described in the Appendix to George Gwilt's article on PE windows in Vol 7 Issue 4.

Start program					( Enter "ex setz" )
Program name is "test4"				( Enter "test4" )
Alter Text					( Press n )
						( Enter "PE in C test 4" )
						( Press n )
						( Enter "Quit" )
						( Press Esc 4 times )

Number of main windows = 1			( Press enter )
Number of loose items = 4			( Press 4 enter )
Number of information windows = 1		( Press 1 enter )
Number of loose items  = 1			( Press 1 enter )
Number of Application Windows = 1		( Press 1 enter )
Number of menu items = 0			( Press enter )
For Main Window
The shadow size = 0 				( Press enter )
The border size = 1 				( Press 1 enter )
The border colour = black			( Press up arrow once & enter )
The paper colour = white			( Press up arrow four times & enter )
Sprite is default				( Press Esc )
Presentation of loose items is default		( Press y )
Type of Loose item 1 is text			( Press enter )
Text is "Quit"					( Press down arrow & enter )
Key is Esc					( Press Esc )
Type of loose item 2 is sprite			( Press down arrow & enter )
Sprite is mode 8 (changed later)		( Press up arrow twice & enter )
Key is Ctrl F1					( Press Ctrl F1 )
Type of loose item 3 is sprite			( Press down arrow & enter )
Sprite is move					( Press up arrow 5 times & enter )
Key is Ctrl F4					( Press Ctrl F4 )
Type of loose item 4 is sprite			( Press down arrow & enter )
Sprite is resize				( Press up arrow 6 times & enter )
Key is Ctrl F3					( Press Ctrl F3 )
Information window border is 0			( Press enter )
Information paper is light green		( Press down arrow & enter )
Object is text					( Press enter )
Object is "PE in C test 4"			( Press enter )
Ink is white					( Press up arrow 4 times & enter )
X_csize is 0					( Press enter )
Y_csize is 0					( Press enter )
Application window border is 4			( Press 4 & enter )
Application window border is grey		( Press enter )
Application window paper is green		( Press up arrow twice & enter )
Application window sprite is default		( Press enter )
Application window select key is tab		( Press tab )
Now for sizes of windows and position
Main Window is 180 wide by 230 deep		( Alter until display shows correct size )
Variable sized window				( Press y )
Minimum size is 120 wide by 130 deep		( Alter until display shows correct size )
Origin is 20 by 8				( Alter until position is correct & enter )
Loose item 1 is correct size at 90, 3		( Alter until position is correct & enter )
Loose item 2 is 24 by 14 at 4, 16		( Alter until correct & press enter )
Loose item 3 is 16 by 14 at 32, 16		( Alter until correct & press enter )
Loose item 4 is 16 by 14 at 60, 16		( Alter until correct & press enter )
Information window is at 2, 3 			( Alter until position is correct & enter )
Object is in correct position 			( Press enter )
Application window is 90, 80 at 14, 40		( Alter until correct & press enter )
Now we position moveable items
Loose item 1 moves horizontally 		( Press n, n, y, n )
Loose items 2, 3 & 4 are fixed			( Press n, n, n, n, thrice 
Information window horizontal size		( Press y, n, n )
Application Window is fixed			( Press n, n )
The information object is fixed			( Press n )

Now the main window will be shown		( Press enter ) . .
. . and the "sleep" window is shown		( Press enter to complete the program )
You will now have four files in ram1_, test4_wda, test4_z, block_blo_bin & wh_pat_bin.
test4_wda is the window definition file for using with TurboPTR.
It can be displayed again with: ex seewinf;'test4'
test4_z is the file to be edited and processed to create the source.
The other files were used by setz and can be either left or deleted since they are no longer needed.

B. Editing the _z File

Open test4_z in your favourite editor.

Not all the parameters are needed in the function declarations alit0_0 alit0_1, alit0_2, alit0_3 and alit1_0 so change them to

						alit0_0(void);
						alit0_1(WM_wwork_t *,WM_litm_t *, WM_wstat_t *);
						alit0_2(WM_wwork_t *,WM_litm_t *, WM_wstat_t *);
						alit0_3(WM_wwork_t *,WM_litm_t *, WM_wstat_t *);
						alit1_0(void);
We want to make the application window variable in size but setz did not allow this. We also want to use a hand sprite in the application window.
So in the lines following "static struct WM_dappw appw0 =": In "static struct WM_dappw appw0 =" change
"  90,              /* xsize " to 			"  90 + 16384,		 /* xsize " ( line 45 )
"  80,              /* ysize " to 			"  80 + 16384,         	 /* ysize " ( line 46 )
"  0,               /* pspr *" to 			"  %%<<&wm_sprite_hand>, /* pspr *"  ( line 53 )
In "W_LITM (4, litm0)" change
"  0,               /* pobj *" to 			"  %%<<&wm_sprite_sleep>,/* pobj * " (line 110 )
so we have a sleep sprite instead of something odd or a crash.

We have now finished tidying up the window definition and can start writing the program.

C. The Program

Scroll down to nearly the end of the file to just pass "End of Declarations" and enter the following before int main()
void (*_consetup)() = NULL;
char *_endmsg = NULL;
char _prog_name[] = "PE in C tutorial 4";
void (*_cmd_params) () = NULL;		/* No arguments are passed		*/
long (*_cmdchannels) () = NULL;		/* Redirection is not used		*/
long (*_stackchannels) () = NULL;	/* No parameters are passed		*/

WM_wwork_t *wwa0;
chanid_t chid0;
We are instructing the compiler not to include facilities for parameters or redirection and setting the program name. CPTR uses the program name to display in the button when it is put to sleep.

*wwa0 is the global variable for the working definition.
chid0 is the global variable for standard out so the program to write to it.

The remainder, which immediately follows
int main()
 {
completes the program:
  int err;

  /* make  mode 8 mode 4 */
  short mode, type;
  mode = -1;
  type = -1;
  mt_dmode(&mode, &type);
  if (mode == 8) { mode = 4; mt_dmode(&mode, &type); }

  if(getsze(&wd0, prtab, &ws[0], wd0_sizes, &num)) exit (ERR_NC);
  if(!(chid0 = fgetchid(stdout))) exit (ERR_NI);
  if(!wm_findv(chid0)) exit (ERR_NF);
  if(!(wwa0 = malloc(wd0_sizes[0]))) exit (ERR_OM);
  if(wm_setup(chid0,0,0,&wd0,&ws[0],&wwa0,0)) exit (ERR_NI);
getsze creates a table to hold the pointers which the pointer environment uses to access various items and functions.
fgetchid and wm_findv connect chid0 to standard out and place it in the window.
malloc creates space for the window definition, and wm_setup creates it.
Now add the lines
  if(wm_prpos (wwa0,DEFXY)) exit(ERR_NI);
  if(wm_wdraw (wwa0)) exit(ERR_BO);
wm_prpros positions the window and wm_wdraw draws it.
Then add the lines
  while(!(err = wm_rptr(wwa0))) ;
  free(wwa0);
  exit (err); 
"while(!(err = wm_rptr(wwa0))) ;" reads the pointer until there is an error.
free(wwa0) frees the space for the window definition and "exit (err);" exits and
displays the error if the program is started with ew.

After the closing bracket "}" we need a function for alit0_0 the "Quit" button or loose item.

/************************** Quit ****************************/

int alit0_0(void)
 {
  exit (EXIT_SUCCESS);
 }
Perhaps now is the time to explain an unique feature of C programming for the pointer environment. When a loose item is activated there are useful items in the registers. So instead of just jumping to the correct function the wrapper makes these items available so the function can use them.
Hence if these items are declared in the function properly they will automatically be used by the function and the programmer does not have to worry that he has used to correct variables. So
"static struct WM_action afun0_1 ={JSR,wm_actli,alit0_1};"
creates an area in the program which has the code for jump to sub routine actli and then jump to routine alit0_1. actli is a function which get these items for the function alit0_1. Then the function alit0_1 and uses these items if they are declared in the correct order and used in the function.

So now we need a routine for the sleep loose item.

/************************** Sleep ***************************/

int alit0_1(WM_wwork_t *wwk, WM_litm_t *li, WM_wstat_t *wst)
 {
  wst->evnt |= PT_ZZZZ;
  do_sleep3(wwk->chid, wwk,0, _prog_name, NULL, wd0_sizes);
  return slitem(wwk, li->item,0);
 }
wst->evnt |= PT_ZZZZ activates the loose item. do_sleep3 puts the program to sleep and slitem resets the loose item to available again.

Then a routine to move the window.

/************************** Move ****************************/

int alit0_2(WM_wwork_t *wwk, WM_litm_t *li, WM_wstat_t *wst)
 {
  short dx,dy;
  int err;
  wst->evnt |= PT_WMOVE;
  if (err = wm_chwin(wwk, &dx, &dy)) return err;
  return slitem(wwk, li->item, 0);
 }
wst->evnt |= PT_WMOVE activates the loose item and wm_chwin changes the window to its new location.
Next we need a routine to resize the window
/************************* Resize ***************************/
int alit0_3(WM_wwork_t *wwk,WM_litm_t *li, WM_wstat_t *wst)
 {
  short ddx, ddy, dx, dy;
  int err;

  wst->evnt |= PT_WSIZE;
  ddx = wwk->xsize+wwk->xorg + wd0.wdefa.xorg;
  ddy = wwk->ysize+wwk->yorg + wd0.wdefa.yorg;
  dx = 4*((dx + 3)/4);
  dy = 2*((dy + 1)/2);
  if (err = wm_chwin(wwk, &dx, &dy) < 0) return err;
  dx = EVEN(MIN(wd0.wdefa.xsize, MAX(wd0.wdefb[0].xsize &
                     0x3FFF, wwk->xsize-dx)));
  dy = MIN(wd0.wdefa.ysize, MAX(wd0.wdefb[0].ysize &
                     0x3FFF, wwk->ysize-dy));
  if (err=wm_unset(wwk)) return err;
  if (err=wm_setup(chid0, dx, dy, &wd0, &ws[0], &wwk,0)) return err;
  if (err=wm_prpos(wwk, ddx- dx, ddy- dy)) return err;
  if (err=wm_wdraw(wwk)) return err;
  return slitem(wwk, li->item,0);
 }
After activating the loose item with wst |= PT_WSIZE, the absolute pointer position is placed in ddx & ddy.
Then new size is placed in dx & dy and rounded up to multiples of 4 & 2 respectively.
The new size is restricted to the maximum size and minimum size of the window.
wm_unset removes the window, wm_setup creates again but has to find channel from chid0, pr_pos positions it and wm_draw draws its, but not its contents.
Finally add the following /******** Dummy action routine for the button window ********/ int alit1_0(void) { exit (EXIT_FAILURE); } This finishes editing the z file.

D. Compilation

Now convert ram1_test4_z to ram1_test4_c file with ex spr,#1;'test4'
If all has gone well you will have a new file test4_c. If not the error will be shown on #1.
Now if the location of your C68 directory is not the same as your CPTR directory change it with
                                        	prog_use " Directory of C68 "
Compile with					ex cc;'test4_c -l cptr -o test4'
and check it with				ex ram1_test4

E. Conclusion

George's CPTR method is so much easier for designing windows and also a lot faster than any other I have seen. Furthermore you have the advantage that it uses the pointer routines and so there is no problem of changes in the pointer environment making it out of date or in the resizing of windows. The code seems to be more compact. There are further explanations in George's test files and examples. There are far more facilities inside CPTR such as a method for designing sprites, the ability to display help comments, drag & drop, and scroll bars for application windows. Finally the code is actively maintained and extended when required by George so the more you use it and ask for extensions the more likely it will be extended to suit your needs.

Introduction Meetings Members Magazine Articles Programs