Aborting jobs and entering the printing loop - Steve Mumford explains
Last time round, I introduced the principle of using a structure of type _kernel_oserror to determine whether an SWI command had completed successfully; the _kernel_swi function returns a pointer to a structure of this type, so it's possible to test for errors in the following manner:
_kernel_oserror *ERR = NULL; ERR = _kernel swi(PDriver_DrawPage, &in, &out); if (ERR != NULL) { /* Deal with the error */ }
If we haven't been given a pointer to an error structure, we're safe. On the other hand, if something has gone wrong, it's nice to know a little more about it: Here's what the structure actually contains, as declared in <kernel.h> - we're given the appropriate error number and associated zero-terminated string:
typedef struct ( int errnum; char errmess[252]; } _kernel_oserror;
Assuming the error didn't occur in the middle of something critical, this information would enable the programmer to pop up a standard error dialogue box with very little work necessary, using one of the functions already set up:
au_report_error(ERR->errnum, ERR->errmess, 0, appname);
However, producing such an error window when we're in the middle of a print job could prove disastrous - if the error occurred during the PDriver_GetRectangle loop, it would probably compound the problem and destroy all hope of the program recovering gracefully. This is where we have to employ one of several escape routes.
During the development of a program, the chances are that the programmer will come across the odd error that causes the printer drivers to go haywire; if this is the case, there's a 'silver bullet' SWI that will abort all active print jobs on the system. PDrlver_Reset takes no parameters and, due to its somewhat ruthless nature, shouldn't be used in the normal course of events.
_kernel_oserror *ERR=NULL; _kernel_swi_regs in, out; in.r[0] = copies; in.r[1] = (int) &box; in.r[2] = 0; in.r[3] = 0; ERR = _kernel_swi(PDriver_Drawpage, &in, &out); if (ERR != NULL) { /* bail out gracefully */ }
Register 0 holds an integer representing the number of copies you wish to make of the current page, and R1 points to a four-word block of memory that will hold the coordinates of the first rectangle the printer driver wishes you to print. R2 holds the number of the page about to be printed, and R3 points to a textual string representing the page number - these allow PostScript output to adhere more strongly to Adobe's guidelines, but if you don't wish to make use of them, setting both registers to zero will disable this function.
On return, if register 0 is non-zero, it indicates that the coordinates of an area have been placed in the block pointed to by R1 (low x and y coordinates first, followed by high x and y), and you should draw any objects contained within that rectangle. After this first round of plotting, the programmer should call PDriver_GetRectangle, with R1 pointing to the four-word block already in use.
It's essentially a continuation of the former SWI, setting R0 according to whether anything remains to be printed and returning another block of coordinates if appropriate. As soon as this call returns R0 with a value of zero, you should stop printing the current page and repeat the process from PDriver_GiveRectangle if you wish to print any more. Otherwise, a call to PDriver_EndJob with R0 set to the print job file handle, followed by the closing of the file itself, will bring the procedure to a close.
Source: | Acorn User - 192 - March 1998 |
Publication: | Acorn User |
Contributor: | Steve Mumford |