home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / opus / v5 / opussdk / examples / iconclock / iconclock.c < prev    next >
C/C++ Source or Header  |  1977-12-31  |  14KB  |  695 lines

  1. #include "iconclock.h"
  2.  
  3. // Define the version string here
  4. static char *version="$VER: iconclock.module 55.0 (15.08.96)";
  5.  
  6. // Main entry point
  7. int __asm __saveds L_Module_Entry(
  8.     register __a0 char *args,
  9.     register __a1 struct Screen *screen,
  10.     register __a2 IPCData *ipc,
  11.     register __a3 IPCData *main_ipc,
  12.     register __d0 ULONG mod_id,
  13.     register __d1 EXT_FUNC(func_callback))
  14. {
  15.     iconclock_data *data;
  16.     IPCData *clock_ipc;
  17.  
  18.     // See if we're already running; return if we are
  19.     if (FindSemaphore(NAME_ICONCLOCK)) return 1;
  20.  
  21.     // Allocate data
  22.     if (data=AllocVec(sizeof(iconclock_data),MEMF_CLEAR))
  23.     {
  24.         // Store A4 and library bases
  25.         data->a4=getreg(REG_A4);
  26.         data->library=DOpusBase;
  27.         data->module=(struct Library *)getreg(REG_A6);
  28.         data->main_ipc=main_ipc;
  29.  
  30.         // Store initial screen
  31.         data->screen=screen;
  32.         data->pen=-1;
  33.  
  34.         // Launch process
  35.         if (!(IPC_Launch(
  36.             0,
  37.             &clock_ipc,
  38.             NAME_ICONCLOCK,
  39.             (ULONG)icon_clock,
  40.             4000,
  41.             (ULONG)data,
  42.             DOSBase))) FreeVec(data);
  43.     }
  44.  
  45.     // No process?
  46.     if (!clock_ipc) return 0;
  47.  
  48.     return 1;
  49. }
  50.  
  51.  
  52. // Icon clock process
  53. void __saveds icon_clock(void)
  54. {
  55.     IPCData *ipc;
  56.     IPCMessage *msg;
  57.     DOpusNotify *nmsg;
  58.     struct AppMessage *amsg;
  59.     struct Library *DOpusBase;
  60.     iconclock_data *data;
  61.     BOOL quit=0,visible=1;
  62.  
  63.     // Get dopus library
  64.     if (!(DOpusBase=(struct Library *)FindName(&((struct ExecBase *)*((ULONG *)4))->LibList,"dopus5.library")))
  65.         return;
  66.  
  67.     // Do startup
  68.     ipc=IPC_ProcStartup((ULONG *)&data,iconclock_startup);
  69.  
  70.     // Fix A4 so we can access global data in the module (eg library bases)
  71.     putreg(REG_A4,data->a4);
  72.  
  73.     // Failed?
  74.     if (!ipc)
  75.     {
  76.         iconclock_cleanup(data);
  77.         return;
  78.     }
  79.  
  80.     // Got a screen?
  81.     if (data->screen)
  82.     {
  83.         struct Screen *scr=data->screen;
  84.  
  85.         // Initialise clock for this screen
  86.         data->screen=0;
  87.         iconclock_init(data,scr);
  88.     }
  89.  
  90.     // Event loop
  91.     FOREVER
  92.     {
  93.         // Timer returned?
  94.         if (CheckTimer(data->timer))
  95.         {
  96.             // Update the time if visible
  97.             if (visible)
  98.             {
  99.                 // Show time
  100.                 iconclock_show(data);
  101.             }
  102.  
  103.             // Restart timer
  104.             StartTimer(data->timer,0,900000);
  105.         }
  106.  
  107.         // IPC messages?
  108.         while (msg=(IPCMessage *)GetMsg(ipc->command_port))
  109.         {
  110.             // We don't do anything with them at this stage
  111.             IPC_Reply(msg);
  112.         }
  113.  
  114.         // Notify messages from Opus?
  115.         while (nmsg=(DOpusNotify *)GetMsg(data->notify_port))
  116.         {
  117.             // Opus has Quit?
  118.             if (nmsg->dn_Type&DN_OPUS_QUIT) quit=1;
  119.  
  120.             // Opus has been hidden?
  121.             else
  122.             if (nmsg->dn_Type&DN_OPUS_HIDE)
  123.             {
  124.                 // Made invisible
  125.                 iconclock_init(data,0);
  126.                 visible=0;
  127.             }
  128.  
  129.             // Opus has been revealed
  130.             else
  131.             if (nmsg->dn_Type&DN_OPUS_SHOW)
  132.             {
  133.                 // Screen changed?
  134.                 if (data->screen!=((struct Window *)nmsg->dn_Data)->WScreen)
  135.                 {
  136.                     // Just made visible
  137.                     iconclock_init(data,((struct Window *)nmsg->dn_Data)->WScreen);
  138.                 }
  139.                 visible=1;
  140.             }
  141.  
  142.             // Reply to the message
  143.             ReplyFreeMsg((struct Message *)nmsg);
  144.         }
  145.  
  146.         // About Requester open?
  147.         if (data->about)
  148.         {
  149.             // Handle requester
  150.             if (SysReqHandler(data->about,0,0)>=0)
  151.             {
  152.                 // Close requester
  153.                 FreeSysRequest(data->about);
  154.                 data->about=0;
  155.             }
  156.         }
  157.  
  158.         // Check quit flag
  159.         if (quit) break;
  160.  
  161.         // AppMessages?
  162.         while (amsg=(struct AppMessage *)GetMsg(data->app_port))
  163.         {
  164.             // SnapShot?
  165.             if (amsg->am_Type==MTYPE_APPSNAPSHOT)
  166.             {
  167.                 struct AppSnapshotMsg *asm;
  168.  
  169.                 // Get SnapShot message pointer
  170.                 asm=(struct AppSnapshotMsg *)amsg;
  171.  
  172.                 // Menu operation?
  173.                 if (asm->flags&APPSNAPF_MENU)
  174.                 {
  175.                     // Help?
  176.                     if (asm->flags&APPSNAPF_HELP)
  177.                     {
  178.                         // Send help request
  179.                         if (data->main_ipc)
  180.                             IPC_Command(data->main_ipc,IPC_HELP,(1<<31),"Icon Clock",0,REPLY_NO_PORT);
  181.                     }
  182.  
  183.                     // Colour?
  184.                     else
  185.                     if (asm->id==0)
  186.                     {
  187.                         struct Screen *screen;
  188.  
  189.                         // Toggle colour state
  190.                         data->colour=1-data->colour;
  191.  
  192.                         // Set menu state
  193.                         SetAppIconMenuState(data->appicon,0,data->colour);
  194.  
  195.                         // Save screen
  196.                         screen=data->screen;
  197.  
  198.                         // Close and re-open
  199.                         iconclock_init(data,0);
  200.                         iconclock_init(data,screen);
  201.                     }
  202.                 }
  203.  
  204.                 // Close?
  205.                 else
  206.                 if (asm->flags&APPSNAPF_CLOSE) quit=1;
  207.  
  208.                 // Info?
  209.                 else
  210.                 if (asm->flags&APPSNAPF_INFO)
  211.                 {
  212.                     // Show info
  213.                     iconclock_info(data);
  214.                 }
  215.  
  216.                 // Otherwise
  217.                 else
  218.                 {
  219.                     // Unsnapshot?
  220.                     if (asm->flags&APPSNAPF_UNSNAPSHOT)
  221.                     {
  222.                         // Reinitialise position
  223.                         data->icon_x=NO_ICON_POSITION;
  224.                         data->icon_y=NO_ICON_POSITION;
  225.                     }
  226.  
  227.                     // Store position
  228.                     else
  229.                     {
  230.                         data->icon_x=asm->position_x;
  231.                         data->icon_y=asm->position_y;
  232.                     }
  233.  
  234.                     // Build environment variable
  235.                     sprintf(
  236.                         data->buffer,
  237.                         "%d/%d/%d\n",
  238.                         data->icon_x,
  239.                         data->icon_y,
  240.                         data->colour);
  241.  
  242.                     // Set environment variable
  243.                     SetEnv(ENV_ICONCLOCK,data->buffer,TRUE);
  244.                 }
  245.             }
  246.  
  247.             // Double-click?
  248.             else
  249.             if (amsg->am_Type==MTYPE_APPICON &&
  250.                 amsg->am_NumArgs==0)
  251.             {
  252.                 // Launch date prefs
  253.                 LaunchWB("sys:prefs/time",0,0);
  254.             }
  255.  
  256.             // Reply to message
  257.             ReplyMsg((struct Message *)amsg);
  258.         }
  259.  
  260.         // Check quit flag
  261.         if (quit) break;
  262.  
  263.         // Wait for event
  264.         Wait(    1<<ipc->command_port->mp_SigBit|
  265.                 1<<data->notify_port->mp_SigBit|
  266.                 1<<data->timer->port->mp_SigBit|
  267.                 1<<data->app_port->mp_SigBit|
  268.                 ((data->about)?(1<<data->about->UserPort->mp_SigBit):0));
  269.     }
  270.  
  271.     // Decrement open count so we can be flushed again
  272.     --data->module->lib_OpenCnt;
  273.  
  274.     // Cleanup
  275.     iconclock_cleanup(data);
  276. }
  277.  
  278.  
  279. // Startup code, called by IPC_ProcStartup()
  280. ULONG __asm __saveds iconclock_startup(
  281.     register __a0 IPCData *ipc,
  282.     register __a1 iconclock_data *data)
  283. {
  284.     struct Library *DOpusBase;
  285.  
  286.     // Fix A4
  287.     putreg(REG_A4,data->a4);
  288.  
  289.     // Store IPC
  290.     data->ipc=ipc;
  291.  
  292.     // Get library
  293.     DOpusBase=data->library;
  294.  
  295.     // Initialise data
  296.     data->icon_x=NO_ICON_POSITION;
  297.     data->icon_y=NO_ICON_POSITION;
  298.  
  299.     // Initialise Semaphore
  300.     data->sem.sem.ss_Link.ln_Name=NAME_ICONCLOCK;
  301.     data->sem.ipc=ipc;
  302.     AddSemaphore((struct SignalSemaphore *)&data->sem);
  303.  
  304.     // Create message ports
  305.     if (!(data->notify_port=CreateMsgPort()) ||
  306.         !(data->app_port=CreateMsgPort()))
  307.         return 0;
  308.  
  309.     // Create timer
  310.     if (!(data->timer=AllocTimer(UNIT_VBLANK,0)))
  311.         return 0;
  312.  
  313.     // Add notify request
  314.     if (!(data->notify_req=
  315.         AddNotifyRequest(
  316.             DN_OPUS_QUIT|DN_OPUS_HIDE|DN_OPUS_SHOW,
  317.             0,
  318.             data->notify_port))) return 0;
  319.  
  320.     // Get environment variable
  321.     if (GetVar(ENV_ICONCLOCK,data->buffer,sizeof(data->buffer),GVF_GLOBAL_ONLY)>0)
  322.     {
  323.         char *ptr;
  324.  
  325.         // Get buffer pointer
  326.         ptr=data->buffer;
  327.  
  328.         // Get position
  329.         read_parse_set(&ptr,&data->icon_x);
  330.         read_parse_set(&ptr,&data->icon_y);
  331.         read_parse_set(&ptr,&data->colour);
  332.     }
  333.  
  334.     // Bump library open count so we don't get flushed
  335.     ++data->module->lib_OpenCnt;
  336.  
  337.     // Start timer
  338.     StartTimer(data->timer,0,900000);
  339.  
  340.     return 1;
  341. }
  342.  
  343.  
  344. // Cleanup
  345. void iconclock_cleanup(iconclock_data *data)
  346. {
  347.     if (data)
  348.     {
  349.         struct Message *msg;
  350.  
  351.         // Free screen lock
  352.         iconclock_init(data,0);
  353.  
  354.         // Remove notify request
  355.         RemoveNotifyRequest(data->notify_req);
  356.  
  357.         // Close requester
  358.         FreeSysRequest(data->about);
  359.         data->about=0;
  360.  
  361.         // Flush message ports
  362.         if (data->notify_port)
  363.         {
  364.             while (msg=GetMsg(data->notify_port))
  365.                 ReplyFreeMsg(msg);
  366.         }
  367.         if (data->app_port)
  368.         {
  369.             while (msg=GetMsg(data->app_port))
  370.                 ReplyFreeMsg(msg);
  371.         }
  372.  
  373.         // Delete message ports
  374.         DeleteMsgPort(data->notify_port);
  375.         DeleteMsgPort(data->app_port);
  376.  
  377.         // Free timer
  378.         FreeTimer(data->timer);
  379.  
  380.         // Remove Semaphore
  381.         RemSemaphore((struct SignalSemaphore *)&data->sem);
  382.  
  383.         // Free data
  384.         IPC_Free(data->ipc);
  385.         FreeVec(data);
  386.     }
  387. }
  388.  
  389.  
  390. // Show current time
  391. void iconclock_show(iconclock_data *data)
  392. {
  393.     struct DateStamp date;
  394.     unsigned long hour,minute,second;
  395.     short time[4],colon,x,y=2,a;
  396.     long flags=CAIF_RENDER|CAIF_SELECT;
  397.  
  398.     // Open?
  399.     if (!data->screen) return;
  400.  
  401.     // Get current time
  402.     DateStamp(&date);
  403.  
  404.     // Get hours and minutes and seconds
  405.     hour=DivideU(date.ds_Minute,60,&minute,UtilityBase);
  406.     second=UDivMod32(date.ds_Tick,TICKS_PER_SECOND);
  407.  
  408.     // Get colon we need (either upper or lower half flashing)
  409.     if ((second%2)==0) colon=0;
  410.     else
  411.     if (second<30) colon=1;
  412.     else
  413.     colon=2;
  414.  
  415.     // Get numerals we need for hour
  416.     if (hour>9)
  417.     {
  418.         if (hour>19)
  419.         {
  420.             time[0]=2;
  421.             time[1]=hour-20;
  422.         }
  423.         else
  424.         {
  425.             time[0]=1;
  426.             time[1]=hour-10;
  427.         }
  428.     }
  429.     else
  430.     {
  431.         time[0]=-1;
  432.         time[1]=hour;
  433.     }
  434.  
  435.     // Get numerals we need for minute
  436.     time[2]=0;
  437.     while (minute>9)
  438.     {
  439.         ++time[2];
  440.         minute-=10;
  441.     }
  442.     time[3]=minute;
  443.  
  444.     // Draw digits
  445.     for (a=0,x=2;a<4;a++,x+=NUMERAL_WIDTH+2)
  446.     {
  447.         // Valid number?
  448.         if (time[a]>-1)
  449.         {
  450.             // Draw number
  451.             BltTemplate(
  452.                 (char *)numeral_data[time[a]],
  453.                 0,2,
  454.                 &data->clock_rp,
  455.                 x,y,
  456.                 NUMERAL_WIDTH,NUMERAL_HEIGHT);
  457.         }
  458.  
  459.         // Erase area
  460.         else
  461.         {
  462.             // Save fg pen
  463.             short fg=data->clock_rp.FgPen;
  464.  
  465.             // Set bg pen
  466.             SetAPen(&data->clock_rp,data->clock_rp.BgPen);
  467.  
  468.             // Erase it
  469.             RectFill(
  470.                 &data->clock_rp,
  471.                 x,y,
  472.                 x+NUMERAL_WIDTH-1,
  473.                 y+NUMERAL_HEIGHT-1);
  474.  
  475.             // Restore pen
  476.             SetAPen(&data->clock_rp,fg);
  477.         }
  478.  
  479.         // Time for the colon?
  480.         if (a==1)
  481.         {
  482.             // Draw colon
  483.             BltTemplate(
  484.                 (char *)colon_data[colon],
  485.                 0,2,
  486.                 &data->clock_rp,
  487.                 x+NUMERAL_WIDTH+1,y,
  488.                 COLON_WIDTH,COLON_HEIGHT);
  489.  
  490.             // Bump x position
  491.             x+=COLON_WIDTH;
  492.         }
  493.     }
  494.  
  495.     // Day different?
  496.     if (date.ds_Days!=data->day)
  497.     {
  498.         struct DateTime dt;
  499.  
  500.         // Fill out dt
  501.         dt.dat_Stamp=date;
  502.         dt.dat_Format=FORMAT_DOS;
  503.         dt.dat_Flags=0;
  504.         dt.dat_StrDay=0;
  505.         dt.dat_StrDate=data->date_buffer;
  506.         dt.dat_StrTime=0;
  507.  
  508.         // Get date string
  509.         DateToStr(&dt);
  510.         flags|=CAIF_TITLE;
  511.     }
  512.  
  513.     // Update image
  514.     ChangeAppIcon(data->appicon,&data->clock_image,&data->clock_image,data->date_buffer,flags);
  515. }
  516.  
  517.  
  518. // Parse number out of string, leave pointer at one character after end of number
  519. void read_parse_set(char **ptr,long *val)
  520. {
  521.     // Digit?
  522.     if (isdigit(*(*ptr)))
  523.     {
  524.         *val=atoi(*ptr);
  525.         while (*(*ptr) && isdigit(*(*ptr))) ++*ptr;
  526.         ++*ptr;
  527.     }
  528. }
  529.  
  530.  
  531. // Initialise screen stuff
  532. void iconclock_init(iconclock_data *data,struct Screen *screen)
  533. {
  534.     // Got a screen locked?
  535.     if (data->screen)
  536.     {
  537.         // Free pen
  538.         if (data->pen>-1)
  539.         {
  540.             ReleasePen(data->screen->ViewPort.ColorMap,data->pen);
  541.             data->pen=-1;
  542.         }
  543.  
  544.         // Unlock it
  545.         UnlockPubScreen(0,data->screen);
  546.         data->screen=0;
  547.  
  548.         // Remove AppIcon
  549.         if (data->appicon) RemoveAppIcon(data->appicon);
  550.         data->appicon=0;
  551.  
  552.         // Free bitmap
  553.         FreeVec(data->clock_image.ImageData);
  554.         data->clock_image.ImageData=0;
  555.     }
  556.  
  557.     // No new screen?
  558.     if (!screen) return;
  559.  
  560.     // Try to lock screen
  561.     if (FindPubScreen(screen,TRUE))
  562.     {
  563.         short depth=1;
  564.  
  565.         // Store pointer
  566.         data->screen=screen;
  567.  
  568.         // Under 39 grab a pen
  569.         if (GfxBase->lib_Version>=39 && data->colour)
  570.         {
  571.             // Allocate pen
  572.             if ((data->pen=ObtainPen(
  573.                 screen->ViewPort.ColorMap,
  574.                 -1,
  575.                 0,0xffffffff,0,
  576.                 PENF_EXCLUSIVE))>-1)
  577.             {
  578.                 // Set colour
  579.                 SetRGB32(&screen->ViewPort,data->pen,0,0xffffffff,0);
  580.  
  581.                 // Get depth we need
  582.                 for (depth=1;depth<=8;depth++)
  583.                     if (1<<depth>data->pen) break;
  584.             }
  585.         }
  586.  
  587.         // Initialise clock bitmap
  588.         InitBitMap(&data->clock_bm,depth,CLOCK_WIDTH,CLOCK_HEIGHT);
  589.  
  590.         // Allocate clock bitmap
  591.         if (data->clock_image.ImageData=
  592.             (USHORT *)AllocVec(RASSIZE(CLOCK_WIDTH,CLOCK_HEIGHT)*depth,MEMF_CHIP|MEMF_CLEAR))
  593.         {
  594.             struct TagItem tags[7];
  595.             USHORT *ptr;
  596.             short a;
  597.  
  598.             // Get bitmap pointers
  599.             ptr=data->clock_image.ImageData;
  600.             for (a=0;a<depth;a++)
  601.             {
  602.                 data->clock_bm.Planes[a]=(PLANEPTR)ptr;
  603.                 ptr+=((CLOCK_WIDTH+15)>>4)*CLOCK_HEIGHT;
  604.             }
  605.  
  606.             // Initialise rastport
  607.             InitRastPort(&data->clock_rp);
  608.             data->clock_rp.BitMap=&data->clock_bm;
  609.             SetDrMd(&data->clock_rp,JAM2);
  610.  
  611.             // Fill in image
  612.             data->clock_image.Width=CLOCK_WIDTH;
  613.             data->clock_image.Height=CLOCK_HEIGHT;
  614.             data->clock_image.Depth=depth;
  615.             data->clock_image.PlanePick=(1<<depth)-1;
  616.  
  617.             // Fill out fake DiskObject
  618.             data->clock_icon.do_Gadget.Width=CLOCK_WIDTH;
  619.             data->clock_icon.do_Gadget.Height=CLOCK_HEIGHT;
  620.             data->clock_icon.do_Gadget.Flags=GFLG_GADGHIMAGE;
  621.             data->clock_icon.do_Gadget.GadgetRender=&data->clock_image;
  622.             data->clock_icon.do_Gadget.SelectRender=&data->clock_image;
  623.             data->clock_icon.do_CurrentX=data->icon_x;
  624.             data->clock_icon.do_CurrentY=data->icon_y;
  625.  
  626.             // AppIcon tags
  627.             tags[0].ti_Tag=DAE_SnapShot;
  628.             tags[0].ti_Data=1;
  629.             tags[1].ti_Tag=DAE_Close;
  630.             tags[1].ti_Data=2;
  631.             tags[2].ti_Tag=DAE_Local;
  632.             tags[2].ti_Data=1;
  633.             tags[3].ti_Tag=DAE_Info;
  634.             tags[3].ti_Data=1;
  635.  
  636.             // Under 39 we can use colour
  637.             if (GfxBase->lib_Version>=39)
  638.             {
  639.                 tags[4].ti_Tag=(data->pen>-1)?DAE_Background:TAG_IGNORE;
  640.                 tags[4].ti_Data=1;
  641.                 tags[5].ti_Tag=(data->colour)?DAE_ToggleMenuSel:DAE_ToggleMenu;
  642.                 tags[5].ti_Data=(ULONG)DOpusGetString(locale,MSG_ICONCLOCK_COLOUR);
  643.                 tags[6].ti_Tag=TAG_END;
  644.             }
  645.             else tags[4].ti_Tag=TAG_END;
  646.  
  647.             // Add AppIcon
  648.             if (data->appicon=AddAppIconA(0,0,NAME_ICONCLOCK,data->app_port,0,&data->clock_icon,tags))
  649.             {
  650.                 // If we have a pen, fill background
  651.                 if (data->pen>-1) SetRast(&data->clock_rp,1);
  652.  
  653.                 // Set pen for clock
  654.                 SetAPen(&data->clock_rp,(data->pen>-1)?data->pen:1);
  655.                 SetBPen(&data->clock_rp,(data->pen>-1)?1:0);
  656.  
  657.                 // Show clock
  658.                 iconclock_show(data);
  659.             }
  660.         }
  661.  
  662.         // Failed?
  663.         if (!data->appicon)
  664.         {
  665.             // Free stuff (this is a bit recursive)
  666.             iconclock_init(data,0);
  667.         }
  668.     }
  669. }
  670.  
  671.  
  672. // Show info window
  673. void iconclock_info(iconclock_data *data)
  674. {
  675.     struct EasyStruct easy;
  676.  
  677.     // Window open?
  678.     if (data->about)
  679.     {
  680.         WindowToFront(data->about);
  681.         ActivateWindow(data->about);
  682.         return;
  683.     }
  684.  
  685.     // Fill out easy struct
  686.     easy.es_StructSize=sizeof(easy);
  687.     easy.es_Flags=0;
  688.     easy.es_Title=DOpusGetString(locale,MSG_ICONCLOCK_TITLE);
  689.     easy.es_TextFormat="Directory Opus 5 Icon Clock\nv55.0 (15.08.96)\n\n© 1996 Jonathan Potter";
  690.     easy.es_GadgetFormat=DOpusGetString(locale,MSG_OK);
  691.  
  692.     // Open requester
  693.     data->about=BuildEasyRequestArgs(data->screen->FirstWindow,&easy,0,0);
  694. }
  695.