/***********************************************************************
***
*** CDTV - Write a Bookmark
***
***     Copyright (C) 1990 Commodore-Amiga, Inc.
***     Permission granted for use in CDTV applications.
***     Author: Carl Sassenrath, Ukiah, CA  (30-DEC-90)
***
************************************************************************
***
***     What:
***       This example will create a new bookmark (if one with
***       the same ID does not exist) and write sample data
***       into the bookmark.  It will overwrite an existing
***       bookmark if one is present.
***
***     Notes:
***       1. You will need to obtain a Bookmark Manufacturer
***          identification number from Commodore before creating
***          bookmarks of your own.  This is very easy to do,
***          just call Commodore (CATS).
***       2. Currently tested with Manx C compiler only.
***
***     Please rush bugs, comments, or suggestions to:
***       Carl Sassenrath, P.O. Box 1510, Ukiah, CA 95482
***
***
***********************************************************************/

#include <exec/types.h>
#include <exec/io.h>
#include <devices/bookmark.h>

extern  struct  IOStdReq *CreateStdIO();
extern  struct  MsgPort  *CreatePort();
struct  IOStdReq *IOReq1 = NULL;
struct  MsgPort  *IOPort = NULL;

char    AssertFail[] = "Assertion failed (MUST)";
#define MUST(expr)  if (!(expr)) Quit(AssertFail);

/*
** Bookmark ID
**
**      This is an example ID.  The upper word is the manufacturer id,
**      the lower is the product code.  You will need to use your own
**      manufacturer ID.
*/
#define APP_BOOKMARK    MAKEBID(5,1)

/*
** Bookmark Data
**
**      This is the data structure you wish to use for your bookmark.
**      It can be of any form you desire.
*/
struct  AppStruct
{
        ULONG   AField;
        WORD    BField;
        char    Name[32];
} AppBookmark;

/***********************************************************************
***
***  Main
***
***********************************************************************/
main(argc,argv)
        int argc;
        char *argv[];
{
        printf("CDTV Bookmark Example (30-Dec-90)\n");

        if (argc < 2)
        {
                puts("Usage: bookmark <action>");
                puts("Where <action> is:");
                puts("   W - to write/create a bookmark");
                puts("   R - to read a bookmark");
                puts("   D - to delete a bookmark");
                puts("   M - bookmark memory available");
                puts("   S - maximum bookmark size");
                Quit("missing action");
        }

        Init();

        switch (*argv[1])
        {
        case 'W':
        case 'w':  WriteBookmark(); break;

        case 'R':
        case 'r':  ReadBookmark(); break;

        case 'D':
        case 'd':  DeleteBookmark(); break;

        case 'M':
        case 'm':  AvailBookmark(); break;

        case 'S':
        case 's':  MaxSizeBookmark(); break;

        default:   Quit("invalid action specified");
        }

        Quit(0);
}

/***********************************************************************
***
***  Bookmark Operations
***
***********************************************************************/
WriteBookmark()
{
        int err;

        /* Create the bookmark.... */
        err = DoIOR(IOReq1, BD_CREATE, APP_BOOKMARK, sizeof(AppBookmark), 0);
        if (err) switch (err)
        {
        case BDERR_EXISTS:  puts("Bookmark exists"); break;
        case BDERR_TOOBIG:  Quit("Boomark is too large");
        case BDERR_NOSPACE: Quit("Not enough memory for bookmark");
        default:
                printf("DoIO error: %d\n",err);
                Quit("BD_CREATE failed");
        }
        else puts("Bookmark created");

        /* Write example data to bookmark... */
        AppBookmark.AField = 12345;
        AppBookmark.BField = 1<<10;
        strcpy(AppBookmark.Name,"important string");
        if (DoIOR(IOReq1, CMD_WRITE, 0, sizeof(AppBookmark), &AppBookmark))
                Quit("CMD_WRITE failed");

        puts("Bookmark written");
}

ReadBookmark()
{
        int err;

        err = DoIOR(IOReq1, CMD_READ, 0, sizeof(AppBookmark), &AppBookmark);
        if (err)
        {
                if (err == BDERR_NOMARK) Quit("Bookmark does not exist");
                printf("DoIO error: %d\n",err);
                Quit("CMD_READ failed");
        }

        printf("Bookmark contents: %d 0x%x \"%s\"\n",
                AppBookmark.AField,
                AppBookmark.BField,
                AppBookmark.Name);
}

DeleteBookmark()
{
        int err;

        err = DoIOR(IOReq1, BD_DELETE, 0, 0, 0);
        if (err)
        {
                if (err == BDERR_NOMARK) Quit("Bookmark does not exist");
                printf("DoIO error: %d\n",err);
                Quit("BD_DELETE failed");
        }

        puts("Bookmark deleted");
}

AvailBookmark()
{
        if (DoIOR(IOReq1, BD_AVAIL, 0, 0, 0))
                Quit("BD_AVAIL failed");

        printf("%d bytes available\n",IOReq1->io_Actual);
}

MaxSizeBookmark()
{
        if (DoIOR(IOReq1, BD_MAXSIZE, 0, 0, 0))
                Quit("BD_MAXSIZE failed");

        printf("Maximum bookmark size is %d bytes\n",IOReq1->io_Actual);
}

/***********************************************************************
***
***  Init -- initialize program and structures
***
***********************************************************************/
Init()
{
        MUST(IOPort = CreatePort(0,0));
        MUST(IOReq1 = CreateStdIO(IOPort));

        if (OpenDevice("bookmark.device",APP_BOOKMARK,IOReq1,0))
                Quit("Bookmark device will not open");
}

/***********************************************************************
***
***  Quit -- exit program and clean-up.  Return an error if needed.
***
***********************************************************************/
Quit(s)
        char *s;        /* error message */
{
        if (IOReq1)
        {
                if (IOReq1->io_Device) CloseDevice(IOReq1);
                DeleteStdIO(IOReq1);
        }
        if (IOPort)     DeletePort(IOPort);
        if (s) {printf("\nERROR: %s\n",s); exit(40);}
        else exit(0);
}

/***********************************************************************
***
***  DoIOR -- execute a device command
***
***********************************************************************/
DoIOR(req,cmd,off,len,data)
        struct IOStdReq *req;
        int cmd;
        long off;
        long len;
        APTR data;
{
        req->io_Command = cmd;
        req->io_Offset = off;
        req->io_Length = len;
        req->io_Data   = data;
        return DoIO(req);
}

