home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 1 / Mecomp-CD.iso / amiga / tools / uhren / tolleuhr / source / tolleuhr.c < prev   
Encoding:
C/C++ Source or Header  |  1997-07-05  |  86.5 KB  |  2,931 lines

  1. #define VERSION "1.7 (5.7.97)"
  2. /***************************************************************************
  3. *                                  *                                       *
  4. * Programm: TolleUhr               * Version: s.o.                         *
  5. *                                  *                                       *
  6. ****************************************************************************
  7. *                                                                          *
  8. * Dieses Programm ist Public-Domain, d.h. wer immer Lust dazu hat, darf    *
  9. * dieses Programm kopieren, umschreiben, usw., vorausgesetzt:              *
  10. *                                                                          *
  11. * 1. Die Autorenliste bleibt voll erhalten. (auch in About-Requestern)     *
  12. * 2. Wer etwas am Programm verbricht, muß sich auch dazuschreiben.         *
  13. *                                                                          *
  14. * Es wird keine Haftung für Schäden irgendwelcher Art übernommen.          *
  15. *                                                                          *
  16. * Autoren: Matthias Fleischer  Adlerstraße 30 7302 Ostfildern 2            *
  17. *          (fleischr@izfm.uni-stuttgart.de)                                *
  18. *          .                                                               *
  19. *          .(Auf Paul, schaff was !)                                       *
  20. *                                                                          *
  21. *          Gunther Nikl  Ziegendorfer Chaussee 96 19370 Parchim            *
  22. *          (gnikl@informatik.uni-rostock.de)                               *
  23. *                                                                          *
  24. ***************************************************************************/
  25.  
  26. /***************************************************************************/
  27. /*                                                                         */
  28. /* includes                                                                */
  29. /*                                                                         */
  30. /***************************************************************************/
  31.  
  32. #include <exec/types.h>
  33.  
  34. #ifndef REG
  35. #define REG(x) asm(#x)
  36. #endif
  37. #ifndef CONST
  38. #define CONST const
  39. #endif
  40. #ifndef INLINE
  41. #define INLINE inline
  42. #endif
  43.  
  44. #include <dos/dos.h>
  45. #include <dos/rdargs.h>
  46. #include <dos/datetime.h>
  47. #include <exec/tasks.h>
  48. #include <exec/memory.h>
  49. #include <exec/execbase.h>
  50. #include <rexx/storage.h>
  51. #include <devices/audio.h>
  52. #include <devices/timer.h>
  53. #include <hardware/cia.h>
  54. #include <prefs/prefhdr.h>
  55. #include <prefs/wbpattern.h>
  56. #include <graphics/gfxmacros.h>
  57. #include <intuition/intuition.h>
  58. #include <intuition/gadgetclass.h>
  59. #include <libraries/screennotify.h>
  60. #include <datatypes/pictureclass.h>
  61. #include <datatypes/pictureclassext.h>
  62. #include <libraries/gadtools.h>
  63. #include <workbench/startup.h>
  64. #include <workbench/workbench.h>
  65. #include <clib/alib_protos.h>
  66. #include <clib/macros.h>
  67.  
  68. /*
  69. ** structure definitions now !
  70. */
  71.  
  72. struct gInfo {
  73.   WORD  left,top,width,height;
  74.   UWORD textnr,kind;
  75. };
  76.  
  77. struct wInfo {
  78.   UWORD        idcmp,textnr,gadcnt;
  79.   struct gInfo gi[1];
  80. };
  81.  
  82. struct WinGad {
  83.   struct Window *Win;
  84.   struct Gadget *Gad;
  85. };
  86.  
  87. struct DateTimeInfo {
  88.   struct DateTime dat;
  89.   UBYTE           buf[34];
  90. };
  91.  
  92. struct BackFillInfo {
  93.   STRPTR               PictureName;
  94.   Object              *PictureObject;
  95.   struct BitMapHeader *BitMapHeader;
  96.   struct BitMap       *ImageBitMap,
  97.                       *SnapBitMap,
  98.                       *BitMap;
  99.   ULONG                Width,Height;
  100. };
  101.  
  102. /*
  103. **  sizeof(struct Globals) _MUST_ be a multiple of 4 !
  104. */
  105.  
  106. struct Globals {
  107.  
  108.   /*** library stuff ***/
  109.  
  110.   struct ExecBase      *SysBase;
  111.   struct DosLibrary    *DOSBase;
  112.   struct IntuitionBase *IntuitionBase;
  113.   struct GfxBase       *GfxBase;
  114.   struct Library       *GadtoolsBase,
  115.                        *IconBase,
  116.                        *DataTypesBase;
  117.   struct LocaleBase    *LocaleBase;
  118.   struct Catalog       *Catalog;
  119.  
  120.   /*** misc stuff ***/
  121.  
  122.   STRPTR                NameBuf,
  123.                         PubName;
  124.   BPTR                  OldLock;
  125.   LONG                  OldPri;
  126.  
  127.   /*** device stuff ***/
  128.  
  129.   struct MsgPort       *WindowPort,
  130.                        *RexxPort;
  131.   struct MsgPort       *TimerPort;
  132.   struct timerequest   *TimerIO;
  133.   struct MsgPort       *AudioPort;
  134.   struct IOAudio       *AudioIO[2];
  135.   APTR                  WaveForm;
  136.  
  137.   /*** graphic stuff ***/
  138.  
  139.   APTR                  VisualInfo;
  140.   struct Menu          *Menus;
  141.   struct Window        *MainWin;
  142.   struct RastPort      *RPort;
  143.   struct WinGad         ColorWin,
  144.                         AlarmWin;
  145.   struct Window        *AboutReq;
  146.  
  147.   /*** screen notify ***/
  148.  
  149.   struct Library       *ScreenNotifyBase;
  150.   struct MsgPort       *NotifyPort;
  151.   APTR                  NotifyHandle;
  152.  
  153.   /*** common variables ***/
  154.  
  155.   LONG                  Left,
  156.                         Top,
  157.                         Width,
  158.                         Height,
  159.                         BoLeft,
  160.                         BoTop,
  161.                         Width2,
  162.                         Height2,
  163.                         Depth,
  164.                         ReDrawx1,
  165.                         ReDrawy1,
  166.                         ReDrawx2,
  167.                         ReDrawy2,
  168.                         xMask,
  169.                         yMask;
  170.   PLANEPTR              Buf;
  171.   UWORD                *PlayTune;
  172.   UBYTE                *Color;
  173.   LONG                  Std,
  174.                         Std24,
  175.                         Min,
  176.                         Sec,
  177.                         AlStd,
  178.                         AlMin,
  179.                         St,
  180.                         Mi,
  181.                         xOffset,
  182.                         yOffset;
  183.   WORD                  GadSize;
  184.   UWORD                 ImgType;
  185.  
  186.   /*** flags ***/
  187.  
  188.   BYTE                  TimerOpen,
  189.                         TimerSent,
  190.                         AudioOpen,
  191.                         AudioSent[2],
  192.                         SoundOn,
  193.                         xDouble,
  194.                         yDouble,
  195.                         ChangedDir,
  196.                         ChangedPri,
  197.                         Active,
  198.                         Alarm,
  199.                         Filter,
  200.                         HiRes,
  201.                         Interlace,
  202.                         SmartHour,
  203.                         GoOn,
  204.                         CloseGad,
  205.                         Backdrop,
  206.                         Activate,
  207.                         Fixed,
  208.                         UseImage,
  209.                         Snap,
  210.                         V39,
  211.                         Hidden;
  212.   UBYTE                 Seconds,
  213.                         Oval,
  214.                         Show,
  215.                         HandType,
  216.                         HandWidth,
  217.                         Shadow,
  218.                         BorderCount,
  219.                         Chime,
  220.                         Remap,
  221.                         RequestNr,
  222.                         ScrNotify;
  223.  
  224.   /*** structures ***/
  225.  
  226.   struct BackFillInfo   BFInfo;
  227.   struct WBArg          ProgArg;
  228.   UBYTE                 Pens[14+4+2];
  229.   struct NewWindow      NewWindowBuf;
  230.   struct Gadget         GadgetBuf[4];
  231.   struct RastPort       RPort1;
  232.   struct TmpRas         TempRas;
  233.   struct AreaInfo       AreaInfo;
  234.   UWORD                 Table[14],
  235.                         Muster[8][2];
  236.   struct NewGadget      NewGad;
  237.   UWORD                 wPad;
  238.   struct EasyStruct     EasyBuf;
  239.   struct DateTimeInfo   DateTime;
  240. };
  241.  
  242. #define PUB_SCREEN (gb->NewWindowBuf.Screen)
  243. #define RP1_BITMAP (gb->RPort1.BitMap)
  244.  
  245. /*
  246. ** ptr to the `global' data space (will be on the stack 8-)
  247. */
  248.  
  249. REGISTER struct Globals *gb REG(a4);
  250.  
  251. /*
  252. ** redirect library bases to the `global' data space
  253. */
  254.  
  255. #define BASE_NAME gb->ScreenNotifyBase
  256. #include <proto/screennotify.h>
  257. #undef BASE_NAME
  258.  
  259. #define BASE_NAME gb->LocaleBase
  260. #include <proto/locale.h>
  261. #undef BASE_NAME
  262.  
  263. #define BASE_NAME gb->DataTypesBase
  264. #include <proto/datatypes.h>
  265. #undef BASE_NAME
  266.  
  267. #define BASE_NAME gb->IntuitionBase
  268. #include <proto/intuition.h>
  269. #undef BASE_NAME
  270.  
  271. #define BASE_NAME gb->GadtoolsBase
  272. #include <proto/gadtools.h>
  273. #undef BASE_NAME
  274.  
  275. #define BASE_NAME gb->GfxBase
  276. #include <proto/graphics.h>
  277. #undef BASE_NAME
  278.  
  279. #define BASE_NAME gb->IconBase
  280. #include <proto/icon.h>
  281. #undef BASE_NAME
  282.  
  283. #define BASE_NAME gb->SysBase
  284. #include <proto/exec.h>
  285. #undef BASE_NAME
  286.  
  287. #define BASE_NAME gb->DOSBase
  288. #include <proto/dos.h>
  289. #undef BASE_NAME
  290.  
  291. #include <proto/iffparse.h>
  292. #include <proto/timer.h>
  293.  
  294. /*
  295. ** strcpy() && strlen()
  296. */
  297.  
  298. #include <string.h>
  299.  
  300. /*
  301. ** locale string numbers
  302. */
  303.  
  304. #include "tolleuhr_locale.h"
  305.  
  306. /***************************************************************************/
  307. /*                                                                         */
  308. /* prototypes                                                              */
  309. /*                                                                         */
  310. /***************************************************************************/
  311.  
  312. VOID AddScreenNotify();
  313. LONG OpenMainWindow();
  314. VOID SnapBackground();
  315. VOID LoadImage();
  316. LONG MakeMenus();
  317. LONG InitClock();
  318. LONG GetArguments(struct WBStartup *);
  319. VOID MergeToolTypes();
  320. VOID ParseArgs(STRPTR,LONG);
  321. VOID ReadStr(UBYTE *,UBYTE *,UBYTE *,LONG);
  322. LONG XtoD(LONG);
  323. struct MsgPort *CreateRexxPort();
  324. LONG OpenDevs();
  325. LONG OpenLibs();
  326. VOID Main();
  327. VOID CloseLibs();
  328. VOID CloseDevs();
  329. VOID DeleteRexxPort();
  330. VOID DeleteBitMap(struct BitMap *,ULONG);
  331. VOID NewSize1();
  332. VOID CloseAboutReq();
  333. VOID CloseGfx();
  334. VOID FreeWindow(struct WinGad *);
  335. VOID CloseWindowSafely(struct Window *);
  336. VOID RemScreenNotify();
  337. VOID CheckNotify();
  338. VOID CheckRexx();
  339. VOID CheckAboutReq();
  340. VOID CheckWindows();
  341. VOID HandleMenus(ULONG);
  342. struct BitMap *CreateBitMap(ULONG,ULONG,ULONG);
  343. LONG NewSize2();
  344. VOID NewTitle();
  345. ULONG NextTick();
  346. VOID Rahmen();
  347. VOID ZifferBlatt();
  348. VOID Zeiger(ULONG,LONG,LONG,LONG,LONG);
  349. VOID Zeichnen();
  350. VOID SetPattern();
  351. VOID SaveSettings();
  352. STRPTR SetToolType(STRPTR,STRPTR,LONG,...);
  353. STRPTR GetToolType(LONG);
  354. STRPTR SetStr(STRPTR,STRPTR,LONG);
  355. LONG DtoX(LONG);
  356. VOID TestIfAlarm();
  357. VOID StartTune(CONST UWORD *);
  358. VOID PlayNote();
  359. VOID EndTune();
  360. VOID CreateRequest(struct WinGad *,struct wInfo *,struct TagItem **);
  361. struct Window *OpenWindowShared(struct NewWindow *,CONST struct TagItem *,ULONG);
  362. STRPTR GetCatalogString(LONG);
  363. VOID CopyTiledBitMap(struct BitMap *,LONG,LONG,struct BitMap *,LONG,LONG,LONG,LONG);
  364.  
  365. /*
  366. ** replacements
  367. */
  368.  
  369. LONG blt_bitmap(struct BitMap *,LONG,LONG,struct BitMap *,LONG,LONG,LONG,LONG);
  370. Object *new_dt_object(APTR name,ULONG,...);
  371. ULONG get_dt_attrs(Object *,ULONG,...);
  372. VOID sprintf(STRPTR,STRPTR,...);
  373.  
  374. /***************************************************************************/
  375. /*                                                                         */
  376. /* `global' defines                                                        */
  377. /*                                                                         */
  378. /***************************************************************************/
  379.  
  380. #define ciaa (*((struct CIA *)0xbfe001L))
  381.  
  382. #define GB_GADCOUNT (sizeof(gb->GadgetBuf)/sizeof(struct Gadget))
  383.  
  384. enum {
  385.   WT_CLOSEGAD=1,WT_BACKDROP=2,WT_FIXED=4,WT_USEIMAGE=8,WT_SNAP=16,WT_LAST=32
  386. };
  387.  
  388. #define MUST 14
  389.  
  390. /***************************************************************************/
  391. /*                                                                         */
  392. /* get bitmap depth (use a V39+ function if available)                     */
  393. /*                                                                         */
  394. /***************************************************************************/
  395.  
  396. STATIC INLINE ULONG GetBitMapDepth(struct BitMap *bm)
  397. { ULONG d = bm->Depth;
  398.  
  399.   if (gb->V39)
  400.     d = GetBitMapAttr(bm,BMA_DEPTH);
  401.   return d;
  402. }
  403.  
  404. /***************************************************************************/
  405. /*                                                                         */
  406. /* memory clear function (!!! caution: size _MUST_ be a multiple of 4 !!!) */
  407. /*                                                                         */
  408. /***************************************************************************/
  409.  
  410. STATIC INLINE VOID MEMZEROL(VOID *mem,ULONG size)
  411. { ULONG *p;
  412.   WORD s;
  413.  
  414.   for(p=(ULONG *)mem,s=(size/sizeof(ULONG))-1; s>=0; *p++=0,s--);
  415. }
  416.  
  417. /***************************************************************************/
  418. /*                                                                         */
  419. /* implementation (!!! DO NOT PLACE ANY FUNCTION BEFORE Start() !!!)       */
  420. /*                                                                         */
  421. /***************************************************************************/
  422.  
  423. LONG Start()
  424. { struct Globals globals;
  425.  
  426.   MEMZEROL(&globals,sizeof(struct Globals)); gb = &globals;
  427.  
  428.   gb->SysBase = *(struct ExecBase **)4L;
  429.  
  430.   Main();
  431.  
  432.   return 0;
  433. }
  434.  
  435. /***************************************************************************/
  436. /*                                                                         */
  437. /* version string                                                          */
  438. /*                                                                         */
  439. /***************************************************************************/
  440.  
  441. CONST UBYTE Version[] = "$VER: TolleUhr "VERSION" by M.Fleischer and G.Nikl in 1993/97";
  442.  
  443. #define PROGNAME ((UBYTE *)(&Version[6]))
  444.  
  445. /***************************************************************************/
  446. /*                                                                         */
  447. /* install screen notification (if desired and possible)                   */
  448. /*                                                                         */
  449. /***************************************************************************/
  450.  
  451. VOID AddScreenNotify()
  452. { struct PubScreenNode *pubnode;
  453.  
  454.   if ((pubnode=(struct PubScreenNode *)FindName(LockPubScreenList(),"Workbench")) != NULL)
  455.     if (pubnode->psn_Screen != PUB_SCREEN)
  456.       pubnode=NULL;
  457.   UnlockPubScreenList();
  458.  
  459.   if (pubnode != NULL)
  460.     if ((gb->ScreenNotifyBase=OpenLibrary(SCREENNOTIFY_NAME,0)) != NULL) {
  461.       if ((gb->NotifyPort=CreateMsgPort()) != NULL)
  462.         if ((gb->NotifyHandle=AddWorkbenchClient(gb->NotifyPort,0)) != NULL)
  463.           return;
  464.       RemScreenNotify();
  465.     }
  466. }
  467.  
  468. /***************************************************************************/
  469. /*                                                                         */
  470. /* open clock window                                                       */
  471. /*                                                                         */
  472. /***************************************************************************/
  473.  
  474. #define MAINIDCMP (IDCMP_CHANGEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK | \
  475.                    IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW)
  476.  
  477. CONST struct TagItem WindowTags[] = {
  478.   { WA_InnerWidth,         148 },
  479.   { WA_InnerHeight,         72 },
  480.   { WA_AutoAdjust,        TRUE },
  481.   { TAG_DONE,             NULL }
  482. };
  483.  
  484. LONG OpenMainWindow()
  485. { struct NewWindow *nw;
  486.   struct Window *win;
  487.  
  488.   nw = &gb->NewWindowBuf;
  489.  
  490.   nw->LeftEdge    = gb->Left;
  491.   nw->TopEdge     = gb->Top;
  492.   nw->Width       = gb->Width;
  493.   nw->Height      = gb->Height;
  494.   nw->BlockPen    = 1;
  495.   nw->Flags       = WFLG_SIMPLE_REFRESH | WFLG_BORDERLESS | WFLG_NEWLOOKMENUS |
  496.                     (gb->Backdrop ? WFLG_BACKDROP : 0) | (gb->Activate ? WFLG_ACTIVATE : 0);
  497.   nw->FirstGadget = NULL;
  498.   nw->Title       = NULL;
  499.   nw->MinWidth    = 10;
  500.   nw->MinHeight   = 10;
  501.   nw->MaxWidth    = 65535;
  502.   nw->MaxHeight   = 65535;
  503.   nw->Type        = PUBLICSCREEN;
  504.  
  505.   if ((gb->MainWin=(win=OpenWindowShared(nw,&WindowTags[2],MAINIDCMP))) != NULL) {
  506.     PUB_SCREEN = win->WScreen;
  507.     gb->RPort  = win->RPort;
  508.     SetMenuStrip(win,gb->Menus);
  509.     if (!gb->BFInfo.ImageBitMap)
  510.       OffMenu(win,FULLMENUNUM(1,8,3));
  511.     SetAPen(gb->RPort,gb->Pens[0]);
  512.     if (NewSize2()) {
  513.       NextTick();
  514.       NewTitle();
  515.       Rahmen();
  516.       ZifferBlatt();
  517.       Zeichnen();
  518.       return TRUE;
  519.     }
  520.   }
  521.   return FALSE;
  522. }
  523.  
  524. /***************************************************************************/
  525. /*                                                                         */
  526. /* snap screen background to be used as window image                       */
  527. /*                                                                         */
  528. /***************************************************************************/
  529.  
  530. VOID SnapBackground()
  531. { struct Screen *scr = PUB_SCREEN;
  532.   struct BitMap *bm;
  533.   LONG w,h,t,l,sw,sh;
  534.  
  535.   if ((w=gb->Width) > (sw=scr->Width))
  536.     w = sw;
  537.  
  538.   if ((l=gb->Left) > sw || l+w > sw)
  539.     l = sw - w;
  540.  
  541.   if ((h=gb->Height) > (sh=scr->Height))
  542.     h = sh;
  543.  
  544.   if ((t=gb->Top) > sh || t+h > sh)
  545.     t = sh - h;
  546.  
  547.   if ((gb->BFInfo.SnapBitMap=(bm=CreateBitMap(w,h,GetBitMapDepth(scr->RastPort.BitMap)))) != NULL)
  548.     { BltBitMap(scr->RastPort.BitMap,l,t,bm,0,0,w,h,0xC0,-1,NULL); gb->UseImage=0; }
  549. }
  550.  
  551. /***************************************************************************/
  552. /*                                                                         */
  553. /* load background image via datatypes                                     */
  554. /*                                                                         */
  555. /***************************************************************************/
  556.  
  557. CONST struct TagItem PicTags[] = {
  558.   { DTA_GroupID          , GID_PICTURE },
  559.   { PDTA_FreeSourceBitMap, TRUE        },
  560.   { PDTA_DestMode        , PMODE_V43   },
  561.   { PDTA_UseFriendBitMap , TRUE        },
  562.   { TAG_DONE             , NULL        }
  563. };
  564.  
  565. VOID LoadImage()
  566. { struct Library *IFFParseBase;
  567.   struct WBPatternPrefs pat;
  568.   struct IFFHandle *handle;
  569.   STRPTR name;
  570.   Object *obj;
  571.   LONG len;
  572.  
  573.   if ((name=gb->BFInfo.PictureName) == NULL) {
  574.     if ((IFFParseBase=OpenLibrary("iffparse.library",37L)) != NULL) {
  575.       if ((handle=AllocIFF()) != NULL) {
  576.         if ((handle->iff_Stream=(ULONG)Open("env:sys/wbpattern.prefs",MODE_OLDFILE)) != NULL) {
  577.           InitIFFasDOS(handle);
  578.           if (!OpenIFF(handle,IFFF_READ)) {
  579.             if (!StopChunk(handle,ID_PREF,ID_PTRN)) {
  580.               while(!ParseIFF(handle,IFFPARSE_SCAN)) {
  581.                 if (ReadChunkBytes(handle,&pat,sizeof(struct WBPatternPrefs)) != sizeof(struct WBPatternPrefs))
  582.                   break;
  583.                 if (pat.wbp_Which == gb->ImgType && !pat.wbp_Flags) {
  584.                   if ((gb->BFInfo.PictureName=AllocVec(1+(len=pat.wbp_DataLength),MEMF_CLEAR|MEMF_ANY)) != NULL) {
  585.                     ReadChunkBytes(handle,gb->BFInfo.PictureName,len);
  586.                   }
  587.                   break;
  588.                 }
  589.               }
  590.             }
  591.             CloseIFF(handle);
  592.           }
  593.           Close((BPTR)handle->iff_Stream);
  594.         }
  595.         FreeIFF(handle);
  596.       }
  597.       CloseLibrary(IFFParseBase);
  598.     }
  599.     name=gb->BFInfo.PictureName;
  600.   }
  601.  
  602.   if (name != NULL) {
  603.     gb->BFInfo.PictureObject = obj =
  604.       new_dt_object(name,
  605.                     PDTA_Screen  ,PUB_SCREEN,
  606.                     PDTA_Remap   ,(!gb->Remap ? FALSE : TRUE),
  607.                     OBP_Precision,(gb->Remap < 2 ? PRECISION_IMAGE : PRECISION_EXACT),
  608.                     TAG_MORE     ,PicTags);
  609.     if (obj != NULL)
  610.       if (DoMethod(obj,DTM_PROCLAYOUT,NULL,1))
  611.         if (get_dt_attrs(obj,
  612.                      PDTA_BitMapHeader,&gb->BFInfo.BitMapHeader,
  613.                      PDTA_DestBitMap  ,&gb->BFInfo.ImageBitMap,
  614.                      TAG_DONE) != 2)
  615.           { gb->BFInfo.BitMapHeader=NULL; gb->BFInfo.ImageBitMap=NULL; gb->UseImage=0; }
  616.   }
  617. }
  618.  
  619. /***************************************************************************/
  620. /*                                                                         */
  621. /* create gadgets and menus                                                */
  622. /*                                                                         */
  623. /***************************************************************************/
  624.  
  625. CONST UBYTE gadgetInfo[] = {
  626.   GADGHNONE                     ,GTYP_CLOSE,
  627.   GADGHNONE|GRELRIGHT           ,GTYP_WDEPTH,
  628.   GADGHNONE|GRELRIGHT|GRELBOTTOM,GTYP_SIZING,
  629.   GADGHNONE|GRELWIDTH|GRELHEIGHT,GTYP_WDRAGGING
  630. };
  631.  
  632. enum {
  633.   MENU_PROJECT=0,
  634.    MENU_PROJECT_ABOUT,
  635.    MENU_PROJECT_QUIT,
  636.   MENU_SETTINGS,
  637.    MENU_SETTINGS_SECONDS,
  638.    MENU_SETTINGS_OVAL,
  639.    MENU_SETTINGS_SHOW,
  640.     MENU_SETTINGS_SHOW_MINUTES,
  641.     MENU_SETTINGS_SHOW_HOURS,
  642.     MENU_SETTINGS_SHOW_QUARTER,
  643.     MENU_SETTINGS_SHOW_ONE,
  644.     MENU_SETTINGS_SHOW_NONE,
  645.    MENU_SETTINGS_HANDS,
  646.     MENU_SETTINGS_HANDS_LINE,
  647.     MENU_SETTINGS_HANDS_TRIANGLE,
  648.     MENU_SETTINGS_HANDS_RHOMBUS,
  649.     MENU_SETTINGS_HANDS_RECTANGLE,
  650.     MENU_SETTINGS_HANDS_BARLABEL,
  651.     MENU_SETTINGS_HANDS_VERYTHIN,
  652.     MENU_SETTINGS_HANDS_THIN,
  653.     MENU_SETTINGS_HANDS_NORMAL,
  654.     MENU_SETTINGS_HANDS_THICK,
  655.     MENU_SETTINGS_HANDS_VERYTHICK,
  656.    MENU_SETTINGS_SHADOW,
  657.    MENU_SETTINGS_BORDER,
  658.     MENU_SETTINGS_BORDER_NONE,
  659.     MENU_SETTINGS_BORDER_SINGLE,
  660.     MENU_SETTINGS_BORDER_DOUBLE,
  661.     MENU_SETTINGS_BORDER_BARLABEL,
  662.     MENU_SETTINGS_BORDER_HIRES,
  663.     MENU_SETTINGS_BORDER_INTERLACE,
  664.    MENU_SETTINGS_CHIME,
  665.     MENU_SETTINGS_CHIME_NONE,
  666.     MENU_SETTINGS_CHIME_HOURS,
  667.     MENU_SETTINGS_CHIME_QUARTER,
  668.     MENU_SETTINGS_CHIME_BARLABEL,
  669.     MENU_SETTINGS_CHIME_SMART,
  670.    MENU_SETTINGS_ALARM,
  671.     MENU_SETTINGS_ALARM_SET,
  672.     MENU_SETTINGS_ALARM_ON,
  673.    MENU_SETTINGS_WINDOW,
  674.     MENU_SETTINGS_WINDOW_CLOSEGAD,
  675.     MENU_SETTINGS_WINDOW_BACKDROP,
  676.     MENU_SETTINGS_WINDOW_FIXED,
  677.     MENU_SETTINGS_WINDOW_USEIMAGE,
  678.     MENU_SETTINGS_WINDOW_SNAP,
  679.    MENU_SETTINGS_BARLABEL,
  680.    MENU_SETTINGS_SAVE,
  681.   MENU_COLORS,
  682.    MENU_COLORS_SECONDS,
  683.    MENU_COLORS_MINAPEN,
  684.    MENU_COLORS_MINOPEN,
  685.    MENU_COLORS_HOURAPEN,
  686.    MENU_COLORS_HOUROPEN,
  687.    MENU_COLORS_SHADOW,
  688.    MENU_COLORS_STR12,
  689.    MENU_COLORS_QUARTER,
  690.    MENU_COLORS_HOURS,
  691.    MENU_COLORS_MINUTES,
  692.    MENU_COLORS_BORDER0,
  693.    MENU_COLORS_BORDER1,
  694.    MENU_COLORS_BORDER2,
  695.    MENU_COLORS_BORDER3,
  696.   MENU_PATTERN,
  697.    MENU_PATTERN_COLOR0,
  698.    MENU_PATTERN_COLOR1,
  699.    MENU_PATTERN_COLOR2,
  700.    MENU_PATTERN_COLOR3
  701. };
  702.  
  703. CONST UBYTE MenuInfo[] = {
  704.   NM_TITLE,MSG_PROJECT,0,0,
  705.    NM_ITEM,MSG_ABOUT,0,0,
  706.    NM_ITEM,MSG_QUIT,0,0,
  707.   NM_TITLE,MSG_SETTINGS,0,0,
  708.    NM_ITEM,MSG_SECONDS,CHECKIT|MENUTOGGLE,0,
  709.    NM_ITEM,MSG_OVAL,CHECKIT|MENUTOGGLE,0,
  710.    NM_ITEM,MSG_SHOW,0,0,
  711.     NM_SUB,MSG_MINUTES,CHECKIT,2|4|8|16,
  712.     NM_SUB,MSG_HOURS,CHECKIT,1|4|8|16,
  713.     NM_SUB,MSG_QUARTER,CHECKIT,1|2|8|16,
  714.     NM_SUB,MSG_ONE,CHECKIT,1|2|4|16,
  715.     NM_SUB,MSG_NONE,CHECKIT,1|2|4|8,
  716.    NM_ITEM,MSG_HANDS,0,0,
  717.     NM_SUB,MSG_LINE,CHECKIT,2|4|8,
  718.     NM_SUB,MSG_TRIANGLE,CHECKIT,1|4|8,
  719.     NM_SUB,MSG_RHOMBUS,CHECKIT,1|2|8,
  720.     NM_SUB,MSG_RECTANGLE,CHECKIT,1|2|4,
  721.     NM_SUB,(UBYTE)NM_BARLABEL,0,0,
  722.     NM_SUB,MSG_VERYTHIN,CHECKIT,128+(2|4|8|16),
  723.     NM_SUB,MSG_THIN,CHECKIT,128+(1|4|8|16),
  724.     NM_SUB,MSG_NORMAL,CHECKIT,128+(1|2|8|16),
  725.     NM_SUB,MSG_THICK,CHECKIT,128+(1|2|4|16),
  726.     NM_SUB,MSG_VERYTHICK,CHECKIT,128+(1|2|4|8),
  727.    NM_ITEM,MSG_SHADOW,CHECKIT|MENUTOGGLE,0,
  728.    NM_ITEM,MSG_BORDER,0,0,
  729.     NM_SUB,MSG_NONE,CHECKIT,2|4,
  730.     NM_SUB,MSG_SINGLE,CHECKIT,1|4,
  731.     NM_SUB,MSG_DOUBLE,CHECKIT,1|2,
  732.     NM_SUB,(UBYTE)NM_BARLABEL,0,0,
  733.     NM_SUB,MSG_HIRES,CHECKIT|MENUTOGGLE,0,
  734.     NM_SUB,MSG_INTERLACE,CHECKIT|MENUTOGGLE,0,
  735.    NM_ITEM,MSG_CHIME,0,0,
  736.     NM_SUB,MSG_NONE,CHECKIT,2|4,
  737.     NM_SUB,MSG_HOURS,CHECKIT,1|4,
  738.     NM_SUB,MSG_QUARTER,CHECKIT,1|2,
  739.     NM_SUB,(UBYTE)NM_BARLABEL,0,0,
  740.     NM_SUB,MSG_SMART,CHECKIT|MENUTOGGLE,0,
  741.    NM_ITEM,MSG_ALARM,0,0,
  742.     NM_SUB,MSG_SET,0,0,
  743.     NM_SUB,MSG_ON,CHECKIT|MENUTOGGLE,0,
  744.    NM_ITEM,MSG_WINDOW,0,0,
  745.     NM_SUB,MSG_CLOSEGAD,CHECKIT|MENUTOGGLE,0,
  746.     NM_SUB,MSG_BACKDROP,CHECKIT|MENUTOGGLE,0,
  747.     NM_SUB,MSG_FIXED,CHECKIT|MENUTOGGLE,0,
  748.     NM_SUB,MSG_USEIMAGE,CHECKIT|MENUTOGGLE,WT_SNAP,
  749.     NM_SUB,MSG_SNAP,CHECKIT|MENUTOGGLE,WT_USEIMAGE,
  750.    NM_ITEM,(UBYTE)NM_BARLABEL,0,0,
  751.    NM_ITEM,MSG_SAVESETTINGS,0,0,
  752.   NM_TITLE,MSG_COLORS,0,0,
  753.    NM_ITEM,MSG_SECONDS,0,0,
  754.    NM_ITEM,MSG_MINAPEN,0,0,
  755.    NM_ITEM,MSG_MINOPEN,0,0,
  756.    NM_ITEM,MSG_HOURAPEN,0,0,
  757.    NM_ITEM,MSG_HOUROPEN,0,0,
  758.    NM_ITEM,MSG_SHADOW,0,0,
  759.    NM_ITEM,MSG_STR12,0,0,
  760.    NM_ITEM,MSG_QUARTER,0,0,
  761.    NM_ITEM,MSG_HOURS,0,0,
  762.    NM_ITEM,MSG_MINUTES,0,0,
  763.    NM_ITEM,MSG_BORDER0,0,0,
  764.    NM_ITEM,MSG_BORDER1,0,0,
  765.    NM_ITEM,MSG_BORDER2,0,0,
  766.    NM_ITEM,MSG_BORDER3,0,0,
  767.   NM_TITLE,MSG_PATTERN,0,0,
  768.    NM_ITEM,MSG_COLOR0,0,0,
  769.    NM_ITEM,MSG_COLOR1,0,0,
  770.    NM_ITEM,MSG_COLOR2,0,0,
  771.    NM_ITEM,MSG_COLOR3,0,0
  772. };
  773.  
  774. #define NM_ITEMCOUNT (sizeof(MenuInfo)/(4*sizeof(UBYTE)))
  775.  
  776. CONST struct TagItem MenuTags[] = {
  777.   { GTMN_NewLookMenus,TRUE },
  778.   { TAG_DONE         ,NULL }
  779. };
  780.  
  781. LONG MakeMenus()
  782. { struct NewMenu menubuf[NM_ITEMCOUNT+1],*nm;
  783.   struct Gadget *gad;
  784.   CONST UBYTE *p;
  785.   LONG tmp,index;
  786.   WORD i,num;
  787.  
  788.   for(gad=&gb->GadgetBuf[0],p=&gadgetInfo[0],num=1,i=GB_GADCOUNT-1; i>=0; i--)
  789.   { gad->Width      = num;
  790.     gad->Height     = num;
  791.     gad->Flags      = *p++;
  792.     gad->Activation = num; /* GACT_RELVERIFY */
  793.     gad->GadgetType = *p++;
  794.     gad++;
  795.     gad[-1].NextGadget = gad;
  796.   }
  797.   gb->GadSize = 0;
  798.  
  799.   MEMZEROL(&menubuf[0],sizeof(menubuf));
  800.   for(nm=&menubuf[0],p=&MenuInfo[0],i=NM_ITEMCOUNT-1; i>=0; i--)
  801.   { nm->nm_Type          = *p++;
  802.     if ((tmp=(BYTE)*p++) >= 0) tmp=(LONG)GetCatalogString(tmp);
  803.     nm->nm_Label         = (STRPTR)tmp;
  804.     nm->nm_Flags         = (UWORD)*p++;
  805.     if ((num=(BYTE)*p++) < 0) num=(((num&0x7f))<<5);
  806.     nm->nm_MutualExclude = (ULONG)num;
  807.     nm++;
  808.   }
  809.   menubuf[MENU_PROJECT_ABOUT].nm_CommKey = GetCatalogString(MSG_ABOUTKEY);
  810.   menubuf[MENU_PROJECT_QUIT ].nm_CommKey = GetCatalogString(MSG_QUITKEY);
  811.   menubuf[MENU_SETTINGS_SAVE].nm_CommKey = GetCatalogString(MSG_SAVEKEY);
  812.  
  813.   if ((gb->VisualInfo=GetVisualInfoA(PUB_SCREEN,NULL)) != NULL) {
  814.     nm = &menubuf[0]; i = CHECKED;
  815.     nm[MENU_SETTINGS_SECONDS].nm_Flags
  816.      |= i & (gb->Seconds ? -1 : 0);
  817.     nm[MENU_SETTINGS_OVAL].nm_Flags
  818.      |= i & (gb->Oval ? -1 : 0);
  819.     index = MENU_SETTINGS_SHOW+gb->Show+1;
  820.     nm[index].nm_Flags
  821.      |= i;
  822.     index = MENU_SETTINGS_HANDS+gb->HandType+1;
  823.     nm[index].nm_Flags
  824.      |= i;
  825.     index = MENU_SETTINGS_HANDS+gb->HandWidth+6;
  826.     nm[index].nm_Flags
  827.      |= i;
  828.     nm[MENU_SETTINGS_SHADOW].nm_Flags
  829.      |= i & (gb->Shadow ? -1 : 0);
  830.     index = MENU_SETTINGS_BORDER+gb->BorderCount+1;
  831.     nm[index].nm_Flags
  832.      |= i;
  833.     nm[MENU_SETTINGS_BORDER_HIRES].nm_Flags
  834.      |= i & (gb->HiRes ? -1 : 0);
  835.     nm[MENU_SETTINGS_BORDER_INTERLACE].nm_Flags
  836.      |= i & (gb->Interlace ? -1 : 0);
  837.     index = MENU_SETTINGS_CHIME+gb->Chime+1;
  838.     nm[index].nm_Flags
  839.      |= i;
  840.     nm[MENU_SETTINGS_CHIME_SMART].nm_Flags
  841.      |= i & (gb->SmartHour ? -1 : 0);
  842.     nm[MENU_SETTINGS_ALARM_ON].nm_Flags
  843.      |= i & (gb->Alarm ? -1 : 0);
  844.  
  845.     nm[MENU_SETTINGS_WINDOW_CLOSEGAD].nm_Flags
  846.      |= i & (gb->CloseGad ? -1 : 0);
  847.     nm[MENU_SETTINGS_WINDOW_BACKDROP].nm_Flags
  848.      |= i & (gb->Backdrop ? -1 : 0);
  849.     nm[MENU_SETTINGS_WINDOW_FIXED].nm_Flags
  850.      |= i & (gb->Fixed ? -1 : 0);
  851.     nm[MENU_SETTINGS_WINDOW_USEIMAGE].nm_Flags
  852.      |= i & (gb->BFInfo.ImageBitMap && gb->UseImage ? -1 : 0);
  853.     nm[MENU_SETTINGS_WINDOW_SNAP].nm_Flags
  854.      |= i & (gb->BFInfo.SnapBitMap && gb->Snap ? -1 : 0);
  855.  
  856.     if ((gb->Menus=CreateMenusA(&menubuf[0],NULL)) != NULL)
  857.       return LayoutMenusA(gb->Menus,gb->VisualInfo,(struct TagItem *)MenuTags);
  858.   }
  859.   return FALSE;
  860. }
  861.  
  862. /***************************************************************************/
  863. /*                                                                         */
  864. /* initialize all graphics                                                 */
  865. /*                                                                         */
  866. /***************************************************************************/
  867.  
  868. LONG InitClock()
  869. { struct Screen *scr;
  870.   LONG ret;
  871.  
  872.   if ((scr=LockPubScreen(gb->PubName)) == NULL)
  873.     scr=LockPubScreen(NULL);
  874.  
  875.   ret = 0;
  876.  
  877.   if ((PUB_SCREEN=scr) != NULL) {
  878.     if (gb->Snap)
  879.       SnapBackground();
  880.     if (gb->DataTypesBase && !gb->Activate)
  881.       LoadImage();
  882.     SetPattern();
  883.     if (MakeMenus())
  884.       ret = OpenMainWindow();
  885.     UnlockPubScreen(NULL,scr);
  886.   }
  887.  
  888.   return ret;
  889. }
  890.  
  891. /***************************************************************************/
  892. /*                                                                         */
  893. /* get arguments either from CLI or WB                                     */
  894. /*                                                                         */
  895. /***************************************************************************/
  896.  
  897. LONG GetArguments(struct WBStartup *wm)
  898. { struct WBArg *arg;
  899.   STRPTR buf;
  900.  
  901.   if (wm != NULL) {
  902.     arg = wm->sm_ArgList;
  903.     if (wm->sm_NumArgs>1)
  904.       arg++;
  905.     gb->ProgArg.wa_Lock = arg->wa_Lock;
  906.     gb->ProgArg.wa_Name = arg->wa_Name;
  907.     gb->OldLock = CurrentDir(arg->wa_Lock);
  908.     gb->ChangedDir = -1;
  909.     MergeToolTypes();
  910.   }
  911.   else
  912.     if ((gb->NameBuf=(buf=AllocVec(124,MEMF_ANY))) != NULL) {
  913.       gb->ProgArg.wa_Lock = GetProgramDir();
  914.       GetProgramName(buf,124);
  915.       gb->ProgArg.wa_Name = FilePart(buf);
  916.       ParseArgs(NULL,0);
  917.     }
  918.     else
  919.       return FALSE;
  920.  
  921.   return TRUE;
  922. }
  923.  
  924. /*
  925. ** read all tooltypes
  926. */
  927.  
  928. STATIC INLINE STRPTR myStpcpy(STRPTR dst,STRPTR src)
  929. {
  930.   while((*dst++=*src++)); return(dst-1);
  931. }
  932.  
  933. VOID MergeToolTypes()
  934. { struct DiskObject *dobj;
  935.   STRPTR argstr,string,p;
  936.   LONG arglen,strln;
  937.   BPTR old_cd;
  938.   char **tt;
  939.  
  940.   argstr = (STRPTR)&gb->EasyBuf; *argstr = '\n'; arglen = 1; string=NULL;
  941.  
  942.   old_cd = CurrentDir(gb->ProgArg.wa_Lock);
  943.  
  944.   if ((dobj=GetDiskObject(gb->ProgArg.wa_Name)) != NULL) {
  945.     tt = dobj->do_ToolTypes; strln = 1;
  946.     while (*tt != NULL) {
  947.       strln+=strlen(*tt++)+1;
  948.     }
  949.  
  950.     if ((string=AllocVec((strln+sizeof(ULONG)-1)&~(sizeof(ULONG)-1),MEMF_ANY)) != NULL) {
  951.       tt = dobj->do_ToolTypes; p=string;
  952.       while (*tt != NULL) {
  953.         p=myStpcpy(p,*tt++); *p++ = ' ';
  954.       }
  955.       *p = '\n';
  956.  
  957.       argstr = string; arglen = strln;
  958.     }
  959.  
  960.     FreeDiskObject(dobj);
  961.   }
  962.  
  963.   ParseArgs(argstr,arglen);
  964.  
  965.   FreeVec(string);
  966.  
  967.   (VOID)CurrentDir(old_cd);
  968. }
  969.  
  970. /*
  971. ** parse arguments and set default values
  972. */
  973.  
  974. enum {
  975.   OPT_NULL=-1,OPT_TOP,OPT_LEFT,OPT_WIDTH,OPT_HEIGHT,OPT_SECONDS,OPT_PATTERN,
  976.   OPT_OVAL,OPT_SHADOW,OPT_SHOWFACE,OPT_HANDTYPE,OPT_HANDWIDTH,OPT_DRAWPENS,
  977.   OPT_BORDERTYPE,OPT_WINDOWTYPE,OPT_CHIME,OPT_ALARM,OPT_SCRNOTIFY,OPT_WBIMAGE,
  978.   OPT_REMAP,OPT_IMAGE,OPT_PUBSCREEN,OPT_TASKPRI,OPT_SIZEOF
  979. };
  980.  
  981. #define TEMPLATE \
  982.   "/M,TOP/N,LEFT/N,WIDTH/N,HEIGHT/N,SECONDS/S,PATTERN/K,OVAL/S,SHADOW/S,"   \
  983.   "SHOWFACE/N,HANDTYPE/N,HANDWIDTH/N,DRAWPENS/K,BORDERTYPE/N,WINDOWTYPE/N," \
  984.   "CHIME/N,ALARM/N,SCREENNOTIFY/S,WBIMAGE/S,REMAP/N,IMAGE/K,PUBSCREEN/K,"   \
  985.   "TASKPRI/N"
  986.  
  987. CONST UBYTE Pens[] = {
  988.   2,0,2,0,2,1,2,2,2,2,0,1,2,3
  989. };
  990.  
  991. VOID ParseArgs(STRPTR argstr,LONG length)
  992. { struct RDArgs *rda,*args;
  993.   LONG result[OPT_SIZEOF+1],*res,def,tmp;
  994.   STRPTR tmpl;
  995.  
  996.   MEMZEROL(&result[0],sizeof(result)); args = NULL;
  997.  
  998.   if ((rda=AllocDosObject(DOS_RDARGS,NULL)) != NULL) {
  999.     rda->RDA_Source.CS_Buffer = argstr;
  1000.     rda->RDA_Source.CS_Length = length;
  1001.     tmpl = TEMPLATE; res = &result[0];
  1002.     if (rda->RDA_Source.CS_Buffer == NULL) {
  1003.       res++; tmpl+=3;
  1004.     }
  1005.     args = ReadArgs(tmpl,res,rda);
  1006.   }
  1007.  
  1008.   res = &result[1];
  1009.  
  1010.   def = 50;
  1011.   if (res[OPT_TOP]) {
  1012.     tmp = *(LONG *)res[OPT_TOP]; if (tmp >= 0) def = tmp;
  1013.   }
  1014.   gb->Top = def;
  1015.  
  1016.   def = 50;
  1017.   if (res[OPT_LEFT]) {
  1018.     tmp = *(LONG *)res[OPT_LEFT]; if (tmp >= 0) def = tmp;
  1019.   }
  1020.   gb->Left = def;
  1021.  
  1022.   def = 108;
  1023.   if (res[OPT_WIDTH]) {
  1024.     tmp = *(LONG *)res[OPT_WIDTH]; if (tmp >= 10) def = tmp;
  1025.   }
  1026.   gb->Width = def;
  1027.  
  1028.   def = 54;
  1029.   if (res[OPT_HEIGHT]) {
  1030.     tmp = *(LONG *)res[OPT_HEIGHT]; if (tmp >= 10) def = tmp;
  1031.   }
  1032.   gb->Height = def;
  1033.  
  1034.   gb->Seconds = res[OPT_SECONDS];
  1035.  
  1036.   ReadStr(&gb->Pens[MUST],(STRPTR)res[OPT_PATTERN],&gb->Pens[MUST],4);
  1037.  
  1038.   gb->Oval = res[OPT_OVAL];
  1039.  
  1040.   gb->Shadow = res[OPT_SHADOW];
  1041.  
  1042.   def = 1;
  1043.   if (res[OPT_SHOWFACE]) {
  1044.     tmp = *(LONG *)res[OPT_SHOWFACE]; if ((ULONG)tmp < 5) def = tmp;
  1045.   }
  1046.   gb->Show = def;
  1047.  
  1048.   def = 2;
  1049.   if (res[OPT_HANDTYPE]) {
  1050.     tmp = *(LONG *)res[OPT_HANDTYPE]; if ((ULONG)tmp < 4) def = tmp;
  1051.   }
  1052.   gb->HandType = def;
  1053.  
  1054.   def = 2;
  1055.   if (res[OPT_HANDWIDTH]) {
  1056.     tmp = *(LONG *)res[OPT_HANDWIDTH]; if ((ULONG)tmp < 5) def = tmp;
  1057.   }
  1058.   gb->HandWidth = def;
  1059.  
  1060.   ReadStr(&gb->Pens[0],(STRPTR)res[OPT_DRAWPENS],(STRPTR)&Pens[0],14);
  1061.  
  1062.   def = 6;
  1063.   if (res[OPT_BORDERTYPE]) {
  1064.     tmp = *(LONG *)res[OPT_BORDERTYPE]; if ((ULONG)tmp < 3+4+8) def = tmp;
  1065.   }
  1066.   gb->Interlace = ((tmp = def & 8) != 0); def -= tmp;
  1067.   gb->HiRes = ((tmp = def & 4) != 0); def -= tmp;
  1068.   gb->BorderCount = def;
  1069.  
  1070.  
  1071.   def = 0;
  1072.   if (res[OPT_WINDOWTYPE]) {
  1073.     tmp = *(LONG *)res[OPT_WINDOWTYPE]; if ((ULONG)tmp < WT_LAST) def = tmp;
  1074.   }
  1075.   gb->Snap = ((tmp = def & WT_SNAP) != 0);
  1076.   gb->UseImage = ((tmp = def & WT_USEIMAGE) != 0);
  1077.   gb->Fixed = ((tmp = def & WT_FIXED) != 0);
  1078.   gb->Backdrop = ((tmp = def & WT_BACKDROP) != 0);
  1079.   gb->CloseGad = ((tmp = def & WT_CLOSEGAD) != 0);
  1080.  
  1081.   def = 0;
  1082.   if (res[OPT_CHIME]) {
  1083.     tmp = *(LONG *)res[OPT_CHIME]; if ((ULONG)tmp < 3+4) def = tmp;
  1084.   }
  1085.   gb->SmartHour = ((tmp = def & 4) != 0); def -= tmp;
  1086.   gb->Chime = def;
  1087.  
  1088.   gb->AlStd = 12;
  1089.   if (res[OPT_ALARM]) {
  1090.     ULONG gna = *(ULONG *)res[OPT_ALARM];
  1091.     gb->Alarm = gna&1; gb->AlMin = (gna>>=1)&0x3f; gb->AlStd = (gna>>=6)&0x1f;
  1092.   }
  1093.  
  1094.   gb->ScrNotify = res[OPT_SCRNOTIFY];
  1095.  
  1096.   def = WBP_SCREEN; if (res[OPT_WBIMAGE]) def = WBP_ROOT; gb->ImgType = def;
  1097.  
  1098.   def = 1;
  1099.   if (res[OPT_REMAP]) {
  1100.     tmp = *(LONG *)res[OPT_REMAP]; if ((ULONG)tmp < 3) def = tmp;
  1101.   }
  1102.   gb->Remap=def;
  1103.  
  1104.   if (res[OPT_IMAGE])
  1105.     if ((gb->BFInfo.PictureName=AllocVec(1+strlen((STRPTR)res[OPT_IMAGE]),MEMF_ANY)) != NULL)
  1106.       strcpy(gb->BFInfo.PictureName,(STRPTR)res[OPT_IMAGE]);
  1107.  
  1108.   if (res[OPT_PUBSCREEN])
  1109.     if ((gb->PubName=AllocVec(1+strlen((STRPTR)res[OPT_PUBSCREEN]),MEMF_ANY)) != NULL)
  1110.       strcpy(gb->PubName,(STRPTR)res[OPT_PUBSCREEN]);
  1111.  
  1112.   if (res[OPT_TASKPRI]) {
  1113.     tmp = *(LONG *)res[OPT_TASKPRI]; if (tmp > 5) tmp = 5;
  1114.     gb->OldPri = SetTaskPri(gb->WindowPort->mp_SigTask,tmp);
  1115.     gb->ChangedPri = -1;
  1116.   }
  1117.  
  1118.   FreeArgs(args);
  1119.  
  1120.   if (rda != NULL)
  1121.     FreeDosObject(DOS_RDARGS,rda);
  1122. }
  1123.  
  1124. /*
  1125. ** init pen-buffer with `def' and replace with src (if non zero)
  1126. */
  1127.  
  1128. VOID ReadStr(UBYTE *dst,UBYTE *src,UBYTE *def,LONG cnt)
  1129. { UBYTE c;
  1130.  
  1131.   CopyMem(def,dst,cnt);
  1132.  
  1133.   if (src != NULL)
  1134.     if (*src=='x' || *src=='X') /* hex */
  1135.       do {
  1136.         if (!*src++ || (c=*src++)==0)
  1137.           return;
  1138.         *dst++ = (XtoD(c)<<4) + XtoD(*src);
  1139.       } while (--cnt);
  1140.     else
  1141.       do { /* decimal */
  1142.         if ((c=*src++) == 0)
  1143.           return;
  1144.         *dst++ = XtoD(c);
  1145.       } while (--cnt);
  1146. }
  1147.  
  1148. LONG XtoD(LONG a)
  1149. {
  1150.   if (a>='0' && a<='9')
  1151.     return (a-'0');
  1152.   if (a>='a' && a<='f')
  1153.     return (a-'a'+10);
  1154.   if (a>='A' && a<='F')
  1155.     return (a-'A'+10);
  1156.   return 0;
  1157. }
  1158.  
  1159. /***************************************************************************/
  1160. /*                                                                         */
  1161. /* open all devices                                                        */
  1162. /*                                                                         */
  1163. /***************************************************************************/
  1164.  
  1165. struct MsgPort *CreateRexxPort()
  1166. { struct MsgPort *mp,*gp;
  1167.   ULONG i;
  1168.  
  1169.   if ((mp=CreateMsgPort()) != NULL) {
  1170.     mp->mp_Node.ln_Pri=0;
  1171.     if ((mp->mp_Node.ln_Name=AllocVec(16,MEMF_PUBLIC)) != NULL) {
  1172.       i=99;
  1173.       do {
  1174.         sprintf(mp->mp_Node.ln_Name,"TOLLEUHR.%ld",100-i);
  1175.         Forbid();
  1176.         if ((gp=FindPort(mp->mp_Node.ln_Name)) == NULL)
  1177.           AddPort(mp);
  1178.         Permit();
  1179.         if (!gp)
  1180.           return mp;
  1181.       } while (--i);
  1182.       FreeVec(mp->mp_Node.ln_Name);
  1183.     }
  1184.     DeleteMsgPort(mp); mp=NULL;
  1185.   }
  1186.   return mp;
  1187. }
  1188.  
  1189. LONG OpenDevs()
  1190. {
  1191.   gb->RexxPort=CreateRexxPort();
  1192.   if ((gb->WindowPort=CreateMsgPort()) != NULL)
  1193.     if ((gb->TimerPort=CreateMsgPort()) != NULL)
  1194.       if ((gb->TimerIO=CreateIORequest(gb->TimerPort,sizeof(struct timerequest))) != NULL)
  1195.         if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)gb->TimerIO,0)) {
  1196.           gb->TimerOpen = -1;
  1197.           if ((gb->WaveForm=AllocMem(8,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL) {
  1198.             ((ULONG *)gb->WaveForm)[0]=0x7f807f80; /* rectangle */
  1199.             if ((gb->AudioPort=CreateMsgPort()) != NULL)
  1200.               if ((gb->AudioIO[0]=CreateIORequest(gb->AudioPort,sizeof(struct IOAudio))) != NULL)
  1201.                 if ((gb->AudioIO[1]=CreateIORequest(gb->AudioPort,sizeof(struct IOAudio))) != NULL) {
  1202.                   if (!OpenDevice(AUDIONAME,0,(struct IORequest *)gb->AudioIO[0],0))
  1203.                     gb->AudioOpen = -1;
  1204.                   return TRUE;
  1205.                 }
  1206.           }
  1207.         }
  1208.   return FALSE;
  1209. }
  1210.  
  1211. /***************************************************************************/
  1212. /*                                                                         */
  1213. /* open all libraries                                                      */
  1214. /*                                                                         */
  1215. /***************************************************************************/
  1216.  
  1217. LONG OpenLibs()
  1218. {
  1219.   if ((gb->DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) != NULL) {
  1220.     if ((gb->IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L)) != NULL)
  1221.       if ((gb->GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L)) != NULL)
  1222.         if ((gb->GadtoolsBase=OpenLibrary("gadtools.library",37L)) != NULL)
  1223.           if ((gb->IconBase=OpenLibrary("icon.library",37L)) != NULL) {
  1224.             gb->DataTypesBase = OpenLibrary("datatypes.library",39L);
  1225.             if ((gb->LocaleBase=(struct LocaleBase *)OpenLibrary("locale.library",38L)) != NULL)
  1226.               gb->Catalog = OpenCatalogA(NULL,"tolleuhr.catalog",NULL);
  1227.             return TRUE;
  1228.           }
  1229.   }
  1230.   return FALSE;
  1231. }
  1232.  
  1233. /***************************************************************************/
  1234. /*                                                                         */
  1235. /* main function                                                           */
  1236. /*                                                                         */
  1237. /***************************************************************************/
  1238.  
  1239. VOID Main()
  1240. { struct WBStartup *wbmsg;
  1241.   struct Process *proc;
  1242.   ULONG mask;
  1243.  
  1244.   proc = (struct Process *)FindTask(NULL); wbmsg = NULL;
  1245.  
  1246.   if (!proc->pr_CLI) {
  1247.     wbmsg = (struct WBStartup *)(WaitPort(&proc->pr_MsgPort),GetMsg(&proc->pr_MsgPort));
  1248.   }
  1249.  
  1250.   if (gb->SysBase->LibNode.lib_Version >= 37) {
  1251.     gb->V39 = (gb->SysBase->LibNode.lib_Version >= 39);
  1252.     if (OpenLibs()) {
  1253.       if (OpenDevs()) {
  1254.         if (GetArguments(wbmsg)) {
  1255.           if (InitClock()) {
  1256.             if (gb->ScrNotify)
  1257.               AddScreenNotify();
  1258.             for(gb->GoOn=-1;;) {
  1259.               mask = 1L<<SIGBREAKB_CTRL_C | 1L<<gb->WindowPort->mp_SigBit |
  1260.                      1L<<gb->TimerPort->mp_SigBit | 1L<<gb->AudioPort->mp_SigBit;
  1261.  
  1262.               if (gb->RexxPort)
  1263.                 mask |= 1L<<gb->RexxPort->mp_SigBit;
  1264.  
  1265.               if (gb->NotifyPort)
  1266.                 mask |= 1L<<gb->NotifyPort->mp_SigBit;
  1267.  
  1268.               if (gb->AboutReq)
  1269.                 mask |= 1L<<gb->AboutReq->UserPort->mp_SigBit;
  1270.  
  1271.               if (Wait(mask) & SIGBREAKF_CTRL_C) /* User-Break */
  1272.                 break;
  1273.  
  1274.               if (GetMsg(gb->TimerPort)) {
  1275.                 if (NextTick()) {
  1276.                   NewTitle(); ZifferBlatt(); TestIfAlarm();
  1277.                 }
  1278.                 Zeichnen();
  1279.               }
  1280.  
  1281.               if (GetMsg(gb->AudioPort))
  1282.                 PlayNote();
  1283.  
  1284.               if (gb->NotifyHandle) {
  1285.                 CheckNotify(); if (!gb->GoOn) break;
  1286.               }
  1287.  
  1288.               CheckAboutReq();
  1289.  
  1290.               if (gb->RexxPort) {
  1291.                 CheckRexx(); if (!gb->GoOn) break;
  1292.               }
  1293.  
  1294.               gb->Activate = -1; CheckWindows(); gb->Activate = 0;
  1295.  
  1296.               if (!gb->GoOn)
  1297.                 break;
  1298.             }
  1299.             RemScreenNotify();
  1300.           }
  1301.           CloseGfx();
  1302.  
  1303.           FreeVec(gb->PubName);
  1304.  
  1305.           FreeVec(gb->BFInfo.PictureName);
  1306.  
  1307.           if (gb->ChangedPri)
  1308.             (VOID)SetTaskPri(gb->WindowPort->mp_SigTask,gb->OldPri);
  1309.  
  1310.           FreeVec(gb->NameBuf);
  1311.  
  1312.           if (gb->ChangedDir)
  1313.             (VOID)CurrentDir(gb->OldLock);
  1314.         }
  1315.       }
  1316.       CloseDevs();
  1317.     }
  1318.     CloseLibs();
  1319.   }
  1320.  
  1321.   if (wbmsg) {
  1322.     Forbid(); ReplyMsg((struct Message *)wbmsg);
  1323.   }
  1324. }
  1325.  
  1326. /***************************************************************************/
  1327. /*                                                                         */
  1328. /* close all libraries                                                     */
  1329. /*                                                                         */
  1330. /***************************************************************************/
  1331.  
  1332. VOID CloseLibs()
  1333. { struct Catalog *cat;
  1334.  
  1335.   if ((cat=gb->Catalog) != NULL)
  1336.     CloseCatalog(cat);
  1337.   CloseLibrary((struct Library *)gb->LocaleBase);
  1338.   CloseLibrary(gb->DataTypesBase);
  1339.   CloseLibrary(gb->IconBase);
  1340.   CloseLibrary(gb->GadtoolsBase);
  1341.   CloseLibrary((struct Library *)gb->GfxBase);
  1342.   CloseLibrary((struct Library *)gb->IntuitionBase);
  1343.   CloseLibrary((struct Library *)gb->DOSBase);
  1344. }
  1345.  
  1346. /***************************************************************************/
  1347. /*                                                                         */
  1348. /* close all devices                                                       */
  1349. /*                                                                         */
  1350. /***************************************************************************/
  1351.  
  1352. VOID StopIO(struct IORequest *ioReq)
  1353. {
  1354.   AbortIO(ioReq); WaitIO(ioReq);
  1355. }
  1356.  
  1357. VOID StopAudio()
  1358. {
  1359.   if (gb->SoundOn) {
  1360.     if (gb->AudioSent[1])
  1361.       StopIO((struct IORequest *)gb->AudioIO[1]);
  1362.     if (gb->AudioSent[0])
  1363.       StopIO((struct IORequest *)gb->AudioIO[0]);
  1364.     EndTune();
  1365.   }
  1366. }
  1367.  
  1368. VOID CloseDevs()
  1369. { APTR buf;
  1370.  
  1371.   if (gb->AudioOpen)
  1372.     { StopAudio(); CloseDevice((struct IORequest *)gb->AudioIO[0]); }
  1373.   DeleteIORequest((struct IORequest *)gb->AudioIO[1]);
  1374.   DeleteIORequest((struct IORequest *)gb->AudioIO[0]);
  1375.   DeleteMsgPort(gb->AudioPort);
  1376.   if ((buf=gb->WaveForm) != NULL) FreeMem(buf,8);
  1377.  
  1378.   if (gb->TimerOpen)
  1379.     CloseDevice((struct IORequest *)gb->TimerIO);
  1380.   DeleteIORequest((struct IORequest *)gb->TimerIO);
  1381.   DeleteMsgPort(gb->TimerPort);
  1382.  
  1383.   DeleteMsgPort(gb->WindowPort);
  1384.  
  1385.   DeleteRexxPort();
  1386. }
  1387.  
  1388. VOID DeleteRexxPort()
  1389. { struct Message *msg;
  1390.   struct MsgPort *mp;
  1391.   
  1392.   if ((mp=gb->RexxPort) != NULL) {
  1393.     RemPort(mp); while((msg=GetMsg(mp)) != NULL) ReplyMsg(msg);
  1394.     FreeVec(mp->mp_Node.ln_Name); DeleteMsgPort(mp);
  1395.   }
  1396. }
  1397.  
  1398. /***************************************************************************/
  1399. /*                                                                         */
  1400. /* close graphic stuff                                                     */
  1401. /*                                                                         */
  1402. /***************************************************************************/
  1403.  
  1404. /*
  1405. ** free a bitmap
  1406. */
  1407.  
  1408. VOID DeleteBitMap(struct BitMap *bm,ULONG depth)
  1409. { PLANEPTR *p;
  1410.   ULONG d;
  1411.  
  1412.   if (bm != NULL) {
  1413.     WaitBlit();
  1414.  
  1415.     if (gb->V39)
  1416.       FreeBitMap(bm);
  1417.     else {
  1418.       for(p=&bm->Planes[0],d=depth; d!=0; d--)
  1419.         FreeVec(*p++);
  1420.       FreeVec(bm);
  1421.     }
  1422.   }
  1423. }
  1424.  
  1425. /*
  1426. ** free some temporary stuff
  1427. */
  1428.  
  1429. VOID NewSize1()
  1430. { PLANEPTR buf;
  1431.  
  1432.   DeleteBitMap(RP1_BITMAP,gb->Depth); RP1_BITMAP=NULL;
  1433.  
  1434.   if ((buf=gb->Buf) != NULL)
  1435.     { FreeRaster(buf,gb->Width2,gb->Height2); gb->Buf=NULL; }
  1436. }
  1437.  
  1438. /*
  1439. ** discard `About'
  1440. */
  1441.  
  1442. VOID CloseAboutReq()
  1443. {
  1444.   FreeSysRequest(gb->AboutReq); gb->AboutReq = NULL;
  1445. }
  1446.  
  1447. /*
  1448. ** discard all windows and other gfx stuff
  1449. */
  1450.  
  1451. VOID CloseGfx()
  1452. { Object *obj;
  1453.  
  1454.   if (gb->TimerSent)
  1455.     { StopIO(&gb->TimerIO->tr_node); gb->TimerSent=0; }
  1456.   NewSize1();
  1457.   CloseAboutReq();
  1458.   FreeWindow(&gb->AlarmWin);
  1459.   FreeWindow(&gb->ColorWin);
  1460.   CloseWindowSafely(gb->MainWin);
  1461.   gb->MainWin = NULL;
  1462.   FreeMenus(gb->Menus);
  1463.   gb->Menus = NULL;
  1464.   FreeVisualInfo(gb->VisualInfo);
  1465.   gb->VisualInfo = NULL;
  1466.   if (!gb->Activate) {
  1467.     if ((obj=gb->BFInfo.PictureObject) != NULL)
  1468.       DisposeDTObject(obj);
  1469.     gb->BFInfo.PictureObject = NULL;
  1470.     gb->BFInfo.BitMapHeader = NULL;
  1471.     gb->BFInfo.ImageBitMap = NULL;
  1472.   }
  1473.   DeleteBitMap(gb->BFInfo.SnapBitMap,gb->Depth);
  1474.   gb->BFInfo.SnapBitMap = NULL;
  1475. }
  1476.  
  1477. /*
  1478. ** close a tool window
  1479. */
  1480.  
  1481. VOID FreeWindow(struct WinGad *wg)
  1482. {
  1483.   CloseWindowSafely(wg->Win); wg->Win = NULL;
  1484.   FreeGadgets(wg->Gad); wg->Gad = NULL;
  1485. }
  1486.  
  1487. /*
  1488. ** close a window with shared IDCMP
  1489. */
  1490.  
  1491. VOID CloseWindowSafely(struct Window *win)
  1492. { struct Node *msg,*succ;
  1493.  
  1494.   if (win != NULL) {
  1495.     Forbid();
  1496.     msg=win->UserPort->mp_MsgList.lh_Head; /* assumes valid port */
  1497.     while ((succ=msg->ln_Succ)!=NULL) {
  1498.       if (((struct IntuiMessage *)msg)->IDCMPWindow==win) {
  1499.         Remove(msg); ReplyMsg((struct Message *)msg);
  1500.       }
  1501.       msg=succ;
  1502.     }
  1503.     win->UserPort=NULL;
  1504.     ModifyIDCMP(win,0L);
  1505.     Permit();
  1506.     ClearMenuStrip(win);
  1507.     CloseWindow(win);
  1508.   }
  1509. }
  1510.  
  1511. /***************************************************************************/
  1512. /*                                                                         */
  1513. /* remove screen notification                                              */
  1514. /*                                                                         */
  1515. /***************************************************************************/
  1516.  
  1517. VOID RemScreenNotify()
  1518. { APTR handle;
  1519.  
  1520.   if ((handle=gb->NotifyHandle) != NULL)
  1521.     while (!RemWorkbenchClient(handle)) Delay(10);
  1522.   gb->NotifyHandle = NULL;
  1523.   DeleteMsgPort(gb->NotifyPort);
  1524.   gb->NotifyPort = NULL;
  1525.   CloseLibrary(gb->ScreenNotifyBase);
  1526.   gb->ScreenNotifyBase = NULL;
  1527. }
  1528.  
  1529. /***************************************************************************/
  1530. /*                                                                         */
  1531. /* check screen notification                                               */
  1532. /*                                                                         */
  1533. /***************************************************************************/
  1534.  
  1535. VOID CheckNotify()
  1536. { struct ScreenNotifyMessage *snm;
  1537.  
  1538.   while ((snm=(struct ScreenNotifyMessage *)GetMsg(gb->NotifyPort)) != NULL) {
  1539.     if (gb->GoOn && !gb->Hidden && (snm->snm_Type == SCREENNOTIFY_TYPE_WORKBENCH)) {
  1540.       switch((LONG)snm->snm_Value) {
  1541.         case TRUE:
  1542.           ReplyMsg(&snm->snm_Message);
  1543.           if (!gb->MainWin && !(gb->GoOn=InitClock()))
  1544.             CloseGfx();
  1545.           break;
  1546.         case FALSE:
  1547.           CloseGfx();
  1548.         default:
  1549.           ReplyMsg(&snm->snm_Message);
  1550.           break;
  1551.       }
  1552.     }
  1553.     else
  1554.       ReplyMsg(&snm->snm_Message);
  1555.   }
  1556. }
  1557.  
  1558. /***************************************************************************/
  1559. /*                                                                         */
  1560. /* process any arexx message                                               */
  1561. /*                                                                         */
  1562. /***************************************************************************/
  1563.  
  1564. VOID RexxHide()
  1565. {
  1566.   CloseGfx(); gb->Hidden = -1;
  1567. }
  1568.  
  1569. VOID RexxShow()
  1570. {
  1571.   if (!gb->MainWin && !(gb->GoOn=InitClock()))
  1572.     CloseGfx();
  1573.   gb->Hidden = 0;
  1574. }
  1575.  
  1576. VOID RexxQuit()
  1577. {
  1578.   gb->GoOn = 0;
  1579. }
  1580.  
  1581. CONST struct arexxTable {
  1582.   STRPTR cmdname;
  1583.   VOID   (*func)();
  1584. } ARexxTable[] = {
  1585.   { "QUIT", RexxQuit },
  1586.   { "SHOW", RexxShow },
  1587.   { "HIDE", RexxHide }
  1588. };
  1589.  
  1590. VOID CheckRexx()
  1591. { const struct arexxTable *at;
  1592.   struct RexxMsg *rmsg;
  1593.   UBYTE *arg,*cmd,*p,c;
  1594.   LONG i;
  1595.  
  1596.   while ((rmsg=(struct RexxMsg *)GetMsg(gb->RexxPort)) != NULL) {
  1597.     if (gb->GoOn) {
  1598.       p=ARG0(rmsg); do{}while((c=*p++) > 0 && c <= ' '); --p;
  1599.       at=&ARexxTable[0]; i=sizeof(ARexxTable)/sizeof(ARexxTable[0]);
  1600.       do {
  1601.         for(arg=p,cmd=at->cmdname;;) {
  1602.           c=*arg++;
  1603.           if (c>('a'-1) && c<('z'+1))
  1604.             c+='A'-'a';
  1605.           if (c!=*cmd++)
  1606.             break;
  1607.           if (!c) {
  1608.             (*at->func)(); i=1; break;
  1609.           }
  1610.         }
  1611.         at++;
  1612.       } while (--i);
  1613.     }
  1614.     ReplyMsg(&rmsg->rm_Node);
  1615.   }
  1616. }
  1617.  
  1618. /***************************************************************************/
  1619. /*                                                                         */
  1620. /* process all input events                                                */
  1621. /*                                                                         */
  1622. /***************************************************************************/
  1623.  
  1624. VOID CheckAboutReq()
  1625. { struct Window *req;
  1626.  
  1627.   if ((req=gb->AboutReq) != NULL)
  1628.     if (SysReqHandler(req,NULL,FALSE) != -2)
  1629.       CloseAboutReq();
  1630. }
  1631.  
  1632. /*
  1633. ** process all windows with shared IDCMP
  1634. */
  1635.  
  1636. VOID CheckWindows()
  1637. { struct IntuiMessage *imsg;
  1638.   struct Window *iwin,*win;
  1639.   ULONG class,code;
  1640.   APTR iadr;
  1641.   LONG tmp;
  1642.  
  1643.   while ((imsg=GT_GetIMsg(gb->WindowPort)) != NULL) {
  1644.     class = imsg->Class;
  1645.     code  = imsg->Code;
  1646.     iadr  = imsg->IAddress;
  1647.     iwin  = imsg->IDCMPWindow;
  1648.     GT_ReplyIMsg(imsg);
  1649.     if (gb->MainWin == iwin) {
  1650.       switch (class) {
  1651.         case CHANGEWINDOW:
  1652.           win = gb->MainWin;
  1653.           gb->Top = win->TopEdge; gb->Left = win->LeftEdge;
  1654.           gb->Width = win->Width; gb->Height = win->Height;
  1655.           if (gb->Snap) {
  1656.             CloseGfx();
  1657.             if (!(gb->GoOn=InitClock()))
  1658.               return;
  1659.           }
  1660.           else {
  1661.             NewSize1();
  1662.             if (!(gb->GoOn=NewSize2()))
  1663.               return;
  1664.             Rahmen();
  1665.             ZifferBlatt();
  1666.             Zeichnen();
  1667.           }
  1668.           break;
  1669.         case REFRESHWINDOW:
  1670.           gb->ReDrawx1=(tmp=gb->BoLeft);
  1671.           gb->ReDrawx2=tmp+gb->Width2-1;
  1672.           gb->ReDrawy1=(tmp=gb->BoTop);
  1673.           gb->ReDrawy2=tmp+gb->Height2-1;
  1674.           BeginRefresh(gb->MainWin);
  1675.           Rahmen();
  1676.           Zeichnen();
  1677.           EndRefresh(gb->MainWin,TRUE);
  1678.           break;
  1679.         case MENUPICK:
  1680.           HandleMenus(code);
  1681.           if (!gb->GoOn)
  1682.             return;
  1683.           break;
  1684.         case CLOSEWINDOW:
  1685.           gb->GoOn = 0; return;
  1686.           break;
  1687.         case ACTIVEWINDOW:
  1688.           StopAudio();
  1689.           gb->Active = -1;
  1690.           Rahmen();
  1691.           break;
  1692.         case INACTIVEWINDOW:
  1693.           gb->Active = 0;
  1694.           Rahmen();
  1695.           break;
  1696.       }
  1697.     }
  1698.     else
  1699.       if (gb->ColorWin.Win == iwin) {
  1700.         if (class == CLOSEWINDOW || class == GADGETUP) {
  1701.           FreeWindow(&gb->ColorWin);
  1702.           if (class!=CLOSEWINDOW) { /* kann nur das Palette-Gadget sein */
  1703.             *gb->Color = code;
  1704.             SetPattern();
  1705.             NewSize1();
  1706.             if (!(gb->GoOn=NewSize2()))
  1707.               return;
  1708.             Rahmen();
  1709.             ZifferBlatt();
  1710.             Zeichnen();
  1711.           }
  1712.         }
  1713.       }
  1714.       else
  1715.         if (gb->AlarmWin.Win == iwin) {
  1716.           if (class==CLOSEWINDOW || class==MOUSEMOVE || class==GADGETUP) {
  1717.             if (class!=CLOSEWINDOW) {
  1718.               switch(((struct Gadget *)iadr)->GadgetID) {
  1719.                 case 1:
  1720.                   gb->St = code;
  1721.                   goto endit;
  1722.                 case 2:
  1723.                   gb->Mi = code;
  1724.                   goto endit;
  1725.                 case 3:
  1726.                   gb->AlStd = gb->St; gb->AlMin = gb->Mi; gb->Alarm = -1;
  1727.                 case 4:
  1728.                   break;
  1729.               }
  1730.             }
  1731.             FreeWindow(&gb->AlarmWin);
  1732.             if (gb->Alarm) {
  1733.               struct MenuItem *item=ItemAddress(gb->Menus,FULLMENUNUM(1,7,1));
  1734.               if (!(item->Flags&CHECKED)) {
  1735.                 ClearMenuStrip(gb->MainWin);
  1736.                 item->Flags |= CHECKED;
  1737.                 ResetMenuStrip(gb->MainWin,gb->Menus);
  1738.               }
  1739.             }
  1740. endit:      ;
  1741.           }
  1742.         }
  1743.   }
  1744. }
  1745.  
  1746. /*
  1747. ** function for Menu-Handling
  1748. */
  1749.  
  1750. CONST UWORD ColorWinInfo[] = {
  1751.   CLOSEWINDOW | PALETTEIDCMP, MSG_CHOOSE,
  1752.   1,
  1753.   4,2,144,68,0,PALETTE_KIND,
  1754. };
  1755.  
  1756. CONST UWORD AlarmWinInfo[] = {
  1757.   CLOSEWINDOW | BUTTONIDCMP | SLIDERIDCMP, MSG_ALARM,
  1758.   4,
  1759.   42,15,20,39,0         ,SLIDER_KIND,
  1760.   82,15,20,39,0         ,SLIDER_KIND,
  1761.    2,58,70,12,MSG_USE   ,BUTTON_KIND,
  1762.   76,58,70,12,MSG_CANCEL,BUTTON_KIND,
  1763. };
  1764.  
  1765. CONST struct TagItem AlarmGadTags1[] = {
  1766.   { GTSL_Min        ,0               },
  1767.   { GTSL_Max        ,23              },
  1768.   { GTSL_MaxLevelLen,10              },
  1769.   { GTSL_LevelPlace ,PLACETEXT_ABOVE },
  1770.   { PGA_FREEDOM     ,LORIENT_VERT    },
  1771.   { GA_RelVerify    ,TRUE            },
  1772.   { TAG_DONE        ,NULL            }
  1773. };
  1774.  
  1775. CONST struct TagItem AlarmGadTags2[] = {
  1776.   { GTSL_Min        ,0               },
  1777.   { GTSL_Max        ,59              },
  1778.   { GTSL_MaxLevelLen,5               },
  1779.   { GTSL_LevelPlace ,PLACETEXT_ABOVE },
  1780.   { PGA_FREEDOM     ,LORIENT_VERT    },
  1781.   { GA_RelVerify    ,TRUE            },
  1782.   { TAG_DONE        ,NULL            }
  1783. };
  1784.  
  1785. VOID HandleMenus(ULONG code)
  1786. { struct TagItem tags[6],*tt[4];
  1787.   struct MenuItem *item;
  1788.   struct Window *req;
  1789.   ULONG mnum,inum,snum,*p,ok=1;
  1790.   BYTE check;
  1791.  
  1792.   while ((UWORD)code != MENUNULL) {
  1793.     item = ItemAddress(gb->Menus,code);
  1794.     mnum = MENUNUM(code); inum = ITEMNUM(code); snum = SUBNUM(code);
  1795.     (UWORD)code = item->NextSelect;
  1796.  
  1797.     switch (mnum) {
  1798.       case 0: /* Project */
  1799.         switch (inum) {
  1800.           case 0: /* About */
  1801.             if (gb->AboutReq == NULL) {
  1802.               gb->EasyBuf.es_StructSize   = 5*sizeof(ULONG);
  1803.               gb->EasyBuf.es_Flags        = 0;
  1804.               gb->EasyBuf.es_Title        = gb->RexxPort->mp_Node.ln_Name;
  1805.               gb->EasyBuf.es_TextFormat   = PROGNAME;
  1806.               gb->EasyBuf.es_GadgetFormat = GetCatalogString(MSG_DESCRIPTION);
  1807.               req = BuildEasyRequestArgs(gb->MainWin,&gb->EasyBuf,NULL,NULL);
  1808.               if ((ULONG)req>1)
  1809.                 gb->AboutReq = req;
  1810.             }
  1811.             break;
  1812.           case 1: /* Quit */
  1813.             gb->GoOn = 0; return;
  1814.             break;
  1815.         }
  1816.         break;
  1817.       case 1: /* Settings */
  1818.         check = (item->Flags&CHECKED ? 1 : 0);
  1819.         switch (inum) {
  1820.           case  0: /* Seconds */
  1821.             gb->Seconds = check;
  1822.             StopIO(&gb->TimerIO->tr_node);
  1823.             NextTick();
  1824.             break;
  1825.           case  1: /* Oval */
  1826.             gb->Oval = check;
  1827.             break;
  1828.           case  2: /* Show */
  1829.             if (check)
  1830.               gb->Show = snum;
  1831.             break;
  1832.           case  3: /* Hands */
  1833.             if (check)
  1834.               switch (snum) {
  1835.                 case 0: case 1: case 2: case 3:
  1836.                   gb->HandType  = snum;
  1837.                   break;
  1838.                 case 5: case 6: case 7: case 8: case 9:
  1839.                   gb->HandWidth = snum-5;
  1840.                   break;
  1841.               }
  1842.             break;
  1843.           case  4: /* Shadow */
  1844.             gb->Shadow = check;
  1845.             break;
  1846.           case  5: /* Border */
  1847.             switch (snum) {
  1848.               case 0: case 1: case 2:
  1849.                 if (check)
  1850.                   gb->BorderCount = snum;
  1851.                 break;
  1852.               case 4:
  1853.                 gb->HiRes = check;
  1854.                 break;
  1855.               case 5:
  1856.                 gb->Interlace = check;
  1857.                 break;
  1858.             }
  1859.             break;
  1860.           case  6: /* Chime */
  1861.             switch (snum) {
  1862.               case 0: case 1: case 2:
  1863.                 if (check)
  1864.                   gb->Chime = snum;
  1865.                 break;
  1866.               case 4:
  1867.                 gb->SmartHour = check;
  1868.                 break;
  1869.             }
  1870.           case  7: /* Alarm */
  1871.             switch (snum) {
  1872.               case 0:
  1873.                 if (gb->AlarmWin.Win == NULL) {
  1874.                   gb->St = gb->AlStd; tt[0] = &tags[0];
  1875.                   p = (ULONG *)tt[0];
  1876.                   *p++ = GTSL_Level; *p++ = gb->AlStd;
  1877.                   *p++ = GTSL_LevelFormat; *p++ = (ULONG)"%2ld";
  1878.                   *p++ = TAG_MORE; *p = (ULONG)&AlarmGadTags1[0];
  1879.                   gb->Mi = gb->AlMin; tt[1] = &tags[3];
  1880.                   p = (ULONG *)tt[1];
  1881.                   *p++ = GTSL_Level; *p++ = gb->AlMin;
  1882.                   *p++ = GTSL_LevelFormat; *p++ = (ULONG)"%02ld";
  1883.                   *p++ = TAG_MORE; *p = (ULONG)&AlarmGadTags2[0];
  1884.                   tt[2] = NULL; tt[3] = NULL;
  1885.                   CreateRequest(&gb->AlarmWin,(struct wInfo *)&AlarmWinInfo[0],&tt[0]);
  1886.                 }
  1887.                 break;
  1888.               case 1:
  1889.                 gb->Alarm = check;
  1890.                 break;
  1891.             }
  1892.             break;
  1893.           case  8: /* Window Properties */
  1894.             switch (snum) {
  1895.               case 0:
  1896.                 gb->CloseGad = check;
  1897.                 break;
  1898.               case 1:
  1899.                 if (gb->Backdrop != check)
  1900.                   { gb->Backdrop = check; ok=0; }
  1901.                 break;
  1902.               case 2:
  1903.                 gb->Fixed = check;
  1904.                 break;
  1905.               case 3:
  1906.                 gb->Snap = 0; gb->UseImage = check;
  1907.                 DeleteBitMap(gb->BFInfo.SnapBitMap,gb->Depth);
  1908.                 gb->BFInfo.SnapBitMap = NULL;
  1909.                 break;
  1910.               case 4:
  1911.                 gb->UseImage = 0; if ((gb->Snap=check)) { ok=0; }
  1912.                 DeleteBitMap(gb->BFInfo.SnapBitMap,gb->Depth);
  1913.                 gb->BFInfo.SnapBitMap = NULL;
  1914.                 break;
  1915.             }
  1916.             break;
  1917.           case 10: /* Save Settings */
  1918.             SaveSettings();
  1919.             break;
  1920.         }
  1921.         break;
  1922.       case 2: /* Colours */
  1923.       case 3: /* Pattern */
  1924.         if (gb->ColorWin.Win == NULL) {
  1925.           gb->Color = &gb->Pens[(mnum == 2 ? inum : inum + MUST)];
  1926.           tt[0] = &tags[0];
  1927.           p = (ULONG *)tt[0];
  1928.           *p++ = GTPA_Depth; *p++ = (gb->Depth<6 ? gb->Depth : 5); *p = TAG_DONE;
  1929.           CreateRequest(&gb->ColorWin,(struct wInfo *)&ColorWinInfo[0],&tt[0]);
  1930.         }
  1931.         break;
  1932.     }
  1933.   }
  1934.   if (!ok) {
  1935.     CloseGfx(); gb->GoOn=InitClock();
  1936.   }
  1937.   else {
  1938.     NewSize1();
  1939.     if (!(gb->GoOn=NewSize2()))
  1940.       return;
  1941.     Rahmen();
  1942.     ZifferBlatt();
  1943.     Zeichnen();
  1944.   }
  1945. }
  1946.  
  1947. /***************************************************************************/
  1948. /*                                                                         */
  1949. /* create a bitmap (use a V39+ function if available)                      */
  1950. /*                                                                         */
  1951. /***************************************************************************/
  1952.  
  1953. struct BitMap *CreateBitMap(ULONG width,ULONG height,ULONG depth)
  1954. { struct BitMap *bm;
  1955.   PLANEPTR *p;
  1956.   LONG size,plus,i;
  1957.  
  1958.   if (gb->V39)
  1959.     return AllocBitMap(width,height,depth,BMF_MINPLANES,PUB_SCREEN->RastPort.BitMap);
  1960.  
  1961.   plus=0; if (depth>8) plus=(depth-8)*sizeof(PLANEPTR);
  1962.  
  1963.   if ((bm=AllocVec(sizeof(struct BitMap)+plus,MEMF_ANY)) != NULL) {
  1964.     InitBitMap(bm,depth,width,height);
  1965.  
  1966.     p=&bm->Planes[0]; size=bm->BytesPerRow*bm->Rows; i=depth;
  1967.     do {
  1968.       if ((*p++=AllocVec(size,MEMF_CHIP)) == NULL)
  1969.         break;
  1970.     } while(--i);
  1971.  
  1972.     if (i != 0)
  1973.       { DeleteBitMap(bm,depth-i); bm=NULL; }
  1974.   }
  1975.   return bm;
  1976. }
  1977.  
  1978. /***************************************************************************/
  1979. /*                                                                         */
  1980. /* resize invisible gadgets, init hidden drawing area                      */
  1981. /*                                                                         */
  1982. /***************************************************************************/
  1983.  
  1984. CONST WORD Sizes[][4] = { /* Für Gadgets */
  1985.   /* close */ {  0, 0, 3, 2 },
  1986.   /* depth */ { -3, 0, 3, 2 },
  1987.   /* size  */ { -3,-2, 3, 2 },
  1988.   /* drag  */ {  0, 2, 0,-4 }
  1989. };
  1990.  
  1991. LONG NewSize2()
  1992. { struct Window *win = gb->MainWin;
  1993.   struct Gadget *gad;
  1994.   struct BitMap *bm;
  1995.   LONG tmp,w,w2,h,h2,bc,ret;
  1996.   WORD i,j,k,newsize,*s;
  1997.  
  1998.   bc = gb->BorderCount;
  1999.   tmp = bc; if (gb->HiRes) tmp += (bc==2)<<1;
  2000.   gb->BoLeft = tmp;
  2001.   tmp = bc; if (gb->Interlace) tmp += (bc==2)<<1;
  2002.   gb->BoTop  = tmp;
  2003.  
  2004.   w = win->Width;  gb->Width  = w;
  2005.   h = win->Height; gb->Height = h;
  2006.  
  2007.   w2 = w-(gb->BoLeft<<1); gb->Width2  = w2;
  2008.   h2 = h-(gb->BoTop<<1);  gb->Height2 = h2;
  2009.  
  2010.   gb->xDouble = (gb->xMask == -2 && w2 > 12);
  2011.   gb->yDouble = (gb->yMask == -2 && h2 > 12);
  2012.  
  2013.   tmp = 0; if (w2 > 25) tmp = (w2 > 50 ? 2 : 1);
  2014.   gb->xOffset = tmp;
  2015.   tmp = 0; if (h2 > 25) tmp = (h2 > 50 ? 2 : 1);
  2016.   gb->yOffset = tmp;
  2017.  
  2018.   tmp = w; if (w > h) tmp = h; newsize = tmp/8;
  2019.  
  2020.   RemoveGList(win,win->FirstGadget,-1);
  2021.  
  2022.   if (gb->GadSize != newsize) {
  2023.     gb->GadSize = newsize;
  2024.     for (gad=&gb->GadgetBuf[0],s=(WORD *)&Sizes[0],i=GB_GADCOUNT-1; i>=0; gad++,i--)
  2025.       for (j=4-1,k=2; j>=0; k++,j--)
  2026.         ((UWORD *)gad)[k] = *s++*gb->GadSize;
  2027.   }
  2028.  
  2029.   if (!gb->Fixed)
  2030.     { tmp=3; gad=&gb->GadgetBuf[1]; if (gb->Backdrop) { gad+=1; tmp-=1; }
  2031.       AddGList(win,gad,0,tmp,NULL); }
  2032.   if (gb->CloseGad)
  2033.     AddGadget(win,&gb->GadgetBuf[0],0);
  2034.  
  2035.   bm = NULL;
  2036.   if (gb->UseImage)
  2037.     { bm=gb->BFInfo.ImageBitMap; w2=gb->BFInfo.BitMapHeader->bmh_Width; h2=gb->BFInfo.BitMapHeader->bmh_Height; }
  2038.   if (gb->Snap)
  2039.     { bm=gb->BFInfo.SnapBitMap; w2=gb->Width; h2=gb->Height; }
  2040.   gb->BFInfo.BitMap=bm; gb->BFInfo.Width=w2; gb->BFInfo.Height=h2;
  2041.  
  2042.   InitRastPort(&gb->RPort1); ret = 0;
  2043.  
  2044.   if ((RP1_BITMAP=CreateBitMap(gb->Width2,gb->Height2,gb->Depth=GetBitMapDepth(PUB_SCREEN->RastPort.BitMap))) != NULL)
  2045.     if ((gb->Buf=AllocRaster(gb->Width2,gb->Height2)) != NULL) {
  2046.       gb->RPort1.TmpRas  = InitTmpRas(&gb->TempRas,gb->Buf,RASSIZE(gb->Width2,gb->Height2));
  2047.       InitArea(&gb->AreaInfo,&gb->Table[0],5);
  2048.       gb->RPort1.AreaInfo= &gb->AreaInfo;
  2049.       ret = 1;
  2050.     }
  2051.  
  2052.   return ret;
  2053. }
  2054.  
  2055. /***************************************************************************/
  2056. /*                                                                         */
  2057. /* screen title will show the current date                                 */
  2058. /*                                                                         */
  2059. /***************************************************************************/
  2060.  
  2061. VOID NewTitle()
  2062. { struct DateTimeInfo *dti = &gb->DateTime;
  2063.   STRPTR p;
  2064.  
  2065.   DateStamp(&dti->dat.dat_Stamp);
  2066.   dti->dat.dat_StrDay  = &dti->buf[ 0];
  2067.   dti->dat.dat_StrDate = &dti->buf[18];
  2068.   DateToStr(&dti->dat);
  2069.   p=dti->dat.dat_StrDay;
  2070.   while (*p++); p[-1] = ','; *p++ = ' ';
  2071.   strcpy(p,dti->dat.dat_StrDate);
  2072.   SetWindowTitles(gb->MainWin,(UBYTE *)-1L,dti->dat.dat_StrDay);
  2073. }
  2074.  
  2075. /***************************************************************************/
  2076. /*                                                                         */
  2077. /* issue a timer request                                                   */
  2078. /*                                                                         */
  2079. /***************************************************************************/
  2080.  
  2081. ULONG NextTick()
  2082. { struct timerequest *treq = gb->TimerIO;
  2083.   struct Device *TimerBase;
  2084.   ULONG tmp,old,std,min,sec;
  2085.  
  2086.   TimerBase=treq->tr_node.io_Device;
  2087.   GetSysTime(&treq->tr_time);
  2088.   treq->tr_time.tv_micro = 1100000-treq->tr_time.tv_micro;
  2089.                                /* ^ Ein ganz besonders netter Effekt: Das Timer */
  2090.                                /* Device rundet aktuelle Zeit und Wartezeit ab  */
  2091.   sec = treq->tr_time.tv_secs;
  2092.   tmp = 0; if (!gb->Seconds) tmp = 59-sec%60;
  2093.   treq->tr_time.tv_secs = tmp;
  2094.   treq->tr_node.io_Command = TR_ADDREQUEST;
  2095.   SendIO(&treq->tr_node);
  2096.   gb->TimerSent = -1;
  2097.  
  2098.   old=gb->Std+gb->Min;
  2099.   min=sec/60;
  2100.   gb->Sec=sec%60;
  2101.   std=min/12;
  2102.   gb->Min=(min%=60);
  2103.   gb->Std24=(std/5)%24;
  2104.   gb->Std=(std%=60);
  2105.  
  2106.   return (std+min-old); /* sec==0 ist unzuverlässig bei hoher CPU-Auslastung */
  2107. }
  2108.  
  2109. /***************************************************************************/
  2110. /*                                                                         */
  2111. /* draw border                                                             */
  2112. /*                                                                         */
  2113. /***************************************************************************/
  2114.  
  2115. VOID Rahmen()
  2116. { struct RastPort *rp = gb->RPort;
  2117.   ULONG pen,pen11,pen12;
  2118.   LONG w,h,bl,bt;
  2119.  
  2120.   if (gb->BorderCount) {
  2121.     w = gb->Width; h = gb->Height; pen11 = gb->Pens[11]; pen12 = gb->Pens[12];
  2122.  
  2123.     if (gb->Active && gb->BorderCount == 1)
  2124.       { pen=pen11; pen11=pen12; pen12=pen; }
  2125.  
  2126.     SetAPen(rp,pen11);
  2127.     Move(rp,1  ,h-1);
  2128.     Draw(rp,w-1,h-1);
  2129.     Draw(rp,w-1,1  );
  2130.     SetAPen(rp,pen12);
  2131.     Move(rp,0  ,h-1);
  2132.     Draw(rp,0  ,0  );
  2133.     Draw(rp,w-1,0  );
  2134.  
  2135.     if (gb->BorderCount == 2) {
  2136.       bl = gb->BoLeft; bt = gb->BoTop;
  2137.       SetAPen(rp,gb->Pens[12]);
  2138.       Move(rp,bl  ,h-bt);
  2139.       Draw(rp,w-bl,h-bt);
  2140.       Draw(rp,w-bl,bt  );
  2141.       SetAPen(rp,gb->Pens[11]);
  2142.       Move(rp,bl-1,h-bt);
  2143.       Draw(rp,bl-1,bt-1);
  2144.       Draw(rp,w-bl,bt-1);
  2145.       pen = gb->Pens[10]; if (gb->Active) pen = gb->Pens[13];
  2146.       SetAPen(rp,pen);
  2147.  
  2148.       if (gb->HiRes) {
  2149.         RectFill(rp,1,1,2,h-2);
  2150.         RectFill(rp,w-3,1,w-2,h-2);
  2151.       }
  2152.  
  2153.       if (gb->Interlace) {
  2154.         RectFill(rp,1,1,w-2,2);
  2155.         RectFill(rp,1,h-3,w-2,h-2);
  2156.       }
  2157.     }
  2158.   }
  2159.   SetAPen(rp,gb->Pens[0]);
  2160. }
  2161.  
  2162. /***************************************************************************/
  2163. /*                                                                         */
  2164. /* create the clock                                                        */
  2165. /*                                                                         */
  2166. /***************************************************************************/
  2167.  
  2168. CONST BYTE sinus[] = { /* sinus-Tabelle */
  2169.   0,13,26,39,52,64,75,85,94,103,110,116,121,124,126,
  2170.   127,126,124,121,116,110,103,94,85,75,64,52,39,26,13,
  2171.   0,-13,-26,-39,-52,-64,-75,-85,-94,-103,-110,-116,-121,-124,-126,
  2172.   -127,-126,-124,-121,-116,-110,-103,-94,-85,-75,-64,-52,-39,-26,-13
  2173. },
  2174.            cosinus[] = { /* cosinus-Tabelle */
  2175.   127,126,124,121,116,110,103,94,85,75,64,52,39,26,13,
  2176.   0,-13,-26,-39,-52,-64,-75,-85,-94,-103,-110,-116,-121,-124,-126,
  2177.   -127,-126,-124,-121,-116,-110,-103,-94,-85,-75,-64,-52,-39,-26,-13,
  2178.   0,13,26,39,52,64,75,85,94,103,110,116,121,124,126
  2179. };
  2180.  
  2181. CONST BYTE srect[] = { /* Für rechteckiges Zifferblatt */
  2182.   0,13,27,41,57,73,92,111,124,127,127,127,127,127,127,
  2183.   127,127,127,127,127,127,127,124,111,92,73,57,41,27,13,
  2184.   0,-13,-27,-41,-57,-73,-92,-111,-124,-127,-127,-127,-127,-127,-127,
  2185.   -127,-127,-127,-127,-127,-127,-127,-124,-111,-92,-73,-57,-41,-27,-13
  2186. },
  2187.            crect[] = {
  2188.   127,127,127,127,127,127,127,124,111,92,73,57,41,27,13,
  2189.   0,-13,-27,-41,-57,-73,-92,-111,-124,-127,-127,-127,-127,-127,-127,
  2190.   -127,-127,-127,-127,-127,-127,-127,-124,-111,-92,-73,-57,-41,-27,-13,
  2191.   0,13,27,41,57,73,92,111,124,127,127,127,127,127,127
  2192. };
  2193.  
  2194. CONST UBYTE pent[] = { /* Pen-Tabelle f. Zifferblatt */
  2195.   6,8,8,7,8,8,7,8,8,7,8,8
  2196. };
  2197.  
  2198. CONST BYTE dx1[] = { /* Daten für Zifferblatt */
  2199.   -2, 2, 1,-2, 1, 2,-2,-2,-1,-2,-1,-2
  2200. },
  2201.            dy1[] = {
  2202.   -4,-1,-2,-2, 2, 1,-2, 1, 2,-2,-2,-1
  2203. },
  2204.            dx2[] = {
  2205.    4,-2, 1, 4, 1,-2, 4, 2,-1, 4,-1, 2
  2206. },
  2207.            dy2[] = {
  2208.    0, 3, 2, 0,-2,-3, 0,-3,-2, 0, 2, 3
  2209. },
  2210.            dx3[] = {
  2211.    0,-2,-3, 0,-3,-2, 0, 2, 3, 0, 3, 2
  2212. },
  2213.            dy3[] = {
  2214.    8,-1, 2, 4,-2, 1, 4, 1,-2, 4, 2,-1
  2215. },
  2216.            dx4[] = {
  2217.   -4, 2,-1,-4,-1, 2,-4,-2, 1,-4, 1,-2
  2218. },
  2219.            dy4[] = {
  2220.    0,-3,-2, 0, 2, 3, 0, 3, 2, 0,-2,-3
  2221. };
  2222.  
  2223. VOID ZifferBlatt()
  2224. { struct RastPort *rp = &gb->RPort1;
  2225.   LONG i,a,b,c,x,y,bt,bl;
  2226.  
  2227.   if (gb->BFInfo.BitMap) {
  2228.     x=0; y=0; if (gb->Snap) { x=gb->BoLeft; y=gb->BoTop; }
  2229.  
  2230.     CopyTiledBitMap(gb->BFInfo.BitMap,gb->BFInfo.Width,gb->BFInfo.Height,
  2231.                     RP1_BITMAP,gb->Width2,gb->Height2,x,y);
  2232.   }
  2233.   else {
  2234.     SetRast  (rp,gb->Pens[MUST]);
  2235.     BNDRYOFF (rp);
  2236.     SetAPen  (rp,-1);
  2237.     SetAfPt  (rp,&gb->Muster[0][0],-1);
  2238.     RectFill (rp,0,0,gb->Width2-1,gb->Height2-1);
  2239.     SetAfPt  (rp,0,0);
  2240.   }
  2241.  
  2242.   i = gb->Show; a = (i > 1 ? (i == 3 ? 60 : 15) : (i ? 5 : 1));
  2243.   if (i < 4)
  2244.     for (i=0; i<60; i+=a) {
  2245.       x = gb->Width2 /2 + (((gb->Oval ?   sinus[i] : srect[i])*gb->Width2 /300) & gb->xMask);
  2246.       y = gb->Height2/2 - (((gb->Oval ? cosinus[i] : crect[i])*gb->Height2/300) & gb->yMask);
  2247.       if (i%5) {
  2248.         if (i%5==1) {
  2249.           c=gb->Pens[9];
  2250.           SetAPen(rp,c);
  2251.           SetOPen(rp,c);
  2252.         }
  2253.         AreaMove (rp,x+gb->Width2/100,y);
  2254.         AreaDraw (rp,x,y+gb->Height2/100);
  2255.         AreaDraw (rp,x-gb->Width2/100,y);
  2256.         AreaDraw (rp,x,y-gb->Height2/100);
  2257.         AreaEnd  (rp);
  2258.       }
  2259.       else {
  2260.         b=i/5;
  2261.         c=gb->Pens[pent[b]];
  2262.         SetAPen(rp,c);
  2263.         SetOPen(rp,c);
  2264.         AreaMove (rp,x+=gb->Width2*dx1[b]/100,y+=gb->Height2*dy1[b]/100);
  2265.         AreaDraw (rp,x+=gb->Width2*dx2[b]/100,y+=gb->Height2*dy2[b]/100);
  2266.         AreaDraw (rp,x+=gb->Width2*dx3[b]/100,y+=gb->Height2*dy3[b]/100);
  2267.         AreaDraw (rp,x+=gb->Width2*dx4[b]/100,y+=gb->Height2*dy4[b]/100);
  2268.         AreaEnd  (rp);
  2269.       }
  2270.     }
  2271.   if (gb->Shadow) {
  2272.     Zeiger(gb->Std,440,1,gb->Pens[5],gb->Pens[5]);
  2273.     Zeiger(gb->Min,300,1,gb->Pens[5],gb->Pens[5]); }
  2274.   Zeiger(gb->Std,440,0,gb->Pens[3],gb->Pens[4]);
  2275.   Zeiger(gb->Min,300,0,gb->Pens[1],gb->Pens[2]);
  2276.  
  2277.   bl = gb->BoLeft;
  2278.   gb->ReDrawx1 = bl; gb->ReDrawx2 = bl + gb->Width2  - 1;
  2279.   bt = gb->BoTop;
  2280.   gb->ReDrawy1 = bt; gb->ReDrawy2 = bt + gb->Height2 - 1;
  2281. }
  2282.  
  2283. /*
  2284. ** create hands
  2285. */
  2286.  
  2287. CONST LONG HandWidth[] = {
  2288.   4000,3250,2500,1750,1000
  2289. };
  2290.  
  2291. VOID Zeiger(ULONG winkel,LONG lfactor,LONG offset,LONG apen,LONG open)
  2292. { struct RastPort *rp;
  2293.   LONG x0,y0,x1,y1,x2,y2,tmp;
  2294.  
  2295.   tmp = gb->Width2;
  2296.   x2 = sinus  [winkel]*tmp/lfactor;
  2297.   x1 = cosinus[winkel]*tmp/HandWidth[gb->HandWidth];
  2298.   x0 = tmp/2 + (offset ? gb->xOffset : 0);
  2299.  
  2300.   tmp = gb->Height2;
  2301.   y2 = cosinus[winkel]*tmp/lfactor;
  2302.   y1 = sinus  [winkel]*tmp/HandWidth[gb->HandWidth];
  2303.   y0 = tmp/2 + (offset ? gb->yOffset : 0);
  2304.  
  2305.   rp = &gb->RPort1;
  2306.  
  2307.   SetAPen(rp,apen);
  2308.   SetOPen(rp,open);
  2309.  
  2310.   switch (gb->HandType) {
  2311.     case 0:
  2312.       SetAPen(rp,open);
  2313.       Move (rp,x0,y0);
  2314.       Draw (rp,x0+x2,y0-y2);
  2315.       if (gb->xDouble) {
  2316.         Move (rp,1+x0,y0);
  2317.         Draw (rp,1+x0+x2,y0-y2); }
  2318.       if (gb->yDouble) {
  2319.         Move (rp,x0,1+y0);
  2320.         Draw (rp,x0+x2,1+y0-y2); }
  2321.       break;
  2322.     case 1:
  2323.       AreaMove (rp,x0+x2     ,y0-y2     );
  2324.       AreaDraw (rp,x0+x1-x2/4,y0+y1+y2/4);
  2325.       AreaDraw (rp,x0-x1-x2/4,y0-y1+y2/4);
  2326.       AreaEnd  (rp);
  2327.       break;
  2328.     case 2:
  2329.       AreaMove (rp,x0+x2  ,y0-y2  );
  2330.       AreaDraw (rp,x0+x1  ,y0+y1  );
  2331.       AreaDraw (rp,x0-x2/4,y0+y2/4);
  2332.       AreaDraw (rp,x0-x1  ,y0-y1  );
  2333.       AreaEnd  (rp);
  2334.       break;
  2335.     case 3:
  2336.       AreaMove (rp,x0+=x2-x1/2,y0-=y2+y1/2);
  2337.       AreaDraw (rp,x0+=x1     ,y0+=y1     );
  2338.       AreaDraw (rp,x0-=x2*5/4 ,y0+=y2*5/4 );
  2339.       AreaDraw (rp,x0-=x1     ,y0-=y1     );
  2340.       AreaEnd  (rp);
  2341.       break;
  2342.   }
  2343. }
  2344.  
  2345. /***************************************************************************/
  2346. /*                                                                         */
  2347. /* display the clock (blit from the `hidden' window to the real one)       */
  2348. /*                                                                         */
  2349. /***************************************************************************/
  2350.  
  2351. VOID Zeichnen()
  2352. { struct RastPort *rp = gb->RPort;
  2353.   LONG tmp,x1,y1,x2,y2;
  2354.  
  2355.   BltBitMapRastPort(RP1_BITMAP,gb->ReDrawx1-gb->BoLeft,gb->ReDrawy1-gb->BoTop,
  2356.                     rp,gb->ReDrawx1,gb->ReDrawy1,gb->ReDrawx2-gb->ReDrawx1+1,
  2357.                     gb->ReDrawy2-gb->ReDrawy1+1,0xc0);
  2358.   if (gb->Seconds) {
  2359.     x1 = gb->Width/2;
  2360.     x2 = x1+sinus[gb->Sec]*gb->Width2/300;
  2361.     y1 = gb->Height/2;
  2362.     y2 = y1-cosinus[gb->Sec]*gb->Height2/300;
  2363.  
  2364.     Move(rp,x1,y1);
  2365.     Draw(rp,x2,y2);
  2366.  
  2367.     if (gb->xDouble) {
  2368.       Move(rp,x1+1,y1);
  2369.       Draw(rp,x2+1,y2); }
  2370.  
  2371.     if (gb->yDouble) {
  2372.       Move(rp,x1,y1+1);
  2373.       Draw(rp,x2,y2+1); }
  2374.  
  2375.     if (x1 > x2)
  2376.       { tmp=x1; x1=x2; x2=tmp; }
  2377.     if (gb->xDouble)
  2378.       x2++;
  2379.     gb->ReDrawx1 = x1; gb->ReDrawx2 = x2;
  2380.  
  2381.     if (y1 > y2)
  2382.       { tmp=y1; y1=y2; y2=tmp; }
  2383.     if (gb->yDouble)
  2384.       y2++;
  2385.     gb->ReDrawy1 = y1; gb->ReDrawy2 = y2;
  2386.   }
  2387. }
  2388.  
  2389. /***************************************************************************/
  2390. /*                                                                         */
  2391. /* initialize background pattern mask                                      */
  2392. /*                                                                         */
  2393. /***************************************************************************/
  2394.  
  2395. VOID SetPattern()
  2396. { LONG i,a,b,c,d;
  2397.   UBYTE *p1;
  2398.   UWORD *p2;
  2399.  
  2400.   p1=&gb->Pens[MUST]; a=*p1++; b=*p1++; c=*p1++; d=*p1;
  2401.  
  2402.   if (a==b && c==d) /* nur horizontale Streifen */
  2403.     gb->xMask = -1;
  2404.   else
  2405.     gb->xMask = -2;
  2406.  
  2407.   if (a==c && b==d) /* nur vertikale Streifen */
  2408.     gb->yMask = -1;
  2409.   else
  2410.     gb->yMask = -2;
  2411.  
  2412.   for (p2=&gb->Muster[0][0],i=0; i<8; i++) {
  2413.     *p2=(a&1<<i?0x5555:0)|(b&1<<i?0xaaaa:0); p2++;
  2414.     *p2=(c&1<<i?0x5555:0)|(d&1<<i?0xaaaa:0); p2++; }
  2415. }
  2416.  
  2417. /***************************************************************************/
  2418. /*                                                                         */
  2419. /* save current settings to the programs icon                              */
  2420. /*                                                                         */
  2421. /***************************************************************************/
  2422.  
  2423. enum {
  2424.   TT_TOP=0,TT_LEFT,TT_WIDTH,TT_HEIGHT,TT_SHOWFACE,TT_HANDTYPE,TT_HANDWIDTH,
  2425.   TT_BORDERTYPE,TT_WINDOWTYPE,TT_CHIME,TT_ALARM,TT_SECONDS,TT_OVAL,TT_SHADOW,
  2426.   TT_DRAWPENS,TT_PATTERN
  2427. };
  2428.  
  2429. CONST STRPTR ToolTypes[] = {
  2430.   "TOP","LEFT","WIDTH","HEIGHT","SHOWFACE","HANDTYPE","HANDWIDTH","BORDERTYPE",
  2431.   "WINDOWTYPE","CHIME","ALARM","SECONDS","OVAL","SHADOW","DRAWPENS","PATTERN"
  2432. };
  2433.  
  2434. #define TTCOUNT (sizeof(ToolTypes)/sizeof(ToolTypes[0]))
  2435.  
  2436. VOID SaveSettings()
  2437. { struct DiskObject *dobj;
  2438.   BPTR old_cd;
  2439.  
  2440.   old_cd = CurrentDir(gb->ProgArg.wa_Lock);
  2441.  
  2442.   if ((dobj=GetDiskObjectNew(gb->ProgArg.wa_Name)) != NULL) { /* Tooltypes einlesen */
  2443.     UBYTE **tt,*t,*tbuf,*tbuf1;
  2444.     char **tmp,*p,**p1,**p2;
  2445.     LONG arg,i;
  2446.  
  2447.     p1=dobj->do_ToolTypes; p2=p1; do {} while(*p2++);
  2448.  
  2449.     if ((tbuf=AllocVec(((STRPTR)p2-(STRPTR)p1)+sizeof(ToolTypes)+40*TTCOUNT,MEMF_ANY))) {
  2450.       tt=(UBYTE **)(tbuf+40*TTCOUNT);
  2451.  
  2452.       p1=dobj->do_ToolTypes; p2=(char **)tt; do {} while((*p2++=*p1++));
  2453.  
  2454.       for (i=0;i<TTCOUNT;i++) { /* eigene Tooltypes entfernen */
  2455.         if (FindToolType(tt,t=GetToolType(i))) {
  2456.           p2=(char **)tt; do {} while(*++p2 && FindToolType((UBYTE **)p2,t));
  2457.           do { p=*p2++; } while((p2[-2]=p));
  2458.         }
  2459.       }
  2460.  
  2461.       /* Tooltypes zählen */
  2462.       p1=(char **)tt; do {} while(*p1++); --p1; tbuf1=tbuf;
  2463.  
  2464.       *p1++=tbuf1;
  2465.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_TOP,gb->Top);
  2466.  
  2467.       *p1++=tbuf1;
  2468.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_LEFT,gb->Left);
  2469.  
  2470.       *p1++=tbuf1;
  2471.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_WIDTH,gb->Width);
  2472.  
  2473.       *p1++=tbuf1;
  2474.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_HEIGHT,gb->Height);
  2475.  
  2476.       *p1++=tbuf1;
  2477.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_SHOWFACE,gb->Show);
  2478.  
  2479.       *p1++=tbuf1;
  2480.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_HANDTYPE,gb->HandType);
  2481.  
  2482.       *p1++=tbuf1;
  2483.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_HANDWIDTH,gb->HandWidth);
  2484.  
  2485.       *p1++=tbuf1;
  2486.       arg = gb->BorderCount + (gb->HiRes ? 4 : 0) + (gb->Interlace ? 8 : 0);
  2487.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_BORDERTYPE,arg);
  2488.  
  2489.       *p1++=tbuf1;
  2490.       arg = (gb->CloseGad ? WT_CLOSEGAD : 0) + (gb->Backdrop ? WT_BACKDROP : 0) +
  2491.             (gb->Fixed ? WT_FIXED : 0) + (gb->UseImage ? WT_USEIMAGE : 0) +
  2492.             (gb->Snap ? WT_SNAP : 0);
  2493.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_WINDOWTYPE,arg);
  2494.  
  2495.       *p1++=tbuf1;
  2496.       arg = gb->Chime + (gb->SmartHour ? 4 : 0);
  2497.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_CHIME,arg);
  2498.  
  2499.       *p1++=tbuf1;
  2500.       arg = gb->AlStd<<6; arg = (arg+gb->AlMin)<<1; if (gb->Alarm) arg++;
  2501.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_ALARM,arg);
  2502.  
  2503.       if (gb->Seconds)
  2504.         { *p1++=tbuf1; tbuf1=SetToolType(tbuf1,"%s",TT_SECONDS); }
  2505.  
  2506.       if (gb->Oval)
  2507.         { *p1++=tbuf1; tbuf1=SetToolType(tbuf1,"%s",TT_OVAL); }
  2508.  
  2509.       if (gb->Shadow)
  2510.         { *p1++=tbuf1; tbuf1=SetToolType(tbuf1,"%s",TT_SHADOW); }
  2511.  
  2512.       *p1++=tbuf1;
  2513.       tbuf1=SetToolType(tbuf1,"%s=x",TT_DRAWPENS); tbuf1=SetStr(tbuf1,&gb->Pens[0],14);
  2514.  
  2515.       *p1++=tbuf1;
  2516.       tbuf1=SetToolType(tbuf1,"%s=x",TT_PATTERN); tbuf1=SetStr(tbuf1,&gb->Pens[MUST],4);
  2517.  
  2518.       *p1=NULL;
  2519.  
  2520.       tmp=dobj->do_ToolTypes;
  2521.       dobj->do_ToolTypes=(char **)tt;
  2522.       PutDiskObject(gb->ProgArg.wa_Name,dobj);
  2523.       dobj->do_ToolTypes=tmp;
  2524.  
  2525.       FreeVec(tbuf);
  2526.     }
  2527.     FreeDiskObject(dobj);
  2528.   }
  2529.   CurrentDir(old_cd);
  2530. }
  2531.  
  2532. /*
  2533. ** make a tooltype string
  2534. */
  2535.  
  2536. CONST ULONG tricky=0x16c04e75; /* move.b d0,(a3)+ ; rts */
  2537.  
  2538. STRPTR SetToolType(STRPTR buf,STRPTR fmt,LONG num,...)
  2539. {
  2540.   ((STRPTR *)&num)[0] = GetToolType(num);
  2541.   RawDoFmt(fmt,(APTR)&num,(VOID (*)())&tricky,buf);
  2542.   for(;*buf++;); return buf;
  2543. }
  2544.  
  2545. /*
  2546. ** get a tooltype name
  2547. */
  2548.  
  2549. STRPTR GetToolType(LONG num)
  2550. {
  2551.   return (STRPTR)ToolTypes[num];
  2552. }
  2553.  
  2554. /*
  2555. ** make an ascii pen-string
  2556. */
  2557.  
  2558. STRPTR SetStr(STRPTR dst,STRPTR src,LONG cnt)
  2559. {
  2560.   --dst;
  2561.   do {
  2562.     *dst++=DtoX(*src>>4);
  2563.     *dst++=DtoX(*src++&0xf);
  2564.   } while (--cnt);
  2565.   *dst++='\0'; return dst;
  2566. }
  2567.  
  2568. LONG DtoX(LONG a)
  2569. {
  2570.   if ((a+='0')>('9'))
  2571.     a+=7;
  2572.   return(a);
  2573. }
  2574.  
  2575. /***************************************************************************/
  2576. /*                                                                         */
  2577. /* audio stuff                                                             */
  2578. /*                                                                         */
  2579. /***************************************************************************/
  2580.  
  2581. CONST UWORD AlarmTune[] = {
  2582.   800,800,800,800,800,800,800,1600,
  2583.   800,800,800,800,800,800,800,1600,
  2584.   800,800,800,800,800,800,800,1600,
  2585.   800,800,800,800,800,800,800,1600,
  2586.   800,800,800,800,800,800,800,4,0
  2587. };
  2588.  
  2589. CONST UWORD HourTune[] = {
  2590.   800,1600,800,1600,800,1600,800,1600,
  2591.   800,1600,800,1600,800,1600,800,1600,
  2592.   800,1600,800,1600,800,1600,800,4,0
  2593. };
  2594.  
  2595. CONST UWORD QuarterTune[] = {
  2596.   400,400,400,400,400,4,0
  2597. };
  2598.  
  2599. VOID TestIfAlarm()
  2600. { CONST UWORD *tune;
  2601.   ULONG st2;
  2602.   LONG mi2,i;
  2603.  
  2604.   st2=gb->Std24; mi2 = gb->Min; tune = AlarmTune;
  2605.   if (!gb->Alarm || mi2!=gb->AlMin || st2!=gb->AlStd) {
  2606.     if (!gb->Chime)
  2607.       return;
  2608.     if (!mi2) {
  2609.       tune = HourTune; i=22; if (gb->SmartHour) i=24-(st2<<=1);
  2610.     }
  2611.     else {
  2612.       if (gb->Chime != 2)
  2613.         return;
  2614.       tune = QuarterTune;
  2615.       for(i=6;;) {
  2616.         i-=2;
  2617.         if ((mi2-=15)<0)
  2618.           return;
  2619.         if (mi2==0)
  2620.           break;
  2621.       }
  2622.     }
  2623.     tune = &tune[i];
  2624.   }
  2625.   StartTune(tune);
  2626. }
  2627.  
  2628. /*
  2629. ** allocate audio channels and initiate the sound
  2630. */
  2631.  
  2632. CONST UBYTE ChannelMap[] = { 1,2,4,8 }; /* Sound Channel Allocation Map */
  2633.  
  2634. VOID StartTune(CONST UWORD *tune)
  2635. { struct IOAudio *io;
  2636.  
  2637.   if (gb->AudioOpen && !gb->SoundOn) {
  2638.     io = gb->AudioIO[0];
  2639.     io->ioa_Request.io_Command = ADCMD_ALLOCATE;
  2640.     io->ioa_Request.io_Message.mn_Node.ln_Pri = 90; /* ALARM-Level */
  2641.     io->ioa_Request.io_Flags   = ADIOF_NOWAIT;
  2642.     io->ioa_Data               = (UBYTE *)&ChannelMap[0];
  2643.     io->ioa_Length             = sizeof(ChannelMap);
  2644.     BeginIO(&io->ioa_Request);
  2645.     if (!WaitIO(&io->ioa_Request)) {
  2646.       gb->SoundOn = -1;
  2647.       if (!(ciaa.ciapra & CIAF_LED))
  2648.         { ciaa.ciapra |= CIAF_LED; gb->Filter = -1; }
  2649.       CopyMemQuick(io,gb->AudioIO[1],sizeof(struct IOAudio));
  2650.       gb->PlayTune = (UWORD *)tune;
  2651.       PlayNote();
  2652.       PlayNote();
  2653.     }
  2654.   }
  2655. }
  2656.  
  2657. /*
  2658. ** beep, beep, ...
  2659. */
  2660.  
  2661. VOID PlayNote()
  2662. { struct IOAudio *io;
  2663.   LONG old,new;
  2664.   BYTE *sent = &gb->AudioSent[0];
  2665.  
  2666.   old = gb->RequestNr;
  2667.   new = !old;
  2668.   gb->RequestNr = new;
  2669.  
  2670.   sent[old] =  0;
  2671.   if (!*gb->PlayTune) {
  2672.     if (!sent[new]) /* Anderer Request auch zurück ? */
  2673.       EndTune(); return; }
  2674.   sent[old] = -1;   /* Merken */
  2675.   io = gb->AudioIO[old];
  2676.   io->ioa_Request.io_Command = CMD_WRITE;
  2677.   io->ioa_Request.io_Flags   = ADIOF_PERVOL;
  2678.   io->ioa_Data               = (UBYTE *)&((ULONG *)gb->WaveForm)[old];
  2679.   io->ioa_Length             = 4;
  2680.   io->ioa_Period             = 500; /* ekliger Piepton */
  2681.   io->ioa_Volume             = 64;
  2682.   io->ioa_Cycles             = *(gb->PlayTune)++;
  2683.   BeginIO(&io->ioa_Request);
  2684. }
  2685.  
  2686. /*
  2687. ** end audio output
  2688. */
  2689.  
  2690. VOID EndTune()
  2691. { struct IOAudio *io = gb->AudioIO[0];
  2692.  
  2693.   io->ioa_Request.io_Command=ADCMD_FREE;
  2694.   DoIO(&io->ioa_Request);
  2695.   if (gb->Filter)
  2696.     { ciaa.ciapra &= ~CIAF_LED; gb->Filter = 0; }
  2697.   gb->SoundOn = 0;
  2698. }
  2699.  
  2700. /***************************************************************************/
  2701. /*                                                                         */
  2702. /* create a new window and its gadgets                                     */
  2703. /*                                                                         */
  2704. /***************************************************************************/
  2705.  
  2706. CONST struct TextAttr Topaz = {
  2707.   "topaz.font",8,FS_NORMAL,FPF_ROMFONT
  2708. };
  2709.  
  2710. VOID CreateRequest(struct WinGad *wg,struct wInfo *wi,struct TagItem **tagptr)
  2711. { struct Gadget *context;
  2712.  
  2713.   if ((context=CreateContext(&wg->Gad)) != NULL) {
  2714.     struct NewWindow *nw = &gb->NewWindowBuf;
  2715.     struct Window *win;
  2716.     struct gInfo *gi;
  2717.     UWORD cnt;
  2718.  
  2719.     nw->LeftEdge    = 100;
  2720.     nw->TopEdge     = 100;
  2721.     nw->Width       = 0;
  2722.     nw->Height      = 0;
  2723.     nw->Flags       = WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_ACTIVATE|WFLG_RMBTRAP;
  2724.     nw->FirstGadget = wg->Gad;
  2725.     nw->Title       = GetCatalogString(wi->textnr);
  2726.  
  2727.     gb->NewGad.ng_GadgetID = 0; cnt = wi->gadcnt; gi = &wi->gi[0];
  2728.     do {
  2729.       struct NewGadget *ng = &gb->NewGad;
  2730.       struct Screen *scr = nw->Screen;
  2731.       ULONG num;
  2732.  
  2733.       ng->ng_LeftEdge   = gi->left + scr->WBorLeft;
  2734.       ng->ng_TopEdge    = gi->top  + scr->WBorLeft + scr->RastPort.TxHeight;
  2735.       ng->ng_Width      = gi->width;
  2736.       ng->ng_Height     = gi->height;
  2737.       if ((num=gi->textnr))
  2738.         num = (ULONG)GetCatalogString(num);
  2739.       ng->ng_GadgetText = (STRPTR)num;
  2740.       ng->ng_TextAttr   = (struct TextAttr *)&Topaz;
  2741.       ng->ng_GadgetID++;
  2742.       ng->ng_VisualInfo = gb->VisualInfo;
  2743.  
  2744.       if ((context=CreateGadgetA(gi->kind,context,ng,tagptr[0])) == NULL) {
  2745.         FreeGadgets(wg->Gad); wg->Gad = NULL; return;
  2746.       }
  2747.  
  2748.       gi++; tagptr++;
  2749.     } while(--cnt);
  2750.  
  2751.     if ((wg->Win=(win=OpenWindowShared(&gb->NewWindowBuf,&WindowTags[0],wi->idcmp))) != NULL) {
  2752.       SetWindowTitles(win,(UBYTE *)-1L,PROGNAME); GT_RefreshWindow(win,NULL);
  2753.     }
  2754.     else {
  2755.       FreeGadgets(wg->Gad); wg->Gad = NULL;
  2756.     }
  2757.   }
  2758. }
  2759.  
  2760. /***************************************************************************/
  2761. /*                                                                         */
  2762. /* open a window for shared IDCMP                                          */
  2763. /*                                                                         */
  2764. /***************************************************************************/
  2765.  
  2766. struct Window *OpenWindowShared(struct NewWindow *nw,CONST struct TagItem *tl,ULONG idcmp)
  2767. { struct Window *win;
  2768.  
  2769.   if ((win=OpenWindowTagList(nw,(struct TagItem *)tl)) != NULL) {
  2770.     win->UserPort = gb->WindowPort;
  2771.     if (!ModifyIDCMP(win,idcmp)) {
  2772.       CloseWindowSafely(win); win=NULL;
  2773.     }
  2774.   }
  2775.   return win;
  2776. }
  2777.  
  2778. /***************************************************************************/
  2779. /*                                                                         */
  2780. /* get localized string                                                    */
  2781. /*                                                                         */
  2782. /***************************************************************************/
  2783.  
  2784. CONST STRPTR LocStrings[] = {
  2785.   /* MSG_PROJECT     */ "Project",
  2786.   /* MSG_ABOUT       */ "About",
  2787.   /* MSG_ABOUTKEY    */ "?",
  2788.   /* MSG_QUIT        */ "Quit",
  2789.   /* MSG_QUITKEY     */ "Q",
  2790.   /* MSG_SETTINGS    */ "Settings",
  2791.   /* MSG_SECONDS     */ "Seconds",
  2792.   /* MSG_OVAL        */ "Oval",
  2793.   /* MSG_SHOW        */ "Show",
  2794.   /* MSG_MINUTES     */ "Minutes",
  2795.   /* MSG_HOURS       */ "Hours",
  2796.   /* MSG_QUARTER     */ "Quarter",
  2797.   /* MSG_ONE         */ "Twelve",
  2798.   /* MSG_NONE        */ "None",
  2799.   /* MSG_HANDS       */ "Hands",
  2800.   /* MSG_LINE        */ "Line",
  2801.   /* MSG_TRIANGLE    */ "Triangle",
  2802.   /* MSG_RHOMBUS     */ "Rhombus",
  2803.   /* MSG_RECTANGLE   */ "Rectangle",
  2804.   /* MSG_VERYTHIN    */ "Very Thin",
  2805.   /* MSG_THIN        */ "Thin",
  2806.   /* MSG_NORMAL      */ "Normal",
  2807.   /* MSG_THICK       */ "Thick",
  2808.   /* MSG_VERYTHICK   */ "Very Thick",
  2809.   /* MSG_SHADOW      */ "Shadow",
  2810.   /* MSG_BORDER      */ "Border",
  2811.   /* MSG_SINGLE      */ "Single",
  2812.   /* MSG_DOUBLE      */ "Double",
  2813.   /* MSG_HIRES       */ "HiRes",
  2814.   /* MSG_INTERLACE   */ "Interlace",
  2815.   /* MSG_CHIME       */ "Chime",
  2816.   /* MSG_SMART       */ "Smart",
  2817.   /* MSG_ALARM       */ "Alarm",
  2818.   /* MSG_SET         */ "Set",
  2819.   /* MSG_ON          */ "On",
  2820.   /* MSG_USEIMAGE    */ "Use Image",
  2821.   /* MSG_CLOSEGAD    */ "Close Gadget",
  2822.   /* MSG_SAVESETTING */ "Save Settings",
  2823.   /* MSG_SAVEKEY     */ "S",
  2824.   /* MSG_COLORS      */ "Colors",
  2825.   /* MSG_MINAPEN     */ "Min. Area",
  2826.   /* MSG_MINOPEN     */ "Min. Outline",
  2827.   /* MSG_HOURAPEN    */ "Hour Area",
  2828.   /* MSG_HOUROPEN    */ "Hour Outline",
  2829.   /* MSG_STR12       */ "Twelve",
  2830.   /* MSG_BORDER0     */ "Border 0",
  2831.   /* MSG_BORDER1     */ "Border 1",
  2832.   /* MSG_BORDER2     */ "Border 2",
  2833.   /* MSG_BORDER3     */ "Border 3",
  2834.   /* MSG_PATTERN     */ "Pattern",
  2835.   /* MSG_COLOR0      */ "Color 0",
  2836.   /* MSG_COLOR1      */ "Color 1",
  2837.   /* MSG_COLOR2      */ "Color 2",
  2838.   /* MSG_COLOR3      */ "Color 3",
  2839.   /* MSG_DESCRIPTION */ "a really nice clock !",
  2840.   /* MSG_CHOOSE      */ "Choose one:",
  2841.   /* MSG_USE         */ "Use",
  2842.   /* MSG_CANCEL      */ "Cancel",
  2843.   /*
  2844.   ** new with 1.5
  2845.   */
  2846.   /* MSG_WINDOW      */ "Window",
  2847.   /* MSG_BACKDROP    */ "Backdrop",
  2848.   /* MSG_FIXED       */ "Immovable",
  2849.   /*
  2850.   ** new with 1.6
  2851.   */
  2852.   /* MSG_SNAP        */ "Transparent"
  2853. };
  2854.  
  2855. STRPTR GetCatalogString(LONG strnum)
  2856. { struct Catalog *cat;
  2857.   STRPTR loc;
  2858.  
  2859.   loc = LocStrings[strnum];
  2860.   if ((cat=gb->Catalog) != NULL)
  2861.     loc = GetCatalogStr(cat,strnum,loc);
  2862.   return loc;
  2863. }
  2864.  
  2865. /***************************************************************************/
  2866. /*                                                                         */
  2867. /* duplicate a bitmap (based on the work of P.Carette + W.Dörwald)         */
  2868. /*                                                                         */
  2869. /***************************************************************************/
  2870.  
  2871. VOID CopyTiledBitMap(struct BitMap *Src,LONG SrcSizeX,LONG SrcSizeY,
  2872.                      struct BitMap *Dst,LONG DstSizeX,LONG DstSizeY,
  2873.                      LONG SrcOffsetX,LONG SrcOffsetY)
  2874. { LONG Pos;  /* used as starting position in the "exponential" blit */
  2875.   LONG Size; /* used as bitmap size in the "exponential" blit       */
  2876.  
  2877.   /* adjust source sizes */
  2878.   SrcSizeX -= SrcOffsetX; SrcSizeY -= SrcOffsetY;
  2879.  
  2880.   /* blit the first piece of the tile */
  2881.   blt_bitmap(Src,SrcOffsetX,SrcOffsetY,Dst,0,0,MIN(SrcSizeX,DstSizeX),MIN(SrcSizeY,DstSizeY));
  2882.  
  2883.   /* this loop generates the first row of the tiles */
  2884.   for (Pos = SrcSizeX,Size = MIN(SrcSizeX,DstSizeX-Pos);Pos<DstSizeX;) {
  2885.     blt_bitmap(Dst,0,0,Dst,Pos,0,Size,MIN(SrcSizeY,DstSizeY));
  2886.     Pos += Size;
  2887.     Size = MIN(Size<<1,DstSizeX-Pos);
  2888.   }
  2889.  
  2890.   /* this loop blit the first row down several times to fill the whole dest rect */
  2891.   for (Pos = SrcSizeY,Size = MIN(SrcSizeY,DstSizeY-Pos);Pos<DstSizeY;) {
  2892.     blt_bitmap(Dst,0,0,Dst,0,Pos,DstSizeX,Size);
  2893.     Pos += Size;
  2894.     Size = MIN(Size<<1,DstSizeY-Pos);
  2895.   }
  2896. }
  2897.  
  2898. /***************************************************************************/
  2899. /*                                                                         */
  2900. /* replacement functions                                                   */
  2901. /*                                                                         */
  2902. /***************************************************************************/
  2903.  
  2904. LONG blt_bitmap(struct BitMap *src,LONG xsrc,LONG ysrc,
  2905.                 struct BitMap *dst,LONG xdst,LONG ydst,
  2906.                 LONG xsize,LONG ysize)
  2907. {
  2908.   return BltBitMap(src,xsrc,ysrc,dst,xdst,ydst,xsize,ysize,0xC0,-1,NULL);
  2909. }
  2910.  
  2911. Object *new_dt_object(APTR name,ULONG data,...)
  2912. {
  2913.   return NewDTObjectA(name,(struct TagItem *)&data);
  2914. }
  2915.  
  2916. ULONG get_dt_attrs(Object *obj,ULONG data,...)
  2917. {
  2918.   return GetDTAttrsA(obj,(struct TagItem *)&data);
  2919. }
  2920.  
  2921. VOID sprintf(STRPTR buf,STRPTR fmt,...)
  2922. {
  2923.   RawDoFmt(fmt,(LONG *)&fmt+1,(VOID (*)())&tricky,buf);
  2924. }
  2925.  
  2926. /***************************************************************************/
  2927. /*                                                                         */
  2928. /* The End                                                                 */
  2929. /*                                                                         */
  2930. /***************************************************************************/
  2931.