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