[xorg-commit-diffs] xc/lib/XprintUtil Imakefile, NONE,
1.1.2.1 xprintutil.c, NONE, 1.1.2.1 xprintutil.h, NONE,
1.1.2.1 xprintutil_printtofile.c, NONE, 1.1.2.1
Roland Mainz
xorg-commit at pdx.freedesktop.org
Mon Apr 12 20:16:35 PDT 2004
- Previous message: [xorg-commit-diffs] xc/lib/XprintAppUtil Imakefile, NONE,
1.1.2.1 xpapputil.c, NONE, 1.1.2.1 xpapputil.h, NONE, 1.1.2.1
- Next message: [xorg-commit-diffs] xc/extras/ttf2pt1 CHANGES.html, NONE,
1.1.2.1 COPYRIGHT, NONE, 1.1.2.1 FONTS.hpux.html, NONE,
1.1.2.1 FONTS.html, NONE, 1.1.2.1 Makefile, NONE,
1.1.2.1 README.FIRST, NONE, 1.1.2.1 README.html, NONE,
1.1.2.1 bdf.c, NONE, 1.1.2.1 bitmap.c, NONE,
1.1.2.1 byteorder.h, NONE, 1.1.2.1 cygbuild.sh, NONE,
1.1.2.1 ft.c, NONE, 1.1.2.1 global.h, NONE, 1.1.2.1 pt1.c,
NONE, 1.1.2.1 pt1.h, NONE, 1.1.2.1 runt1asm.c, NONE,
1.1.2.1 t1asm.c, NONE, 1.1.2.1 ttf.c, NONE, 1.1.2.1 ttf.h,
NONE, 1.1.2.1 ttf2pt1.1, NONE, 1.1.2.1 ttf2pt1.c, NONE,
1.1.2.1 ttf2pt1_convert.1, NONE, 1.1.2.1 ttf2pt1_x2gs.1, NONE,
1.1.2.1 version.h, NONE, 1.1.2.1 winbuild.bat, NONE,
1.1.2.1 windows.h, NONE, 1.1.2.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: gisburn
Update of /cvs/xorg/xc/lib/XprintUtil
In directory pdx:/tmp/cvs-serv9732/xc/lib/XprintUtil
Added Files:
Tag: XPRINT
Imakefile xprintutil.c xprintutil.h xprintutil_printtofile.c
Log Message:
Fix for http://xprint.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=462 - RFE: Merge xprint.mozdev.org Xprint enhancements into Xorg XPRINT branch
--- NEW FILE: Imakefile ---
#define DoNormalLib YES
# XprintUtil is not a stable interface yet, therefore avoid shipping it
# as shared lib for now
#define DoSharedLib NO
#define DoDebugLib NO
#define DoProfileLib NO
#define HasSharedData NO
#define LibName XprintUtil
#define SoRev SOZLIBREV
#define IncSubdir X11
#define IncSubSubdir XprintUtil
HEADERS = xprintutil.h
SRCS = xprintutil.c xprintutil_printtofile.c
OBJS = xprintutil.o xprintutil_printtofile.o
#include <Library.tmpl>
DependTarget()
--- NEW FILE: xprintutil.c ---
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the X11 print system utilities library.
*
* The Initial Developer of the Original Code is Roland Mainz
* <roland.mainz at nrubsig.org>.
* All Rights Reserved.
*
* Contributor(s):
[...1642 lines suppressed...]
return(flags);
}
XpuSupportedFlags XpuGetSupportedJobAttributes(Display *pdpy, XPContext pcontext)
{
return XpuGetSupportedAttributes(pdpy, pcontext, XPPrinterAttr, "job-attributes-supported");
}
XpuSupportedFlags XpuGetSupportedDocAttributes(Display *pdpy, XPContext pcontext)
{
return XpuGetSupportedAttributes(pdpy, pcontext, XPPrinterAttr, "document-attributes-supported");
}
XpuSupportedFlags XpuGetSupportedPageAttributes(Display *pdpy, XPContext pcontext)
{
return XpuGetSupportedAttributes(pdpy, pcontext, XPPrinterAttr, "xp-page-attributes-supported");
}
/* EOF. */
--- NEW FILE: xprintutil.h ---
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
#ifndef XPRINTUTIL_H
#define XPRINTUTIL_H 1
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the X11 print system utilities library.
*
* The Initial Developer of the Original Code is Roland Mainz
* <roland.mainz at nrubsig.org>.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/* Force ANSI C prototypes from X11 headers */
#ifndef FUNCPROTO
#define FUNCPROTO 15
#endif /* !FUNCPROTO */
#include <X11/Xlibint.h>
#include <X11/extensions/Print.h>
#include <X11/Intrinsic.h>
/* I don't know how to make this "better" yet... ;-( */
#ifdef USE_MOZILLA_TYPES
#include <prtypes.h>
#include <prmem.h>
#include <prthread.h>
#define XPU_USE_NSPR 1
/*
* Disabled for now - Threaded codepath does not work properly always.
* See bug 134570 ("Print-to-file not working with threaded XprintUtil")
* #define XPU_USE_THREADS 1
*/
#endif /* USE_MOZILLA_TYPES */
#ifdef DEBUG
/* trace function calls */
#define XPU_TRACE(EX) (puts(#EX),EX)
/* trace function calls in child */
#define XPU_TRACE_CHILD(EX) (puts("child: " #EX),EX)
/* execute function EX only in debug mode */
#define XPU_DEBUG_ONLY(EX) (EX)
#else
#define XPU_TRACE(EX) (EX)
#define XPU_TRACE_CHILD(EX) (EX)
#define XPU_DEBUG_ONLY(EX)
#endif /* DEBUG */
/* debug/logging: replace NULLptrs with "<NULL>" string */
#define XPU_NULLXSTR(s) (((s)!=NULL)?(s):("<NULL>"))
/*
* Struct for XpuGetMediumSourceSizeList(), XpuFreeMediumSourceSizeList(),
* XpuSetDocMediumSourceSize(), XpuSetPageMediumSourceSize(),
* XpuFindMediumSourceSizeBy*()
*/
typedef struct {
const char *tray_name;
const char *medium_name;
int mbool;
float ma1;
float ma2;
float ma3;
float ma4;
} XpuMediumSourceSizeRec, *XpuMediumSourceSizeList;
/*
* Struct for XpuGetResolutionList(), XpuFreeResolutionList(),
* XpuGetResolution(), XpuSetPageResolution(), XpuSetDocResolution(),
* XpuFindResolution()
*/
typedef struct {
long dpi;
/* ToDo: Support for Xdpi != Ydpi */
} XpuResolutionRec, *XpuResolutionList;
/*
* Struct for XpuGetOrientationList(), XpuFreeOrientationList(),
* XpuFindOrientationBy*(), XpuSetPageResolution(),
* XpuSetDocOrientation()
*/
typedef struct {
const char *orientation;
} XpuOrientationRec, *XpuOrientationList;
/*
* Struct for XpuGetPlexList(), XpuFreePlexList(), XpuFindPlexBy*(),
* XpuSetDocPlex(), XpuSetPagePlex()
*/
typedef struct {
const char *plex;
} XpuPlexRec, *XpuPlexList;
/* XPUATTRIBUTESUPPORTED_*:
* Flags which indicate whether it is allowed to set/change a specific attribute
*/
typedef long XpuSupportedFlags;
/* Job attributes */
#define XPUATTRIBUTESUPPORTED_JOB_NAME (1L<<0)
#define XPUATTRIBUTESUPPORTED_JOB_OWNER (1L<<1)
#define XPUATTRIBUTESUPPORTED_NOTIFICATION_PROFILE (1L<<2)
/* Document/Page attributes */
#define XPUATTRIBUTESUPPORTED_COPY_COUNT (1L<<3)
#define XPUATTRIBUTESUPPORTED_DOCUMENT_FORMAT (1L<<4)
#define XPUATTRIBUTESUPPORTED_CONTENT_ORIENTATION (1L<<5)
#define XPUATTRIBUTESUPPORTED_DEFAULT_PRINTER_RESOLUTION (1L<<6)
#define XPUATTRIBUTESUPPORTED_DEFAULT_INPUT_TRAY (1L<<7)
#define XPUATTRIBUTESUPPORTED_DEFAULT_MEDIUM (1L<<8)
#define XPUATTRIBUTESUPPORTED_PLEX (1L<<9)
/* prototypes */
_XFUNCPROTOBEGIN
int XpuCheckExtension( Display *pdpy );
/* Create/destroy connection to printer */
int XpuGetPrinter( const char *printername, Display **pdpyptr, XPContext *pcontextptr );
void XpuClosePrinterDisplay(Display *pdpy, XPContext pcontext);
/* Misc. functions */
void XpuSetOneAttribute( Display *pdpy, XPContext pcontext,
XPAttributes type, const char *attribute_name, const char *value, XPAttrReplacement replacement_rule );
void XpuSetOneLongAttribute( Display *pdpy, XPContext pcontext,
XPAttributes type, const char *attribute_name, long value, XPAttrReplacement replacement_rule );
int XpuCheckSupported( Display *pdpy, XPContext pcontext, XPAttributes type, const char *attribute_name, const char *query );
int XpuSetJobTitle( Display *pdpy, XPContext pcontext, const char *title );
int XpuGetOneLongAttribute( Display *pdpy, XPContext pcontext, XPAttributes type, const char *attribute_name, long *result );
#ifdef DEBUG
void dumpXpAttributes( Display *pdpy, XPContext pcontext );
#endif /* DEBUG */
void XpuWaitForPrintNotify( Display *pdpy, int xp_event_base, int detail );
/* Get list of printers */
XPPrinterList XpuGetPrinterList( const char *printer, int *res_list_count );
void XpuFreePrinterList( XPPrinterList list );
/* Set number of document copies */
int XpuSetDocumentCopies( Display *pdpy, XPContext pcontext, long num_copies );
/* Get/Set/Query supported mediums (paper sizes) */
XpuMediumSourceSizeList XpuGetMediumSourceSizeList( Display *pdpy, XPContext pcontext, int *numEntriesPtr );
void XpuFreeMediumSourceSizeList( XpuMediumSourceSizeList list );
int XpuSetDocMediumSourceSize( Display *pdpy, XPContext pcontext, XpuMediumSourceSizeRec *medium_spec );
int XpuSetPageMediumSourceSize( Display *pdpy, XPContext pcontext, XpuMediumSourceSizeRec *medium_spec );
XpuMediumSourceSizeRec *
XpuFindMediumSourceSizeBySize( XpuMediumSourceSizeList mlist, int mlist_count,
float page_width_mm, float page_height_mm, float tolerance );
XpuMediumSourceSizeRec *
XpuFindMediumSourceSizeByBounds( XpuMediumSourceSizeList mlist, int mlist_count,
float m1, float m2, float m3, float m4, float tolerance );
XpuMediumSourceSizeRec *
XpuFindMediumSourceSizeByName( XpuMediumSourceSizeList mlist, int mlist_count,
const char *tray_name, const char *medium_name );
/* Get/Set resolution */
XpuResolutionList XpuGetResolutionList( Display *pdpy, XPContext pcontext, int *numEntriesPtr );
void XpuFreeResolutionList( XpuResolutionList list );
Bool XpuGetResolution( Display *pdpy, XPContext pcontext, long *dpi );
Bool XpuSetPageResolution( Display *pdpy, XPContext pcontext, XpuResolutionRec * );
Bool XpuSetDocResolution( Display *pdpy, XPContext pcontext, XpuResolutionRec * );
XpuResolutionRec *XpuFindResolution( XpuResolutionList list, int list_count, long min_dpi, long max_dpi );
/* Get/Set orientation */
XpuOrientationList XpuGetOrientationList( Display *pdpy, XPContext pcontext, int *numEntriesPtr );
void XpuFreeOrientationList( XpuOrientationList list );
XpuOrientationRec *
XpuFindOrientationByName( XpuOrientationList list, int list_count, const char *orientation );
int XpuSetDocOrientation( Display *pdpy, XPContext pcontext, XpuOrientationRec *rec );
int XpuSetPageOrientation( Display *pdpy, XPContext pcontext, XpuOrientationRec *rec );
/* Get/set plex modes */
XpuPlexList XpuGetPlexList( Display *pdpy, XPContext pcontext, int *numEntriesPtr );
void XpuFreePlexList( XpuPlexList list );
XpuPlexRec *XpuFindPlexByName( XpuPlexList list, int list_count, const char *plex );
int XpuSetDocPlex( Display *pdpy, XPContext pcontext, XpuPlexRec *rec );
int XpuSetPagePlex( Display *pdpy, XPContext pcontext, XpuPlexRec *rec );
/* Start job to printer (spooler) or file */
void XpuStartJobToSpooler(Display *pdpy);
void *XpuStartJobToFile( Display *pdpy, XPContext pcontext, const char *filename );
XPGetDocStatus XpuWaitForPrintFileChild( void *handle );
/* Get flags which indicate whether it is allowed to set/change a specific attribute */
XpuSupportedFlags XpuGetSupportedJobAttributes(Display *pdpy, XPContext pcontext);
XpuSupportedFlags XpuGetSupportedDocAttributes(Display *pdpy, XPContext pcontext);
XpuSupportedFlags XpuGetSupportedPageAttributes(Display *pdpy, XPContext pcontext);
_XFUNCPROTOEND
#define XpuGetJobAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPJobAttr )
#define XpuGetDocAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPDocAttr )
#define XpuGetPageAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPPageAttr )
#define XpuGetPrinterAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPPrinterAttr )
#define XpuGetServerAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPServerAttr )
#endif /* !XPRINTUTIL_H */
/* EOF. */
--- NEW FILE: xprintutil_printtofile.c ---
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the X11 print system utilities library.
*
* The Initial Developer of the Original Code is Roland Mainz
* <roland.mainz at nrubsig.org>.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "xprintutil.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#ifdef XPU_USE_THREADS
#include <time.h>
#ifdef XPU_USE_NSPR
#include <prthread.h>
#else
#include <pthread.h>
#endif /* XPU_USE_NSPR */
#endif /* XPU_USE_THREADS */
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
/* local prototypes */
#ifdef DEBUG
static void PrintXPGetDocStatus( XPGetDocStatus status );
#endif
static Bool XNextEventTimeout( Display *display, XEvent *event_return, struct timeval *timeout );
static void *XpuPrintToFile( Display *pdpy, XPContext pcontext, const char *filename );
static void MyPrintToFileProc( Display *pdpy, XPContext pcontext, unsigned char *data, unsigned int data_len, XPointer client_data );
static void MyFinishProc( Display *pdpy, XPContext pcontext, XPGetDocStatus status, XPointer client_data );
#ifdef XPU_USE_NSPR
static void PrintToFile_Consumer( void *handle );
#else
static void *PrintToFile_Consumer( void *handle );
#endif
void XpuStartJobToSpooler(Display *pdpy)
{
XpStartJob(pdpy, XPSpool);
}
void *XpuStartJobToFile( Display *pdpy, XPContext pcontext, const char *filename )
{
void *handle;
XpStartJob(pdpy, XPGetData);
handle = XpuPrintToFile(pdpy, pcontext, filename);
if (!handle)
{
/* Cancel the print job and discard all events... */
XpCancelJob(pdpy, True);
}
return(handle);
}
#ifdef DEBUG
/* DEBUG: Print XPGetDocStatus */
static
void PrintXPGetDocStatus( XPGetDocStatus status )
{
switch(status)
{
case XPGetDocFinished: puts("PrintXPGetDocStatus: XPGetDocFinished"); break;
case XPGetDocSecondConsumer: puts("PrintXPGetDocStatus: XPGetDocSecondConsumer"); break;
case XPGetDocError: puts("PrintXPGetDocStatus: XPGetDocError"); break;
default: puts("PrintXPGetDocStatus: <unknown value"); break;
}
}
#endif /* DEBUG */
/* XNextEvent() with timeout */
static
Bool XNextEventTimeout( Display *display, XEvent *event_return, struct timeval *timeout )
{
int res;
fd_set readfds;
int display_fd = XConnectionNumber(display);
/* small shortcut... */
if( timeout == NULL )
{
XNextEvent(display, event_return);
return(True);
}
FD_ZERO(&readfds);
FD_SET(display_fd, &readfds);
/* Note/bug: In the case of internal X events (like used to trigger callbacks
* registered by XpGetDocumentData()&co.) select() will return with "new info"
* - but XNextEvent() below processes these _internal_ events silently - and
* will block if there are no other non-internal events.
* The workaround here is to check with XEventsQueued() if there are non-internal
* events queued - if not select() will be called again - unfortunately we use
* the old timeout here instead of the "remaining" time... (this only would hurt
* if the timeout would be really long - but for current use with values below
* 1/2 secs it does not hurt... =:-)
*/
while( XEventsQueued(display, QueuedAfterFlush) == 0 )
{
res = select(display_fd+1, &readfds, NULL, NULL, timeout);
switch(res)
{
case -1: /* select() error - should not happen */
perror("XNextEventTimeout: select() failure");
return(False);
case 0: /* timeout */
return(False);
}
}
XNextEvent(display, event_return);
return(True);
}
#ifdef XPU_USE_THREADS
/**
** XpuPrintToFile() - threaded version
** Create consumer thread which creates it's own display connection to print server
** (a 2nd display connection/thread is required to avoid deadlocks within Xlib),
** registers (Xlib-internal) consumer callback (via XpGetDocumentData(3Xp)) and
** processes/eats all incoming events via MyPrintToFileProc(). A final call to
** MyPrintToFileProc() cleans-up all stuff and sets the "done" flag.
** Note that these callbacks are called directly by Xlib while waiting for events in
** XNextEvent() because XpGetDocumentData() registeres them as "internal" callbacks,
** e.g. XNextEvent() does _not_ return before/after processing these events !!
**
** Usage:
** XpStartJob(pdpy, XPGetData);
** handle = XpuPrintToFile(pdpy, pcontext, "myfile");
** // render something
** XpEndJob(); // or XpCancelJob()
** status = XpuWaitForPrintFileChild(handle);
**
*/
typedef struct
{
#ifdef XPU_USE_NSPR
PRThread *prthread;
#else
pthread_t tid;
#endif
char *displayname;
Display *pdpy;
Display *parent_pdpy;
XPContext pcontext;
const char *file_name;
FILE *file;
XPGetDocStatus status;
Bool done;
} MyPrintFileData;
static
void *XpuPrintToFile( Display *pdpy, XPContext pcontext, const char *filename )
{
MyPrintFileData *mpfd; /* warning: shared between threads !! */
if( (mpfd = malloc(sizeof(MyPrintFileData))) == NULL )
return(NULL);
mpfd->parent_pdpy = pdpy;
mpfd->displayname = XDisplayString(pdpy);
mpfd->pdpy = NULL;
mpfd->pcontext = pcontext;
mpfd->file_name = filename;
mpfd->file = NULL;
mpfd->status = XPGetDocError;
/* make sure we can open the file for writing */
if( (mpfd->file = fopen(mpfd->file_name, "w")) == NULL )
{
/* fopen() error */
free(mpfd);
return(NULL);
}
/* its important to flush before we start the consumer thread,
* to make sure that the XpStartJob gets through first in the parent
*/
XFlush(pdpy);
#ifdef XPU_USE_NSPR
if( (mpfd->prthread = PR_CreateThread(PR_SYSTEM_THREAD, PrintToFile_Consumer, mpfd, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0)) == NULL )
#else
if( pthread_create(&(mpfd->tid), NULL, PrintToFile_Consumer, mpfd) != 0 )
#endif
{
/* pthread_create() error */
fclose(mpfd->file);
free(mpfd);
return(NULL);
}
/* we're still in the parent */
XPU_DEBUG_ONLY(printf("### parent started consumer thread.\n" ));
return(mpfd);
}
XPGetDocStatus XpuWaitForPrintFileChild( void *handle )
{
MyPrintFileData *mpfd = (MyPrintFileData *)handle;
void *res;
XPGetDocStatus status;
/* Flush data a last time to make sure we send all data to Xprt and that
* the Xlib internal hooks have called a last time */
XFlush(mpfd->parent_pdpy);
#ifdef XPU_USE_NSPR
if( PR_JoinThread(mpfd->prthread) != PR_SUCCESS )
perror("XpuWaitForPrintFileChild: PR_JoinThread() failure"); /* fixme(later): use NSPR error handling calls... */
#else
if( XPU_TRACE(pthread_join(mpfd->tid, &res)) != 0 )
perror("XpuWaitForPrintFileChild: pthread_join() failure");
#endif
status = mpfd->status;
free(handle);
XPU_DEBUG_ONLY(PrintXPGetDocStatus(status));
return(status);
}
#else /* XPU_USE_THREADS */
/**
** XpuPrintToFile() - fork() version
** Create consumer thread which creates it's own display connection to print server
** (a 2nd display connection/process is required to avoid deadlocks within Xlib),
** registers (Xlib-internal) consumer callback (via XpGetDocumentData(3Xp)) and
** processes/eats all incoming events via MyPrintToFileProc(). A final call to
** MyPrintToFileProc() cleans-up all stuff and sets the "done" flag.
** Note that these callbacks are called directly by Xlib while waiting for events in
** XNextEvent() because XpGetDocumentData() registeres them as "internal" callbacks,
** e.g. XNextEvent() does _not_ return before/after processing these events !!
**
** Usage:
** XpStartJob(pdpy, XPGetData);
** handle = XpuPrintToFile(pdpy, pcontext, "myfile");
** // render something
** XpEndJob(); // or XpCancelJob()
** status = XpuWaitForPrintFileChild(handle);
**
*/
typedef struct
{
pid_t pid;
int pipe[2]; /* child-->parent communication pipe */
const char *displayname;
Display *pdpy;
Display *parent_pdpy;
XPContext pcontext;
const char *file_name;
FILE *file;
XPGetDocStatus status;
Bool done;
} MyPrintFileData;
static
void *XpuPrintToFile( Display *pdpy, XPContext pcontext, const char *filename )
{
MyPrintFileData *mpfd;
if( (mpfd = (MyPrintFileData *)malloc(sizeof(MyPrintFileData))) == NULL )
return(NULL);
/* create pipe */
if( pipe(mpfd->pipe) == -1 )
{
/* this should never happen, but... */
perror("XpuPrintToFile: cannot create pipe");
free(mpfd);
return(NULL);
}
mpfd->parent_pdpy = pdpy;
mpfd->displayname = XDisplayString(pdpy);
mpfd->pcontext = pcontext;
mpfd->file_name = filename;
mpfd->file = NULL;
mpfd->status = XPGetDocError;
/* make sure we can open the file for writing */
if( (mpfd->file = fopen(mpfd->file_name, "w")) == NULL )
{
/* fopen() error */
close(mpfd->pipe[1]);
close(mpfd->pipe[0]);
free(mpfd);
return(NULL);
}
/* its important to flush before we fork, to make sure that the
* XpStartJob gets through first in the parent
*/
XFlush(pdpy);
mpfd->pid = fork();
if( mpfd->pid == 0 )
{
/* we're now in the fork()'ed child */
PrintToFile_Consumer(mpfd);
}
else if( mpfd->pid < 0 )
{
/* fork() error */
close(mpfd->pipe[1]);
close(mpfd->pipe[0]);
fclose(mpfd->file);
free(mpfd);
return(NULL);
}
/* we're still in the parent */
XPU_DEBUG_ONLY(printf("### parent fork()'ed consumer child.\n"));
/* child will write into file - we don't need it anymore here... :-) */
fclose(mpfd->file);
close(mpfd->pipe[1]);
return(mpfd);
}
XPGetDocStatus XpuWaitForPrintFileChild( void *handle )
{
MyPrintFileData *mpfd = (MyPrintFileData *)handle;
int res;
XPGetDocStatus status = XPGetDocError; /* used when read() from pipe fails */
/* Flush data a last time to make sure we send all data to Xprt and that
* the Xlib internal hooks have called a last time */
XFlush(mpfd->parent_pdpy);
if( XPU_TRACE(waitpid(mpfd->pid, &res, 0)) == -1 )
perror("XpuWaitForPrintFileChild: waitpid failure");
/* read the status from the child */
if( read(mpfd->pipe[0], &status, sizeof(XPGetDocStatus)) != sizeof(XPGetDocStatus) )
{
perror("XpuWaitForPrintFileChild: can't read XPGetDocStatus");
}
close(mpfd->pipe[0]);
free(handle);
XPU_DEBUG_ONLY(PrintXPGetDocStatus(status));
return(status);
}
#endif /* XPU_USE_THREADS */
static
void MyPrintToFileProc( Display *pdpy,
XPContext pcontext,
unsigned char *data,
unsigned int data_len,
XPointer client_data )
{
MyPrintFileData *mpfd = (MyPrintFileData *)client_data;
/* write to the file */
XPU_TRACE_CHILD((void)fwrite(data, data_len, 1, mpfd->file)); /* what about error handling ? */
}
static
void MyFinishProc( Display *pdpy,
XPContext pcontext,
XPGetDocStatus status,
XPointer client_data )
{
MyPrintFileData *mpfd = (MyPrintFileData *)client_data;
/* remove the file if unsuccessful */
if( status != XPGetDocFinished )
{
XPU_DEBUG_ONLY(printf("MyFinishProc: error %d\n", (int)status));
XPU_TRACE_CHILD(remove(mpfd->file_name));
}
XPU_TRACE_CHILD((void)fclose(mpfd->file)); /* what about error handling ? */
mpfd->status = status;
mpfd->done = True;
}
static
#ifdef XPU_USE_NSPR
void PrintToFile_Consumer( void *handle )
#else
void *PrintToFile_Consumer( void *handle )
#endif
{
MyPrintFileData *mpfd = (MyPrintFileData *)handle;
XEvent dummy;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100000; /* 1/10 s */
XPU_DEBUG_ONLY(printf("### child running, getting data from '%s'.\n", mpfd->displayname));
/* we cannot reuse fork()'ed display handles - our child needs his own one */
if( (mpfd->pdpy = XPU_TRACE_CHILD(XOpenDisplay(mpfd->displayname))) == NULL )
{
perror("child cannot open display");
#ifdef XPU_USE_NSPR
return;
#else
return(NULL);
#endif
}
mpfd->done = False;
/* register "consumer" callbacks */
if( XPU_TRACE_CHILD(XpGetDocumentData(mpfd->pdpy, mpfd->pcontext,
MyPrintToFileProc, MyFinishProc,
(XPointer)mpfd)) == 0 )
{
XPU_DEBUG_ONLY(printf("XpGetDocumentData cannot register callbacks\n"));
#ifdef XPU_USE_NSPR
return;
#else
return(NULL);
#endif
}
/* loop forever - libXp has registered hidden event callbacks for the consumer
* callbacks - the finishCB will call set the "done" boolean after all...
*/
while( mpfd->done != True )
{
XNextEventTimeout(mpfd->pdpy, &dummy, &timeout);
}
XCloseDisplay(mpfd->pdpy);
#ifdef XPU_USE_THREADS
#ifdef XPU_USE_NSPR
return;
#else
return(NULL);
#endif
#else
/* write the status to the parent */
if( XPU_TRACE_CHILD(write(mpfd->pipe[1], &mpfd->status, sizeof(XPGetDocStatus))) != sizeof(XPGetDocStatus) )
{
perror("PrintToFile_Consumer: can't write XPGetDocStatus");
}
/* we don't do any free's or close's, as we are just
* going to exit, in fact, get out without calling any C++
* destructors, etc., as we don't want anything funny to happen
* to the parent
*/
XPU_TRACE_CHILD(_exit(EXIT_SUCCESS));
#endif /* XPU_USE_THREADS */
}
/* EOF. */
- Previous message: [xorg-commit-diffs] xc/lib/XprintAppUtil Imakefile, NONE,
1.1.2.1 xpapputil.c, NONE, 1.1.2.1 xpapputil.h, NONE, 1.1.2.1
- Next message: [xorg-commit-diffs] xc/extras/ttf2pt1 CHANGES.html, NONE,
1.1.2.1 COPYRIGHT, NONE, 1.1.2.1 FONTS.hpux.html, NONE,
1.1.2.1 FONTS.html, NONE, 1.1.2.1 Makefile, NONE,
1.1.2.1 README.FIRST, NONE, 1.1.2.1 README.html, NONE,
1.1.2.1 bdf.c, NONE, 1.1.2.1 bitmap.c, NONE,
1.1.2.1 byteorder.h, NONE, 1.1.2.1 cygbuild.sh, NONE,
1.1.2.1 ft.c, NONE, 1.1.2.1 global.h, NONE, 1.1.2.1 pt1.c,
NONE, 1.1.2.1 pt1.h, NONE, 1.1.2.1 runt1asm.c, NONE,
1.1.2.1 t1asm.c, NONE, 1.1.2.1 ttf.c, NONE, 1.1.2.1 ttf.h,
NONE, 1.1.2.1 ttf2pt1.1, NONE, 1.1.2.1 ttf2pt1.c, NONE,
1.1.2.1 ttf2pt1_convert.1, NONE, 1.1.2.1 ttf2pt1_x2gs.1, NONE,
1.1.2.1 version.h, NONE, 1.1.2.1 winbuild.bat, NONE,
1.1.2.1 windows.h, NONE, 1.1.2.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the xorg-commit-diffs
mailing list