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