1 /* 2 * Copyright 2001-2008, Haiku. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * I.R. Adema 7 * Stefano Ceccherini (burton666@libero.it) 8 * Michael Pfeiffer 9 * julun <host.haiku@gmx.de> 10 */ 11 12 #include <Alert.h> 13 #include <Application.h> 14 #include <Button.h> 15 #include <Debug.h> 16 #include <Entry.h> 17 #include <File.h> 18 #include <FindDirectory.h> 19 #include <Messenger.h> 20 #include <NodeInfo.h> 21 #include <OS.h> 22 #include <Path.h> 23 #include <PrintJob.h> 24 #include <Region.h> 25 #include <Roster.h> 26 #include <View.h> 27 28 29 #include <pr_server.h> 30 #include <ViewPrivate.h> 31 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 38 /* ! 39 * 40 * Summery of R5 spool file: 41 * 42 * |-----------------------------------| 43 * | print_file_header | 44 * |-----------------------------------| 45 * | BMessage print_job_settings | 46 * |-----------------------------------| 47 * | | 48 * | ********** (first page) ********* | 49 * | * * | 50 * | * _page_header_ * | 51 * | * ----------------------------- * | 52 * | * |---------------------------| * | 53 * | * | BPoint where | * | 54 * | * | BRect bounds | * | 55 * | * | BPicture pic | * | 56 * | * |---------------------------| * | 57 * | * |---------------------------| * | 58 * | * | BPoint where | * | 59 * | * | BRect bounds | * | 60 * | * | BPicture pic | * | 61 * | * |---------------------------| * | 62 * | ********************************* | 63 * | | 64 * | ********* (second page) ********* | 65 * | * * | 66 * | * _page_header_ * | 67 * | * ----------------------------- * | 68 * | * |---------------------------| * | 69 * | * | BPoint where | * | 70 * | * | BRect bounds | * | 71 * | * | BPicture pic | * | 72 * | * |---------------------------| * | 73 * | ********************************* | 74 * |-----------------------------------| 75 * 76 * BeOS R5 print_file_header.version is 1 << 16 77 * BeOS R5 print_file_header.first_page is -1 78 * 79 * each page can consist of a collection of picture structures 80 * remaining pages start at _page_header_.next_page of previous _page_header_ 81 * 82 * See also: "How to Write a BeOS R5 Printer Driver" for description of spool 83 * file format: http://haiku-os.org/documents/dev/how_to_write_a_printer_driver 84 * 85 */ 86 87 88 struct _page_header_ { 89 int32 number_of_pictures; 90 off_t next_page; 91 int32 reserved[10]; 92 }; 93 94 95 static void 96 ShowError(const char *message) 97 { 98 BAlert* alert = new BAlert("Error", message, "OK"); 99 alert->Go(); 100 } 101 102 103 // #pragma mark -- PrintServerMessenger 104 105 106 namespace BPrivate { 107 108 109 class PrintServerMessenger { 110 public: 111 PrintServerMessenger(uint32 what, BMessage *input); 112 ~PrintServerMessenger(); 113 114 BMessage* Request(); 115 status_t SendRequest(); 116 117 void SetResult(BMessage* result); 118 BMessage* Result() const { return fResult; } 119 120 static status_t GetPrintServerMessenger(BMessenger& msngr); 121 122 private: 123 void RejectUserInput(); 124 void AllowUserInput(); 125 void DeleteSemaphore(); 126 static status_t MessengerThread(void *data); 127 128 uint32 fWhat; 129 BMessage* fInput; 130 BMessage* fRequest; 131 BMessage* fResult; 132 sem_id fThreadCompleted; 133 BAlert* fHiddenApplicationModalWindow; 134 }; 135 136 137 } // namespace BPrivate 138 using namespace BPrivate; 139 140 141 // #pragma mark -- BPrintJob 142 143 144 BPrintJob::BPrintJob(const char *job_name) 145 : fPrintJobName(NULL), 146 fSpoolFile(NULL), 147 fError(B_ERROR), 148 fSetupMessage(NULL), 149 fDefaultSetupMessage(NULL), 150 fCurrentPageHeader(NULL) 151 { 152 memset(&fSpoolFileHeader, 0, sizeof(print_file_header)); 153 154 if (job_name != NULL) 155 fPrintJobName = strdup(job_name); 156 157 fCurrentPageHeader = new _page_header_; 158 if (fCurrentPageHeader != NULL) 159 memset(fCurrentPageHeader, 0, sizeof(_page_header_)); 160 } 161 162 163 BPrintJob::~BPrintJob() 164 { 165 CancelJob(); 166 167 free(fPrintJobName); 168 delete fSetupMessage; 169 delete fDefaultSetupMessage; 170 delete fCurrentPageHeader; 171 } 172 173 174 status_t 175 BPrintJob::ConfigPage() 176 { 177 PrintServerMessenger messenger(PSRV_SHOW_PAGE_SETUP, fSetupMessage); 178 status_t status = messenger.SendRequest(); 179 if (status != B_OK) 180 return status; 181 182 delete fSetupMessage; 183 fSetupMessage = messenger.Result(); 184 _HandlePageSetup(fSetupMessage); 185 186 return B_OK; 187 } 188 189 190 status_t 191 BPrintJob::ConfigJob() 192 { 193 PrintServerMessenger messenger(PSRV_SHOW_PRINT_SETUP, fSetupMessage); 194 status_t status = messenger.SendRequest(); 195 if (status != B_OK) 196 return status; 197 198 delete fSetupMessage; 199 fSetupMessage = messenger.Result(); 200 if (!_HandlePrintSetup(fSetupMessage)) 201 return B_ERROR; 202 203 return B_OK; 204 } 205 206 207 void 208 BPrintJob::BeginJob() 209 { 210 // can not start a new job until it has been commited or cancelled 211 if (fSpoolFile != NULL || fCurrentPageHeader == NULL) 212 return; 213 214 // TODO show alert, setup message is required 215 if (fSetupMessage == NULL) 216 return; 217 218 // create spool file 219 BPath path; 220 status_t status = find_directory(B_USER_PRINTERS_DIRECTORY, &path); 221 if (status != B_OK) 222 return; 223 224 char *printer = _GetCurrentPrinterName(); 225 if (printer == NULL) 226 return; 227 228 path.Append(printer); 229 free(printer); 230 231 char mangledName[B_FILE_NAME_LENGTH]; 232 _GetMangledName(mangledName, B_FILE_NAME_LENGTH); 233 234 path.Append(mangledName); 235 if (path.InitCheck() != B_OK) 236 return; 237 238 // TODO: fSpoolFileName should store the name only (not path which can be 1024 bytes long) 239 strncpy(fSpoolFileName, path.Path(), sizeof(fSpoolFileName)); 240 fSpoolFile = new BFile(fSpoolFileName, B_READ_WRITE | B_CREATE_FILE); 241 242 if (fSpoolFile->InitCheck() != B_OK) { 243 CancelJob(); 244 return; 245 } 246 247 // add print_file_header 248 // page_count is updated in CommitJob() 249 // on BeOS R5 the offset to the first page was always -1 250 fSpoolFileHeader.version = 1 << 16; 251 fSpoolFileHeader.page_count = 0; 252 fSpoolFileHeader.first_page = (off_t)-1; 253 254 if (fSpoolFile->Write(&fSpoolFileHeader, sizeof(print_file_header)) 255 != sizeof(print_file_header)) { 256 CancelJob(); 257 return; 258 } 259 260 // add printer settings message 261 if (!fSetupMessage->HasString(PSRV_FIELD_CURRENT_PRINTER)) 262 fSetupMessage->AddString(PSRV_FIELD_CURRENT_PRINTER, printer); 263 264 _AddSetupSpec(); 265 _NewPage(); 266 267 // state variables 268 fAbort = 0; 269 fError = B_OK; 270 } 271 272 273 void 274 BPrintJob::CommitJob() 275 { 276 if (fSpoolFile == NULL) 277 return; 278 279 if (fSpoolFileHeader.page_count == 0) { 280 ShowError("No Pages to print!"); 281 CancelJob(); 282 return; 283 } 284 285 // update spool file 286 _EndLastPage(); 287 288 // write spool file header 289 fSpoolFile->Seek(0, SEEK_SET); 290 fSpoolFile->Write(&fSpoolFileHeader, sizeof(print_file_header)); 291 292 // set file attributes 293 app_info appInfo; 294 be_app->GetAppInfo(&appInfo); 295 const char* printerName = ""; 296 fSetupMessage->FindString(PSRV_FIELD_CURRENT_PRINTER, &printerName); 297 298 BNodeInfo info(fSpoolFile); 299 info.SetType(PSRV_SPOOL_FILETYPE); 300 301 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PAGECOUNT, B_INT32_TYPE, 0, 302 &fSpoolFileHeader.page_count, sizeof(int32)); 303 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_DESCRIPTION, B_STRING_TYPE, 0, 304 fPrintJobName, strlen(fPrintJobName) + 1); 305 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PRINTER, B_STRING_TYPE, 0, printerName, 306 strlen(printerName) + 1); 307 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, 308 PSRV_JOB_STATUS_WAITING, strlen(PSRV_JOB_STATUS_WAITING) + 1); 309 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_MIMETYPE, B_STRING_TYPE, 0, 310 appInfo.signature, strlen(appInfo.signature) + 1); 311 312 delete fSpoolFile; 313 fSpoolFile = NULL; 314 fError = B_ERROR; 315 316 // notify print server 317 BMessenger printServer; 318 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 319 return; 320 321 BMessage request(PSRV_PRINT_SPOOLED_JOB); 322 request.AddString("JobName", fPrintJobName); 323 request.AddString("Spool File", fSpoolFileName); 324 325 BMessage reply; 326 printServer.SendMessage(&request, &reply); 327 } 328 329 void 330 BPrintJob::CancelJob() 331 { 332 if (fSpoolFile == NULL) 333 return; 334 335 fAbort = 1; 336 BEntry(fSpoolFileName).Remove(); 337 delete fSpoolFile; 338 fSpoolFile = NULL; 339 } 340 341 342 void 343 BPrintJob::SpoolPage() 344 { 345 if (fSpoolFile == NULL) 346 return; 347 348 if (fCurrentPageHeader->number_of_pictures == 0) 349 return; 350 351 fSpoolFileHeader.page_count++; 352 fSpoolFile->Seek(0, SEEK_END); 353 if (fCurrentPageHeaderOffset) { 354 // update last written page_header 355 fCurrentPageHeader->next_page = fSpoolFile->Position(); 356 fSpoolFile->Seek(fCurrentPageHeaderOffset, SEEK_SET); 357 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_)); 358 fSpoolFile->Seek(fCurrentPageHeader->next_page, SEEK_SET); 359 } 360 361 _NewPage(); 362 } 363 364 365 bool 366 BPrintJob::CanContinue() 367 { 368 // Check if our local error storage is still B_OK 369 return fError == B_OK && !fAbort; 370 } 371 372 373 void 374 BPrintJob::DrawView(BView *view, BRect rect, BPoint where) 375 { 376 if (fSpoolFile == NULL) 377 return; 378 379 if (view == NULL) 380 return; 381 382 if (view->LockLooper()) { 383 BPicture picture; 384 _RecurseView(view, B_ORIGIN - rect.LeftTop(), &picture, rect); 385 _AddPicture(picture, rect, where); 386 view->UnlockLooper(); 387 } 388 } 389 390 391 BMessage * 392 BPrintJob::Settings() 393 { 394 if (fSetupMessage == NULL) 395 return NULL; 396 397 return new BMessage(*fSetupMessage); 398 } 399 400 401 void 402 BPrintJob::SetSettings(BMessage *message) 403 { 404 if (message != NULL) 405 _HandlePrintSetup(message); 406 407 delete fSetupMessage; 408 fSetupMessage = message; 409 } 410 411 412 bool 413 BPrintJob::IsSettingsMessageValid(BMessage *message) const 414 { 415 char *printerName = _GetCurrentPrinterName(); 416 if (printerName == NULL) 417 return false; 418 419 const char *name = NULL; 420 // The passed message is valid if it contains the right printer name. 421 bool valid = message != NULL 422 && message->FindString("printer_name", &name) == B_OK 423 && strcmp(printerName, name) == 0; 424 425 free(printerName); 426 return valid; 427 } 428 429 430 // Either SetSettings() or ConfigPage() has to be called prior 431 // to any of the getters otherwise they return undefined values. 432 BRect 433 BPrintJob::PaperRect() 434 { 435 if (fDefaultSetupMessage == NULL) 436 _LoadDefaultSettings(); 437 438 return fPaperSize; 439 } 440 441 442 BRect 443 BPrintJob::PrintableRect() 444 { 445 if (fDefaultSetupMessage == NULL) 446 _LoadDefaultSettings(); 447 448 return fUsableSize; 449 } 450 451 452 void 453 BPrintJob::GetResolution(int32 *xdpi, int32 *ydpi) 454 { 455 if (fDefaultSetupMessage == NULL) 456 _LoadDefaultSettings(); 457 458 if (xdpi != NULL) 459 *xdpi = fXResolution; 460 461 if (ydpi != NULL) 462 *ydpi = fYResolution; 463 } 464 465 466 int32 467 BPrintJob::FirstPage() 468 { 469 return fFirstPage; 470 } 471 472 473 int32 474 BPrintJob::LastPage() 475 { 476 return fLastPage; 477 } 478 479 480 int32 481 BPrintJob::PrinterType(void *) const 482 { 483 BMessenger printServer; 484 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 485 return B_COLOR_PRINTER; // default 486 487 BMessage reply; 488 BMessage message(PSRV_GET_ACTIVE_PRINTER); 489 printServer.SendMessage(&message, &reply); 490 491 int32 type; 492 if (reply.FindInt32("color", &type) != B_OK) 493 return B_COLOR_PRINTER; // default 494 495 return type; 496 } 497 498 499 500 // #pragma mark ----- PRIVATE ----- 501 502 503 void 504 BPrintJob::_RecurseView(BView *view, BPoint origin, BPicture *picture, 505 BRect rect) 506 { 507 ASSERT(picture != NULL); 508 509 BRegion region; 510 region.Set(BRect(rect.left, rect.top, rect.right, rect.bottom)); 511 view->fState->print_rect = rect; 512 513 view->AppendToPicture(picture); 514 view->PushState(); 515 view->SetOrigin(origin); 516 view->ConstrainClippingRegion(®ion); 517 518 if (view->ViewColor() != B_TRANSPARENT_COLOR) { 519 rgb_color highColor = view->HighColor(); 520 view->SetHighColor(view->ViewColor()); 521 view->FillRect(rect); 522 view->SetHighColor(highColor); 523 } 524 525 view->fIsPrinting = true; 526 view->Draw(rect); 527 view->fIsPrinting = false; 528 529 view->PopState(); 530 view->EndPicture(); 531 532 BView *child = view->ChildAt(0); 533 while (child != NULL) { 534 if ((child->Flags() & B_WILL_DRAW) && !child->IsHidden()) { 535 BPoint leftTop(view->Bounds().LeftTop() + child->Frame().LeftTop()); 536 BRect printRect(rect.OffsetToCopy(rect.LeftTop() - leftTop) & child->Bounds()); 537 if (printRect.IsValid()) 538 _RecurseView(child, origin + leftTop, picture, printRect); 539 } 540 child = child->NextSibling(); 541 } 542 543 if (view->Flags() & B_DRAW_ON_CHILDREN) { 544 view->AppendToPicture(picture); 545 view->PushState(); 546 view->SetOrigin(origin); 547 view->ConstrainClippingRegion(®ion); 548 view->fIsPrinting = true; 549 view->DrawAfterChildren(rect); 550 view->fIsPrinting = false; 551 view->PopState(); 552 view->EndPicture(); 553 } 554 } 555 556 557 void 558 BPrintJob::_GetMangledName(char *buffer, size_t bufferSize) const 559 { 560 snprintf(buffer, bufferSize, "%s@%lld", fPrintJobName, system_time() / 1000); 561 } 562 563 564 void 565 BPrintJob::_HandlePageSetup(BMessage *setup) 566 { 567 setup->FindRect(PSRV_FIELD_PRINTABLE_RECT, &fUsableSize); 568 setup->FindRect(PSRV_FIELD_PAPER_RECT, &fPaperSize); 569 570 // TODO verify data type (taken from libprint) 571 int64 valueInt64; 572 if (setup->FindInt64(PSRV_FIELD_XRES, &valueInt64) == B_OK) 573 fXResolution = (short)valueInt64; 574 575 if (setup->FindInt64(PSRV_FIELD_YRES, &valueInt64) == B_OK) 576 fYResolution = (short)valueInt64; 577 } 578 579 580 bool 581 BPrintJob::_HandlePrintSetup(BMessage *message) 582 { 583 _HandlePageSetup(message); 584 585 bool valid = true; 586 if (message->FindInt32(PSRV_FIELD_FIRST_PAGE, &fFirstPage) != B_OK) 587 valid = false; 588 589 if (message->FindInt32(PSRV_FIELD_LAST_PAGE, &fLastPage) != B_OK) 590 valid = false; 591 592 return valid; 593 } 594 595 596 void 597 BPrintJob::_NewPage() 598 { 599 // init, write new page_header 600 fCurrentPageHeader->next_page = 0; 601 fCurrentPageHeader->number_of_pictures = 0; 602 fCurrentPageHeaderOffset = fSpoolFile->Position(); 603 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_)); 604 } 605 606 607 void 608 BPrintJob::_EndLastPage() 609 { 610 if (!fSpoolFile) 611 return; 612 613 if (fCurrentPageHeader->number_of_pictures == 0) 614 return; 615 616 fSpoolFileHeader.page_count++; 617 fSpoolFile->Seek(0, SEEK_END); 618 if (fCurrentPageHeaderOffset) { 619 fCurrentPageHeader->next_page = 0; 620 fSpoolFile->Seek(fCurrentPageHeaderOffset, SEEK_SET); 621 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_)); 622 fSpoolFile->Seek(0, SEEK_END); 623 } 624 } 625 626 627 void 628 BPrintJob::_AddSetupSpec() 629 { 630 fSetupMessage->Flatten(fSpoolFile); 631 } 632 633 634 void 635 BPrintJob::_AddPicture(BPicture &picture, BRect &rect, BPoint &where) 636 { 637 ASSERT(fSpoolFile != NULL); 638 639 fCurrentPageHeader->number_of_pictures++; 640 fSpoolFile->Write(&where, sizeof(BRect)); 641 fSpoolFile->Write(&rect, sizeof(BPoint)); 642 picture.Flatten(fSpoolFile); 643 } 644 645 /* ! 646 * 647 * Returns a copy of the applications default printer name or NULL if it 648 * could not be obtained. Caller is responsible to free the string using free(). 649 * 650 */ 651 char * 652 BPrintJob::_GetCurrentPrinterName() const 653 { 654 BMessenger printServer; 655 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 656 return NULL; 657 658 const char *printerName = NULL; 659 660 BMessage reply; 661 BMessage message(PSRV_GET_ACTIVE_PRINTER); 662 if (printServer.SendMessage(&message, &reply) == B_OK) 663 reply.FindString("printer_name", &printerName); 664 665 if (printerName == NULL) 666 return NULL; 667 668 return strdup(printerName); 669 } 670 671 672 void 673 BPrintJob::_LoadDefaultSettings() 674 { 675 BMessenger printServer; 676 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 677 return; 678 679 BMessage message(PSRV_GET_DEFAULT_SETTINGS); 680 BMessage *reply = new BMessage; 681 682 printServer.SendMessage(&message, reply); 683 684 // Only override our settings if we don't have any settings yet 685 if (fSetupMessage == NULL) 686 _HandlePrintSetup(reply); 687 688 delete fDefaultSetupMessage; 689 fDefaultSetupMessage = reply; 690 } 691 692 693 void BPrintJob::_ReservedPrintJob1() {} 694 void BPrintJob::_ReservedPrintJob2() {} 695 void BPrintJob::_ReservedPrintJob3() {} 696 void BPrintJob::_ReservedPrintJob4() {} 697 698 699 // #pragma mark -- PrintServerMessenger 700 701 702 namespace BPrivate { 703 704 705 PrintServerMessenger::PrintServerMessenger(uint32 what, BMessage *input) 706 : fWhat(what), 707 fInput(input), 708 fRequest(NULL), 709 fResult(NULL), 710 fThreadCompleted(-1), 711 fHiddenApplicationModalWindow(NULL) 712 { 713 RejectUserInput(); 714 } 715 716 717 PrintServerMessenger::~PrintServerMessenger() 718 { 719 DeleteSemaphore(); 720 // in case SendRequest could not start the thread 721 delete fRequest; fRequest = NULL; 722 AllowUserInput(); 723 } 724 725 726 void 727 PrintServerMessenger::RejectUserInput() 728 { 729 fHiddenApplicationModalWindow = new BAlert("bogus", "app_modal", "OK"); 730 fHiddenApplicationModalWindow->DefaultButton()->SetEnabled(false); 731 fHiddenApplicationModalWindow->SetDefaultButton(NULL); 732 fHiddenApplicationModalWindow->MoveTo(-65000, -65000); 733 fHiddenApplicationModalWindow->Go(NULL); 734 } 735 736 737 void 738 PrintServerMessenger::AllowUserInput() 739 { 740 fHiddenApplicationModalWindow->Lock(); 741 fHiddenApplicationModalWindow->Quit(); 742 } 743 744 745 void 746 PrintServerMessenger::DeleteSemaphore() 747 { 748 if (fThreadCompleted >= B_OK) { 749 sem_id id = fThreadCompleted; 750 fThreadCompleted = -1; 751 delete_sem(id); 752 } 753 } 754 755 756 status_t 757 PrintServerMessenger::SendRequest() 758 { 759 fThreadCompleted = create_sem(0, "print_server_messenger_sem"); 760 if (fThreadCompleted < B_OK) 761 return B_ERROR; 762 763 thread_id id = spawn_thread(MessengerThread, "async_request", 764 B_NORMAL_PRIORITY, this); 765 if (id <= 0 || resume_thread(id) != B_OK) 766 return B_ERROR; 767 768 // Get the originating window, if it exists 769 BWindow* window = dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL))); 770 if (window) { 771 status_t err; 772 while (true) { 773 do { 774 err = acquire_sem_etc(fThreadCompleted, 1, B_RELATIVE_TIMEOUT, 775 50000); 776 // We've (probably) had our time slice taken away from us 777 } while (err == B_INTERRUPTED); 778 779 // Semaphore was finally nuked in SetResult(BMessage *) 780 if (err == B_BAD_SEM_ID) 781 break; 782 window->UpdateIfNeeded(); 783 } 784 } else { 785 // No window to update, so just hang out until we're done. 786 while (acquire_sem(fThreadCompleted) == B_INTERRUPTED); 787 } 788 789 status_t status; 790 wait_for_thread(id, &status); 791 792 return Result() != NULL ? B_OK : B_ERROR; 793 } 794 795 796 BMessage * 797 PrintServerMessenger::Request() 798 { 799 if (fRequest != NULL) 800 return fRequest; 801 802 if (fInput != NULL) { 803 fRequest = new BMessage(*fInput); 804 fRequest->what = fWhat; 805 } else 806 fRequest = new BMessage(fWhat); 807 808 return fRequest; 809 } 810 811 812 void 813 PrintServerMessenger::SetResult(BMessage *result) 814 { 815 fResult = result; 816 DeleteSemaphore(); 817 // terminate loop in thread spawned by SendRequest 818 } 819 820 821 status_t 822 PrintServerMessenger::GetPrintServerMessenger(BMessenger& messenger) 823 { 824 messenger = BMessenger(PSRV_SIGNATURE_TYPE); 825 return messenger.IsValid() ? B_OK : B_ERROR; 826 } 827 828 829 status_t 830 PrintServerMessenger::MessengerThread(void *data) 831 { 832 PrintServerMessenger* messenger = static_cast<PrintServerMessenger*>(data); 833 834 BMessenger printServer; 835 if (messenger->GetPrintServerMessenger(printServer) != B_OK) { 836 ShowError("Print Server is not responding."); 837 messenger->SetResult(NULL); 838 return B_ERROR; 839 } 840 841 BMessage *request = messenger->Request(); 842 if (request == NULL) { 843 messenger->SetResult(NULL); 844 return B_ERROR; 845 } 846 847 848 BMessage reply; 849 if (printServer.SendMessage(request, &reply) != B_OK 850 || reply.what != 'okok' ) { 851 messenger->SetResult(NULL); 852 return B_ERROR; 853 } 854 855 messenger->SetResult(new BMessage(reply)); 856 return B_OK; 857 } 858 859 860 } // namespace BPrivate 861