understandable, but yet involved enough to show something. You may
download and try the complete source here. The included Bitmap is of
size 50×52, and I did it with Painbrush Pro. The size is the same as
the bitmap in the tutorial example. Above you can see a the logo
converted to GIF. It is probably best to keep the logo as simple as
possible. The complete application is here to try on your Avigo.
icon and convert it to dot format with the button on the icon page.
Then compile the source and start the simulator. Go to the applications
and start the Lotto program. You will see the following Avigo screen.
on its left top containing entries "New Numbers" and "Exit", which is
dropped down at this moment, and it can be closed with the cross at the
top right. Nothing spectacular, and of little use. But it serves as a
demo for a simple Avigo program. By the way, you can do screen prints
with a menu item in the debugger.
While trying this in the simulator, I noticed that the menu selection
does not work properly with the mouse. You have to try a bit to get the
"New Numbers" entry to respond.
What follows is the source. I am going to explain most of it later.
/* you have to include all those header files*/
#include "p100plib.h"
#include "ressdk.h"
#include "math.h"
#include "packet.h"/* you have to decleare a static string for the window
title
*/
unsigned char test_title[] = "Test Title";/* you have to declere the event handlers BANKED and extern
*/
extern BANKED void test_draw (VOID_PTR view);
extern BANKED void test_handle_event (VOID_PTR view,unsigned short *evType, unsigned char x, unsigned char y);
/* define the command constants (belongs to a header file)
*/
#define cmdNew 1000/* define the main menu structure
*/
const MENUITEM MainMenu[] =
{ {"New Numbers", cmdNew, 0},{"Exit", cmCancel, 0},
{"\0", 0, 0}
};
/* those are the routines to generate Lotto numbers
*/#define Ntotal 49
#define Nchosen 6
int Numbers[Ntotal];
void init_numbers ()/* initialize the first 6 as chosen
*/
{ int i;
for (i=0; i<Ntotal; i++) Numbers[i]=0;
for (i=0; i<Nchosen; i++) Numbers[i]=1;}
void mix_numbers ()
/* randomly mix them (thanks to the random() function)
*/
{ int i,j,h;for (i=Ntotal-1; i>0; i–)
{ j=random(i+1);
if (j!=i)
{ h=Numbers[j]; Numbers[j]=Numbers[i]; Numbers[i]=h;}
}
}
/* this is the definition of the drawing routine,
which is inserted for the main window with thehelp of the BankedAssign() function.
*/
void test_draw (VOID_PTR view)
{ /* the pointer is really a point to a DESKBOX */PDESKBOX *dsk;
dsk=(PDESKBOX *)view;
int i,y; /* C++ like (variables need not be at function start) */
PDESKBOX_draw(view); /* default, clears the view */SetFontType (PRPFONT14B); /* biggest font available */
unsigned char s[256]; /* for forming the string */
y=dsk->top+40; /* the row of the first string */
for (i=0; i<Ntotal; i++) /* draw all chosen numbers */
if (Numbers[i])
{ /* convert to string and draw */
NumericToStr((double)(i+1),s,DTINTEGER);WriteString(dsk->left+20,y,s,0);
y+=20; /* increment row */
}
}
/* the event handler for the menu commands and for
the main window
*/
void test_handle_event (VOID_PTR view,
unsigned short *evType, unsigned char x, unsigned char y){ /* convert view to deskbox */
PDESKBOX *dsk;
dsk=(PDESKBOX *)view;
/* call default handler (don’t know why) */PDESKBOX_handleEvent(view,evType,x,y);
/* switch events */
if (*evType==evCommand)
{ switch (TOWORD(x,y)){ case cmdNew : /* user wants other numbers */
ClearEvent(evType);
/* event taken */
mix_numbers(); /* shuffle */
dsk->draw(view);
/* redraw window */
break;}
}
}
short main (void)
{/* pointer to the main window (properly destroy it at end) */
PDESKBOX *dsk;
/* init our Lotto numbers */
init_numbers();
randomize();mix_numbers();
/* create a window covering all of the screen
with a menu, a title and a close box */
dsk = (PDESKBOX *)CreateDeskBox(‚A‘,0,0,159,239,
MK_FAR_PTR(test_title),MK_FAR_PTR(MainMenu),0,
bafClose|bafDotTitle);
dsk->options &= ~ofFindable; /* no find in this application */
/* assign the event handlers to this window */
BankedAssign(dsk->handleEvent,test_handle_event);
BankedAssign(dsk->draw,test_draw);
/* seems to generate the main event loop */
ExecView ((PGROUP *) dsk);
/* destroy the window */
Destroy ((VOID_PTR) dsk);
return 0;
}
after only a few hours. Furthermore, the programming style is a bit
different to my favourite Java style, though there are related things.
The compiler is ANSI-C with a few restrictions described in the on-line
help. It has no // comments, but allows variable declarations at every
place in a function. It has a few more keywords like the BANKED
modifier, which marks a function as being available from outside its
16k bank. As you will guess by this memory organization, pointers are
16 Bit wide. So you have to convert pointers to 32 Bit, if you pass
them to system calls. This is done by the MK_FAR_PTR macro.
The main function has no arguments and returns a short. This program
uses main to generate the numbers for the Lotto run, to initialize a DeskBox?
and start the event loop. I won’t comment much on the generation of the
random numbers. There is a random function, which is useful here. Maybe
randomize initializes the random number generator with the Avigo time.
init_numbers();
randomize();mix_numbers();
A DeskBox is an analoge of a window. It may have a title, a menu and a close button, all determined by the CreateDeskBox function arguments. And it has a drawing area. The Avigo SDK calls a DeskBox an object. There is a hierarchie of objects. The grandfather is a PVIEW. This program only uses the DeskBox. I do not understand the rest of the objects at this time.
dsk = (PDESKBOX *)CreateDeskBox(‚A‘,0,0,159,239,
MK_FAR_PTR(test_title),MK_FAR_PTR(MainMenu),0,
bafClose|bafDotTitle);
dsk->options &= ~ofFindable; /* no find in this application */
The second statement makes sure the find button is off while this application runs.
The application then assigns pointers to event handlers for the DeskBox? with the BankedAssign?
function. These handlers must be BANKED functions, because they are
called from outside. The correct way to do this is to declare a
function prototype at the beginning or in a header file. The test_draw
function is the redraw routine for the DeskBox? and the test_handle_event function will handle all events, like pen clicks or menus.
extern BANKED void test_draw (VOID_PTR view);extern BANKED void test_handle_event (VOID_PTR view,
unsigned short *evType, unsigned char x, unsigned char y);
After this preperation, we are ready for the event loop. The event loop is entered with
ExecView ((PGROUP *) dsk);
is triggered by the close button or by the "Exit" menu entry, because I
gave it that value. The menu is defined in an array of MENUITEM
structures. This array is passed as a far pointer to the CreateDeskBox function.
const MENUITEM MainMenu[] =
{ {"New Numbers", cmdNew, 0},
{"Exit", cmCancel, 0},
{"\0", 0, 0}
};
We now discuss the test_draw function.
void test_draw (VOID_PTR view)
{ /* the pointer is really a point to a DESKBOX */
PDESKBOX *dsk;
dsk=(PDESKBOX *)view;
int i,y; /* C++ like (variables need not be at function start) */
PDESKBOX_draw(view); /* default, clears the view */
SetFontType (PRPFONT14B); /* biggest font available */
unsigned char s[256]; /* for forming the string */
y=dsk->top+40; /* the row of the first string */
for (i=0; i<Ntotal; i++) /* draw all chosen numbers */
if (Numbers[i]){ /* convert to string and draw */
NumericToStr((double)(i+1),s,DTINTEGER);
WriteString(dsk->left+20,y,s,0);
y+=20; /* increment row */
}
}
The type name PDESKBOX is somewhat misleading, because it not a pointer
but a structure. We first call the default drawing routine, which will
clear the window. Then we set the font and paint our numbers into the
window. The window margins are with the window bounds and the title
line. There seems to be no way to determine the interior drawing area.
However, it might be save to use absolute constants here. To format a
number, we can use the NumericToStr function.
The test_handle_event routine is very similar.
void test_handle_event (VOID_PTR view,
unsigned short *evType, unsigned char x, unsigned char y)
{ /* convert view to deskbox */
PDESKBOX *dsk;
dsk=(PDESKBOX *)view;
/* call default handler (don’t know why) */
PDESKBOX_handleEvent(view,evType,x,y);
/* switch events */if (*evType==evCommand)
{ switch (TOWORD(x,y))
{ case cmdNew : /* user wants other numbers */
ClearEvent(evType);
/* event taken */
mix_numbers(); /* shuffle */
dsk->draw(view);/* redraw window */
break;
}
}
}
It calls the default event handler by a reason beyond me. Then it
checks for the correct event type. Events are declared invalid by the
ClearEvent routine. This feature is the reason events are passed by a
pointer. The event number is hidden in the x and y parameters, which
might also serve to describe pen events. We simply mix our random
numbers and repaint the DeskBox with its drawing routine.