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