home *** CD-ROM | disk | FTP | other *** search
- /* MouseClock.c *************************************************************
- *
- * MouseClock ---- Ein Uhren-Utility, das ausnahmsweise nicht
- * irgendwo auf einem obskuren Bildschirm
- * (meinetwegen auch Workbench-Bildschirm)
- * existiert, sondern sich in der Nähe des
- * Mauszeigers aufhält. Die Position und
- * der Bildschirm, auf dem sich die Anzeige
- * von MouseClock aufhält, ist unabhängig vom
- * Workbench-Bildschirm. Ähnlich wie beim
- * Mauszeiger liegen die Sprites, die Mouseclock
- * zur Anzeige verwendet, immer auf dem vordersten
- * Bildschirm.
- *
- * Besonders stolz (soviel Eitelkeit darf ich
- * mir hoffentlich gönnen) bin ich auf den Interrupt-
- * code, der die Anzeige bewegt. Es hat auf
- * Anhieb geklappt und ist noch nicht ein einziges
- * mal abgeschmiert.
- *
- * Autor --------- Olaf Barthel, ED Electronic Design Hannover
- * Brabeckstraße 35
- * D-3000 Hannover 71
- *
- * Bundesrepublik Deutschland
- *
- * (C) Copyright 1989 by Olaf Barthel &
- * ED Electronic Design Hannover
- *
- ****************************************************************************/
-
- #include <intuition/intuitionbase.h>
- #include <libraries/dosextens.h>
- #include <graphics/gfxbase.h>
- #include <exec/interrupts.h>
- #include <graphics/sprite.h>
- #include <devices/timer.h>
- #include <exec/memory.h>
-
- /* Vorwärtsdeklarationen, um Compiler-Warnungen zu
- * zu vermeiden.
- */
-
- extern struct Library *OpenLibrary();
- extern struct Window *OpenWindow();
- extern struct ViewPort *ViewPortAddress();
- extern struct Message *GetMsg();
- extern struct MsgPort *CreatePort();
- extern struct MsgPort *FindPort();
- extern void *AllocMem();
- extern PLANEPTR AllocRaster();
- extern long AvailMem();
-
- /* Globale Variablen, die zur Handhabung des Displays
- * und des Fensters dienen.
- */
-
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct Window *Window;
- struct IntuiMessage *Massage;
- struct MsgPort *MouseClockPort;
-
- /* Wir orientieren uns zwar nicht am vordersten ViewPort,
- * wenn wir die Sprites setzen, passen aber die Farben
- * der Sprites an, wenn ein Bildschirm weniger als 32
- * Farben hat.
- */
-
- struct ViewPort *VPort;
-
- /* Die beiden Sprites der Anzeige. */
-
- struct SimpleSprite Position1,Position2;
-
- /* Mit diesen Variablen wird später Schrift in die Sprites
- * gedruckt.
- */
-
- struct BitMap PointerBMap;
- struct RastPort PointerRPort;
-
- /* Aktuelle Position des Mauszeigers, soll die Interruptroutine
- * den Mauszeiger bearbeiten?
- */
-
- WORD CurX,CurY,DoPosition = FALSE;
-
- /* Datenspeicher für die Spritedaten. */
-
- UWORD Pointer1Data[(2 + 72) * 2],Pointer2Data[(2 + 72) * 2];
-
- /* Zeichenfarben für Schrift und Hintergrund. */
-
- UBYTE Render[3],Shadow[3];
-
- /* Mit den folgenden Daten werden Fonts zum Zeichnen der
- * Kurzinfo definiert.
- */
-
- struct TextAttr AboutFont[3] =
- {
- {(UBYTE *)"topaz.font",8,FS_NORMAL ,FPF_ROMFONT},
- {(UBYTE *)"topaz.font",8,FSF_BOLD ,FPF_ROMFONT},
- {(UBYTE *)"topaz.font",8,FSF_ITALIC,FPF_ROMFONT}
- };
-
- /* Dies ist die "Kurzinfo", die gezeigt wird, wenn unser
- * Fenster aktiviert worden ist. Der Titlebar des
- * Workbench-Bildschirms wird ein wenig verschönert.
- */
-
- struct IntuiText AboutTxt[4] =
- {
- {3,1,JAM1, 0,1,(struct TextAttr *)&AboutFont[1],(UBYTE *)"MouseClock", (struct IntuiText *)&AboutTxt[ 1]},
- {2,1,JAM1, 88,1,(struct TextAttr *)&AboutFont[2],(UBYTE *)"v1.2", (struct IntuiText *)&AboutTxt[ 2]},
- {2,1,JAM1,128,1,(struct TextAttr *)&AboutFont[0],(UBYTE *)"© 1989 by", (struct IntuiText *)&AboutTxt[ 3]},
- {0,1,JAM1,232,1,(struct TextAttr *)&AboutFont[2],(UBYTE *)"Electronic Design Hannover", (struct IntuiText *)NULL}
- };
-
- /* Bitmapdaten um das ED-Symbol über dem Schließgadget
- * zeichnen zu können.
- */
-
- USHORT ClipMap[40] =
- {
- 0xFFFF,0xF000,0xFFFF,0xF000,0xF001,0xF000,0xF7FF,0xF000,
- 0xFFFF,0xD000,0xF03F,0xD000,0xF7FF,0x9000,0xFFFF,0x3000,
- 0xF000,0x7000,0xFFFF,0xF000,
-
- 0x0000,0x0000,0x1FFF,0x0000,0x3FFF,0x8000,0x3800,0xC000,
- 0x1F80,0xE000,0x3FC0,0xE000,0x3801,0xE000,0x1FFF,0xC000,
- 0x0FFF,0x8000,0x0000,0x0000
- };
-
- /* Zum Einzeichnen des ED-Symbols notwendige Definition. */
-
- struct Image ClipImage =
- {
- 0,0,
- 20,10,2,
- (USHORT *)ClipMap,
- 0x03,0x00,
- (struct Image *)NULL
- };
-
- /* Dieses Fenster wird geöffnet, um u.A. festellen zu
- * können, ob der Anwender das Programm beenden möchte,
- * oder sich die Farbe des Mauszeigers geändert hat.
- */
-
- struct NewWindow NewWindow =
- {
- 561,0,
- 26,10,
- 1,1,
- CLOSEWINDOW | NEWPREFS | REFRESHWINDOW | ACTIVEWINDOW,
- RMBTRAP | WINDOWCLOSE | SIMPLE_REFRESH,
- (struct Gadget *)NULL,
- (struct Image *)NULL,
- (STRPTR)NULL,
- (struct Screen *)NULL,
- (struct BitMap *)NULL,
- 0,0,
- 0,0,
- WBENCHSCREEN
- };
-
- /* Falls sich DMouse irgendwo im Speicher versteckt, borgen
- * wir den DMouse Mousetimeout, um die Sprites rechtzeitig
- * verschwinden zu lassen.
- */
-
- struct DMSFragment
- {
- struct MsgPort Port; /* Globaler Messageport. */
- short Version;/* Aktuelle Version. */
- short Acc; /* Beschleunigung. */
- short AThresh;/* Beschleunigungsschwelle. */
- long STo; /* Screentimeout. */
- long MTo; /* Mousetimeout. */
- };
-
- /* Diese Variablen sind notwendig, wenn man sich vom
- * CLI abkoppeln möchte, von dem man gestartet wird.
- */
-
- long _stack = 4000;
- long _priority = 1;
- long _BackGroundIO = NULL;
- char *_procname = "MouseClock v1.2";
-
- /* Hilfsstrukturen zur Kontrolle des timer.device. */
-
- struct timerequest *tr_TimerRequest= NULL;
- struct MsgPort *tr_TimerPort = NULL;
-
- /* Mit dieser Struktur wird die Routine zum Positionieren
- * der Anzeige in den Vertical Blanking Interrupt gehängt.
- */
-
- struct Interrupt VBlankServer;
-
- /* Da wir diese Symbole noch brauchen, um in einigen
- * Assemblerroutinen herumzukleistern, aber die Assembler-
- * routinen, die gleich folgen werden, diese Symbole für
- * den Compiler nicht sichtbar erzeugen, schustern wir
- * ein wenig herum.
- */
-
- extern void NuCloseScreen();
- extern void HandleVBlank();
-
- /* Hier wird später einmal ein Zeiger auf eine System-
- * routine erscheinen, OpenScreen() um genau zu sein.
- * Dieser Wert wird von SetFunction() zurückgeliefert,
- * wenn wir in den Libraries herumstochern.
- */
-
- long OldCloseScreen;
-
- #asm
- _HandleVBlank: MOVEM.L A2-A6/D2-D7,-(A7) ; Ein paar Register retten
-
- JSR _geta4# ; Adressregister geraderücken
- JSR _MyHandleVBlank ; C-Routine anspringen
-
- CLR.L D0 ; Da wir im Interrupt sind,
- ; muß D0 gelöscht werden.
-
- MOVEM.L (A7)+,A2-A6/D2-D7 ; Die Register restaurieren
-
- RTS ; ...und weiter.
-
- _NuCloseScreen: MOVEM.L D2/D3/A4/A6,-(SP) ; Ein paar Register retten
-
- MOVE.L A0,-(SP) ; Screen-Zeiger als Argument
- ; übernehmen
-
- JSR _geta4# ; Adressregister geraderücken
- JSR _ModifiedCloseScreen ; C-Routine anspringen
-
- ADDQ.L #4,SP ; Stack korrigieren
- MOVE.L D0,A0 ; Screen weiterleiten
-
- MOVE.L _OldCloseScreen,A1 ; Alte Routine merken
-
- MOVEM.L (SP)+,D2/D3/A4/A6 ; Register restaurieren
-
- JMP (A1) ; Alte Routine anspringen
- #endasm
-
- /* ModifiedCloseScreen(Screen) :
- *
- * Ein Patch für die CloseScreen() Routine, damit
- * sich die Interrupt-Routine nicht an Bildschirme
- * heranmacht, die gerade geschlossen werden.
- */
-
- struct Screen *
- ModifiedCloseScreen(Screen)
- struct Screen *Screen;
- {
- /* Bildschirm nach hinten legen. */
-
- ScreenToBack(Screen);
-
- /* Zweimal auf den Durchlauf des Vertical Blanking
- * warten, damit der Handler auch wirklich mitkriegt,
- * daß er einen Bildschirm nicht manipulieren kann,
- * den es in Zehntelsekunden nicht mehr geben wird.
- * Gut, das ist die kompliziertere Methode, aber
- * wenigstens geht sie nicht immer in die Hose,
- * was ohne diesen Patch sehr häufig passiert.
- */
-
- WaitTOF();
- WaitTOF();
-
- /* Man kann ja nicht immer alles auf dem Stack
- * herumliegen lassen, also liefern wir den Zeiger
- * zurück, damit die alte CloseScreen() Routine
- * nicht im Regen steht.
- */
-
- return(Screen);
- }
-
- /* MyHandleVBlank() :
- *
- * Dies ist eine echte Interrupt-Routine in C,
- * ja das gibt es wirklich und es funktioniert
- * sogar. In dieser Routine werden die Sprites
- * bewegt und die Farben gesetzt. Auf diese
- * Weise ist es wesentlich schneller als eine
- * multitaskingfähige Unterroutine, die z.B.
- * auf das timer.device wartet.
- */
-
- void
- MyHandleVBlank()
- {
- /* WER konnte es ahnen, daß Intuition diese
- * Daten auf einen Bildschirm bezieht, der
- * 640 Pixel in X-Richtung und 512 in Y-Richtung
- * besitzt? Es hat mich eine Menge Zeit gekostet,
- * herauszufinden, weshalb sich die Anzeige
- * schneller bewegte als der Mauszeiger selbst,
- * bis ich herausbekam, daß diese Daten
- * nicht für Sprites gedacht sind, die sich nur
- * in Lo-res Schritten bewegen können.
- */
-
- CurX = IntuitionBase -> MouseX >> 1;
- CurY = IntuitionBase -> MouseY >> 1;
-
- /* Falls nötig, werden die Farben der Sprites
- * an den aktuellen Bildschirm angepaßt.
- */
-
- VPort = &IntuitionBase -> FirstScreen -> ViewPort;
-
- /* Na woher wissen wir denn, wie tief der Bildschirm
- * ist? Na, wozu hängt eine RasInfo am ViewPort?
- */
-
- if(VPort -> RasInfo -> BitMap -> Depth < 5)
- {
- SetRGB4(VPort,22,Shadow[0],Shadow[1],Shadow[2]);
- SetRGB4(VPort,21,Render[0],Render[1],Render[2]);
- }
-
- if(DoPosition)
- {
- /* Sprites an die Position rechts neben dem
- * Mauszeiger rücken.
- */
-
- MoveSprite(NULL,&Position1,CurX + 8,CurY);
- MoveSprite(NULL,&Position2,CurX + 24,CurY);
- }
- }
-
- /* AddVBlankServer() :
- *
- * Dies initialisiert eine Struktur, mit deren Hilfe
- * ein Interruptserver in den Vertical Blanking
- * Interrupt eingeklinkt wird.
- */
-
- void
- AddVBlankServer()
- {
- VBlankServer . is_Data = (APTR)NULL;
- VBlankServer . is_Code = HandleVBlank;
- VBlankServer . is_Node . ln_Succ= NULL;
- VBlankServer . is_Node . ln_Pred= NULL;
- VBlankServer . is_Node . ln_Type= NT_INTERRUPT;
- VBlankServer . is_Node . ln_Pri = 0;
- VBlankServer . is_Node . ln_Name= "MouseClock";
-
- /* Herzlichen Dank an Dan Silva, er benutzt eine
- * ähnliche Methode, um DPaint Colourcycling
- * beizubringen. Ich hab's einfach einmal
- * ausprobiert und es lief sofort!
- */
-
- AddIntServer(5,&VBlankServer);
- }
-
- /* RemVBlankServer() :
- *
- * Wirft den Interruptserver wieder aus der Liste
- * der Interrupts.
- */
-
- void
- RemVBlankServer()
- {
- /* Hoffentlich baut Exec keinen Mist und
- * schickt den Server wirklich in die Wüste.
- */
-
- RemIntServer(5,&VBlankServer);
- }
-
- /* OpenTimerDevice() :
- *
- * Öffnet das timer.device für unsere Zwecke.
- */
-
- BOOL
- OpenTimerDevice()
- {
- if(!(tr_TimerPort = (struct MsgPort *)CreatePort(NULL,0)))
- return(FALSE);
-
- if(!(tr_TimerRequest = (struct timerequest *)AllocMem(sizeof(struct timerequest),MEMF_PUBLIC | MEMF_CLEAR)))
- {
- DeletePort(tr_TimerPort);
-
- return(FALSE);
- }
-
- /* Präzisionszeitgeber aktivieren. */
-
- if(OpenDevice(TIMERNAME,UNIT_VBLANK,tr_TimerRequest,0))
- {
- FreeMem(tr_TimerRequest,(long)sizeof(struct timerequest));
- DeletePort(tr_TimerPort);
-
- return(FALSE);
- }
-
- tr_TimerRequest -> tr_node . io_Message . mn_ReplyPort = tr_TimerPort;
- tr_TimerRequest -> tr_node . io_Command = TR_ADDREQUEST;
- tr_TimerRequest -> tr_node . io_Flags = 0;
- tr_TimerRequest -> tr_node . io_Error = 0;
-
- return(TRUE);
- }
-
- /* CloseTimerDevice() :
- *
- * Gibt den angeforderten Speicher frei und schließt das
- * timer.device.
- */
-
- void
- CloseTimerDevice()
- {
- if(tr_TimerRequest)
- {
- CloseDevice(tr_TimerRequest);
- FreeMem(tr_TimerRequest,sizeof(struct timerequest));
- }
-
- if(tr_TimerPort)
- DeletePort(tr_TimerPort);
- }
-
- /* WaitTime(Seconds,Micros) :
- *
- * Wartet eine Zeitperiode.
- */
-
- void
- WaitTime(Seconds,Micros)
- register ULONG Seconds,Micros;
- {
- tr_TimerRequest -> tr_time . tv_secs = Seconds;
- tr_TimerRequest -> tr_time . tv_micro = Micros;
-
- DoIO(tr_TimerRequest);
- }
-
- /* OpenPixel6Font() :
- *
- * Aktiviert einen speziellen, 4 Pixel breiten und
- * 6 Zeilen hohen Zeichensatz, mit dem später in die
- * Sprites gezeichnet wird.
- */
-
- struct TextFont *
- OpenPixel6Font()
- {
- static struct TextFont Pixel6Font;
-
- static long Pixel6Dump[138] =
- {
- 0x04AA2240,0x00002E2E,0xEAEEEEE0,0x0204E4C4,
- 0xCEE6AE2A,0x8AA4C4C6,0xEAAAAAE6,0x864004A2,
- 0x242A4000,0x2A222A88,0x2AA444E2,0x2AAAA888,
- 0xA42A8ECA,0xAAA84AAA,0xAA2482A0,0x04044424,
- 0xE0E04A2E,0xEEEE2EE0,0x08016EC8,0xAEEAE42C,
- 0x8EEACAC4,0x4AAE4444,0x42000008,0x042A4400,
- 0x8A28222A,0x2A2444E2,0x0AAAA88A,0xA4AA8A6A,
- 0x8AA24AAE,0xA4842200,0x040A0240,0x04048E2E,
- 0xE2EE2EE0,0x42044AC4,0xCE86AE4A,0xEAA487AC,
- 0x464AA4E6,0x26000000,0x00000800,0x00000000,
- 0x00008000,0x00000000,0x00000000,0x00000000,
- 0x0000000F,0x00000004,0x00040004,0x00080004,
- 0x00000004,0x00000004,0x000C0004,0x00000004,
- 0x00100004,0x00140004,0x00180004,0x001C0004,
- 0x00200004,0x00240004,0x00280004,0x002C0004,
- 0x00300004,0x00340004,0x00380004,0x003C0004,
- 0x00400004,0x00440004,0x00480004,0x004C0004,
- 0x00500004,0x00540004,0x00580004,0x005C0004,
- 0x00600004,0x00640004,0x00680004,0x006C0004,
- 0x00700004,0x00000004,0x00740004,0x00780004,
- 0x007C0004,0x00800004,0x00840004,0x00880004,
- 0x008C0004,0x00900004,0x00940004,0x00980004,
- 0x009C0004,0x00A00004,0x00A40004,0x00A80004,
- 0x00AC0004,0x00B00004,0x00B40004,0x00B80004,
- 0x00BC0004,0x00C00004,0x00C40004,0x00C80004,
- 0x00CC0004,0x00D00004,0x00D40004,0x00D80004,
- 0x00DC0004,0x00E00004,0x00E40004,0x00E80004,
- 0x00EC0004,0x00540004,0x005400C3,0x66E00000,
- 0x04002C30,0x78303035,0x43303030,0x342C0A09,
- 0x09307830,0x30363030,0x3030342C,0x30783030,
- 0x36343030,0x30342C30,0x78303036,0x38303030,
- 0x342C3078,0x30303643,0x30303034,0x2C0A0909,
- 0x30783030,0x37303030,0x30342C30,0x78303030,
- 0x30303030,0x342C3078,0x30303734,0x30303034,
- 0x2C307830,0x30373830
- };
-
- Pixel6Font . tf_Message . mn_Node . ln_Name = "Pixel.font";
- Pixel6Font . tf_Message . mn_Node . ln_Type = NT_FONT;
- Pixel6Font . tf_Message . mn_Node . ln_Pri = 0;
-
- Pixel6Font . tf_YSize = 6;
- Pixel6Font . tf_Style = 0;
- Pixel6Font . tf_Flags = 66;
- Pixel6Font . tf_XSize = 4;
- Pixel6Font . tf_Baseline = 4;
- Pixel6Font . tf_BoldSmear = 1;
- Pixel6Font . tf_Accessors = 0;
- Pixel6Font . tf_LoChar = 32;
- Pixel6Font . tf_HiChar = 95;
- Pixel6Font . tf_CharData = (APTR)&Pixel6Dump[0];
- Pixel6Font . tf_Modulo = 30;
- Pixel6Font . tf_CharLoc = (APTR)((char *)&Pixel6Dump[0] + (0xC4EE3A - 0xC4ED86));
- Pixel6Font . tf_CharSpace = 0;
- Pixel6Font . tf_CharKern = 0;
-
- return(&Pixel6Font);
- }
-
- /* CloseAll(ReturnCode) :
- *
- * Gibt allen angeforderten Speicher frei, schließt
- * Libraries, Devices, Fenster, etc. und verläßt das
- * Programm.
- */
-
- void
- CloseAll(ReturnCode)
- long ReturnCode;
- {
- register short i;
-
- DoPosition = FALSE;
-
- /* Die beiden Sprites brauchen wir nicht mehr. Deshalb
- * ab in die Wüste damit.
- */
-
- FreeSprite(2);
- FreeSprite(3);
-
- if(Window)
- {
- while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
- ReplyMsg(Massage);
-
- CloseWindow(Window);
- }
-
- /* Bitmapdaten freigeben. */
-
- for(i = 0 ; i < 2 ; i++)
- if(PointerBMap . Planes[i])
- FreeRaster(PointerBMap . Planes[i],16,72);
-
- if(IntuitionBase)
- {
- /* Intuition wieder Kontrolle über die
- * eigenen Routinen geben.
- */
-
- Forbid();
- SetFunction(IntuitionBase,-0x42,OldCloseScreen);
- Permit();
-
- CloseLibrary(IntuitionBase);
- }
-
- if(GfxBase)
- CloseLibrary(GfxBase);
-
- CloseTimerDevice();
-
- /* Den MessagePort, mit dem wir erreichbar waren,
- * schließen.
- */
-
- if(MouseClockPort)
- DeletePort(MouseClockPort);
-
- RemVBlankServer();
-
- exit(ReturnCode);
- }
-
- /* OpenAll() :
- *
- * Öffnet alles, was geöffnet werden muß und
- * bereitet Speicher vor, den wir später brauchen
- * werden.
- */
-
- void
- OpenAll()
- {
- register short i;
-
- if(!(MouseClockPort = (struct MsgPort *)CreatePort("MouseClockPort",0)))
- CloseAll(20);
-
- if(!OpenTimerDevice())
- CloseAll(20);
-
- if(!(IntuitionBase = (VOID *)OpenLibrary("intuition.library",LIBRARY_VERSION)))
- CloseAll(20);
-
- /* Jetzt hängen wir unsere eigene CloseScreen()
- * Routine ins System.
- */
-
- Forbid();
- OldCloseScreen = SetFunction(IntuitionBase,-0x42,NuCloseScreen);
- Permit();
-
- if(!(GfxBase = (VOID *)OpenLibrary("graphics.library",LIBRARY_VERSION)))
- CloseAll(20);
-
- /* Fenster öffnen und richtig plazieren. */
-
- if(!(Window = (struct Window *)OpenWindow(&NewWindow)))
- CloseAll(20);
-
- WindowToBack(Window);
-
- /* Kleine Information, falls das Fenster gerade aktiv ist. */
-
- SetWindowTitles(Window,-1,NULL);
-
- /* ED-Symbol einzeichnen. */
-
- DrawImage(Window -> RPort,&ClipImage,4,0);
-
- /* Sprites initialisieren. */
-
- Position1 . height = 72;
- Position1 . x = 0;
- Position1 . y = 0;
-
- Position2 . height = 72;
- Position2 . x = 0;
- Position2 . y = 0;
-
- if(GetSprite(&Position1,2) < 0)
- CloseAll(20);
-
- if(GetSprite(&Position2,3) < 0)
- CloseAll(20);
-
- /* Mini-Zeichenbereich zum Vorbereiten der Sprites
- * initialisieren.
- */
-
- InitBitMap(&PointerBMap,2,16,72);
- InitRastPort(&PointerRPort);
-
- PointerRPort . BitMap = &PointerBMap;
-
- for(i = 0 ; i < 2 ; i++)
- if(!(PointerBMap . Planes[i] = (PLANEPTR)AllocRaster(16,72)))
- CloseAll(20);
-
- /* Zeichensatz setzen und Zeichenfarbe einstellen. */
-
- SetFont(&PointerRPort,OpenPixel6Font());
-
- SetAPen(&PointerRPort,1);
- SetBPen(&PointerRPort,0);
- SetDrMd(&PointerRPort,JAM1);
-
- DoPosition = TRUE;
-
- /* Jetzt wird die Spritekontrolle aktiviert. */
-
- AddVBlankServer();
- }
-
- /* WhichDate() :
- *
- * Trägt das aktuelle Datum in eine Zeichenkette ein,
- * die später von uns genutzt werden wird.
- */
-
- char *
- WhichDate()
- {
- static char Buff[10];
- struct DateStamp Date;
- long n,Month,Day,Year;
-
- /* Tolle Technik nicht wahr? Stammt von ...äh,
- * Rob Peck... oder, hmm... Tom Rokicki?
- */
-
- DateStamp(&Date);
-
- n = Date . ds_Days - 2251;
- Year = (4 * n + 3) / 1461;
- n -= 1461 * Year / 4;
- Year += 1984;
- Month = (5 * n + 2) / 153;
- Day = n - (153 * Month + 2) / 5 + 1;
- Month += 3;
-
- if(Month > 12)
- {
- Year++;
- Month -= 12;
- }
-
- Year -= 1900;
-
- /* Europäisches Format: Tag. Monat. Jahr */
-
- sprintf(Buff,"%02d-%02d-%02d",Day,Month,Year);
-
- return(Buff);
- }
-
- /* WhichTime() :
- *
- * Trägt die aktuelle Zeit in eine Zeichenkette ein, die
- * wir später verwenden werden.
- */
-
- char *
- WhichTime()
- {
- static char Buff[10];
-
- struct DateStamp TimeStamp;
- long Hours,Minutes,Seconds;
-
- DateStamp(&TimeStamp);
-
- Hours = TimeStamp . ds_Minute / 60;
- Minutes = TimeStamp . ds_Minute % 60;
- Seconds = TimeStamp . ds_Tick / TICKS_PER_SECOND;
-
- /* 24 Stunden-Format. */
-
- sprintf(Buff,"%2d:%02d:%02d",Hours,Minutes,Seconds);
-
- return(Buff);
- }
-
- /* WhichMem(Type) :
- *
- * Trägt den freien Speicher eines Typs in eine
- * Zeichenkette ein, die auch in die Sprites
- * einzeichnet werden wird.
- */
-
- char *
- WhichMem(Type)
- long Type;
- {
- static char Buff[10];
-
- long BlockSize;
-
- BlockSize = AvailMem(Type);
-
- sprintf(Buff,"%8d",BlockSize);
-
- return(Buff);
- }
-
- /* Diese beiden Zeilen schließen zwei Routinen aus,
- * die wir nicht benötigen; es spart zudem ein wenig
- * Speicher.
- */
-
- void _cli_parse(){}
- void _wb_parse(){}
-
- /* MapToSprite(Sprite,BMap) :
- *
- * Wandelt den Inhalt einer Bitmap in ein Array
- * aus UWORDs um, das dem typischen Format eines
- * Hardwaresprites entspricht.
- */
-
- void
- MapToSprite(Sprite,BMap)
- UWORD Sprite[];
- struct BitMap *BMap;
- {
- register short i,j = 0;
- UWORD *Plane[2];
-
- /* Ein Hardwaresprite hat ein recht "drolliges"
- * Format, das sich sonst in keiner anderen
- * Form auf dem Amiga findet:
- *
- * 2 UWORDs für Position und Kontrolldaten
- * n UWORDs für die eigentlich Spritedaten,
- * wobei sich die Daten für beide Planes
- * abwechseln.
- * 2 UWORDs für dubiose Zwecke.
- *
- * Die Daten für das Sprite folgen nicht wie auf
- * dem Amiga üblich blockweise, sondern Zeile
- * für Zeile gemischt.
- */
-
- Plane[0] = (UWORD *)BMap -> Planes[0];
- Plane[1] = (UWORD *)BMap -> Planes[1];
-
- /* Spritedaten löschen. */
-
- for(i = 0 ; i < 72 * 2 ; i++)
- Sprite[2 + i] = 0;
-
- /* Bitplanes in Sprite-Format wandeln. */
-
- for(i = 0 ; i < 72 ; i++)
- for(j = 0 ; j < 2 ; j++)
- Sprite[2 + (2 * i) + j] = Plane[j][i];
- }
-
- /* DoPtrTxt(Y,Txt) :
- *
- * Druckt einen Text in die Bitmap, die hinterher
- * in ein Sprite umgewandelt wird. Um den Kontrast
- * zu steigern, wird noch ein Schatten hinzugefügt.
- */
-
- void
- DoPtrTxt(Y,Txt)
- LONG Y;
- char *Txt;
- {
- /* Schatten einzeichnen. */
-
- Move(&PointerRPort,1,Y + 1);
- SetAPen(&PointerRPort,2);
- Text(&PointerRPort,Txt,4);
-
- /* Schrift einzeichnen. */
-
- Move(&PointerRPort,0,Y);
- SetAPen(&PointerRPort,1);
- Text(&PointerRPort,Txt,4);
- }
-
- /* AdjustColours() :
- *
- * Die Farben der Anzeige von MouseClock sind von den
- * Farben des Mauszeigers abhängig. In dieser Funktion
- * werden sie aus den Preferences herauskopiert.
- */
-
- void
- AdjustColours()
- {
- struct Preferences *Prefs;
- register short i;
-
- /* Puffer anlegen. */
-
- if(Prefs = (struct Preferences *)AllocMem(sizeof(struct Preferences),MEMF_PUBLIC))
- {
- /* Preferences kopieren. */
-
- GetPrefs(Prefs,sizeof(struct Preferences));
-
- /* Schattenfarbe in Komponenten aufsplitten. */
-
- Shadow[0] = ((Prefs -> color18 >> 8) & 0xF);
- Shadow[1] = ((Prefs -> color18 >> 4) & 0xF);
- Shadow[2] = ((Prefs -> color18 ) & 0xF);
-
- /* Zeichenfarbe in Komponenten aufsplitten. */
-
- Render[0] = ((Prefs -> color19 >> 8) & 0xF);
- Render[1] = ((Prefs -> color19 >> 4) & 0xF);
- Render[2] = ((Prefs -> color19 ) & 0xF);
-
- /* Puffer wieder freigeben. */
-
- FreeMem(Prefs,sizeof(struct Preferences));
- }
- }
-
- /* main() :
- *
- * Endlich! Nach soviel Vorbereitung nun schließlich
- * das Hauptprogramm.
- */
-
- void
- main()
- {
- /* Fall MouseClock ein zweites Mal gestartet
- * wird, teilt es dem schon laufenden Task mit, daß
- * er sich entfernen soll. Diese Nachricht wird mit
- * den folgenden Strukturen verschickt.
- */
-
- struct MsgPort *ReplyPort;
- struct Message WakeUp,*Terminate;
-
- struct DMSFragment *DMS = (struct DMSFragment *)FindPort("DMouse");
- LONG MouseTimeout = 4;
-
- /* Zeichenpuffer, um die gewünschten Daten auf zwei
- * Sprites verteilen zu können.
- */
-
- char DateBuff1[5],DateBuff2[5];
- char TimeBuff1[5],TimeBuff2[5];
- char FastBuff1[5],FastBuff2[5];
- char ChipBuff1[5],ChipBuff2[5];
- char *ptr;
-
- /* Letzte Position des Mauszeigers. */
-
- LONG LastX = 0,LastY = 0;
-
- /* Wie oft lief die Prüfschleife schon durch, ohne
- * daß sich der Mauszeiger bewegte und wie
- * oft lief sie schon durch, ohne daß der Inhalt der
- * Sprites verändert werden mußte?
- */
-
- LONG MoveCount = 0,i;
-
- /* Eingabeart, schon wieder so eine Erfindung von =RJ=,
- * was meint ihr, welchen Ärger ich mit ProSuite
- * hatte! Ich habe fast alles noch einmal schreiben
- * müssen, da die Hälfte der Includes zu nichts zu
- * gebrauchen war!
- */
-
- ULONG Class;
-
- /* Falls schon eine MouseClock läuft, wird ihr
- * eine Nachricht zugesandt, die sie dazu veranlassen
- * soll, sich zu entfernen.
- */
-
- if(MouseClockPort = (struct MsgPort *)FindPort("MouseClockPort",0))
- {
- /* Die Rückantwort soll hier eingehen. */
-
- if(!(ReplyPort = (struct MsgPort *)CreatePort(NULL,0)))
- exit(20);
-
- /* Nachricht initialisieren. */
-
- WakeUp . mn_Node . ln_Type = NT_MESSAGE;
- WakeUp . mn_Length = sizeof(struct Message);
- WakeUp . mn_ReplyPort = ReplyPort;
-
- /* An den MessagePort schicken und
- * auf Bestätigung warten.
- */
-
- PutMsg(MouseClockPort,&WakeUp);
- Wait(1 << ReplyPort -> mp_SigBit);
-
- /* Rückantwortsport löschen. */
-
- DeletePort(ReplyPort);
-
- exit(0);
- }
-
- /* Alles öffnen und Farben der Sprites anpassen. */
-
- OpenAll();
- AdjustColours();
-
- FOREVER
- {
- /* Sollen wir uns schon entfernen? */
-
- if(Terminate = (struct Message *)GetMsg(MouseClockPort))
- {
- ReplyMsg(Terminate);
- CloseAll(0);
- }
-
- if(DMS)
- if((MouseTimeout = DMS -> MTo - 1) < 0)
- MouseTimeout = 0;
-
- Class = NULL;
-
- /* Ist irgendetwas am Fenster passiert? */
-
- if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
- {
- Class = Massage -> Class;
-
- ReplyMsg(Massage);
- }
-
- /* Schließgadget gewählt? */
-
- if(Class == CLOSEWINDOW)
- CloseAll(0);
-
- /* Die Farben des Mauszeigers könnten sich
- * geändert haben.
- */
-
- if(Class == NEWPREFS)
- AdjustColours();
-
- /* Das ED-Symbol muß nachgezeichnet werden. */
-
- if(Class == REFRESHWINDOW)
- {
- BeginRefresh(Window);
- DrawImage(Window -> RPort,&ClipImage,4,0);
- EndRefresh(Window,TRUE);
- }
-
- /* Wir wurden aktiviert und melden uns
- * auch gleich.
- */
-
- if(Class == ACTIVEWINDOW)
- {
- PrintIText(Window -> WScreen -> BarLayer -> rp,&AboutTxt[0],4,0);
- DrawImage(Window -> WScreen -> BarLayer -> rp,&ClipImage,210,0);
- }
-
- /* Wenn sich der Mauszeiger seit fünf
- * Sekunden nicht bewegt hat, wird die
- * Anzeige von MouseClock ausgeschaltet.
- * Bewegt sich der Mauszeiger anschließend
- * jedoch wieder, werden die Sprites
- * angeschaltet.
- */
-
- if(CurX != LastX || CurY != LastY)
- {
- /* Sprites wieder anschalten. */
-
- if(MoveCount > MouseTimeout)
- {
- GetSprite(&Position1,2);
- GetSprite(&Position2,3);
-
- DoPosition = TRUE;
- }
-
- MoveCount = 0;
- }
- else
- {
- if((++MoveCount) >= MouseTimeout)
- {
- /* Sprites ausschalten. */
-
- if(MoveCount == MouseTimeout)
- {
- DoPosition = FALSE;
-
- WaitTOF();
- WaitTOF();
-
- FreeSprite(2);
- FreeSprite(3);
- }
-
- continue;
- }
- }
-
- /* Nur um sicherzugehen, daß wir es überhaupt
- * bemerken, wenn sich der Mauszeiger nicht
- * bewegt hat.
- */
-
- LastX = CurX;
- LastY = CurY;
-
- /* Datum abfragen und aufspalten. */
-
- ptr = WhichDate();
-
- for(i = 0 ; i < 4 ; i++)
- {
- DateBuff1[i] = ptr[i];
- DateBuff2[i] = ptr[i + 4];
- }
-
- DateBuff1[4] = DateBuff2[4] = 0;
-
- /* Zeit abfragen und aufspalten. */
-
- ptr = WhichTime();
-
- for(i = 0 ; i < 4 ; i++)
- {
- TimeBuff1[i] = ptr[i];
- TimeBuff2[i] = ptr[i + 4];
- }
-
- TimeBuff1[4] = TimeBuff2[4] = 0;
-
- /* Chip-Ram abfragen und aufspalten. */
-
- ptr = WhichMem(MEMF_CHIP);
-
- for(i = 0 ; i < 4 ; i++)
- {
- ChipBuff1[i] = ptr[i];
- ChipBuff2[i] = ptr[i + 4];
- }
-
- ChipBuff1[4] = ChipBuff2[4] = 0;
-
- /* Fast-Ram abfragen und aufspalten. */
-
- ptr = WhichMem(MEMF_FAST);
-
- for(i = 0 ; i < 4 ; i++)
- {
- FastBuff1[i] = ptr[i];
- FastBuff2[i] = ptr[i + 4];
- }
-
- FastBuff1[4] = FastBuff2[4] = 0;
-
- /* Bitmap löschen und linkes
- * Sprite erzeugen.
- */
-
- SetRast(&PointerRPort,0);
-
- DoPtrTxt(10,TimeBuff2);
- DoPtrTxt(22,DateBuff2);
- DoPtrTxt(34,ChipBuff2);
- DoPtrTxt(46,FastBuff2);
-
- MapToSprite(Pointer2Data,&PointerBMap);
-
- /* Bitmap löschen und rechtes
- * Sprite erzeugen.
- */
-
- SetRast(&PointerRPort,0);
-
- DoPtrTxt(4,"TIME");
- DoPtrTxt(10,TimeBuff1);
-
- DoPtrTxt(16,"DATE");
- DoPtrTxt(22,DateBuff1);
-
- DoPtrTxt(28,"CHIP");
- DoPtrTxt(34,ChipBuff1);
-
- DoPtrTxt(40,"FAST");
- DoPtrTxt(46,FastBuff1);
-
- MapToSprite(Pointer1Data,&PointerBMap);
-
- /* Neue Sprites anzeigen. */
-
- ChangeSprite(NULL,&Position1,Pointer1Data);
- ChangeSprite(NULL,&Position2,Pointer2Data);
-
- /* Eine Zeitperiode warten. */
-
- WaitTime(1,0);
- }
- }
-