diff --git a/src/kits/interface/PrintJob.cpp b/src/kits/interface/PrintJob.cpp index 5462a26339..23a11d05b7 100644 --- a/src/kits/interface/PrintJob.cpp +++ b/src/kits/interface/PrintJob.cpp @@ -3,9 +3,9 @@ * Distributed under the terms of the MIT license. * * Authors: - I.R. Adema - Stefano Ceccherini (burton666@libero.it) - Michael Pfeiffer + * I.R. Adema + * Stefano Ceccherini (burton666@libero.it) + * Michael Pfeiffer */ // TODO refactor (avoid code duplications, decrease method sizes) @@ -38,11 +38,11 @@ static const char *kNoPagesToPrintText = "No Pages to print!"; // Summery of spool file format: // See articel "How to Write a BeOS R5 Printer Driver" for description -// of spool file format: +// of spool file format: // http://haiku-os.org/documents/dev/how_to_write_a_printer_driver // print_file_header header -// On BeOS R5 header.version is 1 << 16 and +// On BeOS R5 header.version is 1 << 16 and // header.first_page is -1. // BMessage job_settings // _page_header_ page_header @@ -59,7 +59,7 @@ struct _page_header_ { }; -static status_t +static status_t GetPrinterServerMessenger(BMessenger& messenger) { messenger = BMessenger(PSRV_SIGNATURE_TYPE); @@ -67,44 +67,44 @@ GetPrinterServerMessenger(BMessenger& messenger) } -static void +static void ShowError(const char *message) { - BAlert* alert = new BAlert("Error", message, "OK"); + BAlert* alert = new BAlert("Error", message, "OK"); alert->Go(); } namespace BPrivate { - + class Configuration { public: Configuration(uint32 what, BMessage *input); ~Configuration(); - + status_t SendRequest(thread_func function); - - BMessage* Request(); - - void SetResult(BMessage* result); - BMessage* Result() const { return fResult; } - + + BMessage* Request(); + + void SetResult(BMessage* result); + BMessage* Result() const { return fResult; } + private: void RejectUserInput(); - void AllowUserInput(); + void AllowUserInput(); void DeleteSemaphore(); - - uint32 fWhat; + + uint32 fWhat; BMessage *fInput; BMessage *fRequest; BMessage *fResult; sem_id fThreadCompleted; BAlert *fHiddenApplicationModalWindow; }; - - + + Configuration::Configuration(uint32 what, BMessage *input) - : fWhat(what), + : fWhat(what), fInput(input), fRequest(NULL), fResult(NULL), @@ -113,8 +113,8 @@ namespace BPrivate { { RejectUserInput(); } - - + + Configuration::~Configuration() { DeleteSemaphore(); @@ -122,9 +122,9 @@ namespace BPrivate { delete fRequest; fRequest = NULL; AllowUserInput(); } - - - void + + + void Configuration::RejectUserInput() { BAlert* alert = new BAlert("bogus", "app_modal_dialog", "OK"); @@ -134,16 +134,16 @@ namespace BPrivate { alert->MoveTo(-65000, -65000); alert->Go(NULL); } - - - void + + + void Configuration::AllowUserInput() { fHiddenApplicationModalWindow->Lock(); fHiddenApplicationModalWindow->Quit(); } - - + + void Configuration::DeleteSemaphore() { @@ -153,25 +153,25 @@ namespace BPrivate { delete_sem(id); } } - - + + status_t Configuration::SendRequest(thread_func function) { - fThreadCompleted = create_sem(0, "Configuration"); + fThreadCompleted = create_sem(0, "Configuration"); if (fThreadCompleted < B_OK) { return B_ERROR; } - + thread_id id = spawn_thread(function, "async_request", B_NORMAL_PRIORITY, this); if (id <= 0 || resume_thread(id) != B_OK) { return B_ERROR; } - - // Code copied from BAlert::Go() + + // Code copied from BAlert::Go() BWindow* window = dynamic_cast(BLooper::LooperForThread(find_thread(NULL))); // Get the originating window, if it exists - + // Heavily modified from TextEntryAlert code; the original didn't let the // blocked window ever draw. if (window != NULL) { @@ -182,7 +182,7 @@ namespace BPrivate { kSemTimeOut); // We've (probably) had our time slice taken away from us } while (err == B_INTERRUPTED); - + if (err == B_BAD_SEM_ID) { // Semaphore was finally nuked in SetResult(BMessage *) break; @@ -193,20 +193,20 @@ namespace BPrivate { // No window to update, so just hang out until we're done. while (acquire_sem(fThreadCompleted) == B_INTERRUPTED); } - + status_t status; wait_for_thread(id, &status); - + return Result() != NULL ? B_OK : B_ERROR; } - - + + BMessage * Configuration::Request() { if (fRequest != NULL) return fRequest; - + if (fInput != NULL) { fRequest = new BMessage(*fInput); fRequest->what = fWhat; @@ -214,8 +214,8 @@ namespace BPrivate { fRequest = new BMessage(fWhat); return fRequest; } - - + + void Configuration::SetResult(BMessage *result) { @@ -238,11 +238,11 @@ BPrintJob::BPrintJob(const char *job_name) fCurrentPageHeader(NULL) { memset(&fCurrentHeader, 0, sizeof(fCurrentHeader)); - + if (job_name != NULL) { fPrintJobName = strdup(job_name); } - + fCurrentPageHeader = new _page_header_; if (fCurrentPageHeader != NULL) { memset(fCurrentPageHeader, 0, sizeof(*fCurrentPageHeader)); @@ -253,7 +253,7 @@ BPrintJob::BPrintJob(const char *job_name) BPrintJob::~BPrintJob() { CancelJob(); - + free(fPrintJobName); delete fSetupMessage; delete fDefaultSetupMessage; @@ -265,7 +265,7 @@ static status_t ConfigPageThread(void *data) { BPrivate::Configuration* configuration = static_cast(data); - + BMessenger printServer; if (GetPrinterServerMessenger(printServer) != B_OK) { ShowError(kPrintServerNotRespondingText); @@ -279,14 +279,14 @@ ConfigPageThread(void *data) return B_ERROR; } - + BMessage reply; if (printServer.SendMessage(request, &reply) != B_OK || reply.what != 'okok') { configuration->SetResult(NULL); return B_ERROR; } - + configuration->SetResult(new BMessage(reply)); return B_OK; } @@ -294,7 +294,7 @@ ConfigPageThread(void *data) status_t BPrintJob::ConfigPage() -{ +{ BPrivate::Configuration configuration(PSRV_SHOW_PAGE_SETUP, fSetupMessage); status_t status = configuration.SendRequest(ConfigPageThread); if (status != B_OK) @@ -310,7 +310,7 @@ static status_t ConfigJobThread(void *data) { BPrivate::Configuration* configuration = static_cast(data); - + BMessenger printServer; if (GetPrinterServerMessenger(printServer) != B_OK) { ShowError(kPrintServerNotRespondingText); @@ -324,14 +324,14 @@ ConfigJobThread(void *data) return B_ERROR; } - + BMessage reply; if (printServer.SendMessage(request, &reply) != B_OK || reply.what != 'okok') { configuration->SetResult(NULL); return B_ERROR; } - + configuration->SetResult(new BMessage(reply)); return B_OK; } @@ -344,7 +344,7 @@ BPrintJob::ConfigJob() if (status != B_OK) return status; delete fSetupMessage; - fSetupMessage = configuration.Result(); + fSetupMessage = configuration.Result(); _HandlePrintSetup(fSetupMessage); return B_OK; } @@ -360,33 +360,33 @@ BPrintJob::BeginJob() if (fCurrentPageHeader == NULL) { return; } - + if (fSetupMessage == NULL) { // TODO show alert, setup message is required return; } - + // create spool file BPath path; status_t status = find_directory(B_USER_PRINTERS_DIRECTORY, &path); if (status != B_OK) return; - + char *printer = _GetCurrentPrinterName(); if (printer == NULL) return; - + path.Append(printer); free(printer); - + char mangledName[B_FILE_NAME_LENGTH]; _GetMangledName(mangledName, B_FILE_NAME_LENGTH); - + path.Append(mangledName); - + if (path.InitCheck() != B_OK) return; - + // TODO fSpoolFileName should store the name only (not path which can be 1024 bytes long) strncpy(fSpoolFileName, path.Path(), sizeof(fSpoolFileName)); fSpoolFile = new BFile(fSpoolFileName, B_READ_WRITE | B_CREATE_FILE); @@ -394,32 +394,32 @@ BPrintJob::BeginJob() if (fSpoolFile->InitCheck() != B_OK) { CancelJob(); return; - } - - // add print_file_header - // page_count is updated in CommitJob() + } + + // add print_file_header + // page_count is updated in CommitJob() fCurrentHeader.version = 1 << 16; fCurrentHeader.page_count = 0; - // on BeOS R5 the offset to the first page - // was always -1. + // on BeOS R5 the offset to the first page + // was always -1. fCurrentHeader.first_page = (off_t)-1; - + if (fSpoolFile->Write(&fCurrentHeader, sizeof(fCurrentHeader)) != sizeof(fCurrentHeader)) { CancelJob(); return; } - + // add printer settings message if (!fSetupMessage->HasString(PSRV_FIELD_CURRENT_PRINTER)) fSetupMessage->AddString(PSRV_FIELD_CURRENT_PRINTER, printer); _AddSetupSpec(); - // prepare page header + // prepare page header // number_of_pictures is updated in DrawView() - // next_page is updated in SpoolPage() + // next_page is updated in SpoolPage() fCurrentPageHeaderOffset = fSpoolFile->Position(); fCurrentPageHeader->number_of_pictures = 0; - + // state variables fAbort = 0; fPageNumber = 0; @@ -434,18 +434,18 @@ BPrintJob::CommitJob() if (fSpoolFile == NULL) { return; } - + if (fPageNumber <= 0) { ShowError(kNoPagesToPrintText); CancelJob(); return; } - + if (fCurrentPageHeader->number_of_pictures > 0) { SpoolPage(); } - - // update spool file + + // update spool file _EndLastPage(); // set file attributes @@ -453,14 +453,14 @@ BPrintJob::CommitJob() be_app->GetAppInfo(&appInfo); const char* printerName = ""; fSetupMessage->FindString(PSRV_FIELD_CURRENT_PRINTER, &printerName); - + BNodeInfo info(fSpoolFile); info.SetType(PSRV_SPOOL_FILETYPE); - fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PAGECOUNT, B_INT32_TYPE, 0, &fPageNumber, sizeof(int32)); - fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_DESCRIPTION, B_STRING_TYPE, 0, fPrintJobName, strlen(fPrintJobName) + 1); - fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PRINTER, B_STRING_TYPE, 0, printerName, strlen(printerName) + 1); - fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, PSRV_JOB_STATUS_WAITING, strlen(PSRV_JOB_STATUS_WAITING) + 1); + fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PAGECOUNT, B_INT32_TYPE, 0, &fPageNumber, sizeof(int32)); + fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_DESCRIPTION, B_STRING_TYPE, 0, fPrintJobName, strlen(fPrintJobName) + 1); + fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PRINTER, B_STRING_TYPE, 0, printerName, strlen(printerName) + 1); + fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, PSRV_JOB_STATUS_WAITING, strlen(PSRV_JOB_STATUS_WAITING) + 1); fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_MIMETYPE, B_STRING_TYPE, 0, appInfo.signature, strlen(appInfo.signature) + 1); delete fSpoolFile; @@ -471,11 +471,11 @@ BPrintJob::CommitJob() BMessenger printServer; if (GetPrinterServerMessenger(printServer) != B_OK) { return; - } + } BMessage request(PSRV_PRINT_SPOOLED_JOB); BMessage reply; - + request.AddString("JobName", fPrintJobName); request.AddString("Spool File", fSpoolFileName); printServer.SendMessage(&request, &reply); @@ -487,7 +487,7 @@ BPrintJob::CancelJob() if (fSpoolFile == NULL) { return; } - + fAbort = 1; BEntry(fSpoolFileName).Remove(); delete fSpoolFile; @@ -501,13 +501,13 @@ BPrintJob::SpoolPage() if (fSpoolFile == NULL) { return; } - + // update page header fCurrentPageHeader->next_page = fSpoolFile->Position(); fSpoolFile->Seek(fCurrentPageHeaderOffset, SEEK_SET); fSpoolFile->Write(fCurrentPageHeader, sizeof(*fCurrentPageHeader)); fSpoolFile->Seek(0, SEEK_END); - + fCurrentPageHeader->number_of_pictures = 0; } @@ -528,11 +528,11 @@ BPrintJob::DrawView(BView *view, BRect rect, BPoint where) if (view == NULL) return; - + if (view->LockLooper()) { BPicture picture; _RecurseView(view, B_ORIGIN - rect.LeftTop(), &picture, rect); - _AddPicture(picture, rect, where); + _AddPicture(picture, rect, where); view->UnlockLooper(); } } @@ -553,8 +553,8 @@ void BPrintJob::SetSettings(BMessage *message) { if (message != NULL) { - _HandlePrintSetup(message); - } + _HandlePrintSetup(message); + } delete fSetupMessage; fSetupMessage = message; } @@ -567,15 +567,15 @@ BPrintJob::IsSettingsMessageValid(BMessage *message) const if (printerName == NULL) { return false; } - + const char *name = NULL; // The passed message is valid if it contains the right printer name. - bool valid = message != NULL + bool valid = message != NULL && message->FindString("printer_name", &name) == B_OK && strcmp(printerName, name) == 0; - + free(printerName); - + return valid; } @@ -633,13 +633,13 @@ BPrintJob::PrinterType(void *) const BMessenger printServer; if (GetPrinterServerMessenger(printServer) != B_OK) { return B_COLOR_PRINTER; // default - } - + } + BMessage message(PSRV_GET_ACTIVE_PRINTER); BMessage reply; - + printServer.SendMessage(&message, &reply); - + int32 type; if (reply.FindInt32("color", &type) != B_OK) { return B_COLOR_PRINTER; // default @@ -648,18 +648,15 @@ BPrintJob::PrinterType(void *) const } -#if 0 -#pragma mark ----- PRIVATE ----- -#endif + +// #pragma mark ----- PRIVATE ----- void -BPrintJob::_RecurseView(BView *view, BPoint origin, - BPicture *picture, BRect rect) +BPrintJob::_RecurseView(BView *view, BPoint origin, BPicture *picture, + BRect rect) { ASSERT(picture != NULL); - // TODO: test what happens if views don't have - // the B_WILL_DRAW flag or have B_DRAW_ON_CHILDREN view->AppendToPicture(picture); view->f_is_printing = true; @@ -669,13 +666,26 @@ BPrintJob::_RecurseView(BView *view, BPoint origin, view->PopState(); view->f_is_printing = false; view->EndPicture(); - + BView *child = view->ChildAt(0); while (child != NULL) { - // TODO: origin and rect should probably - // be converted for children views in some way - _RecurseView(child, origin, picture, rect); - child = child->NextSibling(); + if ((child->Flags() & B_WILL_DRAW) && !child->IsHidden()) { + // TODO: origin and rect should probably + // be converted for children views in some way + _RecurseView(child, origin, picture, rect); + child = child->NextSibling(); + } + } + + if (view->Flags() & B_DRAW_ON_CHILDREN) { + view->AppendToPicture(picture); + view->f_is_printing = true; + view->PushState(); + view->SetOrigin(origin); + view->DrawAfterChildren(rect); + view->PopState(); + view->f_is_printing = false; + view->EndPicture(); } } @@ -692,7 +702,7 @@ BPrintJob::_HandlePageSetup(BMessage *setup) { setup->FindRect(PSRV_FIELD_PRINTABLE_RECT, &fUsableSize); setup->FindRect(PSRV_FIELD_PAPER_RECT, &fPaperSize); - + // TODO verify data type (taken from libprint) int64 valueInt64; if (setup->FindInt64(PSRV_FIELD_XRES, &valueInt64) == B_OK) { @@ -716,7 +726,7 @@ BPrintJob::_HandlePrintSetup(BMessage *message) if (message->FindInt32(PSRV_FIELD_LAST_PAGE, &fLastPage) != B_OK) { valid = false; } - + return valid; } @@ -731,7 +741,7 @@ BPrintJob::_NewPage() if (fPageNumber == 1) fCurrentHeader.first_page = fCurrentPageHeaderOffset; - fPageNumber ++; + fPageNumber ++; } @@ -756,7 +766,7 @@ BPrintJob::_AddPicture(BPicture &picture, BRect &rect, BPoint &where) ASSERT(fSpoolFile != NULL); if (fCurrentPageHeader->number_of_pictures == 0) { - _NewPage(); + _NewPage(); } fCurrentPageHeader->number_of_pictures ++; @@ -771,17 +781,17 @@ BPrintJob::_AddPicture(BPicture &picture, BRect &rect, BPoint &where) // Caller is responsible to free the string using free(). char * BPrintJob::_GetCurrentPrinterName() const -{ +{ BMessenger printServer; if (GetPrinterServerMessenger(printServer)) { return NULL; } - + BMessage message(PSRV_GET_ACTIVE_PRINTER); BMessage reply; - + const char *printerName = NULL; - + if (printServer.SendMessage(&message, &reply) == B_OK) { reply.FindString("printer_name", &printerName); } @@ -799,17 +809,17 @@ BPrintJob::_LoadDefaultSettings() if (GetPrinterServerMessenger(printServer) != B_OK) { return; } - + BMessage message(PSRV_GET_DEFAULT_SETTINGS); BMessage *reply = new BMessage; - + printServer.SendMessage(&message, reply); // Only override our settings if we don't have any settings yet if (fSetupMessage == NULL) _HandlePrintSetup(reply); - delete fDefaultSetupMessage; + delete fDefaultSetupMessage; fDefaultSetupMessage = reply; }