/* This program is a CW toy for sending morse code using two * windows. * * Speech Toy was written by David M Lucas and that is what * Rob Frohne started with to create CWToy. Thanks also to Rob Peck for his * audiotools2.c without which this would probably never have * been completed. * If you find somthing you don't like, fix it! Have fun! * Thanks Amiga. */ #include "cwtoy.h" /* Revision number is used on calls to OpenLibrary * to let the system know what revision level the * program was written for. Usually refers to the * ROM release number or the release number of a * disk based library. */ #define Enable_Abort 1 #define REVISION 1 #define CONTWINDW 283 /* Overall Control Window Width/Height */ #define CONTWINDH 100 /* Pen numbers to draw gadget borders/images/text with */ #define REDP 3 /* color in register 3 once was red */ #define BLKP 2 /* color in register 2 was black */ #define WHTP 1 /* color in register 1 was white */ #define BLUP 0 /* color in register 0 was blue */ /* the length of the English and phonetic buffers */ #define NUMPROPS 4 /* number of proportional gadgets */ #define SPEEDSIZE 20 /* the number of digits in the speed */ #define StartChannel(c) ControlChannel(c, CMD_START) #define StopChannel(c) ControlChannel(c, CMD_STOP) /* Ranges of proportional data */ #define MAXWEIGHT 2000 #define MINWEIGHT 500 #define MAXSPEED 99 #define MINSPEED 3 #define MAXPITCH1 2000 #define MINPITCH1 100 #define RNGWEIGHT (MAXWEIGHT - MINWEIGHT) +1 #define RNGSPEED (MAXSPEED - MINSPEED) +1 #define RNGPITCH1 (MAXPITCH1 - MINPITCH1) +1 #define RNGVOL (MAXVOL - MINVOL) +1 #define NORMSPACING 1000 /*#define DEFWEIGHT 1000 */ /*#define DEFSPEED 20 */ /*#define DEFPITCH1 440 */ #define CIRQSIZE 4096 struct TextAttr TestFont = /* Needed for opening screen */ { (STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 }; struct Code { int speed; int pitch; int volume; int weight; int spacing; }; struct Code cw = { 20, 440, 64, 1000, 1000 }; USHORT circleq[CIRQSIZE]; /* This is the circlular Q buffer that will * allow us to edit the buffer before it is * sent if we desire. */ /* Initialize the circular Q pointers. */ int inptr = 0, outptr = 0; int ctrls = 0; /* String Gadgets ********************************************* * First the string gadgets. * 1) because the Phonetic string is refreshed programaticly * (that is, deleted and added again) quite often, and doing * this requires the use of RefreshGadgets(), and this causes * gadgets that are closer to the beginning of the list than * the gadget given to RefreshGadgets() to flicker. * 2) because they don't flicker when OTHER gadgets * (ie female/male, coming up) are deleted and added. * * These'll be used to put a nice double line border around * each of the two string gadgets. * * y,x pairs drawn as a connected line. Be sure to have an even * number of arguments (ie complete pairs). */ SHORT StrVectors[] = { 0, 0, 160, 0, 160, 13, 0, 13, 0, 1, 159, 1, 159, 12, 1, 12, 1, 1 }; struct Border StrBorder = { -4, -3, /* initial offsets, gadget relative */ WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */ 9, /* number of vectors */ StrVectors, /* pointer to the actual array of vectors */ NULL /* no next Border, can point to another border */ }; /* The same undo buffer is used for both string gadgets, * this is sized to largest so that largest fits. */ UBYTE UndoBuffer[SPEEDSIZE]; /* Speed Gadget is where the speed will be displayed. */ /* default text */ UBYTE Speed[SPEEDSIZE] = "20 Words per Minute"; UBYTE Space[2] = " "; struct StringInfo EnglInfo = { Speed, /* pointer to I/O buffer */ UndoBuffer, /* pointer to undo buffer */ 0, /* buffer position */ SPEEDSIZE, /* max number of chars, including NULL */ 0, 0, /* first char in display, undo positions */ 20, /* number of chars (currently) in the buffer */ 0, 0, 0, /* position variables calculated by Intuition */ NULL, /* no pointer to RastPort */ 0, /* not a LongInt string gadget */ NULL /* no pointer to alternate keymap */ }; struct IntuiText EnglText = { WHTP, BLUP, /* FrontPen, BackPen */ JAM1, /* DrawMode */ 0, -13, /* LeftEdge, TopEdge (relative to gadget) */ &TestFont, /* pointer to TextFont */ (UBYTE *) "Speed:", /* pointer to Text */ NULL /* no pointer to NextText */ }; struct Gadget SpeedGadget = { NULL, /* pointer to Next Gadget */ 11, 63, 290, 10, /* (Left Top Width Height) Hit Box */ GADGHCOMP, /* Flags */ RELVERIFY, /* Activation flags */ STRGADGET, /* Type */ (APTR)&StrBorder, /* pointer to Border Image */ NULL, /* no pointer to SelectRender */ &EnglText, /* pointer to GadgetText */ 0, /* no MutualExclude */ (APTR)&EnglInfo, /* pointer to SpecialInfo */ 0, /* no ID */ NULL /* no pointer to special data */ }; /* Now the proportional gadgets. */ /* Proportional Gadgets **************************************/ /* The following variables are used to create proportional * Gadgets. These variables will be filled in with copies of * the generic Gadgetry below. */ SHORT PropCount = 0; /* index to next available Gadget */ struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */ /* dummy AUTOKNOB Images are required */ struct Image PImages[NUMPROPS]; /* These get copies of TPropInfo */ struct PropInfo PInfos[NUMPROPS]; /* These get copies of TPropGadget */ struct Gadget Props[NUMPROPS]; struct IntuiText TPropText = { WHTP, BLUP, /* FrontPen, BackPen */ JAM1, /* DrawMode */ 0, -10, /* LeftEdge, TopEdge (relative to gadget) */ &TestFont, /* pointer to TextFont */ NULL, /* pointer to Text is filled at runtime */ NULL /* no pointer to NextText */ }; struct PropInfo TPropInfo = { AUTOKNOB | FREEHORIZ, /* Flags */ 0, 0, /* Pots: Horiz, Vert: both start at 0 */ 0x1FFF, 0x1FFF, /* Bodies: Horiz is 1/8, Vert is 1/8 */ 0, 0, 0, 0, 0, 0 /* System usage stuff */ }; /* this is the template for the Gadget of a horizontal */ /* Proportional Gadget */ struct Gadget TPropGadget = { &SpeedGadget, /* pointer to NextGadget */ 7, 12, 115, 10, /* Select Box L T W H */ GADGHCOMP | GADGIMAGE, /* Flags */ GADGIMMEDIATE | RELVERIFY, /* Activation flags */ PROPGADGET, /* Type */ NULL, /* pointer to Image filled in later */ NULL, /* no pointer to SelectRender */ NULL, /* no pointer to GadgetText */ 0, /* no MutualExclude */ NULL, /* SpecialInfo proportional data filled later */ 0, /* no ID */ NULL /* no pointer to special data */ }; struct IntuitionBase *IntuitionBase = 0; struct GfxBase *GfxBase = 0; /* Only one menu. */ ULONG MenuNumber; ULONG TheMenu; ULONG TheItem; struct IntuiText MenuItemText = { BLUP, /* Front Pen */ WHTP, /* Back pen */ JAM2, /* Draw Mode */ 0, /* Left Edge */ 0, /* Top */ &TestFont, /* pointer to TextFont */ (UBYTE *) "About CW Toy...", /* text */ NULL /* next */ }; struct MenuItem MyMenuItem = { NULL, /* pointer to next item */ 0, /* left */ 0, /* top */ 150, /* width */ 8, /* height */ ITEMTEXT | ITEMENABLED | HIGHCOMP, /* flags */ 0, /* no mutual exclude */ (APTR)&MenuItemText, /* Render */ NULL, /* pointer to alternate image */ NULL, /* Command "amiga" char */ NULL, /* Sub Item */ MENUNULL /* nextselect */ }; struct Menu MyMenu = { NULL, /* pointer to next menu */ 0,0,150,0, /* left,0,Width,0 */ MENUENABLED, /* flags */ (BYTE *) "CW Toy Menu", /* menu name */ &MyMenuItem /* First Item in list */ }; struct IntuiText ReqText1 = { BLUP, /* Front Pen */ WHTP, /* Back pen */ JAM2, /* Draw Mode */ 5, /* Left Edge */ 23, /* Top */ &TestFont, /* pointer to TextFont */ (UBYTE *) "Version 1.0 30 June, 1991", /* text */ NULL /* next */ }; struct IntuiText ReqText2 = { BLUP, /* Front Pen */ WHTP, /* Back pen */ JAM2, /* Draw Mode */ 5, /* Left Edge */ 13, /* Top */ &TestFont, /* pointer to TextFont */ (UBYTE *) "Freeware - Public Domain ", /* text */ &ReqText1 /* next */ }; struct IntuiText ReqText3 = { BLUP, /* Front Pen */ WHTP, /* Back pen */ JAM2, /* Draw Mode */ 5, /* Left Edge */ 3, /* Top */ &TestFont, /* pointer to TextFont */ (UBYTE *) "By Rob Frohne (KL7NA)", /* text */ &ReqText2 /* next */ }; struct IntuiText OKIText = { BLUP, WHTP, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 6, 3, /* LeftEdge, TopEdge (relative to gadget) */ &TestFont, /* pointer to TextFont */ (UBYTE *) "OK", /* pointer to Text */ NULL /* no pointer to NextText */ }; struct Requester *AboutRequester; USHORT autoret; struct Window *ControlWindow = NULL; struct IntuiMessage *MyIntuiMessage; struct NewWindow NewControlWindow = { 00, 11, /* start LeftEdge, TopEdge */ CONTWINDW, CONTWINDH, /* start Width, Height */ -1, -1, /* DetailPen, BlockPen */ GADGETUP | CLOSEWINDOW | MENUPICK | VANILLAKEY, /* IDCMP FLAGS */ WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | GIMMEZEROZERO | ACTIVATE,/* Flags (can be NULL) */ &Props[NUMPROPS-1], /* Pointer to FirstGadget */ NULL, /* no pointer to first CheckMark */ (UBYTE *) "CW Toy", /* Title (can be NULL) */ NULL, /* no Pointer to Screen */ NULL, /* no Pointer to BitMap */ 20, 20, /* Min/max Sizable to (w/h) */ CONTWINDW, CONTWINDH, /* These aint used, can't size */ WBENCHSCREEN /* Type of screen window appears in */ }; struct NewWindow NewDisplayWindow = { 00,(CONTWINDH + 10), CONTWINDW,50, -1,-1, MENUPICK|VANILLAKEY, /* IDCMP FLAGS */ GIMMEZEROZERO|ACTIVATE|WINDOWSIZING|WINDOWDEPTH|WINDOWDRAG|REFRESHWINDOW, 0, NULL, (UBYTE *) "CW Buffer", NULL, NULL, 10,10,700,440, WBENCHSCREEN }; /* Some audio stuff for Rob Peck's Audio Tools. */ extern char *w1; extern int ControlChannel(); extern struct MsgPort *InitAudio(); struct MsgPort *myport; /* CHANGE from article */ LONG channel; /* Some stuff for the Console. */ extern struct ConIOBlocks *CreateConsole(); struct ConIOBlocks *cio; struct Window *DisplayWindow, *OpenWindow(); /** start of code ***************************/ main( argc, argv ) int argc; char *argv[]; { ULONG Signals; /* Wait() tells me which to look at */ ULONG MIClass; /* Save quickly, ReplyMsg() asap */ USHORT MICode; APTR MIAddress; LONG error; int i,j,k,goaway = 0; char numspeed[SPEEDSIZE]; FILE *fp, *fopen(); fp = 0; /* Initialize fp */ /* check for a question mark as the first argument */ if ( argv[1][0] == '?' ) { printf("Usage: %s [message] [-f filename] [-e] [-s speed] [-p pitch] [-v volume] [-w weighting]\n [-b spaceing]\n", argv[0] ); exit(0); } /* end of checking for a question mark */ /* Parse the input line */ for ( i=1; i < argc; i++ ) { /* see if it starts with a minus (then s,p,v,w,f) */ if ( argv[i][0] != '-' ) { /* Get the message if it is there. */ for ( j=0; argv[i][j] != '\0'; j++ ) circleq[inptr++] = argv[i][j]; circleq[inptr++] = 0x20; } else { /* Parse the switches. */ switch( argv[i][1] ) { case 'f' : /* File to send. */ if ((fp = fopen(argv[++i],"r")) == NULL) { printf("cwtoy: can't open %s\n",argv[++i]); exit(1); } break; case 'e' : /* Exit after sending message of file. */ goaway = 1; break; case 's' : /* Speed */ cw.speed = atoi(argv[++i]); ftoa((double)cw.speed,numspeed,0,1); if(cw.speed < 10) strcat(numspeed,Space); strcat(numspeed,(Speed + 2)); strcpy(Speed,numspeed); break; case 'p' : /* Pitch */ cw.pitch = atoi(argv[++i]); break; case 'v' : /* Volume */ cw.volume = atoi(argv[++i]); break; case 'w' : /* Weighting */ cw.weight = atoi(argv[++i]); break; case 'b' : /* Spacingfactor */ cw.spacing = atoi(argv[++i]); break; default : printf("Usage: %s [message] [-f filename] [-e] [-s speed] [-p pitch] [-v volume] [-w weighting]\n [-b spaceing]\n", argv[0] ); exit(0); break; } /* end of switch for the arguments */ } /* end of checking for a switch argument */ } /* First initialize the audio routines using Rob Peck's Audio Tools. */ myport = InitAudio(); /* now returns address of message port */ if(myport == 0) { printf("Problem in InitAudio!\n"); MyCleanup(); } { channel = GetChannel(-1); if(channel == -1) { printf("cannot get a channel!\n"); MyCleanup(); } error = StopChannel(channel); if(error) { printf("error in stopping channel = %ld\n",error); MyCleanup(); } } /* Open those libraries that the program uses directly */ if ((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", REVISION)) == 0) { MyCleanup(); exit(1); } if ((GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", REVISION)) == 0) { MyCleanup(); exit(1); } /* This is where the proportional gadgets are set up, using * the templates that were declared staticly. */ for(PropCount = 0; PropCount < NUMPROPS; PropCount++) { PTexts[PropCount] = TPropText; Props[PropCount] = TPropGadget; PInfos[PropCount] = TPropInfo; Props[PropCount].GadgetText = (struct IntuiText *) &PTexts[PropCount]; Props[PropCount].GadgetRender = (APTR) &PImages[PropCount]; Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount]; switch (PropCount) { case 0: PTexts[PropCount].IText = (UBYTE *) "Weighting:"; if (cw.weight == MAXWEIGHT) PInfos[PropCount].HorizPot = 65535; else PInfos[PropCount].HorizPot = ((cw.weight - MINWEIGHT) << 16) / (MAXWEIGHT - MINWEIGHT); break; case 1: PTexts[PropCount].IText = (UBYTE *) "Speed:"; Props[PropCount].TopEdge += 22; Props[PropCount].NextGadget = &Props[PropCount-1]; if (cw.speed == MAXSPEED ) PInfos[PropCount].HorizPot = 65535; else PInfos[PropCount].HorizPot = ((cw.speed - MINSPEED) << 16) / (MAXSPEED - MINSPEED); break; case 2: PTexts[PropCount].IText = (UBYTE *) "Pitch:"; Props[PropCount].LeftEdge += 145; Props[PropCount].NextGadget = &Props[PropCount-1]; if (cw.pitch == MAXPITCH1) PInfos[PropCount].HorizPot = 65535; else PInfos[PropCount].HorizPot = ((cw.pitch - MINPITCH1) << 16) / (MAXPITCH1 - MINPITCH1); break; case 3: PTexts[PropCount].IText = (UBYTE *) "Volume:"; Props[PropCount].TopEdge += 22; Props[PropCount].LeftEdge += 145; Props[PropCount].NextGadget = &Props[PropCount-1]; if (cw.volume == MAXVOL) PInfos[PropCount].HorizPot = 65535; else PInfos[PropCount].HorizPot = ((cw.volume - MINVOL) << 16) / (MAXVOL - MINVOL); break; default: break; } } if ((ControlWindow = (struct Window *)OpenWindow (&NewControlWindow)) == NULL) { MyCleanup(); exit(1); } if ((DisplayWindow = OpenWindow(&NewDisplayWindow)) == NULL) { MyCleanup(); exit(1); } if ((cio=CreateConsole(DisplayWindow)) == 0) { MyCleanup(); } /* fill background of window */ SetAPen(ControlWindow->RPort, BLKP); RectFill(ControlWindow->RPort,0L,0L, (LONG)ControlWindow->GZZWidth, (LONG)ControlWindow->GZZHeight); RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL); SetMenuStrip(ControlWindow, &MyMenu); SetMenuStrip(DisplayWindow, &MyMenu); if (fp != 0) { /* If we opened a file to send, send it first! */ filesend(fp); if (goaway == 1) { MyCleanup(); exit(0); } } if (inptr > 0) send(); /* Got a -m message to start already! */ /* !!! Ah, But what if Control Window's not been opened? */ /* Rob changed some tricky stuff here! */ for (;;) { /* ever wait for a signal and process it */ /* wait lets the rest of the system run, */ /* this program sleeps */ Signals = Wait((1 << myport->mp_SigBit) | (1 << DisplayWindow->UserPort->mp_SigBit) | (1 << ControlWindow->UserPort->mp_SigBit)); /* now check to see to what we owe the intrusion */ Chk_Abort(); if (Signals & (1<< myport->mp_SigBit)) { if(MayGetNote(myport,FALSE) == 1L) { ++outptr % CIRQSIZE; /* Always increment the outptr after we are * done sending a character. */ /* If not caught up and no pause in effect, send the next one. */ if (inptr != outptr) { if (ctrls == 0) send(); } else { if (goaway == 1) { MyCleanup(); exit(0); } } } } if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) { /* Process the Intuition message */ while (MyIntuiMessage=(struct IntuiMessage *) GetMsg(ControlWindow->UserPort)) { /* Get all the needed info and give message back */ MIClass = MyIntuiMessage->Class; MICode = MyIntuiMessage->Code; MIAddress = MyIntuiMessage->IAddress; ReplyMsg(MyIntuiMessage); /* Now, what was it you wanted? */ switch (MIClass) { case VANILLAKEY: /* Service the character buffer. */ switch(qUp(MICode)) { case 0: /* If we are caught up * initialize the sending. * (Remember that qUp * incremented inptr.) */ if((inptr % CIRQSIZE == (outptr + 1) % CIRQSIZE) && (ctrls == 0)) send(); break; case 1: /* Check for Control C. */ exit(0); case 2: case 3: case 4: break; } break; case MENUPICK: menumessage(MICode, ControlWindow); break; case GADGETUP: /* reply, then process */ gadgetmessage(MIAddress, ControlWindow); break; case CLOSEWINDOW: /* bye! */ while (MyIntuiMessage = (struct IntuiMessage *) GetMsg(ControlWindow->UserPort)) ReplyMsg(MyIntuiMessage); MyCleanup(); exit(0); default: break; } /* switch */ } /* while */ } /* if */ if (Signals & (1<< DisplayWindow->UserPort->mp_SigBit)) { /* Process the Intuition message */ while (MyIntuiMessage=(struct IntuiMessage *) GetMsg(DisplayWindow->UserPort)) { /* Get all the needed info and give message back */ MIClass = MyIntuiMessage->Class; MICode = MyIntuiMessage->Code; MIAddress = MyIntuiMessage->IAddress; ReplyMsg(MyIntuiMessage); /* Now, what was it you wanted? */ switch (MIClass) { case VANILLAKEY: /* Service the character buffer. */ /* For comments see similar section under ControlWindow. */ switch(qUp(MICode)) { case 0: if((inptr % CIRQSIZE == (outptr + 1) % CIRQSIZE) && (ctrls == 0)) send(); break; case 1: exit(0); case 2: case 3: case 4: break; } break; case MENUPICK: menumessage(MICode, DisplayWindow); break; default: break; } /* switch */ } /* while */ } /* if */ }/* for */ } /* main */ /* a MENUPICK has been received, this * routine takes the appropriate action */ menumessage(code, w) USHORT code; struct Window *w; { switch (MENUNUM(code)) { case 0: switch (ITEMNUM(code)) { case 0: AutoRequest(w, &ReqText3, NULL, &OKIText, 0, 0, 280, 47); break; } break; } return(0); } /* a GADGETUP has been received, this * routine takes the appropriate action */ gadgetmessage(address, w) APTR address; struct Window *w; { long PropRange; UBYTE i; int length; char numspeed[SPEEDSIZE]; if (address == (APTR)&Props[2]) { PropRange = RNGPITCH1; cw.pitch = (((PInfos[2].HorizPot >> 1) * PropRange) >> 15) + MINPITCH1; } else if (address == (APTR)&Props[3]) { PropRange = RNGVOL; cw.volume = (((PInfos[3].HorizPot >> 1) * PropRange) >> 15) + MINVOL; } else if (address == (APTR)&Props[0]) { PropRange = RNGWEIGHT; cw.weight = (( (PInfos[0].HorizPot >> 1) * PropRange) >> 15) + MINWEIGHT; } /* Since the program changes the contents of the string * gadgets' buffer and it's size, which is something else * intuition doesn't expect a program (as opposed to the * user) to do. The program must remove, then change, then * add this gadget, and then by passing the address of this * gadget to RefreshGadgets(), only the gadgets from here * to the start of the list will be refreshed, which * minimizes the visible flash that RefreshGadgets() can * introduce. */ else if (address == (APTR)&Props[1]) { PropRange = RNGSPEED ; cw.speed = (((PInfos[1].HorizPot >> 1) * PropRange) >> 15) + MINSPEED; i = RemoveGadget(ControlWindow, &SpeedGadget); /* if((length = stci_d(numspeed, cw.speed)) < 4) { if(length < 3) strcat(numspeed,Space); strcat(numspeed,(Speed + 2)); strcpy(Speed,numspeed); } */ /* This was commented out to modify it to Manx. */ /* The 3 lines below were added to make it Manx compatible. */ ftoa((double)cw.speed,numspeed,0,1); if(cw.speed < 10) strcat(numspeed,Space); strcat(numspeed,(Speed + 2)); strcpy(Speed,numspeed); /* The 3 lines above this were added to make it Manx compatible. */ AddGadget(ControlWindow, &SpeedGadget, i); RefreshGadgets(&SpeedGadget, ControlWindow, NULL); } return(0); } /* Deallocate any memory, and close all of the * windows/screens/devices/libraries in reverse order to * make things work smoothly. And be sure to check * that the open/allocation was successful before * closing/deallocating. */ MyCleanup() { FinishAudio(myport); /* NEW parameter for FinishAudio */ if (myport != 0) DeletePort(myport); if (cio != 0) DeleteConsole(cio); if (DisplayWindow != NULL) CloseWindow(DisplayWindow); if (ControlWindow != NULL) CloseWindow(ControlWindow); /* freeimages makes sure image allocation was successful */ if (GfxBase != 0) CloseLibrary(GfxBase); if (IntuitionBase != 0) CloseLibrary(IntuitionBase); return(0); } UBYTE Lookup[] = {0x01, 0x6, 0x11, 0x15, 0x09, 0x02, 0x14, 0x0b, 0x10, 0x04, 0x1e, 0x0d, 0x12, 0x07, 0x05, 0x0f, 0x16, 0x1b, 0x0a, 0x08, 0x03, 0x0c, 0x18, 0x0e, 0x19, 0x1d, 0x13, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x52, 0x01, 0xc8, 0x01, 0x01, 0x5d, 0x2d, 0x6d, 0x22, 0x2a, 0x73, 0x61, 0x6a, 0x29, 0x3f, 0x3e, 0x3c, 0x38, 0x30, 0x20, 0x21, 0x23, 0x27, 0x2f, 0x47, 0x55, 0x01, 0x31, 0x01, 0x4c, 0x01, 0x06, 0x11, 0x15, 0x09, 0x02, 0x14, 0x0b, 0x10, 0x04, 0x1e, 0x0d, 0x12, 0x07, 0x05, 0x0f, 0x16, 0x1b, 0x0a, 0x08, 0x03, 0x0c, 0x18, 0x0e, 0x19, 0x1d, 0x13, 0x2d, 0x29, 0x6d, 0x01, 0xac, 0x01, 0x06, 0x11, 0x15, 0x09, 0x02, 0x14, 0x0b, 0x10, 0x04, 0x1e, 0x0d, 0x12, 0x07, 0x05, 0x0f, 0x16, 0x1b, 0x0a, 0x08, 0x03, 0x0c, 0x18, 0x0e, 0x19, 0x1d, 0x13, 0x2d, 0x29, 0x6d, 0x01, 0x01}; int qUp(letter) /* qUp is the only place that inptr should ever change! */ USHORT letter; { char buffer[1]; /* Check for backspace and that we can backup. */ if( (letter == 0x08) && (inptr % CIRQSIZE != (outptr + 1) % CIRQSIZE) && (inptr != outptr) && (inptr % CIRQSIZE != (outptr -1) % CIRQSIZE) ) { (--inptr) % CIRQSIZE; /*(--inptr) % CIRQSIZE;*/ buffer[0] = (char)(letter & 0xff); /* Backspace in the * DisplayWindow. */ if(letter != 0x9b) WriteConsole(cio,buffer,1); return(2); } /* Check for Control C. If so, blow it away. */ else if(letter == 0x03) { MyCleanup(); return(1); } /* Control S will pause the sending and control Q * will resume it where it left off. */ /* Control S */ else if(letter == 0x13) { ctrls = 1; return(2); } /* Control Q */ else if(letter == 0x11) { ctrls = 0; if(inptr != outptr) send(); return(2); } /* Check for Control X. If so clear the circlular Q. */ else if(letter == 0x18) { /* How do we handle the wrap around? */ while (inptr % CIRQSIZE != (outptr + 1) % CIRQSIZE) { (--inptr) % CIRQSIZE; buffer[0] = (char)(0x08 & 0xff); if(letter != 0x9b) WriteConsole(cio,buffer,1); } return(2); } /* Make the return key have no effect. */ else if(letter == 0x0d) return(3); /* Main Circular Character Storage. */ /* Make sure that the inptr doesn't catch up with the outptr * * If it doesn't stow it in the buffer and print it in the * * display window. */ else if(((inptr + 1) % CIRQSIZE != outptr % CIRQSIZE) && (letter != 0x08)) { circleq[inptr] = letter; buffer[0] = (char)(letter & 0xff); if(letter != 0x9b) WriteConsole(cio,buffer,1); (++inptr) % CIRQSIZE; /* increment the inptr so the * * next character will go in * * the right place. */ return(0); } /* If the circular Q is full... */ else if((inptr + 1) % CIRQSIZE == outptr % CIRQSIZE) { DisplayBeep(NULL); /* Flash the display. */ printf("Circular Q buffer is full!\n"); return(2); } /* The default (maybe the operator wanted to backspace but wasn't * quick enough) or .... */ else /*(--inptr) % CIRQSIZE;*/ return(3); } send() /* Sends one letter at a time gotten from the user after the file has * been sent of one was. */ { long error; UBYTE inproc; /* Pattern in process of being sent. */ inproc = Lookup[circleq[outptr]]; if(circleq[outptr] == 32) space(); while((inproc) != 1){ if(01 & inproc) dah(); else dit(); inproc >>= 1; } charspace(); error = StartChannel(channel); if(error) { printf("error starting channel = %ld\n",error); MyCleanup(); } return(0); } dit() { PlayFreq(channel,cw.pitch,w1,cw.volume,(LONG)(1200/cw.speed),0L,0L,0L); PlayFreq(channel,cw.pitch,w1,0L,(LONG)(1200/cw.speed),0L,0L,0L); return(0); } dah() { PlayFreq(channel,cw.pitch,w1,cw.volume, (LONG)(3600*cw.weight/1000/ cw.speed),0L,0L,0L); PlayFreq(channel,cw.pitch,w1,0L,(LONG)(1200/cw.speed),0L,0L,0L); return(0); } space() { PlayFreq(channel,cw.pitch,w1,0L, (LONG)(4800*cw.spacing/NORMSPACING/cw.speed),0L,0L,0L); return(0); } charspace() { PlayFreq(channel,(LONG)cw.pitch,w1,0L, (LONG)(2400*cw.spacing/NORMSPACING/cw.speed),0L,myport,1L); return(0); } filesend(fp) FILE *fp; { ULONG Signals; /* Wait() tells me which to look at */ ULONG MIClass; /* Save quickly, ReplyMsg() asap */ USHORT MICode; APTR MIAddress; LONG error; int letter; UBYTE inproc; /* Pattern in process of being sent. */ while((letter = getc(fp)) != EOF) { Chk_Abort(); inproc = Lookup[letter]; if (letter == 0x0a) inproc = 0x01; if(letter == 32) space(); while((inproc) != 1){ if(01 & inproc) dah(); else dit(); inproc >>= 1; } charspace(); if (error = StartChannel(channel)) { printf("error starting channel = %ld\n",error); MyCleanup(); } nosend: /* Wait lets the rest of the system run, * while this program sleeps. */ Signals = Wait((1 << myport->mp_SigBit) | (1 << DisplayWindow->UserPort->mp_SigBit) | (1 << ControlWindow->UserPort->mp_SigBit)); /* now check to see to what we owe the intrusion */ if (Signals & (1<< myport->mp_SigBit)) { MayGetNote(myport,FALSE); } if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) { /* Process the Intuition message */ while (MyIntuiMessage=(struct IntuiMessage *) GetMsg(ControlWindow->UserPort)) { /* Get all the needed info and give message back */ MIClass = MyIntuiMessage->Class; MICode = MyIntuiMessage->Code; MIAddress = MyIntuiMessage->IAddress; ReplyMsg(MyIntuiMessage); /* Now, what was it you wanted? */ switch (MIClass) { case VANILLAKEY: /* We are accepting no input for sending * from the Display Window. */ switch(MICode) { case 0x03: /* Control C */ MyCleanup(); exit(0); case 0x18: /* Control X */ goto finishfile; case 0x13: /* Control S */ ctrls = 1; break; case 0x11: /* Control Q */ ctrls = 0; break; default: break; } break; case MENUPICK: menumessage(MICode, ControlWindow); break; case GADGETUP: /* reply, then process */ gadgetmessage(MIAddress, ControlWindow); break; case CLOSEWINDOW: /* bye! */ while (MyIntuiMessage = (struct IntuiMessage *) GetMsg(ControlWindow->UserPort)) ReplyMsg(MyIntuiMessage); MyCleanup(); exit(0); break; default: break; } /* switch */ } /* while */ } /* if */ if (Signals & (1<< DisplayWindow->UserPort->mp_SigBit)) { /* Process the Intuition message */ while (MyIntuiMessage=(struct IntuiMessage *) GetMsg(DisplayWindow->UserPort)) { /* Get all the needed info and give message back */ MIClass = MyIntuiMessage->Class; MICode = MyIntuiMessage->Code; MIAddress = MyIntuiMessage->IAddress; ReplyMsg(MyIntuiMessage); /* Now, what was it you wanted? */ switch (MIClass) { case VANILLAKEY: /* We are accepting no input for sending * from the Display Window. */ switch(MICode) { case 0x03: /* Control C */ MyCleanup(); exit(0); case 0x18: /* Control X */ goto finishfile; case 0x13: /* Control S */ ctrls = 1; break; case 0x11: /* Control Q */ ctrls = 0; break; default: break; } break; case MENUPICK: menumessage(MICode, DisplayWindow); break; default: break; } /* switch */ } /* while */ } /* if */ if (ctrls == 1) goto nosend; } /* while */ finishfile: fclose(fp); ctrls = 0; PlayFreq(channel,(LONG)cw.pitch,w1,0L,(LONG)(2400/cw.speed),0L,myport,2L); if (error = StartChannel(channel)) { printf("error starting channel = %ld\n",error); MyCleanup(); } for(;;) { /* Wait until the entire file has been sent. */ if(MayGetNote(myport,TRUE) == 2L) return(0); } return(0); } _abort() { MyCleanup(); exit(0); }