From: alain@cs.uchicago.edu (Alain Aslag Roy)

Here's the code that I recently wrote. I won't swear that it's perfect,
but it seems to work well for me. It was chopped out of a class
that has "print_record" defined in it as

THPrint  print_record;

This is a bit more complete than other code that I've seen, because
it attempts to do line breaks properly--that is, there is never a line
that is printed partially at the bottom of one page, and partially at
the top of the next page. To be honest, I'm not sure what would happen
if you were printing with a font that was bigger than the paper.

If anyone notices any serious errors in my code, please tell me!

-alain

---------------- cut here -----------------------
void editor::page_setup(void)
{
        PrOpen();
        if (print_record == NULL)
        {
                print_record = (THPrint) NewHandle(sizeof(TPrint));
                assert(print_record != NULL);
                PrintDefault(print_record);
                PrValidate(print_record);
        }
        PrStlDialog(print_record);
        PrClose();
        return;
}

void editor::print(void)
{
        long       line_count;
        long       page_height, top_line, bottom_line, height;
        Rect       update_rect;
        short      print_error;
        boolean    do_print, done_printing, first_page;
        GrafPtr    old_text_port, old_port;
        Boolean    old_active_flag;
        TPPrPort   printing_port;
        LongRect   page_rect;
        LongRect   old_dest_rect, old_view_rect, view_rect;
        RgnHandle  update_region;
        DialogRef  dialog;

        PrOpen();
        if (print_record == NULL)
        {
                print_record = (THPrint) NewHandle(sizeof(TPrint));
                assert(print_record != NULL);
                PrintDefault(print_record);
                PrValidate(print_record);
        }
        do_print = PrJobDialog(print_record);
        
        if (do_print)
        {
                dialog = GetNewDialog(dlogPRINTING, NULL, (WindowRef) -1);
                assert(dialog != NULL);
                DrawDialog(dialog);
                
                GetPort(&old_port);
                SetPortWindowPort(window);
                // save old variables so they can be restored after printing.
                WEGetInfo(wePort, &old_text_port, text);
                WEGetDestRect(&old_dest_rect, text);
                WEGetViewRect(&old_view_rect, text);
                old_active_flag = WEIsActive(text);

                WEFeatureFlag(weFOutlineHilite, weBitClear, text);
                WEFeatureFlag(weFDrawOffscreen, weBitClear, text);

                if (old_active_flag)
                {
                        SetPort(old_text_port);
                        WEDeactivate(text);
                        // Make the screen look all nice.
                        WEUpdate(GetWindowPort(window)->visRgn, text);
                }
                
                printing_port = PrOpenDoc(print_record, NULL, NULL);
                if (PrError() == noErr)
                {
                        // Set up the waste record for the new port.
                        SetPort((GrafPtr) printing_port);
                        done_printing = FALSE;
                        while (!done_printing)
                        {
                                PrOpenPage(printing_port, NULL);
                                if (PrError() == noErr)
                                {
                                        SetPort((GrafPtr) printing_port);
                                        SetFractEnable(TRUE);  // for purty printin'

                                        // we wait until after the first propenpage() becuase wecaltext() draws
                                        // to the port, but it currently seems to be the screen before the first
                                        // call to propenpage(). 
                                        if (first_page)
                                        {
                                                first_page = FALSE;
                                                WESetInfo(wePort, &printing_port, text);
                                                WERectToLongRect(&((**print_record).prInfo.rPage), &page_rect);
                                                WESetDestRect(&page_rect, text);
                                                WESetViewRect(&page_rect, text);
                                                WECalText(text);
                                                EraseRect(&((**print_record).prInfo.rPage));
                                                
                                                line_count = WECountLines(text);
                                                page_height = page_rect.bottom - page_rect.top;
                                                top_line = bottom_line = 0;
                                        }

                                        while (WEGetHeight(top_line, bottom_line, text) <= page_height && bottom_line <= line_count)
                                                bottom_line++;
                                        if (bottom_line-top_line > 1) // weÕve overshot, unless we have only 1 line.
                                                bottom_line--;
                                        height = WEGetHeight(top_line, bottom_line, text);
                                        WEGetViewRect(&view_rect, text);
                                        view_rect.bottom = view_rect.top + height;
                                        WESetViewRect(&view_rect, text);
                                        update_region = NewRgn(); assert(update_region);
                                        WELongRectToRect(&view_rect, &update_rect);
                                        RectRgn(update_region, &update_rect);
                                        WEUpdate(update_region, text);
                                        DisposeRgn(update_region);
                                        WEScroll(0, -height, text);
                                        top_line = bottom_line;
                                        if (top_line >= line_count)
                                                done_printing = TRUE;
                                }
                                PrClosePage(printing_port);
                                if (PrError() != noErr)
                                        break;
                        }

                        // reset old variables in the waste record
                        WESetInfo(wePort, &old_text_port, text);
                        WESetDestRect(&old_dest_rect, text);
                        WESetViewRect(&old_view_rect, text);
                        PrCloseDoc(printing_port);

                        if (PrError() == noErr)
                        {
                                // Check if print job is spooled
                                if ((**print_record).prJob.bJDocLoop == bSpoolLoop)
                                {
                                        TPrStatus  printing_status;
                                        
                                        PrPicFile(print_record, NULL, NULL, NULL, &printing_status);
                                }
                        }
                }
                SetFractEnable(FALSE);
                DisposeDialog(dialog);
                SetPort(old_port);
                if (old_active_flag)
                        WEActivate(text);
                WEFeatureFlag(weFOutlineHilite, weBitSet, text);
                WEFeatureFlag(weFDrawOffscreen, weBitSet, text);
                WECalText(text);
        }
        
        print_error = PrError();
        PrClose();

        if (print_error != noErr && print_error != iPrAbort)
        {
                report_error(errPrintingProblem, print_error);
        }
        
        SetPort(old_port);
        return;
}
