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