xref: /haiku/src/libs/print/libprint/PrinterDriver.cpp (revision b8a45b3a2df2379b4301bf3bd5949b9a105be4ba)
1 /*
2  * PrinterDriver.cpp
3  * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4  * Copyright 2004 Michael Pfeiffer.
5  */
6 
7 #include "PrinterDriver.h"
8 
9 #include <fs_attr.h> // for attr_info
10 #include <DataIO.h>
11 #include <File.h>
12 #include <FindDirectory.h>
13 #include <Message.h>
14 #include <Node.h>
15 #include <Path.h>
16 #include <StackOrHeapArray.h>
17 #include <String.h>
18 
19 #include "AboutBox.h"
20 #include "AddPrinterDlg.h"
21 #include "DbgMsg.h"
22 #include "Exports.h"
23 #include "GraphicsDriver.h"
24 #include "PrinterCap.h"
25 #include "PrinterData.h"
26 #include "UIDriver.h"
27 #include "Preview.h"
28 #include "PrintUtils.h"
29 
30 
31 // Implementation of PrinterDriver
32 
33 PrinterDriver::PrinterDriver(BNode* spoolFolder)
34 	:
35 	fSpoolFolder(spoolFolder),
36 	fPrinterData(NULL),
37 	fPrinterCap(NULL),
38 	fGraphicsDriver(NULL)
39 {
40 }
41 
42 PrinterDriver::~PrinterDriver()
43 {
44 	delete fGraphicsDriver;
45 	fGraphicsDriver = NULL;
46 
47 	delete fPrinterCap;
48 	fPrinterCap = NULL;
49 
50 	delete fPrinterData;
51 	fPrinterData = NULL;
52 }
53 
54 
55 PrinterData*
56 PrinterDriver::InstantiatePrinterData(BNode* node)
57 {
58 	return new PrinterData(node);
59 }
60 
61 void
62 PrinterDriver::InitPrinterDataAndCap() {
63 	fPrinterData = InstantiatePrinterData(fSpoolFolder);
64 	fPrinterData->Load();
65 	// NOTE: moved the load above from the constructor of PrinterData as
66 	//   we're inheriting from PrinterData and want our overridden versions
67 	//   of load to be called
68 	fPrinterCap = InstantiatePrinterCap(fPrinterData);
69 }
70 
71 void
72 PrinterDriver::About()
73 {
74 	BString copyright;
75 	copyright = "libprint Copyright © 1999-2000 Y.Takagi\n";
76 	copyright << GetCopyright();
77 	copyright << "All Rights Reserved.";
78 
79 	AboutBox app(GetSignature(), GetDriverName(), GetVersion(), copyright.String());
80 	app.Run();
81 }
82 
83 char*
84 PrinterDriver::AddPrinter(char* printerName)
85 {
86 	// print_server has created a spool folder with name printerName in
87 	// folder B_USER_PRINTERS_DIRECTORY. It can be used to store
88 	// settings in the folder attributes.
89 	DBGMSG((">%s: add_printer\n", GetDriverName()));
90 	DBGMSG(("\tprinter_name: %s\n", printerName));
91 	DBGMSG(("<%s: add_printer\n", GetDriverName()));
92 
93 	if (fPrinterCap->Supports(PrinterCap::kProtocolClass)) {
94 		if (fPrinterCap->CountCap(PrinterCap::kProtocolClass) > 1) {
95 			AddPrinterDlg *dialog;
96 			dialog = new AddPrinterDlg(fPrinterData, fPrinterCap);
97 			if (dialog->Go() != B_OK) {
98 				// dialog canceled
99 				return NULL;
100 			}
101 		} else {
102 			const ProtocolClassCap* pcCap;
103 			pcCap = (const ProtocolClassCap*)fPrinterCap->GetDefaultCap(
104 				PrinterCap::kProtocolClass);
105 			if (pcCap != NULL) {
106 				fPrinterData->SetProtocolClass(pcCap->fProtocolClass);
107 				fPrinterData->Save();
108 			}
109 		}
110 	}
111 	return printerName;
112 }
113 
114 BMessage*
115 PrinterDriver::ConfigPage(BMessage* settings)
116 {
117 	DBGMSG((">%s: config_page\n", GetDriverName()));
118 	DUMP_BMESSAGE(settings);
119 	DUMP_BNODE(fSpoolFolder);
120 
121 	BMessage pageSettings(*settings);
122 	_MergeWithPreviousSettings(kAttrPageSettings, &pageSettings);
123 	UIDriver uiDriver(&pageSettings, fPrinterData, fPrinterCap);
124 	BMessage *result = uiDriver.ConfigPage();
125 	_WriteSettings(kAttrPageSettings, result);
126 
127 	DUMP_BMESSAGE(result);
128 	DBGMSG(("<%s: config_page\n", GetDriverName()));
129 	return result;
130 }
131 
132 BMessage*
133 PrinterDriver::ConfigJob(BMessage* settings)
134 {
135 	DBGMSG((">%s: config_job\n", GetDriverName()));
136 	DUMP_BMESSAGE(settings);
137 	DUMP_BNODE(fSpoolFolder);
138 
139 	BMessage jobSettings(*settings);
140 	_MergeWithPreviousSettings(kAttrJobSettings, &jobSettings);
141 	UIDriver uiDriver(&jobSettings, fPrinterData, fPrinterCap);
142 	BMessage *result = uiDriver.ConfigJob();
143 	_WriteSettings(kAttrJobSettings, result);
144 
145 	DUMP_BMESSAGE(result);
146 	DBGMSG(("<%s: config_job\n", GetDriverName()));
147 	return result;
148 }
149 
150 BMessage*
151 PrinterDriver::TakeJob(BFile* printJob, BMessage* settings)
152 {
153 	DBGMSG((">%s: take_job\n", GetDriverName()));
154 	DUMP_BMESSAGE(settings);
155 	DUMP_BNODE(fSpoolFolder);
156 
157 	fGraphicsDriver = InstantiateGraphicsDriver(settings, fPrinterData, fPrinterCap);
158 	const JobData* jobData = fGraphicsDriver->GetJobData(printJob);
159 	if (jobData != NULL && jobData->GetShowPreview()) {
160 		off_t offset = printJob->Position();
161 		PreviewWindow *preview = new PreviewWindow(printJob, true);
162 		if (preview->Go() != B_OK) {
163 			return new BMessage('okok');
164 		}
165 		printJob->Seek(offset, SEEK_SET);
166 	}
167 	BMessage *result = fGraphicsDriver->TakeJob(printJob);
168 
169 	DUMP_BMESSAGE(result);
170 	DBGMSG(("<%s: take_job\n", GetDriverName()));
171 	return result;
172 }
173 
174 // read settings from spool folder attribute
175 bool
176 PrinterDriver::_ReadSettings(const char* attrName, BMessage* settings)
177 {
178 	attr_info info;
179 	ssize_t size;
180 
181 	settings->MakeEmpty();
182 
183 	if (fSpoolFolder->GetAttrInfo(attrName, &info) == B_OK && info.size > 0) {
184 		BStackOrHeapArray<char, 0> data(info.size);
185 		if (!data.IsValid())
186 			return false;
187 		size = fSpoolFolder->ReadAttr(attrName, B_MESSAGE_TYPE, 0, data, info.size);
188 		if (size == info.size && settings->Unflatten(data) == B_OK) {
189 			return true;
190 		}
191 	}
192 	return false;
193 }
194 
195 // write settings to spool folder attribute
196 void
197 PrinterDriver::_WriteSettings(const char* attrName, BMessage* settings)
198 {
199 	if (settings == NULL || settings->what != 'okok') return;
200 
201 	status_t status;
202 	BMallocIO data;
203 	status = settings->Flatten(&data);
204 
205 	if (status == B_OK) {
206 		fSpoolFolder->WriteAttr(attrName, B_MESSAGE_TYPE, 0, data.Buffer(),
207 			data.BufferLength());
208 	}
209 }
210 
211 // read settings from spool folder attribute and merge them to current settings
212 void
213 PrinterDriver::_MergeWithPreviousSettings(const char* attrName, BMessage* settings)
214 {
215 	if (settings == NULL) return;
216 
217 	BMessage stored;
218 	if (_ReadSettings(attrName, &stored)) {
219 		AddFields(&stored, settings);
220 		*settings = stored;
221 	}
222 }
223 
224 // Implementation of PrinterDriverInstance
225 
226 class PrinterDriverInstance
227 {
228 public:
229 	PrinterDriverInstance(BNode* spoolFolder = NULL);
230 	~PrinterDriverInstance();
231 	PrinterDriver* GetPrinterDriver() { return fInstance; }
232 
233 private:
234 	PrinterDriver* fInstance;
235 };
236 
237 PrinterDriverInstance::PrinterDriverInstance(BNode* spoolFolder)
238 {
239 	fInstance = instantiate_printer_driver(spoolFolder);
240 	if (fInstance != NULL) {
241 		fInstance->InitPrinterDataAndCap();
242 	}
243 }
244 
245 PrinterDriverInstance::~PrinterDriverInstance()
246 {
247 	delete fInstance;
248 	fInstance = NULL;
249 }
250 
251 
252 // printer driver add-on functions
253 
254 char *add_printer(char *printerName)
255 {
256 	BPath path;
257 	BNode folder;
258 	BNode* spoolFolder = NULL;
259 	// get spool folder
260 	if (find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK &&
261 		path.Append(printerName) == B_OK &&
262 		folder.SetTo(path.Path()) == B_OK) {
263 		spoolFolder = &folder;
264 	}
265 
266 	PrinterDriverInstance instance(spoolFolder);
267 	return instance.GetPrinterDriver()->AddPrinter(printerName);
268 }
269 
270 BMessage *config_page(BNode *spoolFolder, BMessage *settings)
271 {
272 	PrinterDriverInstance instance(spoolFolder);
273 	return instance.GetPrinterDriver()->ConfigPage(settings);
274 }
275 
276 BMessage *config_job(BNode *spoolFolder, BMessage *settings)
277 {
278 	PrinterDriverInstance instance(spoolFolder);
279 	return instance.GetPrinterDriver()->ConfigJob(settings);
280 }
281 
282 BMessage *take_job(BFile *printJob, BNode *spoolFolder, BMessage *settings)
283 {
284 	PrinterDriverInstance instance(spoolFolder);
285 	return instance.GetPrinterDriver()->TakeJob(printJob, settings);
286 }
287 
288 // main entry if printer driver is launched directly
289 
290 int main(int argc, char* argv[])
291 {
292 	PrinterDriverInstance instance;
293 	instance.GetPrinterDriver()->About();
294 	return 0;
295 }
296