Monat: Dezember 1999

  • 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
    FreewareSimulator. 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 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.

    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->insert((VOID_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->insert((VOID_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->insert((VOID_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

  • René’s Avigo Page: German Hollidays (Feiertage)

    German Hollidays
    (Feiertage)

    This application might only be useful in Germany. But I will stay in English here
    nevertheless, since the purpose of this page is to describe the programming aspects of the application. The use
    is self explaining anyway. You find the application with source in
    this
    archive
    .

    The program does not insert the computed days into the calendar, because I do
    not know how to do this. If anybody can do that for me, please help out!

    Here is a screen dump of the application.

    As you can see, I stick with my main layout of a DeskBox with a menu. In this
    deskbox, you will find two objects of type NUMBERSET attached at each other, a button and the output area. The
    code to insert the number tickers and the button is simply

    	/* A number ticker for the year */	_DATE date;
    GetDate(&date);
    PNUMBERSET *Year,*Century;
    int d=date.year+1901;
    century=d/100;
    year=d-century*100;
    Century=(PNUMBERSET *)CreateNumberSet(
    id++,20,30,19,20,1,&century);
    LoadBank(&(dsk->insert));
    dsk->insert((VOID_PTR)dsk,Century);
    Year=(PNUMBERSET *)CreateNumberSet(
    id++,Century->right,30,0,99,1,&year);
    LoadBank(&(dsk->insert));
    dsk->insert((VOID_PTR)dsk,Year);
    computeEastern();

    /* A button to recompute the year */ PBUTTON *Compute; Compute=(PBUTTON *)CreateButton( id++,Year->right+10,30,Year->right+80, MK_FAR_PTR("Berechnen"),cmdCompute,bttBasic); LoadBank(&(dsk->insert)); dsk->insert((VOID_PTR)dsk,Compute); topline=Century->bottom+15;

    The year is initialized with the current year. The range of the first ticker is
    19,20 and the range of the second 0,…,99. This gives a range from 1900 to 2099. The Easter algorithm works for
    other days too, but the Avigo has only this date range and I wanted to use its date computations and output functions
    for simplicity. By the way, the Easter algorithm is from a paper of St. Deschauer. Thanks to him!

    The output is drawn to the screen in a function draw_output. This is called from
    the DESKBOX drawing routine and from the event handler, when the Berechne button is pressed.

    The easter algorithm is this.

    typedef struct _Datum
    { int day;
    int month;
    int year;
    } Datum;

    Datum Eastern;

    void computeEasternGregorian ()
    { int s,m,u,M,N,a,b,c,d,e;
    s=Eastern.year/100-Eastern.year/400-2;
    m=(Eastern.year-100*(Eastern.year/4200))/300-2;
    u=s-m;
    M=(15+u)%30; N=(6+s)%7;
    a=Eastern.year%19; b=Eastern.year%4; c=Eastern.year%7;
    d=(M+19*a)%30;
    e=(N+2*b+4*c+6*d)%7;
    if (d==29)
    { d=28; e=(e+1)%7;
    }
    if (a>=11 && d==28)
    { d=27; e=(e+1)%7;
    }
    Eastern.day=22+d+e;
    if (Eastern.day>31)
    { Eastern.month=4;
    Eastern.day=Eastern.day-31;
    }
    else Eastern.month=3;
    }

    Beware not to take the _DATE structure of the Avigo. This has only fields of type
    char. Then you have to convert these days to int before using them in int computations. Moreover, the year counts
    from 1901 (making 1900 an invalid year). The above algorithm is correct from 1583 on. It is only valid for the
    Western Eastern date. There is another algorithm for the Orthodox church.

    There is not much more to this program. So you should be able to understand the
    program now.


  • René’s Avigo Page: The Bridge Display

    The Bridge Display

    I had some spare hours to write a program that I
    wanted to have on the Avigo. It is sort of a bridge trainer, which deals random
    hands for you and lets you play the hands. Moreover, it can generate random
    hands from sparse descriptions such as AKxxx. The application can be downloaded
    from
    here.
    The
    source
    is also available.

    The display is just big enough for this, as you
    can see in the following hardcopy.

    Usage

    Once you see a hand, you can tap on a card to
    start playing. The program will then draw a rectangle frame around the hand,
    which is to play next. The winner of each trick will be computed and the
    rectangle will go to the winning hand. If the contract is in a suit, you can
    tap on the trump rectangle below the hand to change the trump suit before you

    start playing.

    The menu contains items to undo the last trick,
    or to play the complete hand from start. It also lets you generate a new random
    hand. Before you start playing, you can also turn the hand clockwise.

    A difficult to program feature was generating a
    hand from a hand description. To enter a description, tap on the inpout field
    below. The normal keyboard will open. You might then edit the hand or enter a
    new hand (you can clear the hand description with a menu option). A hand description
    contains several lines, each starting with the hand name (N,O,S,W). Capitalization
    does not matter. You need not provide all hands. You can enter x for
    unimportant small cards. E.g.,

    N AKxxx Kxxx QT KQJ
    S xxx - xxxxx T9xxx

    is a valid hand description. The program will
    compute a hand based on the description, when you choose the corresponding menu
    entry.

    The Source

    The program was sort of a quick hack. For an
    object oriented programmer the rudimentary C of the Avigo is a pain. My pitty
    is with those that program the Avigo in assembler. For this small program
    however, productivity is good enough to get results.

    I probably met some bugs in the C compiler,
    which I overcame by writing very rudimentary C code. E.g. I did not use
    multiple assignments with array members. Also I hard a hard time finding the
    usual programming trapy with = instead of == etc. Anyway, there was some
    strange instability too, which I attribute to the simulator and its inaccurate mouse
    display. Finally the program seemed to run fine.

    For the novice Avigo programmer, it might be
    interesting how I did the card display and the tap recognition. The program
    imports five bitmaps (four suit symbols and one for the ten, which is an icon).
    While drawing the hand, I initialize four arrays (one for each hand) with
    structures, each containing a bounding rectangle for each card and the number
    of the card. When the user tabs on the screen, these rectangles are processed
    to find the card.

    The most critical part was the parser that
    generates hands from descriptions. I did it in one single function, which is
    really not an elegant way to do it. Now that it works, I don’t want to improve
    that design for better readability.

    You will notice a lot of global variables. This
    is not the way to go in a larger project. To me the program looks like a mess. Also
    it is very difficult to keep track of the various states the program is in. For
    this project, the simple approach is good enough though.

    I also had a strange problem with the text
    field. WhenI tried to set a new text, it would only display the first letter. This
    I resolved by starting the creating the object with a hand description and
    clearing it afterwards.

    One more tip! If your simulator hangs (due to an
    eternal loop) break it and press CTRL-F2 to reset it. Then you will not get
    problems after the next compiler run.

  • René’s Avigo Page: The Sun And Moon Calculator

    Sun
    and Moon calculator

    This is a small application computing the sunset
    and sunrise times for any given location, as well as the phase of the moon. The
    methods are low accuracy methods I found in the Internet and as descibed in the
    World Almanac. If you start the program you will find that the Avigo is not
    really a number cruncher. So it takes a while to compute the sunset and rise
    times. Here is a picture from the application as seen in the fabulous freeware
    simulator by G. Vermeugen. See my
    introduction page on tips how
    to use this simulator.

    You can set the local position, which is
    remembered in the application preferences. The default date and time are the
    current ones. The horizon parameter describes the horizon in degrees, which is
    set to -0.8333 for the spherical horizon. Normally, you will use -15 for
    astronomical purposes. Civil twilight ends at -8 degrees. You need to set the
    time zone for your local positions to get the GMT times translated properly.

    You find the application and source code here.

    I needed to program some trigonometric functions
    for this application. So you find sine, cosine and their inverses in the sun
    file. However, all number computations are very slow on the Avigo. Using faster
    algorithms won’t help very much really, but are more work than is rewarding in
    this case. You will also find computations of Julian date in the sun file.

    I actually wanted to do some more astromonical
    things here, but gave up because of the slowness of the double arithmetic.

    There is nothing spectacular about the user
    interface. The only new thing is the saving of preferences, which you will find
    in the main file.

  • tExas News vom 22. Dezember 1999

    Aufgrund der Umstellung auf einen anderen Provider (jetzt habe ich ADSL) gab´s eine Pause bei meinen Infomails.

    Avigo.Web http://www.dominos.purespace.de/avigoweb/ hat ein Update erfahren. Es gibt neue Tips&Tricks sowie auch neue AvigoScreens. Besonders nett finde ich die Fusion zwischen Apple und dem Avigo (Hey Apple, wär das nix, statt einen neuen Newton mit PalmOS einen mit AvigoOS 😉

    Von PMS habe ich eine AvigoPool CD-ROM http://www.pmssystem.de/avigo/avigo_cd.htm bekommen und werde in Kürze einen Testbericht veröffentlichen.

    Die tExasseite wird nächste Woche wieder aktualisiert. Und auch um
    einiges erweitert…….also nicht die nächste Aussendung versäumen.

    Herzlichen Dank für ein weiteres Jahr tExas lesen, Anregungen senden und konstruktive Kritik üben.

    Der Avigo lebt weiter und 2000 wird sicherlich noch ein spannendes Jahr
    mit neuen Applikationen und vielleicht sogar einem neuen oder
    erweiterten AvigoOS.

    Ich wünsche Euch allen ein schönes, friedliches, genüßliches, fröhliches, besinnliches und/oder ausgelassenes Weihnachtsfest.

  • tExas News vom 15. Dezember 1999

    Um mit der Zeit zu gehen (rennen kann man in diesem Fall wirklich nicht
    sagen) und auch ein bißchen layouterisch zu üben (auch nicht sehr
    aufregend habe ich tExas nun auf Frames umgestellt.


    tExas ist weiterhin unter https://web.archive.org/web/20120510182727/http://members.vienna.at:80/lender/avigo/avigo.html erreichbar

    Es gilt aber auch die kürzere Adresse https://web.archive.org/web/20041111040551/http://members.vienna.at:80/lender/avigo/

    Um bei den Umbauarbeiten nicht ganz durcheinanderzukommen habe ich die
    Seite auf dem Stand 27.11.99 belassen. Dieser wird im Laufe der
    nächsten Tage auf den Stand der Zeit gebracht.

    Sollte irgendwas auf der Seite nicht klappen, irgendwelche Links schon
    wieder nicht funktionieren etc. ersuche ich um eine kurze Nachricht.