Sunday, August 15, 2010

Beads – How to Wait for Input

[Note: This is copied from the "FastCAD XP Programming Reference" that comes with the XP toolkit.  I copied this, with editing only for clarity, because it was so descriptive]

Nowhere in the Windows programming environment will you find a greater need to change your thinking than with regard to getting input.

In Windows, our programs receive messages that inform us of discrete user input - a mouse movement, button click, or a keyboard press. Other than dialog boxes, there is no way provided to wait for a complete word or line of text or other aggregate input in your program and then continue. We must write our program so that each keystroke is processed and then control is returned all the way to Windows.

This means that in a piece of code (creating a text entity, for example) we can not have one procedure that calls another to get a line of text and then continues with the next instruction when it is available, as would be done in a DOS or Unix program. The current position within that first command procedure is normally maintained on the stack, perhaps as a nested chain of procedure calls.

In Windows, after every event (such as a single key press), we have to return all the way up the stack back to Windows! This is why most Windows programs do all of their input through dialog boxes.

The FastCAD solution to this problem is to think of a command as a string of "beads" - little pieces of a command that each do one small part of the overall command, each a piece that can be done in response to an appropriate input event.

Lets take as an example a command to create a line entity. In traditional programming, its logic might be:

LineCommand:

prompt the user for the first point
- Get the first point if there was a problem getting it, end the command

prompt the user for the second point
- Get the second point if there was a problem getting it, end the command

Create the line entity

Append it to the drawing database

Draw the line entity

End the command

In FastCAD, we have an API service, ReqData, that handles data requests. We call ReqData with a packet that tells it about the data request, and then we go back to Windows.

When the data becomes available, ReqData will call another procedure specified in our original request packet to continue with our command. This means that we write our command as a series of procedures, linked together by RDATA packets, each one executing when its data becomes available, and returning to Windows when it needs to wait for more input.

The sequence looks like this:
==========================
Event: Action (Bead procedure):
- LINE function entered
- - Request first point by calling ReqData
- Line function ends

User enters the first request for a point:

Event: Action (Bead procedure):
- Second LINE function entered
- - Did the user cancel the request?
- - - End Command
- - Request second point by calling ReqData
- Second Line function ends

User enters the second request for a point:

Event: Action (Bead procedure):
- Third LINE function entered
- - Did the user cancel the request?
- - - End Command
- - Else
- - - Create the line entity
- - - Append it to the drawing database
- - - Draw the line entity
- - - End Command
-  Third Line function ends

The LINE command is implemented in 3 beads, each of which is called in response to a single event, such as a mouse click or a RETURN keypress. The ReqData service provides all of the intermediate beads that track mouse movement and build up strings of characters into words like "LINE" for you.

Next post, we will start to implement the LINE command.

2 comments:

  1. Just wanted to post a thank you for creating/maintaining this blog. It is very helpful.

    ReplyDelete