xref: /haiku/src/kits/interface/PrintJob.cpp (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
1 /*
2  * Copyright 2001-2005, Haiku.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  				I.R. Adema
7  				Stefano Ceccherini (burton666@libero.it)
8  */
9 
10 #include <Alert.h>
11 #include <Application.h>
12 #include <Debug.h>
13 #include <Entry.h>
14 #include <File.h>
15 #include <FindDirectory.h>
16 #include <Messenger.h>
17 #include <Path.h>
18 #include <PrintJob.h>
19 #include <Roster.h>
20 #include <View.h>
21 
22 #include <pr_server.h>
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 
29 static BMessenger *sPrintServer = NULL;
30 
31 
32 static void
33 EnsureValidMessenger()
34 {
35 	if (sPrintServer == NULL)
36     	sPrintServer = new BMessenger;
37 
38     if (!sPrintServer->IsValid())
39     	*sPrintServer = BMessenger(PSRV_SIGNATURE_TYPE);
40 }
41 
42 
43 BPrintJob::BPrintJob(const char *job_name)
44 	:
45 	print_job_name(NULL),
46 	page_number(0),
47 	spoolFile(NULL),
48 	pr_error(B_OK),
49 	setup_msg(NULL),
50 	default_setup_msg(NULL),
51 	m_curPageHeader(NULL)
52 {
53 	memset(&current_header, 0, sizeof(current_header));
54 	if (job_name != NULL)
55 		print_job_name = strdup(job_name);
56 }
57 
58 
59 BPrintJob::~BPrintJob()
60 {
61 	free(print_job_name);
62 }
63 
64 
65 void
66 BPrintJob::BeginJob()
67 {
68 	// TODO: this should be improved:
69 	// - Take system printers into account
70 	// - handle the case where the path doesn't exist
71 	// - more
72 	BPath path;
73 	status_t status = find_directory(B_USER_PRINTERS_DIRECTORY, &path);
74 	if (status < B_OK)
75 		return;
76 
77 	char *printer = GetCurrentPrinterName();
78 	if (printer == NULL)
79 		return;
80 
81 	path.Append(printer);
82 	free(printer);
83 
84 	char mangledName[B_FILE_NAME_LENGTH];
85 	MangleName(mangledName);
86 
87 	path.Append(mangledName);
88 
89 	if (path.InitCheck() < B_OK)
90 		return;
91 
92 	stop_the_show = 0;
93 	page_number = 0;
94 
95 	strncpy(spool_file_name, path.Path(), sizeof(spool_file_name));
96 	spoolFile = new BFile(spool_file_name, B_READ_WRITE|B_CREATE_FILE);
97 
98 	AddSetupSpec();
99 }
100 
101 
102 void
103 BPrintJob::CommitJob()
104 {
105 	if (page_number <= 0) {
106 		BAlert *alert = new BAlert("Alert", "No Pages to print!", "Okay");
107 		alert->Go();
108 		CancelJob();
109 		return;
110 	}
111 
112 	EnsureValidMessenger();
113 	BMessage *message = new BMessage(PSRV_GET_ACTIVE_PRINTER);
114     BMessage *reply = new BMessage;
115 
116     const char *printerName = NULL;
117     if (sPrintServer->SendMessage(message, reply) < B_OK ||
118     	reply->FindString("printer_name", &printerName) < B_OK) {
119     	// TODO: Show an alert
120     	delete message;
121    		delete reply;
122     	return;
123     }
124 
125     delete message;
126     delete reply;
127 
128     app_info appInfo;
129     be_app->GetAppInfo(&appInfo);
130 
131     spoolFile->WriteAttr("_spool/Page Count", B_INT32_TYPE, 0, &page_number, sizeof(int32));
132     spoolFile->WriteAttr("_spool/Description", B_STRING_TYPE, 0, print_job_name, strlen(print_job_name) + 1);
133     spoolFile->WriteAttr("_spool/Printer", B_STRING_TYPE, 0, printerName, strlen(printerName) + 1);
134 	spoolFile->WriteAttr("_spool/Status", B_STRING_TYPE, 0, "waiting", strlen("waiting") + 1);
135 	spoolFile->WriteAttr("_spool/MimeType", B_STRING_TYPE, 0, appInfo.signature, strlen(appInfo.signature) + 1);
136 
137 	message = new BMessage(PSRV_PRINT_SPOOLED_JOB);
138 	reply = new BMessage;
139 
140 	message->AddString("JobName", print_job_name);
141 	message->AddString("Spool File", spool_file_name);
142 	sPrintServer->SendMessage(message, reply);
143 
144 	delete message;
145 	delete reply;
146 }
147 
148 
149 status_t
150 BPrintJob::ConfigJob()
151 {
152 	// TODO: Implement
153     return B_OK;
154 }
155 
156 
157 void
158 BPrintJob::CancelJob()
159 {
160 	stop_the_show = 1;
161 	BEntry(spool_file_name).Remove();
162 	delete spoolFile;
163 }
164 
165 
166 status_t
167 BPrintJob::ConfigPage()
168 {
169     return B_OK;
170 }
171 
172 
173 void
174 BPrintJob::SpoolPage()
175 {
176 	NewPage();
177 }
178 
179 
180 bool
181 BPrintJob::CanContinue()
182 {
183 		// Check if our local error storage is still B_OK
184     return pr_error == B_OK && !stop_the_show;
185 }
186 
187 
188 void
189 BPrintJob::DrawView(BView *view, BRect rect, BPoint where)
190 {
191 	if (view == NULL)
192 		return;
193 
194 	// TODO: Finish me
195 	if (view->LockLooper()) {
196 		BPicture *picture = new BPicture;
197 		RecurseView(view, where, picture, rect);
198 		AddPicture(picture, &rect, where);
199 
200 		view->UnlockLooper();
201 		delete picture;
202 	}
203 }
204 
205 
206 BMessage *
207 BPrintJob::Settings()
208 {
209     BMessage *message = NULL;
210 
211     if (setup_msg != NULL)
212     	message = new BMessage(*setup_msg);
213 
214     return message;
215 }
216 
217 
218 void
219 BPrintJob::SetSettings(BMessage *message)
220 {
221 	if (message != NULL) {
222 		HandlePageSetup(message);
223 		HandlePrintSetup(message);
224 		delete setup_msg;
225 		setup_msg = message;
226 	}
227 }
228 
229 
230 bool
231 BPrintJob::IsSettingsMessageValid(BMessage *message) const
232 {
233 	const char *messageName = NULL;
234     char *printerName = GetCurrentPrinterName();
235 
236     bool result = false;
237 
238     // The passed message is valid if it contains the right printer name.
239     if (message != NULL
240     	&& message->FindString("printer_name", &messageName) == B_OK
241     	&& strcmp(printerName, messageName) == 0)
242     	result = true;
243 
244     free(printerName);
245 
246     return result;
247 }
248 
249 
250 BRect
251 BPrintJob::PaperRect()
252 {
253     if (default_setup_msg == NULL)
254     	LoadDefaultSettings();
255 
256     return paper_size;
257 }
258 
259 
260 BRect
261 BPrintJob::PrintableRect()
262 {
263 	if (default_setup_msg == NULL)
264     	LoadDefaultSettings();
265 
266     return usable_size;
267 }
268 
269 
270 void
271 BPrintJob::GetResolution(int32 *xdpi, int32 *ydpi)
272 {
273 	int32 xres = -1, yres = -1;
274 
275 	const BMessage *message = NULL;
276 
277 	if (setup_msg != NULL)
278 		message = setup_msg;
279 	else {
280 		if (default_setup_msg == NULL)
281 			LoadDefaultSettings();
282 		message = default_setup_msg;
283 	}
284 
285 	if (message != NULL) {
286 		if (message->HasInt32(PSRV_FIELD_XRES))
287 			message->FindInt32(PSRV_FIELD_XRES, &xres);
288 		if (message->HasInt32(PSRV_FIELD_YRES))
289 			message->FindInt32(PSRV_FIELD_YRES, &yres);
290 	}
291 
292 	if (xdpi != NULL)
293 		*xdpi = xres;
294 	if (ydpi != NULL)
295 		*ydpi = yres;
296 }
297 
298 
299 int32
300 BPrintJob::FirstPage()
301 {
302     return first_page;
303 }
304 
305 
306 int32
307 BPrintJob::LastPage()
308 {
309     return last_page;
310 }
311 
312 
313 int32
314 BPrintJob::PrinterType(void *) const
315 {
316     EnsureValidMessenger();
317 
318     BMessage message(PSRV_GET_ACTIVE_PRINTER);
319     BMessage reply;
320 
321     sPrintServer->SendMessage(&message, &reply);
322 
323     int32 type = B_COLOR_PRINTER;
324     reply.FindInt32("color", &type);
325 
326     return type;
327 }
328 
329 
330 #if 0
331 #pragma mark ----- PRIVATE -----
332 #endif
333 
334 
335 void
336 BPrintJob::RecurseView(BView *view, BPoint origin,
337                        BPicture *picture, BRect rect)
338 {
339 	ASSERT(picture != NULL);
340 
341 	view->AppendToPicture(picture);
342 	view->f_is_printing = true;
343 	view->Draw(rect);
344 	view->f_is_printing = false;
345 	view->EndPicture();
346 
347 	// TODO: call recursively on every view's children.
348 }
349 
350 
351 void
352 BPrintJob::MangleName(char *filename)
353 {
354 	char sysTime[10];
355 	snprintf(sysTime, sizeof(sysTime), "@%lld", system_time() / 1000);
356 	strncpy(filename, print_job_name, B_FILE_NAME_LENGTH - sizeof(sysTime));
357 	strcat(filename, sysTime);
358 }
359 
360 
361 void
362 BPrintJob::HandlePageSetup(BMessage *setup)
363 {
364 }
365 
366 
367 bool
368 BPrintJob::HandlePrintSetup(BMessage *message)
369 {
370     if (message->HasRect(PSRV_FIELD_PRINTABLE_RECT))
371     	message->FindRect(PSRV_FIELD_PRINTABLE_RECT, &usable_size);
372     if (message->HasRect(PSRV_FIELD_PAPER_RECT))
373     	message->FindRect(PSRV_FIELD_PAPER_RECT, &paper_size);
374     if (message->HasInt32(PSRV_FIELD_FIRST_PAGE))
375     	message->FindInt32(PSRV_FIELD_FIRST_PAGE, &first_page);
376     if (message->HasInt32(PSRV_FIELD_LAST_PAGE))
377     	message->FindInt32(PSRV_FIELD_LAST_PAGE, &last_page);
378 
379     return true;
380 }
381 
382 
383 void
384 BPrintJob::NewPage()
385 {
386 	// TODO: this function could be removed, and its functionality moved
387 	// to SpoolPage()
388 	// TODO: Implement for real
389 	page_number++;
390 }
391 
392 
393 void
394 BPrintJob::EndLastPage()
395 {
396 }
397 
398 
399 void
400 BPrintJob::AddSetupSpec()
401 {
402 	if (setup_msg != NULL && spoolFile != NULL)
403 		setup_msg->Flatten(spoolFile);
404 }
405 
406 
407 void
408 BPrintJob::AddPicture(BPicture *picture, BRect *rect, BPoint where)
409 {
410 	ASSERT(picture != NULL);
411 	ASSERT(spoolFile != NULL);
412 	ASSERT(rect != NULL);
413 
414 	spoolFile->Write(&where, sizeof(where));
415 	spoolFile->Write(rect, sizeof(*rect));
416 	picture->Flatten(spoolFile);
417 }
418 
419 
420 char *
421 BPrintJob::GetCurrentPrinterName() const
422 {
423 	EnsureValidMessenger();
424 
425     BMessage message(PSRV_GET_ACTIVE_PRINTER);
426     BMessage reply;
427 
428     const char *printerName = NULL;
429 
430     if (sPrintServer->SendMessage(&message, &reply) == B_OK)
431     	reply.FindString("printer_name", &printerName);
432 
433     return printerName != NULL ? strdup(printerName) : NULL;
434 }
435 
436 
437 void
438 BPrintJob::LoadDefaultSettings()
439 {
440 	EnsureValidMessenger();
441 
442 	BMessage message(PSRV_GET_DEFAULT_SETTINGS);
443     BMessage *reply = new BMessage;
444 
445     sPrintServer->SendMessage(&message, reply);
446 
447     if (reply->HasRect(PSRV_FIELD_PAPER_RECT))
448     	reply->FindRect(PSRV_FIELD_PAPER_RECT, &paper_size);
449     if (reply->HasRect(PSRV_FIELD_PRINTABLE_RECT))
450     	reply->FindRect(PSRV_FIELD_PRINTABLE_RECT, &usable_size);
451 
452     delete default_setup_msg;
453     default_setup_msg = reply;
454 }
455 
456 
457 void BPrintJob::_ReservedPrintJob1() {}
458 void BPrintJob::_ReservedPrintJob2() {}
459 void BPrintJob::_ReservedPrintJob3() {}
460 void BPrintJob::_ReservedPrintJob4() {}
461