home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / DOpus4-GPL / Program / tasks.c < prev    next >
C/C++ Source or Header  |  2000-01-27  |  25KB  |  846 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "DOpus.h"
  32. #include "ppdata.h"
  33.  
  34. #define HOTKEY_UNICONIFY   1
  35. #define HOTKEY_ABORT       3
  36. #define HOTKEY_MMB         5
  37. #define HOTKEY_HOTKEY      10
  38.  
  39. struct Gadget
  40.     abortopgad={
  41.         NULL,0,0,104,0,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  42.         NULL,NULL,NULL,NULL,NULL,0,NULL};
  43.  
  44. static struct NewWindow
  45.     progresswindow={
  46.         0,0,0,0,255,255,
  47.         IDCMP_GADGETUP|IDCMP_RAWKEY,WFLG_BORDERLESS|WFLG_RMBTRAP|WFLG_ACTIVATE,
  48.         NULL,NULL,NULL,NULL,NULL,0,0,0,0,CUSTOMSCREEN};
  49.  
  50. static struct Window *pwindow;
  51. static struct RastPort *prp;
  52. static struct DOpusRemember *prog_key;
  53. static int prog_barx[2],prog_bary[2],prog_texty[2];
  54. static int prog_xoff,prog_yoff,prog_xextra,prog_yextra,prog_areax;
  55. static struct Interrupt
  56.     hotkey_interrupt={
  57.         {NULL,NULL,2,52,"hotkeez_port"},
  58.         NULL,(VOID *)keyhandler};
  59.  
  60. static struct NewBroker
  61.     hotkey_broker={
  62.         NB_VERSION,
  63.         "Directory Opus",
  64.         "Directory Opus © Jonathan Potter",
  65.         "The most amazing program ever written",
  66.         0,COF_SHOW_HIDE,100,NULL,0};
  67.  
  68. static IX hotkey_ix={IX_VERSION};
  69.  
  70. void __saveds hotkeytaskcode()
  71. {
  72.     int top,sig,waitbits,commodity=0,command,x;
  73.     struct dopustaskmsg *hmsg;
  74.     struct IOStdReq *inreq;
  75.     struct MsgPort *inputport,*idcmpport;
  76.     struct IntuiMessage *msg;
  77.     ULONG class,msgid,msgtype;
  78.     USHORT gadgetid,norm_height,norm_width;
  79.     struct IntuiMessage *dummymsg;
  80.     struct dopushotkey *hotkey;
  81.     CxObj *broker,*hotkey_filter,*mmb_filter=NULL;
  82.     CxMsg *cxmsg;
  83.  
  84.     norm_height=scrdata_norm_height;
  85.     norm_width=scrdata_norm_width;
  86.  
  87.     hotkeymsg_port=LCreatePort(NULL,0);
  88.     inputport=LCreatePort(NULL,0);
  89.     idcmpport=LCreatePort(NULL,0);
  90.  
  91.     if (CxBase && !(status_flags&STATUS_IANSCRAP)) {
  92.         hotkey_broker.nb_Port=inputport;
  93.         if (broker=CxBroker(&hotkey_broker,NULL)) {
  94.  
  95.             /* Initialise main hotkey */
  96.             if (hotkey_filter=set_dopus_filter(
  97.                 broker,
  98.                 inputport,
  99.                 NULL,
  100.                 config->hotkeycode,
  101.                 config->hotkeyqual,
  102.                 HOTKEY_UNICONIFY,1)) {
  103.  
  104.                 hotkey_ix.ix_Code=IECODE_LBUTTON;
  105.                 hotkey_ix.ix_Qualifier=IEQUALIFIER_RBUTTON;
  106.                 hotkey_ix.ix_QualMask=0xffff&~(IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RELATIVEMOUSE|IEQUALIFIER_CAPSLOCK);
  107.                 if (set_dopus_filter(broker,inputport,"rawmouse lbutton",
  108.                     0,0,HOTKEY_ABORT,0)) {
  109.  
  110.                     hotkey_ix.ix_Code=IECODE_RBUTTON;
  111.                     hotkey_ix.ix_Qualifier=IEQUALIFIER_LEFTBUTTON;
  112.                     hotkey_ix.ix_QualMask=0xffff&~(IEQUALIFIER_RBUTTON|IEQUALIFIER_RELATIVEMOUSE|IEQUALIFIER_CAPSLOCK);
  113.                     if (set_dopus_filter(broker,inputport,"rawmouse rbutton",
  114.                         0,0,HOTKEY_ABORT,0)) {
  115.  
  116.                         if (config->hotkeyflags&HOTKEY_USEMMB) {
  117.                             hotkey_ix.ix_Code=IECODE_MBUTTON;
  118.                             hotkey_ix.ix_Qualifier=IEQUALIFIER_MIDBUTTON;
  119.                             hotkey_ix.ix_QualMask=0xffff&~(IEQUALIFIER_RELATIVEMOUSE|IEQUALIFIER_CAPSLOCK);
  120.                             mmb_filter=set_dopus_filter(broker,inputport,"rawmouse midbutton",
  121.                                 0,0,HOTKEY_MMB,1);
  122.                         }
  123.  
  124.                         add_hotkey_objects(broker,inputport,1);
  125.                         set_hotkey(hotkey_filter,config->hotkeycode,config->hotkeyqual);
  126.  
  127.                         ActivateCxObj(broker,1);
  128.                         commodity=1;
  129.                     }
  130.                 }
  131.             }
  132.         }
  133.         if (!commodity) {
  134.             add_hotkey_objects(broker,inputport,0);
  135.             DeleteCxObjAll(broker);
  136.         }
  137.     }
  138.  
  139.     if (!commodity) {
  140.         inreq=(struct IOStdReq *)LCreateExtIO(inputport,sizeof(struct IOStdReq));
  141.         OpenDevice("input.device",NULL,(struct IORequest *)inreq,NULL);
  142.         inreq->io_Data=(APTR)&hotkey_interrupt;
  143.         inreq->io_Command=IND_ADDHANDLER;
  144.         DoIO((struct IORequest *)inreq);
  145.     }
  146.  
  147.     FOREVER {
  148.         waitbits=1<<hotkeymsg_port->mp_SigBit|1<<idcmpport->mp_SigBit;
  149.         if (commodity) waitbits|=1<<inputport->mp_SigBit;
  150.         else waitbits|=INPUTSIG_UNICONIFY|INPUTSIG_HOTKEY;
  151.         if (pwindow) waitbits|=1<<pwindow->UserPort->mp_SigBit;
  152.  
  153.         sig=Wait(waitbits);
  154.         command=0;
  155.  
  156.         while (dummymsg=(struct IntuiMessage *)GetMsg(idcmpport))
  157.             FreeMem(dummymsg,sizeof(struct IntuiMessage));
  158.  
  159.         if (commodity) {
  160.             while (cxmsg=(CxMsg *)GetMsg(inputport)) {
  161.                 msgid=CxMsgID(cxmsg);
  162.                 msgtype=CxMsgType(cxmsg);
  163.                 ReplyMsg((struct Message *)cxmsg);
  164.                 switch (msgtype) {
  165.                     case CXM_IEVENT:
  166.                         if ((command=msgid)>=HOTKEY_HOTKEY) {
  167.                             x=command-HOTKEY_HOTKEY; command=HOTKEY_HOTKEY;
  168.                             hotkey=dopus_firsthotkey;
  169.                             while (x-- && hotkey) hotkey=hotkey->next;
  170.                             dopus_globalhotkey=hotkey;
  171.                         }
  172.                         break;
  173.  
  174.                     case CXM_COMMAND:
  175.                         switch (msgid) {
  176.                             case CXCMD_KILL:
  177.                                 command=HOTKEY_HOTKEY;
  178.                                 dopus_globalhotkey=(struct dopushotkey *)-1;
  179.                                 break;
  180.  
  181.                             case CXCMD_DISABLE:
  182.                                 ActivateCxObj(broker,0);
  183.                                 break;
  184.  
  185.                             case CXCMD_ENABLE:
  186.                                 ActivateCxObj(broker,1);
  187.                                 break;
  188.  
  189.                             case CXCMD_APPEAR:
  190.                                 command=HOTKEY_UNICONIFY;
  191.                                 break;
  192.  
  193.                             case CXCMD_DISAPPEAR:
  194.                                 command=HOTKEY_HOTKEY;
  195.                                 dopus_globalhotkey=(struct dopushotkey *)-2;
  196.                                 break;
  197.                         }
  198.                         break;
  199.                 }
  200.             }
  201.         }
  202.         else {
  203.             if (sig&INPUTSIG_UNICONIFY)
  204.                 command=HOTKEY_UNICONIFY;
  205.             else if (sig&INPUTSIG_HOTKEY)
  206.                 command=HOTKEY_HOTKEY;
  207.         }
  208.  
  209.         switch (command) {
  210.             case HOTKEY_ABORT:
  211.                 if (IntuitionBase->ActiveWindow==Window) {
  212.                     status_haveaborted=status_rexxabort=1;
  213.                     Signal((struct Task *)main_proc,INPUTSIG_ABORT);
  214.                 }
  215.                 break;
  216.  
  217.             case HOTKEY_MMB:
  218.                 if (!(config->hotkeyflags&HOTKEY_USEMMB)) break;
  219.             case HOTKEY_UNICONIFY:
  220.                 if (status_configuring==-1) break;
  221.                 if (status_iconified==1) Signal((struct Task *)main_proc,INPUTSIG_UNICONIFY);
  222.                 else if (status_iconified==0) {
  223.                     if (MainScreen) {
  224.                         if (!status_configuring && config->screenflags&SCRFLAGS_HALFHEIGHT)
  225.                             top=main_scr.TopEdge;
  226.                         else top=0;
  227.  
  228.                         if (IntuitionBase->FirstScreen==MainScreen &&
  229.                             MainScreen->TopEdge==top &&
  230.                             (!IntuitionBase->ActiveWindow ||
  231.                                 IntuitionBase->ActiveWindow->WScreen==MainScreen)) {
  232.                             ScreenToBack(MainScreen);
  233.                             if (Window->Parent && Window->Parent->WScreen==IntuitionBase->FirstScreen)
  234.                                 ActivateWindow(Window->Parent);
  235.                             else ActivateWindow(IntuitionBase->FirstScreen->FirstWindow);
  236.                         }
  237.                         else {
  238.                             struct Window *window;
  239.     
  240.                             ScreenToFront(MainScreen);
  241.                             if (MainScreen->FirstWindow==ansiread_window) window=Window;
  242.                             else window=MainScreen->FirstWindow;
  243.  
  244.                             if (!(window->Flags&WFLG_BACKDROP)) WindowToFront(window);
  245.                             ActivateWindow(window);
  246.                         }
  247.                         MoveScreen(MainScreen,0,top-MainScreen->TopEdge);
  248.                     }
  249.                     else {
  250.                         if (IntuitionBase->ActiveWindow==Window &&
  251.                             IntuitionBase->FirstScreen==Window->WScreen &&
  252.                             Window->WScreen->LayerInfo.top_layer==Window->RPort->Layer) {
  253.                             WindowToBack(Window);
  254.                             if (Window->Parent) ActivateWindow(Window->Parent);
  255.                         }
  256.                         else {
  257.                             ScreenToFront(Window->WScreen);
  258.                             WindowToFront(Window);
  259.                             ActivateWindow(Window);
  260.                         }
  261.                     }
  262.                 }
  263.                 break;
  264.  
  265.             case HOTKEY_HOTKEY:
  266.                 if (status_configuring) continue;
  267.                 Signal((struct Task *)main_proc,INPUTSIG_HOTKEY);
  268.                 break;
  269.         }
  270.  
  271.         if (pwindow) {
  272.             while (msg=(struct IntuiMessage *)GetMsg(pwindow->UserPort)) {
  273.                 if ((class=msg->Class)==IDCMP_GADGETUP)
  274.                     gadgetid=((struct Gadget *)msg->IAddress)->GadgetID;
  275.                 ReplyMsg((struct Message *)msg);
  276.                 if (class==IDCMP_GADGETUP && gadgetid==0) {
  277.                     status_haveaborted=status_rexxabort=1;
  278.                     Signal((struct Task *)main_proc,INPUTSIG_ABORT);
  279.                 }
  280.             }
  281.         }
  282.  
  283.         while (hmsg=(struct dopustaskmsg *)GetMsg(hotkeymsg_port)) {
  284.             switch (hmsg->command) {
  285.                 case TASK_QUIT:
  286.                     if (commodity) {
  287.                         add_hotkey_objects(broker,inputport,0);
  288.                         DeleteCxObjAll(broker);
  289.                         while (cxmsg=(CxMsg *)GetMsg(inputport))
  290.                             ReplyMsg((struct Message *)cxmsg);
  291.                     }
  292.                     else {
  293.                         inreq->io_Data=(APTR)&hotkey_interrupt;
  294.                         inreq->io_Command=IND_REMHANDLER;
  295.                         DoIO((struct IORequest *)inreq);
  296.                         CloseDevice((struct IORequest *)inreq);
  297.                         LDeleteExtIO((struct IORequest *)inreq);
  298.                     }
  299.                     LDeletePort(inputport);
  300.                     ReplyMsg((struct Message *)hmsg);
  301.                     LDeletePort(hotkeymsg_port);
  302.                     LDeletePort(idcmpport);
  303.                     if (pwindow) CloseWindow(pwindow);
  304.                     LFreeRemember(&prog_key);
  305.                     Wait(0);
  306.  
  307.                 case PROGRESS_OPEN:
  308.                     if (!pwindow) {
  309.                         openprogresswindow(hmsg->data,hmsg->value,hmsg->total,hmsg->flag);
  310.                         if (pwindow) SetBusyPointer(pwindow);
  311.                     }
  312.                     break;
  313.  
  314.                 case PROGRESS_CLOSE:
  315.                     if (pwindow) {
  316.                         CloseWindow(pwindow);
  317.                         pwindow=NULL;
  318.                     }
  319.                     LFreeRemember(&prog_key);
  320.                     break;
  321.  
  322.                 case PROGRESS_UPDATE:
  323.                     if (pwindow) {
  324.                         if (hmsg->flag==0 || prog_yextra) {
  325.                             if (hmsg->value>-1)
  326.                                 progressbar(prog_barx[hmsg->flag],prog_bary[hmsg->flag],hmsg->value,hmsg->total);
  327.                             if (!hmsg->flag || hmsg->data)
  328.                                 progresstext(prog_texty[hmsg->flag],hmsg->value,hmsg->total,hmsg->data);
  329.                         }
  330.                     }
  331.                     break;
  332.  
  333.                 case HOTKEY_HOTKEYCHANGE:
  334.                     if (commodity) {
  335.                         set_hotkey(hotkey_filter,config->hotkeycode,config->hotkeyqual);
  336.  
  337.                         if (config->hotkeyflags&HOTKEY_USEMMB) {
  338.                             if (!mmb_filter) {
  339.                                 hotkey_ix.ix_Code=IECODE_MBUTTON;
  340.                                 hotkey_ix.ix_Qualifier=IEQUALIFIER_MIDBUTTON;
  341.                                 hotkey_ix.ix_QualMask=0xffff&~(IEQUALIFIER_RELATIVEMOUSE|IEQUALIFIER_CAPSLOCK);
  342.                                 mmb_filter=set_dopus_filter(broker,inputport,"rawmouse midbutton",
  343.                                     0,0,HOTKEY_MMB,1);
  344.                             }
  345.                         }
  346.                         else if (mmb_filter) {
  347.                             DeleteCxObjAll(mmb_filter);
  348.                             mmb_filter=NULL;
  349.                         }
  350.                     }
  351.                     break;
  352.  
  353.                 case HOTKEY_KILLHOTKEYS:
  354.                     if (commodity)
  355.                         add_hotkey_objects(broker,inputport,0);
  356.                     break;
  357.  
  358.                 case HOTKEY_NEWHOTKEYS:
  359.                     if (commodity)
  360.                         add_hotkey_objects(broker,inputport,1);
  361.                     break;
  362.             }
  363.             ReplyMsg((struct Message *)hmsg);
  364.         }
  365.     }
  366. }
  367.  
  368. void add_hotkey_objects(broker,port,add)
  369. CxObj *broker;
  370. struct MsgPort *port;
  371. int add;
  372. {
  373.     static CxObj **filter_table;
  374.     static int hotkey_count;
  375.     struct dopushotkey *hotkey;
  376.     int a;
  377.  
  378.     if (filter_table) {
  379.         for (a=0;a<hotkey_count;a++)
  380.             DeleteCxObjAll(filter_table[a]);
  381.         FreeMem(filter_table,hotkey_count*sizeof(CxObj *));
  382.         filter_table=NULL;
  383.     }
  384.     
  385.     hotkey=dopus_firsthotkey;
  386.     hotkey_count=0;
  387.     while (hotkey) {
  388.         ++hotkey_count;
  389.         hotkey=hotkey->next;
  390.     }
  391.  
  392.     if (!add || !hotkey_count ||
  393.         !(filter_table=AllocMem(hotkey_count*sizeof(CxObj *),MEMF_CLEAR))) return;
  394.  
  395.     hotkey=dopus_firsthotkey;
  396.     a=0;
  397.     while (hotkey) {
  398.         filter_table[a]=
  399.             set_dopus_filter(broker,port,NULL,
  400.                 hotkey->code,hotkey->qualifier,
  401.                 HOTKEY_HOTKEY+a,1);
  402.         ++a;
  403.         hotkey=hotkey->next;
  404.     }
  405. }
  406.  
  407. CxObj *set_dopus_filter(broker,port,string,code,qual,command,translate)
  408. CxObj *broker;
  409. struct MsgPort *port;
  410. char *string;
  411. USHORT code,qual;
  412. int command;
  413. int translate;
  414. {
  415.     CxObj *filter,*cxobj;
  416.  
  417.     if (filter=CxFilter(string)) {
  418.         if (!string) {
  419.             hotkey_ix.ix_Class=IECLASS_RAWKEY;
  420.             if (code==~0) {
  421.                 hotkey_ix.ix_Code=0;
  422.                 hotkey_ix.ix_CodeMask=0;
  423.             }
  424.             else {
  425.                 hotkey_ix.ix_Code=code;
  426.                 hotkey_ix.ix_CodeMask=0xff;
  427.             }
  428.             hotkey_ix.ix_Qualifier=qual&VALID_QUALIFIERS;
  429.             hotkey_ix.ix_QualMask=VALID_QUALIFIERS;
  430.         }
  431.         else {
  432.             hotkey_ix.ix_Class=IECLASS_RAWMOUSE;
  433.             hotkey_ix.ix_CodeMask=0xff;
  434.             hotkey_ix.ix_QualSame=0;
  435.         }
  436.         SetFilterIX(filter,&hotkey_ix);
  437.         AttachCxObj(broker,filter);
  438.         if (cxobj=CxSender(port,command))
  439.             AttachCxObj(filter,cxobj);
  440.         if (translate && (cxobj=CxTranslate(NULL)))
  441.             AttachCxObj(filter,cxobj);
  442.         return(filter);
  443.     }
  444.     return(NULL);
  445. }
  446.  
  447. void set_hotkey(filter,code,qual)
  448. CxObj *filter;
  449. USHORT code,qual;
  450. {
  451.     if (filter) {
  452.         hotkey_ix.ix_Class=IECLASS_RAWKEY;
  453.         if (qual==0 && code==~0) {
  454.             hotkey_ix.ix_Code=0xffff;
  455.             hotkey_ix.ix_CodeMask=0xffff;
  456.             hotkey_ix.ix_Qualifier=0;
  457.             hotkey_ix.ix_Qualifier=0xffff;
  458.         }
  459.         else {
  460.             if (code==~0) {
  461.                 hotkey_ix.ix_Code=0;
  462.                 hotkey_ix.ix_CodeMask=0;
  463.             }
  464.             else {
  465.                 hotkey_ix.ix_Code=code;
  466.                 hotkey_ix.ix_CodeMask=0xff;
  467.             }
  468.             hotkey_ix.ix_Qualifier=qual&VALID_QUALIFIERS;
  469.             hotkey_ix.ix_QualMask=VALID_QUALIFIERS;
  470.         }
  471.         SetFilterIX(filter,&hotkey_ix);
  472.     }
  473. }
  474.  
  475. void openprogresswindow(title,value,total,flag)
  476. char *title;
  477. int value,total,flag;
  478. {
  479.     struct TextFont *font;
  480.     char *gadtxt[2];
  481.     int a;
  482.  
  483.     gadtxt[0]=globstring[STR_ABORT];
  484.     gadtxt[1]=NULL;
  485.  
  486.     if (config->generalscreenflags&SCR_GENERAL_REQDRAG) {
  487.         prog_xoff=Window->WScreen->WBorLeft+2;
  488.         prog_yoff=Window->WScreen->WBorTop+Window->WScreen->Font->ta_YSize+2;
  489.         prog_xextra=prog_xoff+Window->WScreen->WBorRight-2;
  490.     }
  491.     else {
  492.         prog_xoff=2;
  493.         prog_yoff=1;
  494.         prog_xextra=0;
  495.     }
  496.  
  497.     progresswindow.Width=384+(scr_font[FONT_REQUEST]->tf_XSize*8)+prog_xextra;
  498.  
  499.     if (progresswindow.Width>Window->WScreen->Width) {
  500.         font=scr_font[FONT_GENERAL];
  501.         progresswindow.Width=432;
  502.         if (config->generalscreenflags&SCR_GENERAL_REQDRAG)
  503.             progresswindow.Width+=prog_xextra;
  504.     }
  505.     else font=scr_font[FONT_REQUEST];
  506.  
  507.     progresswindow.Height=(font->tf_YSize*5)+22;
  508.     if (flag) {
  509.         progresswindow.Height+=(font->tf_YSize*2)+8;
  510.         prog_yextra=(font->tf_YSize*2)+8;
  511.     }
  512.     else prog_yextra=0;
  513.  
  514.     if (config->generalscreenflags&SCR_GENERAL_REQDRAG) {
  515.         progresswindow.Height+=prog_yoff+Window->WScreen->WBorBottom-1;
  516.         progresswindow.Flags=WFLG_RMBTRAP|WFLG_ACTIVATE|WFLG_DRAGBAR|WFLG_DEPTHGADGET;
  517.         progresswindow.Title=title;
  518.     }
  519.     else {
  520.         progresswindow.Flags=WFLG_BORDERLESS|WFLG_RMBTRAP|WFLG_ACTIVATE;
  521.         progresswindow.Title=NULL;
  522.     }
  523.  
  524.     centerwindow(&progresswindow);
  525.     if (!(pwindow=OpenWindow(&progresswindow))) return;
  526.     prp=pwindow->RPort;
  527.     setupwindreq(pwindow);
  528.     SetFont(prp,font);
  529.  
  530.     Do3DBox(prp,
  531.         26+prog_xoff,
  532.         6+prog_yoff,
  533.         pwindow->Width-prog_xextra-56,
  534.         (font->tf_YSize*4)+prog_yextra,
  535.         screen_pens[config->gadgetbotcol].pen,
  536.         screen_pens[config->gadgettopcol].pen);
  537.     SetAPen(prp,screen_pens[config->requestfg].pen);
  538.  
  539.     abortopgad.LeftEdge=(pwindow->Width-abortopgad.Width)/2;
  540.     abortopgad.Height=font->tf_YSize+4;
  541.     abortopgad.TopEdge=pwindow->Height-pwindow->BorderBottom-9-font->tf_YSize;
  542.     AddGadgetBorders(&prog_key,
  543.         &abortopgad,1,
  544.         screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen);
  545.     AddGadgets(pwindow,
  546.         &abortopgad,
  547.         gadtxt,
  548.         1,
  549.         screen_pens[config->gadgettopcol].pen,
  550.         screen_pens[config->gadgetbotcol].pen,1);
  551.  
  552.     SetAPen(prp,screen_pens[0].pen);
  553.     SetDrMd(prp,JAM2);
  554.     RectFill(prp,
  555.         26+prog_xoff,
  556.         6+prog_yoff,
  557.         (prog_areax=prog_xoff+pwindow->Width-prog_xextra-31),
  558.         prog_yoff+(font->tf_YSize*4)+prog_yextra+5);
  559.  
  560.     for (a=0;a<2;a++) {
  561.         prog_barx[a]=(((pwindow->Width-356)/2)+28)-font->tf_XSize;
  562.         prog_bary[a]=font->tf_YSize+3+prog_yoff;
  563.         if (a==0) prog_bary[a]+=prog_yextra+3;
  564.  
  565.         Do3DBox(prp,
  566.             prog_barx[a],prog_bary[a],
  567.             300,font->tf_YSize,
  568.             screen_pens[config->gadgetbotcol].pen,
  569.             screen_pens[config->gadgettopcol].pen);
  570.         SetBPen(prp,screen_pens[0].pen);
  571.  
  572.         prog_texty[a]=prog_bary[a]+font->tf_YSize+(font->tf_YSize/2)+font->tf_Baseline;
  573.         if (a==0) progresstext(prog_texty[a],value,total,NULL);
  574.         SetAPen(prp,screen_pens[1].pen);
  575.         Move(prp,prog_barx[a]-(TextLength(prp,"0% ",3))-4,prog_bary[a]+font->tf_Baseline);
  576.         Text(prp,"0%",2);
  577.         Move(prp,prog_barx[a]+302+font->tf_XSize,prog_bary[a]+font->tf_Baseline);
  578.         Text(prp,"100%",4);
  579.         progressbar(prog_barx[a],prog_bary[a],value,total);
  580.         if (!flag) break;
  581.     }
  582. }
  583.  
  584. void progresstext(y,val,total,text)
  585. int y,val,total;
  586. char *text;
  587. {
  588.     char buf[40],*ptr;
  589.     int x,y1,len;
  590.  
  591.     if (val==-1) {
  592.         if (total) ptr=globstring[STR_ABORTED];
  593.         else ptr=globstring[STR_COMPLETED];
  594.     }
  595.     else {
  596.         if (text) ptr=text;
  597.         else {
  598.             lsprintf(buf,globstring[STR_REMAINING],val,total);
  599.             ptr=buf;
  600.         }
  601.     }
  602.     x=27+((pwindow->Width-prog_xextra-56-TextLength(prp,ptr,(len=strlen(ptr))))/2)+prog_xoff;
  603.     y1=y-prp->Font->tf_Baseline;
  604.  
  605.     if (x>prog_xoff+32) {
  606.         SetAPen(prp,screen_pens[0].pen);
  607.         RectFill(prp,
  608.             prog_xoff+32,
  609.             y1,
  610.             x-1,
  611.             y1+prp->Font->tf_YSize);
  612.     }
  613.  
  614.     SetAPen(prp,screen_pens[1].pen);
  615.     Move(prp,x,y);
  616.     Text(prp,ptr,len);
  617.  
  618.     if (prp->cp_x<=prog_areax) {
  619.         SetAPen(prp,screen_pens[0].pen);
  620.         RectFill(prp,
  621.             prp->cp_x,
  622.             y1,
  623.             prog_areax,
  624.             y1+prp->Font->tf_YSize);
  625.     }
  626. }
  627.  
  628. void progressbar(x,y,val,total)
  629. int x,y,val,total;
  630. {
  631.     int w;
  632.     float f;
  633.  
  634.     f=(float)val/(float)total;
  635.     if (f>0) {
  636.         if ((w=(int)(300*f))>300) w=300;
  637.         else if (w<1) w=1;
  638.         SetAPen(prp,screen_pens[3].pen);
  639.     }
  640.     else {
  641.         w=300;
  642.         SetAPen(prp,screen_pens[0].pen);
  643.     }
  644.     RectFill(prp,x,y,x+w-1,y+prp->Font->tf_YSize-1);
  645. }
  646.  
  647. struct InputEvent *__saveds __asm keyhandler(register __a0 struct InputEvent *oldevent,register __a1 APTR userdata)
  648. {
  649.     int wakeup=0;
  650.     struct dopushotkey *hotkey;
  651.  
  652.     if (oldevent->ie_Class==IECLASS_RAWKEY) {
  653.         if ((config->hotkeycode==~0 || oldevent->ie_Code==config->hotkeycode) &&
  654.             (!config->hotkeyqual || (oldevent->ie_Qualifier&VALID_QUALIFIERS)==config->hotkeyqual))
  655.             wakeup=1;
  656.         else {
  657.             hotkey=dopus_firsthotkey;
  658.             while (hotkey) {
  659.                 if (oldevent->ie_Code==hotkey->code &&
  660.                     (oldevent->ie_Qualifier&VALID_QUALIFIERS)==hotkey->qualifier) {
  661.                     dopus_globalhotkey=hotkey;
  662.                     Signal(hotkey_task,INPUTSIG_HOTKEY);
  663.                     oldevent->ie_Class=IECLASS_NULL;
  664.                     break;
  665.                 }
  666.                 hotkey=hotkey->next;
  667.             }
  668.         }
  669.     }
  670.     else if (oldevent->ie_Class==IECLASS_RAWMOUSE) {
  671.         if ((oldevent->ie_Code&~IECODE_UP_PREFIX)==IECODE_LBUTTON) {
  672.             if (oldevent->ie_Qualifier&IEQUALIFIER_RBUTTON) wakeup=2;
  673.         }
  674.         else if (oldevent->ie_Code==IECODE_RBUTTON &&
  675.             oldevent->ie_Qualifier&IEQUALIFIER_LEFTBUTTON) wakeup=2;
  676.         else if (config->hotkeyflags&HOTKEY_USEMMB &&
  677.             oldevent->ie_Code==IECODE_MBUTTON) wakeup=1;
  678.     }
  679.     if (wakeup) {
  680.         if (wakeup==1 && hotkey_task) {
  681.             Signal(hotkey_task,INPUTSIG_UNICONIFY);
  682.             oldevent->ie_Class=IECLASS_NULL;
  683.         }
  684.         else if (wakeup==2) {
  685.             if (IntuitionBase->ActiveWindow==Window) {
  686.                 status_haveaborted=status_rexxabort=1;
  687.                 Signal((struct Task *)main_proc,INPUTSIG_ABORT);
  688.             }
  689.         }
  690.     }
  691.     return(oldevent);
  692. }
  693.  
  694. void __saveds clocktask()
  695. {
  696.     int chipc,fast,wmes,h,m,s,secs,micro,cx,sig,cy,len,ct,chipnum,fastnum,a,active=1;
  697.     USHORT clock_width,clock_height,scr_height;
  698.     char buf[160],date[20],time[20],formstring[160],memstring[160],ampm;
  699.     struct MsgPort *clock_time_port;
  700.     struct timerequest ctimereq;
  701.     struct DOpusDateTime datetime;
  702.     struct dopustaskmsg *cmsg;
  703.     struct RastPort clock_rp;
  704.  
  705.     clockmsg_port=LCreatePort(NULL,0);
  706.     Forbid();
  707.     CopyMem((char *)main_rp,(char *)&clock_rp,sizeof(struct RastPort));
  708.     SetDrawModes(&clock_rp,config->clockfg,config->clockbg,JAM2);
  709.     SetFont(&clock_rp,scr_font[FONT_CLOCK]);
  710.     scr_height=scrdata_height+scrdata_yoffset;
  711.     clock_width=scrdata_clock_width;
  712.     clock_height=scrdata_clock_height;
  713.     Permit();
  714.  
  715.     clock_time_port=LCreatePort(0,0);
  716.     OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)&ctimereq,0);
  717.     ctimereq.tr_node.io_Message.mn_ReplyPort=clock_time_port;
  718.     ctimereq.tr_node.io_Command=TR_ADDREQUEST;
  719.     ctimereq.tr_node.io_Flags=0;
  720.     ctimereq.tr_time.tv_secs=0;
  721.     ctimereq.tr_time.tv_micro=2;
  722.     SendIO((struct IORequest *)&ctimereq.tr_node);
  723.     sig=1<<clock_time_port->mp_SigBit|1<<clockmsg_port->mp_SigBit;
  724.     cy=scrdata_clock_ypos+scr_font[FONT_CLOCK]->tf_Baseline-1;
  725.     ct=scr_height-(clock_height-1);
  726.     chipnum=getmaxmem(MEMF_CHIP,MEMF_ANY);
  727.     fastnum=getmaxmem(MEMF_ANY,MEMF_CHIP);
  728.     a=getmaxmem(MEMF_ANY,MEMF_ANY);
  729.     if (fastnum>1) {
  730.         if (config->scrclktype&SCRCLOCK_C_AND_F) {
  731.             lsprintf(memstring,"%lc:%%-%ldld%s %lc:%%-%ldld%s %lc:%%-%ldld%lc",
  732.                 globstring[STR_CLOCK_CHIP][0],
  733.                 chipnum+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?" ":"K ",
  734.                 globstring[STR_CLOCK_FAST][0],
  735.                 fastnum+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?" ":"K ",
  736.                 globstring[STR_CLOCK_TOTAL][0],
  737.                 a+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?0:'K');
  738.         }
  739.         else {
  740.             lsprintf(memstring,"%s%%-%ldld%s %s%%-%ldld%s %s%%-%ldld%lc",
  741.                 globstring[STR_CLOCK_CHIP],
  742.                 chipnum+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?" ":"K ",
  743.                 globstring[STR_CLOCK_FAST],
  744.                 fastnum+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?" ":"K ",
  745.                 globstring[STR_CLOCK_TOTAL],
  746.                 a+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?0:'K');
  747.         }
  748.     }
  749.     else {
  750.         if (config->scrclktype&SCRCLOCK_C_AND_F) {
  751.             lsprintf(memstring,"%lc:%%-%ldld%lc",
  752.                 globstring[STR_CLOCK_MEMORY][0],
  753.                 chipnum+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?0:'K');
  754.         }
  755.         else {
  756.             lsprintf(memstring,"%s%%-%ldld%lc",
  757.                 globstring[STR_CLOCK_MEMORY],
  758.                 chipnum+(config->scrclktype&SCRCLOCK_BYTES)?3:0,(config->scrclktype&SCRCLOCK_BYTES)?0:'K');
  759.         }
  760.     }
  761.  
  762.     FOREVER {
  763.         wmes=Wait(sig);
  764.         if (wmes&1<<clockmsg_port->mp_SigBit) {
  765.             while (cmsg=(struct dopustaskmsg *)GetMsg(clockmsg_port)) {
  766.                 switch (cmsg->command) {
  767.                     case TASK_QUIT:
  768.                         if (!(CheckIO((struct IORequest *)&ctimereq.tr_node)))
  769.                             AbortIO((struct IORequest *)&ctimereq.tr_node);
  770.                         WaitIO((struct IORequest *)&ctimereq.tr_node);
  771.                         CloseDevice((struct IORequest *)&ctimereq);
  772.                         LDeletePort(clock_time_port);
  773.                         LDeletePort(clockmsg_port); clockmsg_port=NULL;
  774.                         ReplyMsg((struct Message *)cmsg);
  775.                         Wait(0);
  776.                     case CLOCK_ACTIVE:
  777.                         active=cmsg->value;
  778.                         break;
  779.                 }
  780.                 ReplyMsg((struct Message *)cmsg);
  781.             }
  782.         }
  783.         if (CheckIO((struct IORequest *)&ctimereq.tr_node)) {
  784.             WaitIO((struct IORequest *)&ctimereq.tr_node);
  785.             if (active && !(Window->Flags&WFLG_MENUSTATE)) {
  786.                 chipc=AvailMem(MEMF_CHIP);
  787.                 fast=AvailMem(MEMF_ANY)-chipc;
  788.                 if (!(config->scrclktype&SCRCLOCK_BYTES)) chipc/=1024;
  789.                 if (!(config->scrclktype&SCRCLOCK_BYTES)) fast/=1024;
  790.  
  791.                 CurrentTime((ULONG *)&secs,(ULONG *)µ);
  792.                 datetime.dat_Stamp.ds_Days=secs/86400; secs-=(datetime.dat_Stamp.ds_Days*86400);
  793.                 datetime.dat_Stamp.ds_Minute=secs/60; secs-=(datetime.dat_Stamp.ds_Minute*60);
  794.                 datetime.dat_Stamp.ds_Tick=secs*50;
  795.                 initdatetime(&datetime,date,time,0);
  796.  
  797.                 if (config->dateformat&DATE_12HOUR) {
  798.                     h=datetime.dat_Stamp.ds_Minute/60; m=datetime.dat_Stamp.ds_Minute%60;
  799.                     s=datetime.dat_Stamp.ds_Tick/TICKS_PER_SECOND;
  800.                     if (h>11) { ampm='P'; h-=12; }
  801.                     else ampm='A';
  802.                     if (h==0) h=12;
  803.                     lsprintf(time,"%2ld:%02ld:%02ld%lc",h,m,s,ampm);
  804.                 }
  805.  
  806.                 if (!(config->scrclktype&(SCRCLOCK_MEMORY|SCRCLOCK_CPU|SCRCLOCK_DATE|SCRCLOCK_TIME)))
  807.                     lsprintf(formstring,"Directory Opus  Version %s  Compiled %s  %s",
  808.                         str_version_string,comp_time,comp_date);
  809.                 else {
  810.                     formstring[0]=0;
  811.                     if (config->scrclktype&SCRCLOCK_MEMORY) {
  812.                         if (fastnum>1) lsprintf(buf,memstring,chipc,fast,chipc+fast);
  813.                         else lsprintf(buf,memstring,chipc);
  814.                         strcat(formstring,buf); strcat(formstring,"  ");
  815.                     }
  816.                     if (config->scrclktype&SCRCLOCK_CPU) {
  817.                         lsprintf(buf,"CPU:%3ld%%  ",(getusage()/10));
  818.                         strcat(formstring,buf);
  819.                     }
  820.                     if (config->scrclktype&SCRCLOCK_DATE) {
  821.                         lsprintf(buf,"%-9s  ",date);
  822.                         strcat(formstring,buf);
  823.                     }
  824.                     if (config->scrclktype&SCRCLOCK_TIME) strcat(formstring,time);
  825.                 }
  826.                 len=strlen(formstring);
  827.                 if (len>1 && formstring[len-2]==' ') len-=2;
  828.                 cx=(clock_width-dotextlength(&clock_rp,formstring,&len,clock_width-4))/2;
  829.                 cx+=scrdata_clock_xpos;
  830.                 if (cx<scrdata_clock_xpos) cx=scrdata_clock_xpos;
  831.                 Move(&clock_rp,cx,cy); Text(&clock_rp,formstring,len);
  832.                 SetAPen(&clock_rp,screen_pens[config->clockbg].pen);
  833.                 if (scr_height>ct+1) {
  834.                     if (cx>scrdata_clock_xpos) RectFill(&clock_rp,scrdata_clock_xpos,ct,cx-1,scr_height-2);
  835.                     if (clock_rp.cp_x<clock_width-1)
  836.                         RectFill(&clock_rp,clock_rp.cp_x,ct,clock_width-2,scr_height-2);
  837.                 }
  838.                 SetAPen(&clock_rp,screen_pens[config->clockfg].pen);
  839.             }
  840.             ctimereq.tr_time.tv_secs=1;
  841.             ctimereq.tr_time.tv_micro=0;
  842.             SendIO((struct IORequest *)&ctimereq.tr_node);
  843.         }
  844.     }
  845. }
  846.