This chapter describes how an application can use the fax libraries and Mailbox library to compose and send a fax. Most GEOS devices, including the Nokia 9000i Communicator, come with an application that composes and sends simple fax documents; this chapter will show you how you can write a program that composes a custom fax using graphics commands.
This chapter assumes that you know the basics of GEOS programming. It also assumes that you know how to draw the image that you want to fax, given a GState to draw to. (Most visible objects draw themselves when sent a
MSG_VIS_DRAW
; documentation of kernel drawing commands may be found in
A PrintControl object provides the API for drawing the contents of the fax; while this chapter will tell you what you need to know for simple faxes, more information about the PrintControl is available in .
Sending a fax may be broken down into the following tasks:
Ideally, these tasks are carried out using standard object classes that conform to the device's look and feel.
1 Destination Phone Number
2 Drawing the Contents
2.1 Declaring the Objects
2.2 Supplying the Document's Name
2.3 Supplying the Fax's Contents
To prompt the user for the fax's destination phone number while employing the device's standard look and feel, we will use the Mailbox library and its fax adjuncts. Specifically, we will use a
MailboxSendControl
object, configured for use with fax.
Make sure the following lines appear in the application's .gp file:
library mailbox # Defines MailboxSendControlClass library spool # Defines PrintControlClass
We will use a
MailboxSendControl
object to provide the UI that prompts the user for a phone number. When it comes time to draw the contents of our fax, we'll also need a
PrintControl
object.
We make sure that these controller objects are added to the correct GCN lists in the declaration of our application's Application object:
Code Display 4-1 Adding the Fax Controls to the Proper GCN Lists
In the declaration of the application's Application object, we make sure that the MailboxSendControl and PrintControl objects are placed on the proper GCN lists.
@object ... MyApp = {
...
gcnList(MANUFACTURER_ID_GEOWORKS, GAGCNLT_SELF_LOAD_OPTIONS) =
... @MyPrintControl, @MySendControl;
gcnList(MANUFACTURER_ID_GEOWORKS, MGCNLT_ACTIVE_LIST) = ... @MySendControl;
gcnList(MANUFACTURER_ID_GEOWORKS, GAGCNLT_MAILBOX_SEND_CONTROL) =
... @MySendControl;
ATTR_GEN_APPLICATION_PRINT_CONTROL = @MyPrintControl;
}
We make sure that the
MailboxSendControl
will be visible to the user; the straightforward way to do this is to add it to the application's generic UI tree. For example:
@object GenPrimaryClass MyPrimary = {
GI_comp = ..., @MySendControl;
}
Finally, we're ready to declare the
MailboxSendControl
object itself:
Code Display 4-2 MailboxSendControl Object Ready for Fax
@object MailboxSendControlClass MySendControl = {
GI_visMoniker = "Send";
GII_visibility = GIV_POPUP;
GCI_output = process;
MSCI_defBodyType = MOT_SELECTION;
ATTR_MAILBOX_SEND_CONTROL_SEND_SELECTION;
ATTR_GEN_INIT_FILE_CATEGORY = "fax" ;
ATTR_MAILBOX_SEND_CONTROL_SINGLE_TRANSPORT = {
{GMID_CELL_MODEM, MANUFACTURER_ID_GEOWORKS},
{GMTID_FAX_SEND, MANUFACTURER_ID_GEOWORKS},0};
ATTR_MAILBOX_SEND_CONTROL_TRANSPORT_HINT_OPTR = {
{GMTID_FAX_SEND, MANUFACTURER_ID_GEOWORKS}, 0,
@MyPrintControl};
}
(If your application is to run on the Nokia 9000i Communicator, use ComplexMonikerClass to give your
MailboxSendControl
the standard Nokia 9000i Communicator look and feel. In the example above, you would replace
@object MailboxSendControlClass MySendControl = {
GI_visMoniker = "Send";
...with...
@object ComplexMonikerClass MySendControl = {
ComplexMoniker = MailboxSendControlClass;
CMI_topText = CMT_SELECT_RECEIVER;
HINT_SEEK_REPLY_BAR; /* make this button 0 */
HINT_SEEK_SLOT = 0;
)
ATTR_MAILBOX_SEND_CONTROL_TRANSPORT_HINT_OPTR
tells the
MailboxSendControl
that when it comes time to send a fax, it should look to the
MyPrintControl
object to provide the data. The FaxSendTD Mailbox transport driver knows how to interact with PrintControl objects; we will add code to our program to work with the PrintControl to draw our fax contents.
ATTR_GEN_INIT_FILE_CATEGORY tells the send control where to find the user's faxing preferences within the INI file--the "fax" category.
ATTR_MAILBOX_SEND_CONTROL_SINGLE_TRANSPORT
specifies that this
MailboxSendControl
only sends data by fax. To allow your application to send data in additional ways, get rid of this ATTR.
The
MailboxSendControl
would ask the user what data they wish to send: the current selection, current page, all pages. In most fax programs, we don't want to give the user that choice. In our example, we use the
ATTR_MAILBOX_SEND_CONTROL_SEND_SELECTION
vardata field to prevent the controller from presenting the user with this choice--the
MailboxSendControl
will always try to send the "current selection," though our program ignores any idea of selection.
We have configured the
MailboxSendControl
so that when the user has specified a recipient for the fax, the control will query a
PrintControl
object for the fax's contents.
Again, make sure the following line is in the application's .gp file:
library spool # Defines PrintControlClass
In the previous section, we saw that the
PrintControl
object needed to appear on certain GCN lists and in the
MailboxSendControl
's
ATTR_MAILBOX_SEND_CONTROL_TRANSPORT_HINT_OPTR
field. (See Adding the Fax Controls to the Proper GCN Lists
and MailboxSendControl Object Ready for Fax
.)
Assuming that the
PrintControl
won't be used for anything else, the following declaration will suffice:
@object PrintControlClass MyPrintControl = {
GI_states = @default & ~GS_ENABLED;
PCI_docNameOutput = process;
PCI_output = process;
}
Here we have turned off the GS_ENABLED flag because the
PrintControl
's UI will never appear in the application; it isn't part of the application's generic UI tree. (To include the PrintControl's UI in your application, leave it enabled, add it to the generic UI tree, and see the Printing chapter for more information.)
The
PCI_output
line specifies that the application's process object will be responsible for drawing the fax's contents. The
PCI_docNameOutput
line specifies that the application's process will be responsible for providing the fax's name.
The process object (or whatever object is specified in the
PrintControl
's
PCI_docNameOutput
field) must supply the fax's name when queried. (On the Nokia 9000i Communicator, this name is not especially important; this is just a required part of the
PrintControl
's API.) The name need not be unique.
To fulfill its responsibility, the object must handle
MSG_PRINT_GET_DOC_NAME
, responding by sending
MSG_PRINT_CONTROL_SET_DOC_NAME
. If the message is not handled in this manner, the fax will never be sent.
The following is an acceptable handler:
Code Display 4-3 Handling MSG_PRINT_CONTROL_SET_DOC_NAME for faxing
The printCtrlOD value is an argument to the message.
@method MyProcessClass, MSG_PRINT_GET_DOC_NAME {
@send printCtrlOD::MSG_PRINT_CONTROL_SET_DOC_NAME("Good Morning");
}
The process object (or whatever object is specified in the
PrintControl
's
PCI_output
field) describes the fax's contents in the method for the imported message
MSG_PRINT_START_PRINTING
. It will receive this message after the user has specified a recipient for the fax. This message is defined:
void MSG_PRINT_START_PRINTING( \ optr printCtrlOD , \ GStateHandle gstate );
There are some things that the handler for this message must do:
GrNewPage()
to generate a form feed. (It should also call
GrNewPage()
between the pages of a multi-page fax, of course.)
PrintControl
MSG_PRINT_CONTROL_PRINTING_COMPLETED
.There are many things that the handler for this message may do. For information about some of them, see thePrinting chapter. (If you read that chapter, you might think it's important that the print job's page range is also determined; this is not important for faxing.)
The following example shows a handler that draws a fax's contents to contain some text and a rectangle:
Code Display 4-4 Handling MSG_PRINT_START_PRINTING when faxing
@method MyProcessClass, MSG_PRINT_START_PRINTING {
/* We draw the contents of the fax. */
GrDrawText(gstate, 20,40, "Good Morning", 0);
GrDrawRect(gstate, 10,30, 110,55);
/* Make sure that our last drawing command is a form-feed */
GrNewPage(gstate, PEC_FORM_FEED);
/* Let the PrintControl know we're done */
@send printCtrlOD::MSG_PRINT_CONTROL_PRINTING_COMPLETED();
}
In the example, we draw the fax's contents with a couple of kernel graphics commands. We might just have easily passed gstate as the graphic state argument to some Visible object's
MSG_VIS_DRAW
message (also passing the
DrawFlag
DF_PRINT).
We also need to tell the
PrintControl
how many pages we're printing. The first page that we draw on is page one. If there is a separate cover page, that will be page zero. To specify how many pages there are to print, we call MSG_PRINT_CONTROL_SET_SELECTED_PAGE_RANGE, and then MSG_PRINT_CONTROL_SET_SELECTED_PAGE_RANGE, passing the number of pages to print as that message's second argument.
It is possible that the fax cover page will appear on the same page on which drawing starts. To find out how much vertical space this cover page will take up on the first page, call the PrintControl with
MSG_PRINT_GET_FIRST_PAGE_OFFSET
; the return value will be the height of the cover page. (To properly follow naming conventions, this message should be called
MSG_PRINT_CONTROL_GET_FIRST_PAGE_OFFSET
; as of this writing it has not yet had its name fixed.)