home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Utilities / MorseCode ƒ / MorseCode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-09  |  32.0 KB  |  1,359 lines  |  [TEXT/KAHL]

  1. /* Morse Code Program for Macintosh      */
  2. /* by James R. Logan Jr.              */
  3.  
  4. /* Part of the "send()" routine was   */
  5. /* taken from a Morse Code program    */
  6. /* writen by Keith J. McQueen (N7HMF) */
  7. /* and modified by Brian Minert.      */
  8.  
  9. #include <Quickdraw.h>
  10. #include <Windows.h>
  11. #include <Menus.h>
  12. #include <Errors.h>
  13. #include <Events.h>
  14. #include <TextEdit.h>
  15. #include <Dialogs.h>
  16. #include <Controls.h>
  17. #include <StandardFile.h>
  18. #include <sound.h>
  19. #include <stdio.h>
  20. #include <ToolUtils.h>
  21. #include <types.h>
  22.  
  23. /* Factor for converting from words per minute to the 
  24.    duration of "di" in half milliseconds.  It should be 
  25.    2400, but adjusted downward because the actual 
  26.    performance was too slow. */ 
  27.    
  28. /* Convert from the number of "di" in 1/60 of a second (a tick)
  29.    to Morse Code words per minute */
  30. #define DPHMS_TO_WPM 66    
  31.  
  32. #define AMP            120
  33.  
  34. #define REPEAT_EVENT_DELAY_TICKS 20
  35. #define REPEAT_AGAIN_DELAY_TICKS 4
  36.  
  37. #define CODE_MODES 5
  38. #define WAIT_MODES 2
  39. #define PLAY_MODES 3
  40. #define PAUSE_MODES 2
  41. #define FILE_MODES 2
  42.  
  43. #define PAUSE_STRING 0
  44. #define RESUME_STRING 1
  45.  
  46. #define OPEN_STRING 0
  47. #define CLOSE_STRING 1
  48.  
  49. #define HAND_CURSOR_ID 128
  50.  
  51. #define CODE_STR_ID 128
  52. #define WAIT_STR_ID 129
  53. #define PLAY_STR_ID 130
  54. #define PAUSE_STR_ID 131
  55. #define FILE_STR_ID 132
  56.  
  57. #define LINESIZE 8        /* Number of characters to display left of the code */
  58.                         /* This affects the code speed, higher numbers slow it down */
  59.  
  60. #define TEXTHEIGHT 20
  61. #define TEXTINDENT 0
  62. #define TEXTMARGINS 0        /* Sum of left and right margin */
  63. #define TEXTWIDTH 226
  64. #define WINDOWWIDTH 256
  65.  
  66. #define MAX_Menus    3
  67.  
  68. #define BASE_MenuID        128
  69. #define MENUBAR_ID        128
  70.  
  71. #define CODE_DIALOG   28243
  72. #define SettingsID    31324
  73.  
  74. #define CNTL_OKAY_BTN   128
  75.  
  76. #define QUEUE_SIZE   1024
  77.  
  78. #define SOUND_COMPLETE    1
  79.  
  80. enum    {
  81.         AppleN=128,            /* APPLE/DA    */
  82.         fileMenuN,            /* File */
  83.         editMenuN,            /* Edit */
  84.         lastMenuN
  85.         };
  86.  
  87. enum {                         /* File    */
  88.         mFile_Open = 1,
  89.         mSave_Settings,
  90.         mFile_Quit,
  91.         mFile_Last
  92.     };
  93.  
  94. enum {                         /* Dialog items    */
  95.         open_button = 1,
  96.         quit_button,
  97.         pause_button,
  98.         volume_up,
  99.         volume_down,
  100.         frequency_up,
  101.         frequency_down,
  102.         duration_up,
  103.         duration_down,
  104.         whichcode_up,
  105.         whichcode_down,
  106.         wait_up,
  107.         wait_down,
  108.         play_up,
  109.         play_down,
  110.         volumeitem,
  111.         freqitem,
  112.         wordsitem,
  113.         codeitem,
  114.         waititem,
  115.         playitem,
  116.         code_pattern,
  117.         code_character,
  118.         volumelabelitem,
  119.         frequencylabelitem,
  120.         wordslabelitem,
  121.         gray1item,
  122.         gray2item,
  123.         titleitem,
  124.         wpmitem,
  125.         dialog_item_last
  126.     };
  127.  
  128. short initsound(SndChannelPtr *soundptr);
  129.  
  130. Boolean            done;
  131. Boolean            has_multifinder;
  132. Boolean            key_correct;
  133. Boolean            paused;
  134. Boolean            playfile;
  135. Boolean            random;
  136. Boolean            ready;
  137. Boolean            speedfor1character;
  138. short            chasex;
  139. short            codetimecharactercount;
  140. short            codetimeunits;
  141. short            cr_windowwidth;
  142. short            duration;
  143. short            playcontinuous;
  144. short            frequency;
  145. short            gp;                /* Play file */
  146. short            queuex;
  147. short            repeat_event_item;
  148. short            waitforkey;
  149. short            whichcode;        /* All, letters, numbers, symbols */
  150. short            version;
  151. short            volume;
  152. long            codetimebegin;
  153. long            codetimeend;
  154. long            sharedTimeTicks;
  155. Point            dialogPoint;
  156. Rect            dragRect;
  157. Rect            pattern_rect;
  158. ControlHandle    OkayBtnHdl;
  159. DialogPtr        myDialog;  
  160. GrafPtr            screenPort;        /* For DragWindow() */
  161. SndChannelPtr    soundptr;
  162. MenuHandle        mymenus[MAX_Menus];
  163. WindowPtr        noticeWindow;     /* Window for copyright notice */
  164. WindowRecord     nrecord;
  165.  
  166. unsigned char display_code;
  167. unsigned char last_code;
  168.  
  169. unsigned char queue[QUEUE_SIZE];
  170.  
  171. static ResType  crstyp = 'CURS';
  172. static ResType    Setres = 'CNFG';
  173.  
  174. static unsigned char *notice[] = 
  175.   {"\pMorseCode v1.0",
  176.    "\p© 1993",
  177.    "\pJames R. Logan Jr.",
  178.    "\pE-mail: loganj@cs.byu.edu",
  179.    "\p"};    /* The code stops when it sees a null string */
  180.  
  181. char *code_line = { "                    " };
  182. unsigned char randomtable[] = {
  183.     'A','B','C','D','E','F','G','H','I','J',
  184.     'K','L','M','N','O','P','Q','R','S','T',
  185.     'U','V','W','X','Y','Z','0','1','2','3',
  186.     '4','5','6','7','8','9','"','$','\'','/',
  187.     '(',')','+',',','-','.','/',':',';','=',
  188.     '?'};
  189.  
  190. unsigned char *codetable[] = {
  191.         "\pspace",                /* ASCII 32 */
  192.         "\p! ",                    // !
  193.         "\p• – • • – •",        // "
  194.         "\p# ",                    // #
  195.         "\p• • • – • • –",        // $
  196.         "\p% ",                    // %
  197.         "\p& ",                    // &
  198.         "\p• – – – – •",        // '
  199.  
  200.         "\p– • – – •",            /* ( ASCII 40 */
  201.         "\p– • – – • –",        // )
  202.         "\p* ",                    // *
  203.         "\p• – • – •",            // +
  204.         "\p– – • • – –",        // ,
  205.         "\p– • • • • –",        // -
  206.         "\p• – • – • –",        // .
  207.         "\p– • • – •",            // /
  208.         "\p– – – – –",            // 0
  209.         "\p• – – – –",            // 1
  210.  
  211.         "\p• • – – –",            /* 2 ASCII 50 */
  212.         "\p• • • – –",            // 3
  213.         "\p• • • • –",            // 4
  214.         "\p• • • • •",            // 5
  215.         "\p– • • • •",            // 6
  216.         "\p– – • • •",            // 7
  217.         "\p– – – • •",            // 8
  218.         "\p– – – – •",            // 9
  219.         "\p– – – • • •",        // :
  220.         "\p– • – • – •",        // ;
  221.  
  222.         "\p< ",                    /* < ASCII 60 */
  223.         "\p– • • • –",            // =
  224.         "\p> ",                    // >
  225.         "\p• • – – • •",        // ?
  226.         "\p@ ",                    // @
  227.         "\p• –",                // A
  228.         "\p– • • •",            // B
  229.         "\p– • – •",            // C
  230.         "\p– • •",                // D
  231.         "\p•",                    // E
  232.  
  233.         "\p• • – •",            /* F ASCII 70 */
  234.         "\p– – •",                // G
  235.         "\p• • • •",            // H
  236.         "\p• •",                // I
  237.         "\p• – – –",            // J
  238.         "\p– • –",                // K
  239.         "\p• – • •",            // L
  240.         "\p– –",                // M
  241.         "\p– •",                // N
  242.         "\p– – –",                // O
  243.  
  244.         "\p• – – •",            /* P ASCII 80 */
  245.         "\p– – • –",            // Q
  246.         "\p• – •",                // R
  247.         "\p• • •",                // S
  248.         "\p–",                    // T
  249.         "\p• • –",                // U
  250.         "\p• • • –",            // V
  251.         "\p• – –",                // W
  252.         "\p– • • –",            // X
  253.         "\p– • – –",            // Y
  254.  
  255.         "\p– – • •"                /* Z ASCII 90 */
  256.     };
  257.  
  258.  
  259. Str255 mcode[CODE_MODES];
  260. Str255 mwait[WAIT_MODES];
  261. Str255 mplay[PLAY_MODES];
  262. Str255 mpause[PAUSE_MODES];
  263. Str255 mfile[PAUSE_MODES];
  264.  
  265.  
  266.  
  267. short BoundsLimitWithWrapAround(short *vPtr,short lo,short hi) {
  268.     if( *vPtr < lo)
  269.         *vPtr = hi;
  270.     else if( *vPtr > hi)
  271.         *vPtr = lo;
  272.     return( *vPtr);
  273. }
  274.  
  275.  
  276.  
  277. short BoundsLimit(short *vPtr, short lo, short hi) {
  278.     if( *vPtr < lo)
  279.         *vPtr = lo;
  280.     else if( *vPtr > hi)
  281.         *vPtr = hi;
  282.     return( *vPtr);
  283. }
  284.  
  285.  
  286.  
  287.  
  288. #define THE_TYPE_H_RECT     short         theType;    \
  289.                           Handle     theHandle;    \
  290.                           Rect         theRect;
  291.  
  292. /* GetDIHandle - return handle value of dialog item */
  293. Handle GetDIHandle(DialogPtr theDia, short i) {
  294. THE_TYPE_H_RECT
  295.   GetDItem(theDia, i, &theType, &theHandle, &theRect);
  296.   return theHandle;
  297. }
  298.  
  299.  
  300.  
  301. void SetSettings(short *rp) {
  302. short i,*resptr;
  303.   resptr = rp;
  304.   version             = *(resptr++);
  305.   volume             = *(resptr++);
  306.   frequency         = *(resptr++);
  307.   duration             = *(resptr++);
  308.   whichcode         = *(resptr++);
  309.   waitforkey         = *(resptr++);
  310.   playcontinuous     = *(resptr++);
  311.  
  312.   random = playcontinuous == 2;
  313.  
  314.   dialogPoint.h = *(resptr++);
  315.   dialogPoint.v = *(resptr++);  
  316. }
  317.  
  318.  
  319.  
  320. void getSettings() {
  321. char **myResource; short i,*resptr;
  322. #define    SettingsID    31324
  323. long mysize;
  324.  
  325.     myResource = GetResource(Setres, SettingsID);
  326.     if (myResource == 0) SysBeep(4);
  327.     else {
  328.       resptr = (short*) *myResource;
  329.       SetSettings(resptr);
  330.         ReleaseResource(myResource);
  331.       }
  332. }
  333.  
  334.  
  335. void saveSettings() {
  336. short     i,*resptr;
  337. char     **myResource; 
  338. GrafPtr tempPort;
  339.  
  340.   GetPort(&tempPort);
  341.   myResource = GetResource( Setres, SettingsID);
  342.   resptr = (short*) *myResource;
  343.   *(resptr++) = version;
  344.   *(resptr++) = volume;
  345.   *(resptr++) = frequency;
  346.   *(resptr++) = duration;
  347.   *(resptr++) = whichcode;
  348.   *(resptr++) = waitforkey;
  349.   *(resptr++) = playcontinuous;
  350.  
  351.   dialogPoint.h = myDialog->portRect.left;            /* Save window position */
  352.   dialogPoint.v = myDialog->portRect.top;
  353.   SetPort(myDialog); LocalToGlobal(&dialogPoint);  
  354.   *(resptr++) = dialogPoint.h;
  355.   *(resptr++) = dialogPoint.v;  
  356.  
  357.   ChangedResource(myResource);
  358.   WriteResource(myResource);
  359.   ReleaseResource(myResource);
  360.   SetPort(tempPort);
  361. }
  362.  
  363.  
  364.  
  365. void GetStrings(Str255 buf[], short resource_id, short num_strings) {
  366. short i1;
  367.   for (i1 = 0; i1 < num_strings; i1++)
  368.   GetIndString(&buf[i1], resource_id, i1+1);
  369. }
  370.  
  371.  
  372.  
  373. void OpenAppFile(short filenumber) {
  374. AppFile codefile;
  375. short status;
  376.   GetAppFiles(filenumber,&codefile);
  377.   status = FSOpen(codefile.fName, codefile.vRefNum, &gp);
  378.   if (status != noErr) {
  379.     SysBeep(4);
  380.     gp = 0;
  381. } }
  382.  
  383.  
  384.  
  385. void DrawCopyright() {
  386. short        i1,linelength,linewidth,mycharwidth,wordwidth;
  387. char        *linestart,*myptr;
  388. Rect        box;
  389. PicHandle    lrepict;
  390. GrafPtr        tempPort;
  391.  
  392.   GetPort(&tempPort);                    /* Save the previous port */
  393.   SetPort(noticeWindow);
  394.  
  395.   EraseRect(¬iceWindow->portRect);
  396.  
  397.   SetRect(&box, TEXTINDENT, -5, TEXTINDENT + TEXTWIDTH, TEXTHEIGHT);    /* Dimensions of text box in window coordinates */
  398.   TextSize(12); TextFace(0); TextFont(0);                        /* Font characteristics */
  399.  
  400.   i1 = 0;
  401.   while (notice[i1][0]) {
  402.     OffsetRect(&box, 0, 20);                    /* Move text box down */
  403.     TextBox( ¬ice[i1][1], notice[i1][0], &box ,teJustCenter);
  404.     i1++;
  405.   }
  406.  
  407.   SetPort(tempPort);
  408. }
  409.  
  410.  
  411.  
  412. void WaitForOperator() {
  413. Boolean gotEvent,waiting;
  414. short part;
  415. WindowPtr window;
  416. EventRecord myEvent;
  417.  
  418.     waiting = true;
  419.     do {
  420.         if (has_multifinder)
  421.             gotEvent = WaitNextEvent(everyEvent, &myEvent, sharedTimeTicks, NULL); /* give time to other processes */
  422.         else
  423.             gotEvent = GetNextEvent(everyEvent, &myEvent); /* no other processes */
  424.  
  425.         if (gotEvent) {
  426.             if (myEvent.what == mouseDown) {
  427.                 part = FindWindow(myEvent.where, &window);        /* where did the click land */
  428.                 if ((FrontWindow() == noticeWindow) && (window == noticeWindow)) 
  429.                     waiting = false;
  430.             } else if (myEvent.what == updateEvt) {
  431.                 if ((WindowPtr) myEvent.message == noticeWindow) {
  432.                     BeginUpdate(noticeWindow);
  433.                     DrawCopyright();
  434.                     DrawControls(noticeWindow);
  435.                     EndUpdate(noticeWindow);
  436.                 }
  437. #if 0
  438.             } else if (myEvent.what == osEvt) {
  439.                 if (myEvent.message & 1)
  440.                     DrawCopyright(message,linecount);
  441. #endif
  442.             } else if (myEvent.what == keyDown) {
  443.                 if (FrontWindow() == noticeWindow)
  444.                     waiting = false;
  445.             }
  446.         }
  447.     } while (waiting);
  448. }
  449.  
  450.  
  451.  
  452. /* The bounds of the copyright notice were hard coded here to discourage 
  453.    tampering, otherwise this stuff could be in resources. */
  454.  
  455. void DoCopyright() {
  456. GrafPtr            tempPort;
  457. Rect            screenRect;
  458. Rect            sRect;
  459.  
  460.   GetPort(&tempPort);                    /* Save the previous port */
  461.  
  462.   cr_windowwidth = TEXTWIDTH;                    /* Width of text portion of window (for drawing "Okay" button */
  463.   SetRect(&screenRect,30,40,WINDOWWIDTH,180);    /* Window bounds in screen coordinates */
  464.   noticeWindow = NewWindow(&nrecord,&screenRect,"\p",false,3,(WindowPtr)-1L,0,(long)0L);
  465.   OkayBtnHdl = GetNewControl(CNTL_OKAY_BTN,noticeWindow);
  466.   MoveControl(OkayBtnHdl,(cr_windowwidth >> 1) - 20,noticeWindow->portRect.bottom - 30);
  467.   ShowWindow(noticeWindow);
  468.   SetPort(noticeWindow);
  469.   SelectWindow(noticeWindow);
  470.  
  471. /*    DrawCopyright();    /*  */
  472.  
  473.   WaitForOperator();
  474.  
  475.   DisposeWindow(noticeWindow);
  476.  
  477.   SetPort(tempPort);
  478. }
  479.  
  480.  
  481.  
  482. ShowOptions() {
  483. short     handshake,item_type,mSettings;
  484. Handle     item_Handle;  
  485. Rect     item_box; 
  486. Str255     item_text;  
  487.  
  488.   GetSoundVol(&volume);
  489.   NumToString(volume,item_text);
  490.   SetIText( GetDIHandle( myDialog, volumeitem),    item_text);
  491.  
  492.   NumToString(frequency,item_text);
  493.   SetIText( GetDIHandle( myDialog, freqitem),    item_text);
  494.  
  495.   NumToString(duration,item_text);
  496.   SetIText( GetDIHandle( myDialog, wordsitem), item_text);
  497.  
  498.   SetIText( GetDIHandle( myDialog, codeitem), mcode[whichcode]);  
  499.  
  500.   SetIText( GetDIHandle( myDialog, waititem), mwait[waitforkey]);  
  501.  
  502.   SetIText( GetDIHandle( myDialog, playitem), mplay[playcontinuous]);  
  503. }
  504.  
  505.  
  506.  
  507. ShowCode(unsigned char c) {
  508. short i1,width;
  509.   if ((c >= ' ') && (c <= 'Z')) {
  510.     SetIText( GetDIHandle( myDialog, code_pattern),    codetable[c - ' ']);
  511.   }
  512.   for (i1 = 1; i1 < LINESIZE; i1++)
  513.     code_line[i1-1] = code_line[i1];
  514.   code_line[LINESIZE-1] = c;
  515.   SetPort(myDialog);
  516. #if 1
  517.   EraseRect(&pattern_rect);
  518.   width = TextWidth(code_line,0,LINESIZE);
  519.   MoveTo(pattern_rect.right - width, pattern_rect.bottom - 4);
  520.   DrawText(code_line,0,LINESIZE);
  521. #else
  522.   TextBox(code_line,LINESIZE,&pattern_rect,teJustRight);
  523. #endif
  524. }
  525.  
  526.  
  527.  
  528. ShowSpeed(void) {
  529. THE_TYPE_H_RECT
  530. long codespeed;
  531. Str255 mystring;
  532.   if ((codetimeend > codetimebegin) && 
  533.       ((codetimecharactercount > 1) || (speedfor1character))) {
  534.     codespeed = (DPHMS_TO_WPM * codetimeunits)/(codetimeend - codetimebegin);
  535.     NumToString(codespeed,mystring);
  536.     SetIText( GetDIHandle( myDialog, wpmitem), mystring);
  537.     codetimeend = -1;
  538.   }
  539. }
  540.  
  541.  
  542.  
  543. pascal void GrayItem(DialogPtr myDialog, short theItem) {
  544. THE_TYPE_H_RECT
  545. Handle myhandle;
  546. Rect myrect;
  547. short mytype;
  548. GrafPtr tempPort;
  549.  
  550.   GetPort(&tempPort);
  551.   SetPort(myDialog);
  552.   GetDItem(myDialog, theItem, &theType, &theHandle, &theRect);
  553.   if ((playcontinuous < 2) && (whichcode > 0)) {
  554.     PenPat(&qd.gray);
  555.     PenMode(patBic);
  556.     GetDItem(myDialog, codeitem, &mytype, &myhandle, &myrect);
  557.     SetDItem(myDialog, theItem, theType, theHandle, &myrect);
  558.     PaintRect(&myrect);
  559.     PenNormal();
  560.   } else {
  561.     SetRect(&myrect, 20000, 20000, 20010, 20010);
  562.     SetDItem(myDialog, theItem, theType, theHandle, &myrect);
  563.     InvalRect(&theRect);
  564.   }
  565.   SetPort(tempPort);
  566. }
  567.  
  568.  
  569.  
  570. pascal void PGrayItem(DialogPtr myDialog, short theItem) {
  571. THE_TYPE_H_RECT
  572. Handle myhandle;
  573. Rect myrect;
  574. short mytype;
  575.   GrayItem(myDialog,theItem);
  576. }
  577.  
  578.  
  579.  
  580. void AdjustControls(void) {
  581. THE_TYPE_H_RECT
  582.   GetDItem(myDialog, waititem, &theType, &theHandle, &theRect);
  583.   SetPort(myDialog);
  584.   InvalRect(&theRect);
  585. }
  586.  
  587.  
  588.  
  589. SetOptions(short the_item) {
  590. short     handshake,item_type,mSettings;
  591. Handle     item_handle;  
  592. Rect     item_box; 
  593. Str255     item_text;  
  594.  
  595. #if 0
  596.   NumToString(frequency,item_text);
  597.   SetIText( GetDIHandle( myDialog, freqitem),    item_text);
  598. #endif
  599.  
  600.     repeat_event_item = 0;
  601.  
  602.     if (the_item == open_button)
  603.  
  604.       if (playfile) {
  605.         playfile = false;
  606.         FSClose(gp);
  607.         gp = 0;
  608.         SetCTitle(GetDIHandle( myDialog, open_button), mfile[OPEN_STRING]);
  609.       } else {
  610.         FileCode();
  611.       }
  612.  
  613.     else if (the_item == quit_button) 
  614.  
  615.       done = true;
  616.  
  617.     else if (the_item == pause_button) 
  618.  
  619.       if (paused) {
  620.         paused = false;
  621.         SetCTitle(GetDIHandle( myDialog, pause_button), mpause[PAUSE_STRING]);
  622.       } else {
  623.         paused = true;
  624.         SetCTitle(GetDIHandle( myDialog, pause_button), mpause[RESUME_STRING]);
  625.       }
  626.  
  627.     else if ((the_item == volume_up) || 
  628.              (the_item == volume_down) ) {            /* UP/DOWN volume*/
  629.  
  630.       GetSoundVol(&volume);
  631.       volume += ((the_item == volume_up) ? 1 : -1);
  632.       BoundsLimitWithWrapAround( &volume, 0, 7);
  633.       SetSoundVol(volume);
  634.       NumToString(volume,item_text);
  635.       SetIText( GetDIHandle( myDialog, volumeitem), item_text);
  636.       repeat_event_item = the_item;
  637.  
  638.     } else if ((the_item == frequency_up) || 
  639.                (the_item == frequency_down)) {        /* UP/DOWN frequency */
  640.  
  641.       frequency += ((the_item == frequency_up) ? 1 : -1);
  642.       BoundsLimitWithWrapAround( &frequency, 70, 110);
  643.       NumToString(frequency,item_text);
  644.       SetIText( GetDIHandle( myDialog, freqitem), item_text);
  645.       repeat_event_item = the_item;
  646.  
  647.     } else if ((the_item == duration_up) || 
  648.                (the_item == duration_down)) {        /* UP/DOWN words per minute    */
  649.  
  650.       duration += ((the_item == duration_up) ? 1 : -1);
  651.       BoundsLimitWithWrapAround( &duration, 40, 500);
  652.       NumToString(duration,item_text);
  653.       SetIText( GetDIHandle( myDialog, wordsitem), item_text);  
  654.       repeat_event_item = the_item;
  655.       speedfor1character = true;                /* Restart speed computation */
  656.  
  657.     } else if ((the_item == whichcode_up) || 
  658.                (the_item == whichcode_down)) {        /* UP/DOWN which codes */
  659.  
  660.       whichcode += ((the_item == whichcode_up) ? 1 : -1);
  661.       BoundsLimitWithWrapAround( &whichcode, 0, 4);
  662.       SetIText( GetDIHandle( myDialog, codeitem), mcode[ whichcode]);  
  663.       GrayItem(myDialog, gray1item);
  664.       repeat_event_item = the_item;
  665.  
  666.     } else if ((the_item == wait_up) || 
  667.                (the_item == wait_down)) {            /* UP/DOWN wait for key */
  668.  
  669.       waitforkey += ((the_item == wait_up) ? 1 : -1);
  670.       BoundsLimitWithWrapAround( &waitforkey, 0, 1);
  671.       SetIText( GetDIHandle( myDialog, waititem), mwait[ waitforkey]);  
  672.       repeat_event_item = the_item;
  673.  
  674.     } else if ((the_item == play_up) || 
  675.                (the_item == play_down)) {            /* Play file continuously */
  676.  
  677.       playcontinuous += ((the_item == play_up) ? 1 : -1);
  678.       BoundsLimitWithWrapAround( &playcontinuous, 0, 2);
  679.       SetIText( GetDIHandle( myDialog, playitem), mplay[playcontinuous]);  
  680.       random = playcontinuous == 2;
  681.       GrayItem(myDialog, gray1item);
  682.       repeat_event_item = the_item;
  683.  
  684.     }
  685.  
  686.     AdjustControls();    /*  */
  687. }
  688.  
  689.  
  690.  
  691. di() {
  692. short myerr;
  693. SndCommand mysnd;
  694.  
  695.   codetimeunits += 2;
  696.  
  697.   mysnd.cmd = ampCmd;
  698.   mysnd.param1 = AMP;
  699.   mysnd.param2 = 0;
  700.   myerr = SndDoCommand(soundptr, &mysnd, false);
  701.  
  702.   mysnd.cmd = freqDurationCmd;
  703.   mysnd.param1 = duration;                    /* Duration in half-milliseconds. */
  704.   mysnd.param2 = frequency;                    /* Frequency */
  705.   myerr = SndDoCommand(soundptr, &mysnd, false);
  706.  
  707.   mysnd.cmd = restCmd;
  708.   mysnd.param1 = duration;                    /* Duration in half-milliseconds. */
  709.   mysnd.param2 = 0;
  710.   myerr = SndDoCommand(soundptr, &mysnd, false);
  711. }
  712.  
  713.  
  714.  
  715. dah() {
  716. short myerr;
  717. SndCommand mysnd;
  718.  
  719.   codetimeunits += 4;
  720.  
  721.   mysnd.cmd = ampCmd;
  722.   mysnd.param1 = AMP;
  723.   mysnd.param2 = 0;
  724.   myerr = SndDoCommand(soundptr, &mysnd, false);
  725.  
  726.   mysnd.cmd = freqDurationCmd;
  727.   mysnd.param1 = 3 * duration;                /* Duration in half-milliseconds. */
  728.   mysnd.param2 = frequency;                    /* Frequency */
  729.   myerr = SndDoCommand(soundptr, &mysnd, false);
  730.  
  731.   mysnd.cmd = restCmd;
  732.   mysnd.param1 = duration;                    /* Duration in half-milliseconds. */
  733.   mysnd.param2 = 0;
  734.   myerr = SndDoCommand(soundptr, &mysnd, false);
  735. }
  736.  
  737.  
  738.  
  739. dit() {
  740. short myerr;
  741. SndCommand mysnd;
  742.  
  743.   codetimeunits += 4;
  744.  
  745.   mysnd.cmd = ampCmd;
  746.   mysnd.param1 = AMP;
  747.   mysnd.param2 = 0;
  748.   myerr = SndDoCommand(soundptr, &mysnd, false);
  749.  
  750.   mysnd.cmd = freqDurationCmd;
  751.   mysnd.param1 = duration;                    /* Duration in half-milliseconds. */
  752.   mysnd.param2 = frequency;                    /* Frequency */
  753.   myerr = SndDoCommand(soundptr, &mysnd, false);
  754.  
  755.   mysnd.cmd = restCmd;
  756.   mysnd.param1 = 3 * duration;                /* Duration in half-milliseconds. */
  757.   mysnd.param2 = 0;
  758.   myerr = SndDoCommand(soundptr, &mysnd, false);
  759.  
  760.   mysnd.cmd = callBackCmd;
  761.   mysnd.param1 = SOUND_COMPLETE;
  762.   mysnd.param2 = SetCurrentA5();
  763.   myerr = SndDoCommand(soundptr, &mysnd, false);
  764. }
  765.  
  766.  
  767.  
  768. daht() {
  769. short myerr;
  770. SndCommand mysnd;
  771.  
  772.   codetimeunits += 6;
  773.  
  774.   mysnd.cmd = ampCmd;
  775.   mysnd.param1 = AMP;
  776.   mysnd.param2 = 0;
  777.   myerr = SndDoCommand(soundptr, &mysnd, false);
  778.  
  779.   mysnd.cmd = freqDurationCmd;
  780.   mysnd.param1 = 3 * duration;                /* Duration in half-milliseconds. */
  781.   mysnd.param2 = frequency;                    /* Frequency */
  782.   myerr = SndDoCommand(soundptr, &mysnd, false);
  783.  
  784.   mysnd.cmd = restCmd;
  785.   mysnd.param1 = 3 * duration;                /* Duration in half-milliseconds. */
  786.   mysnd.param2 = 0;
  787.   myerr = SndDoCommand(soundptr, &mysnd, false);
  788.  
  789.   mysnd.cmd = callBackCmd;
  790.   mysnd.param1 = SOUND_COMPLETE;
  791.   mysnd.param2 = SetCurrentA5();
  792.   myerr = SndDoCommand(soundptr, &mysnd, false);
  793. }
  794.  
  795.  
  796.  
  797. space() {
  798. short myerr;
  799. SndCommand mysnd;
  800.  
  801.   codetimeunits += 4;
  802.  
  803.   mysnd.cmd = restCmd;
  804.   mysnd.param1 = 4 * duration;        /* Duration in half-milliseconds. */
  805.   mysnd.param2 = 0;
  806.   myerr = SndDoCommand(soundptr, &mysnd, false);
  807.  
  808.   mysnd.cmd = callBackCmd;
  809.   mysnd.param1 = SOUND_COMPLETE;
  810.   mysnd.param2 = SetCurrentA5();
  811.   myerr = SndDoCommand(soundptr, &mysnd, false);
  812. }
  813.  
  814.  
  815.  
  816. /*    Check to see if a character is a displayable character. */
  817.  
  818. short iswhite(char c) {
  819.     if ((c <= ' ') || (c > 126))
  820.         return 1;
  821.     else
  822.         return 0;
  823. }
  824.  
  825.  
  826.  
  827.  
  828. /*     This is the routine that translates a character into it's */
  829. /*     corresponding DIs and DAHs, from Keith J. McQueen's       */
  830. /*  Morse Code program */
  831.  
  832. void send(char c) {        /* Input: the letter to be sent */
  833. char verify_c;
  834. Str255 code_text;
  835.  
  836.     /* Translate the character to uppercase and translate any tabs, */
  837.     /* returns, linefeeds etc. to spaces */
  838.  
  839.     c = toupper(c);
  840.     if (iswhite(c))
  841.         c = ' ';
  842.  
  843.     if (!volume)
  844.       return;
  845.  
  846.     if ((c < ' ') || (c > 'Z') || (c == '<') || (c == '>') || (c == '>') ||
  847.         (c == '*') || (c == '&') || (c == '%') || (c == '#') || (c == '!') || 
  848.         (c == '@')) {
  849.         SysBeep(4);                    /* If not Morse Code */
  850.         return;
  851.     }
  852.  
  853.     if (ready) {
  854.       ShowCode(c);
  855.       ready = false;
  856.     } else {
  857.       queue[queuex++] = c;
  858.       if (queuex >= QUEUE_SIZE)
  859.         queuex = 0;                    /* Wrap around at end of queue */
  860.     }
  861.  
  862.     last_code = c;
  863.  
  864.     if (speedfor1character ||                 /* First time through, or */
  865.         codetimecharactercount > 4) {    /* after 5 characters... */
  866.       speedfor1character = false;
  867.       codetimebegin = TickCount();
  868.       codetimeend = -1;
  869.       codetimecharactercount = 0;
  870.       codetimeunits = 0;
  871.     } 
  872.  
  873.  
  874.     switch(c) {
  875.         case 'A': di(); daht(); break;
  876.         case 'B': dah(); di(); di(); dit(); break;
  877.         case 'C': dah(); di(); dah(); dit(); break;
  878.         case 'D': dah(); di(); dit(); break;
  879.         case 'E': dit(); break;
  880.         case 'F': di(); di(); dah(); dit(); break;
  881.         case 'G': dah(); dah(); dit(); break;
  882.         case 'H': di(); di(); di(); dit(); break;
  883.         case 'I': di(); dit(); break;
  884.         case 'J': di(); dah(); dah(); daht(); break;
  885.  
  886.         case 'K': dah(); di(); daht(); break;
  887.         case 'L': di(); dah(); di(); dit(); break;
  888.         case 'M': dah(); daht(); break;
  889.         case 'N': dah(); dit(); break;
  890.         case 'O': dah(); dah(); daht(); break;
  891.         case 'P': di(); dah(); dah(); dit(); break;
  892.         case 'Q': dah(); dah(); di(); daht(); break;
  893.         case 'R': di(); dah(); dit(); break;
  894.         case 'S': di(); di(); dit(); break;
  895.         case 'T': daht(); break;
  896.  
  897.         case 'U': di(); di(); daht(); break;
  898.         case 'V': di(); di(); di(); daht(); break;
  899.         case 'W': di(); dah(); daht(); break;
  900.         case 'X': dah(); di(); di(); daht(); break;
  901.         case 'Y': dah(); di(); dah(); daht(); break;
  902.         case 'Z': dah(); dah(); di(); dit(); break;
  903.         case '0': dah(); dah(); dah(); dah(); daht(); break;
  904.         case '1': di(); dah(); dah(); dah(); daht(); break;
  905.         case '2': di(); di(); dah(); dah(); daht(); break;
  906.         case '3': di(); di(); di(); dah(); daht(); break;
  907.  
  908.         case '4': di(); di(); di(); di(); daht(); break;
  909.         case '5': di(); di(); di(); di(); dit(); break;
  910.         case '6': dah(); di(); di(); di(); dit(); break;
  911.         case '7': dah(); dah(); di(); di(); dit(); break;
  912.         case '8': dah(); dah(); dah(); di(); dit(); break;
  913.         case '9': dah(); dah(); dah(); dah(); dit(); break;
  914.         case '"': di(); dah(); di(); di(); dah(); dit(); break;
  915.         case '$': di(); di(); di(); dah(); di(); di(); daht(); break;
  916.         case '\'':  di(); dah(); dah(); dah(); dah(); dit(); break;
  917.         case '(': dah(); di(); dah(); dah(); dit(); break;
  918.  
  919.         case ')': dah(); di(); dah(); dah(); di(); daht(); break;
  920.         case '+': di(); dah(); di(); dah(); dit(); break;
  921.         case ',': dah(); dah(); di(); di(); dah(); daht(); break;
  922.         case '-': dah(); di(); di(); di(); di(); daht(); break;
  923.         case '.': di(); dah(); di(); dah(); di(); daht(); break;
  924.         case '/': dah(); di(); di(); dah(); dit(); break;
  925.         case ':':  dah(); dah(); dah(); di(); di(); dit(); break;
  926.         case ';': dah(); di(); dah(); di(); dah(); dit(); break;
  927.         case '=': dah(); di(); di(); di(); daht(); break;
  928.         case '?': di(); di(); dah(); dah(); di(); dit(); break;
  929.  
  930.         case ' ': space(); break;
  931.  
  932.         default: break;
  933.     }
  934. }
  935.  
  936.  
  937.  
  938. pascal void CallBack(SndChannelPtr soundptr, SndCommand soundcmd) {
  939. long myA5;
  940. SndCommand mysnd;
  941.  
  942.   if (soundcmd.param1 == SOUND_COMPLETE) {
  943.     myA5 = SetA5(soundcmd.param2);
  944.     codetimeend = TickCount();
  945.     codetimecharactercount++;
  946.  
  947.     if (chasex != queuex) {
  948.       display_code = queue[chasex++];
  949.       if (chasex >= QUEUE_SIZE)
  950.       chasex = 0;
  951.     }
  952.  
  953.     if (chasex == queuex)
  954.       ready = true;
  955.  
  956.     myA5 = SetA5(myA5);
  957.   }
  958. }
  959.  
  960.  
  961.  
  962. #if 1
  963. short initsound(SndChannelPtr *soundptr) {
  964. short i1,myerr;
  965. SndCommand mysnd;
  966.  
  967.   *soundptr = NULL;
  968.     myerr = SndNewChannel(soundptr,squareWaveSynth,initMono,&CallBack);
  969.   if (!myerr) {
  970.       mysnd.cmd = timbreCmd;    /* freqCmd or timbreCmd? */
  971.     mysnd.param1 = 0;        /*timbre = 0 produces sine wave....127 produces a square wave*/
  972.     mysnd.param2 = 0;        /*ignored on input & output*/
  973.     myerr = SndDoImmediate(*soundptr, &mysnd);
  974.  
  975.       mysnd.cmd = ampCmd;
  976.     mysnd.param1 = AMP;
  977.     mysnd.param2 = 0;
  978.     myerr = SndDoImmediate(*soundptr, &mysnd);
  979.   }
  980.   return (myerr);
  981. }
  982.  
  983.  
  984. #else
  985. short initsound(SndChannelPtr *soundptr) {
  986. short i1,myerr;
  987. SndCommand mysnd;
  988. unsigned char mytable1[512];
  989.  
  990.   for (i1 = 0; i1 < 512; i1++)
  991.     mytable1[i1] = (i1 >> 1) | 3;
  992.  
  993.   *soundptr = NULL;
  994.   myerr = SndNewChannel(soundptr,waveTableSynth,initMono,(SndCallBackProcPtr) &CallBack);
  995.  
  996.   if (!myerr) {
  997.     mysnd.cmd = waveTableCmd;
  998.     mysnd.param1 = 512;
  999.     mysnd.param2 = (long) &mytable1;
  1000.     myerr = SndDoCommand(*soundptr, &mysnd, false);
  1001.   }
  1002.   return (myerr);
  1003. }
  1004. #endif
  1005.  
  1006.  
  1007.  
  1008. FileCode() {
  1009. unsigned char    mychar;
  1010. long        gcount;
  1011. SFReply        reply; 
  1012. Point        pt;
  1013. SFTypeList    myTypes;
  1014. short        status;
  1015. short        howManyInTypeList=0;    /* Try any file type */
  1016.     
  1017.   myTypes[0]='TEXT';    /* 'TYPE' of file to be played, not used */
  1018.  
  1019.   if (gp == 0) {
  1020.     SetPt(&pt, 148, 80);
  1021.     SFGetFile(pt, "\p", NULL, howManyInTypeList, myTypes, NULL, &reply);
  1022.     if (reply.good) {
  1023.       status = FSOpen(reply.fName,reply.vRefNum,&gp);
  1024.       if (status != noErr) {
  1025.         gp = 0;
  1026.         playfile = false;
  1027.         SetCTitle(GetDIHandle( myDialog, open_button), mfile[OPEN_STRING]);
  1028.       } else {
  1029.         playfile = true;
  1030.         SetCTitle(GetDIHandle( myDialog, open_button), mfile[CLOSE_STRING]);
  1031.         if (random) {
  1032.           playcontinuous = 1;
  1033.           random = false;
  1034.           ShowOptions();
  1035.     } } }
  1036.   } else if (ready) {
  1037.     gcount = 1; 
  1038.     status = FSRead(gp,&gcount,&mychar);
  1039.     if (!status)
  1040.       send(mychar);
  1041.     else if (status == eofErr) {
  1042.       if (playcontinuous)
  1043.         SetFPos(gp,fsFromStart,0);
  1044.       else {
  1045.         FSClose(gp);
  1046.         gp = 0;
  1047.         playfile = false;
  1048.         SetCTitle(GetDIHandle( myDialog, open_button), mfile[OPEN_STRING]);
  1049.       }
  1050.     }
  1051.   }
  1052. }
  1053.  
  1054.  
  1055.  
  1056. RandomCode() {
  1057. short r;
  1058.     switch (whichcode) {
  1059.     case 0:
  1060.     default:
  1061.       r = (Random() & 0x7fff) % 51;  /* Choose any random code. */
  1062.       break;
  1063.     case 1:
  1064.       r = (Random() & 0x7fff) % 26;  /* Choose letters random code. */
  1065.       break;
  1066.     case 2:
  1067.       r = 26 + ((Random() & 0x7fff) % 10);  /* Choose numbers random code. */
  1068.       break;
  1069.     case 3:
  1070.       r = 36 + ((Random() & 0x7fff) % 15);  /* Choose symbols random code. */
  1071.       break;
  1072.     case 4:
  1073.       r = (Random() & 0x7fff) % 36;  /* Choose letters & numbers random code. */
  1074.     }
  1075.     send(randomtable[r]);
  1076. }
  1077.  
  1078.  
  1079.  
  1080. void FileMenu(short theitem) {
  1081.   switch (theitem) {
  1082.     case mFile_Open:
  1083.       if (playfile) {
  1084.         playfile = false;
  1085.         FSClose(gp);
  1086.         gp = 0;
  1087.         SetCTitle(GetDIHandle( myDialog, open_button), mfile[OPEN_STRING]);
  1088.       } else {
  1089.         FileCode();
  1090.       }
  1091.       break;
  1092.     case mSave_Settings:
  1093.       saveSettings();
  1094.       break;
  1095.     case mFile_Quit:
  1096.       done = true;
  1097.       break;
  1098.     default:
  1099.       break;
  1100.   }
  1101. }
  1102.  
  1103.  
  1104.  
  1105. /* Create menu bar and menus.
  1106.  * Inputs are:
  1107.  *   menu bar resource id (barid) 
  1108.  *   resource id of first menu item (other menu id's must follow sequentially) 
  1109.  */
  1110. void Setupmenus(short barid, short baseid) {
  1111. short i;
  1112.  
  1113.   for (i=0; i < MAX_Menus; i++) {
  1114.     mymenus[i] = GetMenu(baseid + i);
  1115.     InsertMenu( mymenus[i], 0);
  1116.   }
  1117.  
  1118.   DrawMenuBar();
  1119.  
  1120.   AddResMenu(mymenus[0], 'DRVR');
  1121. }
  1122.  
  1123.  
  1124.  
  1125. void docommand(short themenu, short theitem) {
  1126. Str255 name;
  1127. short refnum;
  1128.  
  1129.   switch (themenu) {
  1130.     case AppleN:
  1131.       if (theitem == 1)
  1132.         DoCopyright();
  1133.       else if (theitem > 2) {
  1134.         GetItem( mymenus[0], theitem, name);
  1135.         refnum = OpenDeskAcc(name);
  1136.       }
  1137.       break;
  1138.     
  1139.     case editMenuN:
  1140.       /*DoEditMenu(theitem);*/ break;
  1141.     
  1142.     case fileMenuN:
  1143.       FileMenu(theitem); break;
  1144.   }
  1145.   HiliteMenu(0);    /* unHiliteMenu    */
  1146. }
  1147.  
  1148.  
  1149.  
  1150. main() {    /* ChkForAbort is called from time consuming abcontrol()    */
  1151. EventRecord     myevent;
  1152. Boolean            event_repeated;
  1153. short            count;
  1154. short            i1;
  1155. short            message;
  1156. short            temp;
  1157. short            theItem;
  1158. short            theMenu;
  1159. short            Windowcode;
  1160. long            next_event_time;
  1161. long            theCommand;
  1162. CursHandle        handcursor;
  1163. Point            mypoint;
  1164. THE_TYPE_H_RECT
  1165. DialogPtr        whichDialog;
  1166. WindowPtr        whichWindow;
  1167. Str255            code_text;
  1168.  
  1169.   InitGraf( (Ptr) &qd.thePort);
  1170.   InitFonts();
  1171.   InitWindows();
  1172.   TEInit();
  1173.   InitDialogs( (ProcPtr) NULL);    /* restart proc */
  1174.   InitCursor();
  1175.   InitMenus();
  1176.  
  1177.   MaxApplZone();
  1178.     
  1179.   for (i1 = 0; i1 < 32; i1++) MoreMasters();
  1180.  
  1181.   qd.randSeed = TickCount() & 0xffff; /* Initialize the random number sequence */
  1182.  
  1183.   getSettings();
  1184.   GetStrings(mcode, CODE_STR_ID, CODE_MODES);
  1185.   GetStrings(mwait, WAIT_STR_ID, WAIT_MODES);
  1186.   GetStrings(mplay, PLAY_STR_ID, PLAY_MODES);
  1187.   GetStrings(mpause, PAUSE_STR_ID, PAUSE_MODES);
  1188.   GetStrings(mfile, FILE_STR_ID, FILE_MODES);
  1189.  
  1190.   handcursor = (CursHandle) GetResource( crstyp,HAND_CURSOR_ID);
  1191.  
  1192.   Setupmenus(MENUBAR_ID,BASE_MenuID);
  1193.  
  1194.   FlushEvents( everyEvent, 0);
  1195.  
  1196.   sharedTimeTicks = 15;
  1197.   if (GetTrapAddress(0x60) != GetTrapAddress(0x9f) )
  1198.     has_multifinder = true;
  1199.   else 
  1200.     has_multifinder = false;
  1201.  
  1202.   done = initsound(&soundptr);
  1203.   SetSoundVol(volume);
  1204.  
  1205.   paused = false;
  1206.   playfile = false;
  1207.   ready = true;
  1208.   key_correct = true;
  1209.  
  1210.   gp = 0;
  1211.   chasex = 0;
  1212.   queuex = 0;
  1213.   next_event_time = 0;
  1214.   repeat_event_item = 0;
  1215.   codetimebegin = 0;
  1216.   codetimeend = -1;
  1217.   speedfor1character = true;
  1218.  
  1219.   GetWMgrPort (&screenPort);
  1220.   dragRect = screenPort->portRect;
  1221.  
  1222.   CountAppFiles(&message,&count); /* message = 0 open, message = 1 print */
  1223.   if (count > 0) { 
  1224.     OpenAppFile(count);
  1225.     if (gp) {
  1226.       ClrAppFiles(count--);
  1227.       random = false;
  1228.       playfile = true;
  1229.   } }
  1230.  
  1231.   myDialog = GetNewDialog(CODE_DIALOG,(DialogPeek) 0L, (WindowPtr)-1L);
  1232.  
  1233.   MoveWindow(myDialog,dialogPoint.h,dialogPoint.v,false);
  1234.  
  1235.   GetDItem(myDialog, gray1item, &theType, &theHandle, &theRect);
  1236.   theHandle = (Handle) &PGrayItem;
  1237.   SetDItem(myDialog, gray1item, theType, theHandle, &theRect);
  1238.  
  1239. /* Save the rectangle of the code text for faster drawing */
  1240.   GetDItem(myDialog, code_character, &theType, &theHandle, &pattern_rect);
  1241.  
  1242.   if (gp)
  1243.     SetCTitle(GetDIHandle( myDialog, open_button), mfile[CLOSE_STRING]);
  1244.  
  1245.   DrawDialog(myDialog);
  1246.  
  1247.   ShowOptions();
  1248.  
  1249.   do {
  1250.  
  1251.     if (display_code) {
  1252.       ShowCode(display_code);
  1253.       display_code = 0;
  1254.     }
  1255.  
  1256.     ShowSpeed();
  1257.  
  1258.     if (!paused) {
  1259.       if (random || playfile) {
  1260.         if (ready) {
  1261.  
  1262.           if (!waitforkey || key_correct || (last_code == ' ')) {
  1263.             if (random)
  1264.               RandomCode();
  1265.             else if (playfile) 
  1266.               FileCode();
  1267.  
  1268.             key_correct = false;
  1269.  
  1270.           } else
  1271.             send(last_code);
  1272.           }
  1273.       } else 
  1274.         speedfor1character = true;
  1275.     } else
  1276.       speedfor1character = true;
  1277.  
  1278.     temp = WaitNextEvent(everyEvent, &myevent, sharedTimeTicks, NULL);
  1279.  
  1280.     if (((myevent.modifiers & optionKey) != 0) &&
  1281.         ((myevent.modifiers & shiftKey)  == 0)) {
  1282.       SetCursor(*handcursor);
  1283.     } else {
  1284.       InitCursor();
  1285.  
  1286.       if (IsDialogEvent(&myevent)) {
  1287.         event_repeated = false;
  1288.         if (StillDown() && 
  1289.             repeat_event_item && 
  1290.             (TickCount() > (next_event_time))) {
  1291.           GetDItem(myDialog, repeat_event_item, &theType, &theHandle, &theRect);
  1292.           mypoint = myevent.where;
  1293.           GlobalToLocal(&mypoint);
  1294.           if (PtInRect(mypoint,&theRect)) {
  1295.             SetOptions(repeat_event_item);
  1296.             next_event_time = TickCount() + REPEAT_AGAIN_DELAY_TICKS;
  1297.             event_repeated = true;
  1298.         } }
  1299.  
  1300.         if (!event_repeated && 
  1301.             DialogSelect(&myevent,&whichDialog,&theItem)) {
  1302.           if (myDialog == whichDialog) {
  1303.             SetOptions(theItem);
  1304.             next_event_time = TickCount() + REPEAT_EVENT_DELAY_TICKS;
  1305.     } } } }
  1306.  
  1307.     switch (myevent.what) {
  1308.       char c;
  1309.  
  1310.       case mouseDown:
  1311.         Windowcode = FindWindow( myevent.where, &whichWindow);
  1312.     
  1313.         switch (Windowcode) {
  1314.           case inContent:
  1315.             if (((myevent.modifiers & optionKey) != 0) &&
  1316.                 ((myevent.modifiers & shiftKey)  == 0)    ) {
  1317.               DragWindow( whichWindow, myevent.where, &dragRect);
  1318.               InitCursor();
  1319.             }
  1320.             break;
  1321.           case inMenuBar: 
  1322.             {    long    theCommand = MenuSelect(myevent.where);
  1323.               short        theMenu = HiWord( theCommand);
  1324.               short        theItem = LoWord( theCommand);
  1325.               docommand(theMenu, theItem); break;
  1326.             }
  1327.             break;
  1328.           default:
  1329.             break;
  1330.         }
  1331.         break;
  1332.  
  1333.       case keyDown:
  1334.       case autoKey:
  1335.         c = (char) (255 & myevent.message);
  1336.  
  1337.         if (myevent.modifiers & cmdKey) {        /* Try menu equivalent */
  1338.           theCommand = MenuKey (c);
  1339.           theMenu = HiWord(theCommand);
  1340.           theItem = LoWord(theCommand);
  1341.  
  1342.           if (HiWord(theCommand)) {
  1343.             docommand(theMenu, theItem);
  1344.             break;
  1345.           }
  1346.         } else if ((random || playfile) && waitforkey) {
  1347.           if (toupper(c) == last_code)
  1348.             key_correct = true;
  1349.         } else if ((!random && !playfile) || paused) {
  1350.           send(c);
  1351.         }
  1352.         break;
  1353.       default:
  1354.         break;
  1355.     }
  1356.   } while (!done);
  1357.   DisposDialog( myDialog); 
  1358. }
  1359.