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
PrinterDriver(BNode * spoolFolder)33 PrinterDriver::PrinterDriver(BNode* spoolFolder)
34 :
35 fSpoolFolder(spoolFolder),
36 fPrinterData(NULL),
37 fPrinterCap(NULL),
38 fGraphicsDriver(NULL)
39 {
40 }
41
~PrinterDriver()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*
InstantiatePrinterData(BNode * node)56 PrinterDriver::InstantiatePrinterData(BNode* node)
57 {
58 return new PrinterData(node);
59 }
60
61 void
InitPrinterDataAndCap()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
About()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*
AddPrinter(char * printerName)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*
ConfigPage(BMessage * settings)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*
ConfigJob(BMessage * settings)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*
TakeJob(BFile * printJob,BMessage * settings)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
_ReadSettings(const char * attrName,BMessage * settings)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
_WriteSettings(const char * attrName,BMessage * settings)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
_MergeWithPreviousSettings(const char * attrName,BMessage * settings)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();
GetPrinterDriver()231 PrinterDriver* GetPrinterDriver() { return fInstance; }
232
233 private:
234 PrinterDriver* fInstance;
235 };
236
PrinterDriverInstance(BNode * spoolFolder)237 PrinterDriverInstance::PrinterDriverInstance(BNode* spoolFolder)
238 {
239 fInstance = instantiate_printer_driver(spoolFolder);
240 if (fInstance != NULL) {
241 fInstance->InitPrinterDataAndCap();
242 }
243 }
244
~PrinterDriverInstance()245 PrinterDriverInstance::~PrinterDriverInstance()
246 {
247 delete fInstance;
248 fInstance = NULL;
249 }
250
251
252 // printer driver add-on functions
253
add_printer(char * printerName)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
config_page(BNode * spoolFolder,BMessage * settings)270 BMessage *config_page(BNode *spoolFolder, BMessage *settings)
271 {
272 PrinterDriverInstance instance(spoolFolder);
273 return instance.GetPrinterDriver()->ConfigPage(settings);
274 }
275
config_job(BNode * spoolFolder,BMessage * settings)276 BMessage *config_job(BNode *spoolFolder, BMessage *settings)
277 {
278 PrinterDriverInstance instance(spoolFolder);
279 return instance.GetPrinterDriver()->ConfigJob(settings);
280 }
281
take_job(BFile * printJob,BNode * spoolFolder,BMessage * settings)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
main(int argc,char * argv[])290 int main(int argc, char* argv[])
291 {
292 PrinterDriverInstance instance;
293 instance.GetPrinterDriver()->About();
294 return 0;
295 }
296