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