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