Zum Inhalt springen

tExas News vom 27. Dezember 1999

René Grothmann hat seine Avigoprogrammierer-Seite leider aufgelassen. Mit seiner freundlichen Unterstützung habe ich nunmehr diese Seiten in tExas integriert. Danke René! Derzeit sind die Seiten so, wie ich sie übernommen habe. Änderungen sind aber möglich. Wenn Ihr also Ideen, Anregungen, etc. habt, so schickt sie mir einfach!!!

Uwe schickte mir folgende email:

Meine Frage an Markus van Griethuijsen (Programmier von AvigoConnect für Lotus) griethu@xs4all.nl war
I waited a long time for this programme. I’m happy that you had produced it and I will express you my praise. Its a very nice tool. Would you send me a Mail if it is possible to send documents from Notes to Avigo? Thank you very much.
Das ist seine Antwort:
I will not update the program anymore, the source is published on the web so I hope someone else will continue.Met vriendelijke groet / With kind regards, Markus van Griethuijsen griethu@xs4all.nl

Die Firma Microbasic Deutschland vertreibt leider nicht mehr die Intellisync - Vollversion. Nach einer Anfrage meinerseits versucht nun PMS-Systems (AvigoPool) http://www.pmssystem.de/avigo.htm die Vertriebsrechte zu erhalten.

René's Avigo Page

tExas bietet der von René Grothmann aufgelassenen Seiten rund um die Programmierung des Avigo (mit seinem Einverständnis) einen neuen Platz.

René’s Avigo Page


I gave up the development for the Avigo some time ago. So please do not expect too much here.
The purpose of this page is to provide support for programmers of the TI Avigo organizer. I will provide sample source code to get you started, help on the way, and complete projects.

Content
Installing and testing the SDK
A first simple project
The Numbers Game (Les Chiffres) (Ver 1.2)
German Hollidays (Feiertage) (Ver. 1.2)
Bridge Display (Ver. 1.1)
Computing the Sunset (Ver. 1.1)

That’s all for now.
René Grothmann

René's Avigo Page: Installing and testing the SDK

Installing and Running the SDK

Buying the SDK

The SDK is a commercial product by Advocet. Go to their Web-Page and get more information. They shipped the SDK to me within seven days. The SDK includes

  • a devoper IDE,
  • a debugger and simulator for Avigo programs,
  • documentation of the Avigo API and the tools.

Installing

I had no problems installing the SDK from the CD-ROM. However, neither the IDE, nor the simulator runs on NT. The IDE claims about an incorrect DLL, and the simulator about lacking VESA support. Advocet should be able to fix both. However, you can use the SDK on Windows NT quite comofortably as described below.

I had a problem on another Windows 95b machine. The installation complained about not being able to replace a MFC library and refuses to let me skip that replacement. So I had to close several running programs (screen manager etc.) before I could go on. Installation on Windows can be a nightmare!

One more problem occured on another Windows 95 machine (with a ATI XPression graphics card). The Simulator mouse destroys the screen picture there. This is probably due to false Vesa drivers.

Maybe it is a good idea to include the p100sdk\bin directory into the path. There is a setenv batch file in p100sdk that sets some environment variables and extends the path (in a very amateurish way). However, I did not need any of this.

Testing

The first thing to do is to start the IDE and open the help. You will see a tutorial section. Follow the instructions. You need to open a new directory and copy the tutorial files, then set up your project and test it. At one point you need to run a batch file in a DOS window, because a bitmap needs to be converted into bin format. Just do it. I did set the environment with p100sdk\setenv.bat before, but that may not be necessary.

You may want to try a simple program, which was the first one I wrote. Got it after a few hours of reading around in the documentation and the tutorial example, and after a considerable bit of trial and error. Too bad that the debug program shows no variable contents. I find most debuggers useless and help myself with variable dumps.

Bugs and Problems

I met a few bugs.

The compiler is somewhat sloppy with checking of code correctness. It will accept code, which cannot be accessed, or labels, which are never used. Thus forgetting the case keyword in a switch statement will be accepted, but not work. Furthermore, there are things like

counter++:

with a ":" instead of a ";". This is accepted as a label. So be careful. Of course, this is not really a bug.

Sometimes, code won’t recompile with strange error messages. Try rebooting the system. Then try deleteing all object files and the *.lin files. If this does not help, try deleteing everything but your sources and bitmap files, and set up a new project.

Imported files might not compile, if you have the wrong line separators. To get that right, copy the files to the clipboard and import them into notepad. This editor seems to fix that problem. I met it only once, when I copied and pasted the file directly from the browser to the IDE.

It is annoying that the code window goes to the beginning of the file at each compiler run. You can use bookmarks to find back to specific points. During compilation the file window will be distorted. Don’t worry. It seems that auto-indent is not functioning properly too. I found no way to help this.

Not Using the IDE

After all, it might be a good idea to use another editor (like my favourite UltraEdit) and call the compiler from it. This is possible by writing a batch file with the following content

path=c:\p100sdk\bin
call make -f
Project.mak

where Project is the name of your project. Then call that command from your editor, which should be able to catch the compiler output. This assumes that the IDE has set up the flash files, the make files and several project settings. The simulator can be started with

c:\p100sdk\bin\falcon

in the directory of your project. Since this does not work on Windows NT, you might want to use the great Freeware Simulator. Thanks to Gerard Vermeugen for this masterpiece! You can use his simulator for development in the following way. You first open the simulator by typing avsim and after setting up the Avigo, go to the system setup page and switch off the display of the startup graphics. Then exit the simulator and copy the RAM file

copy avsim.sav avsim.bak

Create a batch file, which copies the RAM file back before it starts the simulator. E.g.

copy avsim.bak avsim.sav
start avsim

This will give you a fresh simulator. You may install an application with the menu. The menu even contains a list of recenty installed applications. It’s a very good piece of software. I haven’t yet found a bug.

René's Avigo Page: The Lotto Program

The Lotto Program


Lotto.gif



So here is my first application. I tried to keep it simple enough to be understandable, but yet involved enough to show something. You may download and try the complete source here. The included Bitmap is of size 50x52, 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.


Lotto.app 16 kb
lotto.zip 2 kb


Now open a new project and add the C-file as source. Add the bitmap as 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.


Lotto-Capture.jpg

It simply displays 6 numbers randomly chosen out of 49. It has a menu 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 the
help 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;
}


Actually, I do not understand a few things, which is to be expected 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);
It will exit as soon as a cmCancel command event is found. This event 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 */
}
}


As you see, the function gets a void pointer, which is actually a pointer to our "DeskBox?". 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.

This is as much as I understood by now. Hope it helps you. More complex projects will follow.


René Grothmann

René's Avigo Page: The Numbers Game

The Numbers Game - Les Chiffres

This is my second try on the Avigo system. It is actually a port from a Java applet and then again from very old C routines I once wrote. The problem is based on a TV show in french channel one.

Numbers-Capture.jpg

In the above picture, the problem is to form the 179 with 3, 5, 6, 6, 7, and 100 not using any number twice. The allowed operations are +, -, * and /. You can either let the computer solve the problem, and the solution in the captured image has been found by the computer. Or you can try to solve yourself, using the right part of the panel. This is done by selecting two numbers on the list of available numbers and pressing an arithmetic button. Other screen elements are four buttons and one label "New".

The code consists of two header files and two C files. You can download the application with source in zipped form from here: numbers.zip


Screen Layout

The screen layout consists of several elements. Here is a list from the code


PNUMBERFIELD * INumbers[6];
PNUMBERFIELD * ITarget;
PBUTTON * NewProblem;
PBUTTON * NewTarget;
PBUTTON * Solve;
PBUTTON * Retry;
PBUTTON * Plus;
PBUTTON * Minus;
PBUTTON * Div;
PBUTTON * Mult;
PLISTER * List;
PLABEL * Output[5];
PLABEL * New;
The seven top elements are of type NUMBERFIELD. Clicking on one of them displays a number picker, which is a small calculator. The screen is repainted afterwards. It might be possible to save the image below the picker, but I did not find the code for this. I did not want to invest too much time for this application. The code to get and display a number field is this:


/* Generate six number labels at the top */
for (i=0; i<6; i++)
{INumbers[i]=(PNUMBERFIELD *)CreateNumberField(
id++, 5+25*i, row,
(unsigned char *)(Numbers+i),
DTINTEGER, MK_FAR_PTR("Input Number"));
INumbers[i]->right=25+25*i;
LoadBank(&(dsk->insert));
dsk->insertVOID_PTR)dsk,INumbers[i]);
}

/* Generate a target label centered below */
row+=20;
ITarget=(PNUMBERFIELD *)CreateNumberField(
id++, 65, row,
(unsigned char *)(&Target),
DTINTEGER, MK_FAR_PTR("Input Target"
;
ITarget->right=95;
LoadBank(&(dsk->insert));
dsk->insertVOID_PTR)dsk,ITarget);

As you see, there is a row variable, which is allows later insertion or rearrangement of screen elements. I am unsure, if the LoadBank? operations are needed every time. However, they seem not to harm. By the way, the objects are inserted into a DESKBOX object dsk, which is the same as in the Lotto example.

Then we have six labels at the left. These are generated with the CreateLabel function, just as the Number Fields. I won’t explain the buttons either, because they are straightforward. The only change is a command number, which the CreateButton function takes. This number will be used in the event handler.

A more complicate topic is the list of available numbers at the right panel. The Avigo SDk does not support a comfortable list element. It only provides a LISTER object, which reacts on mouse buttons and calls a redraw routine for each item. You have to override both event handlers and take the proper action. My solution is this:



/* event handlers */
extern BANKED void list_writeItem (VOID_PTR view,
unsigned char x, unsigned char y, unsigned short item);
extern BANKED void list_pen (VOID_PTR view,
unsigned char x, unsigned char y);
int Available[6],Marked[6];
int NAvailable;
void setAvailable ()
/* copy numbers from the Numbers field */
{ int i;
for (i=0; i<6; i++)
{ Available[i]=Numbers[i];
Marked[i]=0;
}
NAvailable=6;
}
int nmarked ()
/* get number of marked objects */
{ int i,n=0;
for (i=0; i<NAvailable; i++)
if (Marked[i]) n++;
return n;
}
void list_writeItem (VOID_PTR view,
unsigned char x, unsigned char y, unsigned short item)

/* event handler for writing */
{ char s[16];
PLISTER *p; p=(PLISTER *)view;
if (item>=NAvailable) return;
NumericToStr((double)Available[item],s,DTINTEGER);
SetFontType(PRPFONT11N);
WriteString(x,y,s,Marked[item]);
}
void unmarkall ()

/* unmark all numbers */
{ int i;
for (i=0; i<NAvailable; i++) Marked[i]=0;
}
void list_pen (VOID_PTR view, unsigned char x, unsigned char y)
/* event handler for pen touches */
{ PLISTER *p; p=(PLISTER *)view;
int i;
x=0;
i=(y-p->top)/((p->bottom-p->top)/6);
if (i>=0 && i<NAvailable)
{ if (nmarked()>=2)
{ if (!Marked[i]) unmarkall();
}
Marked[i]=!Marked[i];
}
PLISTER_draw(view);
}
void availableremove (int j)

/* remove number at j from available numbers */
{ int i;
if (j>=NAvailable) return;
for (i=j; i<NAvailable-1; i++)
{ Available[i]=Available[i+1];
Marked[i]=Marked[i+1];
}
NAvailable—;
}
void availableappend (int h)

/* append number h to available nubmers */
{ if (NAvailable>=6) return;
Available[NAvailable]=h;
Marked[NAvailable]=0;
NAvailable++;
}
void available (int command)
/* called from the main event handler (buttons +,-,*,/) */
{ if (nmarked()!=2) return;
int h1,h2,i1,i2,f,i,h;
long L;
f=0;
for (i=0; i<NAvailable; i++)
{ if (Marked[i])
{ if (f) i2=i;
else i1=i;
f++;
}
}
h1=Available[i1]; h2=Available[i2];
if (NAvailable==6) clear();
switch (command)
{ case cmdPlus :
h=h1+h2;
writesolution(6-NAvailable,h1,h2,’+’,h);
break;
case cmdMinus :
if (h1<h2)
{ h=h2-h1;
writesolution(6-NAvailable,h2,h1,’-‘,h);
}
else if (h1>h2)
{ h=h1-h2;
writesolution(6-NAvailable,h1,h2,’-‘,h);
}
break;
case cmdMult :
L=h1*h2;
if (L>30000l) return;
h=h1*h2;
writesolution(6-NAvailable,h1,h2,’*’,h);
break;
case cmdDiv :
if (h1>h2)
{ if (h1%h2!=0) return;
h=h1/h2;
writesolution(6-NAvailable,h1,h2,’/’,h);
}
else if (h1<h2)
{ if (h2%h1!=0) return;
h=h2/h1;
writesolution(6-NAvailable,h2,h1,’/’,h);
}
else if (h1==h2)
{ h=1;
writesolution(6-NAvailable,h2,h1,’/’,h);
}
else return;
}
availableremove(i2);
availableremove(i1);
availableappend(h);
}
This is some code! The last function, however, is already an interface, which connects the +, -, * and / buttons to the available numbers list. So it does not count. You have to assign the handler functions.


List=(PLISTER *)CreateLister?(
id++,95,row,120,row+5*15,6);
LoadBank(&(dsk->insert;
dsk->insertVOID_PTR)dsk,List);
BankedAssign(List->writeItem,list_writeItem);
BankedAssign(List->penDownAct,list_pen);

So you only insert the List field as a complete object.

The last problem is to draw the lines, which seperate the panels. this is done in the panel redraw function.

void test_draw (VOID_PTR view)
{ /* the pointer is really a point to a DESKBOX */
PDESKBOX *dsk;
dsk=(PDESKBOX *)view;
PDESKBOX_draw(view); /* default, clears the view */
DrawLine(0,line1,160,line1,DRAW_BLACK);
DrawLine(0,line2,160,line2,DRAW_BLACK);
DrawLine(80,line1,80,line2,DRAW_BLACK);
}
The line1 and line2 variables are set by the generation routine, which inserts the screen elements from top to bottom.

After a first test, it was clear that a complete redraw of the screen is to slow. So separate redraw functions had to be written for the numbers, the target, the solution and the available number list.


void solution_draw ()
/* redraw the solution strings */
{ int i;
for (i=0; i<5; i++)
{ PVIEW *p;
p=(PVIEW *)Output[i];
FillRect(p->left,p->top,
p->right,p->bottom,
DRAW_WHITE);
PLABEL_draw((VOID_PTR)Output[i]);
}
}
void clearSolution ()

/* clear the solution area and redraw it */
{ clear();
solution_draw();
}
void available_draw ()

/* redraw the available nubmers */
{ PLISTER_draw((VOID_PTR)List);
}
void numbers_draw ()
/* redraw the numbers */
{ int i;
for (i=0; i<6; i++)
PNUMBERFIELD_draw((VOID_PTR)INumbers[i]);
}
void target_draw ()
/* redraw the target number */
{ PNUMBERFIELD_draw((VOID_PTR)ITarget);
}


The Solution strings are contained in the other source file, by the way.

Solving the problem

This routine is ported from the Java version. However, Java on a Pentium 166 detects if any solution within seconds. I did not even bother for multithreading. On the Avigo, detecting that there is no solution takes minutes.

So I tried to make this interruptable by the user. I did it by calling GetEvent? at regular intervals (every 1000 trials). However, this only makes the application slower, since I am catching Timer interrupts only. In the simulator however it works OK. So right now, you can only interrupt the trial by pressing the TODO key. This does not work immediately, but after a while. Switching off and on does not work. The Avigo just resumes the computation. I will try to find a solution for this.

The main problem is the lack of a TestEvent function, which tests for events without waiting for them. There is a TestPutEvent function but it only tests for events that you have put on the event queue. It seems there is a special buffer for one such user put event.

I do switch off the auto power off during computation, and on again after it is finished. So when the user interrupts the computation, its auto power off setting may be switched off. I had not time to investigate this.


Problems I met

I had two bugs, which were very hard to find. One was a missing case statement.

switch (TOWORD(x,y
{ cmdNewProblem :
ClearEvent(evType);
mix(); makeTarget();
PDESKBOX_draw(view);
break;
cmdNewTarget :
ClearEvent(evType);
makeTarget();
PDESKBOX_draw(view);
break;
}
A clever C compiler might issue a warning about two unused labels. But this is one of the reasons, why Java abandoned simple form of goto and label usage. Such errors tend to be very tough to detect.

The second bug was an index out of range. The simulated Avigo fell into the setup routine (tab the screen here and so on), when the function in question was called. This is not exactly a clear error message. Again, such errors are much easier to find in Java.


René Grothmann

tweetbackcheck