/* * * DISCLAIMER: * * This program is provided as a service to the programmer * community to demonstrate one or more features of the Amiga * personal computer. These code samples may be freely used * for commercial or noncommercial purposes. * * Commodore Electronics, Ltd ("Commodore") makes no * warranties, either expressed or implied, with respect * to the program described herein, its quality, performance, * merchantability, or fitness for any particular purpose. * This program is provided "as is" and the entire risk * as to its quality and performance is with the user. * Should the program prove defective following its * purchase, the user (and not the creator of the program, * Commodore, their distributors or their retailers) * assumes the entire cost of all necessary damages. In * no event will Commodore be liable for direct, indirect, * incidental or consequential damages resulting from any * defect in the program even if it has been advised of the * possibility of such damages. Some laws do not allow * the exclusion or limitation of implied warranties or * liabilities for incidental or consequential damages, * so the above limitation or exclusion may not apply. * */ /* "SIMPLE" demo showing the use of the Intuition windowing system. * * Opens a graphics-window, that is also a console window. When you click * in the console window, it echos what you type. RETURN key issues * both a carriage return and a line feed. When you click in the * Graphics window, the console window reports the kinds of events * that the graphics window IDCMP is seeing, except, of course for * the CLOSEWINDOW gadget that causes a program exit. Note that a * user will generally have either an IDCMP or a Console attached * to a window, but not necessarily both. (Or if both, then that * window won't usually ask for RAWKEYS, to allow the console to * translate them for normal reporting.) * * No menu stuff is included, but the event handling is included * for menu picks within the HandleEvent() function. * * Additionally, shows how to trap the right hand mouse button * events for any given active window. * * Author: Rob Peck, 12/18/85 */ /* DEFINES ********************************************************** */ #define HOWMUCHTIME 40000 #define SECONDS io_Actual #define MICROSECONDS io_Length #define DEPTH 5 #define WINDOWGADGETS (WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE) #define INTUITION_MESSAGE (1<RPort; /* set a rastport pointer for both windows */ /* create ports and messages for communicating with the console */ consoleWritePort = CreatePort("my.con.write",0); if(consoleWritePort == 0) { problem = 5; goto cleanup5; } consoleWriteMsg = CreateStdIO(consoleWritePort); if(consoleWritePort == 0) { problem = 6; goto cleanup6; } consoleReadPort = CreatePort("my.con.read",0); if(consoleReadPort == 0) { problem = 7; goto cleanup7; } consoleReadMsg = CreateStdIO(consoleReadPort); if(consoleReadPort == 0) { problem = 8; goto cleanup8; } /* now attach a console to the window provided for its use */ error = OpenConsole(consoleWriteMsg,consoleReadMsg,wG); if(error != 0) { problem = 10; goto cleanup10; } /* attach a console to this window, initialize * for both write and read */ /* Initialize the timer */ if (init_timer(timermsg) != 0) goto cleanup10; /* ask for the first timing interval */ /* 40,000 microseconds = .04 sec */ set_timer(timermsg,0,HOWMUCHTIME); /* tell console where to put a character that * it wants to give me queue up first read */ QueueRead(consoleReadMsg,&letter); /* reset the top offset to leave room for graphics */ ConPutStr(consoleWriteMsg,&topoffset[0]); /* reset the number of lines on the page for text */ ConPutStr(consoleWriteMsg,&linesonpage[0]); ConWrite(consoleWriteMsg,"\fHello, World\r\n",15); ConWrite(consoleWriteMsg,"I will echo what\r\n you type\r\n",-1); /* (use the variable length ... -1 ... function of ConWrite) */ ConWrite(consoleWriteMsg,"Hit close gadget\r\n to exit",-1); /* find out which signals to wait for.... Intuition allocates a signal bit * for an IDCMP and the call to OpenConsole allocates a different bit */ consoleReadBit = consoleReadPort->mp_SigBit; intuitionMsgBit = wG->UserPort->mp_SigBit; timerMsgBit = timerport->mp_SigBit; /* this code assumes that the only events we expect to wake up for are * characters typed to the console or messages from intuition arriving at * the IDCMP */ /* Wait for a CLOSEWINDOW or other event from intuition as well as * waiting for a typed character */ do { wakeupmask = Wait( INTUITION_MESSAGE | TYPED_CHARACTER | TIME_OUT ); /* if an intuition message, copy the contents of the * message to some global variables (our own local * copy of the message) and reply immediately */ if(wakeupmask & INTUITION_MESSAGE) { while( (message = (struct IntuiMessage *) GetMsg(wG->UserPort) ) != NULL) { /* EMPTY THE PORT!!!! */ /* make a local copy of the * message before replying, and * then try to handle the event */ class = message->Class; code = message->Code; qualifier = message->Qualifier; address = message->IAddress; ReplyMsg(message); if(HandleEvent() == FALSE) break; } } if(wakeupmask & TYPED_CHARACTER) { /* Task woke up because a message arrived * at this port, so we must remove the * message from the port to allow its reuse */ GetMsg(consoleReadPort); /* Console character was read into 'letter' */ ConPutChar(consoleWriteMsg,letter); if(letter == '\r') ConPutChar(consoleWriteMsg,'\n'); /* added a line feed to a carriage return */ /* Now that have typed the character, must * send off another read request */ QueueRead(consoleReadMsg, &letter); } if(wakeupmask & TIME_OUT) { /* Task woke up because of a timeout; that * is, the timer completed and returned its * message to the reply port */ GetMsg(timerport); drawSomething(wG); set_timer(timermsg,0,HOWMUCHTIME); } } while (HandleEvent()); /* keep going as long as * HandleEvent returns nonzero */ problem = 0; AbortIO(consoleReadMsg); /* cancel the last queued read */ CloseConsole(consoleWriteMsg); cleanup10: cleanup8: DeleteStdIO(consoleReadMsg); cleanup7: DeletePort(consoleReadPort); cleanup6: DeleteStdIO(consoleWriteMsg); cleanup5: DeletePort(consoleWritePort); cleanup3: CloseWindow(wG); cleanup2: if (GfxBase != NULL) CloseLibrary(GfxBase); AbortIO(timermsg); DeleteStdIO(timermsg); cleanup1a: DeletePort(timerport); cleanup1: if (IntuitionBase != NULL) CloseLibrary(IntuitionBase); if(problem > 0) exit(problem+1000); else return(0); } drawSomething(w) struct Window *w; { struct RastPort *rp; SHORT xsize, ysize; rp = w->RPort; xsize = w->Width; /* use current size limits for the window */ ysize = (w->Height)/2; /* draw only in top half of window */ SetAPen(rp,RangeRand(4)); /* can even draw in background color */ Move(rp, RangeRand(xsize), RangeRand(ysize)); Draw(rp, RangeRand(xsize), RangeRand(ysize)); return(0); } HandleEvent() { switch(class) { case CLOSEWINDOW: return(FALSE); /* cleanup and exit if close * gadget is hit */ break; /* could have provided processing for each of these */ case RAWKEY: ConPutStr(consoleWriteMsg,"\n\rRAWKEY event:\n\r"); ConPutStr(consoleWriteMsg,"value = "); ConPutChar(consoleWriteMsg, (tohex((code & 0xf0)>>4))); ConPutChar(consoleWriteMsg,(tohex(code & 0x0f))); break; case GADGETUP: break; /* event not in use */ case GADGETDOWN: break; /* event not in use */ case MOUSEBUTTONS: ConPutStr(consoleWriteMsg,"\n\rMOUSEBUTTONS event="); switch(code) { case SELECTDOWN: ConPutStr(consoleWriteMsg,"\n\rSELECTDOWN\n\r"); break; case SELECTUP: ConPutStr(consoleWriteMsg,"\n\rSELECTUP\n\r"); break; case MENUDOWN: ConPutStr(consoleWriteMsg, "\n\rMENUDOWN\n\r"); break; case MENUUP: ConPutStr(consoleWriteMsg, "\n\rMENUUP\n\r"); break; } } class = 0; code = 0; qualifier = 0; address = 0; return(TRUE); } /* These functions are taken directly from the console.device chapter * in the Amiga V1.1 ROM KERNEL manual. */ /* Open a console device */ /* this function returns a value of 0 if the console * device opened correctly and a nonzero value (the error * returned from OpenDevice) if there was an error. */ int OpenConsole(writerequest,readrequest,window) struct IOStdReq *writerequest; struct IOStdReq *readrequest; struct Window *window; { int error; writerequest->io_Data = (APTR) window; writerequest->io_Length = sizeof(*window); error = OpenDevice("console.device", 0, writerequest, 0); readrequest->io_Device = writerequest->io_Device; readrequest->io_Unit = writerequest->io_Unit; /* clone required parts of the request */ return(error); } /* Output a single character to a specified console */ int ConPutChar(request,character) struct IOStdReq *request; char character; { request->io_Command = CMD_WRITE; request->io_Data = (APTR)&character; request->io_Length = 1; DoIO(request); /* command works because DoIO blocks until command is * done (otherwise pointer to the character could become * invalid in the meantime). */ return(0); } /* Output a stream of known length to a console */ int ConWrite(request,string,length) struct IOStdReq *request; char *string; int length; { request->io_Command = CMD_WRITE; request->io_Data = (APTR)string; request->io_Length = length; DoIO(request); /* command works because DoIO blocks until command is * done (otherwise pointer to string could become * invalid in the meantime). */ return(0); } /* Output a NULL-terminated string of characters to a console */ int ConPutStr(request,string) struct IOStdReq *request; char *string; { request->io_Command = CMD_WRITE; request->io_Data = (APTR)string; request->io_Length = -1; /* tells console to end when it * sees a terminating zero on * the string. */ DoIO(request); return(0); } /* queue up a read request to a console, show where to * put the character when ready to be returned. Most * efficient if this is called right after console is * opened */ int QueueRead(request,whereto) struct IOStdReq *request; char *whereto; { request->io_Command = CMD_READ; request->io_Data = (APTR)whereto; request->io_Length = 1; SendIO(request); return(0); } /* see if there is a character to read. If none, don't wait, * come back with a value of -1 */ int ConMayGetChar(request,requestPort, whereto) struct IOStdReq *request; char *whereto; { register temp; if ( GetMsg(requestPort) == NULL ) return(-1); temp = *whereto; QueueRead(request,whereto); return(temp); } /* go and get a character; put the task to sleep if * there isn't one present */ UBYTE ConGetChar(consolePort,request,whereto) struct IOStdReq *request; struct MsgPort *consolePort; char *whereto; { register UBYTE temp; while((GetMsg(consolePort) == NULL)) WaitPort(consolePort); temp = *whereto; /* get the character */ QueueRead(request,whereto); return(temp); } int init_timer(tmsg) /* return an error code if timer did not open */ { return( OpenDevice(TIMERNAME,UNIT_VBLANK,tmsg,0)); } int set_timer(tmsg,sec,micro) ULONG sec,micro; struct IOStdReq *tmsg; { tmsg->io_Command = TR_ADDREQUEST; /* add a new timer request */ tmsg->SECONDS = sec; /* seconds */ tmsg->MICROSECONDS = micro; /* microseconds */ SendIO( tmsg ); /* post a request to the timer */ return(0); }