home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / commodities / mouseaccell / mouseaccelerator.c < prev    next >
C/C++ Source or Header  |  1991-10-07  |  38KB  |  1,183 lines

  1. /*
  2.  *  MouseAccelerator.c
  3.  *
  4.  *  Commodity
  5.  *
  6.  *  Author: Stefan Sticht
  7.  *
  8.  *  Copyright: source is public domain, no copyright
  9.  *
  10.  *  Version history:
  11.  *
  12.  *  V1.00   initial release
  13.  *  V1.01   two small changes in messages (thanks to Holger Gzella)
  14.  *  V1.02   recompiled with changed (for 68040 compatiblity) cback.o
  15.  *  V1.03   small changes; set MAX_THRESH to 20;
  16.  *          setting acceleration = 1 now disables the mousefilter
  17.  *  V1.04   removed enforcer hit under low mem in createallgadgets()
  18.  *          now window opens on the front screen, if it is a public screen, else on
  19.  *          the default public screen
  20.  *  V1.05 14 Sep 1991 Stefan Sticht changed request() to open on the same screen
  21.  *                                  as the window; replaced strlen() with sizeof();
  22.  *                                  other optimizations
  23.  *  V1.06 16 Sep 1991 Stefan Sticht removed error in lockfrontpubscr()
  24.  *  V1.07 Mon 07-Oct-91 Stefan Sticht removed obsolete code: replying IDCMP messages before CloseWindow()
  25.  */
  26.  
  27. #define VERSION "V1.07"
  28.  
  29. /********************************************************************
  30.  *                             interfacing                          *
  31.  ********************************************************************/
  32.  
  33. /*
  34.  *  include files
  35.  */
  36.  
  37. #include <math.h>
  38. #include <stdarg.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <devices/inputevent.h>
  42. #include <intuition/intuitionbase.h>
  43. #include <libraries/commodities.h>
  44.  
  45. #include <clib/alib_protos.h>
  46. #include <clib/commodities_protos.h>
  47. #include <pragmas/commodities_pragmas.h>
  48. #include <clib/dos_protos.h>
  49. #include <pragmas/dos_pragmas.h>
  50. #include <clib/exec_protos.h>
  51. #include <pragmas/exec_pragmas.h>
  52. #include <clib/gadtools_protos.h>
  53. #include <pragmas/gadtools_pragmas.h>
  54. #include <clib/graphics_protos.h>
  55. #include <pragmas/graphics_pragmas.h>
  56. #include <clib/intuition_protos.h>
  57. #include <pragmas/intuition_pragmas.h>
  58. #include <clib/utility_protos.h>
  59. #include <pragmas/utility_pragmas.h>
  60.  
  61. #ifdef DEBUG
  62. #define printf KPrintF
  63. #include <clib/dlib_protos.h>
  64. #endif
  65.  
  66. /*
  67.  *  prototypes
  68.  */
  69. long openwindow(void);
  70. struct Gadget *createallgadgets(struct Gadget **glist, APTR vi, struct Screen *scr, ULONG *height, ULONG *width);
  71. struct Library *myopenlibrary(char *name, unsigned long version);
  72. struct Screen *lockfrontpubscr(void);
  73. void __saveds accelerator(CxMsg *cxm);
  74. void closewindow(void);
  75. void processmessages(short window);
  76.  
  77. /*
  78.  *  global data defined in other moduls
  79.  *
  80.  *  libraries opened by startup code; basepointers needed by function pragmas
  81.  */
  82. extern struct Library *DOSBase;
  83. extern struct Library *SysBase;
  84.  
  85. /*
  86.  *  Disable SAS/C CTRL/C handling
  87.  */
  88. void chkabort(void) {}
  89.  
  90. /********************************************************************
  91.  *                             global data                          *
  92.  ********************************************************************/
  93.  
  94. /*
  95.  *  definition of all messages (multi language support not completed yet)
  96.  */
  97. #if defined(GERMAN)
  98.  
  99. #define RETRY_GADGETS           "Wiederholen|Abbrechen"
  100. #define RESUME_GADGETS          "Weiter"
  101. #define MSG_LIBRARY_OPENERR     "Die %s (V%ld+) kann nicht geöffnet werden!"
  102. #define MSG_WINDOW_OPENERR          "Leider kann das Fenster nicht geöffnet werden!"
  103. #define COM_NAME                "Mausbeschleuniger"
  104. #define COM_DESCR               "Beschleunigt Mausbewegungen"
  105. #define MSG_ACC                 "Beschleunigungsfaktor: %-lu  "
  106. #define MSG_ACC_SCC             'F'
  107. #define MSG_THRESH              "Beschleunigungsminimum: %-lu  "
  108. #define MSG_THRESH_SCC          'M'
  109. #define MSG_HIDE                "_Verstecken"
  110. #define MSG_HIDE_SCC            'V'
  111. #define MSG_QUIT                "_Beenden"
  112. #define MSG_QUIT_SCC            'B'
  113. #define YES                     "JA"
  114. #define NO                      "NEIN"
  115. #define TT_ACC                  "FAKTOR"
  116. #define TT_THRESH               "MINIMUM"
  117.  
  118. #else
  119.  
  120. #define RETRY_GADGETS           "Retry|Cancel"
  121. #define RESUME_GADGETS          "Resume"
  122. #define MSG_LIBRARY_OPENERR     "%s (V%ld+) can't be opened!"
  123. #define MSG_WINDOW_OPENERR      "Window can't be opened!"
  124. #define COM_NAME                "MouseAccelerator"
  125. #define COM_DESCR               "Accelerates mouse movements"
  126. #define MSG_ACC                 "Acceleration: %-lu  "
  127. #define MSG_ACC_SCC             'A'
  128. #define MSG_THRESH              "Threshold: %-lu  "
  129. #define MSG_THRESH_SCC          'T'
  130. #define MSG_HIDE                "_Hide"
  131. #define MSG_HIDE_SCC            'H'
  132. #define MSG_QUIT                "_Quit"
  133. #define MSG_QUIT_SCC            'Q'
  134. #define YES                     "YES"
  135. #define NO                      "NO"
  136. #define TT_ACC                  "ACCELERATION"
  137. #define TT_THRESH               "THRESHOLD"
  138.  
  139. #endif
  140.  
  141. #define COM_TITLE               COM_NAME " " VERSION
  142. #define CX_PRIORITY             "CX_PRIORITY"
  143. #define DEF_CX_PRIORITY         0
  144. #define CX_POPKEY               "CX_POPKEY"
  145. #define DEF_CX_POPKEY           ""
  146. #define CX_POPUP                "CX_POPUP"
  147. #define DEF_CX_POPUP            NO
  148. #define DEF_TT_ACC              5
  149. #define DEF_TT_THRESH           4
  150.  
  151. #define MAX_ACC                 20
  152. #define MAX_THRESH              20
  153. #define MIN_ACC                 1
  154. #define MIN_THRESH              1
  155.  
  156. #define POP_KEY_ID              100
  157.  
  158. #define CCMD_NOP                0
  159. #define CCMD_HIDE               1
  160. #define CCMD_QUIT               2
  161.  
  162. #define CASE_DIFF               ('a' - 'A')
  163.  
  164. #define ON                      1l
  165. #define OFF                     0l
  166.  
  167. /*
  168.  *  data for cback.o
  169.  */
  170. long _stack = 2048l;
  171. char *_procname = COM_NAME;
  172. long _priority = 0l;
  173. long _BackGroundIO = 1;
  174. extern BPTR _Backstdout;
  175.  
  176. /*
  177.  *  library base pointers
  178.  */
  179. struct IntuitionBase *IntuitionBase;
  180. struct Library *CxBase;
  181. struct Library *IconBase;
  182. struct Library *GadToolsBase;
  183. struct Library *GfxBase;
  184. struct Library *UtilityBase;
  185.  
  186. /*
  187.  *  our task
  188.  */
  189. struct Task *mytask = NULL;
  190.  
  191. /*
  192.  *  signal we AllocSignal() in main()
  193.  */
  194. long signal = -1l;
  195.  
  196. /*
  197.  *  message ports
  198.  */
  199. struct MsgPort *idcmpport;
  200. struct MsgPort *cxport;
  201.  
  202. /*
  203.  *  signal flags
  204.  */
  205. unsigned long cxsigflag = 0l;
  206. unsigned long idcmpsigflag = 0l;
  207.  
  208. /*
  209.  *  programtitle and version for Version command
  210.  */
  211. char versionstring[] ="\0$VER: " COM_NAME " " VERSION;
  212.  
  213. /*
  214.  *  helpstring
  215.  */
  216. #if defined(GERMAN)
  217. char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) von Stefan Sticht\n"\
  218.                     "Aufruf: " COM_NAME " [" CX_PRIORITY "=<Zahl>] [" CX_POPKEY "=<Zeichenkette>] ["
  219.                     CX_POPUP "=" YES "|" NO "] [" TT_ACC "=<Zahl>] [" TT_THRESH "=<Zahl>]\n";
  220. #else
  221. char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) by Stefan Sticht\n"
  222.                     "Usage: " COM_NAME " [" CX_PRIORITY "=<number>] [" CX_POPKEY "=<string>] ["
  223.                     CX_POPUP "=" YES "|" NO "] [" TT_ACC "=<number>] [" TT_THRESH "=<number>]\n";
  224. #endif
  225.  
  226. /*
  227.  *  the tooltypearray
  228.  */
  229. char **tooltypes;
  230.  
  231. /*
  232.  *  our broker
  233.  */
  234. CxObj *broker = NULL;
  235. CxObj *mousefilter;
  236. CxObj *hotkeyfilter;
  237.  
  238. struct NewBroker newbroker = {
  239.     NB_VERSION,                         /* BYTE nb_Version               */
  240.     COM_NAME,                           /* BYTE *nb_Name                 */
  241.     COM_TITLE,                          /* BYTE *nb_Title                */
  242.     COM_DESCR,                          /* BYTE *nb_Descr                */
  243.     NBU_NOTIFY | NBU_UNIQUE,            /* SHORT nb_Unique               */
  244.     COF_SHOW_HIDE,                      /* SHORT nb_Flags                */
  245.     0,                                  /* BYTE nb_Pri                   */
  246.     NULL,                               /* struct MsgPort nb_Port        */
  247.     0                                   /* WORD nb_ReservedChannel       */
  248. };
  249.  
  250. IX mouseix = {
  251.     IX_VERSION,                         /* UBYTE ix_version     */
  252.     IECLASS_RAWMOUSE,                   /* UBYTE ix_Class       */
  253.     0,                                  /* UWORD ix_Code        */
  254.     0,                                  /* UWORD ix_CodeMask    */
  255.     IEQUALIFIER_RELATIVEMOUSE,          /* UWORD ix_Qualifier   */
  256.     IEQUALIFIER_RELATIVEMOUSE,          /* UWORD ix_Qualmask    */
  257.     0                                   /* UWORD ix_QualSame    */
  258.     };
  259.  
  260. /*
  261.  *  acceleration and threshold
  262.  */
  263. unsigned short acceleration;
  264. unsigned short threshold;
  265.  
  266. /*
  267.  *  data for our window
  268.  */
  269. struct Window *win;
  270. APTR vi;
  271. struct Gadget *gadgetlist;
  272. struct Screen *scr;
  273. char windowtitle[] = COM_TITLE;
  274.  
  275. /*
  276.  *  space for zoomed window pos & size
  277.  */
  278. WORD zoompos[4];
  279.  
  280. #define P_WA_Left       0
  281. #define P_WA_Top        1
  282. #define P_WA_Width      2
  283. #define P_WA_Height     3
  284. #define P_WA_Title      6
  285. #define P_WA_PubScreen  7
  286. #define P_WA_Gadgets    8
  287. struct TagItem mywindowtag[] = {
  288.     WA_Left,        0l,
  289.     WA_Top,         20l,
  290.     WA_Width,       400l,
  291.     WA_Height,      150l,
  292.     WA_IDCMP,       IDCMP_CLOSEWINDOW | BUTTONIDCMP | SLIDERIDCMP | IDCMP_REFRESHWINDOW |
  293.                     IDCMP_VANILLAKEY,
  294.     WA_Flags,       WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
  295.                     WFLG_ACTIVATE | WFLG_RMBTRAP,
  296.     WA_Title,       (ULONG)windowtitle,
  297.     WA_PubScreen,   0l,
  298.     WA_Gadgets,     0l,
  299.     WA_Zoom,        (ULONG)zoompos,
  300.     WA_AutoAdjust,  FALSE,
  301.     TAG_END
  302.     };
  303.  
  304. char msg_acc[]    = MSG_ACC;
  305. char msg_thresh[] = MSG_THRESH;
  306. char msg_hide[]   = MSG_HIDE;
  307. char msg_quit[]   = MSG_QUIT;
  308.  
  309. /*
  310.  *  gadget definitions
  311.  */
  312. #define DBL_INTERWIDTH  (INTERWIDTH << 1)
  313. #define DBL_INTERHEIGHT (INTERHEIGHT << 1)
  314.  
  315. #define GAD_ACC     6
  316. #define GAD_THRESH  7
  317. #define GAD_HIDE    8
  318. #define GAD_QUIT    9
  319.  
  320. struct Gadget *gad_acc;
  321. struct Gadget *gad_thresh;
  322.  
  323. /********************************************************************
  324.  *                             functions                            *
  325.  ********************************************************************/
  326.  
  327. /*
  328.  *  request(): a glue routine to EasyRequest as simple as printf plus
  329.  *             titlestring, gadgettexts
  330.  *
  331.  *  Input: char *title:         pointer to the title of the requester
  332.  *         char *gadgets:       pointer to gadgettext
  333.  *         char *text:          text displayed in requester
  334.  *
  335.  *  Result: same as EasyrequestArgs()
  336.  *
  337.  * !!! for more info see EasyRequestArgs() in Autodocs/intuition.doc !!!
  338.  */
  339. long request(char *title, char *gadgets, char *text, ...)
  340. {
  341.     /*
  342.      *  structure textreq only needed in this function, so hide it here
  343.      *  must be static, in order to be initialized only once
  344.      */
  345.     static struct EasyStruct textreq = {
  346.         sizeof (struct EasyStruct), /* ULONG es_StructSize      */
  347.         0l,                         /* ULONG es_Flags           */
  348.         NULL,                       /* UBYTE *es_Title          */
  349.         NULL,                       /* UBYTE *es_TextFormat     */
  350.         NULL,                       /* UBYTE *es_GadgetFormat   */
  351.         };
  352.     va_list ap;
  353.     long rc;
  354.  
  355.     /*
  356.      *  get start of variable arguments
  357.      */
  358.     va_start(ap, text);
  359.  
  360.     /*
  361.      *  update textreq
  362.      */
  363.     textreq.es_Title = (UBYTE *)title;
  364.     textreq.es_TextFormat = (UBYTE *)text;
  365.     textreq.es_GadgetFormat = (UBYTE *)gadgets;
  366.  
  367.     /*
  368.      *  win may be NULL
  369.      */
  370.     rc = EasyRequestArgs(win, &textreq, NULL, ap);
  371.  
  372.     va_end(ap);
  373.  
  374.     return(rc);
  375. }
  376.  
  377. /*
  378.  *  myopenlibrary(): same as OpenLibrary(), but opens a retry-requester
  379.  *                   if OpenLibrary() fails, to give the user a chance to
  380.  *                   copy the library to libs: and retry
  381.  *                   requires request(), see above
  382.  */
  383. struct Library *myopenlibrary(char *name, unsigned long version)
  384. {
  385.     static char errortext[] = MSG_LIBRARY_OPENERR;
  386.     struct Library *libptr;
  387.     long ok = TRUE;
  388.  
  389.     do {
  390.         if (!(libptr = OpenLibrary((UBYTE *)name, version))) {
  391.             if (IntuitionBase) {
  392.                 ok = request(COM_NAME ":", RETRY_GADGETS, errortext, name, version);
  393.                 }
  394.             else ok = FALSE;
  395.             }
  396.         } while (!libptr && ok);
  397.  
  398.     return(libptr);
  399. }
  400.  
  401. void main(int argc, char *argv[])
  402. {
  403.     CxObj *customobj;
  404.     char *hotkey;
  405.     struct Message *msg;
  406.     short window = FALSE;
  407.  
  408.     if ((argc > 1) && (*argv[1] == '?')) {
  409.         /*
  410.          *  display help string
  411.          */
  412.         if (_Backstdout) {
  413.             Write(_Backstdout, helpstring, sizeof(helpstring) - 1l);
  414.             Close(_Backstdout);
  415.             }
  416.         return;
  417.         }
  418.     else if (argc && _Backstdout) Close(_Backstdout);
  419.  
  420.     if (IntuitionBase = (struct IntuitionBase *)myopenlibrary("intuition.library", 37l)) {
  421.         /*
  422.          *  parse command line or tool types
  423.          *
  424.          *  we need icon.library therefore
  425.          */
  426.         if (IconBase = myopenlibrary("icon.library", 37l)) {
  427.  
  428.             long value;
  429.  
  430.             /*
  431.              * create tooltypes array (requires icon.library open!!!)
  432.              */
  433.             tooltypes = (char **)ArgArrayInit(argc, argv);
  434.  
  435.             newbroker.nb_Pri = ArgInt(tooltypes, CX_PRIORITY, DEF_CX_PRIORITY);
  436.  
  437.             /*
  438.              *  acceleration
  439.              */
  440.             value = ArgInt(tooltypes, TT_ACC, DEF_TT_ACC);
  441.             if (value < MIN_ACC) acceleration = MIN_ACC;
  442.             else if (value > MAX_ACC) acceleration = MAX_ACC;
  443.             else acceleration = value;
  444.             /*
  445.              *  acceleration
  446.              */
  447.             value = ArgInt(tooltypes, TT_THRESH, DEF_TT_THRESH);
  448.             if (value < MIN_THRESH) threshold = MIN_THRESH;
  449.             else if (value > MAX_THRESH) threshold = MAX_THRESH;
  450.             else threshold = value;
  451.  
  452.             /*
  453.              *  check for a hotkey
  454.              */
  455.             hotkey = ArgString(tooltypes, CX_POPKEY, DEF_CX_POPKEY);
  456.  
  457.             if (UtilityBase = myopenlibrary("utility.library", 37l)) {
  458.  
  459.                 if (Stricmp(ArgString(tooltypes, CX_POPUP, DEF_CX_POPUP), YES) == 0l)
  460.                     window = TRUE;
  461.  
  462.                 CloseLibrary(UtilityBase);
  463.  
  464.                 } /* if UtilityBase */
  465.  
  466.             if (CxBase = myopenlibrary("commodities.library", 37l)) {
  467.  
  468.                 if (GfxBase = myopenlibrary("graphics.library", 37l)) {
  469.  
  470.                     if (GadToolsBase = myopenlibrary("gadtools.library", 37l)) {
  471.                         /*
  472.                          *  create our message port
  473.                          */
  474.                         if (cxport = CreateMsgPort()) {
  475.  
  476.                             cxsigflag = 1l << cxport->mp_SigBit;
  477.                             newbroker.nb_Port = cxport;
  478.  
  479.                             if (broker = CxBroker(&newbroker, NULL)) {
  480.  
  481.                                 if (mousefilter = CxFilter(NULL)) {
  482.  
  483.                                     AttachCxObj(broker, mousefilter);
  484.  
  485.                                     SetFilterIX(mousefilter, &mouseix);
  486.  
  487.                                     if (customobj = CxCustom(accelerator, 0l)) {
  488.  
  489.                                         AttachCxObj(mousefilter, customobj);
  490.  
  491.                                         if (*hotkey && (hotkeyfilter = HotKey(hotkey, cxport, POP_KEY_ID))) {
  492.                                             AttachCxObj(broker, hotkeyfilter);
  493.                                             }
  494.  
  495.                                         if (!CxObjError(mousefilter) &&
  496.                                             !CxObjError(broker) &&
  497.                                             !(hotkeyfilter && CxObjError(hotkeyfilter))) {
  498.                                             /*
  499.                                              *  if acceleration == 1 we don't need to get events
  500.                                              */
  501.                                             if (acceleration == MIN_ACC) ActivateCxObj(mousefilter, OFF);
  502.                                             #ifdef DEBUG
  503.                                             printf("main(): no acceleration, deactivate mousefilter\n");
  504.                                             #endif
  505.                                             /*
  506.                                              *  activate our commodity
  507.                                              */
  508.                                             ActivateCxObj(broker, ON);
  509.                                             /*
  510.                                              *  now watch our numerous ports
  511.                                              */
  512.                                             processmessages(window);
  513.  
  514.                                             } /* if !CxObjError() */
  515.  
  516.                                         } /* if customobj */
  517.  
  518.                                     } /* if mousefilter */
  519.  
  520.                                 DeleteCxObjAll(broker);
  521.  
  522.                                 } /* if broker */
  523.  
  524.                             #ifdef DEBUG
  525.                             else printf("main(): CxBroker() failed!\n");
  526.                             #endif
  527.  
  528.                             /*
  529.                              *  delete our message port after replying all pending messages
  530.                              */
  531.                             while (msg = GetMsg(cxport)) ReplyMsg(msg);
  532.                             DeleteMsgPort(cxport);
  533.                             } /* if cxport */
  534.  
  535.                         #ifdef DEBUG
  536.                         else printf("main(): CraeteMsgPort() failed!\n");
  537.                         #endif
  538.  
  539.                         CloseLibrary(GadToolsBase);
  540.                         } /* if GadToolsBase */
  541.  
  542.                     CloseLibrary(GfxBase);
  543.                     } /* if GfxBase */
  544.  
  545.                 CloseLibrary(CxBase);
  546.                 } /* if CxBase */
  547.  
  548.             /*
  549.              *  free memory allocated by ArgArrayInit()
  550.              */
  551.             ArgArrayDone();
  552.  
  553.             CloseLibrary(IconBase);
  554.             } /* if IconBase */
  555.  
  556.         CloseLibrary((struct Library *)IntuitionBase);
  557.         } /* if IntuitionBase */
  558.  
  559. } /* main() */
  560.  
  561. void processmessages(short window)
  562. {
  563.     struct Message *msg;
  564.     unsigned long sigreceived;
  565.     unsigned long msgtype;
  566.     unsigned long msgid;
  567.     unsigned short quit = FALSE;
  568.     unsigned char command = CCMD_NOP;
  569.  
  570.     if (window) {
  571.         if (!openwindow()) request(COM_NAME ":", RESUME_GADGETS, MSG_WINDOW_OPENERR);
  572.         }
  573.  
  574.     while (!quit) {
  575.  
  576.         sigreceived = Wait(SIGBREAKF_CTRL_C | cxsigflag | idcmpsigflag);
  577.  
  578.         #ifdef DEBUG
  579.         printf("processmessages(): signal received\n");
  580.         #endif
  581.  
  582.         if (sigreceived & SIGBREAKF_CTRL_C) quit = TRUE;
  583.  
  584.         if (sigreceived & cxsigflag) {
  585.  
  586.             #ifdef DEBUG
  587.             printf("processmessages(): message at cxport\n");
  588.             #endif
  589.  
  590.             while (msg = (struct Message *)GetMsg(cxport)) {
  591.  
  592.                 msgid = CxMsgID((CxMsg *)msg);
  593.                 msgtype = CxMsgType((CxMsg *)msg);
  594.  
  595.                 ReplyMsg(msg);
  596.  
  597.                 switch (msgtype) {
  598.  
  599.                     case CXM_IEVENT:
  600.                         if (msgid == POP_KEY_ID) {
  601.                             if (!openwindow()) request(COM_NAME ":", RESUME_GADGETS, MSG_WINDOW_OPENERR);
  602.                             }
  603.                         break;
  604.  
  605.                     case CXM_COMMAND:
  606.                         switch (msgid) {
  607.  
  608.                             case CXCMD_KILL:
  609.                                 quit = TRUE;
  610.  
  611.                             case CXCMD_DISABLE:
  612.                                 ActivateCxObj(broker, OFF);
  613.                                 #ifdef DEBUG
  614.                                 printf("processmessages(): broker disabled\n");
  615.                                 #endif
  616.                                 break;
  617.  
  618.                             case CXCMD_ENABLE:
  619.                                 ActivateCxObj(broker, ON);
  620.                                 #ifdef DEBUG
  621.                                 printf("processmessages(): broker enabled\n");
  622.                                 #endif
  623.                                 break;
  624.  
  625.                             case CXCMD_UNIQUE:
  626.                             case CXCMD_APPEAR:
  627.                                 if (!openwindow()) request(COM_NAME ":", RESUME_GADGETS, MSG_WINDOW_OPENERR);
  628.                                 break;
  629.  
  630.                             case CXCMD_DISAPPEAR:
  631.                                 closewindow();
  632.                                 break;
  633.  
  634.                             }
  635.                         break;
  636.  
  637.                     } /* switch msgtype */
  638.  
  639.                 } /* while CxMsg */
  640.  
  641.             } /* if (sigreceived & cxsigflag) */
  642.  
  643.         if (sigreceived & idcmpsigflag) {
  644.  
  645.             APTR *object;
  646.             ULONG class;
  647.             UWORD code;
  648.  
  649.             #ifdef DEBUG
  650.             printf("processmessages(): message at idcmpport\n");
  651.             #endif
  652.  
  653.             while (idcmpport && (msg = (struct Message *)GT_GetIMsg(idcmpport))) {
  654.                 /*
  655.                  *  handle IDCMP messages
  656.                  */
  657.                 class    = ((struct IntuiMessage *)msg)->Class;
  658.                 code     = ((struct IntuiMessage *)msg)->Code;
  659.                 object   = ((struct IntuiMessage *)msg)->IAddress;
  660.                 GT_ReplyIMsg((struct IntuiMessage *)msg);
  661.  
  662.                 switch (class) {
  663.  
  664.                     case CLOSEWINDOW:
  665.                         command = CCMD_HIDE;
  666.                         break;
  667.  
  668.                     case REFRESHWINDOW:
  669.                         GT_BeginRefresh(win);
  670.                         GT_EndRefresh(win, TRUE);
  671.                         break;
  672.  
  673.                     case GADGETUP:
  674.                         if (object) command = (unsigned char)((struct Gadget *)object)->UserData;
  675.                         break;
  676.  
  677.                     case MOUSEMOVE:
  678.                         if (object) {
  679.                             switch(((struct Gadget *)object)->GadgetID & GADTOOLMASK) {
  680.  
  681.                                 case GAD_ACC:
  682.                                     if (code > MIN_ACC) {
  683.                                         if (acceleration == MIN_ACC) {
  684.                                             #ifdef DEBUG
  685.                                             printf("processmessages(): acceleration, activate mousefilter\n");
  686.                                             #endif
  687.                                             ActivateCxObj(mousefilter, ON);
  688.                                             }
  689.                                         }
  690.                                     else {
  691.                                         #ifdef DEBUG
  692.                                         printf("processmessages(): no acceleration, deactivate mousefilter\n");
  693.                                         #endif
  694.                                         ActivateCxObj(mousefilter, OFF);
  695.                                         }
  696.                                     acceleration = code;
  697.                                     break;
  698.  
  699.                                 case GAD_THRESH:
  700.                                     threshold = code;
  701.                                     break;
  702.  
  703.                                 }
  704.                             }
  705.                         break;
  706.  
  707.                     case VANILLAKEY:
  708.                         switch (code) {
  709.  
  710.                             case 27:
  711.                             case MSG_HIDE_SCC:
  712.                             case MSG_HIDE_SCC + CASE_DIFF:
  713.                                         command = CCMD_HIDE;
  714.                                         break;
  715.  
  716.                             case MSG_QUIT_SCC:
  717.                             case MSG_QUIT_SCC + CASE_DIFF:
  718.                                         command = CCMD_QUIT;
  719.                                         break;
  720. /* doesn't work yet
  721.                             case MSG_ACC_SCC:
  722.                                         if (acceleration > MIN_ACC) {
  723.                                             acceleration--;
  724.                                             GT_SetGadgetAttrs(gad_acc, win, NULL, GTSL_Level, acceleration, TAG_DONE);
  725.                                             if (acceleration == MIN_ACC) {
  726.                                                 #ifdef DEBUG
  727.                                                 printf("processmessages(): no acceleration, deactivate mousefilter\n");
  728.                                                 #endif
  729.                                                 ActivateCxObj(mousefilter, OFF);
  730.                                                 }
  731.                                             }
  732.                                         break;
  733.  
  734.                             case MSG_ACC_SCC + CASE_DIFF:
  735.                                         if (acceleration < MAX_ACC) {
  736.                                             if (acceleration == MIN_ACC) {
  737.                                                 #ifdef DEBUG
  738.                                                 printf("processmessages(): acceleration, activate mousefilter\n");
  739.                                                 #endif
  740.                                                 ActivateCxObj(mousefilter, ON);
  741.                                                 }
  742.                                             acceleration++;
  743.                                             GT_SetGadgetAttrs(gad_acc, win, NULL, GTSL_Level, acceleration, TAG_DONE);
  744.                                             }
  745.                                         break;
  746.  
  747.                             case MSG_THRESH_SCC:
  748.                                         if (threshold > MIN_THRESH) {
  749.                                             threshold--;
  750.                                             GT_SetGadgetAttrs(gad_thresh, win, NULL, GTSL_Level, threshold, TAG_DONE);
  751.                                             }
  752.                                         break;
  753.  
  754.                             case MSG_THRESH_SCC + CASE_DIFF:
  755.                                         if (threshold < MAX_THRESH) {
  756.                                             threshold++;
  757.                                             GT_SetGadgetAttrs(gad_thresh, win, NULL, GTSL_Level, threshold, TAG_DONE);
  758.                                             }
  759.                                         break;
  760. */
  761.                             }
  762.                         break;
  763.  
  764.                     } /* switch class */
  765.  
  766.                 } /* while idcmp message */
  767.  
  768.             } /* if (sigreceived & idcmpsigflag) */
  769.  
  770.         #ifdef DEBUG
  771.         printf("processmessages(): command = %ld\n", command);
  772.         #endif
  773.  
  774.         switch(command) {
  775.  
  776.             case CCMD_NOP:
  777.                 break;
  778.  
  779.             case CCMD_HIDE:
  780.                 closewindow();
  781.                 break;
  782.  
  783.             case CCMD_QUIT:
  784.                 quit = TRUE;
  785.                 break;
  786.  
  787.             } /* switch (command) */
  788.  
  789.         command = CCMD_NOP;
  790.  
  791.         } /* while !quit */
  792.  
  793.     ActivateCxObj(broker, OFF);
  794.     #ifdef DEBUG
  795.     printf("processmessages(): broker disabled\n");
  796.     #endif
  797.     closewindow();
  798. }
  799.  
  800. /*
  801.  *  commodity functions
  802.  */
  803. void __saveds accelerator(CxMsg *cxm)
  804. {
  805.     register struct InputEvent *ie;
  806.     register short n;
  807.     register short s;
  808.  
  809.     if ((ie = (struct InputEvent *)CxMsgData(cxm)) && (acceleration > 1)) {
  810.  
  811.         n = ie->ie_X;
  812.         s = 1;
  813.  
  814.         if (n < 0) {
  815.             n = -n;
  816.             s = -1;
  817.             }
  818.  
  819.         if (n > threshold)
  820.             ie->ie_X = s * (short)((n - threshold - 1) * acceleration + threshold + 1);
  821.  
  822.         n = ie->ie_Y;
  823.         s = 1;
  824.         if (n < 0) {
  825.             n = -n;
  826.             s = -1;
  827.             }
  828.  
  829.         if (n > threshold)
  830.             ie->ie_Y = s * (short)((n - threshold - 1) * acceleration + threshold + 1);
  831.  
  832.         }
  833. }
  834.  
  835.  
  836. /*
  837.  *  window functions
  838.  */
  839.  
  840. struct Screen *lockfrontpubscr(void)
  841. {
  842.     struct Screen *scr;
  843.     struct Screen *pubscr = NULL;
  844.     struct List *pslist;
  845.     struct PubScreenNode *psnode;
  846.     unsigned long lock;
  847.     unsigned short screentype;
  848.  
  849.     lock = LockIBase(0l);
  850.  
  851.     if (scr = IntuitionBase->FirstScreen) {
  852.  
  853.         screentype = scr->Flags & SCREENTYPE;
  854.  
  855.         UnlockIBase(lock);
  856.  
  857.         if (screentype == PUBLICSCREEN || screentype == WBENCHSCREEN) {
  858.  
  859.             if (pslist = LockPubScreenList()) {
  860.  
  861.                 for (psnode = (struct PubScreenNode *)pslist->lh_Head;
  862.                      psnode->psn_Node.ln_Succ && (psnode->psn_Screen != scr);
  863.                      psnode = (struct PubScreenNode *)psnode->psn_Node.ln_Succ);
  864.  
  865.                 if (psnode && (psnode->psn_Screen == scr) && !(psnode->psn_Flags & PSNF_PRIVATE)) {
  866.  
  867.                     pubscr = LockPubScreen(psnode->psn_Node.ln_Name);
  868.  
  869.                     }
  870.  
  871.                 UnlockPubScreenList();
  872.  
  873.                 }
  874.  
  875.             }
  876.  
  877.         }
  878.  
  879.     else UnlockIBase(lock);
  880.  
  881.     if (pubscr && ((pubscr->Width < 640) || (pubscr->Height < 200))) {
  882.         UnlockPubScreen(NULL, pubscr);
  883.         pubscr = NULL;
  884.         }
  885.  
  886.     /*
  887.      *  no locked screen yet, try default public screen
  888.      */
  889.     if (!pubscr) pubscr = LockPubScreen(NULL);
  890.  
  891.     return(pubscr);
  892. }
  893.  
  894. long openwindow(void)
  895. {
  896.     struct DimensionInfo di;
  897.     struct Rectangle *rect;
  898.     unsigned long vpmid;
  899.     long ok = FALSE;
  900.  
  901.     if (win) {
  902.         #ifdef DEBUG
  903.         printf("openwindow(): window already open\n");
  904.         #endif
  905.  
  906.         /*
  907.          *  dont't open window but pop it to front, unzip it
  908.          *
  909.          *  unzip window if zipped
  910.          */
  911.         if (win->Height < mywindowtag[P_WA_Height].ti_Data) ZipWindow(win);
  912.  
  913.         /*
  914.          *  window to front
  915.          */
  916.         WindowToFront(win);
  917.  
  918.         /*
  919.          *  activate window
  920.          */
  921.         if (win != IntuitionBase->ActiveWindow) ActivateWindow(win);
  922.  
  923.         /*
  924.          *  screen to front
  925.          */
  926.         if (win->WScreen != IntuitionBase->FirstScreen) ScreenToFront(win->WScreen);
  927.  
  928.         ok = TRUE;
  929.  
  930.         }
  931.  
  932.     else {
  933.         /*
  934.          *  lock the default public screen
  935.          */
  936.         if (scr = lockfrontpubscr()) {
  937.             /*
  938.              *  GetVisualInfo() for gadtools
  939.              */
  940.             if (vi = GetVisualInfo(scr, TAG_DONE)) {
  941.                 /*
  942.                  *  update some window information
  943.                  */
  944.                 mywindowtag[P_WA_Width].ti_Data = zoompos[2] =
  945.                     TextLength(&scr->RastPort, (STRPTR)windowtitle, sizeof(windowtitle) - 1l) + 100;
  946.                 mywindowtag[P_WA_Height].ti_Data = zoompos[3] =
  947.                     scr->WBorTop + scr->RastPort.TxHeight + 1;
  948.                 /*
  949.                  *  create all gadgets:
  950.                  *
  951.                  *  this function may also change the width and height of our window
  952.                  */
  953.                 if (createallgadgets(&gadgetlist, vi, scr,
  954.                                      &mywindowtag[P_WA_Height].ti_Data,
  955.                                      &mywindowtag[P_WA_Width].ti_Data)) {
  956.                     /*
  957.                      *  center the window in the visible box of the screen
  958.                      */
  959.                     if ((vpmid = GetVPModeID(&scr->ViewPort )) != INVALID_ID) {
  960.  
  961.                         GetDisplayInfoData(0, (UBYTE *)&di, sizeof(struct DimensionInfo), DTAG_DIMS, vpmid);
  962.                         rect = &di.TxtOScan;
  963.                         zoompos[0] = mywindowtag[P_WA_Left].ti_Data =
  964.                             (scr->LeftEdge < 0 ? -scr->LeftEdge : 0) +
  965.                             ((min((rect->MaxX - rect->MinX + 1), scr->Width) -
  966.                               mywindowtag[P_WA_Width].ti_Data) >> 1);
  967.                         zoompos[1] = mywindowtag[P_WA_Top].ti_Data =
  968.                             (scr->TopEdge < 0 ? -scr->TopEdge : 0) +
  969.                             ((min((rect->MaxY - rect->MinY + 1), scr->Height) -
  970.                               mywindowtag[P_WA_Height].ti_Data) >> 1);
  971.  
  972.                         }
  973.  
  974.                     #ifdef DEBUG
  975.                     else printf("openwindow(): GetVPModeID() == INVALID_ID\n");
  976.                     #endif
  977.  
  978.                     mywindowtag[P_WA_PubScreen].ti_Data = (ULONG)scr;
  979.                     mywindowtag[P_WA_Gadgets].ti_Data = (ULONG)gadgetlist;
  980.  
  981.                     if (win = OpenWindowTagList(NULL, mywindowtag)) {
  982.                         /*
  983.                          *  save IDCMP port
  984.                          */
  985.                         idcmpport = win->UserPort;
  986.                         idcmpsigflag = 1L << idcmpport->mp_SigBit;
  987.  
  988.                         GT_RefreshWindow(win, NULL);
  989.  
  990.                         /*
  991.                          *  switch screen to front
  992.                          */
  993.                         if (win->WScreen != IntuitionBase->FirstScreen) ScreenToFront(win->WScreen);
  994.  
  995.                         ok = TRUE;
  996.  
  997.                         } /* if (win = OpenWindowTagList(NULL, mywindowtag)) */
  998.  
  999.                     #ifdef DEBUG
  1000.                     else printf("openwindow(): OpenWindowTagList() failed\n");
  1001.                     #endif
  1002.  
  1003.                     } /* if (createallgadgets() */
  1004.  
  1005.                 #ifdef DEBUG
  1006.                 else printf("openwindow(): createallgadgets() failed\n");
  1007.                 #endif
  1008.  
  1009.                 } /*  if (vi = GetVisualInfo(scr, TAG_DONE)) */
  1010.  
  1011.             #ifdef DEBUG
  1012.             else printf("openwindow(): GetVisualInfo() failed\n");
  1013.             #endif
  1014.  
  1015.             } /* if (scr = LockPubScreen(NULL)) */
  1016.  
  1017.         #ifdef DEBUG
  1018.         else printf("openwindow(): could LockPubScreen(NULL)\n");
  1019.         #endif
  1020.  
  1021.         if (!ok) {
  1022.                 /*
  1023.                  *  window could not be opened - free all resources
  1024.                  */
  1025.                 closewindow();
  1026.                 }
  1027.  
  1028.         } /* if (!win) */
  1029.  
  1030.     return(ok);
  1031. }
  1032.  
  1033. void closewindow(void)
  1034. {
  1035.     if (win) {
  1036.         /*
  1037.          *  now close the window
  1038.          */
  1039.         CloseWindow(win);
  1040.         win = NULL;
  1041.         idcmpport = NULL;
  1042.         idcmpsigflag = 0l;
  1043.         }
  1044.  
  1045.     if (gadgetlist) {
  1046.         FreeGadgets(gadgetlist);
  1047.         gadgetlist = NULL;
  1048.         }
  1049.  
  1050.     if (vi) {
  1051.         FreeVisualInfo(vi);
  1052.         vi = NULL;
  1053.         }
  1054.  
  1055.     if (scr) {
  1056.         UnlockPubScreen(NULL, scr);
  1057.         scr = NULL;
  1058.         }
  1059. }
  1060.  
  1061. #define TAG_Max         1
  1062. #define TAG_Level       2
  1063. #define TAG_LevelFormat 3
  1064. #define TAG_MaxLevelLen 4
  1065. struct TagItem slidertags[] = {
  1066.     GTSL_Min, 1l,
  1067.     GTSL_Max, 0l,
  1068.     GTSL_Level, 0l,
  1069.     GTSL_LevelFormat, 0l,
  1070.     GTSL_MaxLevelLen, 0l,
  1071.     GTSL_LevelPlace, PLACETEXT_ABOVE,
  1072.     TAG_END
  1073.     };
  1074.  
  1075. struct TagItem underscoretag[] = {
  1076.     GT_Underscore, '_',
  1077.     TAG_END
  1078.     };
  1079.  
  1080. /*
  1081.  *  createallgadgets(): create all gadgets and put required width and height
  1082.  *                      of window in height and width
  1083.  */
  1084. struct Gadget *
  1085. createallgadgets(struct Gadget **glist, APTR vi, struct Screen *scr, ULONG *height, ULONG *width)
  1086. {
  1087.     static struct NewGadget ng;
  1088.     struct Gadget *gad;
  1089.     struct RastPort *rp;
  1090.     short underscorewidth;
  1091.     short borderswidth;
  1092.     short buttonwidth;
  1093.     short accwidth;
  1094.     short threshwidth;
  1095.     short dummy;
  1096.  
  1097.     /*
  1098.      *  first get RastPort of screen to determine some TextLength()
  1099.      */
  1100.     rp = &scr->RastPort;
  1101.     borderswidth = scr->WBorLeft + scr->WBorRight;
  1102.     underscorewidth = TextLength(rp, "_", 1l);
  1103.     /*
  1104.      *  calculate width
  1105.      */
  1106.     accwidth = TextLength(rp, msg_acc, sizeof(msg_acc) - 1l);
  1107.     *width = max(accwidth + DBL_INTERWIDTH + borderswidth, *width);
  1108.     threshwidth = TextLength(rp, msg_thresh, sizeof(msg_thresh) - 1l);
  1109.     *width = max(threshwidth + DBL_INTERWIDTH + borderswidth, *width);
  1110.  
  1111.     buttonwidth = TextLength(rp, (STRPTR)msg_hide, sizeof(msg_hide) - 1l);
  1112.     dummy       = TextLength(rp, (STRPTR)msg_quit, sizeof(msg_quit) - 1l);
  1113.     buttonwidth = max(buttonwidth, dummy) - underscorewidth + DBL_INTERWIDTH;
  1114.     /*
  1115.      *  check out if the window's width has to be enlarged
  1116.      */
  1117.     *width = max((buttonwidth << 1) + (DBL_INTERWIDTH + INTERWIDTH) + borderswidth, *width);
  1118.  
  1119.     /*
  1120.      *  now create the gadgets
  1121.      */
  1122.     gad = CreateContext(glist);
  1123.  
  1124.     /*
  1125.      *  Acceleration gadget:
  1126.      */
  1127.     ng.ng_TopEdge       = scr->WBorTop + (rp->TxHeight << 1) + 1 + DBL_INTERHEIGHT;
  1128.     ng.ng_Width         = *width - DBL_INTERWIDTH - borderswidth;
  1129.     ng.ng_LeftEdge      = INTERWIDTH + scr->WBorLeft;
  1130.     ng.ng_Height        = rp->TxHeight + 4;
  1131.     ng.ng_TextAttr      = scr->Font;
  1132.     ng.ng_GadgetText    = NULL;
  1133.     ng.ng_GadgetID      = GAD_ACC;
  1134.     ng.ng_VisualInfo    = vi;
  1135.     slidertags[TAG_Max].ti_Data = (ULONG)MAX_ACC;
  1136.     slidertags[TAG_Level].ti_Data = (ULONG)acceleration;
  1137.     slidertags[TAG_LevelFormat].ti_Data = (ULONG)msg_acc;
  1138.     slidertags[TAG_MaxLevelLen].ti_Data = sizeof(msg_acc) - 2l;
  1139.     gad_acc = gad = CreateGadgetA(SLIDER_KIND, gad, &ng, slidertags);
  1140.  
  1141.     /*
  1142.      *  threshold gadget
  1143.      */
  1144.     ng.ng_TopEdge      += ng.ng_Height + DBL_INTERHEIGHT + rp->TxHeight;
  1145.     ng.ng_GadgetID      = GAD_THRESH;
  1146.     slidertags[TAG_Max].ti_Data = (ULONG)MAX_THRESH;
  1147.     slidertags[TAG_Level].ti_Data = (ULONG)threshold;
  1148.     slidertags[TAG_LevelFormat].ti_Data = (ULONG)msg_thresh;
  1149.     slidertags[TAG_MaxLevelLen].ti_Data = sizeof(msg_thresh) - 2l;
  1150.     gad_thresh = gad = CreateGadgetA(SLIDER_KIND, gad, &ng, slidertags);
  1151.  
  1152.     /*
  1153.      *  dummy now gets the spacing between the button gadgets
  1154.      */
  1155.     dummy = (*width - (buttonwidth << 1) - borderswidth) / 3;
  1156.  
  1157.     /*
  1158.      *  Hide gadget
  1159.      */
  1160.     ng.ng_TopEdge      += ng.ng_Height + DBL_INTERHEIGHT;
  1161.     ng.ng_Width         = buttonwidth;
  1162.     ng.ng_LeftEdge      = dummy + scr->WBorLeft;
  1163.     ng.ng_GadgetText    = (UBYTE *)msg_hide;
  1164.     ng.ng_GadgetID      = GAD_HIDE;
  1165.     ng.ng_Flags         = 0l;
  1166.     ng.ng_UserData      = (APTR)CCMD_HIDE;
  1167.  
  1168.     gad = CreateGadgetA(BUTTON_KIND, gad, &ng, underscoretag);
  1169.  
  1170.     /*
  1171.      *  Quit gadget
  1172.      */
  1173.     ng.ng_LeftEdge     += ng.ng_Width + dummy;
  1174.     ng.ng_GadgetText    = (UBYTE *)msg_quit;
  1175.     ng.ng_GadgetID      = GAD_QUIT;
  1176.     ng.ng_UserData      = (APTR)CCMD_QUIT;
  1177.  
  1178.     gad = CreateGadgetA(BUTTON_KIND, gad, &ng, underscoretag);
  1179.  
  1180.     *height = ng.ng_TopEdge + ng.ng_Height + scr->WBorBottom + INTERHEIGHT;
  1181.  
  1182.     return(gad);
  1183. }