home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d09xx
/
d0983.lha
/
TitleClock
/
TitleClock.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-04
|
16KB
|
729 lines
/*
** TitleClock - throw up a clock in the top right
**
** Copyright ⌐1992-94 by Anders Hammarquist, permission granted for
** non-commercial use and distribution. See documentation for further
** information.
**
** $Id: TitleClock.c,v 3.3 94/02/12 16:08:52 Viking Exp Locker: Viking $
**
** $Revision: 3.3 $
** $Date: 94/02/12 16:08:52 $
**
*/
#define __USE_SYSBASE
#include <dos/datetime.h>
#include <dos/dos.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <exec/devices.h>
#include <exec/libraries.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfx.h>
#include <libraries/commodities.h>
#include <devices/timer.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <proto/utility.h>
#include <proto/commodities.h>
#include <proto/timer.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include "titleclock_protos.h"
#include <libraries/locale.h>
#include <proto/locale.h>
/* Stuff */
#define MAXCLOCKLEN 256
#define CLOCKOFFSET 5 /* Number of pixels between screen depth gadget */
/* and clock text */
#define TEMPLATE "UPDATE/N/K,SHOWDATE/S,SHOWDAY/S,SHORTDAY/S,SHOWSECS/S,FORMAT/K,DATEFORMAT/K,PUBSCREEN/K,SCREENPAT/K,FRONTSCREEN/S,DEFSCREEN/S,CX_PRIORITY/N/K"
enum ArgsEnum
{
UPDATE,
SHOWDATE,
SHOWDAY,
SHORTDAY,
SHOWSECS,
FORMAT,
DATEFORMAT,
PUBSCREEN,
SCREENPAT,
FRONTSCREEN,
DEFSCREEN,
CX_PRI,
NUMARGS
};
#ifndef BARDETAILPEN
#define BARDETAILPEN (0x0009)
#define BARBLOCKPEN (0x000A)
#endif
#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)<(b)?(b):(a))
#define tolower(a) ((a)|0x20) /* Quick-and-dirty */
#define isnum(a) (((a)>0x2F)&&((a)<0x3A))
/* From sysiclass docs */
#define LOWDEPTHWIDTH 17
#define HIDEPTHWIDTH 23
/* More stuff */
static struct RastPort *MyRPort=NULL;
static struct BitMap *MyBitMap=NULL;
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct Library *UtilityBase;
struct Library *CxBase;
struct Library *IconBase;
struct Library *TimerBase;
struct LocaleBase *LocaleBase;
struct Locale *Locale;
static const char *Ver="$VER: TitleClock 3.3 (12.2.94)";
static struct NewBroker newbrok =
{
NB_VERSION,
"TitleClock",
"TitleClock",
"Displays clock in screen titlebar",
NBU_UNIQUE|NBU_NOTIFY,
0,
0,
0,
0
};
static LONG Update=1;
static LONG Fmt=FORMAT_DOS;
static LONG Args[NUMARGS] = { (LONG)&Update, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (LONG)&(newbrok.nb_Pri)};
static int LeftEdge;
static char *PubPat=NULL, *ScrPat=NULL;
static struct timerequest *TimerIO=NULL;
static BOOL TimerPending=0, WildPub;
/* Da main routine */
int __saveds TitleClock(void)
{
struct Process *MyProc;
struct WBStartup *WBs=NULL;
struct DiskObject *Do=NULL;
struct MsgPort *CXPort=NULL, *TimerPort=NULL;
struct RDArgs *rdargs=NULL;
CxObj *Broker=NULL;
BOOL TimerFail=TRUE;
int CXSig, TimerSig;
long sig;
CxMsg *CXMsg;
/* set up ExecBase */
SysBase = *((struct ExecBase **)(4L));
if(!((MyProc=(struct Process *)FindTask(NULL))->pr_CLI))
{
/* Started from WB */
/* Get Message */
WaitPort(&(MyProc->pr_MsgPort));
WBs=(struct WBStartup *)GetMsg(&(MyProc->pr_MsgPort));
}
/* Check version */
if(SysBase->LibNode.lib_Version<37) /* Too Old */
goto exit;
/* Open needed libraries */
DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37);
GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37);
IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37);
UtilityBase=OpenLibrary("utility.library",37);
CxBase=OpenLibrary("commodities.library",37);
IconBase=OpenLibrary("icon.library",37);
LocaleBase=(struct LocaleBase *)OpenLibrary("locale.library",38);
if(!(DOSBase&&GfxBase&&IntuitionBase&&UtilityBase&&CxBase&&IconBase))
/* didn't open */
goto cleanup;
if(LocaleBase)
Locale=OpenLocale(NULL);
if(WBs)
{
BPTR oldLock;
oldLock=CurrentDir(WBs->sm_ArgList[0].wa_Lock);
if(Do=GetDiskObject(WBs->sm_ArgList[0].wa_Name))
{
char *ToolValue;
/* Update */
if(ToolValue=FindToolType(Do->do_ToolTypes,"UPDATE"))
StrToLong(ToolValue,&Update);
/* Showdate */
Args[SHOWDATE]=(long)FindToolType(Do->do_ToolTypes,"SHOWDATE");
/* Showday */
Args[SHOWDAY]=(long)FindToolType(Do->do_ToolTypes,"SHOWDAY");
/* Shortday */
Args[SHORTDAY]=(long)FindToolType(Do->do_ToolTypes,"SHORTDAY");
/* Showsecs */
Args[SHOWSECS]=(long)FindToolType(Do->do_ToolTypes,"SHOWSECS");
/* Format */
Args[FORMAT]=(long)FindToolType(Do->do_ToolTypes,"FORMAT");
/* DateFormat */
Args[DATEFORMAT]=(long)FindToolType(Do->do_ToolTypes,"DATEFORMAT");
/* PubScreen */
Args[PUBSCREEN]=(long)FindToolType(Do->do_ToolTypes,"PUBSCREEN");
/* NonPubScreen */
Args[SCREENPAT]=(long)FindToolType(Do->do_ToolTypes,"SCREENPAT");
/* FrontScreen */
Args[FRONTSCREEN]=(long)FindToolType(Do->do_ToolTypes,"FRONTSCREEN");
/* DefScreen */
Args[DEFSCREEN]=(long)FindToolType(Do->do_ToolTypes,"DEFSCREEN");
/* CX_Priority */
if(ToolValue=FindToolType(Do->do_ToolTypes,"CX_PRIORITY"))
StrToLong(ToolValue,&Args[CX_PRI]);
}
CurrentDir(oldLock);
}
else
if(!(rdargs=ReadArgs(TEMPLATE,Args,NULL)))
{
PrintFault(IoErr(),"TitleClock");
goto cleanup;
}
newbrok.nb_Pri=*(int *)Args[CX_PRI];
if(Args[FORMAT])
{
switch(tolower(((char *)Args[FORMAT])[1]))
{
case 'o': /* DOS */
Fmt=FORMAT_DOS;
break;
case 'n': /* International */
Fmt=FORMAT_INT;
break;
case 'm': /* American */
Fmt=FORMAT_USA;
break;
case 'a': /* Canadian */
Fmt=FORMAT_CDN;
break;
}
}
if(Args[PUBSCREEN])
{
int len;
if(PubPat=AllocVec(len=StrLen((char *)Args[PUBSCREEN])*2+2,MEMF_ANY))
{
if((WildPub=ParsePattern((char *)Args[PUBSCREEN],PubPat,len))==-1)
{
FreeVec(PubPat);
PubPat=NULL;
}
}
}
if(Args[SCREENPAT])
{
int len;
if(ScrPat=AllocVec(len=StrLen((char *)Args[SCREENPAT])*2+2,MEMF_ANY))
{
if(ParsePattern((char *)Args[SCREENPAT],ScrPat,len)==-1)
{
FreeVec(ScrPat);
ScrPat=NULL;
}
}
}
/* Args read */
/* Allocate BitMap and RastPort */
if(!(MyBitMap=AllocVec(sizeof(struct BitMap),MEMF_CLEAR|MEMF_PUBLIC)))
goto cleanup;
if(!(MyRPort=AllocVec(sizeof(struct RastPort),MEMF_CLEAR|MEMF_PUBLIC)))
goto cleanup;
InitRastPort(MyRPort);
MyRPort->BitMap=MyBitMap;
/* Set up timer.device */
if(!(TimerPort=CreateMsgPort()))
goto cleanup;
TimerSig= 1L << TimerPort->mp_SigBit;
if(!(TimerIO=(struct timerequest *)
CreateIORequest(TimerPort,sizeof(struct timerequest))))
goto cleanup;
if(TimerFail=OpenDevice("timer.device",UNIT_WAITUNTIL,TimerIO,0))
goto cleanup;
/* Library pointer */
TimerBase=TimerIO->tr_node.io_Device;
/* Init timerequest */
TimerIO->tr_node.io_Command=TR_ADDREQUEST;
TimerIO->tr_time.tv_micro=0;
if(!(CXPort=CreateMsgPort()))
goto cleanup;
CXSig = 1L << CXPort->mp_SigBit;
newbrok.nb_Port=CXPort;
if(!(Broker=CxBroker(&newbrok,NULL)))
goto cleanup;
ActivateCxObj(Broker,1L);
/* Setup done */
{
int Abort=0, Enabled=1;
UpdateClk();
while(!Abort)
{
sig=Wait(CXSig|TimerSig|SIGBREAKF_CTRL_C);
if(sig&TimerSig)
{
if(GetMsg(TimerPort))
{
TimerPending--;
if(Enabled) UpdateClk();
}
}
while(CXMsg=(CxMsg *)GetMsg(CXPort))
{
const int msgid=CxMsgID(CXMsg);
const int msgtype=CxMsgType(CXMsg);
ReplyMsg((struct Message *)CXMsg);
if(msgtype==CXM_COMMAND)
switch(msgid)
{
case CXCMD_DISABLE:
Enabled=0;
ActivateCxObj(Broker,0);
break;
case CXCMD_ENABLE:
Enabled=1;
if(!TimerPending) UpdateClk();
ActivateCxObj(Broker,1);
break;
case CXCMD_KILL:
case CXCMD_UNIQUE:
Abort=1;
}
}
if(sig&SIGBREAKF_CTRL_C) Abort=1;
}
if(TimerPending)
{
if(!CheckIO(TimerIO)) AbortIO(TimerIO);
WaitIO(TimerIO);
}
}
cleanup:
CleanUp();
/* Commodity stuff */
if(Broker)
{
DeleteCxObj(Broker);
while(CXMsg=(CxMsg *)GetMsg(CXPort))
ReplyMsg((struct Message *)CXMsg);
}
if(CXPort) DeleteMsgPort(CXPort);
/* Timer stuff */
if(!TimerFail)
CloseDevice(TimerIO);
if(TimerIO) DeleteIORequest(TimerIO);
if(TimerPort) DeleteMsgPort(TimerPort);
FreeVec(PubPat);
FreeVec(ScrPat);
if(rdargs) FreeArgs(rdargs);
if(Do) FreeDiskObject(Do);
CloseLocale(Locale);
CloseLibrary(LocaleBase);
CloseLibrary(IconBase);
CloseLibrary(UtilityBase);
CloseLibrary(CxBase);
CloseLibrary((struct Library *)IntuitionBase);
CloseLibrary((struct Library *)GfxBase);
CloseLibrary((struct Library *)DOSBase);
exit:
if(WBs)
{
/* Reply WBStartup */
Forbid();
ReplyMsg(WBs);
}
MyProc->pr_Result2=0;
return 0;
}
void __asm SPFunc(register __a0 struct Hook *pHook, register __a1 char pChar)
{
if ((pChar&0x60) && ((int)pHook->h_Data - (int)pHook->h_SubEntry <
MAXCLOCKLEN)) /* Quick-and-dirty isprint() + */
/* make sure that we're not */
/* printing too many chars. */
*((*(char **)&(pHook->h_Data))++)=pChar;
}
/* Print hook */
struct Hook PrintHook =
{
NULL, NULL, /* MinNode */
(ULONG (* )())SPFunc, /* h_Entry, PrintFunc */
NULL, /* h_SubEntry. Dirtily used as pointer for */
/* where the string began. */
NULL /* h_Data, where to put char */
};
/* print date */
int SPrintD(char *Dest, char *Fmt, struct DateStamp *Date)
{
PrintHook.h_SubEntry=(ULONG (* )())(PrintHook.h_Data=Dest);
FormatDate(Locale,Fmt,Date,&PrintHook);
*((char *)PrintHook.h_Data)='\0';
return ((int)((char *)PrintHook.h_Data-Dest)); /* return length of string */
}
/* Display clocks on appropriate screens */
static void DisplayClk(char *clkstr, int clklen, struct Screen *cs)
{
if(AttemptLockLayerRom(cs->BarLayer))
{
struct DrawInfo *dri;
struct TextFont *MyFont;
int i, BltLen;
UWORD FrontPen, BackPen;
WORD dSize;
MyFont=cs->BarLayer->rp->Font; /* No need to 'open' it */
if(MyBitMap->Depth<min(cs->RastPort.BitMap->Depth,8)||MyBitMap->Rows<MyFont->tf_YSize||MyBitMap->BytesPerRow<cs->RastPort.BitMap->BytesPerRow)
{
/* Need 'better' rastport */
FreeVec(MyBitMap->Planes[0]);
InitBitMap(MyBitMap,max(MyBitMap->Depth,min(cs->RastPort.BitMap->Depth,8)),cs->Width,max(MyBitMap->Rows,MyFont->tf_YSize));
if(!(MyBitMap->Planes[0]=AllocVec(MyBitMap->BytesPerRow*MyBitMap->Rows*MyBitMap->Depth,MEMF_CHIP)))
{
MyBitMap->Depth=0;
goto next;
}
for(i=1;i<min(MyBitMap->Depth,8);i++)
MyBitMap->Planes[i]=((UBYTE *)MyBitMap->Planes[i-1])+MyBitMap->BytesPerRow*MyBitMap->Rows;
}
if(dri=GetScreenDrawInfo(cs))
{
if(dri->dri_NumPens>=0x000A)
{
FrontPen=dri->dri_Pens[BARDETAILPEN];
BackPen=dri->dri_Pens[BARBLOCKPEN];
}
else
{
FrontPen=dri->dri_Pens[DETAILPEN];
BackPen=dri->dri_Pens[BLOCKPEN];
}
FreeScreenDrawInfo(cs,dri);
}
/* If we don't get DrawInfo, the pens will be somewhat random */
SetFont(MyRPort,MyFont);
SetDrMd(MyRPort,JAM2);
SetAPen(MyRPort,FrontPen);
SetBPen(MyRPort,BackPen);
SetRast(MyRPort,BackPen);
Move(MyRPort, MyFont->tf_XSize, MyFont->tf_Baseline);
Text(MyRPort, clkstr, clklen);
dSize = (cs->Flags&SCREENHIRES?HIDEPTHWIDTH:LOWDEPTHWIDTH);
LeftEdge = cs->Width - (BltLen=MyRPort->cp_x+CLOCKOFFSET) - dSize;
if(BltLen+dSize>cs->Width)
BltLen=cs->Width-dSize;
ClipBlit(MyRPort,0,0,cs->BarLayer->rp,LeftEdge,1,BltLen,MyFont->tf_YSize,0x0C0);
next:
UnlockLayerRom(cs->BarLayer);
}
}
struct PSList
{
struct PSList *psl_Next;
struct Screen *psl_Screen;
};
static struct PSList *LockPubScreens(UBYTE *Pattern)
{
struct PubScreenNode *psnode;
struct PSList *mylist=NULL, *tmp, *last;
if(psnode=(struct PubScreenNode *)LockPubScreenList())
{
while((psnode=(struct PubScreenNode *)psnode->ln_Succ)->ln_Succ)
{
if(!(psnode->psn_Flags&PSNF_PRIVATE)&&MatchPattern(Pattern,psnode->ln_Name))
{
if(tmp=AllocVec(sizeof(struct PSList),0L))
{
psnode->psn_VisitorCount++;
tmp->psl_Screen=psnode->psn_Screen;
#pragma msg 94 ignore push
if(mylist) last->psl_Next=tmp;
#pragma msg 94 pop
else mylist=tmp;
last=tmp;
}
}
}
tmp->psl_Next=NULL;
UnlockPubScreenList();
}
return mylist;
}
static void UnlockPubScreens(struct PSList *list)
{
struct PSList *tmp;
do {
tmp=list->psl_Next;
UnlockPubScreen(NULL,list->psl_Screen);
FreeVec(list);
}
while(list=tmp);
}
/* Update clock */
static void UpdateClk(void)
{
struct DateTime dt;
static char DispStr[MAXCLOCKLEN];
int StringLen=0;
DateStamp(&dt);
if(!Args[DATEFORMAT] || !LocaleBase)
{
dt.dat_Format = Fmt;
dt.dat_Flags = 0;
dt.dat_StrDay = NULL;
dt.dat_StrDate= NULL;
dt.dat_StrTime= NULL;
DispStr[0]='\0';
if(Args[SHOWDAY])
{
dt.dat_StrDay = DispStr;
DateToStr(&dt);
if(Args[SHORTDAY]) DispStr[3] = '\0';
DispStr[StringLen=StrLen(DispStr)]=' ';
StringLen++;
}
if(Args[SHOWDATE])
{
dt.dat_StrDay = NULL;
dt.dat_StrDate= &DispStr[StringLen];
DateToStr(&dt);
DispStr[StringLen=StrLen(DispStr)]=' ';
StringLen++;
}
dt.dat_StrDate= NULL;
dt.dat_StrTime= &DispStr[StringLen];
DateToStr(&dt);
StringLen=StrLen(DispStr);
if(!Args[SHOWSECS]) StringLen -= 3;
}
else
{
/* Use FormatDate */
StringLen=SPrintD(DispStr,(char *)Args[DATEFORMAT],&dt);
}
/* Now display the things on the right screens */
{
ULONG ILock;
struct Screen *cs;
ILock=LockIBase(0);
/* This is part while the IntuitionBase lock is held not-quite */
/* legal. The AutoDoc says not to call any intuition, */
/* graphics, etc functions while holding the lock, but it */
/* seems to work. My guess is that the warning in the AutoDoc */
/* is to keep people from locking up the machine trying to */
/* draw while someone has a layer locked. If this is the */
/* reason, then the following should not cause any problems */
/* what so ever, since I won't draw unless I get to lock the */
/* layer. If there is some other obscure reason, then this may */
/* cause problems on some systems. But so far I haven't seen */
/* or heard of any problems with it, and it's really the only */
/* way to do what we want to do. Also, we probably hold the */
/* lock for way too long trying to draw the clock on all the */
/* right screens :-) */
cs=IntuitionBase->FirstScreen;
if(cs&&Args[FRONTSCREEN]) /* First Screen */
{
DisplayClk(DispStr,StringLen,cs);
cs=cs->NextScreen;
}
if(ScrPat&&cs) /* Match screen title */
{
do
{
if(cs->DefaultTitle&&MatchPattern(ScrPat,cs->DefaultTitle))
DisplayClk(DispStr,StringLen,cs);
}
while(cs=cs->NextScreen);
}
UnlockIBase(ILock);
/* Public screens */
if(PubPat)
{
if(WildPub)
{
struct PSList *pslist, *psl;
if(psl=pslist=LockPubScreens(PubPat)) {
do {
DisplayClk(DispStr,StringLen,pslist->psl_Screen);
}
while(pslist=pslist->psl_Next);
}
UnlockPubScreens(psl);
}
else
{
if(cs=LockPubScreen((char *)Args[PUBSCREEN]))
{
DisplayClk(DispStr,StringLen,cs);
UnlockPubScreen(NULL,cs);
}
}
}
/* Default public screen */
if(Args[DEFSCREEN]&&(cs=LockPubScreen(NULL)))
{
DisplayClk(DispStr,StringLen,cs);
UnlockPubScreen(NULL,cs);
}
}
/* Rescheduele timer */
GetSysTime(&TimerIO->tr_time);
TimerIO->tr_time.tv_secs+=*(int *)Args[UPDATE];
TimerIO->tr_time.tv_micro=0;
SendIO(TimerIO);
TimerPending++;
}
static void CleanUp(void)
{
if(MyBitMap)
{
FreeVec(MyBitMap->Planes[0]);
FreeVec(MyBitMap);
}
FreeVec(MyRPort);
}
static int StrLen(const char *str)
{
int i;
for(i=0;str[i];i++);
return (i);
}