home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d517 / cwtoy.lha / CWToy / src / cwtoy.c < prev    next >
C/C++ Source or Header  |  1991-07-20  |  34KB  |  1,053 lines

  1.  
  2. /* This program is a CW toy for sending morse code using two
  3.  * windows. 
  4.  *
  5.  * Speech Toy was written by David M Lucas and that is what
  6.  * Rob Frohne started with to create CWToy.   Thanks also to Rob Peck for his
  7.  * audiotools2.c without which this would probably never have
  8.  * been completed.  
  9.  * If you find somthing you don't like, fix it! Have fun! 
  10.  * Thanks Amiga. */
  11.  
  12. #include "cwtoy.h"
  13.  
  14. /* Revision number is used on calls to OpenLibrary
  15.  * to let the system know what revision level the
  16.  * program was written for. Usually refers to the
  17.  * ROM release number or the release number of a
  18.  * disk based library.
  19.  */
  20.  
  21. #define Enable_Abort 1
  22. #define REVISION 1
  23.  
  24. #define CONTWINDW 283   /* Overall Control Window Width/Height */
  25. #define CONTWINDH 100
  26.  
  27. /* Pen numbers to draw gadget borders/images/text with */
  28. #define REDP   3        /* color in register 3 once was red */
  29. #define BLKP   2        /* color in register 2 was black */
  30. #define WHTP   1        /* color in register 1 was white */
  31. #define BLUP   0        /* color in register 0 was blue */
  32. /* the length of the English and phonetic buffers */
  33.  
  34. #define NUMPROPS 4      /* number of proportional gadgets */
  35.  
  36. #define SPEEDSIZE 20     /* the number of digits in the speed */
  37. #define StartChannel(c) ControlChannel(c, CMD_START)
  38. #define StopChannel(c) ControlChannel(c, CMD_STOP)
  39.  
  40. /* Ranges of proportional data */
  41. #define MAXWEIGHT  2000
  42. #define MINWEIGHT  500
  43. #define MAXSPEED   99
  44. #define MINSPEED   3
  45. #define MAXPITCH1  2000
  46. #define MINPITCH1  100
  47. #define RNGWEIGHT  (MAXWEIGHT - MINWEIGHT)  +1
  48. #define RNGSPEED   (MAXSPEED - MINSPEED)  +1
  49. #define RNGPITCH1  (MAXPITCH1 - MINPITCH1) +1
  50. #define RNGVOL     (MAXVOL   - MINVOL)   +1
  51. #define NORMSPACING  1000
  52. /*#define DEFWEIGHT  1000 */
  53. /*#define DEFSPEED   20 */
  54. /*#define DEFPITCH1  440 */
  55. #define CIRQSIZE   4096
  56.  
  57. struct TextAttr TestFont = /* Needed for opening screen */
  58.    {
  59.    (STRPTR)"topaz.font",
  60.    TOPAZ_EIGHTY, 0, 0
  61. };
  62.  
  63. struct Code {
  64.     int speed;
  65.     int pitch;
  66.     int volume;
  67.     int weight;
  68.         int spacing;
  69. };
  70.  
  71. struct Code cw = {
  72.     20, 440, 64, 1000, 1000 
  73. };
  74.  
  75. USHORT circleq[CIRQSIZE]; /* This is the circlular Q buffer that will
  76.                 * allow us to edit the buffer before it is
  77.                 * sent if we desire. */
  78.  
  79. /* Initialize the circular Q pointers. */
  80. int inptr = 0, outptr = 0;
  81.  
  82. int ctrls = 0;
  83.  
  84. /* String Gadgets *********************************************
  85.  * First the string gadgets.
  86.  * 1) because the Phonetic string is refreshed programaticly
  87.  * (that is, deleted and added again) quite often, and doing
  88.  * this requires the use of RefreshGadgets(), and this causes
  89.  * gadgets that are closer to the beginning of the list than
  90.  * the gadget given to RefreshGadgets() to flicker.
  91.  * 2) because they don't flicker when OTHER gadgets
  92.  * (ie female/male, coming up) are deleted and added.
  93.  *
  94.  * These'll be used to put a nice double line border around
  95.  * each of the two string gadgets.
  96.  *
  97.  * y,x pairs drawn as a connected line. Be sure to have an even
  98.  * number of arguments (ie complete pairs).
  99.  */
  100.  
  101. SHORT StrVectors[] = {
  102.    0, 0,   160, 0,   160, 13,   0, 13,
  103.    0, 1,   159, 1,   159, 12,   1, 12,
  104.    1, 1
  105. };
  106. struct Border StrBorder = {
  107.    -4, -3,           /* initial offsets, gadget relative */
  108.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  109.    9,                /* number of vectors */
  110.    StrVectors,     /* pointer to the actual array of vectors */
  111.    NULL       /* no next Border, can point to another border */
  112. };
  113.  
  114. /* The same undo buffer is used for both string gadgets,
  115.  * this is sized to largest so that largest fits.
  116.  */
  117. UBYTE UndoBuffer[SPEEDSIZE];
  118.  
  119. /* Speed Gadget is where the speed will be displayed. */
  120. /* default text */
  121. UBYTE Speed[SPEEDSIZE] = "20 Words per Minute";
  122. UBYTE Space[2] = " ";
  123. struct StringInfo EnglInfo = {
  124.    Speed,         /* pointer to I/O buffer */
  125.    UndoBuffer,    /* pointer to undo buffer */
  126.    0,             /* buffer position */
  127.    SPEEDSIZE,     /* max number of chars, including NULL */
  128.    0, 0,          /* first char in display, undo positions */
  129.    20,             /* number of chars (currently) in the buffer */
  130.    0, 0, 0,       /* position variables calculated by Intuition */
  131.    NULL,          /* no pointer to RastPort */
  132.    0,             /* not a LongInt string gadget */
  133.    NULL           /* no pointer to alternate keymap */
  134. };
  135. struct IntuiText EnglText = {
  136.    WHTP, BLUP,    /* FrontPen, BackPen */
  137.    JAM1,          /* DrawMode */
  138.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  139.    &TestFont,     /* pointer to TextFont */
  140.    (UBYTE *) "Speed:",      /* pointer to Text */
  141.    NULL           /* no pointer to NextText */
  142. };
  143. struct Gadget SpeedGadget = {
  144.    NULL,             /* pointer to Next Gadget */
  145.    11, 63, 290, 10,  /* (Left Top Width Height) Hit Box */
  146.    GADGHCOMP,        /* Flags */
  147.    RELVERIFY,        /* Activation flags */
  148.    STRGADGET,        /* Type */
  149.    (APTR)&StrBorder, /* pointer to Border Image */
  150.    NULL,             /* no pointer to SelectRender */
  151.    &EnglText,        /* pointer to GadgetText */
  152.    0,                /* no MutualExclude */
  153.    (APTR)&EnglInfo,  /* pointer to SpecialInfo */
  154.    0,                /* no ID */
  155.    NULL              /* no pointer to special data */
  156. };
  157.  
  158.  
  159. /* Now the proportional gadgets. */
  160. /* Proportional Gadgets **************************************/
  161. /* The following variables are used to create proportional
  162.  * Gadgets. These variables will be filled in with copies of
  163.  * the generic Gadgetry below.
  164.  */
  165. SHORT PropCount = 0;       /* index to next available Gadget */
  166. struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */
  167. /* dummy AUTOKNOB Images are required */
  168. struct Image PImages[NUMPROPS];
  169. /* These get copies of TPropInfo */
  170. struct PropInfo PInfos[NUMPROPS];
  171. /* These get copies of TPropGadget */
  172. struct Gadget Props[NUMPROPS];
  173. struct IntuiText TPropText = {
  174.    WHTP, BLUP,   /* FrontPen, BackPen */
  175.    JAM1,         /* DrawMode */
  176.    0, -10,       /* LeftEdge, TopEdge (relative to gadget) */
  177.    &TestFont,    /* pointer to TextFont */
  178.    NULL,         /* pointer to Text is filled at runtime */
  179.    NULL          /* no pointer to NextText */
  180. };   
  181. struct PropInfo TPropInfo = {
  182.    AUTOKNOB | FREEHORIZ,  /* Flags */
  183.    0, 0,            /* Pots:  Horiz, Vert: both start at 0 */
  184.    0x1FFF, 0x1FFF,  /* Bodies: Horiz is 1/8, Vert is 1/8 */
  185.    0, 0, 0, 0, 0, 0 /* System usage stuff */
  186. };
  187. /* this is the template for the Gadget of a horizontal */
  188. /* Proportional Gadget */
  189. struct Gadget TPropGadget = {
  190.    &SpeedGadget,              /* pointer to NextGadget */
  191.    7, 12, 115, 10,            /* Select Box L T W H */
  192.    GADGHCOMP | GADGIMAGE,     /* Flags */
  193.    GADGIMMEDIATE | RELVERIFY, /* Activation flags */
  194.    PROPGADGET,                /* Type */
  195.    NULL,       /* pointer to Image filled in later */
  196.    NULL,       /* no pointer to SelectRender */
  197.    NULL,       /* no pointer to GadgetText */
  198.    0,          /* no MutualExclude */
  199.    NULL,       /* SpecialInfo proportional data filled later */
  200.    0,          /* no ID */
  201.    NULL        /* no pointer to special data */
  202. };
  203.  
  204. struct IntuitionBase *IntuitionBase = 0;
  205. struct GfxBase *GfxBase = 0;
  206.  
  207. /* Only one menu. */
  208.  
  209. ULONG MenuNumber;
  210. ULONG TheMenu;
  211. ULONG TheItem;
  212.  
  213. struct IntuiText MenuItemText = {
  214.    BLUP,         /* Front Pen */
  215.    WHTP,         /* Back pen */
  216.    JAM2,         /* Draw Mode */
  217.    0,            /* Left Edge */
  218.    0,            /* Top */
  219.    &TestFont,    /* pointer to TextFont */
  220.    (UBYTE *) "About CW Toy...", /* text */
  221.    NULL          /* next */
  222. };
  223. struct MenuItem MyMenuItem = {
  224.    NULL,                /* pointer to next item */
  225.    0,                   /* left */
  226.    0,                   /* top */
  227.    150,                 /* width */
  228.    8,                   /* height */
  229.    ITEMTEXT | ITEMENABLED | HIGHCOMP,  /* flags */
  230.    0,                   /* no mutual exclude */
  231.    (APTR)&MenuItemText, /* Render */
  232.    NULL,                /* pointer to alternate image */
  233.    NULL,                /* Command "amiga" char */
  234.    NULL,                /* Sub Item */
  235.    MENUNULL             /* nextselect */
  236. };
  237.  
  238. struct Menu MyMenu = {
  239.    NULL,          /* pointer to next menu */
  240.    0,0,150,0,     /* left,0,Width,0 */
  241.    MENUENABLED,   /* flags */
  242.    (BYTE *) "CW Toy Menu", /* menu name */
  243.    &MyMenuItem    /* First Item in list */
  244. };
  245.  
  246. struct IntuiText ReqText1 = {
  247.    BLUP,         /* Front Pen */
  248.    WHTP,         /* Back pen */
  249.    JAM2,         /* Draw Mode */
  250.    5,            /* Left Edge */
  251.    23,           /* Top */
  252.    &TestFont,    /* pointer to TextFont */
  253.    (UBYTE *) "Version 1.0  30 June, 1991",  /* text */
  254.    NULL          /* next */
  255. };
  256. struct IntuiText ReqText2 = {
  257.    BLUP,         /* Front Pen */
  258.    WHTP,         /* Back pen */
  259.    JAM2,         /* Draw Mode */
  260.    5,            /* Left Edge */
  261.    13,           /* Top */
  262.    &TestFont,    /* pointer to TextFont */
  263.    (UBYTE *) "Freeware - Public Domain ", /* text */
  264.    &ReqText1     /* next */
  265. };
  266. struct IntuiText ReqText3 = {
  267.    BLUP,         /* Front Pen */
  268.    WHTP,         /* Back pen */
  269.    JAM2,         /* Draw Mode */
  270.    5,            /* Left Edge */
  271.    3,            /* Top */
  272.    &TestFont,    /* pointer to TextFont */
  273.    (UBYTE *) "By Rob Frohne (KL7NA)", /* text */
  274.    &ReqText2     /* next */
  275. };
  276.  
  277. struct IntuiText OKIText = {
  278.    BLUP, WHTP, /* FrontPen, BackPen */
  279.    JAM2,       /* DrawMode */
  280.    6, 3,       /* LeftEdge, TopEdge (relative to gadget) */
  281.    &TestFont,  /* pointer to TextFont */
  282.    (UBYTE *) "OK",       /* pointer to Text */
  283.    NULL        /* no pointer to NextText */
  284. };
  285.  
  286. struct Requester *AboutRequester;
  287.  
  288. USHORT autoret;
  289. struct Window *ControlWindow = NULL;
  290. struct IntuiMessage *MyIntuiMessage;
  291. struct NewWindow NewControlWindow = {
  292.    00, 11,                    /* start LeftEdge, TopEdge */
  293.    CONTWINDW, CONTWINDH,      /* start Width, Height */
  294.    -1, -1,                    /* DetailPen, BlockPen */
  295.    GADGETUP | CLOSEWINDOW | MENUPICK
  296.    | VANILLAKEY,              /* IDCMP FLAGS */
  297.    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
  298.    | GIMMEZEROZERO | ACTIVATE,/* Flags (can be NULL) */
  299.    &Props[NUMPROPS-1],        /* Pointer to FirstGadget */
  300.    NULL,                      /* no pointer to first CheckMark */
  301.    (UBYTE *) "CW Toy",                  /* Title (can be NULL) */
  302.    NULL,                      /* no Pointer to Screen */
  303.    NULL,                      /* no Pointer to BitMap */
  304.    20, 20,                    /* Min/max  Sizable to (w/h) */
  305.    CONTWINDW, CONTWINDH,      /* These aint used, can't size */
  306.    WBENCHSCREEN         /* Type of screen window appears in */
  307. };
  308.  
  309. struct NewWindow NewDisplayWindow = {
  310.     00,(CONTWINDH + 10),
  311.     CONTWINDW,50,
  312.     -1,-1,
  313.     MENUPICK|VANILLAKEY,              /* IDCMP FLAGS */
  314.     GIMMEZEROZERO|ACTIVATE|WINDOWSIZING|WINDOWDEPTH|WINDOWDRAG|REFRESHWINDOW,
  315.     0,
  316.     NULL,
  317.     (UBYTE *) "CW Buffer",
  318.     NULL,
  319.     NULL,
  320.     10,10,700,440,
  321.     WBENCHSCREEN };
  322.     
  323. /* Some audio stuff for Rob Peck's Audio Tools. */
  324.    extern char *w1;
  325.    extern int ControlChannel();
  326.    extern struct MsgPort *InitAudio();
  327.    struct MsgPort *myport;   /* CHANGE from article */
  328.    LONG channel;
  329.  
  330. /* Some stuff for the Console.  */
  331.    extern struct ConIOBlocks *CreateConsole();
  332.    struct ConIOBlocks *cio;
  333.    struct Window *DisplayWindow, *OpenWindow();
  334.  
  335.  
  336.  
  337. /** start of code ***************************/
  338. main( argc, argv )
  339. int argc;
  340. char *argv[];
  341. {
  342.    ULONG Signals;                     /* Wait() tells me which to look at */
  343.    ULONG MIClass;                     /* Save quickly, ReplyMsg() asap */
  344.    USHORT MICode;
  345.    APTR MIAddress;
  346.    LONG error;
  347.    int i,j,k,goaway = 0;
  348.    char numspeed[SPEEDSIZE];
  349.    FILE *fp, *fopen();   
  350.    fp = 0; /* Initialize fp */
  351.    
  352.    /* check for a question mark as the first argument */
  353.    if ( argv[1][0] == '?' ) {
  354.        printf("Usage: %s [message] [-f filename] [-e] [-s speed] [-p pitch] [-v volume] [-w weighting]\n [-b spaceing]\n", argv[0] );
  355.        exit(0);
  356.    }   /* end of checking for a question mark */
  357.    
  358.    /* Parse the input line */
  359.    for ( i=1; i < argc; i++ ) {
  360.  
  361.        /* see if it starts with a minus (then s,p,v,w,f) */
  362.        if ( argv[i][0] != '-' ) {
  363.            /* Get the message if it is there. */
  364.            for ( j=0; argv[i][j] != '\0'; j++ )
  365.               circleq[inptr++] = argv[i][j];
  366.            circleq[inptr++] = 0x20;
  367.        }
  368.        else {
  369.            /* Parse the switches. */
  370.            switch( argv[i][1] ) {
  371.                case 'f' : /* File to send. */
  372.                    if ((fp = fopen(argv[++i],"r")) == NULL) {
  373.               printf("cwtoy: can't open %s\n",argv[++i]);
  374.               exit(1);
  375.           }
  376.                    break;
  377.                case 'e' : /* Exit after sending message of file. */
  378.                goaway = 1;
  379.                    break;
  380.                case 's' : /* Speed */
  381.                    cw.speed = atoi(argv[++i]);
  382.                ftoa((double)cw.speed,numspeed,0,1);
  383.                if(cw.speed < 10) strcat(numspeed,Space);
  384.                   strcat(numspeed,(Speed + 2));
  385.                    strcpy(Speed,numspeed);
  386.                    break;
  387.                case 'p' : /* Pitch */
  388.                    cw.pitch = atoi(argv[++i]);
  389.                    break;
  390.                case 'v' : /* Volume */
  391.                    cw.volume = atoi(argv[++i]);
  392.                    break;
  393.                case 'w' : /* Weighting */
  394.                    cw.weight = atoi(argv[++i]);
  395.                    break;
  396.                case 'b' : /* Spacingfactor */
  397.                    cw.spacing = atoi(argv[++i]);
  398.                    break;
  399.                default :
  400.                    printf("Usage: %s [message] [-f filename] [-e] [-s speed] [-p pitch] [-v volume] [-w weighting]\n [-b spaceing]\n", argv[0] );
  401.                  exit(0);
  402.                    break;
  403.            }   /* end of switch for the arguments */
  404.        }   /* end of checking for a switch argument */        
  405.    }
  406.    
  407.    /*  First initialize the audio routines using Rob Peck's Audio Tools. */
  408.    myport = InitAudio();   /* now returns address of message port */
  409.    if(myport == 0) 
  410.    {
  411.       printf("Problem in InitAudio!\n");
  412.       MyCleanup();
  413.    }
  414.    {   
  415.       channel = GetChannel(-1);
  416.       if(channel == -1)
  417.       {
  418.          printf("cannot get a channel!\n");
  419.          MyCleanup();
  420.       }
  421.       error = StopChannel(channel);
  422.       if(error) 
  423.       {  
  424.          printf("error in stopping channel = %ld\n",error);
  425.          MyCleanup();
  426.       }
  427.    }
  428.  
  429.    /* Open those libraries that the program uses directly */
  430.    if ((IntuitionBase = (struct IntuitionBase *)
  431.           OpenLibrary("intuition.library", REVISION)) == 0) {
  432.       MyCleanup();
  433.       exit(1);
  434.    }
  435.  
  436.    if ((GfxBase = (struct GfxBase *)
  437.         OpenLibrary("graphics.library", REVISION)) == 0) {
  438.       MyCleanup();
  439.       exit(1);
  440.    }
  441.  
  442.    /* This is where the proportional gadgets are set up, using
  443.     * the templates that were declared staticly.
  444.     */
  445.    for(PropCount = 0; PropCount < NUMPROPS; PropCount++) {
  446.       PTexts[PropCount] = TPropText;
  447.       Props[PropCount] = TPropGadget;
  448.       PInfos[PropCount] = TPropInfo;
  449.       Props[PropCount].GadgetText = (struct IntuiText *)
  450.            &PTexts[PropCount];
  451.       Props[PropCount].GadgetRender = (APTR)
  452.            &PImages[PropCount];
  453.       Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount];
  454.       switch (PropCount) {
  455.       case 0:
  456.          PTexts[PropCount].IText = (UBYTE *) "Weighting:";
  457.          if (cw.weight == MAXWEIGHT)
  458.             PInfos[PropCount].HorizPot = 65535;
  459.          else
  460.             PInfos[PropCount].HorizPot = ((cw.weight - MINWEIGHT)
  461.              << 16) / (MAXWEIGHT - MINWEIGHT);
  462.          break;
  463.       case 1:
  464.          PTexts[PropCount].IText = (UBYTE *) "Speed:";
  465.          Props[PropCount].TopEdge += 22;
  466.          Props[PropCount].NextGadget = &Props[PropCount-1];
  467.          if (cw.speed == MAXSPEED )
  468.             PInfos[PropCount].HorizPot = 65535;
  469.          else
  470.             PInfos[PropCount].HorizPot = ((cw.speed - MINSPEED)
  471.              << 16) / (MAXSPEED - MINSPEED);
  472.          break;
  473.       case 2:
  474.          PTexts[PropCount].IText = (UBYTE *) "Pitch:";
  475.          Props[PropCount].LeftEdge += 145;
  476.          Props[PropCount].NextGadget = &Props[PropCount-1];
  477.          if (cw.pitch == MAXPITCH1)
  478.             PInfos[PropCount].HorizPot = 65535;
  479.          else
  480.             PInfos[PropCount].HorizPot = ((cw.pitch - MINPITCH1)
  481.              << 16) / (MAXPITCH1 - MINPITCH1);
  482.          break;
  483.       case 3:
  484.          PTexts[PropCount].IText = (UBYTE *) "Volume:";
  485.          Props[PropCount].TopEdge += 22;
  486.          Props[PropCount].LeftEdge += 145;
  487.          Props[PropCount].NextGadget = &Props[PropCount-1];
  488.          if (cw.volume == MAXVOL)
  489.             PInfos[PropCount].HorizPot = 65535;
  490.          else
  491.             PInfos[PropCount].HorizPot = ((cw.volume - MINVOL)
  492.              << 16) / (MAXVOL - MINVOL);
  493.          break;
  494.       default:
  495.          break;
  496.       }
  497.    }
  498.    if ((ControlWindow = (struct Window *)OpenWindow
  499.         (&NewControlWindow)) == NULL) {
  500.       MyCleanup();
  501.       exit(1);
  502.    }
  503.    if ((DisplayWindow = OpenWindow(&NewDisplayWindow)) == NULL) {
  504.       MyCleanup();
  505.       exit(1);
  506.    }
  507.    if ((cio=CreateConsole(DisplayWindow)) == 0) {
  508.       MyCleanup();
  509.    }
  510.  
  511.    /* fill background of window */
  512.    SetAPen(ControlWindow->RPort, BLKP);
  513.    RectFill(ControlWindow->RPort,0L,0L,
  514.         (LONG)ControlWindow->GZZWidth, (LONG)ControlWindow->GZZHeight);
  515.    RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL);
  516.  
  517.    SetMenuStrip(ControlWindow, &MyMenu);  
  518.    SetMenuStrip(DisplayWindow, &MyMenu);  
  519.    
  520.    if (fp != 0) { /* If we opened a file to send, send it first! */
  521.        filesend(fp);
  522.        if (goaway == 1) {
  523.           MyCleanup();
  524.           exit(0);
  525.        }
  526.    }
  527.    if (inptr > 0) send(); /* Got a -m message to start already! */
  528.    
  529. /* !!! Ah, But what if Control Window's not been opened? */
  530. /* Rob changed some tricky stuff here! */
  531.    for (;;) {  /* ever wait for a signal and process it */
  532.       /* wait lets the rest of the system run, */
  533.       /* this program sleeps */
  534.       Signals = Wait((1 << myport->mp_SigBit) | 
  535.       (1 << DisplayWindow->UserPort->mp_SigBit) |
  536.       (1 << ControlWindow->UserPort->mp_SigBit));
  537.       /* now check to see to what we owe the intrusion */
  538.  
  539.       Chk_Abort();
  540.       if (Signals & (1<< myport->mp_SigBit)) {
  541.          if(MayGetNote(myport,FALSE) == 1L) {
  542.             ++outptr % CIRQSIZE; /* Always increment the outptr after we are
  543.                   * done sending a character. */
  544.            /* If not caught up and no pause in effect, send the next one. */
  545.         if (inptr != outptr) {
  546.                if (ctrls == 0) send(); 
  547.             }
  548.             else {
  549.              if (goaway == 1) {
  550.              MyCleanup();
  551.                       exit(0);
  552.              }
  553.             }
  554.          }
  555.       }
  556.        
  557.       if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
  558.          /* Process the Intuition message */
  559.          while (MyIntuiMessage=(struct IntuiMessage *)
  560.                       GetMsg(ControlWindow->UserPort)) {
  561.             /* Get all the needed info and give message back */
  562.             MIClass = MyIntuiMessage->Class;
  563.             MICode = MyIntuiMessage->Code;
  564.             MIAddress = MyIntuiMessage->IAddress;
  565.             ReplyMsg(MyIntuiMessage);
  566.             /* Now, what was it you wanted? */
  567.             switch (MIClass) {
  568.                case VANILLAKEY:
  569.                     /* Service the character buffer. */
  570.          switch(qUp(MICode)) {
  571.             case 0:
  572.                                /* If we are caught up
  573.                         * initialize the sending. 
  574.                        * (Remember that qUp
  575.                        * incremented inptr.) */
  576.                           if((inptr % CIRQSIZE == (outptr + 1) % CIRQSIZE) 
  577.                     && (ctrls == 0))
  578.                     send();
  579.                                    break;
  580.              case 1:
  581.                       /* Check for Control C. */
  582.                 exit(0);
  583.             case 2:
  584.             case 3:
  585.                           case 4:
  586.                 break;
  587.          }
  588.                   break;
  589.                case MENUPICK:
  590.                   menumessage(MICode, ControlWindow);
  591.                   break;
  592.                case GADGETUP:         /* reply, then process */
  593.                   gadgetmessage(MIAddress, ControlWindow);
  594.                   break;
  595.                case CLOSEWINDOW:       /* bye! */
  596.                   while (MyIntuiMessage = (struct
  597.                    IntuiMessage *) GetMsg(ControlWindow->UserPort))
  598.                    ReplyMsg(MyIntuiMessage);
  599.                   MyCleanup();
  600.                   exit(0);
  601.                default:
  602.                   break;
  603.             }  /* switch */
  604.          } /* while */
  605.       } /* if */
  606.       if (Signals & (1<< DisplayWindow->UserPort->mp_SigBit)) {
  607.          /* Process the Intuition message */
  608.          while (MyIntuiMessage=(struct IntuiMessage *)
  609.                       GetMsg(DisplayWindow->UserPort)) {
  610.             /* Get all the needed info and give message back */
  611.             MIClass = MyIntuiMessage->Class;
  612.             MICode = MyIntuiMessage->Code;
  613.             MIAddress = MyIntuiMessage->IAddress;
  614.             ReplyMsg(MyIntuiMessage);
  615.             /* Now, what was it you wanted? */
  616.             switch (MIClass) {
  617.                case VANILLAKEY:
  618.                     /* Service the character buffer. */
  619.                   /* For comments see similar section under ControlWindow. */
  620.          switch(qUp(MICode)) {
  621.             case 0:
  622.                           if((inptr % CIRQSIZE == (outptr + 1) % CIRQSIZE) 
  623.                     && (ctrls == 0))
  624.                     send();
  625.                                    break;
  626.              case 1:
  627.                 exit(0);
  628.             case 2:
  629.             case 3:
  630.                           case 4:
  631.                 break;
  632.          }
  633.                   break;
  634.                case MENUPICK:
  635.                   menumessage(MICode, DisplayWindow);
  636.                   break;
  637.                default:
  638.                   break;
  639.             }  /* switch */
  640.          } /* while */
  641.       } /* if */
  642.    }/* for */
  643. }  /* main */
  644.  
  645. /* a MENUPICK has been received, this
  646.  * routine takes the appropriate action
  647.  */
  648.  
  649. menumessage(code, w)
  650.  
  651. USHORT code;
  652. struct Window *w;
  653. {
  654.    switch (MENUNUM(code)) {
  655.       case 0:
  656.          switch (ITEMNUM(code)) {
  657.             case 0:
  658.                AutoRequest(w, &ReqText3, NULL,
  659.                            &OKIText, 0, 0, 280, 47);
  660.                break;
  661.          }
  662.       break;
  663.    }
  664.    return(0);
  665. }
  666.  
  667. /* a GADGETUP has been received, this
  668.  * routine takes the appropriate action
  669.  */
  670. gadgetmessage(address, w)
  671. APTR address;
  672. struct Window *w;
  673. {
  674.    long PropRange;
  675.    UBYTE i;
  676.    int length;
  677.    char numspeed[SPEEDSIZE];
  678.  
  679.    if (address == (APTR)&Props[2]) {
  680.       PropRange = RNGPITCH1;
  681.       cw.pitch = (((PInfos[2].HorizPot >> 1)
  682.        * PropRange) >> 15) + MINPITCH1;
  683.    }
  684.    else if (address == (APTR)&Props[3]) {
  685.       PropRange = RNGVOL;
  686.       cw.volume = (((PInfos[3].HorizPot >> 1)
  687.        * PropRange) >> 15) + MINVOL;
  688.   }
  689.  
  690.    else if (address == (APTR)&Props[0]) {
  691.       PropRange = RNGWEIGHT;
  692.       cw.weight = (( (PInfos[0].HorizPot >> 1)
  693.        * PropRange) >> 15) + MINWEIGHT;
  694.    }
  695.    
  696.    /* Since the program changes the contents of the string
  697.     * gadgets' buffer and it's size, which is something else
  698.     * intuition doesn't expect a program (as opposed to the
  699.     * user) to do. The program must remove, then change, then
  700.     * add this gadget, and then by passing the address of this
  701.     * gadget to RefreshGadgets(), only the gadgets from here
  702.     * to the start of the list will be refreshed, which
  703.     * minimizes the visible flash that RefreshGadgets() can
  704.     * introduce.
  705.     */
  706.    else if (address == (APTR)&Props[1]) {
  707.       PropRange = RNGSPEED ;
  708.       cw.speed = (((PInfos[1].HorizPot >> 1)
  709.        * PropRange) >> 15) + MINSPEED;
  710.       i = RemoveGadget(ControlWindow, &SpeedGadget);
  711. /*      if((length = stci_d(numspeed, cw.speed)) < 4)
  712.     {
  713.          if(length < 3) strcat(numspeed,Space);
  714.          strcat(numspeed,(Speed + 2));
  715.          strcpy(Speed,numspeed);
  716.         }  */ /* This was commented out to modify it to Manx. */
  717. /* The 3 lines below were added to make it Manx compatible. */
  718.       ftoa((double)cw.speed,numspeed,0,1);
  719.       if(cw.speed < 10) strcat(numspeed,Space);
  720.       strcat(numspeed,(Speed + 2));
  721.       strcpy(Speed,numspeed);
  722. /* The 3 lines above this were added to make it Manx compatible. */
  723.       AddGadget(ControlWindow, &SpeedGadget, i);
  724.       RefreshGadgets(&SpeedGadget, ControlWindow, NULL);
  725.    }
  726.    return(0);
  727. }
  728.  
  729.  
  730. /* Deallocate any memory, and close all of the
  731.  * windows/screens/devices/libraries in reverse order to
  732.  * make things work smoothly. And be sure to check
  733.  * that the open/allocation was successful before
  734.  * closing/deallocating.
  735.  */
  736. MyCleanup()
  737. {
  738.    FinishAudio(myport);   /* NEW parameter for FinishAudio */
  739.    if (myport != 0) 
  740.       DeletePort(myport);
  741.    if (cio != 0)
  742.       DeleteConsole(cio);
  743.    if (DisplayWindow != NULL)
  744.       CloseWindow(DisplayWindow);
  745.    if (ControlWindow != NULL)
  746.       CloseWindow(ControlWindow);
  747.    /* freeimages makes sure image allocation was successful */
  748.    if (GfxBase != 0)
  749.       CloseLibrary(GfxBase);
  750.    if (IntuitionBase != 0)
  751.       CloseLibrary(IntuitionBase);
  752.    return(0);
  753. }
  754.  
  755. UBYTE Lookup[] = {0x01, 0x6, 0x11, 0x15, 0x09, 0x02, 0x14, 0x0b, 0x10, 0x04, 0x1e,
  756.    0x0d, 0x12, 0x07, 0x05, 0x0f, 0x16, 0x1b, 0x0a, 0x08, 0x03, 0x0c, 0x18,
  757.    0x0e, 0x19, 0x1d, 0x13, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
  758.    0x01, 0x52, 0x01, 0xc8,
  759.    0x01, 0x01, 0x5d, 0x2d, 0x6d, 0x22, 0x2a, 0x73, 0x61, 0x6a, 0x29, 0x3f, 0x3e, 0x3c, 
  760.    0x38, 0x30, 0x20, 0x21, 0x23, 0x27, 0x2f, 0x47, 0x55, 0x01, 0x31, 0x01, 0x4c, 
  761.    0x01, 0x06, 0x11, 0x15, 0x09, 0x02, 0x14, 0x0b, 0x10, 0x04, 0x1e,
  762.    0x0d, 0x12, 0x07, 0x05, 0x0f, 0x16, 0x1b, 0x0a, 0x08, 0x03, 0x0c, 0x18,
  763.    0x0e, 0x19, 0x1d, 0x13, 0x2d, 0x29, 0x6d, 0x01, 0xac, 0x01, 
  764.    0x06, 0x11, 0x15, 0x09, 0x02, 0x14, 0x0b, 0x10, 0x04, 0x1e,
  765.    0x0d, 0x12, 0x07, 0x05, 0x0f, 0x16, 0x1b, 0x0a, 0x08, 0x03, 0x0c, 0x18,
  766.    0x0e, 0x19, 0x1d, 0x13, 0x2d, 0x29, 0x6d, 0x01, 0x01}; 
  767.  
  768. int qUp(letter)
  769. /* qUp is the only place that inptr should ever change! */
  770.  
  771. USHORT letter;
  772.  
  773. {
  774.     char buffer[1];
  775.         /* Check for backspace and that we can backup. */
  776.     if( (letter == 0x08) && (inptr % CIRQSIZE != (outptr + 1) % CIRQSIZE) 
  777.               && (inptr != outptr) 
  778.               && (inptr % CIRQSIZE != (outptr -1) % CIRQSIZE) ) {
  779.         (--inptr) % CIRQSIZE;
  780.         /*(--inptr) % CIRQSIZE;*/
  781.         buffer[0] = (char)(letter & 0xff); /* Backspace in the 
  782.                         * DisplayWindow. */
  783.            if(letter != 0x9b) WriteConsole(cio,buffer,1);
  784.         return(2);
  785.     }
  786.         
  787.         /* Check for Control C.  If so, blow it away. */
  788.     else if(letter == 0x03) {
  789.         MyCleanup();
  790.                  return(1);
  791.     }
  792.         
  793.     /* Control S will pause the sending and control Q 
  794.      * will resume it where it left off. */
  795.         /* Control S */
  796.         else if(letter == 0x13) {
  797.         ctrls = 1;
  798.             return(2);
  799.         }
  800.         /* Control Q */
  801.         else if(letter == 0x11) {
  802.         ctrls = 0; 
  803.                  if(inptr != outptr) send();
  804.             return(2);
  805.         }
  806.         
  807.         /* Check for Control X.  If so clear the circlular Q. */
  808.         else if(letter == 0x18) {
  809.                  /* How do we handle the wrap around? */
  810.             while (inptr % CIRQSIZE != (outptr + 1) % CIRQSIZE) {
  811.                      (--inptr) % CIRQSIZE; 
  812.             buffer[0] = (char)(0x08 & 0xff);
  813.                if(letter != 0x9b) WriteConsole(cio,buffer,1);
  814.                  }
  815.                  return(2);
  816.     }        
  817.         
  818.         /* Make the return key have no effect. */
  819.         else if(letter == 0x0d) return(3);
  820.     
  821.         /* Main Circular Character Storage. */
  822.         /* Make sure that the inptr doesn't catch up with the outptr *
  823.          * If it doesn't stow it in the buffer and print it in the   *
  824.      * display window. */
  825.     else if(((inptr + 1) % CIRQSIZE != outptr % CIRQSIZE) 
  826.             && (letter != 0x08)) {
  827.             circleq[inptr] = letter;
  828.         buffer[0] = (char)(letter & 0xff);
  829.            if(letter != 0x9b) WriteConsole(cio,buffer,1);
  830.                  (++inptr) % CIRQSIZE; /* increment the inptr so the *
  831.                      * next character will go in  *
  832.                      * the right place.           */
  833.         return(0);
  834.         }
  835.         
  836.         /* If the circular Q is full... */
  837.     else if((inptr + 1) % CIRQSIZE == outptr % CIRQSIZE) {
  838.             DisplayBeep(NULL);  /* Flash the display. */
  839.         printf("Circular Q buffer is full!\n");
  840.                  return(2);
  841.     }
  842.         
  843.         /* The default (maybe the operator wanted to backspace but wasn't
  844.      * quick enough) or .... */
  845.         else 
  846.     /*(--inptr) % CIRQSIZE;*/
  847.     return(3);
  848. }
  849.     
  850. send()
  851. /* Sends one letter at a time gotten from the user after the file has
  852.  * been sent of one was. */
  853.  
  854. {
  855.         long error;
  856.     UBYTE inproc;   /* Pattern in process of being sent. */
  857.     
  858.         inproc = Lookup[circleq[outptr]];
  859.         if(circleq[outptr] == 32) space();
  860.         while((inproc) != 1){
  861.         if(01 & inproc) dah();
  862.         else dit();
  863.         inproc >>= 1;
  864.     }
  865.         charspace();
  866.         error = StartChannel(channel);
  867.         if(error)
  868.        {
  869.         printf("error starting channel = %ld\n",error);
  870.         MyCleanup();
  871.     }
  872.     return(0);
  873. }
  874.  
  875. dit()
  876. {
  877.     
  878.     PlayFreq(channel,cw.pitch,w1,cw.volume,(LONG)(1200/cw.speed),0L,0L,0L);
  879.     PlayFreq(channel,cw.pitch,w1,0L,(LONG)(1200/cw.speed),0L,0L,0L);
  880.         return(0);
  881. }
  882.  
  883. dah()
  884. {
  885.     
  886.     PlayFreq(channel,cw.pitch,w1,cw.volume,
  887.         (LONG)(3600*cw.weight/1000/ cw.speed),0L,0L,0L);
  888.     PlayFreq(channel,cw.pitch,w1,0L,(LONG)(1200/cw.speed),0L,0L,0L);
  889.         return(0);
  890. }
  891.     
  892. space()
  893. {
  894.     PlayFreq(channel,cw.pitch,w1,0L,
  895.         (LONG)(4800*cw.spacing/NORMSPACING/cw.speed),0L,0L,0L);
  896.         return(0);
  897. }    
  898. charspace()
  899. {
  900.     PlayFreq(channel,(LONG)cw.pitch,w1,0L,
  901.         (LONG)(2400*cw.spacing/NORMSPACING/cw.speed),0L,myport,1L);
  902.         return(0);
  903. }    
  904.  
  905.  
  906.  
  907. filesend(fp)
  908.  
  909. FILE *fp;
  910.  
  911. {
  912.     ULONG Signals;                     /* Wait() tells me which to look at */
  913.     ULONG MIClass;                     /* Save quickly, ReplyMsg() asap */
  914.     USHORT MICode;
  915.     APTR MIAddress;
  916.     LONG error;
  917.     int letter;
  918.     UBYTE inproc;   /* Pattern in process of being sent. */
  919.     
  920.     while((letter = getc(fp)) != EOF) {
  921.         Chk_Abort();
  922.         inproc = Lookup[letter];
  923.         if (letter == 0x0a) inproc = 0x01;
  924.     if(letter == 32) space();
  925.            while((inproc) != 1){
  926.         if(01 & inproc) dah();
  927.         else dit();
  928.         inproc >>= 1;
  929.     }
  930.         charspace();
  931.         if (error = StartChannel(channel))
  932.         {
  933.             printf("error starting channel = %ld\n",error);
  934.        MyCleanup();
  935.         }
  936. nosend:
  937.         /* Wait lets the rest of the system run,
  938.          * while this program sleeps. */
  939.         Signals = Wait((1 << myport->mp_SigBit) | 
  940.             (1 << DisplayWindow->UserPort->mp_SigBit) |
  941.           (1 << ControlWindow->UserPort->mp_SigBit));
  942.         /* now check to see to what we owe the intrusion */
  943.  
  944.         if (Signals & (1<< myport->mp_SigBit)) {
  945.            MayGetNote(myport,FALSE);
  946.            }
  947.          
  948.          
  949.         if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
  950.            /* Process the Intuition message */
  951.            while (MyIntuiMessage=(struct IntuiMessage *)
  952.                       GetMsg(ControlWindow->UserPort)) {
  953.               /* Get all the needed info and give message back */
  954.               MIClass = MyIntuiMessage->Class;
  955.               MICode = MyIntuiMessage->Code;
  956.               MIAddress = MyIntuiMessage->IAddress;
  957.               ReplyMsg(MyIntuiMessage);
  958.               /* Now, what was it you wanted? */
  959.               switch (MIClass) {
  960.                  case VANILLAKEY: /* We are accepting no input for sending
  961.                 * from the Display Window. */
  962.                     switch(MICode) {
  963.               case 0x03: /* Control C */
  964.                  MyCleanup();
  965.                  exit(0);
  966.                        case 0x18: /* Control X */
  967.                  goto finishfile;
  968.               case 0x13: /* Control S */
  969.                           ctrls = 1;
  970.                           break;
  971.               case 0x11: /* Control Q */
  972.                           ctrls = 0;
  973.                           break;
  974.                        default:
  975.                  break;
  976.            }
  977.                     break;
  978.                  case MENUPICK:
  979.                     menumessage(MICode, ControlWindow);
  980.                     break;
  981.                  case GADGETUP:         /* reply, then process */
  982.                     gadgetmessage(MIAddress, ControlWindow);
  983.                     break;
  984.                  case CLOSEWINDOW:       /* bye! */
  985.                     while (MyIntuiMessage = (struct
  986.                        IntuiMessage *) GetMsg(ControlWindow->UserPort))
  987.                        ReplyMsg(MyIntuiMessage);
  988.                     MyCleanup();
  989.                     exit(0);
  990.                     break;
  991.                  default:
  992.                     break;
  993.               }  /* switch */
  994.            } /* while */
  995.         } /* if */
  996.         if (Signals & (1<< DisplayWindow->UserPort->mp_SigBit)) {
  997.            /* Process the Intuition message */
  998.            while (MyIntuiMessage=(struct IntuiMessage *)
  999.                       GetMsg(DisplayWindow->UserPort)) {
  1000.               /* Get all the needed info and give message back */
  1001.               MIClass = MyIntuiMessage->Class;
  1002.               MICode = MyIntuiMessage->Code;
  1003.               MIAddress = MyIntuiMessage->IAddress;
  1004.               ReplyMsg(MyIntuiMessage);
  1005.               /* Now, what was it you wanted? */
  1006.               switch (MIClass) {
  1007.                  case VANILLAKEY: /* We are accepting no input for sending
  1008.                 * from the Display Window. */
  1009.                     switch(MICode) {
  1010.               case 0x03: /* Control C */
  1011.                  MyCleanup();
  1012.                  exit(0);
  1013.                        case 0x18: /* Control X */
  1014.                  goto finishfile;
  1015.               case 0x13: /* Control S */
  1016.                           ctrls = 1;
  1017.                           break;
  1018.               case 0x11: /* Control Q */
  1019.                           ctrls = 0;
  1020.                           break;
  1021.                        default:
  1022.                  break;
  1023.            }
  1024.                     break;
  1025.                  case MENUPICK:
  1026.                     menumessage(MICode, DisplayWindow);
  1027.                     break;
  1028.                  default:
  1029.                     break;
  1030.               }  /* switch */
  1031.            } /* while */
  1032.         } /* if */
  1033.         if (ctrls == 1) goto nosend;
  1034.     } /* while */
  1035. finishfile:
  1036.     fclose(fp);
  1037.     ctrls = 0;
  1038.     PlayFreq(channel,(LONG)cw.pitch,w1,0L,(LONG)(2400/cw.speed),0L,myport,2L);
  1039.     if (error = StartChannel(channel)) {
  1040.         printf("error starting channel = %ld\n",error);
  1041.         MyCleanup();
  1042.     }
  1043.     for(;;) { /* Wait until the entire file has been sent. */
  1044.         if(MayGetNote(myport,TRUE) == 2L) return(0);
  1045.     }
  1046.     return(0);
  1047. }
  1048.  
  1049. _abort()
  1050. {
  1051.    MyCleanup();
  1052.    exit(0);
  1053. }