xref: /haiku/src/libs/print/libprint/PrinterDriver.cpp (revision 03187b607b2b5eec7ee059f1ead09bdba14991fb)
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 		off_t offset = printJob->Position();
147 		PreviewWindow *preview = new PreviewWindow(printJob, true);
148 		if (preview->Go() != B_OK) {
149 			return new BMessage('okok');
150 		}
151 		printJob->Seek(offset, SEEK_SET);
152 	}
153 	BMessage *result = fGraphicsDriver->takeJob(printJob);
154 
155 	DUMP_BMESSAGE(result);
156 	DBGMSG(("<%s: take_job\n", GetDriverName()));
157 	return result;
158 }
159 
160 // read settings from spool folder attribute
161 bool
162 PrinterDriver::ReadSettings(const char* attrName, BMessage* settings)
163 {
164 	attr_info info;
165 	char*  data;
166 	ssize_t size;
167 
168 	settings->MakeEmpty();
169 
170 	if (fSpoolFolder->GetAttrInfo(attrName, &info) == B_OK && info.size > 0) {
171 		data = new char[info.size];
172 		auto_ptr<char> _data(data);
173 		size = fSpoolFolder->ReadAttr(attrName, B_MESSAGE_TYPE, 0, data, info.size);
174 		if (size == info.size && settings->Unflatten(data) == B_OK) {
175 			return true;
176 		}
177 	}
178 	return false;
179 }
180 
181 // write settings to spool folder attribute
182 void
183 PrinterDriver::WriteSettings(const char* attrName, BMessage* settings)
184 {
185 	if (settings == NULL || settings->what != 'okok') return;
186 
187 	size_t size;
188 	char* data;
189 
190 	size = settings->FlattenedSize();
191 	data = new char[size];
192 	auto_ptr<char> _data(data);
193 
194 	if (data != NULL && settings->Flatten(data, size) == B_OK) {
195 		fSpoolFolder->WriteAttr(attrName, B_MESSAGE_TYPE, 0, data, size);
196 	}
197 }
198 
199 // read settings from spool folder attribute and merge them to current settings
200 void
201 PrinterDriver::MergeWithPreviousSettings(const char* attrName, BMessage* settings)
202 {
203 	if (settings == NULL) return;
204 
205 	BMessage stored;
206 	if (ReadSettings(attrName, &stored)) {
207 		AddFields(&stored, settings);
208 		*settings = stored;
209 	}
210 }
211 
212 // Implementation of PrinterDriverInstance
213 
214 class PrinterDriverInstance
215 {
216 public:
217 	PrinterDriverInstance(BNode* spoolFolder = NULL);
218 	~PrinterDriverInstance();
219 	PrinterDriver* GetPrinterDriver() { return fInstance; }
220 
221 private:
222 	PrinterDriver* fInstance;
223 };
224 
225 PrinterDriverInstance::PrinterDriverInstance(BNode* spoolFolder)
226 {
227 	fInstance = instantiate_printer_driver(spoolFolder);
228 	if (fInstance != NULL) {
229 		fInstance->InitPrinterDataAndCap();
230 	}
231 }
232 
233 PrinterDriverInstance::~PrinterDriverInstance()
234 {
235 	delete fInstance;
236 	fInstance = NULL;
237 }
238 
239 
240 // printer driver add-on functions
241 
242 char *add_printer(char *printerName)
243 {
244 	BPath path;
245 	BNode folder;
246 	BNode* spoolFolder = NULL;
247 	// get spool folder
248 	if (find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK &&
249 		path.Append(printerName) == B_OK &&
250 		folder.SetTo(path.Path()) == B_OK) {
251 		spoolFolder = &folder;
252 	}
253 
254 	PrinterDriverInstance instance(spoolFolder);
255 	return instance.GetPrinterDriver()->AddPrinter(printerName);
256 }
257 
258 BMessage *config_page(BNode *spoolFolder, BMessage *settings)
259 {
260 	PrinterDriverInstance instance(spoolFolder);
261 	return instance.GetPrinterDriver()->ConfigPage(settings);
262 }
263 
264 BMessage *config_job(BNode *spoolFolder, BMessage *settings)
265 {
266 	PrinterDriverInstance instance(spoolFolder);
267 	return instance.GetPrinterDriver()->ConfigJob(settings);
268 }
269 
270 BMessage *take_job(BFile *printJob, BNode *spoolFolder, BMessage *settings)
271 {
272 	PrinterDriverInstance instance(spoolFolder);
273 	return instance.GetPrinterDriver()->TakeJob(printJob, settings);
274 }
275 
276 // main entry if printer driver is launched directly
277 
278 int main(int argc, char* argv[])
279 {
280 	PrinterDriverInstance instance;
281 	instance.GetPrinterDriver()->About();
282 	return 0;
283 }
284