Fix bug #1004. The directory B_USER_PRINTERS_DIRECTORY does not exist in

haiku.image. It is now created when print_server or the Printers preflet
is started.
Applied coding style.
"Flattened" some nested if statements.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20030 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2007-02-01 20:39:20 +00:00
parent f6c0820638
commit 24a0bfcb01
5 changed files with 495 additions and 479 deletions

View File

@ -44,41 +44,43 @@
// Implementation of PrinterListView
PrinterListView::PrinterListView(BRect frame)
: Inherited(frame, "printers_list", B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL)
, fFolder(NULL)
: Inherited(frame, "printers_list", B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL),
fFolder(NULL)
{
}
void PrinterListView::BuildPrinterList() {
// clear list
const BListItem** items = Items();
for (int32 i = CountItems()-1; i >= 0; i --) {
delete items[i];
}
MakeEmpty();
// TODO: Fixup situation in which PrintServer is not running
BEntry entry;
status_t rc;
BPath path;
void
PrinterListView::BuildPrinterList()
{
// clear list
const BListItem** items = Items();
for (int32 i = CountItems()-1; i >= 0; i --)
delete items[i];
MakeEmpty();
// Find directory containing printer definition nodes
if ((rc=::find_directory(B_USER_PRINTERS_DIRECTORY, &path)) == B_OK) {
BDirectory dir(path.Path());
// Find directory containing printer definition nodes
BPath path;
status_t rc = ::find_directory(B_USER_PRINTERS_DIRECTORY, &path);
if (rc != B_OK)
return;
BDirectory dir(path.Path());
rc = dir.InitCheck();
if (rc != B_OK)
return;
// Can we reach the directory?
if ((rc = dir.InitCheck()) == B_OK) {
fNode = dir;
// Yes, so loop over it's entries
while((rc = dir.GetNextEntry(&entry)) == B_OK) {
BDirectory printer(&entry);
AddPrinter(printer);
}
}
fNode = dir;
BEntry entry;
while(dir.GetNextEntry(&entry) == B_OK) {
BDirectory printer(&entry);
AddPrinter(printer);
}
}
void PrinterListView::AttachedToWindow()
void
PrinterListView::AttachedToWindow()
{
Inherited::AttachedToWindow();
@ -86,18 +88,25 @@ void PrinterListView::AttachedToWindow()
SetInvocationMessage(new BMessage(MSG_MKDEF_PRINTER));
SetTarget(Window());
BPath path;
bool hasPrintersDirectory = find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK;
if (hasPrintersDirectory) {
create_directory(path.Path(), 0777);
// directory has to exist in order to start watching it
}
BuildPrinterList();
// Select active printer
// Select active printer
for (int32 i = 0; i < CountItems(); i ++) {
PrinterItem* item = dynamic_cast<PrinterItem*>(ItemAt(i));
if (item->IsActivePrinter()) {
if (item != NULL && item->IsActivePrinter()) {
Select(i); break;
}
}
BPath path;
if (find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK) {
if (hasPrintersDirectory) {
BDirectory dir(path.Path());
if (dir.InitCheck() == B_OK) {
fFolder = new FolderWatcher(this->Window(), dir, true);
@ -106,12 +115,18 @@ void PrinterListView::AttachedToWindow()
}
}
bool PrinterListView::QuitRequested() {
bool
PrinterListView::QuitRequested()
{
delete fFolder; fFolder = NULL;
return true;
}
void PrinterListView::AddPrinter(BDirectory& printer) {
void
PrinterListView::AddPrinter(BDirectory& printer)
{
BString state;
node_ref node;
// If the entry is a directory
@ -132,7 +147,9 @@ void PrinterListView::AddPrinter(BDirectory& printer) {
}
}
PrinterItem* PrinterListView::FindItem(node_ref* node) {
PrinterItem* PrinterListView::FindItem(node_ref* node)
{
for (int32 i = CountItems()-1; i >= 0; i --) {
PrinterItem* item = dynamic_cast<PrinterItem*>(ItemAt(i));
node_ref ref;
@ -143,12 +160,17 @@ PrinterItem* PrinterListView::FindItem(node_ref* node) {
return NULL;
}
void PrinterListView::EntryCreated(node_ref* node, entry_ref* entry) {
void
PrinterListView::EntryCreated(node_ref* node, entry_ref* entry)
{
BDirectory printer(node);
AddPrinter(printer);
}
void PrinterListView::EntryRemoved(node_ref* node) {
void PrinterListView::EntryRemoved(node_ref* node)
{
PrinterItem* item = FindItem(node);
if (item) {
RemoveItem(item);
@ -156,51 +178,56 @@ void PrinterListView::EntryRemoved(node_ref* node) {
}
}
void PrinterListView::AttributeChanged(node_ref* node) {
void
PrinterListView::AttributeChanged(node_ref* node)
{
BDirectory printer(node);
AddPrinter(printer);
}
void PrinterListView::UpdateItem(PrinterItem* item) {
void
PrinterListView::UpdateItem(PrinterItem* item)
{
item->UpdatePendingJobs();
InvalidateItem(IndexOf(item));
}
PrinterItem* PrinterListView::SelectedItem() {
PrinterItem* PrinterListView::SelectedItem()
{
BListItem* item = ItemAt(CurrentSelection());
return dynamic_cast<PrinterItem*>(item);
}
BBitmap* PrinterItem::sIcon = NULL;
BBitmap* PrinterItem::sSelectedIcon = NULL;
PrinterItem::PrinterItem(PrintersWindow* window, const BDirectory& node)
: BListItem(0, false)
, fFolder(NULL)
, fNode(node)
: BListItem(0, false),
fFolder(NULL),
fNode(node)
{
if (sIcon == NULL)
{
if (sIcon == NULL) {
sIcon = new BBitmap(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8);
BMimeType type(PSRV_PRINTER_FILETYPE);
type.GetIcon(sIcon, B_LARGE_ICON);
}
if (sSelectedIcon == NULL)
{
if (sSelectedIcon == NULL) {
sSelectedIcon = new BBitmap(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8);
BMimeType type(PRNT_SIGNATURE_TYPE);
type.GetIcon(sSelectedIcon, B_LARGE_ICON);
}
// Get Name of printer
// Get Name of printer
GetStringProperty(PSRV_PRINTER_ATTR_PRT_NAME, fName);
GetStringProperty(PSRV_PRINTER_ATTR_COMMENTS, fComments);
GetStringProperty(PSRV_PRINTER_ATTR_TRANSPORT, fTransport);
GetStringProperty(PSRV_PRINTER_ATTR_DRV_NAME, fDriverName);
BPath path;
// Setup spool folder
// Setup spool folder
if (find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK) {
path.Append(fName.String());
BDirectory dir(path.Path());
@ -210,16 +237,22 @@ PrinterItem::PrinterItem(PrintersWindow* window, const BDirectory& node)
UpdatePendingJobs();
}
PrinterItem::~PrinterItem() {
PrinterItem::~PrinterItem()
{
delete fFolder; fFolder = NULL;
}
void PrinterItem::GetStringProperty(const char* propName, BString& outString)
void
PrinterItem::GetStringProperty(const char* propName, BString& outString)
{
fNode.ReadAttrString(propName, &outString);
}
void PrinterItem::Update(BView *owner, const BFont *font)
void
PrinterItem::Update(BView *owner, const BFont *font)
{
BListItem::Update(owner,font);
@ -229,6 +262,7 @@ void PrinterItem::Update(BView *owner, const BFont *font)
SetHeight( (height.ascent+height.descent+height.leading) * 3.0 +4 );
}
bool PrinterItem::Remove(BListView* view)
{
BMessenger msgr;
@ -247,104 +281,113 @@ bool PrinterItem::Remove(BListView* view)
return false;
}
void PrinterItem::DrawItem(BView *owner, BRect /*bounds*/, bool complete)
{
BListView* list = dynamic_cast<BListView*>(owner);
if (list)
{
font_height height;
BFont font;
owner->GetFont(&font);
font.GetHeight(&height);
float fntheight = height.ascent+height.descent+height.leading;
if (list == NULL)
return;
BRect bounds = list->ItemFrame(list->IndexOf(this));
rgb_color color = owner->ViewColor();
if ( IsSelected() )
color = tint_color(color, B_HIGHLIGHT_BACKGROUND_TINT);
rgb_color oldviewcolor = owner->ViewColor();
rgb_color oldlowcolor = owner->LowColor();
rgb_color oldcolor = owner->HighColor();
owner->SetViewColor( color );
owner->SetHighColor( color );
owner->SetLowColor( color );
owner->FillRect(bounds);
owner->SetLowColor( oldlowcolor );
owner->SetHighColor( oldcolor );
font_height height;
BFont font;
owner->GetFont(&font);
font.GetHeight(&height);
float fntheight = height.ascent+height.descent+height.leading;
BPoint iconPt = bounds.LeftTop() + BPoint(2,2);
BPoint namePt = iconPt + BPoint(B_LARGE_ICON+8, fntheight);
BPoint driverPt = iconPt + BPoint(B_LARGE_ICON+8, fntheight*2);
BPoint commentPt = iconPt + BPoint(B_LARGE_ICON+8, fntheight*3);
float width = owner->StringWidth("No pending jobs.");
BPoint pendingPt(bounds.right - width -8, namePt.y);
BPoint transportPt(bounds.right - width -8, driverPt.y);
drawing_mode mode = owner->DrawingMode();
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(IsActivePrinter() ? sSelectedIcon : sIcon, iconPt);
// left of item
owner->DrawString(fName.String(), fName.Length(), namePt);
owner->DrawString(fDriverName.String(), fDriverName.Length(), driverPt);
owner->DrawString(fComments.String(), fComments.Length(), commentPt);
// right of item
owner->DrawString(fPendingJobs.String(), 16, pendingPt);
owner->DrawString(fTransport.String(), fTransport.Length(), transportPt);
owner->SetDrawingMode(mode);
owner->SetViewColor(oldviewcolor);
}
}
bool PrinterItem::IsActivePrinter()
{
bool rc = false;
BMessenger msgr;
if (::GetPrinterServerMessenger(msgr) == B_OK)
{
BMessage reply, getNameOfActivePrinter(B_GET_PROPERTY);
getNameOfActivePrinter.AddSpecifier("ActivePrinter");
BRect bounds = list->ItemFrame(list->IndexOf(this));
BString activePrinterName;
if (msgr.SendMessage(&getNameOfActivePrinter, &reply) == B_OK &&
reply.FindString("result", &activePrinterName) == B_OK) {
// Compare name of active printer with name of 'this' printer item
rc = (fName == activePrinterName);
}
}
rgb_color color = owner->ViewColor();
if ( IsSelected() )
color = tint_color(color, B_HIGHLIGHT_BACKGROUND_TINT);
rgb_color oldviewcolor = owner->ViewColor();
rgb_color oldlowcolor = owner->LowColor();
rgb_color oldcolor = owner->HighColor();
owner->SetViewColor( color );
owner->SetHighColor( color );
owner->SetLowColor( color );
owner->FillRect(bounds);
owner->SetLowColor( oldlowcolor );
owner->SetHighColor( oldcolor );
return rc;
BPoint iconPt = bounds.LeftTop() + BPoint(2,2);
BPoint namePt = iconPt + BPoint(B_LARGE_ICON+8, fntheight);
BPoint driverPt = iconPt + BPoint(B_LARGE_ICON+8, fntheight*2);
BPoint commentPt = iconPt + BPoint(B_LARGE_ICON+8, fntheight*3);
float width = owner->StringWidth("No pending jobs.");
BPoint pendingPt(bounds.right - width -8, namePt.y);
BPoint transportPt(bounds.right - width -8, driverPt.y);
drawing_mode mode = owner->DrawingMode();
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(IsActivePrinter() ? sSelectedIcon : sIcon, iconPt);
// left of item
owner->DrawString(fName.String(), fName.Length(), namePt);
owner->DrawString(fDriverName.String(), fDriverName.Length(), driverPt);
owner->DrawString(fComments.String(), fComments.Length(), commentPt);
// right of item
owner->DrawString(fPendingJobs.String(), 16, pendingPt);
owner->DrawString(fTransport.String(), fTransport.Length(), transportPt);
owner->SetDrawingMode(mode);
owner->SetViewColor(oldviewcolor);
}
bool PrinterItem::HasPendingJobs() {
bool
PrinterItem::IsActivePrinter()
{
BMessenger msgr;
if (::GetPrinterServerMessenger(msgr) != B_OK)
return false;
BMessage getNameOfActivePrinter(B_GET_PROPERTY);
getNameOfActivePrinter.AddSpecifier("ActivePrinter");
BString activePrinterName;
BMessage reply;
return msgr.SendMessage(&getNameOfActivePrinter, &reply) == B_OK
&& reply.FindString("result", &activePrinterName) == B_OK
&& fName == activePrinterName;
}
bool
PrinterItem::HasPendingJobs()
{
return fFolder && fFolder->CountJobs() > 0;
}
SpoolFolder* PrinterItem::Folder() {
SpoolFolder* PrinterItem::Folder()
{
return fFolder;
}
BDirectory* PrinterItem::Node() {
BDirectory*
PrinterItem::Node()
{
return &fNode;
}
void PrinterItem::UpdatePendingJobs() {
void
PrinterItem::UpdatePendingJobs()
{
if (fFolder) {
uint32 pendingJobs = fFolder->CountJobs();
fPendingJobs = "";
if (pendingJobs == 1) {
fPendingJobs = "1 pending job.";
return;
} else if (pendingJobs > 1) {
fPendingJobs << pendingJobs << " pending jobs.h";
return;
}
if (pendingJobs >= 1) return;
}
fPendingJobs = "No pending jobs.";
}

View File

@ -43,65 +43,67 @@ class SpoolFolder;
class PrinterItem;
class PrinterListView;
class PrinterListView : public BListView, public FolderListener
{
typedef BListView Inherited;
BDirectory fNode;
FolderWatcher* fFolder;
void AddPrinter(BDirectory& printer);
PrinterItem* FindItem(node_ref* node);
void EntryCreated(node_ref* node, entry_ref* entry);
void EntryRemoved(node_ref* node);
void AttributeChanged(node_ref* node);
public:
PrinterListView(BRect frame);
void AttachedToWindow();
bool QuitRequested();
void BuildPrinterList();
PrinterItem* SelectedItem();
class PrinterListView : public BListView, public FolderListener {
private:
typedef BListView Inherited;
void UpdateItem(PrinterItem* item);
void AddPrinter(BDirectory &printer);
PrinterItem *FindItem(node_ref *node);
void EntryCreated(node_ref *node, entry_ref *entry);
void EntryRemoved(node_ref *node);
void AttributeChanged(node_ref *node);
public:
PrinterListView(BRect frame);
void AttachedToWindow();
bool QuitRequested();
void BuildPrinterList();
PrinterItem *SelectedItem();
void UpdateItem(PrinterItem *item);
private:
BDirectory fNode;
FolderWatcher *fFolder;
};
class BBitmap;
class PrintersWindow;
class PrinterItem : public BListItem
{
public:
PrinterItem(PrintersWindow* window, const BDirectory& node/*const BMessenger& thePrinter*/);
~PrinterItem();
void DrawItem(BView *owner, BRect bounds, bool complete);
void Update(BView *owner, const BFont *font);
bool Remove(BListView* view);
bool IsActivePrinter();
bool HasPendingJobs();
const char* Name() const
{ return fName.String(); }
class PrinterItem : public BListItem {
public:
PrinterItem(PrintersWindow *window, const BDirectory &node);
~PrinterItem();
SpoolFolder* Folder();
BDirectory* Node();
void UpdatePendingJobs();
void DrawItem(BView *owner, BRect bounds, bool complete);
void Update(BView *owner, const BFont *font);
bool Remove(BListView *view);
bool IsActivePrinter();
bool HasPendingJobs();
const char *Name() const {
return fName.String();
}
SpoolFolder *Folder();
BDirectory *Node();
void UpdatePendingJobs();
private:
void GetStringProperty(const char *propName, BString &outString);
private:
void GetStringProperty(const char* propName, BString& outString);
SpoolFolder *fFolder;
BDirectory fNode;
BString fComments;
BString fTransport;
BString fDriverName;
BString fName;
BString fPendingJobs;
static BBitmap* sIcon;
static BBitmap* sSelectedIcon;
SpoolFolder *fFolder;
BDirectory fNode;
BString fComments;
BString fTransport;
BString fDriverName;
BString fName;
BString fPendingJobs;
static BBitmap *sIcon;
static BBitmap *sSelectedIcon;
};
#endif

View File

@ -185,40 +185,6 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg)
}
break;
#if 0
// Create a new printer
case PSRV_MAKE_PRINTER: {
BString driverName, transportName, transportPath;
BString printerName, connection;
if (msg->FindString("driver", &driverName) == B_OK &&
msg->FindString("transport", &transportName) == B_OK &&
msg->FindString("transport path", &transportPath) == B_OK &&
msg->FindString("printer name", &printerName) == B_OK
) {
if (msg->FindString("connection", &connection) != B_OK)
connection = "Local";
// then create the actual printer
if (CreatePrinter(printerName.String(), driverName.String(),
connection.String(),
transportName.String(), transportPath.String()) == B_OK) {
// If printer was created ok, ask if it needs to be the default
char buffer[256];
::sprintf(buffer, "Would you like to make %s the default printer?",
printerName.String());
BAlert* alert = new BAlert("", buffer, "No", "Yes");
if (alert->Go() == 1) {
SelectPrinter(printerName.String());
}
}
}
}
break;
#endif
case PSRV_SHOW_PAGE_SETUP:
case PSRV_SHOW_PRINT_SETUP:
case PSRV_GET_DEFAULT_SETTINGS:

View File

@ -12,7 +12,7 @@
#include "Printer.h"
#include "pr_server.h"
// BeOS API
// BeOS API
#include <Alert.h>
#include <Autolock.h>
#include <Directory.h>
@ -27,9 +27,11 @@
#include <PrintJob.h>
#include <String.h>
// ANSI C
#include <stdio.h> //for printf
#include <unistd.h> //for unlink
// ANSI C
#include <stdio.h>
// for printf
#include <unistd.h>
// for unlink
BLocker *gLock = NULL;
@ -47,18 +49,13 @@ typedef char* (*add_printer_func_t)(const char* printer_name);
*
* @returns B_OK if application was started, or an errorcode if
* application failed to start.
*
* @see your favorite C/C++ textbook :P
*/
int
main()
main()
{
status_t rc = B_OK;
gLock = new BLocker();
// Create our application object
PrintServerApp print_server(&rc);
// If all went fine, let's start it
if (rc == B_OK) {
print_server.Run();
}
@ -76,7 +73,6 @@ main()
*
* @see BApplication
*/
PrintServerApp::PrintServerApp(status_t* err)
: Inherited(PSRV_SIGNATURE_TYPE, err),
fSelectedIconMini(NULL),
@ -88,120 +84,128 @@ PrintServerApp::PrintServerApp(status_t* err)
{
fSettings = Settings::GetSettings();
LoadSettings();
// If our superclass initialized ok
if (*err == B_OK) {
fHasReferences = create_sem(1, "has_references");
if (*err != B_OK)
return;
// let us try as well
SetupPrinterList();
RetrieveDefaultPrinter();
fSelectedIconMini = new BBitmap(BRect(0,0,B_MINI_ICON-1,B_MINI_ICON-1), B_CMAP8);
fSelectedIconLarge = new BBitmap(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8);
// Cache icons for selected printer
BMimeType type(PRNT_SIGNATURE_TYPE);
type.GetIcon(fSelectedIconMini, B_MINI_ICON);
type.GetIcon(fSelectedIconLarge, B_LARGE_ICON);
// Start handling of spooled files
PostMessage(PSRV_PRINT_SPOOLED_JOB);
}
fHasReferences = create_sem(1, "has_references");
SetupPrinterList();
RetrieveDefaultPrinter();
// Cache icons for selected printer
fSelectedIconMini = new BBitmap(BRect(0,0,B_MINI_ICON-1,B_MINI_ICON-1), B_CMAP8);
fSelectedIconLarge = new BBitmap(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8);
BMimeType type(PRNT_SIGNATURE_TYPE);
type.GetIcon(fSelectedIconMini, B_MINI_ICON);
type.GetIcon(fSelectedIconLarge, B_LARGE_ICON);
PostMessage(PSRV_PRINT_SPOOLED_JOB);
// Start handling of spooled files
}
PrintServerApp::~PrintServerApp() {
PrintServerApp::~PrintServerApp()
{
SaveSettings();
delete fSettings;
}
bool PrintServerApp::QuitRequested()
bool
PrintServerApp::QuitRequested()
{
// don't quit when user types Command+Q!
BMessage* m = CurrentMessage();
bool shortcut;
// don't quit when user types Command+Q!
if (m && m->FindBool("shortcut", &shortcut) == B_OK && shortcut) return false;
bool shortcut;
if (m != NULL && m->FindBool("shortcut", &shortcut) == B_OK && shortcut)
return false;
bool rc = Inherited::QuitRequested();
if (rc) {
delete fFolder; fFolder = NULL;
#if 0
// Find directory containing printer definition nodes
BPath path;
if (::find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK) {
BEntry entry(path.Path());
node_ref nref;
if (entry.InitCheck() == B_OK &&
entry.GetNodeRef(&nref) == B_OK) {
// Stop watching the printer directory
::watch_node(&nref, B_STOP_WATCHING, be_app_messenger);
}
}
#endif
if (!Inherited::QuitRequested())
return false;
// Release all printers
Printer* printer;
while ((printer = Printer::At(0)) != NULL) {
printer->AbortPrintThread();
UnregisterPrinter(printer);
}
// Stop watching the folder
delete fFolder; fFolder = NULL;
// Wait for printers
if (fHasReferences > 0) {
acquire_sem(fHasReferences);
delete_sem(fHasReferences);
fHasReferences = 0;
}
ASSERT(fSelectedIconMini != NULL);
delete fSelectedIconMini; fSelectedIconMini = NULL;
delete fSelectedIconLarge; fSelectedIconLarge = NULL;
// Release all printers
Printer* printer;
while ((printer = Printer::At(0)) != NULL) {
printer->AbortPrintThread();
UnregisterPrinter(printer);
}
return rc;
// Wait for printers
if (fHasReferences > 0) {
acquire_sem(fHasReferences);
delete_sem(fHasReferences);
fHasReferences = 0;
}
delete fSelectedIconMini; fSelectedIconMini = NULL;
delete fSelectedIconLarge; fSelectedIconLarge = NULL;
return true;
}
void PrintServerApp::Acquire() {
if (atomic_add(&fReferences, 1) == 0) acquire_sem(fHasReferences);
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::Release()
{
if (atomic_add(&fReferences, -1) == 1)
release_sem(fHasReferences);
}
void PrintServerApp::RegisterPrinter(BDirectory* printer) {
void
PrintServerApp::RegisterPrinter(BDirectory* printer)
{
BString transport, address, connection, state;
if (printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport) == B_OK &&
printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address) == B_OK &&
printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection) == B_OK &&
printer->ReadAttrString(PSRV_PRINTER_ATTR_STATE, &state) == B_OK &&
state == "free") {
if (printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport) == B_OK
&& printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address) == B_OK
&& printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection) == B_OK
&& printer->ReadAttrString(PSRV_PRINTER_ATTR_STATE, &state) == B_OK
&& state == "free") {
BAutolock lock(gLock);
if (lock.IsLocked()) {
// check if printer is already registered
// check if printer is already registered
node_ref node;
Printer* p;
if (printer->GetNodeRef(&node) != B_OK) return;
p = Printer::Find(&node);
if (p != NULL) return;
// register new printer
if (printer->GetNodeRef(&node) != B_OK)
return;
if (Printer::Find(&node) != NULL)
return;
// register new printer
Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String());
p = new Printer(printer, r);
AddHandler(p);
AddHandler(new Printer(printer, r));
Acquire();
}
}
}
void PrintServerApp::UnregisterPrinter(Printer* printer) {
void
PrintServerApp::UnregisterPrinter(Printer* printer)
{
RemoveHandler(printer);
Printer::Remove(printer);
printer->Release();
}
void PrintServerApp::NotifyPrinterDeletion(Printer* printer) {
void
PrintServerApp::NotifyPrinterDeletion(Printer* printer)
{
BAutolock lock(gLock);
if (lock.IsLocked()) {
fResourceManager.Free(printer->GetResource());
@ -210,7 +214,9 @@ void PrintServerApp::NotifyPrinterDeletion(Printer* printer) {
}
void PrintServerApp::EntryCreated(node_ref* node, entry_ref* entry) {
void
PrintServerApp::EntryCreated(node_ref* node, entry_ref* entry)
{
BEntry printer(entry);
if (printer.InitCheck() == B_OK && printer.IsDirectory()) {
BDirectory dir(&printer);
@ -218,7 +224,10 @@ void PrintServerApp::EntryCreated(node_ref* node, entry_ref* entry) {
}
}
void PrintServerApp::EntryRemoved(node_ref* node) {
void
PrintServerApp::EntryRemoved(node_ref* node)
{
Printer* printer = Printer::Find(node);
if (printer) {
if (printer == fDefaultPrinter) fDefaultPrinter = NULL;
@ -226,13 +235,17 @@ void PrintServerApp::EntryRemoved(node_ref* node) {
}
}
void PrintServerApp::AttributeChanged(node_ref* node) {
void
PrintServerApp::AttributeChanged(node_ref* node)
{
BDirectory printer(node);
if (printer.InitCheck() == B_OK) {
RegisterPrinter(&printer);
}
}
// ---------------------------------------------------------------
// SetupPrinterList
//
@ -246,51 +259,45 @@ void PrintServerApp::AttributeChanged(node_ref* node) {
// Returns:
// B_OK if successful, or an errorcode if failed.
// ---------------------------------------------------------------
status_t PrintServerApp::SetupPrinterList()
status_t
PrintServerApp::SetupPrinterList()
{
BEntry entry;
status_t rc;
// Find directory containing printer definition nodes
BPath path;
rc = ::find_directory(B_USER_PRINTERS_DIRECTORY, &path);
if (rc != B_OK)
return rc;
// Find directory containing printer definition nodes
if ((rc=::find_directory(B_USER_PRINTERS_DIRECTORY, &path)) == B_OK) {
BDirectory dir(path.Path());
// Can we reach the directory?
if ((rc=dir.InitCheck()) == B_OK) {
// Yes, so loop over it's entries
while((rc=dir.GetNextEntry(&entry)) == B_OK) {
// If the entry is a directory
if (entry.IsDirectory()) {
// Check it's Mime type for a spool director
BDirectory node(&entry);
BNodeInfo info(&node);
char buffer[256];
if (info.GetType(buffer) == B_OK &&
strcmp(buffer, PSRV_PRINTER_FILETYPE) == 0) {
// Yes, it is a printer definition node
RegisterPrinter(&node);
}
}
}
fFolder = new FolderWatcher(this, dir, true);
fFolder->SetListener(this);
#if 0
// If we scanned all entries successfully
node_ref nref;
if (rc == B_ENTRY_NOT_FOUND &&
(rc=dir.GetNodeRef(&nref)) == B_OK) {
// Get node to watch
rc = ::watch_node(&nref, B_WATCH_DIRECTORY, be_app_messenger);
}
#endif
// Directory has to exist in order to watch it
mode_t mode = 0777;
create_directory(path.Path(), mode);
BDirectory dir(path.Path());
rc = dir.InitCheck();
if (rc != B_OK)
return rc;
// Register printer definition nodes
BEntry entry;
while(dir.GetNextEntry(&entry) == B_OK) {
if (!entry.IsDirectory())
continue;
BDirectory node(&entry);
BNodeInfo info(&node);
char buffer[256];
if (info.GetType(buffer) == B_OK && strcmp(buffer, PSRV_PRINTER_FILETYPE) == 0) {
RegisterPrinter(&node);
}
}
// Now we are ready to start node watching
fFolder = new FolderWatcher(this, dir, true);
fFolder->SetListener(this);
return rc;
return B_OK;
}
// ---------------------------------------------------------------
@ -358,52 +365,57 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName,
{
status_t rc;
// Find directory containing printer definitions
// Find directory containing printer definitions
BPath path;
if ((rc=::find_directory(B_USER_PRINTERS_DIRECTORY,&path,true,NULL)) == B_OK) {
rc = ::find_directory(B_USER_PRINTERS_DIRECTORY,&path,true,NULL);
if (rc != B_OK)
return rc;
// Create our printer definition/spool directory
BDirectory printersDir(path.Path());
BDirectory printer;
if ((rc=printersDir.CreateDirectory(printerName,&printer)) == B_OK) {
// Set its type to a printer
BNodeInfo info(&printer);
info.SetType(PSRV_PRINTER_FILETYPE);
// Create our printer definition/spool directory
BDirectory printersDir(path.Path());
BDirectory printer;
rc = printersDir.CreateDirectory(printerName, &printer);
if (rc != B_OK)
return rc;
// Set its type to a printer
BNodeInfo info(&printer);
info.SetType(PSRV_PRINTER_FILETYPE);
// Store the settings in its attributes
printer.WriteAttr(PSRV_PRINTER_ATTR_PRT_NAME, B_STRING_TYPE, 0, printerName, ::strlen(printerName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_DRV_NAME, B_STRING_TYPE, 0, driverName, ::strlen(driverName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT, B_STRING_TYPE, 0, transportName,::strlen(transportName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, B_STRING_TYPE, 0, transportPath,::strlen(transportPath)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_CNX, B_STRING_TYPE, 0, connection, ::strlen(connection)+1);
// Notify printer driver that a new printer definition node
// has been created.
// TODO check why we keep the printer definition node
// although printer driver cannot be found or loaded
if (FindPrinterDriver(driverName, path) != B_OK)
return B_OK;
image_id id = ::load_add_on(path.Path());
if (id <= 0)
return B_OK;
add_printer_func_t func;
if (get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT, (void**)&func) == B_OK) {
// call the function and check its result
if ((*func)(printerName) == NULL) {
BEntry entry;
if (printer.GetEntry(&entry) == B_OK)
entry.Remove();
// Store the settings in its attributes
printer.WriteAttr(PSRV_PRINTER_ATTR_PRT_NAME, B_STRING_TYPE, 0, printerName, ::strlen(printerName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_DRV_NAME, B_STRING_TYPE, 0, driverName, ::strlen(driverName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT, B_STRING_TYPE, 0, transportName,::strlen(transportName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, B_STRING_TYPE, 0, transportPath,::strlen(transportPath)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_CNX, B_STRING_TYPE, 0, connection, ::strlen(connection)+1);
// Find printer driver
if (FindPrinterDriver(driverName, path) == B_OK) {
// Try and load the addon
image_id id = ::load_add_on(path.Path());
if (id > 0) {
// Addon was loaded, so try and get the add_printer symbol
add_printer_func_t func;
if (get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT, (void**)&func) == B_OK) {
// call the function and check its result
if ((*func)(printerName) == NULL) {
BEntry entry;
if (printer.GetEntry(&entry) == B_OK) {
// Delete the printer if function failed
entry.Remove();
}
} else {
printer.WriteAttr(PSRV_PRINTER_ATTR_STATE, B_STRING_TYPE, 0, "free", ::strlen("free")+1);
}
}
::unload_add_on(id);
}
}
}
} else
printer.WriteAttr(PSRV_PRINTER_ATTR_STATE, B_STRING_TYPE, 0, "free", ::strlen("free")+1);
}
return rc;
::unload_add_on(id);
return B_OK;
}
// ---------------------------------------------------------------
@ -427,25 +439,27 @@ PrintServerApp::SelectPrinter(const char* printerName)
status_t rc;
BNode node;
// Find the node of the "old" default printer
if (fDefaultPrinter != NULL &&
FindPrinterNode(fDefaultPrinter->Name(), node) == B_OK) {
// and remove the custom icon
// Find the node of the "old" default printer
if (fDefaultPrinter != NULL
&& FindPrinterNode(fDefaultPrinter->Name(), node) == B_OK) {
// and remove the custom icon
BNodeInfo info(&node);
info.SetIcon(NULL, B_MINI_ICON);
info.SetIcon(NULL, B_LARGE_ICON);
}
// Find the node for the new default printer
if ((rc=FindPrinterNode(printerName, node)) == B_OK) {
// and add the custom icon
// Find the node for the new default printer
rc=FindPrinterNode(printerName, node);
if (rc == B_OK) {
// and add the custom icon
BNodeInfo info(&node);
info.SetIcon(fSelectedIconMini, B_MINI_ICON);
info.SetIcon(fSelectedIconLarge, B_LARGE_ICON);
}
fDefaultPrinter = Printer::Find(printerName);
StoreDefaultPrinter(); // update our pref file
StoreDefaultPrinter();
// update our pref file
be_roster->Broadcast(new BMessage(B_PRINTER_CHANGED));
return rc;
@ -467,8 +481,6 @@ PrintServerApp::HandleSpooledJobs()
}
}
// static const char* kPrinterData = "printer_data";
// ---------------------------------------------------------------
// RetrieveDefaultPrinter()
//
@ -525,18 +537,15 @@ PrintServerApp::StoreDefaultPrinter()
// ---------------------------------------------------------------
status_t
PrintServerApp::FindPrinterNode(const char* name, BNode& node)
{
status_t rc;
// Find directory containing printer definitions
{
// Find directory containing printer definitions
BPath path;
if ((rc=::find_directory(B_USER_PRINTERS_DIRECTORY,&path,true,NULL)) == B_OK)
{
path.Append(name);
rc = node.SetTo(path.Path());
}
return rc;
status_t rc = ::find_directory(B_USER_PRINTERS_DIRECTORY, &path, true, NULL);
if (rc != B_OK)
return rc;
path.Append(name);
return node.SetTo(path.Path());
}
// ---------------------------------------------------------------
@ -557,10 +566,9 @@ PrintServerApp::FindPrinterNode(const char* name, BNode& node)
status_t
PrintServerApp::FindPrinterDriver(const char* name, BPath& outPath)
{
// try to locate the driver
if (::TestForAddonExistence(name, B_USER_ADDONS_DIRECTORY, "Print", outPath) != B_OK)
if (::TestForAddonExistence(name, B_COMMON_ADDONS_DIRECTORY, "Print", outPath) != B_OK)
return ::TestForAddonExistence(name, B_BEOS_ADDONS_DIRECTORY, "Print", outPath);
if (::TestForAddonExistence(name, B_USER_ADDONS_DIRECTORY, "Print", outPath) != B_OK
&& TestForAddonExistence(name, B_COMMON_ADDONS_DIRECTORY, "Print", outPath) != B_OK)
return ::TestForAddonExistence(name, B_BEOS_ADDONS_DIRECTORY, "Print", outPath);
return B_OK;
}
@ -569,9 +577,9 @@ PrintServerApp::FindPrinterDriver(const char* name, BPath& outPath)
bool PrintServerApp::OpenSettings(BFile& file, const char* name, 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(name) == B_OK &&
file.SetTo(path.Path(), openMode) == B_OK;
return find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK
&& path.Append(name) == B_OK
&& file.SetTo(path.Path(), openMode) == B_OK;
}
static const char* kSettingsName = "print_server_settings";

View File

@ -1,96 +1,93 @@
/*
* Copyright 2001-2006, Haiku. All rights reserved.
* Copyright 2001-2007, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema
* Michael Pfeiffer
*/
#ifndef PRINTSERVERAPP_H
#define PRINTSERVERAPP_H
#include "ResourceManager.h"
#include "Settings.h"
#include "FolderWatcher.h"
class PrintServerApp;
#ifndef _PRINT_SERVER_APP_H
#define _PRINT_SERVER_APP_H
#include <Application.h>
#include <Bitmap.h>
#include <OS.h>
#include <String.h>
// global BLocker for synchronisation
extern BLocker* gLock;
#include "FolderWatcher.h"
#include "ResourceManager.h"
#include "Settings.h"
/*****************************************************************************/
// PrintServerApp
//
// Application class for print_server.
/*****************************************************************************/
class Printer;
class PrintServerApp : public BApplication, public FolderListener
{
typedef BApplication Inherited;
public:
PrintServerApp(status_t* err);
~PrintServerApp();
// The global BLocker for synchronisation.
extern BLocker *gLock;
// The print_server application.
class PrintServerApp : public BApplication, public FolderListener {
private:
typedef BApplication Inherited;
public:
PrintServerApp(status_t *err);
~PrintServerApp();
void Acquire();
void Release();
bool QuitRequested();
void MessageReceived(BMessage *msg);
void NotifyPrinterDeletion(Printer *printer);
void Acquire();
void Release();
bool QuitRequested();
void MessageReceived(BMessage* msg);
void NotifyPrinterDeletion(Printer* printer);
// Scripting support, see PrintServerApp.Scripting.cpp
status_t GetSupportedSuites(BMessage* msg);
void HandleScriptingCommand(BMessage* msg);
Printer* GetPrinterFromSpecifier(BMessage* msg);
BHandler* ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,
int32 form, const char* prop);
private:
bool OpenSettings(BFile& file, const char* name, bool forReading);
void LoadSettings();
void SaveSettings();
status_t SetupPrinterList();
void HandleSpooledJobs();
status_t GetSupportedSuites(BMessage *msg);
void HandleScriptingCommand(BMessage *msg);
Printer *GetPrinterFromSpecifier(BMessage *msg);
BHandler *ResolveSpecifier(BMessage *msg, int32 index, BMessage *spec,
int32 form, const char *prop);
private:
bool OpenSettings(BFile &file, const char *name, bool forReading);
void LoadSettings();
void SaveSettings();
status_t SelectPrinter(const char* printerName);
status_t CreatePrinter( const char* printerName, const char* driverName,
const char* connection, const char* transportName,
const char* transportPath);
void RegisterPrinter(BDirectory* node);
void UnregisterPrinter(Printer* printer);
// FolderListener
void EntryCreated(node_ref* node, entry_ref* entry);
void EntryRemoved(node_ref* node);
void AttributeChanged(node_ref* node);
status_t SetupPrinterList();
void HandleSpooledJobs();
status_t StoreDefaultPrinter();
status_t RetrieveDefaultPrinter();
status_t FindPrinterNode(const char* name, BNode& node);
status_t FindPrinterDriver(const char* name, BPath& outPath);
ResourceManager fResourceManager;
Printer* fDefaultPrinter;
BBitmap* fSelectedIconMini;
BBitmap* fSelectedIconLarge;
vint32 fReferences;
sem_id fHasReferences;
Settings*fSettings;
bool fUseConfigWindow;
FolderWatcher* fFolder;
status_t SelectPrinter(const char *printerName);
status_t CreatePrinter(const char *printerName, const char *driverName,
const char *connection, const char *transportName,
const char *transportPath);
void RegisterPrinter(BDirectory *node);
void UnregisterPrinter(Printer *printer);
// FolderListener
void EntryCreated(node_ref *node, entry_ref *entry);
void EntryRemoved(node_ref *node);
void AttributeChanged(node_ref *node);
status_t StoreDefaultPrinter();
status_t RetrieveDefaultPrinter();
status_t FindPrinterNode(const char *name, BNode &node);
status_t FindPrinterDriver(const char *name, BPath &outPath);
// "Classic" BeOS R5 support, see PrintServerApp.R5.cpp
static status_t async_thread(void* data);
void AsyncHandleMessage(BMessage* msg);
void Handle_BeOSR5_Message(BMessage* msg);
static status_t async_thread(void *data);
void AsyncHandleMessage(BMessage *msg);
void Handle_BeOSR5_Message(BMessage *msg);
ResourceManager fResourceManager;
Printer *fDefaultPrinter;
BBitmap *fSelectedIconMini;
BBitmap *fSelectedIconLarge;
vint32 fReferences;
sem_id fHasReferences;
Settings *fSettings;
bool fUseConfigWindow;
FolderWatcher *fFolder;
};
#endif