home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 384.lha / MyClock / MyClock.c < prev    next >
C/C++ Source or Header  |  1990-06-02  |  9KB  |  385 lines

  1. /*
  2.  * MKSoft Mini Clock Face
  3.  *
  4.  * The DoClock() routine is 100% reentrant.  However, it needs
  5.  * GfxBase and IntuitionBase set up for it.
  6.  */
  7.  
  8. #include    <exec/types.h>
  9. #include    <exec/memory.h>
  10. #include    <devices/timer.h>
  11. #include    <graphics/gfx.h>
  12. #include    <graphics/rastport.h>
  13. #include    <intuition/intuition.h>
  14.  
  15. #include    <proto/exec.h>
  16. #include    <proto/intuition.h>
  17. #include    <proto/graphics.h>
  18. #include    <proto/timer.h>
  19.  
  20. /* MKS_WINDOW is the special version that puts the clock exactly where I want it... */
  21. /* #define    MKS_WINDOW    */
  22.  
  23. /* DETATCH_CLOCK is used to add in the Detatch data structures */
  24. /* #define    DETATCH_CLOCK    */
  25.  
  26. /* When testing, I set this to 1 so that I can see the hands move faster */
  27. /* It should be 60 for any real work... */
  28. #define    SECONDS_PER_MINUTE    (60)
  29.  
  30. static short SinArray[16]={0,105,208,309,407,500,588,669,743,809,866,914,951,978,995,1000};
  31.  
  32. void AdjustXY(short Minutes,short *x1,short *y1,short Radius_X,short Radius_Y)
  33. {
  34. register    long    x;
  35. register    long    y;
  36. register    short    tmp;
  37. register    short    tmp1;
  38.  
  39.     tmp1=(15-(tmp=(Minutes % 15)));
  40.  
  41.     if (Minutes<15)
  42.     {
  43.         x=SinArray[tmp];    y=-SinArray[tmp1];
  44.     }
  45.     else if (Minutes<30)
  46.     {
  47.         x=SinArray[tmp1];    y=SinArray[tmp];
  48.     }
  49.     else if (Minutes<45)
  50.     {
  51.         x=-SinArray[tmp];    y=SinArray[tmp1];
  52.     }
  53.     else
  54.     {
  55.         x=-SinArray[tmp1];    y=-SinArray[tmp];
  56.     }
  57.  
  58.     x*=Radius_X;
  59.     y*=Radius_Y;
  60.  
  61.     (*x1)+=(short)((x+((x<0) ? -500 : 500))/1000);
  62.     (*y1)+=(short)((y+((y<0) ? -500 : 500))/1000);
  63. }
  64.  
  65. void DrawArm(struct RastPort *rp,short Minutes,short Radius_X,short Radius_Y,short Center_X,short Center_Y)
  66. {
  67. #ifdef    THIN_LINE
  68.  
  69.     Move(rp,Center_X,Center_Y);
  70.     AdjustXY(Minutes,&Center_X,&Center_Y,Radius_X,Radius_Y);
  71.     Draw(rp,Center_X,Center_Y);
  72.  
  73. #else    /* THIN_LINE */
  74.  
  75. register    short    loop;
  76.         short    x,y;
  77.         short    x1,y1;
  78.  
  79.     x=Center_X;
  80.     y=Center_Y;
  81.  
  82.     AdjustXY(Minutes,&x,&y,Radius_X,Radius_Y);
  83.  
  84.     Move(rp,x,y);
  85.  
  86.     Radius_X=1+(Radius_X >> 4);
  87.     Radius_Y=1+(Radius_Y >> 4);
  88.  
  89.     for (loop=0;loop<3;loop++)
  90.     {
  91.         x1=Center_X;
  92.         y1=Center_Y;
  93.         Minutes=(Minutes+15)%60;
  94.         AdjustXY(Minutes,&x1,&y1,Radius_X,Radius_Y);
  95.         Draw(rp,x1,y1);
  96.     }
  97.  
  98.     Draw(rp,x,y);
  99.  
  100. #endif    /* THIN_LINE */
  101. }
  102.  
  103. void DrawHands(struct RastPort *rp,short Hours,short Minutes,short Center_X,short Center_Y)
  104. {
  105.     DrawArm(rp,(Hours*5)+(Minutes/12),Center_X-5-(Center_X >> 2),Center_Y-5-(Center_Y >> 2),Center_X,Center_Y);
  106.     DrawArm(rp,Minutes,Center_X-4,Center_Y-4,Center_X,Center_Y);
  107. }
  108.  
  109. void DoClock(short LeftEdge,short TopEdge,short Size_X,short Size_Y,UBYTE Face_Pen,UBYTE Hand_Pen,short DragFlag)
  110. {
  111. register    struct    MsgPort        *myport;
  112. register    struct    Window        *window;
  113. register    struct    RastPort    *rp;
  114. register        PLANEPTR    raster;
  115. register        short        ExitFlag=FALSE;
  116. register        short        loop;
  117. register        ULONG        winSig;
  118. register        ULONG        timSig;
  119. register        short        Minutes=0;
  120. register        short        Hours=0;
  121. register        ULONG        tmp;
  122. register        short        Center_X;
  123. register        short        Center_Y;
  124.         struct    timerequest    Time_Req;
  125.         struct    TmpRas        tmpras;
  126.         struct    AreaInfo    AreaInfo;
  127.         struct    NewWindow    NewWin;
  128. #ifndef    MKS_WINDOW
  129.         struct    Gadget        Gad;
  130. #endif    /* MKS_WINDOW */
  131.             short        AreaBuffer[10];
  132.  
  133.     Center_X=((Size_X - 1) >> 1);
  134.     Center_Y=((Size_Y - 1) >> 1);
  135.  
  136. #ifndef    MKS_WINDOW
  137.     Gad.NextGadget=NULL;
  138.     Gad.LeftEdge=0;
  139.     Gad.TopEdge=0;
  140.     Gad.Width=Size_X;
  141.     Gad.Height=Size_Y;
  142.     Gad.Flags=GADGHNONE;
  143.     Gad.Activation=RELVERIFY;
  144.     Gad.GadgetType=WDRAGGING;
  145.     Gad.GadgetRender=NULL;
  146.     Gad.SelectRender=NULL;
  147.     Gad.GadgetText=NULL;
  148.     Gad.MutualExclude=NULL;
  149.     Gad.SpecialInfo=NULL;
  150. #endif    /* MKS_WINDOW */
  151.  
  152.     NewWin.LeftEdge=LeftEdge;
  153.     NewWin.TopEdge=TopEdge;
  154.     NewWin.Width=Size_X;
  155.     NewWin.Height=Size_Y;
  156.     NewWin.IDCMPFlags=VANILLAKEY;
  157.     NewWin.Flags=BORDERLESS|NOCAREREFRESH|RMBTRAP;
  158.  
  159.     NewWin.FirstGadget=NULL;
  160. #ifndef    MKS_WINDOW
  161.     if (DragFlag) NewWin.FirstGadget=&Gad;
  162. #endif    /* MKS_WINDOW */
  163.  
  164.     NewWin.CheckMark=NULL;
  165.     NewWin.Title=NULL;
  166.     NewWin.Screen=NULL;
  167.     NewWin.BitMap=NULL;
  168.     NewWin.Type=WBENCHSCREEN;
  169.  
  170.     if (myport=CreatePort(NULL,NULL))
  171.     {
  172.         timSig=(1L << (myport->mp_SigBit));
  173.         if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)&Time_Req,NULL))
  174.         {
  175.             Time_Req.tr_node.io_Message.mn_ReplyPort=myport;
  176.  
  177.             if (raster=AllocRaster(Size_X,Size_Y))
  178.             {
  179.                 InitTmpRas(&tmpras,(APTR)raster,RASSIZE((ULONG)Size_X,(ULONG)Size_Y));
  180.                 if (window=OpenWindow(&NewWin))
  181.                 {
  182.                     winSig=(1L << (window->UserPort->mp_SigBit));
  183.  
  184.                     /* Get RastPort and set draw modes... */
  185.                     rp=window->RPort;
  186.                     rp->TmpRas=&tmpras;
  187.                     SetAPen(rp,Face_Pen);
  188.                     SetDrMd(rp,JAM1);
  189.  
  190.                     /* Draw the circle */
  191.                     for (loop=0;loop<10;AreaBuffer[loop++]=0);
  192.                     InitArea(rp->AreaInfo=&AreaInfo,(APTR)AreaBuffer,4);
  193.                     AreaEllipse(rp,Center_X,Center_Y,Center_X,Center_Y);
  194.                     AreaEnd(rp);
  195.  
  196.                     /* Draw the hash marks */
  197.                     SetAPen(rp,Hand_Pen);
  198.                     Move(rp,Center_X,1);        Draw(rp,Center_X,3);
  199.                     Move(rp,1,Center_Y);        Draw(rp,3,Center_Y);
  200.                     Move(rp,Center_X,Size_Y-2);    Draw(rp,Center_X,Size_Y-4);
  201.                     Move(rp,Size_X-2,Center_Y);    Draw(rp,Size_X-4,Center_Y);
  202.  
  203.                     while (!ExitFlag)
  204.                     {
  205.                         /* Get current time... */
  206.                         Time_Req.tr_node.io_Command=TR_GETSYSTIME;
  207.                         Time_Req.tr_node.io_Flags=IOF_QUICK;
  208.                         DoIO(&Time_Req.tr_node);
  209.  
  210.                         /* Erase old hands... */
  211.                         SetAPen(rp,Face_Pen);
  212.                         DrawHands(rp,Hours,Minutes,Center_X,Center_Y);
  213.  
  214.                         /* Calculate new time... */
  215.                         tmp=(Time_Req.tr_time.tv_secs)/SECONDS_PER_MINUTE;
  216.                         Minutes=tmp % 60;
  217.                         Hours=(tmp / 60) % 12;
  218.  
  219.                         /* Draw hands new...*/
  220.                         SetAPen(rp,Hand_Pen);
  221.                         DrawHands(rp,Hours,Minutes,Center_X,Center_Y);
  222.  
  223.                         /* Clear possible old timer signal */
  224.                         if ((FindTask(NULL)->tc_SigRecvd)&timSig) Wait(timSig);
  225.  
  226.                         /* Set sleep time... */
  227.                         Time_Req.tr_node.io_Command=TR_ADDREQUEST;
  228.                         Time_Req.tr_time.tv_secs=SECONDS_PER_MINUTE;
  229.                         Time_Req.tr_time.tv_micro=0;
  230.                         SendIO(&Time_Req.tr_node);
  231.  
  232.                         if (Wait(winSig|timSig)&winSig)
  233.                         {
  234.                         register    struct    IntuiMessage    *msg;
  235.  
  236.                             while (msg=(struct IntuiMessage *)GetMsg(window->UserPort))
  237.                             {
  238.                                 if ((msg->Class==VANILLAKEY)&&(msg->Code==0x1B)) ExitFlag=TRUE;
  239.                                 ReplyMsg((struct Message *)msg);
  240.                             }
  241.                             AbortIO((struct IORequest *)&Time_Req);
  242.                         }
  243.                         WaitIO((struct IORequest *)&Time_Req);
  244.                     }
  245.                     CloseWindow(window);
  246.                 }
  247.                 FreeRaster(raster,Size_X,Size_Y);
  248.             }
  249.             CloseDevice((struct IORequest *)&Time_Req);
  250.         }
  251.         DeletePort(myport);
  252.     }
  253. }
  254.  
  255. int CXBRK(VOID) { return(0); }
  256.  
  257. #ifdef    MKS_WINDOW
  258.  
  259. #define    FACE_SIZE_X    (55)
  260. #define    FACE_SIZE_Y    (45)
  261.  
  262. void main(void)
  263. {
  264. #else    /* MKS_WINDOW */
  265.  
  266. #include    <proto/dos.h>
  267. #include    <string.h>
  268. #include    <stdlib.h>
  269.  
  270. #define    FACE_SIZE_X    (45)
  271. #define    FACE_SIZE_Y    (39)
  272. #define    FACE_SIZE_MIN    (19)
  273.  
  274. #define    USAGE_SIZE    102
  275.  
  276. #ifdef    DETATCH_CLOCK
  277.  
  278. /* For CBack.o */
  279. char procname[]="MKSoft Mini-Clock";
  280. long priority=1;
  281. long stack=4000;
  282.  
  283. #else    /* DETATCH_CLOCK */
  284.  
  285. /* Help line.  Only if not DETATCH_CLOCK... */
  286. static char Usage[USAGE_SIZE+1]="Usage: MyClock [LEFT x] [TOP y] [WIDTH x] [HEIGHT y]\n               [FACE c] [HANDS c] [DRAG|NODRAG]\n\n";
  287.  
  288. #endif    /* DETATCH_CLOCK */
  289.  
  290. void main(int argc,char *argv[])
  291. {
  292. register    short    Drag_Flag=TRUE;
  293. register    short    loop;
  294. register    short    error=FALSE;
  295.     struct    Screen    Screen;
  296.         short    LeftEdge;
  297.         short    TopEdge;
  298.         short    Size_X=0;
  299.         short    Size_Y=0;
  300.         short    Face_Pen;
  301.         short    Hand_Pen;
  302. #endif    /* MKS_WINDOW */
  303.  
  304.     if (IntuitionBase=OpenLibrary("intuition.library",33L))
  305.     {
  306.         if (GfxBase=OpenLibrary("graphics.library",33L))
  307.         {
  308. #ifdef    MKS_WINDOW
  309.             DoClock(656-((FACE_SIZE_X-1)>>1),434-FACE_SIZE_Y,FACE_SIZE_X,FACE_SIZE_Y,2,1,FALSE);
  310. #else    /* MKS_WINDOW */
  311.             GetScreenData((CPTR)&Screen,sizeof(struct Screen),WBENCHSCREEN,NULL);
  312.             Size_X=FACE_SIZE_X;
  313.             Size_Y=(Screen.Height < 300) ? FACE_SIZE_MIN : FACE_SIZE_Y;
  314.             LeftEdge=Screen.Width;
  315.             TopEdge=Screen.Height;
  316.             Face_Pen=Screen.BlockPen;
  317.             Hand_Pen=Screen.DetailPen;
  318.  
  319.             if (argc)
  320.             {
  321.             register    char    *c;
  322.             register    short    *change;
  323.  
  324.                 for (loop=1;loop<argc;loop++)
  325.                 {
  326.                     c=argv[loop];
  327.                     if (!stricmp(c,"DRAG")) Drag_Flag=TRUE;
  328.                     else if (!stricmp(c,"NODRAG")) Drag_Flag=FALSE;
  329.                     else if ((loop+1)<argc)
  330.                     {
  331.                         if (!stricmp(c,"LEFT")) change=&LeftEdge;
  332.                         else if (!stricmp(c,"TOP")) change=&TopEdge;
  333.                         else if (!stricmp(c,"WIDTH")) change=&Size_X;
  334.                         else if (!stricmp(c,"HEIGHT")) change=&Size_Y;
  335.                         else if (!stricmp(c,"FACE")) change=&Face_Pen;
  336.                         else if (!stricmp(c,"HANDS")) change=&Hand_Pen;
  337.                         else change=NULL;
  338.                         if (change)
  339.                         {
  340.                             loop++;
  341.                             *change=(short)atol(argv[loop]);
  342.                         }
  343.                         else error=TRUE;
  344.                     }
  345.                     else error=TRUE;
  346.                 }
  347.             }
  348.  
  349.             if (error)
  350.             {
  351. #ifndef    DETATCH_CLOCK
  352.             register    BPTR    out;
  353.  
  354.                 if (out=Output()) Write(out,Usage,USAGE_SIZE);
  355. #endif    /* DETATCH_CLOCK */
  356.             }
  357.             else
  358.             {
  359.                 if (Size_X<FACE_SIZE_MIN) Size_X=FACE_SIZE_MIN;
  360.                 if (Size_Y<FACE_SIZE_MIN) Size_Y=FACE_SIZE_MIN;
  361.  
  362.                 if (Size_X>Screen.Width) Size_X=Screen.Width;
  363.                 if (Size_Y>Screen.Height) Size_Y=Screen.Height;
  364.  
  365.                 if (LeftEdge<0) LeftEdge=0;
  366.                 if ((LeftEdge+Size_X)>Screen.Width) LeftEdge=Screen.Width-Size_X;
  367.  
  368.                 if (TopEdge<0) TopEdge=0;
  369.                 if ((TopEdge+Size_Y)>Screen.Height) TopEdge=Screen.Height-Size_Y;
  370.  
  371.                 if (Face_Pen==Hand_Pen)
  372.                 {
  373.                     Face_Pen=1;
  374.                     Hand_Pen=0;
  375.                 }
  376.  
  377.                 DoClock(LeftEdge,TopEdge,Size_X,Size_Y,(UBYTE)Face_Pen,(UBYTE)Hand_Pen,Drag_Flag);
  378.             }
  379. #endif    /* MKS_WINDOW */
  380.             CloseLibrary((struct Library *)GfxBase);
  381.         }
  382.         CloseLibrary((struct Library *)IntuitionBase);
  383.     }
  384. }
  385.