#include <stdlib.h>
#include <stdio.h>
#include <X11/XprintAppUtil/xpapputil.h>
XpauContext *XpauGetContext( const char *printername )
{
Display *pdpy;
XPContext pcontext;
XpauContext *context;
if( XpuGetPrinter(printername, &pdpy, &pcontext) != 1 )
return NULL;
if( (context = (XpauContext *)malloc(sizeof(XpauContext))) )
{
memset(context, 0, sizeof(XpauContext));
context->pdpy = pdpy;
context->pcontext = pcontext;
if( XpQueryExtension(pdpy, &context->xp_event_base, &context->xp_error_base) == False )
{
fprintf(stderr, "XpauGetContext: XpQueryExtension() failed.\n");
XpauReleaseContext(context);
return NULL;
}
context->medium_list = XpuGetMediumSourceSizeList(pdpy, pcontext, &context->medium_num_list_entries);
context->resolution_list = XpuGetResolutionList(pdpy, pcontext, &context->resolution_num_list_entries);
context->orientation_list = XpuGetOrientationList(pdpy, pcontext, &context->orientation_num_list_entries);
context->plex_list = XpuGetPlexList(pdpy, pcontext, &context->plex_num_list_entries);
context->supported_job_attributes = XpuGetSupportedJobAttributes(pdpy, pcontext);
context->supported_doc_attributes = XpuGetSupportedDocAttributes(pdpy, pcontext);
context->supported_page_attributes = XpuGetSupportedPageAttributes(pdpy, pcontext);
return context;
}
XpuClosePrinterDisplay(pdpy, pcontext);
return NULL;
}
void XpauReleaseContext( XpauContext *context )
{
if( context )
{
if( context->medium_list )
XpuFreeMediumSourceSizeList(context->medium_list);
if( context->resolution_list )
XpuFreeResolutionList(context->resolution_list);
if( context->orientation_list )
XpuFreeOrientationList(context->orientation_list);
if( context->plex_list )
XpuFreePlexList(context->plex_list);
XpuClosePrinterDisplay(context->pdpy, context->pcontext);
free(context);
}
}
static
XpAuErrorValue XpauParseArg( const char *arg_name, const char *arg_value, XpauContext *context,
XpauFlags *jobvaluemask, XpauJobValues *jobvalues,
XpauFlags *docvaluemask, XpauDocValues *docvalues,
char **jobfilename )
{
XPAU_DEBUG(printf("XpauParseArg: name='%s', value='%s'\n", arg_name, arg_value));
if( !strcasecmp(arg_name, "file") ||
!strcasecmp(arg_name, "tofile") )
{
if( *jobfilename )
free((char *)*jobfilename);
*jobfilename = strdup(arg_value);
if( !*jobfilename )
return XpAuError_error_no_memory;
return XpAuError_success;
}
else if( !strcasecmp(arg_name, "medium") ||
!strcasecmp(arg_name, "papersize"))
{
if( !(context->medium_list && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_DEFAULT_MEDIUM)) )
return XpAuError_unsupported_medium;
docvalues->medium = XpuFindMediumSourceSizeByName(context->medium_list,
context->medium_num_list_entries,
NULL, arg_value);
if( !docvalues->medium )
return XpAuError_unsupported_medium;
*docvaluemask |= XpauVMedium;
return XpAuError_success;
}
else if( !strcasecmp(arg_name, "resolution") )
{
if( !(context->resolution_list && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_DEFAULT_PRINTER_RESOLUTION)) )
return XpAuError_unsupported_resolution;
docvalues->resolution = XpuFindResolutionByName(context->resolution_list,
context->resolution_num_list_entries,
arg_value);
if( !docvalues->resolution )
return XpAuError_unsupported_resolution;
*docvaluemask |= XpauVResolution;
return XpAuError_success;
}
else if( !strcasecmp(arg_name, "orientation") )
{
if( !(context->orientation_list && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_CONTENT_ORIENTATION)) )
return XpAuError_unsupported_orientation;
docvalues->orientation = XpuFindOrientationByName(context->orientation_list,
context->orientation_num_list_entries,
arg_value);
if( !docvalues->orientation )
return XpAuError_unsupported_orientation;
*docvaluemask |= XpauVOrientation;
return XpAuError_success;
}
else if( !strcasecmp(arg_name, "plex") )
{
if( !(context->plex_list && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_PLEX)) )
return XpAuError_unsupported_plex;
docvalues->plex = XpuFindPlexByName(context->plex_list,
context->plex_num_list_entries,
arg_value);
if( !docvalues->plex )
return XpAuError_unsupported_plex;
*docvaluemask |= XpauVPlex;
return XpAuError_success;
}
else if( !strcasecmp(arg_name, "copies") )
{
if( !(context->supported_job_attributes & XPUATTRIBUTESUPPORTED_COPY_COUNT) )
return XpAuError_unsupported_copy_count;
jobvalues->copies = atoi(arg_value);
if( jobvalues->copies <= 1 )
return XpAuError_unsupported_copy_count;
*jobvaluemask |= XpauVCopies;
return XpAuError_success;
}
else if( !strcasecmp(arg_name, "title") )
{
if( !(context->supported_job_attributes & XPUATTRIBUTESUPPORTED_JOB_NAME) )
return XpAuError_unsupported_job_name;
if( jobvalues->title )
free((char *)jobvalues->title);
jobvalues->title = strdup(arg_value);
if( !jobvalues->title )
return XpAuError_error_no_memory;
*jobvaluemask |= XpauVTitle;
return XpAuError_success;
}
return XpAuError_unknown_argument;
}
XpAuErrorValue XpauParseArgs( XpauContext *context,
XpauFlags *jobvaluemask, XpauJobValues *jobvalues,
XpauFlags *docvaluemask, XpauDocValues *docvalues,
char **jobfilename,
const char *argument_string )
{
char *args_string,
*arg_name,
*arg_value,
*start,
*s;
int result;
if( !argument_string )
return XpAuError_success;
args_string = strdup(argument_string);
if( !args_string )
return XpAuError_error_no_memory;
s = args_string;
while( s != NULL )
{
start = s;
while( *s != '\0' && *s != '=' )
s++;
if( *s == '\0' )
{
free(args_string);
return XpAuError_unexpected_eos;
}
*s++ = '\0';
arg_name = start;
start = s;
while( *s != '\0' && *s != ',' )
s++;
if( *s == '\0' )
s = NULL;
else
*s++ = '\0';
arg_value = start;
result = XpauParseArg(arg_name, arg_value, context, jobvaluemask, jobvalues, docvaluemask, docvalues, jobfilename);
if( result != XpAuError_success )
{
free(args_string);
return result;
}
}
free(args_string);
return XpAuError_success;
}
XpAuErrorValue
XpauSetJobValues( XpauContext *context, XpauFlags valuemask, XpauJobValues *jobvalues )
{
XPAU_RETURN_IF_FAIL(context->inJob == False, XpAuError_inside_job);
if( valuemask & XpauVTitle )
XPAU_RETURN_IF_FAIL(jobvalues->title && (context->supported_job_attributes & XPUATTRIBUTESUPPORTED_JOB_NAME), XpAuError_unsupported_job_name);
if( valuemask & XpauVCopies )
XPAU_RETURN_IF_FAIL((jobvalues->copies > 0) && (context->supported_job_attributes & XPUATTRIBUTESUPPORTED_COPY_COUNT), XpAuError_unsupported_copy_count);
if( valuemask & XpauVTitle )
XpuSetJobTitle(context->pdpy, context->pcontext, jobvalues->title);
#ifdef NOTNOW
if( valuemask & XpauVResolution )
XpuJobDocumentCopies(context->pdpy, context->pcontext, jobvalues->copies);
#endif
return XpAuError_success;
}
XpAuErrorValue
XpauSetDocValues( XpauContext *context, XpauFlags valuemask, XpauDocValues *docvalues )
{
XPAU_RETURN_IF_FAIL(context->inDocument == False, XpAuError_inside_document);
if( valuemask & XpauVMedium )
XPAU_RETURN_IF_FAIL(docvalues->medium && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_DEFAULT_MEDIUM), XpAuError_unsupported_medium);
if( valuemask & XpauVOrientation )
XPAU_RETURN_IF_FAIL(docvalues->orientation && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_CONTENT_ORIENTATION), XpAuError_unsupported_orientation);
if( valuemask & XpauVPlex )
XPAU_RETURN_IF_FAIL(docvalues->plex && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_PLEX), XpAuError_unsupported_plex);
if( valuemask & XpauVResolution )
XPAU_RETURN_IF_FAIL(docvalues->resolution && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_DEFAULT_PRINTER_RESOLUTION), XpAuError_unsupported_resolution);
if( valuemask & XpauVCopies )
XPAU_RETURN_IF_FAIL((docvalues->copies > 0) && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_COPY_COUNT), XpAuError_unsupported_copy_count);
if( valuemask & XpauVMedium )
XpuSetDocMediumSourceSize(context->pdpy, context->pcontext, docvalues->medium);
if( valuemask & XpauVOrientation )
XpuSetDocOrientation(context->pdpy, context->pcontext, docvalues->orientation);
if( valuemask & XpauVPlex )
XpuSetDocPlex(context->pdpy, context->pcontext, docvalues->plex);
if( valuemask & XpauVResolution )
XpuSetDocResolution(context->pdpy, context->pcontext, docvalues->resolution);
if( valuemask & XpauVCopies )
XpuSetDocumentCopies(context->pdpy, context->pcontext, docvalues->copies);
return XpAuError_success;
}
XpAuErrorValue
XpauSetPageValues( XpauContext *context, XpauFlags valuemask, XpauPageValues *pagevalues )
{
XPAU_RETURN_IF_FAIL(context->inPage == False, XpAuError_inside_page);
if( valuemask & XpauVMedium )
XPAU_RETURN_IF_FAIL(pagevalues->medium && (context->supported_page_attributes & XPUATTRIBUTESUPPORTED_DEFAULT_MEDIUM), XpAuError_unsupported_medium);
if( valuemask & XpauVOrientation )
XPAU_RETURN_IF_FAIL(pagevalues->orientation && (context->supported_page_attributes & XPUATTRIBUTESUPPORTED_CONTENT_ORIENTATION), XpAuError_unsupported_orientation);
if( valuemask & XpauVPlex )
XPAU_RETURN_IF_FAIL(pagevalues->plex && (context->supported_page_attributes & XPUATTRIBUTESUPPORTED_PLEX), XpAuError_unsupported_plex);
if( valuemask & XpauVResolution )
XPAU_RETURN_IF_FAIL(pagevalues->resolution && (context->supported_page_attributes & XPUATTRIBUTESUPPORTED_DEFAULT_PRINTER_RESOLUTION), XpAuError_unsupported_resolution);
if( valuemask & XpauVMedium )
XpuSetPageMediumSourceSize(context->pdpy, context->pcontext, pagevalues->medium);
if( valuemask & XpauVOrientation )
XpuSetPageOrientation(context->pdpy, context->pcontext, pagevalues->orientation);
if( valuemask & XpauVPlex )
XpuSetPagePlex(context->pdpy, context->pcontext, pagevalues->plex);
if( valuemask & XpauVResolution )
XpuSetPageResolution(context->pdpy, context->pcontext, pagevalues->resolution);
return XpAuError_success;
}
XpAuErrorValue XpauStartJob( XpauContext *context, const char *printerfile )
{
void *handle;
XpAuErrorValue result = XpAuError_unspecified_error;
XPAU_RETURN_IF_FAIL(context->inJob == False, XpAuError_inside_job);
XpSetContext(context->pdpy, context->pcontext);
if( printerfile )
{
context->print_to_filehandle = XpuStartJobToFile(context->pdpy, context->pcontext, printerfile);
if( context->print_to_filehandle )
{
result = XpAuError_success;
}
else
{
result = XpAuError_errno;
}
}
else
{
XpuStartJobToSpooler(context->pdpy);
result = XpAuError_success;
}
if( XpuGetResolution(context->pdpy, context->pcontext, &context->document_dpi_x, &context->document_dpi_y) != 1 )
{
result = XpAuError_no_dpi_set;
}
if( result == XpAuError_success )
{
context->inJob = True;
context->pscreen = XpGetScreenOfContext(context->pdpy, context->pcontext);
context->pscreennumber = XScreenNumberOfScreen(context->pscreen);
}
return result;
}
XpAuErrorValue XpauEndJob( XpauContext *context )
{
XPAU_RETURN_IF_FAIL(context->inJob, XpAuError_not_inside_job);
XpEndJob(context->pdpy);
XFlush(context->pdpy);
context->inJob = False;
context->pscreen = NULL;
context->pscreennumber = -1;
context->document_dpi_x = 0L;
context->document_dpi_y = 0L;
if( context->print_to_filehandle )
{
if( XpuWaitForPrintFileChild(context->print_to_filehandle) != XPGetDocFinished )
{
return XpAuError_errno;
}
}
return XpAuError_success;
}
XpAuErrorValue XpauStartDocument( XpauContext *context, XPDocumentType type )
{
XPAU_RETURN_IF_FAIL(context->inJob == True, XpAuError_not_inside_job);
XPAU_RETURN_IF_FAIL(context->inDocument == False, XpAuError_inside_document);
XPAU_RETURN_IF_FAIL(context->inPage == False, XpAuError_inside_page);
XpStartDoc(context->pdpy, type);
context->inDocument = True;
return XpAuError_success;
}
XpAuErrorValue XpauEndDocument( XpauContext *context )
{
XPAU_RETURN_IF_FAIL(context->inDocument, XpAuError_not_inside_document);
XpEndDoc(context->pdpy);
context->inDocument = False;
return XpAuError_success;
}
XpAuErrorValue XpauStartPage( XpauContext *context, Window pwin )
{
XPAU_RETURN_IF_FAIL(context->inPage == False, XpAuError_inside_page);
XPAU_RETURN_IF_FAIL(context->inJob == True, XpAuError_not_inside_job);
XpStartPage(context->pdpy, pwin);
if( context->inDocument == False )
{
context->inDocument = True;
}
context->inPage = True;
return XpAuError_success;
}
XpAuErrorValue XpauEndPage( XpauContext *context )
{
XPAU_RETURN_IF_FAIL(context->inPage, XpAuError_not_inside_page);
XpEndPage(context->pdpy);
context->inPage = False;
return XpAuError_success;
}
void XpauWaitForPrintNotify(XpauContext *context, int type)
{
XpuWaitForPrintNotify(context->pdpy, context->xp_event_base, type);
}
const char *XpAuErrorValueToString(XpAuErrorValue value)
{
char *msg;
switch(value)
{
case XpAuError_success: msg = "success" ; break;
case XpAuError_errno: msg = strerror(errno) ; break;
case XpAuError_error_no_memory: msg = "out of memory" ; break;
case XpAuError_unexpected_eos: msg = "unexpected end of string" ; break;
case XpAuError_unknown_argument: msg = "unknown argument" ; break;
case XpAuError_unsupported_medium: msg = "unsupported print medium" ; break;
case XpAuError_unsupported_resolution: msg = "unsupported print resolution" ; break;
case XpAuError_unsupported_orientation: msg = "unsupported orientation" ; break;
case XpAuError_unsupported_plex: msg = "unsupported plex" ; break;
case XpAuError_unsupported_copy_count: msg = "unsupported copy count" ; break;
case XpAuError_unsupported_job_name: msg = "unsupported job name" ; break;
case XpAuError_no_dpi_set: msg = "no DPI set (or no default DPI provided by server)" ; break;
case XpAuError_not_inside_job: msg = "state error: not inside job" ; break;
case XpAuError_not_inside_document: msg = "state error: not inside document" ; break;
case XpAuError_not_inside_page: msg = "stage error: not inside page" ; break;
case XpAuError_inside_job: msg = "state error: (already) inside job" ; break;
case XpAuError_inside_document: msg = "state error: (already) inside document" ; break;
case XpAuError_inside_page: msg = "stage error: (already) inside page" ; break;
case XpAuError_unspecified_error: msg = "unspecified error" ; break;
default:
msg = "unknown error" ;
break;
}
return msg;
}