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