* Fixed bug #1009. Update window while in BPrintJob.ConfigPage() or
ConfigPage(). * Set mime type of spool file so print_server accepts the file. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20075 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c1c0c22091
commit
c282eba324
|
@ -12,11 +12,14 @@
|
||||||
|
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
|
#include <Button.h>
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#include <Messenger.h>
|
#include <Messenger.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <OS.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <PrintJob.h>
|
#include <PrintJob.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
|
@ -28,6 +31,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static const int kSemTimeOut = 50000;
|
||||||
|
|
||||||
|
static const char *kPrintServerNotRespondingText = "Print Server is not responding.";
|
||||||
|
static const char *kNoPagesToPrintText = "No Pages to print!";
|
||||||
|
|
||||||
// Summery of spool file format:
|
// Summery of spool file format:
|
||||||
// See articel "How to Write a BeOS R5 Printer Driver" for description
|
// See articel "How to Write a BeOS R5 Printer Driver" for description
|
||||||
// of spool file format: http://haiku-os.org/node/82
|
// of spool file format: http://haiku-os.org/node/82
|
||||||
|
@ -48,12 +56,174 @@ struct _page_header_ {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static status_t GetPrinterServerMessenger(BMessenger& messenger)
|
static status_t
|
||||||
|
GetPrinterServerMessenger(BMessenger& messenger)
|
||||||
{
|
{
|
||||||
messenger = BMessenger(PSRV_SIGNATURE_TYPE);
|
messenger = BMessenger(PSRV_SIGNATURE_TYPE);
|
||||||
return messenger.IsValid() ? B_OK : B_ERROR;
|
return messenger.IsValid() ? B_OK : B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ShowError(const char *message)
|
||||||
|
{
|
||||||
|
BAlert* alert = new BAlert("Error", message, "OK");
|
||||||
|
alert->Go();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
class Configuration {
|
||||||
|
public:
|
||||||
|
Configuration(uint32 what, BMessage *input);
|
||||||
|
~Configuration();
|
||||||
|
|
||||||
|
status_t SendRequest(thread_func function);
|
||||||
|
|
||||||
|
BMessage* Request();
|
||||||
|
|
||||||
|
void SetResult(BMessage* result);
|
||||||
|
BMessage* Result() const { return fResult; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RejectUserInput();
|
||||||
|
void AllowUserInput();
|
||||||
|
void DeleteSemaphore();
|
||||||
|
|
||||||
|
uint32 fWhat;
|
||||||
|
BMessage *fInput;
|
||||||
|
BMessage *fRequest;
|
||||||
|
BMessage *fResult;
|
||||||
|
sem_id fThreadCompleted;
|
||||||
|
BAlert *fHiddenApplicationModalWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Configuration::Configuration(uint32 what, BMessage *input)
|
||||||
|
: fWhat(what),
|
||||||
|
fInput(input),
|
||||||
|
fRequest(NULL),
|
||||||
|
fResult(NULL),
|
||||||
|
fThreadCompleted(-1),
|
||||||
|
fHiddenApplicationModalWindow(NULL)
|
||||||
|
{
|
||||||
|
RejectUserInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Configuration::~Configuration()
|
||||||
|
{
|
||||||
|
DeleteSemaphore();
|
||||||
|
// in case SendRequest could not start the thread
|
||||||
|
delete fRequest; fRequest = NULL;
|
||||||
|
AllowUserInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Configuration::RejectUserInput()
|
||||||
|
{
|
||||||
|
BAlert* alert = new BAlert("bogus", "app_modal_dialog", "OK");
|
||||||
|
fHiddenApplicationModalWindow = alert;
|
||||||
|
alert->DefaultButton()->SetEnabled(false);
|
||||||
|
alert->SetDefaultButton(NULL);
|
||||||
|
alert->MoveTo(-65000, -65000);
|
||||||
|
alert->Go(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Configuration::AllowUserInput()
|
||||||
|
{
|
||||||
|
fHiddenApplicationModalWindow->Lock();
|
||||||
|
fHiddenApplicationModalWindow->Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Configuration::DeleteSemaphore()
|
||||||
|
{
|
||||||
|
if (fThreadCompleted >= B_OK) {
|
||||||
|
sem_id id = fThreadCompleted;
|
||||||
|
fThreadCompleted = -1;
|
||||||
|
delete_sem(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Configuration::SendRequest(thread_func function)
|
||||||
|
{
|
||||||
|
fThreadCompleted = create_sem(0, "Configuration");
|
||||||
|
if (fThreadCompleted < B_OK) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_id id = spawn_thread(function, "async_request", B_NORMAL_PRIORITY, this);
|
||||||
|
if (id <= 0 || resume_thread(id) != B_OK) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code copied from BAlert::Go()
|
||||||
|
BWindow* window = dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
|
||||||
|
// Get the originating window, if it exists
|
||||||
|
|
||||||
|
// Heavily modified from TextEntryAlert code; the original didn't let the
|
||||||
|
// blocked window ever draw.
|
||||||
|
if (window != NULL) {
|
||||||
|
status_t err;
|
||||||
|
for (;;) {
|
||||||
|
do {
|
||||||
|
err = acquire_sem_etc(fThreadCompleted, 1, B_RELATIVE_TIMEOUT,
|
||||||
|
kSemTimeOut);
|
||||||
|
// We've (probably) had our time slice taken away from us
|
||||||
|
} while (err == B_INTERRUPTED);
|
||||||
|
|
||||||
|
if (err == B_BAD_SEM_ID) {
|
||||||
|
// Semaphore was finally nuked in SetResult(BMessage *)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
window->UpdateIfNeeded();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No window to update, so just hang out until we're done.
|
||||||
|
while (acquire_sem(fThreadCompleted) == B_INTERRUPTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t status;
|
||||||
|
wait_for_thread(id, &status);
|
||||||
|
|
||||||
|
return Result() != NULL ? B_OK : B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage *
|
||||||
|
Configuration::Request()
|
||||||
|
{
|
||||||
|
if (fRequest != NULL)
|
||||||
|
return fRequest;
|
||||||
|
|
||||||
|
if (fInput != NULL) {
|
||||||
|
fRequest = new BMessage(*fInput);
|
||||||
|
fRequest->what = fWhat;
|
||||||
|
} else
|
||||||
|
fRequest = new BMessage(fWhat);
|
||||||
|
return fRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Configuration::SetResult(BMessage *result)
|
||||||
|
{
|
||||||
|
fResult = result;
|
||||||
|
DeleteSemaphore();
|
||||||
|
// terminate loop in thread spawned by SendRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
} // BPrivate
|
||||||
|
|
||||||
|
|
||||||
BPrintJob::BPrintJob(const char *job_name)
|
BPrintJob::BPrintJob(const char *job_name)
|
||||||
:
|
:
|
||||||
fPrintJobName(NULL),
|
fPrintJobName(NULL),
|
||||||
|
@ -96,82 +266,90 @@ BPrintJob::~BPrintJob()
|
||||||
fCurrentPageHeader = NULL;
|
fCurrentPageHeader = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
status_t
|
status_t ConfigPageThread(void *data)
|
||||||
BPrintJob::ConfigPage()
|
{
|
||||||
{
|
BPrivate::Configuration* configuration = static_cast<BPrivate::Configuration*>(data);
|
||||||
|
|
||||||
BMessenger printServer;
|
BMessenger printServer;
|
||||||
if (GetPrinterServerMessenger(printServer) != B_OK) {
|
if (GetPrinterServerMessenger(printServer) != B_OK) {
|
||||||
BAlert* alert = new BAlert("Error", "Print Server is not responding.", "OK");
|
ShowError(kPrintServerNotRespondingText);
|
||||||
alert->Go();
|
configuration->SetResult(NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessage *request = configuration->Request();
|
||||||
|
if (request == NULL) {
|
||||||
|
configuration->SetResult(NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage reply;
|
||||||
|
if (printServer.SendMessage(request, &reply) != B_OK
|
||||||
|
|| reply.what != 'okok') {
|
||||||
|
configuration->SetResult(NULL);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fSetupMessage == NULL) {
|
configuration->SetResult(new BMessage(reply));
|
||||||
LoadDefaultSettings();
|
|
||||||
if (fDefaultSetupMessage == NULL) {
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
fSetupMessage = new BMessage(*fDefaultSetupMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
BMessage request(*fSetupMessage);
|
|
||||||
request.what = PSRV_SHOW_PAGE_SETUP;
|
|
||||||
|
|
||||||
BMessage* reply = new BMessage();
|
|
||||||
if (printServer.SendMessage(&request, reply) != B_OK) {
|
|
||||||
delete reply;
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reply->what != 'okok') {
|
|
||||||
delete reply;
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete fSetupMessage;
|
|
||||||
fSetupMessage = reply;
|
|
||||||
HandlePageSetup(fSetupMessage);
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPrintJob::ConfigJob()
|
BPrintJob::ConfigPage()
|
||||||
|
{
|
||||||
|
BPrivate::Configuration configuration(PSRV_SHOW_PAGE_SETUP, fSetupMessage);
|
||||||
|
status_t status = configuration.SendRequest(ConfigPageThread);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
delete fSetupMessage;
|
||||||
|
fSetupMessage = configuration.Result();
|
||||||
|
HandlePageSetup(fSetupMessage);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
ConfigJobThread(void *data)
|
||||||
{
|
{
|
||||||
|
BPrivate::Configuration* configuration = static_cast<BPrivate::Configuration*>(data);
|
||||||
|
|
||||||
BMessenger printServer;
|
BMessenger printServer;
|
||||||
if (GetPrinterServerMessenger(printServer) != B_OK) {
|
if (GetPrinterServerMessenger(printServer) != B_OK) {
|
||||||
BAlert* alert = new BAlert("Error", "Print Server is not responding.", "OK");
|
ShowError(kPrintServerNotRespondingText);
|
||||||
alert->Go();
|
configuration->SetResult(NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessage *request = configuration->Request();
|
||||||
|
if (request == NULL) {
|
||||||
|
configuration->SetResult(NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage reply;
|
||||||
|
if (printServer.SendMessage(request, &reply) != B_OK
|
||||||
|
|| reply.what != 'okok') {
|
||||||
|
configuration->SetResult(NULL);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fSetupMessage == NULL) {
|
configuration->SetResult(new BMessage(reply));
|
||||||
LoadDefaultSettings();
|
return B_OK;
|
||||||
if (fDefaultSetupMessage == NULL) {
|
}
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
fSetupMessage = new BMessage(*fDefaultSetupMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
BMessage request(*fSetupMessage);
|
|
||||||
request.what = PSRV_SHOW_PRINT_SETUP;
|
|
||||||
|
|
||||||
BMessage* reply = new BMessage();
|
|
||||||
if (printServer.SendMessage(&request, reply) != B_OK) {
|
|
||||||
delete reply;
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reply->what != 'okok') {
|
|
||||||
delete reply;
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BPrintJob::ConfigJob()
|
||||||
|
{
|
||||||
|
BPrivate::Configuration configuration(PSRV_SHOW_PRINT_SETUP, fSetupMessage);
|
||||||
|
status_t status = configuration.SendRequest(ConfigJobThread);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
delete fSetupMessage;
|
delete fSetupMessage;
|
||||||
fSetupMessage = reply;
|
fSetupMessage = configuration.Result();
|
||||||
HandlePrintSetup(fSetupMessage);
|
HandlePrintSetup(fSetupMessage);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
@ -260,8 +438,7 @@ BPrintJob::CommitJob()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fPageNumber <= 0) {
|
if (fPageNumber <= 0) {
|
||||||
BAlert *alert = new BAlert("Alert", "No Pages to print!", "Okay");
|
ShowError(kNoPagesToPrintText);
|
||||||
alert->Go();
|
|
||||||
CancelJob();
|
CancelJob();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -279,6 +456,9 @@ BPrintJob::CommitJob()
|
||||||
const char* printerName = "";
|
const char* printerName = "";
|
||||||
fSetupMessage->FindString(PSRV_FIELD_CURRENT_PRINTER, &printerName);
|
fSetupMessage->FindString(PSRV_FIELD_CURRENT_PRINTER, &printerName);
|
||||||
|
|
||||||
|
BNodeInfo info(fSpoolFile);
|
||||||
|
info.SetType(PSRV_SPOOL_FILETYPE);
|
||||||
|
|
||||||
fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PAGECOUNT, B_INT32_TYPE, 0, &fPageNumber, sizeof(int32));
|
fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PAGECOUNT, B_INT32_TYPE, 0, &fPageNumber, sizeof(int32));
|
||||||
fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_DESCRIPTION, B_STRING_TYPE, 0, fPrintJobName, strlen(fPrintJobName) + 1);
|
fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_DESCRIPTION, B_STRING_TYPE, 0, fPrintJobName, strlen(fPrintJobName) + 1);
|
||||||
fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PRINTER, B_STRING_TYPE, 0, printerName, strlen(printerName) + 1);
|
fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PRINTER, B_STRING_TYPE, 0, printerName, strlen(printerName) + 1);
|
||||||
|
|
Loading…
Reference in New Issue