home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d500 / wiconify.lha / wIconify / wUtilities.lzh / wIconClock / wIconClock.c < prev    next >
C/C++ Source or Header  |  1991-04-19  |  20KB  |  728 lines

  1. /*
  2.  *  WICONCLOCK      A utility that works with WICONIFY to display a
  3.  *                  clock icon on every wIconify screen.  The clock face
  4.  *                  shows the current time, and updates as time passes.
  5.  *
  6.  *  Copyright 1990 by Davide P. Cervone, all rights reserved.
  7.  *  You may use this code, provided this copyright notice is kept intact.
  8.  */
  9.  
  10.  
  11. #define INTUITION_PREFERENCES_H             /* don't need 'em */
  12. #include <intuition/intuitionbase.h>
  13. #include <devices/timer.h>
  14. #include <libraries/dos.h>
  15.  
  16. #include "wIcon.h"
  17.  
  18. static char *Program = "wIconClock v1.1";
  19. static char *Copyright =
  20.    "Copyright (c) 1990 by Davide P. Cervone, all rights reserved";
  21.  
  22.  
  23. struct IntuitionBase *IntuitionBase;
  24. #define INTUITION_REV    0
  25.  
  26. #define DELAYSECS       1       /* How often to look for time changes */
  27. #define DELAYMICS       0
  28.  
  29. #define MAXSCREENS      24      /* Largest number of screens expected */
  30.  
  31.  
  32. #define STANDARD_TIME   1       /* 12 hour clock with AM/PM */
  33. #define MILITARY_TIME   2       /* 24 hour clock */
  34.  
  35. #define EXIT_OK         0L
  36. #define EXIT_ERROR      10L
  37.  
  38. #define REPORTFLAGS     WI_REPORTOPEN| WI_REPORTCLOSE| WI_REPORTAUTOREMOVE
  39.  
  40.  
  41. /*
  42.  *  Clock face image size   
  43.  */
  44.  
  45. #define CLOCKWIDTH      40
  46. #define CLOCKHEIGHT     19
  47. #define CLOCKDEPTH      2
  48. #define WORDSPERROW     3
  49.  
  50.  
  51. static struct timerequest TimerRequest;     /* Timer IO request */
  52. static struct MsgPort *TimerPort;           /* Timer IO reply port */
  53. static int TimerOpen;                       /* TRUE if timer open */
  54. static int TimerSet;                        /* TRUE if request pending */
  55. static int OldPri;                          /* Old process priority */
  56. static APTR ClockTask;                      /* Pointer to this task */
  57. static int TimeType = STANDARD_TIME;        /* Time display type */
  58.  
  59. /*
  60.  *  The clock face image data area
  61.  */
  62. extern USHORT ClockData[CLOCKDEPTH][CLOCKHEIGHT*WORDSPERROW];
  63.  
  64. /*
  65.  *  The clock icon name area
  66.  */
  67. static char ClockName[] = "00:00 AM";
  68.  
  69. /*
  70.  *  The clock icon's image structure
  71.  */
  72. static struct Image ClockImage =
  73.    {0,0, CLOCKWIDTH,CLOCKHEIGHT,CLOCKDEPTH, &ClockData[0][0], 0x03,0, NULL};
  74.  
  75. /*
  76.  *  The clock icon definition
  77.  */
  78. static WICON ClockIcon =
  79.    {&ClockName[0], &ClockImage, NULL,NULL,
  80.     600,15, WI_AUTOREMOVE| WI_NOORGANIZE, REPORTFLAGS, NULL};
  81. static short ClockX,ClockY;
  82.  
  83. static WICONREF *Clock[MAXSCREENS];     /* wIconRefs of all open clocks */
  84. static WICONREF *NewScreenClock;        /* Clock receiving NEWSCREEN reports */
  85. static int ClockCount;                  /* How many are open */
  86.  
  87.  
  88. extern WICONREF *wAddIcon();
  89.  
  90. /*
  91.  *  HandData tells how to draw each hand.  Offset says how far to change
  92.  *  the x position from our current position, and count says how many
  93.  *  pixels in a row to use.  {0,0} ends the list.
  94.  */
  95. struct HandData {BYTE Offset,Count;};
  96.  
  97. /*
  98.  *  The big hand has sixty positions, but these are brocken down into
  99.  *  four sets (15 minute chuncks) which are symmetric either by a
  100.  *  flip horizontally, vertically, or both.
  101.  */
  102.  
  103. static struct HandData BigHand[16][6] =
  104. {
  105.    {{-1,2},{-1,2},{-1,2},{-2,4},{-2,4},{-1,2}},
  106.    {{-1,2},{-1,2},{-1,3},{-1,3},{-1,3},{0,2}},
  107.    {{-1,2},{-1,2},{-1,3},{-1,4},{0,3},{1,2}},
  108.    {{-1,2},{-1,3},{0,3},{0,4},{1,3},{2,2}},
  109.    {{-1,2},{0,2},{1,3},{1,4},{2,4},{4,1}},
  110.    {{-1,2},{0,3},{1,4},{2,4},{4,3},{0,0}},
  111.    {{-1,2},{0,3},{2,3},{3,4},{6,3},{0,0}},
  112.    {{-1,2},{1,2},{3,3},{5,4},{7,3},{0,0}},
  113.    {{-1,2},{1,3},{3,5},{6,4},{0,0},{0,0}},
  114.    {{-1,3},{2,3},{4,4},{7,3},{0,0},{0,0}},
  115.    {{-1,4},{2,4},{5,3},{8,2},{0,0},{0,0}},
  116.    {{-1,5},{4,5},{7,5},{0,0},{0,0},{0,0}},
  117.    {{-1,6},{3,7},{9,4},{0,0},{0,0},{0,0}},
  118.    {{-1,5},{4,8},{0,0},{0,0},{0,0},{0,0}},
  119.    {{-1,9},{8,5},{0,0},{0,0},{0,0},{0,0}},
  120.    {{-1,14},{0,0},{0,0},{0,0},{0,0},{0,0}}
  121. };
  122.  
  123.  
  124. /*
  125.  *  The little hand has positions for each hour and half-hour, and
  126.  *  are brocken down in the same way as the big hand.
  127.  */
  128.  
  129. static struct HandData LittleHand[7][6] =
  130. {
  131.    {{-1,2},{-1,2},{-2,4},{-1,2},{0,0},{0,0}},
  132.    {{-1,2},{-1,3},{-1,3},{0,2},{0,0},{0,0}},
  133.    {{-1,2},{0,3},{1,3},{2,2},{0,0},{0,0}},
  134.    {{-1,3},{0,4},{2,3},{0,0},{0,0},{0,0}},
  135.    {{-1,3},{1,4},{3,4},{0,0},{0,0},{0,0}},
  136.    {{-1,5},{2,5},{0,0},{0,0},{0,0},{0,0}},
  137.    {{-1,9},{0,0},{0,0},{0,0},{0,0},{0,0}}
  138. };
  139.  
  140.  
  141. /*
  142.  *  FreeClocks()
  143.  *
  144.  *  For each clock in the clock array, remove the clock icon from the
  145.  *  screen, and clear its array position.  Decrement the clock count as
  146.  *  we go.
  147.  */
  148.  
  149. static void FreeClocks()
  150. {
  151.    short i;
  152.    
  153.    for (i=0; i<MAXSCREENS && ClockCount; i++)
  154.    {
  155.       if (Clock[i]) wRemoveIcon(Clock[i]);
  156.       Clock[i] = NULL;
  157.       ClockCount--;
  158.    }
  159. }
  160.  
  161.  
  162. /*
  163.  *  Print()
  164.  *
  165.  *  Find the standard AmigaDOS output file and write the output string
  166.  *  to the output file.  This is intended as a substitute for printf()
  167.  *  when no formatting is required, and when you want a small executable.
  168.  */
  169.  
  170. static void Print(s)
  171. char *s;
  172. {
  173.    ULONG OutFile;
  174.    extern ULONG Output();
  175.    
  176.    OutFile = Output();
  177.    if (OutFile && s) Write(OutFile,s,strlen(s));
  178. }
  179.  
  180.  
  181. /*
  182.  *  DoExit()
  183.  *
  184.  *  Print an error message, if one is give, and set the return status.
  185.  *  Return the task priority to normal, and clean up any memory or
  186.  *  other resources that were allocated.
  187.  *  Exit with the correct return status.
  188.  */
  189.  
  190. static void DoExit(message)
  191. char *message;
  192. {
  193.    int status = EXIT_OK;
  194.  
  195.    if (message)
  196.    {
  197.       Print(message);
  198.       Print("\n");
  199.       status = EXIT_ERROR;
  200.    }
  201.    SetTaskPri(ClockTask,OldPri);
  202.    if (TimerSet)            AbortIO(&(TimerRequest.tr_node));
  203.    if (TimerOpen)           CloseDevice(&TimerRequest);
  204.    if (TimerPort)           DeletePort(TimerPort);
  205.    if (ClockCount)          FreeClocks();
  206.    if (ClockIcon.IconPort)  DeletePort(ClockIcon.IconPort);
  207.    if (IntuitionBase)       CloseLibrary(IntuitionBase);
  208.    _exit(status);
  209. }
  210.  
  211. #define ISSPACE(x)      (x == ' ' || x == '\t')
  212. #define NOTSPACE(x)     (x != '\0' && x != ' ' && x != '\t')
  213.  
  214.  
  215. /*
  216.  *  ParseArgs()
  217.  *
  218.  *  If there was a parameter line,
  219.  *  Skip the command (which is the first thing on the line).
  220.  *  Skip any trailing spaces.
  221.  *  Find the end-of-line and remove the new-line character and any
  222.  *    trailing blanks.
  223.  *  While there is more one the line
  224.  *    Find the first space (ie, the end of the word).
  225.  *    Mark the end of the word and skip any trailing spaces.
  226.  *    If the word is one of the time specifiers, save the type,
  227.  *    Otherwise, if the word is a position X,Y then save the position,
  228.  *    Otherwise exit with the usage message.
  229.  *    Continue looking at the rest of the line.
  230.  */
  231.  
  232. static void ParseArgs(line)
  233. char *line;
  234. {
  235.    char *s;
  236.    int X,Y;
  237.  
  238.    if (line)
  239.    {
  240.       while (ISSPACE(*line)) line++;
  241.       while (NOTSPACE(*line)) line++;
  242.       while (ISSPACE(*line)) line++;
  243.       for (s = line; *s && *s != '\n'; s++);
  244.       if (*s) *s = 0; if (s > line) while (*(--s) == ' ') *s = 0;
  245.  
  246.       while (*line)
  247.       {
  248.          s = line; while (NOTSPACE(*s)) s++;
  249.          if (*s)
  250.          {
  251.             *s++ = 0;
  252.             while (ISSPACE(*s)) s++;
  253.          }
  254.          if (stricmp(line,"MILITARY") == 0) TimeType = MILITARY_TIME; else
  255.          if (stricmp(line,"STANDARD") == 0) TimeType = STANDARD_TIME; else
  256.          if (sscanf(line,"%ld,%ld",&X,&Y) == 2)
  257.             ClockX = X, ClockY = Y;
  258.          else DoExit("Usage:  wIconClock [MILITARY | STANDARD] [x,y]");
  259.  
  260.          line = s;
  261.       }
  262.    }
  263. }
  264.    
  265.  
  266. /*
  267.  *  CheckLibOpen()
  268.  *
  269.  *  Call OpenLibrary() for the specified library, and check that the 
  270.  *  open succeeded.
  271.  */
  272.  
  273. static void CheckLibOpen(lib,name,rev)
  274. APTR *lib;
  275. char *name;
  276. int rev;
  277. {
  278.    extern APTR OpenLibrary();
  279.    
  280.    if ((*lib = OpenLibrary(name,(ULONG)rev)) == NULL)
  281.       DoExit("Can't Open Library");
  282. }
  283.  
  284.  
  285. /*
  286.  *  SetupClock()
  287.  *
  288.  *  Get a pointer to the clock task (the current task) and change the
  289.  *    task priority to 5 (so we update the screen a little faster).
  290.  *  Get a port for the clock icons, if possible.
  291.  *  Get a reply port for the timer requests, if possible.
  292.  *  Open the timer device, and initialize the timer request.
  293.  */
  294.  
  295. static void SetupClock()
  296. {
  297.    extern struct MsgPort *CreatePort();
  298.    extern APTR FindTask();
  299.  
  300.    ClockTask = FindTask(NULL);
  301.    OldPri = SetTaskPri(ClockTask,5);
  302.    
  303.    ClockIcon.IconPort = CreatePort(0,0);
  304.    if (ClockIcon.IconPort == NULL) DoExit("Can't Create Icon Port\n");
  305.  
  306.    TimerPort = CreatePort(0,0);
  307.    if (TimerPort == NULL) DoExit("Can't Create Timer Port\n");
  308.  
  309.    if (OpenDevice(TIMERNAME,UNIT_VBLANK,&TimerRequest,0) != NULL)
  310.       DoExit("Can't Open Timer Device");
  311.    TimerRequest.tr_node.io_Message.mn_ReplyPort = TimerPort;
  312.    TimerRequest.tr_node.io_Command = TR_ADDREQUEST;
  313.    TimerRequest.tr_node.io_Flags = 0;
  314.    TimerOpen = TRUE;
  315. }
  316.  
  317.  
  318. /*
  319.  *  UpdateTime()
  320.  *
  321.  *  Set the time string to the proper characters for the specified 
  322.  *  time display type.  Trim the initial zero if the hour is only
  323.  *  one digit long.
  324.  */
  325.  
  326. static void UpdateTime(s,h,m)
  327. char s[];
  328. short h,m;
  329. {
  330.    switch(TimeType)
  331.    {
  332.       case STANDARD_TIME:
  333.          s[5] = ' ';
  334.          s[6] = (h >= 12)? 'P': 'A';
  335.          h = h % 12; if (h == 0) h = 12;
  336.          break;
  337.  
  338.       case MILITARY_TIME:
  339.          s[5] = 0;
  340.          break;
  341.    }
  342.    s[0] = '0' + (h / 10);
  343.    s[1] = '0' + (h % 10);
  344.    s[2] = ':';
  345.    s[3] = '0' + (m / 10);
  346.    s[4] = '0' + (m % 10);
  347.    if (s[0] == '0') s++;
  348.    ClockIcon.Name = s;
  349. }
  350.  
  351.  
  352. /*
  353.  *  UpdateHand()
  354.  *
  355.  *  dx and dy specify the direction we are moving on the clock face,
  356.  *  Hand is the hand array of the particular position we are using,
  357.  *  SetIt specifies whether we are adding or removing the hand.
  358.  *
  359.  *  Start at the center of the clock.
  360.  *  For each {offset,count} pair,
  361.  *    Get the offset and count.
  362.  *    If there is anything to do,
  363.  *      Set the mask to the correct number of bits.
  364.  *      Shift the mask by the correct offset for the dx direction.
  365.  *      Divide the mask into three parts (one for each word in a row of
  366.  *        the clock image data).
  367.  *      If we are adding the had, clear those bits (to make the pen color 2)
  368.  *      Otherwise set them (to make the pen color 3).
  369.  *    Increment the y position in the correct direction.
  370.  */
  371.  
  372. static void UpdateHand(dx,dy,Hand,SetIt)
  373. short dx,dy;
  374. struct HandData *Hand;
  375. int SetIt;
  376. {
  377.    short y = (CLOCKHEIGHT-1)/2 * WORDSPERROW;
  378.    short i;
  379.    ULONG mask;
  380.    UWORD m1,m2,m3;
  381.    short count,offset;
  382.    
  383.    for (i=0; i<6; i++)
  384.    {
  385.       count  = Hand[i].Count;
  386.       offset = Hand[i].Offset;
  387.       if (count)
  388.       {
  389.          mask = ((1 << count) - 1);
  390.          mask <<= (dx < 0)? (16 + offset): (16 - count - offset);
  391.          m1 =  mask >> (CLOCKWIDTH/2);
  392.          m2 = (mask >> (16 - (32-(CLOCKWIDTH/2)))) & 0xFFFF;
  393.          m3 = (mask <<       (32-(CLOCKWIDTH/2)) ) & 0xFFFF;
  394.          if (SetIt)
  395.          {
  396.             ClockData[0][y]   &= ~m1;
  397.             ClockData[0][y+1] &= ~m2;
  398.             ClockData[0][y+2] &= ~m3;
  399.          } else {
  400.             ClockData[0][y]   |=  m1;
  401.             ClockData[0][y+1] |=  m2;
  402.             ClockData[0][y+2] |=  m3;
  403.          }
  404.       }
  405.       y += dy;
  406.    }
  407. }
  408.  
  409.  
  410. /*
  411.  *  UpdateFace()
  412.  *
  413.  *  Get the proper quadrant for the position of the big hand for the current
  414.  *  time, and update the big hand.
  415.  *  Now get the correct quadrant for the little hand:
  416.  *    shift the minutes by 15 mintes since we want the little hand to
  417.  *    change at a quarter after and a quarter of - that way the be one the
  418.  *    hour from a quarter of to a quarter after, and on the half hour from
  419.  *    a quarter after to a quarter to.
  420.  *    Take the hour modulo 12 and multiply by two (every other hand is the
  421.  *    hour position).  If the minutes are in the half-hour range, increment
  422.  *    to the half-hour position.
  423.  *    Finally, reduce by quadrants, as before.
  424.  *  Update the clock face.
  425.  */
  426.  
  427. static void UpdateFace(h,m,SetIt)
  428. short h,m;
  429. int SetIt;
  430. {
  431.    short dx,dy;
  432.    short m1 = m;
  433.    
  434.    dx = 1; dy = -WORDSPERROW;
  435.    if (m > 30) m -= 30, dx = -1, dy = WORDSPERROW;
  436.    if (m > 15) m = 30 - m, dy = -dy;
  437.    UpdateHand(dx,dy,&BigHand[m][0],SetIt);
  438.    
  439.    m1 += 15; if (m1 >= 60) m1 -= 60, h++;
  440.    h %= 12; h *= 2; if (m1 > 29) h++;
  441.    dx = 1; dy = -WORDSPERROW;
  442.    if (h > 12) h -= 12, dx = -1, dy = WORDSPERROW;
  443.    if (h > 6) h = 12 - h, dy = -dy;
  444.    UpdateHand(dx,dy,&LittleHand[h][0],SetIt);
  445. }
  446.  
  447.  
  448. /*
  449.  *  UpdateClocks()
  450.  *
  451.  *  Clear the clock position so the icons will remain where they are.
  452.  *  For each clock that has been openned,
  453.  *    Update the clock to the new face iamge,
  454.  *    If the clock is the one receiving NEWSCREEN reports, add its report flags.
  455.  */
  456.  
  457. static void UpdateClocks()
  458. {
  459.    short i,count;
  460.  
  461.    ClockIcon.x = ClockIcon.y = 0;
  462.    for (i=0, count=ClockCount; i<MAXSCREENS && count; i++)
  463.    {
  464.       if (Clock[i])
  465.       {
  466.          wUpdateIcon(Clock[i],&ClockIcon); count--;
  467.          if (Clock[i] == NewScreenClock)
  468.             wModifyReport(Clock[i],REPORTFLAGS | WI_REPORTNEWSCREEN);
  469.       }
  470.    }
  471. }
  472.  
  473.  
  474. /*
  475.  *  SetNewScreenClock()
  476.  *
  477.  *  We only want one clock to report NEWSCREEN events, otherwise we would
  478.  *  be adding too many new clocks as new screens open (one for each clock
  479.  *  already open).  So only the first clock in the list is marked to
  480.  *  receive NEWSCREEN message.
  481.  *
  482.  *  Skip any blank array elements, and if we have found a clock,
  483.  *  mark it to receive NEWSCREEN messages.
  484.  */
  485.  
  486. static void SetNewScreenClock()
  487. {
  488.    short i;
  489.    
  490.    for (i=0; i<MAXSCREENS && Clock[i] == NULL; i++);
  491.    if (i < MAXSCREENS)
  492.    {
  493.       wModifyReport(Clock[i],REPORTFLAGS | WI_REPORTNEWSCREEN);
  494.       NewScreenClock = Clock[i];
  495.    }
  496. }
  497.  
  498.  
  499. /*
  500.  *  FinishClock()
  501.  *
  502.  *  Look through the clock list for the given clock,
  503.  *  If found,
  504.  *    Clear the array element for re-use, and cancel the loop.
  505.  *    Decrement the clock count, and if this is the last one, we're done.
  506.  *    If the clock was the one receiving NEWSCREEN messages, we need to choose
  507.  *      another one to get them.
  508.  */
  509.  
  510. static int FinishClock(theClock)
  511. WICONREF *theClock;
  512. {
  513.    short i;
  514.    int NotDone = TRUE;
  515.    
  516.    for (i=0; i<MAXSCREENS; i++)
  517.    {
  518.       if (Clock[i] == theClock)
  519.       {
  520.          Clock[i] = NULL; i = MAXSCREENS;
  521.          if (--ClockCount == 0) NotDone = FALSE; else
  522.          if (theClock == NewScreenClock) SetNewScreenClock();
  523.       }
  524.    }
  525.    return(NotDone);
  526. }
  527.  
  528.  
  529. /*
  530.  *  NewClock()
  531.  *
  532.  *  If we can add more clocks,
  533.  *    Look through the clock array for an open spot.
  534.  *    If we found a spot,
  535.  *      Set the clock position:  if it was specified on the command line,
  536.  *        use that, otherwise back it near the upper right.
  537.  *      Add the clock to the new screen.
  538.  *      If the add was successful, increment the clock count.
  539.  *      End the search loop.
  540.  */
  541.  
  542. static void NewClock(theScreen)
  543. struct Screen *theScreen;
  544. {
  545.    short i;
  546.    
  547.    if (ClockCount < MAXSCREENS)
  548.    {
  549.       for (i=0; i<MAXSCREENS; i++)
  550.       {
  551.          if (Clock[i] == NULL)
  552.          {
  553.             if (ClockX || ClockY)
  554.             {
  555.                ClockIcon.x = ClockX;
  556.                ClockIcon.y = ClockY;
  557.             } else {
  558.                ClockIcon.x = theScreen->Width - CLOCKWIDTH - 12;
  559.                ClockIcon.y = 15;
  560.             }
  561.             Clock[i] = wAddIcon(theScreen,&ClockIcon);
  562.             if (Clock[i]) ClockCount++;
  563.             i = MAXSCREENS;
  564.          }
  565.       }
  566.    }
  567. }
  568.  
  569.  
  570. /*
  571.  *  CreateClocks()
  572.  *
  573.  *  Look through the Intuition screen list, and save the screen
  574.  *  pointers (we do this because we don't want te list to change while
  575.  *  we're looking at it, but we can't add icons as we go, since we
  576.  *  will enter a Wait() state which may allow other tasks to change
  577.  *  the screen list).
  578.  *  For each pointer found, try to add a clock the that screen.
  579.  *  Get a clock to receive NEWSCREEN messages.
  580.  */
  581.  
  582. static void CreateClocks()
  583. {
  584.    struct Screen *Screen[MAXSCREENS];
  585.    struct Screen *theScreen;
  586.    short i = 0;
  587.    int ILock;
  588.    
  589.    ILock = LockIBase(0L);
  590.    theScreen = IntuitionBase->FirstScreen;
  591.    while (theScreen)
  592.    {
  593.       Screen[i++] = theScreen;
  594.       theScreen = theScreen->NextScreen;
  595.    }
  596.    UnlockIBase(ILock);
  597.    while (i--) NewClock(Screen[i]);
  598.    SetNewScreenClock();
  599. }
  600.  
  601.  
  602. /*
  603.  *  WaitForAction()
  604.  *
  605.  *  Wait for the messages from the timer or the icon port.
  606.  *  While there are still clock icons on screen,
  607.  *    Get the datestamp, and recover the hours and minutes.
  608.  *    If the time has changed since the last check,
  609.  *      Remove the old hands and add the new ones.
  610.  *      Update all the clocks to use the new faces.
  611.  *      Save the time of the last update.
  612.  *    Of no timer request is pending,
  613.  *      Set up the timer request and send it.
  614.  *      Mark that a requet is pending (in case we need to remove it later).
  615.  *
  616.  *    Wait for the timer or icon message.
  617.  *    If the timer message was returned, mark it so we can re-issue it.
  618.  *    For each icon message we receive, do the right thing:
  619.  *      OPEN: change the display format when the user double-clicks the
  620.  *            clock icon, and unselect the icon.  Only change if the
  621.  *            icons is actually selected (to avoid changing during OPENALL
  622.  *            commands).
  623.  *      CLOSE:  remove the icon if the user closes it.
  624.  *      AUTOREMOVE:  wIconify removed the icon when it closed the screen.
  625.  *            In either casem we check to make sure it was not the NEWSCREEN
  626.  *            icon, and if so, choose another.
  627.  *      NEWSCREEN:  try to open a new clock icon on the new screen.
  628.  *    Then reply to the message.
  629.  */
  630.  
  631. static void WaitForAction()
  632. {
  633.    short Hours,Mins;
  634.    short OldH = 0, OldM = 0;
  635.    struct DateStamp theDateStamp;
  636.    ULONG Signals;
  637.    int NotDone = TRUE;
  638.    struct wIconMessage *theMessage;
  639.    extern struct wIconMessage *GetMsg();
  640.  
  641.    Signals = (1 << TimerPort->mp_SigBit)| (1 << ClockIcon.IconPort->mp_SigBit);
  642.  
  643.    while (NotDone)
  644.    {
  645.       DateStamp(&theDateStamp);
  646.       Hours = theDateStamp.ds_Minute / 60;
  647.       Mins  = theDateStamp.ds_Minute % 60;
  648.       if (Hours != OldH || Mins != OldM)
  649.       {
  650.          UpdateFace(OldH,OldM,FALSE);
  651.          UpdateFace(Hours,Mins,TRUE);
  652.          UpdateTime(ClockName,Hours,Mins);
  653.          UpdateClocks();
  654.          OldH = Hours; OldM = Mins;
  655.       }
  656.       if (TimerSet == FALSE)
  657.       {
  658.          TimerRequest.tr_time.tv_secs  = DELAYSECS;
  659.          TimerRequest.tr_time.tv_micro = DELAYMICS;
  660.          SendIO(&(TimerRequest.tr_node));
  661.          TimerSet = TRUE;
  662.       }
  663.  
  664.       Wait(Signals);
  665.       while (GetMsg(TimerPort)) TimerSet = FALSE;
  666.       while (theMessage = GetMsg(ClockIcon.IconPort))
  667.       {
  668.          switch(theMessage->Action)
  669.          {
  670.             case WI_REPORTOPEN:
  671.                if (wIconFlags(theMessage->Icon) & WI_SELECTED)
  672.                {
  673.                   TimeType = (MILITARY_TIME + STANDARD_TIME) - TimeType;
  674.                   OldH = OldM = 0;
  675.                   wUnSelectIcon(theMessage->Icon);
  676.                }
  677.                break;
  678.  
  679.             case WI_REPORTCLOSE:
  680.                wRemoveIcon(theMessage->Icon);
  681.             case WI_REPORTAUTOREMOVE:
  682.                NotDone = FinishClock(theMessage->Icon);
  683.                break;
  684.  
  685.             case WI_REPORTNEWSCREEN:
  686.                NewClock(theMessage->Data.Screen);
  687.                break;
  688.          }
  689.          ReplyMsg(theMessage);
  690.       }
  691.    }
  692. }
  693.  
  694.  
  695. /*
  696.  *  _main()
  697.  *
  698.  *  Replaces the standard Lattice C _main routine.  It receives the
  699.  *  complete command line as a single string as its only argument.
  700.  *
  701.  *  Parse the argument list.
  702.  *  If wIconify is active,
  703.  *    Open Intuition.
  704.  *    Set up the ports and timer stuff.
  705.  *    Create the clocks for the existing screens.
  706.  *    If there were any clocks created, wait for them to be closed,
  707.  *    Otherwise, say that none could be created.
  708.  *    Exit with no error.
  709.  *  Otherwise, say wIconify is not running.
  710.  */
  711.  
  712. void _main(line)
  713. char *line;
  714. {
  715.    ParseArgs(line);
  716.    if (wIconifyActive())
  717.    {
  718.       CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  719.       SetupClock();
  720.       CreateClocks();
  721.       if (ClockCount) WaitForAction();
  722.          else Print("Can't create Clock Icons on any Screen\n");
  723.       DoExit(NULL);
  724.    } else {
  725.       Print("wIconify not running or incompatible version\n");
  726.    }
  727. }
  728.