diff --git a/src/servers/print/ConfigWindow.cpp b/src/servers/print/ConfigWindow.cpp new file mode 100644 index 0000000000..ea9dd230ed --- /dev/null +++ b/src/servers/print/ConfigWindow.cpp @@ -0,0 +1,235 @@ +/*****************************************************************************/ +// ConfigWindow +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + + +#include "Printer.h" +#include "PrintServerApp.h" +#include "ConfigWindow.h" + +// posix +#include +#include + +// BeOS +#include +#include +#include + +ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMessage* settings, AutoReply* sender) + : BWindow(BRect(30, 30, 200, 125), "Printer Setup", + B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE) + , fKind(kind) + , fDefaultPrinter(defaultPrinter) + , fSettings(settings) + , fSender(sender) + , fCurrentPrinter(NULL) +{ + MimeTypeForSender(settings, fSenderMimeType); + PrinterForMimeType(); + + BView* panel = new BBox(Bounds(), "top_panel", B_FOLLOW_ALL, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, + B_PLAIN_BORDER); + + AddChild(panel); + + float left = 10, top = 5; + BRect r(left, top, 160, 15); + + BPopUpMenu* menu = new BPopUpMenu("PrinterMenu"); + SetupPrintersMenu(menu); + + fPrinters = new BMenuField(r, "Printer", "Printer", menu); + fPrinters->SetDivider(60); + panel->AddChild(fPrinters); + top += fPrinters->Bounds().Height() + 5; + + r.OffsetTo(left, top); + fPageSetup = new BButton(r, "Page Setup", "Page Setup", new BMessage(MSG_PAGE_SETUP)); + panel->AddChild(fPageSetup); + fPageSetup->ResizeToPreferred(); + top += fPageSetup->Bounds().Height() + 5; + + fJobSetup = NULL; + if (kind == kJobSetup) { + r.OffsetTo(left, top); + fJobSetup = new BButton(r, "Job Setup", "Job Setup", new BMessage(MSG_JOB_SETUP)); + panel->AddChild(fJobSetup); + fJobSetup->SetEnabled(fKind == kJobSetup); + fJobSetup->ResizeToPreferred(); + top += fJobSetup->Bounds().Height() + 5; + } + + ResizeTo(Bounds().Width(), top); + + UpdateSettings(true); +} + +ConfigWindow::~ConfigWindow() { + if (fCurrentPrinter) fCurrentPrinter->Release(); + release_sem(fFinished); +} + +void ConfigWindow::Go() { + sem_id sid = create_sem(0, "finished"); + if (sid >= 0) { + fFinished = sid; + Show(); + acquire_sem(sid); + delete_sem(sid); + } else { + Quit(); + } +} + +void ConfigWindow::MessageReceived(BMessage* m) { + switch (m->what) { + case MSG_PAGE_SETUP: PageSetup(m); + break; + case MSG_JOB_SETUP: JobSetup(m); + break; + case MSG_PRINTER_SELECTED: { + BString printer; + if (m->FindString("name", &printer) == B_OK) { + UpdateAppSettings(fSenderMimeType.String(), printer.String()); + PrinterForMimeType(); + UpdateSettings(true); + } + } + break; + default: + inherited::MessageReceived(m); + } +} + +void ConfigWindow::PrinterForMimeType() { + BAutolock lock(gLock); + if (fCurrentPrinter) { + fCurrentPrinter->Release(); fCurrentPrinter = NULL; + } + if (lock.IsLocked()) { + Settings* s = Settings::GetSettings(); + AppSettings* app = s->FindAppSettings(fSenderMimeType.String()); + if (app) { + fPrinterName = app->GetPrinter(); + } else { + fPrinterName = fDefaultPrinter ? fDefaultPrinter->Name() : ""; + } + fCurrentPrinter = Printer::Find(fPrinterName); + if (fCurrentPrinter) fCurrentPrinter->Acquire(); + } +} + +void ConfigWindow::SetupPrintersMenu(BMenu* menu) { + // clear menu + for (int i = menu->CountItems() - 1; i >= 0; i --) { + delete menu->RemoveItem(i); + } + // fill menu with printer names + BAutolock lock(gLock); + if (lock.IsLocked()) { + BString n; + Printer* p; + BMessage* m; + BMenuItem* item; + for (int i = 0; i < Printer::CountPrinters(); i ++) { + Printer::At(i)->GetName(n); + m = new BMessage(MSG_PRINTER_SELECTED); + m->AddString("name", n.String()); + menu->AddItem(item = new BMenuItem(n.String(), m)); + if (n == fPrinterName) item->SetMarked(true); + } + } +} + +void ConfigWindow::UpdateAppSettings(const char* mime, const char* printer) { + BAutolock lock(gLock); + if (lock.IsLocked()) { + Settings* s = Settings::GetSettings(); + AppSettings* app = s->FindAppSettings(mime); + if (app) app->SetPrinter(printer); + else s->AddAppSettings(new AppSettings(mime, printer)); + } +} + +void ConfigWindow::UpdateSettings(bool read) { + BAutolock lock(gLock); + if (lock.IsLocked()) { + Settings* s = Settings::GetSettings(); + PrinterSettings* p = s->FindPrinterSettings(fPrinterName.String()); + if (p == NULL) { + p = new PrinterSettings(fPrinterName.String()); + s->AddPrinterSettings(p); + } + ASSERT(p != NULL); + if (read) { + fPageSettings = *p->GetPageSettings(); + fJobSettings = *p->GetJobSettings(); + } else { + if (fJobSettings.IsEmpty()) fJobSettings = fPageSettings; + p->SetPageSettings(&fPageSettings); + p->SetJobSettings(&fJobSettings); + } + if (fJobSetup) { + fJobSetup->SetEnabled(fKind == kJobSetup && !fPageSettings.IsEmpty()); + } + } +} + +void ConfigWindow::PageSetup(BMessage* m) { + if (fCurrentPrinter) { + Hide(); + UpdateSettings(true); + bool ok = fCurrentPrinter->ConfigurePage(fPageSettings) == B_OK; + if (ok) UpdateSettings(false); + if (ok && fKind == kPageSetup) { + fSender->SetReply(&fJobSettings); + Quit(); + } else { + Show(); + } + } +} + +void ConfigWindow::JobSetup(BMessage* m) { + if (fCurrentPrinter) { + Hide(); + UpdateSettings(true); + bool ok = fCurrentPrinter->ConfigureJob(fJobSettings) == B_OK; + if (ok) UpdateSettings(false); + if (ok && fKind == kJobSetup) { + fSender->SetReply(&fJobSettings); + Quit(); + } else { + Show(); + } + } +} diff --git a/src/servers/print/ConfigWindow.h b/src/servers/print/ConfigWindow.h new file mode 100644 index 0000000000..9c3c702035 --- /dev/null +++ b/src/servers/print/ConfigWindow.h @@ -0,0 +1,85 @@ +/*****************************************************************************/ +// ConfigWindow +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef _CONFIG_WINDOW_H +#define _CONFIG_WINDOW_H + +#include "BeUtils.h" +#include "ObjectList.h" + +#include + +enum config_setup_kind { + kPageSetup, + kJobSetup, +}; + +class ConfigWindow : public BWindow { + enum { + MSG_PAGE_SETUP = 'cwps', + MSG_JOB_SETUP = 'cwjs', + MSG_PRINTER_SELECTED = 'cwpr', + }; + +public: + ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMessage* settings, AutoReply* sender); + ~ConfigWindow(); + void Go(); + + void MessageReceived(BMessage* m); + +private: + void PrinterForMimeType(); + void SetupPrintersMenu(BMenu* menu); + void UpdateAppSettings(const char* mime, const char* printer); + void UpdateSettings(bool read); + void PageSetup(BMessage* m); + void JobSetup(BMessage* m); + + config_setup_kind fKind; + Printer* fDefaultPrinter; + BMessage* fSettings; + AutoReply* fSender; + BString fSenderMimeType; + + BString fPrinterName; + Printer* fCurrentPrinter; + BMessage fPageSettings; + BMessage fJobSettings; + + sem_id fFinished; + + BMenuField* fPrinters; + BButton* fPageSetup; + BButton* fJobSetup; +}; + +#endif diff --git a/src/servers/print/PrintServerApp.R5.cpp b/src/servers/print/PrintServerApp.R5.cpp index df817b273a..5340bc50d6 100644 --- a/src/servers/print/PrintServerApp.R5.cpp +++ b/src/servers/print/PrintServerApp.R5.cpp @@ -14,7 +14,7 @@ // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001, 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -39,26 +39,35 @@ #include "pr_server.h" #include "Printer.h" +#include "ConfigWindow.h" // BeOS API -#include #include - - // TODO: - // Somehow block application that wants to show page/printer config dialog - // Handle situation where there are pending print jobs but printer is requested for deletion +#include +#include struct AsyncThreadParams { + PrintServerApp* app; Printer* printer; BMessage* message; - AsyncThreadParams(Printer* p, BMessage* m) - : printer(p) + AsyncThreadParams(PrintServerApp* app, Printer* p, BMessage* m) + : app(app) + , printer(p) , message(m) - { } + { + app->Acquire(); + if (printer) printer->Acquire(); + } ~AsyncThreadParams() { + if (printer) printer->Release(); delete message; + app->Release(); + } + + BMessage* AcquireMessage() { + BMessage* m = message; message = NULL; return m; } }; @@ -67,62 +76,61 @@ status_t PrintServerApp::async_thread(void* data) AsyncThreadParams* p = (AsyncThreadParams*)data; Printer* printer = p->printer; - BMessage* msg = p->message; + BMessage* msg = p->AcquireMessage(); + + { + AutoReply sender(msg, 'stop'); + switch (msg->what) { + // Handle showing the page config dialog + case PSRV_SHOW_PAGE_SETUP: { + if (p->app->fUseConfigWindow) { + ConfigWindow* w = new ConfigWindow(kPageSetup, printer, msg, &sender); + w->Go(); + } else if (printer != NULL) { + BMessage reply(*msg); + if (printer->ConfigurePage(reply) == B_OK) { + sender.SetReply(&reply); + break; + } + } + else { + // If no default printer, give user choice of aborting or setting up a printer + BAlert* alert = new BAlert("Info", "Hang on there! You don't have any printers set up!\nYou'll need to do that before trying to print\n\nWould you like to set up a printer now?", "No thanks", "Sure!"); + if (alert->Go() == 1) { + run_add_printer_panel(); + } + } + } + break; - switch (msg->what) { - // Handle showing the page config dialog - case PSRV_SHOW_PAGE_SETUP: { + // Handle showing the print config dialog + case PSRV_SHOW_PRINT_SETUP: { + if (p->app->fUseConfigWindow) { + ConfigWindow* w = new ConfigWindow(kJobSetup, printer, msg, &sender); + w->Go(); + } else if (printer != NULL) { + BMessage reply(*msg); + if (printer->ConfigureJob(reply) == B_OK) { + sender.SetReply(&reply); + break; + } + } + } + break; + + // Retrieve default configuration message from printer add-on + case PSRV_GET_DEFAULT_SETTINGS: if (printer != NULL) { - BMessage reply(*msg); - if (printer->ConfigurePage(reply) == B_OK) { - msg->SendReply(&reply); + BMessage reply; + if (printer->GetDefaultSettings(reply) == B_OK) { + sender.SetReply(&reply); break; } } - else { - // If no default printer, give user choice of aborting or setting up a printer - BAlert* alert = new BAlert("Info", "Hang on there! You don't have any printers set up!\nYou'll need to do that before trying to print\n\nWould you like to set up a printer now?", "No thanks", "Sure!"); - if (alert->Go() == 1) { - run_add_printer_panel(); - } - - } - // Always stop dialog flow - BMessage reply('stop'); - msg->SendReply(&reply); - } - break; + break; + } + } - // Handle showing the print config dialog - case PSRV_SHOW_PRINT_SETUP: { - if (printer != NULL) { - BMessage reply(*msg); - if (printer->ConfigureJob(reply) == B_OK) { - msg->SendReply(&reply); - break; - } - } - BMessage reply('stop'); - msg->SendReply(&reply); - } - break; - - // Retrieve default configuration message from printer add-on - case PSRV_GET_DEFAULT_SETTINGS: - if (printer != NULL) { - BMessage reply; - if (printer->GetDefaultSettings(reply) == B_OK) { - msg->SendReply(&reply); - break; - } - } - BMessage reply('stop'); - msg->SendReply(&reply); - break; - - } - - if (printer) printer->Release(); delete p; } @@ -130,12 +138,11 @@ status_t PrintServerApp::async_thread(void* data) // Async. processing of received message void PrintServerApp::AsyncHandleMessage(BMessage* msg) { - AsyncThreadParams* data = new AsyncThreadParams(fDefaultPrinter, msg); + AsyncThreadParams* data = new AsyncThreadParams(this, fDefaultPrinter, msg); thread_id tid = spawn_thread(async_thread, "async", B_NORMAL_PRIORITY, (void*)data); if (tid > 0) { - if (fDefaultPrinter) fDefaultPrinter->Acquire(); resume_thread(tid); } else { delete data; @@ -148,7 +155,17 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg) // Get currently selected printer case PSRV_GET_ACTIVE_PRINTER: { BMessage reply('okok'); - reply.AddString("printer_name", fDefaultPrinter ? fDefaultPrinter->Name() : ""); + BString printerName = fDefaultPrinter ? fDefaultPrinter->Name() : ""; + BString mime; + if (fUseConfigWindow && MimeTypeForSender(msg, mime)) { + BAutolock lock(gLock); + if (lock.IsLocked()) { + // override with printer for application + PrinterSettings* p = fSettings->FindPrinterSettings(mime.String()); + if (p) printerName = p->GetPrinter(); + } + } + reply.AddString("printer_name", printerName); reply.AddInt32("color", BPrintJob::B_COLOR_PRINTER); // BeOS knows not if color or not, so always color msg->SendReply(&reply); } diff --git a/src/servers/print/PrintServerApp.cpp b/src/servers/print/PrintServerApp.cpp index 60f5884007..71756b8e77 100644 --- a/src/servers/print/PrintServerApp.cpp +++ b/src/servers/print/PrintServerApp.cpp @@ -119,12 +119,15 @@ PrintServerApp::PrintServerApp(status_t* err) : Inherited(PSRV_SIGNATURE_TYPE, err), fSelectedIconMini(NULL), fSelectedIconLarge(NULL), - fNumberOfPrinters(0), - fNoPrinterAvailable(0) + fReferences(0), + fHasReferences(0), + fUseConfigWindow(true) { + fSettings = Settings::GetSettings(); + LoadSettings(); // If our superclass initialized ok if (*err == B_OK) { - fNoPrinterAvailable = create_sem(1, ""); + fHasReferences = create_sem(1, "has_references"); // let us try as well SetupPrinterList(); @@ -143,6 +146,11 @@ PrintServerApp::PrintServerApp(status_t* err) } } +PrintServerApp::~PrintServerApp() { + SaveSettings(); + delete fSettings; +} + bool PrintServerApp::QuitRequested() { bool rc = Inherited::QuitRequested(); @@ -167,10 +175,10 @@ bool PrintServerApp::QuitRequested() } // Wait for printers - if (fNoPrinterAvailable > 0) { - acquire_sem(fNoPrinterAvailable); - delete_sem(fNoPrinterAvailable); - fNoPrinterAvailable = 0; + if (fHasReferences > 0) { + acquire_sem(fHasReferences); + delete_sem(fHasReferences); + fHasReferences = 0; } ASSERT(fSelectedIconMini != NULL); @@ -182,6 +190,13 @@ bool PrintServerApp::QuitRequested() return rc; } +void PrintServerApp::Acquire() { + if (atomic_add(&fReferences, 1) == 0) acquire_sem(fHasReferences); +} + +void PrintServerApp::Release() { + if (atomic_add(&fReferences, -1) == 1) release_sem(fHasReferences); +} void PrintServerApp::RegisterPrinter(BDirectory* printer) { BString transport, address, connection; @@ -195,8 +210,7 @@ void PrintServerApp::RegisterPrinter(BDirectory* printer) { Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String()); Printer* p = new Printer(printer, r); AddHandler(p); - if (fNumberOfPrinters == 0) acquire_sem(fNoPrinterAvailable); - fNumberOfPrinters ++; + Acquire(); } } @@ -209,9 +223,8 @@ void PrintServerApp::UnregisterPrinter(Printer* printer) { void PrintServerApp::NotifyPrinterDeletion(Printer* printer) { BAutolock lock(gLock); if (lock.IsLocked()) { - fNumberOfPrinters --; fResourceManager.Free(printer->GetResource()); - if (fNumberOfPrinters == 0) release_sem(fNoPrinterAvailable); + Release(); } } @@ -299,9 +312,6 @@ status_t PrintServerApp::SetupPrinterList() void PrintServerApp::MessageReceived(BMessage* msg) { -// fprintf(stdout, "PrintServerApp\n"); -// msg->PrintToStream(); printf("\n\n"); -// fflush(stdout); switch(msg->what) { case PSRV_GET_ACTIVE_PRINTER: case PSRV_MAKE_PRINTER_ACTIVE_QUIETLY: @@ -592,3 +602,22 @@ PrintServerApp::FindPrinterDriver(const char* name, BPath& outPath) return B_OK; } + + +bool PrintServerApp::OpenSettings(BFile& file, bool forReading) { + BPath path; + uint32 openMode = forReading ? B_READ_ONLY : B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY; + return find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK && + path.Append("print_server_settings") == B_OK && + file.SetTo(path.Path(), openMode) == B_OK; +} + +void PrintServerApp::LoadSettings() { + BFile file; + if (OpenSettings(file, true)) fSettings->Load(&file); +} + +void PrintServerApp::SaveSettings() { + BFile file; + if (OpenSettings(file, false)) fSettings->Save(&file); +} diff --git a/src/servers/print/PrintServerApp.h b/src/servers/print/PrintServerApp.h index e46a86b42c..8a9658e424 100644 --- a/src/servers/print/PrintServerApp.h +++ b/src/servers/print/PrintServerApp.h @@ -39,6 +39,7 @@ #define PRINTSERVERAPP_H #include "ResourceManager.h" +#include "Settings.h" class PrintServerApp; @@ -61,6 +62,10 @@ class PrintServerApp : public BApplication typedef BApplication Inherited; public: PrintServerApp(status_t* err); + ~PrintServerApp(); + + void Acquire(); + void Release(); bool QuitRequested(); void MessageReceived(BMessage* msg); @@ -73,6 +78,10 @@ public: BHandler* ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, int32 form, const char* prop); private: + bool OpenSettings(BFile& file, bool forReading); + void LoadSettings(); + void SaveSettings(); + status_t SetupPrinterList(); void HandleSpooledJobs(); @@ -96,8 +105,10 @@ private: Printer* fDefaultPrinter; BBitmap* fSelectedIconMini; BBitmap* fSelectedIconLarge; - int fNumberOfPrinters; // number of existing Printer objects - sem_id fNoPrinterAvailable; // can be acquired if number of printers == 0 + vint32 fReferences; + sem_id fHasReferences; + Settings*fSettings; + bool fUseConfigWindow; // "Classic" BeOS R5 support, see PrintServerApp.R5.cpp static status_t async_thread(void* data); diff --git a/src/servers/print/Printer.cpp b/src/servers/print/Printer.cpp index 1ffecc1325..2c96b34a05 100644 --- a/src/servers/print/Printer.cpp +++ b/src/servers/print/Printer.cpp @@ -226,9 +226,10 @@ status_t Printer::ConfigurePage(BMessage& settings) if ((rc=get_image_symbol(id, "config_page", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) { // call the function and check its result BMessage* new_settings = (*func)(SpoolDir(), &settings); - if (new_settings != NULL && new_settings->what != 'baad') + if (new_settings != NULL && new_settings->what != 'baad') { settings = *new_settings; - else + AddCurrentPrinter(&settings); + } else rc = B_ERROR; delete new_settings; } @@ -264,9 +265,10 @@ status_t Printer::ConfigureJob(BMessage& settings) if ((rc=get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) { // call the function and check its result BMessage* new_settings = (*func)(SpoolDir(), &settings); - if ((new_settings != NULL) && (new_settings->what != 'baad')) + if ((new_settings != NULL) && (new_settings->what != 'baad')) { settings = *new_settings; - else + AddCurrentPrinter(&settings); + } else rc = B_ERROR; delete new_settings; } @@ -315,6 +317,7 @@ status_t Printer::GetDefaultSettings(BMessage& settings) { BMessage* new_settings = (*func)(SpoolDir()); if (new_settings) { settings = *new_settings; + AddCurrentPrinter(&settings); } else { rc = B_ERROR; } @@ -367,12 +370,19 @@ status_t Printer::LoadPrinterAddon(image_id& id) return rc; } +void Printer::AddCurrentPrinter(BMessage* msg) +{ + BString name; + GetName(name); + if (msg->HasString(PSRV_FIELD_CURRENT_PRINTER)) { + msg->ReplaceString(PSRV_FIELD_CURRENT_PRINTER, name.String()); + } else { + msg->AddString(PSRV_FIELD_CURRENT_PRINTER, name.String()); + } +} + void Printer::MessageReceived(BMessage* msg) { - printf("Printer::MessageReceived(): "); - msg->PrintToStream(); - - switch(msg->what) { case B_GET_PROPERTY: case B_SET_PROPERTY: @@ -388,10 +398,49 @@ void Printer::MessageReceived(BMessage* msg) } } +void Printer::GetName(BString& name) { + if (B_OK != SpoolDir()->ReadAttrString(PSRV_PRINTER_ATTR_PRT_NAME, &name)) + name = "Unknown Printer"; +} + +bool Printer::HasCurrentPrinter(BString& name) { + BMessage settings; + // read settings from spool file and get printer name + BFile jobFile(&fJob->EntryRef(), B_READ_WRITE); + return jobFile.InitCheck() == B_OK && + jobFile.Seek(sizeof(print_file_header), SEEK_SET) == sizeof(print_file_header) && + settings.Unflatten(&jobFile) == B_OK && + settings.FindString(PSRV_FIELD_CURRENT_PRINTER, &name) == B_OK; +} + +bool Printer::MoveJob(const BString& name) { + BPath file(&fJob->EntryRef()); + BPath path; + file.GetParent(&path); + path.Append(".."); path.Append(name.String()); + BDirectory dir(path.Path()); + BEntry entry(&fJob->EntryRef()); + // try to move job file to proper directory + return entry.MoveTo(&dir) == B_OK; +} + bool Printer::FindSpooledJob() { - fJob = fPrinter.GetNextJob(); - if (fJob) fJob->SetPrinter(this); - return fJob; + BString name2; + GetName(name2); + do { + fJob = fPrinter.GetNextJob(); + if (fJob) { + BString name; + if (HasCurrentPrinter(name) && name != name2 && MoveJob(name)) { + fJob->SetStatus(kUnknown, false); // so that fPrinter.GetNextJob skips it + fJob->Release(); + } else { + fJob->SetPrinter(this); + return true; + } + } + } while (fJob != NULL); + return false; } status_t Printer::PrintSpooledJob(BFile* spoolFile) diff --git a/src/servers/print/Printer.h b/src/servers/print/Printer.h index f702589982..e3e506cdea 100644 --- a/src/servers/print/Printer.h +++ b/src/servers/print/Printer.h @@ -95,10 +95,12 @@ public: BHandler* ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, int32 form, const char* prop); + void GetName(BString& name); Resource* GetResource() { return fResource; } private: status_t LoadPrinterAddon(image_id& id); + void AddCurrentPrinter(BMessage* m); Folder fPrinter; // the printer spooling directory Resource* fResource; // the resource required for processing a print job @@ -112,6 +114,8 @@ private: // Accessor BDirectory* SpoolDir() { return fPrinter.GetSpoolDir(); } + bool HasCurrentPrinter(BString& name); + bool MoveJob(const BString& name); // Get next spooled job if any bool FindSpooledJob(); status_t PrintSpooledJob(BFile* spoolFile); diff --git a/src/servers/print/Settings.cpp b/src/servers/print/Settings.cpp new file mode 100644 index 0000000000..a124c58a49 --- /dev/null +++ b/src/servers/print/Settings.cpp @@ -0,0 +1,137 @@ +/*****************************************************************************/ +// Settings +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + + +#include "Settings.h" + +#include + +// Implementation of AppSettings + +AppSettings::AppSettings(const char* mimetype, const char* printer) + : fMimeType(mimetype) +{ + if (printer) fPrinter = printer; +} + + +// Implementation of PrinterSettings + +PrinterSettings::PrinterSettings(const char* printer, BMessage* pageSettings, BMessage* jobSettings) + : fPrinter(printer) +{ + if (pageSettings) fPageSettings = *pageSettings; + if (jobSettings) fJobSettings = *jobSettings; +} + + +// Implementation of Settings + +Settings* Settings::fSingleton = NULL; + +Settings::~Settings() { + fSingleton = NULL; + + for (int i = 0; i < AppSettingsCount(); i++) { + AppSettings* app = AppSettingsAt(i); + app->Release(); + } + for (int i = 0; i < PrinterSettingsCount(); i++) { + PrinterSettings* p = PrinterSettingsAt(i); + p->Release(); + } +} + +Settings* Settings::GetSettings() { + if (fSingleton == NULL) fSingleton = new Settings(); + return fSingleton; +} + +void Settings::RemoveAppSettings(int i) { + delete fApps.RemoveItemAt(i); +} + +void Settings::RemovePrinterSettings(int i) { + delete fPrinters.RemoveItemAt(i); +} + +AppSettings* Settings::FindAppSettings(const char* mimeType) { + for (int i = AppSettingsCount()-1; i >= 0; i --) { + if (strcmp(AppSettingsAt(i)->GetMimeType(), mimeType) == 0) + return AppSettingsAt(i); + } + return NULL; +} + +PrinterSettings* Settings::FindPrinterSettings(const char* printer) { + for (int i = PrinterSettingsCount()-1; i >= 0; i --) { + if (strcmp(PrinterSettingsAt(i)->GetPrinter(), printer) == 0) + return PrinterSettingsAt(i); + } + return NULL; +} + +void Settings::Save(BFile* file) { + BMessage m; + // store application settings + for (int i = 0; i < AppSettingsCount(); i++) { + AppSettings* app = AppSettingsAt(i); + m.AddString("m", app->GetMimeType()); + m.AddString("p", app->GetPrinter()); + } + // store printer settings + for (int i = 0; i < PrinterSettingsCount(); i++) { + PrinterSettings* p = PrinterSettingsAt(i); + m.AddString("P", p->GetPrinter()); + m.AddMessage("S", p->GetPageSettings()); + m.AddMessage("J", p->GetJobSettings()); + } + m.Flatten(file); +} + +void Settings::Load(BFile* file) { + BMessage m; + if (m.Unflatten(file) == B_OK) { + // restore application settings + BString mimetype, printer; + for (int i = 0; m.FindString("m", i, &mimetype) == B_OK && + m.FindString("p", i, &printer ) == B_OK; i ++) { + AddAppSettings(new AppSettings(mimetype.String(), printer.String())); + } + // restore printer settings + BMessage page, job; + for (int i = 0; m.FindString("P", i, &printer) == B_OK && + m.FindMessage("S", i, &page) == B_OK && + m.FindMessage("J", i, &job) == B_OK; i ++) { + AddPrinterSettings(new PrinterSettings(printer.String(), &page, &job)); + } + } +} diff --git a/src/servers/print/Settings.h b/src/servers/print/Settings.h new file mode 100644 index 0000000000..da61b2848e --- /dev/null +++ b/src/servers/print/Settings.h @@ -0,0 +1,101 @@ +/*****************************************************************************/ +// Settings +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef _SETTINGS_H +#define _SETTINGS_H + +#include "BeUtils.h" +#include "ObjectList.h" + +#include + +class AppSettings : public Object { +private: + BString fMimeType; + BString fPrinter; + +public: + AppSettings(const char* mimeType, const char* printer = NULL); + + const char* GetMimeType() const { return fMimeType.String(); } + bool UsesDefaultPrinter() const { return fMimeType.Length() == 0; } + const char* GetPrinter() const { return fPrinter.String(); } + void SetPrinter(const char* printer) { fPrinter = printer; } + void SetDefaultPrinter() { fPrinter = ""; } +}; + + +class PrinterSettings : public Object { +private: + BString fPrinter; + BMessage fPageSettings; + BMessage fJobSettings; + +public: + PrinterSettings(const char* printer, BMessage* pageSettings = NULL, BMessage* jobSettings = NULL); + + const char* GetPrinter() const { return fPrinter.String(); } + BMessage* GetPageSettings() { return &fPageSettings; } + BMessage* GetJobSettings() { return &fJobSettings; } + void SetPrinter(const char* p) { fPrinter = p; } + void SetPageSettings(BMessage* s) { fPageSettings = *s; } + void SetJobSettings(BMessage* s) { fJobSettings = *s; } +}; + +class Settings { +private: + BObjectList fApps; + BObjectList fPrinters; + + static Settings* fSingleton; + Settings() { } + +public: + static Settings* GetSettings(); + ~Settings(); + + int AppSettingsCount() const { return fApps.CountItems(); } + AppSettings* AppSettingsAt(int i) { return fApps.ItemAt(i); } + void AddAppSettings(AppSettings* s) { fApps.AddItem(s); } + void RemoveAppSettings(int i); + AppSettings* FindAppSettings(const char* mimeType); + + int PrinterSettingsCount() const { return fPrinters.CountItems(); } + PrinterSettings* PrinterSettingsAt(int i) { return fPrinters.ItemAt(i); } + void AddPrinterSettings(PrinterSettings* s) { fPrinters.AddItem(s); } + void RemovePrinterSettings(int i); + PrinterSettings* FindPrinterSettings(const char* printer); + + void Save(BFile* settings_file); + void Load(BFile* settings_file); +}; + +#endif