Stevens Creek Software



PalmPrint/SCS Print Server

Developing with Satellite Forms? Click here.
Want to print from web clipping results (from PQAs)? Click here.

SDK & Sample Code

An "SDK" is unneccessary since we are using all standard Palm API calls, as you will read below. However, here is a list of constants you can cut and paste into your app:

// Print command defines
#define cmdPrintChars     32768
#define cmdXmitChars      32769
#define cmdStartPrint     32770
#define cmdStartXmit      32771
#define cmdPrintLine      32772
#define cmdXmitLine       32773
#define cmdEndPrint       32774
#define cmdEndXmit        32775
#define cmdPrintLinePassThru 32776
#define cmdXmitLinePassThru  32777
#define cmdDoFF           32800
#define cmdSetPlain       32802
#define cmdSetBold        32804
#define cmdSetStdFont     32810
#define cmdSetNewFont     32812
#define cmdSetPtSize      32814
#define cmdSetLeftMargin  32820
#define cmdSetTopMargin   32822
#define cmdSetChars       32824
#define cmdSetLines       32826
#define cmdSetPortrait    32828
#define cmdSetLandscape   32830
#define cmdSetIndent      32832
#define cmdSetNumCopies   32834
#define cmdGetChars       33000
#define cmdGetLines       33001
#define sysAppLaunchPrintSetup 40000

// Font defines
#define Courier               0
#define Times                 1
#define Helvetica             2
#define fontMask              7
#define pt12                  0
#define pt10                  8
#define pt9                  16
#define pointMask            56 

Simplest Possible Printing

Using PalmPrint can be simplicity itself - you simply provide a pointer to a character string containing the material to be printed and PalmPrint does the rest. A snippet of code is shown below. cmdPrintChars (32768) is the "launch code" PalmPrint is using to identify a request for print service; the rest is straightforward.

    DWord    result;
    LocalID  dbID;
    Char     theChars[32];

    if (dbID) {
      StrCopy(theChars,"This is the string to print");

The fifth argument to SysAppLaunch should be a CharPtr. CharPtr's can be generated in a variety of ways, as you should realize; the method above is one of the crudest but suffices for this example. Form feeds (new pages) and word wrapping are handled automatically within PalmPrint based on a maximum number of lines per page and maximum number of characters per line. However if you want to control these factors, the character string can contain newline characters - use linefeed (0x0A hex, 10 decimal) for this purpose, or formfeed characters (0x0C hex, 12 decimal).

Data Transmission

The PalmPrint user configures the software for the printer type (PCL, PostScript, etc.) that they will be printing to. One of the possibilities is "Plain Text", which is primarily used for transmission of data from the PalmPilot to another computer. In this mode, no control characters or escape sequences are transmitted, and word-wrap is suppressed.

You can force PalmPrint into the Plain Text mode temporarily by using a launch code of cmdXmitChars (32769); otherwise everything is as described in the previous section. The user's printer choice is overridden, but is not permanently changed.

Doing Your Own Formatting

As noted above, PalmPrint normally does automatic word wrapping and page breaks. If you want to control these things yourself from your application, you'll probably want to know the number of characters per line and lines per page. You can retrieve these pieces of information from PalmPrint using launch codes cmdGetChars (33000) and cmdGetLines (33001), respectively, using a pointer to an integer rather than a character string, but passed as a character pointer. Here's a more complete example:

static void TestPrint(void)
    CharPtr   dataP;
    VoidHand  dataH;
    DWord     result;
    Word      err;
    LocalID   dbID;
    int       theInfo;
    char      theChars[32];

    if (dataH!=0) {
        StrCopy(dataP,"This is the string to print");
        if (dbID) {
            StrCat(theChars," chars per line");
            StrCat(theChars," lines per page");
            StrCopy(dataP,"This is the string to print");

Line by Line Printing

If you don't want to assemble all the text to print into one block, you can also use PalmPrint to print one line (or a few lines) at a time. In line by line mode problems can occur (e.g., your app might crash, not send a finish code, etc.); it goes without saying it will be up to you to insure that your app is properly behaved in this regard. This should not be under user control in your program; otherwise, the user might leave the serial line open which is definitely a bad idea.

The list of launch codes and associated pointers follow. Remember that all pointers must be case as a (char*) even when they are really pointers to something else.

Launch Code Pointer Description
cmdPrintChars CharPtr Print characters at CharPtr
cmdXmitChars CharPtr Transmit characters at CharPtr
cmdStartPrint n.a. Start printing in line by line mode
cmdStartXmit n.a. Start transmission in line by line mode
cmdPrintLine CharPtr Print a line (or set of lines) in line by line mode
cmdXmitLine CharPtr Transmit a line (or set of lines) in line by line mode
cmdEndPrint n.a. Finish printing in line by line mode
cmdEndXmit n.a. Finish transmitting in line by line mode
cmdPrintLinePassThru CharPtr Print a line of characters in passthru mode (see below)
cmdXmitLinePassThru CharPtr Transmit a line of characters in passthru mode (see below)
cmdGetChars int* Return number of characters per line in *(int*)
cmdGetLines int* Return number of lines per page in *(int*)

Here's an example of using line by line printing to print out a list of the numbers from 1 to 20:

CharPtr dataP;
VoidHand dataH;
Word err;
DWord result;
LocalID  dbID;
int i;

if (dataH!=0) {
    if (dbID) {
        // Start Printing for (i=0; i<20; i++) {
            StrCat(dataP,"                is the number");
            if (result==0) err=SysAppLaunch(0,dbID,0,cmdPrintLine,dataP,&result);                // Print a Line
        } if (result==0) err=SysAppLaunch(0,dbID,0,cmdEndPrint,dataP,&result);                // Finish Printing

Expanded Formatting Options

Starting with PalmPrint 2.0, we support an additional set of format control launch codes (everything above applies to 1.0; what follows applies to users (esentially all of them) with 2.0):

Launch Code Pointer Description
cmdDoFF n.a. Perform a form feed (eject page)
cmdSetPlain n.a. Set characters to plain mode
cmdSetBold n.a. Set characters to bold mode
cmdSetStdFont n.a. Set standard (monospaced, Courier) font
cmdSetNewFont long Select a new font: 0=Courier, 1=Times, 2=Helvetica
cmdSetPtSize long Select new point size: 0=12 pt, 8=10 pt, 16=9 pt
cmdSetLeftMargin long Set left margin (in characters)
cmdSetTopMargin long Set top margin (in lines)
cmdSetChars long Set #characters per line
cmdSetLines long Set #lines per page
cmdSetPortrait n.a. Set portrait mode (PCL, Postscript only)
cmdSetLandscape n.a. Set landscape mode (PCL, Postscript only)
cmdSetIndent long Set indent for word-wrapped lines (in characters)
(Used to create "hanging" paragraphs)
cmdSetNumCopies long Set number of copies for the following print job
[Present beginning with PalmPrint 4.0, and only functional
when PalmPrint is called using "line by line"mode]

Note that any changes to formatting (orientation, margins, #characters per line, etc.) are temporary (while your application runs) and are set back to the default settings (set by PalmPrint) when your application issues an "End Print" command (32774 launch code).

Some formatting changes (margins, characters per line or lines per page, orientation, should be set BEFORE printing starts (with a cmdPrintChars or cmdStartPrint launch code); others (font changes, bold) must be issued AFTER printing starts (before or after any actual printing has been done).

The indent command allows you to set the indent of word-wrapped lines only (thus allowing you to set up for "hanging paragraphs." The indentation of the FIRST line of a paragraph is set by you (using spaces), but PalmPrint will then word-wrap subseqent lines of that paragraph according to the indent setting. Indent is reset to 0 whenever a new print job is started, and you can change it at any time during the printing.

Sample code for these functions:

static void Print(void)
  LocalID    PalmPrintID;
  Handle     hc;
  CharPtr    c;
   int        theVal;
  Err        err;
  DWord      result;
  if (PalmPrintID==0) {
    FrmCustomAlert(infoAlert,"Couldn't find PalmPrint application","","");
  if (hc==0) {
    FrmCustomAlert(infoAlert,"Couldn't allocate enough memory to print!","","");
  // First setup things that must be done BEFORE starting the print job
  // Now initialize the print job
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdStartPrint,0,&result);  
  theVal=Helvetica; // Set font to Helvetica
  theVal=pt12; // Set point size to 12 point
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetPtSize,(Char*)theVal,&result);
  // Set to plain print
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetPlain,0,&result);
  StrCopy(c,"Printing in plain Helvetica 12 pt");
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdPrintLine,c,&result);
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetBold,0,&result);
  theVal=pt9;  // Set point size to 9 point
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetPtSize,(Char*)theVal,&result);
  StrCopy(c,"Printing in bold Helvetica 9 pt");
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdPrintLine,c,&result);
  // Set to Courier ("Standard", i.e., monospaced, font)
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetStdFont,0,&result);
  theVal=pt10;  // Set point size to 10 point
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetPtSize,(Char*)theVal,&result);
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetPlain,0,&result);
  StrCopy(c,"Printing in plain Courier 10 pt");
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdPrintLine,c,&result);
  StrCopy(c,"This is a very long line to indicate what happens when normal 
  word wrapping is in effect so it should wrap to the beginning of the line.");
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdPrintLine,c,&result);
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdSetIndent,(Char*)20L,&result);
  StrCopy(c,"This is another very long line but now an indent is in effect so it should
  be a \"hanging\" paragraph wrapping to the indent point (20 characters).");
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdPrintLine,c,&result);
  if (result==0) err=SysAppLaunch(0,PalmPrintID,0,cmdEndPrint,0,&result);

Printing Character 0

For some applications like barcode printing, it becomes necessary to send a byte of 0 to the printer. PalmPrint uses standard string operations, so that embedding a 0 byte in the string you send to PalmPrint will terminate the string and not produce the results you want. If you need to send a zero byte to the printer, substitute 255 (hex FF) in the string you send to PalmPrint in place of each zero byte. At the point it is about to send bytes to the printer, PalmPrint substitutes back zeroes in place of any 255's it finds in the string. Alternatively, you can use the pass-through mode (next section).

PassThru Mode

Starting with PalmPrint 2.6 (available as a free upgrade to users of PalmPrint 2.0 or higher, so there is no reason any of your users won't have this), we support a new "pass-thru" mode as an alternative line by line mode. In normal "line by line" mode, everything being sent to the printer is checked for a variety of special cases - word-wrapping occurs at the end of a line, certain characters whose printing is not supported in PalmPrint (e.g., a TM symbol) are expanded into printing characters ("(tm)" in that example), and a return is added at the end of the material sent if one was not provided. In addition, in this mode (or in the "print all at once" mode either) you cannot send a byte of 0 to the printer, since a 0 will end the string of characters being read from your call by PalmPrint.

All of these limitations are lifted in the new "passthru" mode, which lets you sent a string of bytes to PalmPrint which are then passed on "as is" to the printer. The CharPtr you pass to PalmPrint points in this case NOT to a simple string, but to a structure whose first two bytes are an unsigned integer (UInt) containing the number of bytes to be printed, and whose remaining bytes are the bytes to be printed (potentially including embedded zeroes).

You can create a structure to handle this case if you want to, but the simplest way is to simply use a normal CharPtr pointing to a normal string, but to use it as shown here. This example illustrates the only way you can MIX plain and bold characters on a single line:

CharPtr		dataP;
VoidHand		dataH;
Word			err;
DWord		result;
LocalID		dbID;
UInt           len;

if (dataH!=0) {
  if (dbID) {
    err=SysAppLaunch(0,dbID,0,cmdStartPrint,0,&result);      // Start Printing
    StrCopy(&dataP[2],"Print plain,");
    if (result==0) err=SysAppLaunch(0,dbID,0,cmdSetPlain,0,&result);
    if (result==0) err=SysAppLaunch(0,dbID,0,cmdPrintLinePassThru,dataP,&result);
    StrCopy(&dataP[2]," then print bold,");
    if (result==0) err=SysAppLaunch(0,dbID,0,cmdSetBold,0,&result);
    if (result==0) err=SysAppLaunch(0,dbID,0,cmdPrintLinePassThru,dataP,&result);
    StrCopy(&dataP[2]," then print plain, and end line\n");
    if (result==0) err=SysAppLaunch(0,dbID,0,cmdSetPlain,0,&result);
    if (result==0) err=SysAppLaunch(0,dbID,0,cmdPrintLinePassThru,dataP,&result);
    if (result==0) err=SysAppLaunch(0,dbID,0,cmdEndPrint,0,&result);      // Finish Printing

Print Setup

Starting with version 4.0 of PalmPrint and SCS PrintServer, a new "print setup" feature is provided. This feature lets you add a "Print Setup" menu to your application, which will jump to PalmPrint/SCS PrintServer to let your user choose appropriate parameters (printer type, baud rate, margins, etc.) and then tap on a "Done" button which returns to your application.

Sample code you would use, in response to the Print Setup menu, might look like this:

LocalID           PalmPrintID;
DmSearchStateType theSearch;
UInt              cardNo;
Err               err;

if (err==errNone) {
  FtrSet('SCSp',0,myAppFileCreator); // Let PalmPrint know where to return
else FrmCustomAlert(infoAlert,"PalmPrint application not found","","");

Two things about this code need to be noted. First, "myAppFileCreator" in the FtrSet line is the creator ID for YOUR application, which is used by PalmPrint to know where to return when it exits (because you are launching it with a SysUIAppSwitch, and NOT a SysAppLaunch "subcall" as you are doing for the "regular" calls to PalmPrint. You do NOT need to worry about destroying this feature in your application; PalmPrint takes care of that.

The second thing to note is that in this code we are using DmGetNextDatabaseByTypeCreator to find the ID for PalmPrint, rather than the DmFindDatabase used in the examples elsewhere on this page. This is a better way to do things in general, since it searches all "cards" on the Palm.

Returning to your application from Print Setup

When PalmPrint/SCS PrintServer exits from your application, it calls your application using a SysAppLaunchNormalCommand, just as if your application had been started from the Launcher. This may not be what you want. If so, we recommend simply setting a feature in YOUR application prior to calling PalmPrint in setup mode (e.g., add FtrSet(myAppFileCreator,99,1) just before the FtrSet command shown above).Now when your application is started with a SysAppLaunchNormalCommand, you can simply read that feature value with a FtrGet to decide if you are entering "normally" or returning from a PalmPrint setup. If you are returning from PalmPrint, you can open your program in a different way (for example, skip the splash screen). Then make sure to set your special feature (99 in this example) back to 0 so that the next time your application is launched normally, you won't mistake it for a PalmPrint return.

Other Changes in 4.0

Version 3.2 of PalmPrint/SCS PrintServer had a bug which returned incorrect values if your application asked for the number of characters per line or number of lines per page. This is now fixed in 4.0, and the number of characters and lines that you get will be exactly what you should send it if you are trying to format output for a full page (e.g., for a printed receipt that fills the page, and repeats its header on the top of each page). If your application was "fudged" to account for the bug in the previous version of PalmPrint, version 4.0 has a "3.2 compatibility mode" which allows the user to continue to run in that mode until you (or other developers) update your application to correspond to PalmPrint 4.0. Once you do, they can turn off the compatibility mode and run in "correct" mode.

Somewhat related to this change, one other conceptual change has been made which may affect some developers. In version 3.2, two different printers (the Monarch 6015 and the Datamax E3202) used the number of characters per line to determine the font size. Below a certain number, a small font would be used, and above a certain number, a large font. This has now beeen changed to be consistent with all other printers, so that the user (or the developer using the CmdSetPtSize command described above) sets the font size and the number of characters per line independently (although of course for a given font size, there is one "correct" number of characters per line if the user wants to use the full page).

Setting the number of copies

This call should be made BEFORE the cmdStartPrint command, that is, BEFORE the printer is really activated by your program. The number of copies must be set on each print job, it is NOT remembered by PalmPrint. It is also not user-selectable within PalmPrint itself. Our reasoning there is that PalmPrint is used for many functions. You might want your receipt printing application to always print 2 copies, but that doesn't mean if the user uses PalmPrint to print a memo that they want 2 copies of the memo. So there is no UI within PalmPrint to set the number of copies; that's something you need to provide in your application if you want to.

Also note that, as currently implemented, the number of copies feature functions ONLY if you are using PalmPrint in the "line-by-line" mode. If you are using the single "cmdPrintChars" call to print your entire job with one command, then you can simply repeat that call N times to print N copies, so the cmdSetNumCopies isn't functional in that mode.

Return to the main PalmPrint Developers page

Handheld Solutions for Real-world Problems
Products | Buy Now | Downloads | Support | Info for Resellers | Site Map | Contact Us | About Us