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 : 34 fSpoolFolder(spoolFolder), 35 fPrinterData(NULL), 36 fPrinterCap(NULL), 37 fGraphicsDriver(NULL) 38 { 39 } 40 41 PrinterDriver::~PrinterDriver() 42 { 43 delete fGraphicsDriver; 44 fGraphicsDriver = NULL; 45 46 delete fPrinterCap; 47 fPrinterCap = NULL; 48 49 delete fPrinterData; 50 fPrinterData = NULL; 51 } 52 53 54 PrinterData* 55 PrinterDriver::InstantiatePrinterData(BNode* node) 56 { 57 return new PrinterData(node); 58 } 59 60 void 61 PrinterDriver::InitPrinterDataAndCap() { 62 fPrinterData = InstantiatePrinterData(fSpoolFolder); 63 fPrinterData->Load(); 64 // NOTE: moved the load above from the constructor of PrinterData as 65 // we're inheriting from PrinterData and want our overridden versions 66 // of load to be called 67 fPrinterCap = InstantiatePrinterCap(fPrinterData); 68 } 69 70 void 71 PrinterDriver::About() 72 { 73 BString copyright; 74 copyright = "libprint Copyright © 1999-2000 Y.Takagi\n"; 75 copyright << GetCopyright(); 76 copyright << "All Rights Reserved."; 77 78 AboutBox app(GetSignature(), GetDriverName(), GetVersion(), copyright.String()); 79 app.Run(); 80 } 81 82 char* 83 PrinterDriver::AddPrinter(char* printerName) 84 { 85 // print_server has created a spool folder with name printerName in 86 // folder B_USER_PRINTERS_DIRECTORY. It can be used to store 87 // settings in the folder attributes. 88 DBGMSG((">%s: add_printer\n", GetDriverName())); 89 DBGMSG(("\tprinter_name: %s\n", printerName)); 90 DBGMSG(("<%s: add_printer\n", GetDriverName())); 91 92 if (fPrinterCap->Supports(PrinterCap::kProtocolClass)) { 93 if (fPrinterCap->CountCap(PrinterCap::kProtocolClass) > 1) { 94 AddPrinterDlg *dialog; 95 dialog = new AddPrinterDlg(fPrinterData, fPrinterCap); 96 if (dialog->Go() != B_OK) { 97 // dialog canceled 98 return NULL; 99 } 100 } else { 101 const ProtocolClassCap* pcCap; 102 pcCap = (const ProtocolClassCap*)fPrinterCap->GetDefaultCap( 103 PrinterCap::kProtocolClass); 104 if (pcCap != NULL) { 105 fPrinterData->SetProtocolClass(pcCap->fProtocolClass); 106 fPrinterData->Save(); 107 } 108 } 109 } 110 return printerName; 111 } 112 113 BMessage* 114 PrinterDriver::ConfigPage(BMessage* settings) 115 { 116 DBGMSG((">%s: config_page\n", GetDriverName())); 117 DUMP_BMESSAGE(settings); 118 DUMP_BNODE(fSpoolFolder); 119 120 BMessage pageSettings(*settings); 121 _MergeWithPreviousSettings(kAttrPageSettings, &pageSettings); 122 UIDriver uiDriver(&pageSettings, fPrinterData, fPrinterCap); 123 BMessage *result = uiDriver.ConfigPage(); 124 _WriteSettings(kAttrPageSettings, result); 125 126 DUMP_BMESSAGE(result); 127 DBGMSG(("<%s: config_page\n", GetDriverName())); 128 return result; 129 } 130 131 BMessage* 132 PrinterDriver::ConfigJob(BMessage* settings) 133 { 134 DBGMSG((">%s: config_job\n", GetDriverName())); 135 DUMP_BMESSAGE(settings); 136 DUMP_BNODE(fSpoolFolder); 137 138 BMessage jobSettings(*settings); 139 _MergeWithPreviousSettings(kAttrJobSettings, &jobSettings); 140 UIDriver uiDriver(&jobSettings, fPrinterData, fPrinterCap); 141 BMessage *result = uiDriver.ConfigJob(); 142 _WriteSettings(kAttrJobSettings, result); 143 144 DUMP_BMESSAGE(result); 145 DBGMSG(("<%s: config_job\n", GetDriverName())); 146 return result; 147 } 148 149 BMessage* 150 PrinterDriver::TakeJob(BFile* printJob, BMessage* settings) 151 { 152 DBGMSG((">%s: take_job\n", GetDriverName())); 153 DUMP_BMESSAGE(settings); 154 DUMP_BNODE(fSpoolFolder); 155 156 fGraphicsDriver = InstantiateGraphicsDriver(settings, fPrinterData, fPrinterCap); 157 const JobData* jobData = fGraphicsDriver->GetJobData(printJob); 158 if (jobData != NULL && jobData->GetShowPreview()) { 159 off_t offset = printJob->Position(); 160 PreviewWindow *preview = new PreviewWindow(printJob, true); 161 if (preview->Go() != B_OK) { 162 return new BMessage('okok'); 163 } 164 printJob->Seek(offset, SEEK_SET); 165 } 166 BMessage *result = fGraphicsDriver->TakeJob(printJob); 167 168 DUMP_BMESSAGE(result); 169 DBGMSG(("<%s: take_job\n", GetDriverName())); 170 return result; 171 } 172 173 // read settings from spool folder attribute 174 bool 175 PrinterDriver::_ReadSettings(const char* attrName, BMessage* settings) 176 { 177 attr_info info; 178 char* data; 179 ssize_t size; 180 181 settings->MakeEmpty(); 182 183 if (fSpoolFolder->GetAttrInfo(attrName, &info) == B_OK && info.size > 0) { 184 data = new char[info.size]; 185 auto_ptr<char> _data(data); 186 size = fSpoolFolder->ReadAttr(attrName, B_MESSAGE_TYPE, 0, data, info.size); 187 if (size == info.size && settings->Unflatten(data) == B_OK) { 188 return true; 189 } 190 } 191 return false; 192 } 193 194 // write settings to spool folder attribute 195 void 196 PrinterDriver::_WriteSettings(const char* attrName, BMessage* settings) 197 { 198 if (settings == NULL || settings->what != 'okok') return; 199 200 size_t size; 201 char* data; 202 203 size = settings->FlattenedSize(); 204 data = new char[size]; 205 auto_ptr<char> _data(data); 206 207 if (data != NULL && settings->Flatten(data, size) == B_OK) { 208 fSpoolFolder->WriteAttr(attrName, B_MESSAGE_TYPE, 0, data, size); 209 } 210 } 211 212 // read settings from spool folder attribute and merge them to current settings 213 void 214 PrinterDriver::_MergeWithPreviousSettings(const char* attrName, BMessage* settings) 215 { 216 if (settings == NULL) return; 217 218 BMessage stored; 219 if (_ReadSettings(attrName, &stored)) { 220 AddFields(&stored, settings); 221 *settings = stored; 222 } 223 } 224 225 // Implementation of PrinterDriverInstance 226 227 class PrinterDriverInstance 228 { 229 public: 230 PrinterDriverInstance(BNode* spoolFolder = NULL); 231 ~PrinterDriverInstance(); 232 PrinterDriver* GetPrinterDriver() { return fInstance; } 233 234 private: 235 PrinterDriver* fInstance; 236 }; 237 238 PrinterDriverInstance::PrinterDriverInstance(BNode* spoolFolder) 239 { 240 fInstance = instantiate_printer_driver(spoolFolder); 241 if (fInstance != NULL) { 242 fInstance->InitPrinterDataAndCap(); 243 } 244 } 245 246 PrinterDriverInstance::~PrinterDriverInstance() 247 { 248 delete fInstance; 249 fInstance = NULL; 250 } 251 252 253 // printer driver add-on functions 254 255 char *add_printer(char *printerName) 256 { 257 BPath path; 258 BNode folder; 259 BNode* spoolFolder = NULL; 260 // get spool folder 261 if (find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK && 262 path.Append(printerName) == B_OK && 263 folder.SetTo(path.Path()) == B_OK) { 264 spoolFolder = &folder; 265 } 266 267 PrinterDriverInstance instance(spoolFolder); 268 return instance.GetPrinterDriver()->AddPrinter(printerName); 269 } 270 271 BMessage *config_page(BNode *spoolFolder, BMessage *settings) 272 { 273 PrinterDriverInstance instance(spoolFolder); 274 return instance.GetPrinterDriver()->ConfigPage(settings); 275 } 276 277 BMessage *config_job(BNode *spoolFolder, BMessage *settings) 278 { 279 PrinterDriverInstance instance(spoolFolder); 280 return instance.GetPrinterDriver()->ConfigJob(settings); 281 } 282 283 BMessage *take_job(BFile *printJob, BNode *spoolFolder, BMessage *settings) 284 { 285 PrinterDriverInstance instance(spoolFolder); 286 return instance.GetPrinterDriver()->TakeJob(printJob, settings); 287 } 288 289 // main entry if printer driver is launched directly 290 291 int main(int argc, char* argv[]) 292 { 293 PrinterDriverInstance instance; 294 instance.GetPrinterDriver()->About(); 295 return 0; 296 } 297