aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/XprintUtil/xprintutil_printtofile.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/XprintUtil/xprintutil_printtofile.c')
-rw-r--r--nx-X11/lib/XprintUtil/xprintutil_printtofile.c498
1 files changed, 0 insertions, 498 deletions
diff --git a/nx-X11/lib/XprintUtil/xprintutil_printtofile.c b/nx-X11/lib/XprintUtil/xprintutil_printtofile.c
deleted file mode 100644
index 331e7ad5b..000000000
--- a/nx-X11/lib/XprintUtil/xprintutil_printtofile.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/******************************************************************************
- ******************************************************************************
- **
- ** (c) Copyright 2001-2004 Roland Mainz <roland.mainz@nrubsig.org>
- **
- ** Permission is hereby granted, free of charge, to any person obtaining a copy
- ** of this software and associated documentation files (the "Software"), to deal
- ** in the Software without restriction, including without limitation the rights
- ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- ** copies of the Software, and to permit persons to whom the Software is
- ** furnished to do so, subject to the following conditions:
- **
- ** 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
- ** COPYRIGHT HOLDERS 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 names of the copyright holders shall
- ** not be used in advertising or otherwise to promote the sale, use or other
- ** dealings in this Software without prior written authorization from said
- ** copyright holders.
- **
- ******************************************************************************
- *****************************************************************************/
-
-#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. */