home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff398.lzh / DClock / DClock.c < prev    next >
C/C++ Source or Header  |  1990-11-01  |  41KB  |  1,802 lines

  1. /* DClock.c *****************************************************************
  2.  *
  3.  *    DClock --------    A Dumb Clock utility, my idea of how a clock
  4.  *            should really be like.
  5.  *
  6.  *    Author --------    Olaf 'Olsen' Barthel, MXM
  7.  *            Brabeckstrasse 35
  8.  *            D-3000 Hannover 71
  9.  *
  10.  *            Federal Republic of Germany
  11.  *
  12.  *    This  program  truly is in the PUBLIC DOMAIN.  Written on a cold
  13.  *    and  damp  September  evening,  hoping the next morning would be
  14.  *    better.
  15.  *
  16.  *    Compiled using Aztec C 5.0b, CygnusEd Professional 2 & ARexx.
  17.  *
  18.  ***************************************************************************/
  19.  
  20.     /* ARP help messages. */
  21.  
  22. char *CLI_Template    = "Q=Quit/S,I=Info/S,V=Version/S,S=Quiet/S,R=Refresh/S,C=Readclock/S,Beep/K,Click/K,\
  23. Speech/K,Hour/K,Seconds/K,SetEnv/K,Tea=Countdown/K,Sound/K,Textcolour/K,Backcolour/K,\
  24. Clickvolume/K,Priority/K,Page/K,Alarm/K,Alarmtime/K";
  25.  
  26. char *CLI_Help        = "\nUsage: \33[1mDClock\33[0m [Quit] [Info] [Version] [Quiet] [Refresh] [Readclock]\
  27. \n              [Beep On|Off] [Click On|Off] [Speech On|Off]\
  28. \n              [Hour On|Off] [Seconds On|Off] [SetEnv On|Off]\
  29. \n              [Countdown/Tea #|Off] [Sound \"Name\"|Off]\
  30. \n              [Textcolour #] [Backcolour #]\
  31. \n              [Clickvolume 0..64] [Priority -128..127] [Page 0..4]\
  32. \n              [Alarm On|Off|Show] [Alarmtime HH:MM:SS]\n";
  33.  
  34.     /* Where to find the different arguments (quite a lot). */
  35.  
  36. #define ARG_QUIT     1
  37. #define ARG_INFO     2
  38. #define ARG_VERSION     3
  39. #define ARG_QUIET     4
  40. #define ARG_REFRESH     5
  41. #define ARG_READCLOCK     6
  42. #define ARG_BEEP     7
  43. #define ARG_CLICK     8
  44. #define ARG_SPEECH     9
  45. #define ARG_HOUR    10
  46. #define ARG_SECONDS    11
  47. #define ARG_SETENV    12
  48. #define ARG_COUNTDOWN    13
  49. #define ARG_SOUND    14
  50. #define ARG_TEXTCOLOUR    15
  51. #define ARG_BACKCOLOUR    16
  52. #define ARG_CLICKVOLUME    17
  53. #define ARG_PRIORITY    18
  54. #define ARG_PAGE    19
  55. #define ARG_ALARM    20
  56. #define ARG_ALARMTIME    21
  57.  
  58.     /* Pop-up requester support structure. */
  59.  
  60. struct PopSupport
  61. {
  62.     ULONG    ps_Flags;
  63.     LONG    ps_TimeOut;
  64. };
  65.  
  66.     /* Pop-up requester support flags. */
  67.  
  68. #define PS_CENTER    0x00000001    /* Center window on screen. */
  69. #define PS_TIMEOUT    0x00000002    /* Wait for timeout. */
  70. #define PS_DONTMOVE    0x00000004    /* Don't move the pointer. */
  71. #define PS_BEEP        0x00000008    /* Beep on startup. */
  72. #define PS_STAYACTIVE    0x00000010    /* Keep the window activated. */
  73.  
  74.     /* Prototypes. */
  75.  
  76. LONG    Chk_Abort(VOID);
  77. VOID    _wb_parse(VOID);
  78.  
  79. LONG    MovePointer(struct Screen *mp_Screen, LONG mp_X, LONG mp_Y);
  80. LONG    WriteConsole(struct Window *wc_Window, UBYTE *wc_String);
  81. VOID    CalcDimensions(UBYTE *cd_String, LONG *cd_Width, LONG *cd_Height, LONG cd_MaxWidth);
  82. VOID    EraseGadget(struct RastPort *RPort, struct Gadget *Gadget);
  83. LONG    PopRequest(struct Window *pr_ParentWindow, UBYTE *pr_TitleText, UBYTE *pr_BodyText, UBYTE *pr_PosText, UBYTE *pr_NegText, LONG pr_Default, struct PopSupport *pr_ExtraInfo);
  84. VOID    ProcessIcon(VOID);
  85. LONG    FindChunk(ULONG ChunkName,BPTR FileHandle);
  86. LONG    LoadChimeSound(char *Name);
  87.  
  88. VOID    main(int argc,char **argv);
  89.  
  90.     /* For Workbench startability we need access to the icon info. */
  91.  
  92. struct Library    *IconBase;
  93. BOOL         FromWorkbench = FALSE;
  94.  
  95.     /* Some more libraries... */
  96.  
  97. extern struct IntuitionBase    *IntuitionBase;
  98. extern struct GfxBase        *GfxBase;
  99. extern struct ExecBase        *SysBase;
  100.  
  101.     /* Main communication structure. */
  102.  
  103. struct DSeg *DSeg;
  104.  
  105.     /* Stubs, don't need these. */
  106.  
  107. LONG Chk_Abort(VOID) { return(0); }
  108. VOID _wb_parse(VOID) {}
  109.  
  110.     /* Our current version tag. */
  111.  
  112. const char *VersionTag = "$VER: DClock 1.29 (15 Sep 1990)\n\r";
  113.  
  114.     /* MovePointer(mp_Screen,mp_X,mp_Y) :
  115.      *
  116.      *    Moves the mouse pointer to a given position
  117.      *    on a screen.
  118.      */
  119.  
  120. LONG
  121. MovePointer(struct Screen *mp_Screen,LONG mp_X,LONG mp_Y)
  122. {
  123.     static struct InputEvent mp_StaticEvent =
  124.     {
  125.         NULL,
  126.         IECLASS_POINTERPOS,
  127.         0,
  128.         IECODE_NOBUTTON,
  129.         0,0,0,0
  130.     };
  131.  
  132.     struct MsgPort        *mp_InputPort;
  133.     struct IOStdReq        *mp_InputRequest;
  134.     struct InputEvent    *mp_FakeEvent;
  135.  
  136.     LONG mp_Success = FALSE;
  137.  
  138.     if(mp_InputPort = (struct MsgPort *)CreatePort(NULL,0))
  139.     {
  140.         if(mp_InputRequest = (struct IOStdReq *)CreateStdIO(mp_InputPort))
  141.         {
  142.             if(!OpenDevice("input.device",0,(struct IORequest *)mp_InputRequest,0))
  143.             {
  144.                 if(mp_FakeEvent = (struct InputEvent *)AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC))
  145.                 {
  146.                     CopyMem(&mp_StaticEvent,mp_FakeEvent,sizeof(struct InputEvent));
  147.  
  148.                     mp_InputRequest -> io_Command    = IND_WRITEEVENT;
  149.                     mp_InputRequest -> io_Flags    = 0;
  150.                     mp_InputRequest -> io_Length    = sizeof(struct InputEvent);
  151.                     mp_InputRequest -> io_Data    = (APTR)mp_FakeEvent;
  152.  
  153.                     mp_FakeEvent -> ie_X = mp_X;
  154.                     mp_FakeEvent -> ie_Y = mp_Y;
  155.  
  156.                     if(!(mp_Screen -> ViewPort . Modes & HIRES))
  157.                         mp_FakeEvent -> ie_X *= 2;
  158.  
  159.                     if(!(mp_Screen -> ViewPort . Modes & LACE))
  160.                         mp_FakeEvent -> ie_Y *= 2;
  161.  
  162.                     mp_FakeEvent -> ie_Y += (2 * mp_Screen -> TopEdge);
  163.  
  164.                     DoIO((struct IORequest *)mp_InputRequest);
  165.  
  166.                     mp_Success = TRUE;
  167.  
  168.                     FreeMem(mp_FakeEvent,sizeof(struct InputEvent));
  169.                 }
  170.  
  171.                 CloseDevice((struct IORequest *)mp_InputRequest);
  172.             }
  173.  
  174.             DeleteStdIO(mp_InputRequest);
  175.         }
  176.  
  177.         DeletePort(mp_InputPort);
  178.     }
  179.  
  180.     return(mp_Success);
  181. }
  182.  
  183.     /* WriteConsole(wc_Window,wc_String) :
  184.      *
  185.      *    Writes a string to a window (via console.device).
  186.      */
  187.  
  188. LONG
  189. WriteConsole(struct Window *wc_Window,UBYTE *wc_String)
  190. {
  191.     struct IOStdReq    *wc_ConWrite;
  192.     struct MsgPort    *wc_ConPort;
  193.  
  194.     LONG wc_Success = FALSE;
  195.  
  196.     if(wc_ConPort = (struct MsgPort *)CreatePort(NULL,0))
  197.     {
  198.         if(wc_ConWrite = (struct IOStdReq *)CreateStdIO(wc_ConPort))
  199.         {
  200.             wc_ConWrite -> io_Data    = (APTR)wc_Window;
  201.             wc_ConWrite -> io_Length= sizeof(struct Window);
  202.  
  203.             if(!OpenDevice("console.device",0,(struct IORequest *)wc_ConWrite,0))
  204.             {
  205.                 wc_ConWrite -> io_Command    = CMD_WRITE;
  206.                 wc_ConWrite -> io_Data        = (APTR)"\2330 p";
  207.                 wc_ConWrite -> io_Length    = -1;
  208.  
  209.                 DoIO((struct IORequest *)wc_ConWrite);
  210.  
  211.                 wc_ConWrite -> io_Data        = (APTR)wc_String;
  212.                 wc_ConWrite -> io_Length    = -1;
  213.  
  214.                 DoIO((struct IORequest *)wc_ConWrite);
  215.  
  216.                 wc_Success = TRUE;
  217.  
  218.                 CloseDevice((struct IORequest *)wc_ConWrite);
  219.             }
  220.  
  221.             DeleteStdIO(wc_ConWrite);
  222.         }
  223.  
  224.         DeletePort(wc_ConPort);
  225.     }
  226.  
  227.     return(wc_Success);
  228. }
  229.  
  230.     /* CalcDimensions(cd_String,cd_Width,cd_Height,cd_MaxWidth) :
  231.      *
  232.      *    Calculates the width and height of a formatted
  233.      *    string block.
  234.      */
  235.  
  236. VOID
  237. CalcDimensions(UBYTE *cd_String,LONG *cd_Width,LONG *cd_Height,LONG cd_MaxWidth)
  238. {
  239.     LONG i,cd_InLine = 0,cd_NumLines = 0;
  240.  
  241.     *cd_Width = *cd_Height = 0;
  242.  
  243.     for(i = 0 ; i < strlen(cd_String) ; i++)
  244.     {
  245.         if(cd_String[i] == '\n' || cd_InLine == cd_MaxWidth)
  246.         {
  247.             if(cd_InLine > *cd_Width)
  248.                 *cd_Width = cd_InLine;
  249.  
  250.             cd_NumLines++;
  251.             cd_InLine = 0;
  252.  
  253.             continue;
  254.         }
  255.  
  256.         if(cd_String[i] == '\33')
  257.         {
  258.             while(cd_String[i] != 'm' && cd_String[i] != 'w' && i < strlen(cd_String))
  259.                 i++;
  260.  
  261.             if(i >= strlen(cd_String))
  262.                 i = strlen(cd_String) - 1;
  263.  
  264.             continue;
  265.         }
  266.  
  267.         if(cd_String[i] < ' ')
  268.             continue;
  269.  
  270.         cd_InLine++;
  271.     }
  272.  
  273.     *cd_Height = cd_NumLines;
  274.  
  275.     if(cd_InLine > *cd_Width)
  276.         *cd_Width = cd_InLine;
  277. }
  278.  
  279.     /* EraseGadget(RPort,Gadget) :
  280.      *
  281.      *    Clears the background of a gadget.
  282.      */
  283.  
  284. VOID
  285. EraseGadget(struct RastPort *RPort,struct Gadget *Gadget)
  286. {
  287.     SetAPen(RPort,2);
  288.  
  289.     SetDrMd(RPort,JAM1);
  290.  
  291.     RectFill(RPort,Gadget -> LeftEdge,Gadget -> TopEdge,Gadget -> LeftEdge + Gadget -> Width - 1,Gadget -> TopEdge + Gadget -> Height - 1);
  292.  
  293.     SetAPen(RPort,1);
  294. }
  295.  
  296.     /* PopRequest(pr_ParentWindow,pr_TitleText,pr_BodyText,pr_PosText,pr_NegText,pr_Default,pr_ExtraInfo) :
  297.      *
  298.      *    Creates a pop-up requester, note: this function is reentrant,
  299.      *    just like all functions above.
  300.      */
  301.  
  302. LONG
  303. PopRequest(struct Window *pr_ParentWindow,UBYTE *pr_TitleText,UBYTE *pr_BodyText,UBYTE *pr_PosText,UBYTE *pr_NegText,LONG pr_Default,struct PopSupport *pr_ExtraInfo)
  304. {
  305.     static struct NewWindow pr_StaticNewWindow =
  306.     {
  307.         0,0,
  308.         0,1,
  309.         0,1,
  310.         VANILLAKEY | MOUSEBUTTONS | GADGETUP | CLOSEWINDOW,
  311.         RMBTRAP | WINDOWDRAG | WINDOWDEPTH,
  312.         (struct Gadget *)NULL,
  313.         (struct Image *)NULL,
  314.         (STRPTR)NULL,
  315.         (struct Screen *)NULL,
  316.         (struct BitMap *)NULL,
  317.         0,0,
  318.         0,0,
  319.         WBENCHSCREEN
  320.     };
  321.  
  322.     static struct Gadget pr_StaticGadget =
  323.     {
  324.         (struct Gadget *)NULL,
  325.         0,0,
  326.         0,0,
  327.         GADGHBOX,
  328.         RELVERIFY | GADGIMMEDIATE,
  329.         BOOLGADGET,
  330.         (APTR)NULL,
  331.         (APTR)NULL,
  332.         (struct IntuiText *)NULL,
  333.         NULL,
  334.         (APTR)NULL,
  335.         0,
  336.         (APTR)NULL
  337.     };
  338.  
  339.     static struct TextAttr pr_TextAttr =
  340.     {
  341.         (UBYTE *)"topaz.font",
  342.         8,
  343.         FS_NORMAL,
  344.         FPF_ROMFONT
  345.     };
  346.  
  347.     struct NewWindow    *pr_NewWindow;
  348.     struct Window        *pr_Window;
  349.     struct IntuiMessage    *pr_IMsg;
  350.     struct Gadget        *pr_PosGadget = NULL,*pr_NegGadget = NULL,*pr_TempGadget;
  351.  
  352.     struct Screen         pr_Screen,*pr_FirstScreen;
  353.     struct TextFont        *pr_TextFont;
  354.  
  355.     LONG             pr_Width,pr_Height;
  356.     LONG             pr_Result = FALSE;
  357.  
  358.     LONG             pr_TickCount = 0;
  359.  
  360.     ULONG             pr_IntuiLock;
  361.  
  362.     if(!pr_BodyText)
  363.         return(pr_Result);
  364.  
  365.     if(!(pr_NewWindow = (struct NewWindow *)AllocMem(sizeof(struct NewWindow),MEMF_PUBLIC)))
  366.         return(pr_Result);
  367.  
  368.     CopyMem(&pr_StaticNewWindow,pr_NewWindow,sizeof(struct NewWindow));
  369.  
  370.     pr_IntuiLock = LockIBase(NULL);
  371.  
  372.     pr_FirstScreen = IntuitionBase -> FirstScreen;
  373.  
  374.     UnlockIBase(pr_IntuiLock);
  375.  
  376.     if(pr_ParentWindow)
  377.     {
  378.         pr_NewWindow -> Type    = CUSTOMSCREEN;
  379.         pr_NewWindow -> Screen    = pr_ParentWindow -> WScreen;
  380.     }
  381.     else
  382.         OpenWorkBench();
  383.  
  384.     if(!GetScreenData(&pr_Screen,sizeof(struct Screen),pr_NewWindow -> Type,pr_NewWindow -> Screen))
  385.     {
  386.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  387.         return(pr_Result);
  388.     }
  389.  
  390.     CalcDimensions(pr_BodyText,&pr_Width,&pr_Height,(pr_Screen . Width - 6) / 8);
  391.  
  392.     if(pr_Height > (pr_Screen . Height - 15 - 13) / 8)
  393.     {
  394.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  395.         return(pr_Result);
  396.     }
  397.  
  398.     pr_NewWindow -> Width    = pr_Width * 8 + 6 + 4;
  399.     pr_NewWindow -> Height    = pr_Height * 8 + 15 + 19 + 2;
  400.  
  401.     if(pr_TitleText)
  402.         pr_NewWindow -> Title = pr_TitleText;
  403.     else
  404.         pr_NewWindow -> Title = (UBYTE *)"System Request";
  405.  
  406.     if(!pr_PosText && !pr_NegText)
  407.         pr_NegText = (UBYTE *)"Okay";
  408.  
  409.     if(pr_PosText)
  410.     {
  411.         if(!(pr_PosGadget = (struct Gadget *)AllocMem(sizeof(struct Gadget),MEMF_PUBLIC)))
  412.         {
  413.             FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  414.             return(pr_Result);
  415.         }
  416.  
  417.         CopyMem(&pr_StaticGadget,pr_PosGadget,sizeof(struct Gadget));
  418.  
  419.         pr_PosGadget -> Width    = 8 * strlen(pr_PosText) + 4;
  420.         pr_PosGadget -> Height    = 8 + 2;
  421.  
  422.         pr_PosGadget -> LeftEdge= 3 + 2 + 3;
  423.         pr_PosGadget -> TopEdge    = pr_NewWindow -> Height - 13 - 1;
  424.     }
  425.  
  426.     if(pr_NegText)
  427.     {
  428.         if(!(pr_NegGadget = (struct Gadget *)AllocMem(sizeof(struct Gadget),MEMF_PUBLIC)))
  429.         {
  430.             FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  431.  
  432.             if(pr_PosGadget)
  433.                 FreeMem(pr_PosGadget,sizeof(struct Gadget));
  434.  
  435.             return(pr_Result);
  436.         }
  437.  
  438.         CopyMem(&pr_StaticGadget,pr_NegGadget,sizeof(struct Gadget));
  439.  
  440.         pr_NegGadget -> Width    = 8 * strlen(pr_NegText) + 4;
  441.         pr_NegGadget -> Height    = 8 + 2;
  442.  
  443.         pr_Width = pr_NegGadget -> Width + 6 + 4 + 6;
  444.  
  445.         if(pr_PosGadget)
  446.             pr_Width += (pr_PosGadget -> Width + 12);
  447.  
  448.         if(pr_NewWindow -> Width < pr_Width)
  449.             pr_NewWindow -> Width = pr_Width;
  450.  
  451.         pr_NegGadget -> LeftEdge= pr_NewWindow -> Width - pr_NegGadget -> Width - 3 - 2 - 3;
  452.         pr_NegGadget -> TopEdge    = pr_NewWindow -> Height - 13 - 1;
  453.  
  454.         pr_NegGadget -> GadgetID= 1;
  455.     }
  456.  
  457.     if(!pr_NegGadget && pr_NewWindow -> Width < pr_PosGadget -> Width + 6 + 4 + 6)
  458.         pr_NewWindow -> Width = pr_PosGadget -> Width + 6 + 4 + 6;
  459.  
  460.     if(pr_Default && !pr_PosGadget)
  461.         pr_Default = FALSE;
  462.  
  463.     if(!pr_Default && !pr_NegGadget)
  464.         pr_Default = TRUE;
  465.  
  466.     if(pr_Default)
  467.         pr_TempGadget = pr_PosGadget;
  468.     else
  469.         pr_TempGadget = pr_NegGadget;
  470.  
  471.     pr_NewWindow -> LeftEdge= pr_Screen . MouseX - (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2);
  472.     pr_NewWindow -> TopEdge    = pr_Screen . MouseY - (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2);
  473.  
  474.     while(pr_NewWindow -> LeftEdge < 0)
  475.         pr_NewWindow -> LeftEdge++;
  476.  
  477.     while(pr_NewWindow -> TopEdge < 0)
  478.         pr_NewWindow -> TopEdge++;
  479.  
  480.     while(pr_NewWindow -> LeftEdge + pr_NewWindow -> Width >= pr_Screen . Width)
  481.         pr_NewWindow -> LeftEdge--;
  482.  
  483.     while(pr_NewWindow -> TopEdge + pr_NewWindow -> Height >= pr_Screen . Height)
  484.         pr_NewWindow -> TopEdge--;
  485.  
  486.     if(!(pr_TextFont = (struct TextFont *)OpenFont(&pr_TextAttr)))
  487.     {
  488.         if(pr_PosGadget)
  489.             FreeMem(pr_PosGadget,sizeof(struct Gadget));
  490.  
  491.         if(pr_NegGadget)
  492.             FreeMem(pr_NegGadget,sizeof(struct Gadget));
  493.  
  494.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  495.  
  496.         return(pr_Result);
  497.     }
  498.  
  499.     if(pr_ExtraInfo)
  500.     {
  501.         if(pr_ExtraInfo -> ps_Flags & PS_CENTER)
  502.         {
  503.             pr_NewWindow -> LeftEdge    = (pr_Screen . Width - pr_NewWindow -> Width) / 2;
  504.             pr_NewWindow -> TopEdge        = (pr_Screen . Height - pr_NewWindow -> Height) / 2;
  505.         }
  506.  
  507.         if(pr_ExtraInfo -> ps_Flags & PS_TIMEOUT)
  508.             pr_NewWindow -> IDCMPFlags |= INTUITICKS;
  509.  
  510.         if(pr_ExtraInfo -> ps_Flags & PS_STAYACTIVE)
  511.             pr_NewWindow -> IDCMPFlags |= INACTIVEWINDOW;
  512.     }
  513.  
  514.     if(!(pr_Window = (struct Window *)OpenWindow(pr_NewWindow)))
  515.     {
  516.         CloseFont(pr_TextFont);
  517.  
  518.         if(pr_PosGadget)
  519.             FreeMem(pr_PosGadget,sizeof(struct Gadget));
  520.  
  521.         if(pr_NegGadget)
  522.             FreeMem(pr_NegGadget,sizeof(struct Gadget));
  523.  
  524.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  525.  
  526.         return(pr_Result);
  527.     }
  528.  
  529.     SetFont(pr_Window -> RPort,pr_TextFont);
  530.  
  531.     WriteConsole(pr_Window,pr_BodyText);
  532.  
  533.     if(pr_PosGadget)
  534.     {
  535.         AddGadget(pr_Window,pr_PosGadget,1);
  536.  
  537.         EraseGadget(pr_Window -> RPort,pr_PosGadget);
  538.  
  539.         Move(pr_Window -> RPort,pr_PosGadget -> LeftEdge + 2,pr_PosGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline);
  540.         Text(pr_Window -> RPort,pr_PosText,strlen(pr_PosText));
  541.     }
  542.  
  543.     if(pr_NegGadget)
  544.     {
  545.         AddGadget(pr_Window,pr_NegGadget,1);
  546.  
  547.         EraseGadget(pr_Window -> RPort,pr_NegGadget);
  548.  
  549.         Move(pr_Window -> RPort,pr_NegGadget -> LeftEdge + 2,pr_NegGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline);
  550.         Text(pr_Window -> RPort,pr_NegText,strlen(pr_NegText));
  551.     }
  552.  
  553.     MoveScreen(pr_Window -> WScreen,0,- pr_Window -> WScreen -> TopEdge);
  554.     ScreenToFront(pr_Window -> WScreen);
  555.     ActivateWindow(pr_Window);
  556.  
  557.     if(pr_ExtraInfo && pr_ExtraInfo -> ps_Flags & PS_DONTMOVE)
  558.         goto Skip1;
  559.  
  560.     MovePointer(pr_Window -> WScreen,
  561.         pr_Window -> LeftEdge + (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2),
  562.         pr_Window -> TopEdge + (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2));
  563.  
  564. Skip1:    if(pr_ExtraInfo)
  565.     {
  566.         if(pr_ExtraInfo -> ps_Flags & PS_BEEP)
  567.             DisplayBeep(pr_Window -> WScreen);
  568.  
  569.         if(pr_ExtraInfo -> ps_Flags & PS_TIMEOUT)
  570.             pr_TickCount = pr_ExtraInfo -> ps_TimeOut * 10;
  571.     }
  572.  
  573.     FOREVER
  574.     {
  575.         ULONG pr_Class,pr_Code,pr_Qualifier;
  576.         struct Gadget *pr_Gadget;
  577.  
  578.         WaitPort(pr_Window -> UserPort);
  579.  
  580.         if(pr_IMsg = (struct IntuiMessage *)GetMsg(pr_Window -> UserPort))
  581.         {
  582.             pr_Class    = pr_IMsg -> Class;
  583.             pr_Code        = pr_IMsg -> Code;
  584.             pr_Qualifier    = pr_IMsg -> Qualifier;
  585.             pr_Gadget    = (struct Gadget *)pr_IMsg -> IAddress;
  586.  
  587.             ReplyMsg((struct Message *)pr_IMsg);
  588.  
  589.             if(pr_Class == INTUITICKS)
  590.             {
  591.                 if(pr_TickCount)
  592.                     pr_TickCount--;
  593.                 else
  594.                 {
  595.                     pr_Result = pr_Default;
  596.                     break;
  597.                 }
  598.  
  599.                 continue;
  600.             }
  601.  
  602.             if(pr_Class == INACTIVEWINDOW)
  603.             {
  604.                 MoveScreen(pr_Window -> WScreen,0,- pr_Window -> WScreen -> TopEdge);
  605.                 ScreenToFront(pr_Window -> WScreen);
  606.                 ActivateWindow(pr_Window);
  607.  
  608.                 if(!(pr_ExtraInfo -> ps_Flags & PS_DONTMOVE))
  609.                 {
  610.                     MovePointer(pr_Window -> WScreen,
  611.                         pr_Window -> LeftEdge + (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2),
  612.                         pr_Window -> TopEdge + (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2));
  613.                 }
  614.  
  615.                 if(pr_ExtraInfo -> ps_Flags & PS_BEEP)
  616.                     DisplayBeep(pr_Window -> WScreen);
  617.  
  618.                 continue;
  619.             }
  620.  
  621.             if(pr_Class == GADGETUP)
  622.             {
  623.                 if(pr_Gadget -> GadgetID == 0)
  624.                     pr_Result = TRUE;
  625.  
  626.                 break;
  627.             }
  628.  
  629.             if(pr_Class == CLOSEWINDOW)
  630.                 break;
  631.  
  632.             if(pr_Class == VANILLAKEY)
  633.             {
  634.                 pr_Code = Toupper(pr_Code);
  635.  
  636.                 if((pr_Code == 'Y' || pr_Code == 'J' || pr_Code == 'V' || pr_Code == 'C' || pr_Code == 'R' || pr_Code == '\r') && pr_PosText)
  637.                 {
  638.                     pr_Result = TRUE;
  639.                     break;
  640.                 }
  641.  
  642.                 if((pr_Code == 'N' || pr_Code == 'Q' || pr_Code == 'B' || pr_Code == '\33') && pr_NegText)
  643.                     break;
  644.  
  645.                 continue;
  646.             }
  647.  
  648.             if(pr_Class == MOUSEBUTTONS && pr_Code == MENUDOWN)
  649.             {
  650.                 MovePointer(pr_Window -> WScreen,
  651.                     pr_Window -> LeftEdge+ (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2),
  652.                     pr_Window -> TopEdge + (pr_TempGadget -> TopEdge  + pr_TempGadget -> Height / 2));
  653.             }
  654.         }
  655.     }
  656.  
  657.     CloseFont(pr_TextFont);
  658.  
  659.     if(pr_PosGadget)
  660.     {
  661.         RemoveGadget(pr_Window,pr_PosGadget);
  662.         FreeMem(pr_PosGadget,sizeof(struct Gadget));
  663.     }
  664.  
  665.     if(pr_NegGadget)
  666.     {
  667.         RemoveGadget(pr_Window,pr_NegGadget);
  668.         FreeMem(pr_NegGadget,sizeof(struct Gadget));
  669.     }
  670.  
  671.     FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  672.  
  673.     if(pr_FirstScreen != pr_Window -> WScreen)
  674.         ScreenToBack(pr_Window -> WScreen);
  675.  
  676.     CloseWindow(pr_Window);
  677.  
  678.     return(pr_Result);
  679. }
  680.  
  681.     /* FindChunk(ChunkName,FileHandle):
  682.      *
  683.      *    Tries to locate a an iff-chunk inside a file.
  684.      */
  685.  
  686. LONG
  687. FindChunk(ULONG ChunkName,BPTR FileHandle)
  688. {
  689.     LONG     OldPosition;
  690.     ULONG    FormType = 0;
  691.  
  692.         /* The format of a typical IFF-chunk. */
  693.  
  694.     struct
  695.     {
  696.         ULONG    IFF_Type;
  697.         ULONG    IFF_Length;
  698.     } Chunk;
  699.  
  700.         /* Remember initial file position. */
  701.  
  702.     OldPosition = Seek(FileHandle,0,OFFSET_CURRENT);
  703.  
  704.         /* Try to find it. */
  705.  
  706.     FOREVER
  707.     {
  708.             /* Read the first bytes. */
  709.  
  710.         if(Read(FileHandle,&Chunk,sizeof(Chunk)) != sizeof(Chunk))
  711.         {
  712.             Seek(FileHandle,OldPosition,OFFSET_BEGINNING);
  713.             return(FALSE);
  714.         }
  715.  
  716.             /* Is it a FORM-chunk? */
  717.  
  718.         if(OldPosition == 0 && FormType == 0 && Chunk . IFF_Type == 'FORM')
  719.         {
  720.             Read(FileHandle,&FormType,sizeof(LONG));
  721.  
  722.                 /* Check the form type. */
  723.  
  724.             if(FormType == ChunkName)
  725.                 return(TRUE);
  726.  
  727.             continue;
  728.         }
  729.  
  730.             /* Is it the chunk type we want? */
  731.  
  732.         if(Chunk . IFF_Type == ChunkName)
  733.             return(TRUE);
  734.  
  735.             /* Skip chunk. */
  736.  
  737.         Seek(FileHandle,Chunk . IFF_Length,OFFSET_CURRENT);
  738.     }
  739. }
  740.  
  741.     /* LoadChimeSound(Name):
  742.      *
  743.      *    Loads an IFF-8SVX-soundfile to be used as the hour
  744.      *    chime sound.
  745.      */
  746.  
  747. LONG
  748. LoadChimeSound(char *Name)
  749. {
  750.     BPTR SoundHandle;
  751.  
  752.     APTR SoundData;
  753.     LONG SoundRate,SoundLength,SoundVolume;
  754.  
  755.         /* The format of the VoiceHeader chunk. */
  756.  
  757.     struct
  758.     {
  759.         ULONG    oneShotHiSamples,
  760.             repeatHiSamples,
  761.             samplesPerHiCycle;
  762.         UWORD    samplesPerSec;
  763.         UBYTE    ctOctave,
  764.             sCompression;
  765.         LONG    volume;
  766.     } VoiceHeader;
  767.  
  768.         /* No name? Reset to defaults. */
  769.  
  770.     if(!Strcmp(Name,"OFF"))
  771.     {
  772.         ObtainSemaphore(DSeg -> SoundSemaphore);
  773.  
  774.             /* Free the memory. */
  775.  
  776.         if(DSeg -> SoundLength && DSeg -> SoundData)
  777.             FreeMem(DSeg -> SoundData,DSeg -> SoundLength);
  778.  
  779.             /* Mark sound slot as vacant. */
  780.  
  781.         DSeg -> SoundLength    = 0;
  782.         DSeg -> SoundData    = NULL;
  783.  
  784.         ReleaseSemaphore(DSeg -> SoundSemaphore);
  785.  
  786.         return(TRUE);
  787.     }
  788.  
  789.         /* Open the file for reading. */
  790.  
  791.     if(!(SoundHandle = Open(Name,MODE_OLDFILE)))
  792.     {
  793.         if(FromWorkbench)
  794.             PopRequest(NULL,"DClock problem:","No such sound file found!",NULL,"Continue?",FALSE,NULL);
  795.         else
  796.             Puts("\33[1mDClock:\33[0m No such sound file found!");
  797.  
  798.         return(FALSE);
  799.     }
  800.  
  801.         /* Is it a sound file? */
  802.  
  803.     if(!FindChunk('8SVX',SoundHandle))
  804.     {
  805.         Close(SoundHandle);
  806.  
  807.         if(FromWorkbench)
  808.             PopRequest(NULL,"DClock problem:","File is not an IFF-8SVX-file!",NULL,"Continue?",FALSE,NULL);
  809.         else
  810.             Puts("\33[1mDClock:\33[0m File is not an IFF-8SVX-file!");
  811.  
  812.         return(FALSE);
  813.     }
  814.  
  815.         /* Look for the VoiceHeader. */
  816.  
  817.     if(!FindChunk('VHDR',SoundHandle))
  818.     {
  819.         if(FromWorkbench)
  820.             PopRequest(NULL,"DClock problem:","Didn't find VHDR chunk!",NULL,"Continue?",FALSE,NULL);
  821.         else
  822.             Puts("\33[1mDClock:\33[0m Didn't find VHDR chunk!");
  823.  
  824.         Close(SoundHandle);
  825.         return(FALSE);
  826.     }
  827.  
  828.         /* Read the header. */
  829.  
  830.     if(Read(SoundHandle,&VoiceHeader,sizeof(VoiceHeader)) != sizeof(VoiceHeader))
  831.     {
  832.         if(FromWorkbench)
  833.             PopRequest(NULL,"DClock problem:","Error while reading file!",NULL,"Continue?",FALSE,NULL);
  834.         else
  835.             Puts("\33[1mDClock:\33[0m Error while reading file!");
  836.  
  837.         Close(SoundHandle);
  838.         return(FALSE);
  839.     }
  840.  
  841.         /* Fill in the more important information. */
  842.  
  843.     SoundLength    = VoiceHeader . oneShotHiSamples + VoiceHeader . repeatHiSamples;
  844.     SoundRate    = ((GfxBase -> DisplayFlags & PAL) ? 3546895 : 3579545) / VoiceHeader . samplesPerSec;
  845.     SoundVolume    = (VoiceHeader . volume > 64 ? 64 : VoiceHeader . volume);
  846.  
  847.         /* Proceed with the body chunk. */
  848.  
  849.     if(!FindChunk('BODY',SoundHandle))
  850.     {
  851.         if(FromWorkbench)
  852.             PopRequest(NULL,"DClock problem:","Didn't find BODY chunk!",NULL,"Continue?",FALSE,NULL);
  853.         else
  854.             Puts("\33[1mDClock:\33[0m Didn't find BODY chunk!");
  855.  
  856.         Close(SoundHandle);
  857.         return(FALSE);
  858.     }
  859.  
  860.         /* Allocate space for the sound data. */
  861.  
  862.     if(!(SoundData = (APTR)AllocMem(SoundLength,MEMF_PUBLIC | MEMF_CHIP)))
  863.     {
  864.         if(FromWorkbench)
  865.             PopRequest(NULL,"DClock problem:","Not enough memory for sound data!",NULL,"Continue?",FALSE,NULL);
  866.         else
  867.             Puts("\33[1mDClock:\33[0m Not enough memory for sound data!");
  868.  
  869.         Close(SoundHandle);
  870.         return(FALSE);
  871.     }
  872.  
  873.         /* Read the sound data. */
  874.  
  875.     if(Read(SoundHandle,SoundData,SoundLength) != SoundLength)
  876.     {
  877.         if(FromWorkbench)
  878.             PopRequest(NULL,"DClock problem:","Error while reading file!",NULL,"Continue?",FALSE,NULL);
  879.         else
  880.             Puts("\33[1mDClock:\33[0m Error while reading file!");
  881.  
  882.         FreeMem(SoundData,SoundLength);
  883.         Close(SoundHandle);
  884.         return(FALSE);
  885.     }
  886.  
  887.         /* Close the file. */
  888.  
  889.     Close(SoundHandle);
  890.  
  891.         /* Lock access to sound data. */
  892.  
  893.     ObtainSemaphore(DSeg -> SoundSemaphore);
  894.  
  895.         /* Free last sound. */
  896.  
  897.     if(DSeg -> SoundLength && DSeg -> SoundData)
  898.         FreeMem(DSeg -> SoundData,DSeg -> SoundLength);
  899.  
  900.         /* Fill in the data. */
  901.  
  902.     DSeg -> SoundData    = SoundData;
  903.     DSeg -> SoundLength    = SoundLength;
  904.     DSeg -> SoundRate    = SoundRate;
  905.     DSeg -> SoundVolume    = SoundVolume;
  906.  
  907.         /* Unlock it again. */
  908.  
  909.     ReleaseSemaphore(DSeg -> SoundSemaphore);
  910.  
  911.     return(TRUE);
  912. }
  913.  
  914.     /* ProcessIcon():
  915.      *
  916.      *    To add startability from Workbench this function
  917.      *    checks for the approritate tooltype entries.
  918.      */
  919.  
  920. VOID
  921. ProcessIcon()
  922. {
  923.     struct DiskObject *DiskObject;
  924.     extern struct WBStartup *WBenchMsg;
  925.     char *Option;
  926.  
  927.         /* No need to continue? */
  928.  
  929.     if(!DSeg || !FromWorkbench)
  930.     {
  931.         if(!DSeg && FromWorkbench)
  932.             PopRequest(NULL,"DClock problem:","Can't find \33[1m\"DClock-Handler\"\33[0m!\nCheck L: and current directory.",NULL,"Continue?",FALSE,NULL);
  933.  
  934.         return;
  935.     }
  936.  
  937.         /* Try to open the icon.library. */
  938.  
  939.     if(!(IconBase = (struct Library *)OpenLibrary("icon.library",0)))
  940.     {
  941.         PopRequest(NULL,"DClock problem:","Unable to open \33[1micon.library\33[0m!",NULL,"Continue?",FALSE,NULL);
  942.         return;
  943.     }
  944.  
  945.         /* Can we read the icon file please? */
  946.  
  947.     if(!(DiskObject = (struct DiskObject *)GetDiskObject(WBenchMsg -> sm_ArgList -> wa_Name)))
  948.     {
  949.         PopRequest(NULL,"DClock problem:","Couldn't read icon information file!",NULL,"Continue?",FALSE,NULL);
  950.  
  951.         CloseLibrary(IconBase);
  952.         return;
  953.     }
  954.  
  955.         /* Adjust Click volume? */
  956.  
  957.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"CLICKVOLUME"))
  958.     {
  959.         if(Atol(Option) > 64 || Atol(Option) < 0)
  960.             PopRequest(NULL,"DClock problem:","Illegal value for click volume (must be between 0 and 64)!",NULL,"Continue?",FALSE,NULL);
  961.         else
  962.             DSeg -> ClickVolume = Atol(Option);
  963.     }
  964.  
  965.         /* Adjust task priority? */
  966.  
  967.     if((Option = FindToolType(DiskObject -> do_ToolTypes,"PRIORITY")) && DSeg -> Child)
  968.     {
  969.         if(Atol(Option) > 127 || Atol(Option) < -128)
  970.             PopRequest(NULL,"DClock problem:","Illegal value for handler task priority (must be between -128 and 127)!",NULL,"Continue?",FALSE,NULL);
  971.         else
  972.         {
  973.             DSeg -> Priority = Atol(Option);
  974.             SetTaskPri(DSeg -> Child,DSeg -> Priority);
  975.         }
  976.     }
  977.  
  978.         /* Turn DisplayBeep() off? */
  979.  
  980.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"BEEP"))
  981.     {
  982.         if(!Strcmp(Option,"OFF"))
  983.             DSeg -> Beep = FALSE;
  984.         else
  985.         {
  986.             if(!Strcmp(Option,"ON"))
  987.                 DSeg -> Beep = TRUE;
  988.             else
  989.                 PopRequest(NULL,"DClock problem:","Beep settings not understood (must be OFF or ON)!",NULL,"Continue?",FALSE,NULL);
  990.         }
  991.     }
  992.  
  993.         /* Turn keyboard click off? */
  994.  
  995.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"CLICK"))
  996.     {
  997.         if(!Strcmp(Option,"OFF"))
  998.             DSeg -> Click = FALSE;
  999.         else
  1000.         {
  1001.             if(!Strcmp(Option,"ON"))
  1002.                 DSeg -> Click = TRUE;
  1003.             else
  1004.                 PopRequest(NULL,"DClock problem:","Click settings not understood (must be OFF or ON)!",NULL,"Continue?",FALSE,NULL);
  1005.         }
  1006.     }
  1007.  
  1008.         /* Set text colour? */
  1009.  
  1010.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"TEXTCOLOUR"))
  1011.         DSeg -> TextColour = Atol(Option);
  1012.  
  1013.         /* Set background colour? */
  1014.  
  1015.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"BACKCOLOUR"))
  1016.         DSeg -> BackColour = Atol(Option);
  1017.  
  1018.         /* Turn alarm on? */
  1019.  
  1020.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"ALARM"))
  1021.     {
  1022.         if(!Strcmp(Option,"OFF"))
  1023.             DSeg -> Alarm = FALSE;
  1024.         else
  1025.         {
  1026.             if(!Strcmp(Option,"ON"))
  1027.                 DSeg -> Alarm = TRUE;
  1028.             else
  1029.                 PopRequest(NULL,"DClock problem:","Alarm settings not understood (must be OFF or ON)!",NULL,"Continue?",FALSE,NULL);
  1030.         }
  1031.     }
  1032.  
  1033.         /* Set alarm time? */
  1034.  
  1035.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"ALARMTIME"))
  1036.     {
  1037.         char TimeBuff[3];
  1038.         LONG TheTime;
  1039.  
  1040.         TimeBuff[2] = 0;
  1041.  
  1042.         TimeBuff[0] = Option[0];
  1043.         TimeBuff[1] = Option[1];
  1044.  
  1045.         TheTime = Atol(TimeBuff);
  1046.  
  1047.         if(TheTime >= 0 && TheTime <= 23)
  1048.             DSeg -> AlarmHour = TheTime;
  1049.         else
  1050.             PopRequest(NULL,"DClock problem:","Illegal value for alarm hour (must be between 0 and 23)!",NULL,"Continue?",FALSE,NULL);
  1051.  
  1052.         TimeBuff[0] = Option[3];
  1053.         TimeBuff[1] = Option[4];
  1054.  
  1055.         TheTime = Atol(TimeBuff);
  1056.  
  1057.         if(TheTime >= 0 && TheTime <= 59)
  1058.             DSeg -> AlarmMinute = TheTime;
  1059.         else
  1060.             PopRequest(NULL,"DClock problem:","Illegal value for alarm minute (must be between 0 and 59)!",NULL,"Continue?",FALSE,NULL);
  1061.  
  1062.         TimeBuff[0] = Option[6];
  1063.         TimeBuff[1] = Option[7];
  1064.  
  1065.         TheTime = Atol(TimeBuff);
  1066.  
  1067.         if(TheTime >= 0 && TheTime <= 59)
  1068.             DSeg -> AlarmSecond = TheTime;
  1069.         else
  1070.             PopRequest(NULL,"DClock problem:","Illegal value for alarm seconds (must be between 0 and 59)!",NULL,"Continue?",FALSE,NULL);
  1071.     }
  1072.  
  1073.         /* Set environment variables? */
  1074.  
  1075.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"SETENV"))
  1076.     {
  1077.         if(!Strcmp(Option,"OFF"))
  1078.             DSeg -> SetEnv = FALSE;
  1079.         else
  1080.         {
  1081.             if(!Strcmp(Option,"ON"))
  1082.                 DSeg -> SetEnv = TRUE;
  1083.             else
  1084.                 PopRequest(NULL,"DClock problem:","Environment settings not understood (must be OFF or ON)!",NULL,"Continue?",FALSE,NULL);
  1085.         }
  1086.     }
  1087.  
  1088.         /* Start countdown? */
  1089.  
  1090.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"COUNTDOWN"))
  1091.     {
  1092.         if(Atol(Option) > 0)
  1093.             DSeg -> Countdown = Atol(Option);
  1094.         else
  1095.             PopRequest(NULL,"DClock problem:","Countdown must be greater than 0!",NULL,"Continue?",FALSE,NULL);
  1096.     }
  1097.  
  1098.         /* Set hour chime? */
  1099.  
  1100.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"HOUR"))
  1101.     {
  1102.         if(!Strcmp(Option,"OFF"))
  1103.             DSeg -> Hour = FALSE;
  1104.         else
  1105.         {
  1106.             if(!Strcmp(Option,"ON"))
  1107.                 DSeg -> Hour = TRUE;
  1108.             else
  1109.                 PopRequest(NULL,"DClock problem:","Hour settings not understood (must be OFF or ON)!",NULL,"Continue?",FALSE,NULL);
  1110.         }
  1111.     }
  1112.  
  1113.         /* Turn seconds off? */
  1114.  
  1115.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"SECONDS"))
  1116.     {
  1117.         if(!Strcmp(Option,"OFF"))
  1118.             DSeg -> Seconds = FALSE;
  1119.         else
  1120.         {
  1121.             if(!Strcmp(Option,"ON"))
  1122.                 DSeg -> Seconds = TRUE;
  1123.             else
  1124.                 PopRequest(NULL,"DClock problem:","Second settings not understood (must be OFF or ON)!",NULL,"Continue?",FALSE,NULL);
  1125.         }
  1126.     }
  1127.  
  1128.         /* Load a chime sound? */
  1129.  
  1130.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"SOUND"))
  1131.         LoadChimeSound(Option);
  1132.  
  1133.         /* Show which page on startup? */
  1134.  
  1135.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"PAGE"))
  1136.     {
  1137.         if(Atol(Option) < 0 || Atol(Option) > 4 || (Atol(Option) == 4 && DSeg -> Countdown < 1))
  1138.             PopRequest(NULL,"DClock problem:","Illegal value for page!",NULL,"Continue?",FALSE,NULL);
  1139.         else
  1140.             DSeg -> Page = Atol(Option);
  1141.     }
  1142.  
  1143.         /* Turn the speech off? */
  1144.  
  1145.     if(Option = FindToolType(DiskObject -> do_ToolTypes,"SPEECH"))
  1146.     {
  1147.         if(!Strcmp(Option,"OFF"))
  1148.             DSeg -> Speech = FALSE;
  1149.         else
  1150.         {
  1151.             if(!Strcmp(Option,"ON"))
  1152.                 DSeg -> Speech = TRUE;
  1153.             else
  1154.                 PopRequest(NULL,"DClock problem:","Speech settings not understood (must be OFF or ON)!",NULL,"Continue?",FALSE,NULL);
  1155.         }
  1156.     }
  1157.  
  1158.         /* Read the system clock? */
  1159.  
  1160.     if(FindToolType(DiskObject -> do_ToolTypes,"READCLOCK"))
  1161.     {
  1162.         if(!ReadClock())
  1163.             PopRequest(NULL,"DClock problem:","Could not find battery backed up clock!",NULL,"Continue?",FALSE,NULL);
  1164.     }
  1165.  
  1166.         /* Free the rest... */
  1167.  
  1168.     FreeDiskObject(DiskObject);
  1169.  
  1170.     CloseLibrary(IconBase);
  1171. }
  1172.  
  1173.     /* main(argc,argv):
  1174.      *
  1175.      *    That's where all the trouble starts.
  1176.      */
  1177.  
  1178. VOID
  1179. main(int argc,char **argv)
  1180. {
  1181.     BOOL         Quiet = FALSE;
  1182.     struct Process    *ThatsMe = (struct Process *)SysBase -> ThisTask;
  1183.  
  1184.         /* Init important pointers. */
  1185.  
  1186.     if(!ThatsMe -> pr_CLI)
  1187.         FromWorkbench = TRUE;
  1188.  
  1189.         /* Are we already running? */
  1190.  
  1191.     DSeg = (struct DSeg *)FindPort(PORTNAME);
  1192.  
  1193.         /* Restart? */
  1194.  
  1195.     if(FromWorkbench && DSeg)
  1196.     {
  1197.         ProcessIcon();
  1198.         exit(RETURN_OK);
  1199.     }
  1200.  
  1201.         /* Yeah... push it! */
  1202.  
  1203.     if(FromWorkbench)
  1204.         goto PushIt;
  1205.  
  1206.         /* Be quiet? */
  1207.  
  1208.     if(argv[ARG_QUIET])
  1209.         Quiet = TRUE;
  1210.  
  1211.         /* No argument and DClock's already running? */
  1212.  
  1213.     if(argc < 2 && DSeg)
  1214.     {
  1215.         Printf("Can't install \33[1mDClock\33[0m, handler process \33[33malready running\33[31m\7!\n");
  1216.  
  1217.         exit(RETURN_OK);
  1218.     }
  1219.  
  1220.         /* Read the system clock? */
  1221.  
  1222.     if(argv[ARG_READCLOCK])
  1223.     {
  1224.         if(!ReadClock() && !Quiet)
  1225.             Puts("\33[1mDClock:\33[0m Could not find battery backed up clock.");
  1226.     }
  1227.  
  1228.         /* User wants information. */
  1229.  
  1230.     if(argv[ARG_INFO])
  1231.     {
  1232.         Printf("\n\33[1m\33[33mDClock\33[0m\33[31m - A \33[33mD\33[31mumb \33[33mClock\33[31m. Renders time and date\n");
  1233.         Printf("         into the Workbench title bar. Place\n");
  1234.         Printf("         \33[33mDClock-Handler\33[31m in L:, \33[33mDClock\33[31m somewhere\n");
  1235.         Printf("         in C: or in SYS:. Type '\33[1m\33[33mDClock\33[31m\33[0m' to\n");
  1236.         Printf("         install, '\33[1m\33[33mDClock quit\33[31m\33[0m' to remove.\n\n");
  1237.         Printf("         \33[33mDClock\33[31m is \33[1mfree\33[0m and in the \33[33m\33[1mPUBLIC-DOMAIN\33[31m\33[0m!\n\n");
  1238.  
  1239.         Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel, MXM\n");
  1240.         Printf("         Brabeckstrasse 35\n");
  1241.         Printf("         D-3000 Hannover 71\n\n");
  1242.  
  1243.         Printf("     Federal Republic of Germany.\n\n");
  1244.  
  1245.         exit(RETURN_OK);
  1246.     }
  1247.  
  1248.         /* Print current release version number. */
  1249.  
  1250.     if(argv[ARG_VERSION])
  1251.     {
  1252.         Printf("\33[1mDClock\33[0m version 1.%ld, created \33[33mSaturday, 15-Sep-90 23:18\33[31m.\n",DSeg ? DSeg -> Revision : REVISION);
  1253.         exit(RETURN_OK);
  1254.     }
  1255.  
  1256.         /* Terminate dumb clock? */
  1257.  
  1258.     if(argv[ARG_QUIT])
  1259.     {
  1260.         Printf("Removing \33[1m\33[33mDClock\33[31m\33[0m (DClock-Handler revision 1.%ld), ",DSeg ? DSeg -> Revision : -1);
  1261.  
  1262.             /* Segment not loaded. */
  1263.  
  1264.         if(!DSeg)
  1265.         {
  1266.             Printf("failed!\7\n");
  1267.             exit(RETURN_FAIL);
  1268.         }
  1269.  
  1270.             /* We are the caller. */
  1271.  
  1272.         DSeg -> Father = (struct Task *)ThatsMe;
  1273.  
  1274.             /* Child still present? */
  1275.  
  1276.         if(DSeg -> Child)
  1277.         {
  1278.             Signal(DSeg -> Child,SIGBREAKF_CTRL_D);
  1279.             Wait(SIGBREAKF_CTRL_D);
  1280.         }
  1281.  
  1282.             /* Remove port and associated data. */
  1283.  
  1284.         RemPort(&DSeg -> Port);
  1285.         FreeMem(DSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
  1286.  
  1287.         if(DSeg -> SoundData && DSeg -> SoundLength)
  1288.             FreeMem(DSeg -> SoundData,DSeg -> SoundLength);
  1289.  
  1290.         FreeMem(DSeg -> SoundSemaphore,sizeof(struct SignalSemaphore));
  1291.  
  1292.         if(DSeg -> Segment)
  1293.             UnLoadSeg(DSeg -> Segment);
  1294.  
  1295.         FreeMem(DSeg,DSeg -> SegSize);
  1296.  
  1297.         Printf("OK.\n");
  1298.  
  1299.         exit(RETURN_OK);
  1300.     }
  1301.  
  1302.         /* Create global communication structure. */
  1303.  
  1304. PushIt:    if(!DSeg)
  1305.     {
  1306.         if(DSeg = (struct DSeg *)AllocMem(sizeof(struct DSeg),MEMF_PUBLIC | MEMF_CLEAR))
  1307.         {
  1308.             ULONG Micros;
  1309.  
  1310.                 /* Dummy MessagePort. */
  1311.  
  1312.             DSeg -> Port . mp_Flags            = PA_IGNORE;
  1313.             DSeg -> Port . mp_Node . ln_Pri        = 1;
  1314.             DSeg -> Port . mp_Node . ln_Type    = NT_MSGPORT;
  1315.             DSeg -> Port . mp_Node . ln_Name    = AllocMem(sizeof(PORTNAME),MEMF_PUBLIC);
  1316.             DSeg -> Child                = NULL;
  1317.             DSeg -> Father                = (struct Task *)ThatsMe;
  1318.             DSeg -> SoundSemaphore            = (struct SignalSemaphore *)AllocMem(sizeof(struct SignalSemaphore),MEMF_PUBLIC | MEMF_CLEAR);
  1319.  
  1320.             if(!DSeg -> Port . mp_Node . ln_Name || !DSeg -> SoundSemaphore)
  1321.                 goto Purge;
  1322.  
  1323.                 /* For future expansion of this structure;
  1324.                  * this will insure that any version of
  1325.                  * DClock will be able to free the memory
  1326.                  * occupied by the segment.
  1327.                  */
  1328.  
  1329.             DSeg -> SegSize            = sizeof(struct DSeg);
  1330.  
  1331.                 /* We'll wait for this signal to come from
  1332.                  * the handler process.
  1333.                  */
  1334.  
  1335.             DSeg -> RingBack        = SIGBREAKF_CTRL_E;
  1336.  
  1337.                 /* Enable beep and disable click feature. */
  1338.  
  1339.             DSeg -> Beep            = TRUE;
  1340.             DSeg -> Click            = FALSE;
  1341.  
  1342.                 /* So we have valid time counter. */
  1343.  
  1344.             CurrentTime(&DSeg -> LastSecs,&Micros);
  1345.  
  1346.                 /* Click volume and handler priority. */
  1347.  
  1348.             DSeg -> ClickVolume        = 64;
  1349.             DSeg -> Priority        = 5;
  1350.  
  1351.                 /* Rendering colours. */
  1352.  
  1353.             DSeg -> TextColour        = 0;
  1354.             DSeg -> BackColour        = 1;
  1355.  
  1356.                 /* Set alarm default. */
  1357.  
  1358.             DSeg -> Alarm            = FALSE;
  1359.  
  1360.             DSeg -> AlarmHour        = 12;
  1361.             DSeg -> AlarmMinute        = 0;
  1362.             DSeg -> AlarmSecond        = 0;
  1363.  
  1364.                 /* Disable countdown & hour chime. */
  1365.  
  1366.             DSeg -> Countdown        = 0;
  1367.             DSeg -> Hour            = FALSE;
  1368.  
  1369.                 /* Seconds are by default enabled. */
  1370.  
  1371.             DSeg -> Seconds            = TRUE;
  1372.  
  1373.                 /* Set environment variables. */
  1374.  
  1375.             DSeg -> SetEnv            = FALSE;
  1376.  
  1377.                 /* Install the current revision number. */
  1378.  
  1379.             DSeg -> Revision        = REVISION;
  1380.  
  1381.                 /* Init port. */
  1382.  
  1383.             strcpy(DSeg -> Port . mp_Node . ln_Name,PORTNAME);
  1384.  
  1385.             if(!FromWorkbench)
  1386.                 Printf("Installing \33[33m\33[1mDClock\33[0m\33[31m, ");
  1387.  
  1388.                 /* Load the handler code. */
  1389.  
  1390.             DSeg -> Segment = LoadSeg("DClock-Handler");
  1391.  
  1392.             if(!DSeg -> Segment)
  1393.                 DSeg -> Segment = LoadSeg("L:DClock-Handler");
  1394.  
  1395.             if(!DSeg -> Segment)
  1396.             {
  1397.                 if(!FromWorkbench)
  1398.                     Printf("unable to find \33[33mL:DClock-Handler\33[31m\7!\n");
  1399.                 else
  1400.                     PopRequest(NULL,"DClock problem:","Can't find \33[1m\"DClock-Handler\"\33[0m!\nCheck L: and current directory.",NULL,"Continue?",FALSE,NULL);
  1401.  
  1402. Purge:                if(DSeg)
  1403.                 {
  1404.                     if(DSeg -> Port . mp_Node . ln_Name)
  1405.                         FreeMem(DSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
  1406.  
  1407.                     if(DSeg -> SoundSemaphore)
  1408.                         FreeMem(DSeg -> SoundSemaphore,sizeof(struct SignalSemaphore));
  1409.  
  1410.                     FreeMem(DSeg,DSeg -> SegSize);
  1411.                 }
  1412.             }
  1413.             else
  1414.             {
  1415.                     /* Install the port and start the handler. */
  1416.  
  1417.                 AddPort(&DSeg -> Port);
  1418.  
  1419.                 CreateProc("DClock-Handler",DSeg -> Priority,DSeg -> Segment,4096);
  1420.  
  1421.                     /* Wait for child task to ring back... */
  1422.  
  1423.                 Wait(SIGBREAKF_CTRL_E);
  1424.  
  1425.                 if(!DSeg -> Child)
  1426.                 {
  1427.                     if(!FromWorkbench)
  1428.                         Printf("\33[33mFAILED!\33[31m (care to retry?)\n");
  1429.                     else
  1430.                         PopRequest(NULL,"DClock problem:","Handler process didn't reply startup-message.",NULL,"Continue?",FALSE,NULL);
  1431.  
  1432.                     RemPort(&DSeg -> Port);
  1433.                     FreeMem(DSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
  1434.  
  1435.                     if(DSeg -> Segment)
  1436.                         UnLoadSeg(DSeg -> Segment);
  1437.  
  1438.                     FreeMem(DSeg,DSeg -> SegSize);
  1439.  
  1440.                     if(FromWorkbench)
  1441.                         Delay(TICKS_PER_SECOND * 2);
  1442.  
  1443.                     exit(RETURN_FAIL);
  1444.                 }
  1445.                 else
  1446.                 {
  1447.                     if(!FromWorkbench)
  1448.                         Printf("\33[3mOkay. \33[0m\33[33mDClock v1.%ld\33[31m, by \33[4mMXM\33[0m. \33[1mPUBLIC DOMAIN\33[0m.\n",REVISION);
  1449.                     else
  1450.                         PopRequest(NULL,"DClock Message:","Handler process successfully installed!\n\n\33[33mDClock\33[31m (C) Copyright 1989, 1990 \33[3mby MXM.\33[0m \33[1mPUBLIC DOMAIN\33[0m.",NULL,"Continue?",FALSE,NULL);
  1451.                 }
  1452.             }
  1453.         }
  1454.     }
  1455.  
  1456.         /* Deal with the icon... */
  1457.  
  1458.     if(FromWorkbench)
  1459.     {
  1460.         ProcessIcon();
  1461.         exit(RETURN_OK);
  1462.     }
  1463.  
  1464.         /* Change click volume. */
  1465.  
  1466.     if(argv[ARG_CLICKVOLUME] && DSeg)
  1467.     {
  1468.         if(Atol(argv[ARG_CLICKVOLUME]) >= 0 && Atol(argv[ARG_CLICKVOLUME]) <= 64 )
  1469.         {
  1470.             if(!Quiet)
  1471.                 Printf("\33[1mDClock:\33[0m Click volume set to %ld.\n",DSeg -> ClickVolume = Atol(argv[ARG_CLICKVOLUME]));
  1472.         }
  1473.         else
  1474.             Puts(CLI_Help);
  1475.     }
  1476.  
  1477.         /* Change handler priority? */
  1478.  
  1479.     if(argv[ARG_PRIORITY] && DSeg)
  1480.     {
  1481.         if(DSeg -> Child)
  1482.         {
  1483.             if(!Quiet)
  1484.                 Printf("\33[1mDClock:\33[0m Handler priority set to %ld.\n",DSeg -> Priority = Atol(argv[ARG_PRIORITY]));
  1485.  
  1486.             SetTaskPri(DSeg -> Child,DSeg -> Priority);
  1487.         }
  1488.         else
  1489.             Puts("\33[1mDClock:\33[0m Unable to find handler task.");
  1490.     }
  1491.  
  1492.         /* Turn beeping on/off? */
  1493.  
  1494.     if(argv[ARG_BEEP] && DSeg)
  1495.     {
  1496.         if(!Strcmp(argv[ARG_BEEP],"OFF"))
  1497.         {
  1498.             if(!Quiet)
  1499.                 Puts("\33[1mDClock:\33[0m Beep disabled.");
  1500.  
  1501.             DSeg -> Beep = FALSE;
  1502.         }
  1503.         else
  1504.         {
  1505.             if(!Strcmp(argv[ARG_BEEP],"ON"))
  1506.             {
  1507.                 if(!Quiet)
  1508.                     Puts("\33[1mDClock:\33[0m Beep enabled.");
  1509.  
  1510.                 DSeg -> Beep = TRUE;
  1511.             }
  1512.             else
  1513.                 Puts(CLI_Help);
  1514.         }
  1515.     }
  1516.  
  1517.         /* Turn clicking on/off? */
  1518.  
  1519.     if(argv[ARG_CLICK])
  1520.     {
  1521.         if(!Strcmp(argv[ARG_CLICK],"OFF"))
  1522.         {
  1523.             if(!Quiet)
  1524.                 Puts("\33[1mDClock:\33[0m Click disabled.");
  1525.  
  1526.             DSeg -> Click = FALSE;
  1527.         }
  1528.         else
  1529.         {
  1530.             if(!Strcmp(argv[ARG_CLICK],"ON"))
  1531.             {
  1532.                 if(!Quiet)
  1533.                     Puts("\33[1mDClock:\33[0m Click enabled.");
  1534.  
  1535.                 DSeg -> Click = TRUE;
  1536.             }
  1537.             else
  1538.                 Puts(CLI_Help);
  1539.         }
  1540.     }
  1541.  
  1542.         /* Select new front colour? */
  1543.  
  1544.     if(argv[ARG_TEXTCOLOUR])
  1545.     {
  1546.         DSeg -> TextColour = Atol(argv[ARG_TEXTCOLOUR]);
  1547.  
  1548.         if(!Quiet)
  1549.             Printf("\33[1mDClock:\33[0m Text colour set to %ld.\n",DSeg -> TextColour);
  1550.     }
  1551.  
  1552.         /* Select new background colour? */
  1553.  
  1554.     if(argv[ARG_BACKCOLOUR])
  1555.     {
  1556.         DSeg -> BackColour = Atol(argv[ARG_BACKCOLOUR]);
  1557.  
  1558.         if(!Quiet)
  1559.             Printf("\33[1mDClock:\33[0m Background colour set to %ld.\n",DSeg -> BackColour);
  1560.     }
  1561.  
  1562.         /* Set/check alarm status. */
  1563.  
  1564.     if(argv[ARG_ALARM])
  1565.     {
  1566.         if(!Strcmp(argv[ARG_ALARM],"OFF"))
  1567.         {
  1568.             if(!Quiet)
  1569.                 Puts("\33[1mDClock:\33[0m Alarm disabled.");
  1570.  
  1571.             DSeg -> Alarm = FALSE;
  1572.         }
  1573.         else
  1574.         {
  1575.             if(!Strcmp(argv[ARG_ALARM],"ON"))
  1576.             {
  1577.                 if(!Quiet)
  1578.                     Puts("\33[1mDClock:\33[0m Alarm enabled.");
  1579.  
  1580.                 DSeg -> Alarm = TRUE;
  1581.             }
  1582.             else
  1583.             {
  1584.                 if(!Strcmp(argv[ARG_ALARM],"SHOW"))
  1585.                     Printf("\33[1mDClock:\33[0m Current alarm time is %02ld:%02ld:%02ld.\n",DSeg -> AlarmHour,DSeg -> AlarmMinute,DSeg -> AlarmSecond);
  1586.                 else
  1587.                     Puts(CLI_Help);
  1588.             }
  1589.         }
  1590.     }
  1591.  
  1592.         /* Adjust alarm time. */
  1593.  
  1594.     if(argv[ARG_ALARMTIME])
  1595.     {
  1596.         char TimeBuff[3];
  1597.         LONG TheTime;
  1598.  
  1599.         TimeBuff[2] = 0;
  1600.  
  1601.         if(strlen(argv[ARG_ALARMTIME]) != 8)
  1602.         {
  1603.             Puts("\33[1mDClock:\33[0m Alarm time format = HH:MM:SS, example: 09:03:07.");
  1604.             exit(RETURN_ERROR);
  1605.         }
  1606.  
  1607.         TimeBuff[0] = argv[ARG_ALARMTIME][0];
  1608.         TimeBuff[1] = argv[ARG_ALARMTIME][1];
  1609.  
  1610.         TheTime = Atol(TimeBuff);
  1611.  
  1612.         if(TheTime < 0 || TheTime > 23)
  1613.         {
  1614.             Puts("\33[1mDClock:\33[0m Illegal time value, Hours must be within 0 ... 23.");
  1615.             exit(RETURN_ERROR);
  1616.         }
  1617.  
  1618.         DSeg -> AlarmHour    = TheTime;
  1619.  
  1620.         TimeBuff[0] = argv[ARG_ALARMTIME][3];
  1621.         TimeBuff[1] = argv[ARG_ALARMTIME][4];
  1622.  
  1623.         TheTime = Atol(TimeBuff);
  1624.  
  1625.         if(TheTime < 0 || TheTime > 59)
  1626.         {
  1627.             Puts("\33[1mDClock:\33[0m Illegal time value, Minutes must be within 0 ... 59.");
  1628.             exit(RETURN_ERROR);
  1629.         }
  1630.  
  1631.         DSeg -> AlarmMinute    = TheTime;
  1632.  
  1633.         TimeBuff[0] = argv[ARG_ALARMTIME][6];
  1634.         TimeBuff[1] = argv[ARG_ALARMTIME][7];
  1635.  
  1636.         TheTime = Atol(TimeBuff);
  1637.  
  1638.         if(TheTime < 0 || TheTime > 59)
  1639.         {
  1640.             Puts("\33[1mDClock:\33[0m Illegal time value, Seconds must be within 0 ... 59.");
  1641.             exit(RETURN_ERROR);
  1642.         }
  1643.  
  1644.         DSeg -> AlarmSecond    = TheTime;
  1645.  
  1646.         if(!Quiet)
  1647.             Printf("\33[1mDClock:\33[0m Alarm time set to %02ld:%02ld:%02ld.\n",DSeg -> AlarmHour,DSeg -> AlarmMinute,DSeg -> AlarmSecond);
  1648.     }
  1649.  
  1650.     if(argv[ARG_REFRESH])
  1651.     {
  1652.         if(CloseWorkBench())
  1653.             OpenWorkBench();
  1654.  
  1655.         if(!Quiet)
  1656.             Puts("\33[1mDClock:\33[0m Main window refreshed.");
  1657.     }
  1658.  
  1659.         /* Set environment variables? */
  1660.  
  1661.     if(argv[ARG_SETENV])
  1662.     {
  1663.         if(!Strcmp(argv[ARG_SETENV],"OFF"))
  1664.         {
  1665.             if(!Quiet)
  1666.                 Puts("\33[1mDClock:\33[0m Environment variables disabled.");
  1667.  
  1668.             DSeg -> SetEnv = FALSE;
  1669.         }
  1670.         else
  1671.         {
  1672.             if(!Strcmp(argv[ARG_SETENV],"ON"))
  1673.             {
  1674.                 if(!Quiet)
  1675.                     Puts("\33[1mDClock:\33[0m Environment variables enabled.");
  1676.  
  1677.                 DSeg -> SetEnv = TRUE;
  1678.             }
  1679.             else
  1680.                 Puts(CLI_Help);
  1681.         }
  1682.     }
  1683.  
  1684.         /* Set countdown timeout? */
  1685.  
  1686.     if(argv[ARG_COUNTDOWN])
  1687.     {
  1688.         if(Atol(argv[ARG_COUNTDOWN]) > 0)
  1689.         {
  1690.             DSeg -> Countdown = Atol(argv[ARG_COUNTDOWN]);
  1691.  
  1692.             if(!Quiet)
  1693.                 Printf("\33[1mDClock:\33[0m Countdown set to %ld.\n",DSeg -> Countdown);
  1694.         }
  1695.         else
  1696.             Puts(CLI_Help);
  1697.     }
  1698.  
  1699.         /* Enable/disable the hour chime? */
  1700.  
  1701.     if(argv[ARG_HOUR])
  1702.     {
  1703.         if(!Strcmp(argv[ARG_HOUR],"OFF"))
  1704.         {
  1705.             if(!Quiet)
  1706.                 Puts("\33[1mDClock:\33[0m Hour chime disabled.");
  1707.  
  1708.             DSeg -> Hour = FALSE;
  1709.         }
  1710.         else
  1711.         {
  1712.             if(!Strcmp(argv[ARG_HOUR],"ON"))
  1713.             {
  1714.                 if(!Quiet)
  1715.                     Puts("\33[1mDClock:\33[0m Hour chime enabled.");
  1716.  
  1717.                 DSeg -> Hour = TRUE;
  1718.             }
  1719.             else
  1720.                 Puts(CLI_Help);
  1721.         }
  1722.     }
  1723.  
  1724.         /* Display seconds or not? */
  1725.  
  1726.     if(argv[ARG_SECONDS])
  1727.     {
  1728.         if(!Strcmp(argv[ARG_SECONDS],"OFF"))
  1729.         {
  1730.             if(!Quiet)
  1731.                 Puts("\33[1mDClock:\33[0m Seconds disabled.");
  1732.  
  1733.             DSeg -> Seconds = FALSE;
  1734.         }
  1735.         else
  1736.         {
  1737.             if(!Strcmp(argv[ARG_SECONDS],"ON"))
  1738.             {
  1739.                 if(!Quiet)
  1740.                     Puts("\33[1mDClock:\33[0m Seconds enabled.");
  1741.  
  1742.                 DSeg -> Seconds = TRUE;
  1743.             }
  1744.             else
  1745.                 Puts(CLI_Help);
  1746.         }
  1747.     }
  1748.  
  1749.         /* Load a sound file? */
  1750.  
  1751.     if(argv[ARG_SOUND])
  1752.     {
  1753.         if(LoadChimeSound(argv[ARG_SOUND]))
  1754.         {
  1755.             if(!Strcmp(argv[ARG_SOUND],"OFF") && !Quiet)
  1756.                 Puts("\33[1mDClock:\33[0m Chime sound reset.");
  1757.         }
  1758.     }
  1759.  
  1760.         /* Show a special page on startup? */
  1761.  
  1762.     if(argv[ARG_PAGE] && DSeg)
  1763.     {
  1764.         UBYTE Page = Atol(argv[ARG_PAGE]);
  1765.  
  1766.         if(Page >= 0 && Page <= 4 || (Page == 4 && DSeg -> Countdown > 0))
  1767.         {
  1768.             if(!Quiet)
  1769.                 Printf("\33[1mDClock:\33[0m Showing display page %ld.\n",DSeg -> Page = Page);
  1770.         }
  1771.         else
  1772.             Puts("\33[1mDClock:\33[0m Page value out of limits (must be 0-3/4).");
  1773.     }
  1774.  
  1775.         /* Turn the speech on/off? */
  1776.  
  1777.     if(argv[ARG_SPEECH])
  1778.     {
  1779.         if(!Strcmp(argv[ARG_SPEECH],"OFF"))
  1780.         {
  1781.             if(!Quiet)
  1782.                 Puts("\33[1mDClock:\33[0m Speech now off.");
  1783.  
  1784.             DSeg -> Speech = FALSE;
  1785.         }
  1786.         else
  1787.         {
  1788.             if(!Strcmp(argv[ARG_SPEECH],"ON"))
  1789.             {
  1790.                 if(!Quiet)
  1791.                     Puts("\33[1mDClock:\33[0m Speech now on.");
  1792.  
  1793.                 DSeg -> Speech = TRUE;
  1794.             }
  1795.             else
  1796.                 Puts(CLI_Help);
  1797.         }
  1798.     }
  1799.  
  1800.     exit(RETURN_OK);
  1801. }
  1802.