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 33PrinterDriver::PrinterDriver(BNode* spoolFolder) 34 : 35 fSpoolFolder(spoolFolder), 36 fPrinterData(NULL), 37 fPrinterCap(NULL), 38 fGraphicsDriver(NULL) 39{ 40} 41 42PrinterDriver::~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 55PrinterData* 56PrinterDriver::InstantiatePrinterData(BNode* node) 57{ 58 return new PrinterData(node); 59} 60 61void 62PrinterDriver::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 71void 72PrinterDriver::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 83char* 84PrinterDriver::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 114BMessage* 115PrinterDriver::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 132BMessage* 133PrinterDriver::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 150BMessage* 151PrinterDriver::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 175bool 176PrinterDriver::_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 196void 197PrinterDriver::_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 212void 213PrinterDriver::_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 226class PrinterDriverInstance 227{ 228public: 229 PrinterDriverInstance(BNode* spoolFolder = NULL); 230 ~PrinterDriverInstance(); 231 PrinterDriver* GetPrinterDriver() { return fInstance; } 232 233private: 234 PrinterDriver* fInstance; 235}; 236 237PrinterDriverInstance::PrinterDriverInstance(BNode* spoolFolder) 238{ 239 fInstance = instantiate_printer_driver(spoolFolder); 240 if (fInstance != NULL) { 241 fInstance->InitPrinterDataAndCap(); 242 } 243} 244 245PrinterDriverInstance::~PrinterDriverInstance() 246{ 247 delete fInstance; 248 fInstance = NULL; 249} 250 251 252// printer driver add-on functions 253 254char *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 270BMessage *config_page(BNode *spoolFolder, BMessage *settings) 271{ 272 PrinterDriverInstance instance(spoolFolder); 273 return instance.GetPrinterDriver()->ConfigPage(settings); 274} 275 276BMessage *config_job(BNode *spoolFolder, BMessage *settings) 277{ 278 PrinterDriverInstance instance(spoolFolder); 279 return instance.GetPrinterDriver()->ConfigJob(settings); 280} 281 282BMessage *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 290int main(int argc, char* argv[]) 291{ 292 PrinterDriverInstance instance; 293 instance.GetPrinterDriver()->About(); 294 return 0; 295} 296