summaryrefslogtreecommitdiff
path: root/src/xpapputil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xpapputil.c')
-rw-r--r--src/xpapputil.c551
1 files changed, 551 insertions, 0 deletions
diff --git a/src/xpapputil.c b/src/xpapputil.c
new file mode 100644
index 0000000..7e86f8e
--- /dev/null
+++ b/src/xpapputil.c
@@ -0,0 +1,551 @@
+
+/*
+ * $Xorg:xpapputil.c,v 1.1 2002/06/10 02:54:18 gisburn Exp $
+ *
+ * xpapputil - Application level utility library for Xprint
+ *
+ *
+Copyright 2002-2004 Roland Mainz <roland.mainz@nrubsig.org>
+
+All Rights Reserved.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ *
+ * Author: Roland Mainz <roland.mainz@nrubsig.org>
+ */
+
+#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;
+ }
+
+ /* It may be better to fetch all this info on demand... */
+ 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;
+
+ /* XXX: What about the tray name ? */
+ 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") )
+ {
+ int arg_res = atoi(arg_value);
+
+ if( !(context->resolution_list && (context->supported_doc_attributes & XPUATTRIBUTESUPPORTED_DEFAULT_PRINTER_RESOLUTION)) )
+ return XpAuError_unsupported_resolution;
+
+ docvalues->resolution = XpuFindResolution(context->resolution_list,
+ context->resolution_num_list_entries,
+ arg_res, arg_res);
+
+ 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); /* Create copy of read-only string that we can write into it... */
+ if( !args_string )
+ return XpAuError_error_no_memory;
+
+ s = args_string;
+
+ while( s != NULL )
+ {
+ /* Fetch argument name */
+ start = s;
+ while( *s != '\0' && *s != '=' )
+ s++;
+ if( *s == '\0' )
+ {
+ free(args_string);
+ return XpAuError_unexpected_eos;
+ }
+ *s++ = '\0';
+ arg_name = start;
+
+ /* Fetch argument value */
+ 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 )
+{
+ /* "Dry-run" tests */
+
+ /* We can't change job attributes while we are at the "job level"
+ * (e.g. after |XpStartJob()| and before |XpEndJob()| */
+ 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);
+
+ /* Set values */
+
+ if( valuemask & XpauVTitle )
+ XpuSetJobTitle(context->pdpy, context->pcontext, jobvalues->title);
+
+#ifdef NOTNOW
+ if( valuemask & XpauVResolution )
+ XpuJobDocumentCopies(context->pdpy, context->pcontext, jobvalues->copies);
+#endif /* NOTNOW */
+
+ return XpAuError_success;
+}
+
+XpAuErrorValue
+XpauSetDocValues( XpauContext *context, XpauFlags valuemask, XpauDocValues *docvalues )
+{
+ /* "Dry-run" tests */
+
+ /* We can't change document attributes while we are at the "document level"
+ * (e.g. after |XpStartDoc()| and before |XpEndDoc()| */
+ 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);
+
+ /* Set values */
+
+ 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 )
+{
+ /* "Dry-run" tests */
+
+ /* We can't change page attributes while we are at the "page level"
+ * (e.g. after |XpStartPage()| and before |XpEndPage()| */
+ 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);
+
+ /* Set values */
+
+ 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);
+
+ /* Set print context
+ * Note that this modifies the available fonts, including build-in printer prints.
+ * All XListFonts()/XLoadFont() stuff should be done _after_ setting the print
+ * context to obtain the proper fonts.
+ */
+ 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;
+ }
+
+ /* Get default printer resolution */
+ if( XpuGetResolution(context->pdpy, context->pcontext, &context->document_dpi) != 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);
+
+ /* End the print job - the final results are sent by the X print
+ * server to the spooler sub system.
+ */
+ XpEndJob(context->pdpy);
+
+ /* Be sure to process the X traffic (remember that we registered a
+ * "consumer" hook via Xlib internal magic when we print to a
+ * file)
+ * FixMe: |XpuWaitForPrintFileChild()| should call XFlush() instead!
+ */
+ XFlush(context->pdpy);
+
+ context->inJob = False;
+ context->pscreen = NULL;
+ context->pscreennumber = -1;
+ context->document_dpi = 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);
+
+ /* |XpStartPage()| will generate a "synthetic" |XpStartDoc()|
+ * if it was not called yet */
+ 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;
+}
+
+
+
+