/*---------------------------------------------------* | File: VLTIMER.c - Small timer for the Amiga. | | First release: MLO 900513 - Rev. 1.02 MLO 910619 | +---------------------------------------------------+-----* | Author: Maurizio Loreti, aka MLO or I3NOO. | | Address: University of Padova - Department of Physics | | Via F. Marzolo, 8 - 35131 PADOVA - Italy | | Phone: (39)(49) 844-313 FAX: (39)(49) 844-245 | | E-Mail: LORETI at IPDINFN (BITNET); or VAXFPD::LORETI | | (DECnet) - VAXFPD is node 38.257 i.e. 39169; or | | LORETI@PADOVA.INFN.IT (INTERNET). | | Home: Via G. Donizetti 6 - 35010 CADONEGHE (PD) - Italy | *---------------------------------------------------------*/ /** | This program opens a small window with a digital clock/timer in | the VLT custom screen (or in the Workbench screen); the timer can | be reset and you can switch between clock and timer using two | window gadgets. | This program requires the screenshare.library, from Willy Langeveld, | in your LIBS: directory: you can find it on the Fred Fish collection. **/ /** | #include's **/ #include /* Standard library */ #include #include /* Amiga stuff */ #include #include #include #include #include #include "mlo.h" /* My own stuff */ /** | Global variables to detach from CLI **/ long _stack = 4000; char *_procname = "VLTimer"; long _priority = 0; long _BackGroundIO = 0; /** | Global variables to be addressed by Cleanup() **/ struct IntuitionBase *IntuitionBase = NULL; struct GfxBase *GfxBase = NULL; struct Library *ScrSharBase = NULL; struct Screen *pScreen = NULL; struct Window *Window = NULL; /** | Other global variables **/ struct RastPort *pRP; /* VLTimer window raster port */ /** | #define's **/ #define REVISION 33 /* Library revision (Kickstart 1.2) */ #define W_LEFT 470 /* Window left edge */ #define W_TOP 0 /* Window top edge */ #define W_WIDTH 117 /* Window width */ #define W_HEIGHT 22 /* Window height */ #define DETAIL_PEN 0 /* Window detail pen */ #define BLOCK_PEN 1 /* Window block pen */ #define TEXT_X 27 /* Text baseline (x-coordinate) */ #define TEXT_Y 18 /* Text baseline (y-coordinate) */ #define TEXT_FG 3 /* Text foreground pen */ #define TEXT_BG 0 /* Text background pen */ #define NO_TIME 0xFFFFFFFF /* Flag 'no time on screen' */ #define SLATE_DIM 10 /* 'slate' array dimension */ #define DELTA 10 /* Sleep time (DELTA/50 seconds) */ #define W_OFFSET_X (640-W_LEFT) /* Pixels to end of WB screen */ #define ZERO '0' /* ASCII zero */ #define COLON ':' /* ASCII colon */ /** | Gadget definition. **/ USHORT __chip zgData[] = { /* "Zero gadget" nibbles */ 0xFFFF, 0xFC3F, 0xF99F, 0xF91F, 0xF81F, 0xF89F, 0xF99F, 0xF99F, 0xFC3F, 0xFFFF }; USHORT __chip cgData[] = { 0xFFFF, 0xFE7F, 0xFE7F, 0xFE7F, 0xFE7F, /* "Cycle gadget" nibbles */ 0xFE7F, 0xF81F, 0xFC3F, 0xFE7F, 0xFFFF }; struct Image zgImage = { /* "Zero gadget" image */ 0, 0, 16, 10, 1, zgData, 1, 0, NULL }; struct Image cgImage = { /* "Cycle gadget" image */ 0, 0, 16, 10, 1, cgData, 1, 0, NULL }; struct Gadget zg = { /* "Zero gadget" structure */ NULL, 2, 11, 16, 10, GADGHCOMP | GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR) &zgImage, NULL, NULL, 0, NULL, 0, NULL }; struct Gadget cg = { /* "Cycle gadget" structure */ &zg, 98, 11, 16, 10, GADGHCOMP | GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR) &cgImage, NULL, NULL, 0, NULL, 0, NULL }; /** | Timer window definition **/ struct NewWindow NWind = { /* VLTimer window */ W_LEFT, W_TOP, W_WIDTH, W_HEIGHT, DETAIL_PEN, BLOCK_PEN, CLOSEWINDOW | GADGETUP, WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | SMART_REFRESH | NOCAREREFRESH, &cg, NULL, (UBYTE *) "MT", /* i.e. Maurizio's Timer ... */ NULL, NULL, W_WIDTH, W_HEIGHT, W_WIDTH, W_HEIGHT, CUSTOMSCREEN }; /** | ANSI procedures prototypes **/ void Cleanup(int ReturnCode); void *LibOpen(char *Name, long Rev); int NtoA(char *buf, int h, int m, int s); void Setup(void); struct Screen *LockPubScreen(); void UnlockPubScreen(); struct IntuiMessage *GetMsg(); struct Window *OpenWindow(); struct Library *OpenLibrary(); /*--------------* | MAIN PROGRAM | *--------------*/ void _main() { struct IntuiMessage *IMsg; /* Intuition message pointer */ register ULONG SysSecs[2]; /* System time: now, */ register ULONG Start[2]; /* and when the timer was started */ ULONG Last = NO_TIME; /* Last printed time */ char slate[SLATE_DIM]; /* Printing array */ short n; /* Number of characters to print */ ULONG MClass; /* Intuition message class */ struct Gadget *pG; /* Pointer to selected gadget */ register short hour, mins, secs; /* Time */ register short oldSec; /* Last time clock was updated */ register Boolean clock = False; /* Clock/Timer flag */ struct DateStamp ds; /* System time */ /** | First: setup window and timer base **/ Setup(); timer(Start); /** | Infinite loop (exit closing the window). | Check for Intuition event (window closed, or gadget hit) and do | the appropriate action; (reset timer if zero-gadget hit, switch | between timer and clock if cycle-gadget hit). Then ask for current | time and, if the display has changed, update it; then suspend for | a short time. **/ FOREVER { while ((IMsg = GetMsg(Window->UserPort)) != NULL) { MClass = IMsg->Class; pG = (struct Gadget *) IMsg->IAddress; ReplyMsg(IMsg); switch (MClass) { case CLOSEWINDOW: Cleanup(SYS_NORMAL_CODE); case GADGETUP: if (pG == &zg) { timer(Start); } else if (pG == &cg) { if (clock = !clock) { oldSec = -1; } } break; } } if (clock) { DateStamp(&ds); secs = ds.ds_Tick / TICKS_PER_SECOND; if (secs != oldSec) { hour = ds.ds_Minute / 60; mins = ds.ds_Minute % 60; oldSec = secs; n = NtoA(slate, hour, mins, secs); Move(pRP, TEXT_X, TEXT_Y); Text(pRP, slate, n); } } else { timer(SysSecs); *SysSecs -= *Start; if (SysSecs[1] < Start[1]) (*SysSecs)--; if (*SysSecs != Last) { secs = (Last = *SysSecs) % 60; mins = (Last / 60) % 60; hour = (Last / 3600) % 24; n = NtoA(slate, hour, mins, secs); Move(pRP, TEXT_X, TEXT_Y); Text(pRP, slate, n); } } Delay(DELTA); } } void Cleanup( int ReturnCode /* Exit code */ ) { /** | Releases all system resources, then exits. **/ struct IntuiMessage *IMsg; if (Window != NULL) { while ((IMsg = GetMsg(Window->UserPort)) != NULL) { ReplyMsg(IMsg); } CloseWindow(Window); } if (pScreen != NULL) UnlockPubScreen("VLT"); if (ScrSharBase != NULL) CloseLibrary(ScrSharBase); if (GfxBase != NULL) CloseLibrary(GfxBase); if (IntuitionBase != NULL) CloseLibrary(IntuitionBase); exit(ReturnCode); } void *LibOpen( char *Name, /* Library name */ long Rev /* Revision level (or 0) */ ) { /** | Opens required library, at the needed revision level. **/ void *p; if ((p = OpenLibrary(Name, Rev)) == NULL) { Cleanup(SYS_ABORT_CODE); } return p; } int NtoA( char *buf, /* Output buffer */ int h, /* Hours */ int m, /* Minutes */ int s /* Seconds */ ) {/*-------------------------------------------------------* | Instead of sprintf(... "%02d:%02d:%02d" ...); to save | | memory. Returns the number of characters written. | *-------------------------------------------------------*/ char *z = buf; *buf++ = ZERO + ((h / 10) % 10); *buf++ = ZERO + (h % 10); *buf++ = COLON; *buf++ = ZERO + (m / 10); *buf++ = ZERO + (m % 10); *buf++ = COLON; *buf++ = ZERO + (s / 10); *buf++ = ZERO + (s % 10); return (buf - z); } void Setup(void) { /** | Opens required libraries. **/ IntuitionBase = LibOpen("intuition.library", REVISION); GfxBase = LibOpen("graphics.library", REVISION); ScrSharBase = LibOpen("screenshare.library", 0); /** | Open timer window in the VLT custom screen, or in the | Workbench screen (if VLT is on the Workbench, or not | running). **/ if ((pScreen = LockPubScreen("VLT")) == NULL) { NWind.Type = WBENCHSCREEN; } else { NWind.Screen = pScreen; } if ((Window = OpenWindow(&NWind)) == NULL) { Cleanup(SYS_ABORT_CODE); } SetAPen((pRP = Window->RPort), TEXT_FG); SetBPen(pRP, TEXT_BG); SetDrMd(pRP, JAM2); }