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