XtEnum XmPrintToFile(Display *pdpy, char *file_name, XPFinishProc finish_proc, XPointer client_data) { FileCallbackRec *callback; int pid; XPContext pcontext ; String application_name, application_class, display_name; FILE *file; int filedes[2]; /* make sure we can open the file for writing */ if ((file = fopen(file_name, "w")) == NULL) { return False; } if ((pipe(filedes)) == -1) { return False; } /* its important to flush before we fork, to make sure that the XpStartJob gets through first in the parent */ XFlush(pdpy); XtGetApplicationNameAndClass(pdpy, &application_name, &application_class); display_name = XDisplayString(pdpy) ; pcontext = XpGetContext(pdpy) ; pid = fork(); if (pid == 0) { ChildPrintToFile(display_name, pcontext, file, file_name, filedes[1], application_name, application_class); } else if (pid < 0) { return False; } /* we are in the parent */ fclose(file); close(filedes[1]); /* allocate the space for a callback */ callback = (FileCallbackRec *) XtMalloc(sizeof(FileCallbackRec)); callback->display = pdpy; callback->pipe = filedes[0]; callback->finish_proc = finish_proc; callback->client_data = client_data; /* notification that the child has completed */ callback->input_id = XtAppAddInput(XtDisplayToApplicationContext(pdpy), callback->pipe, (XtPointer)XtInputReadMask, FilePipeCB, callback); return True; }
/* ARGSUSED */ static void Destroy( Widget w ) { XmPrintShellWidget print_shell = (XmPrintShellWidget) w ; /* need to remove the pixmap from this shell: no sharing between diff shell and the same shell pointer id can come up next time */ _XmCleanPixmapCache (XtScreen(w), w); if (!print_shell->print.xp_connected) return ; /*** remove entry in the widget/XPContext table, used in the event dispatch mechanism */ DeleteFromTable(XpGetContext(XtDisplay(w)), w); _XmProcessLock(); /* unmark the screen of this print shell in this context */ XDeleteContext(XtDisplay(w), (XID)XtScreen(w), _XmPrintScreenToShellContext); /* also maintain a counter of all shells alive */ _XmPrintShellCounter -- ; _XmProcessUnlock(); }
static void SelectXpEvents ( Widget widget, int *event_types, XtPointer *select_data, int count, XtPointer client_data) { XpSelectInput(XtDisplay(widget), XpGetContext(XtDisplay(widget)), XPPrintMask|XPAttributeMask); }
static void FilePipeCB(XtPointer client_data, int *source, XtInputId *id) { FileCallbackRec *cb = (FileCallbackRec *) client_data; XPGetDocStatus status; /* read the status from the child */ (void) read(cb->pipe, &status, sizeof(XPGetDocStatus)); XtRemoveInput(cb->input_id); close(cb->pipe); if (cb->finish_proc) { (*cb->finish_proc)(cb->display, XpGetContext(cb->display), status, cb->client_data); } XtFree((char*)cb); }
void XpCancelJob ( Display *dpy, Bool discard ) { xPrintEndJobReq *req; XExtDisplayInfo *info = (XExtDisplayInfo *) xp_find_display (dpy); _XpDiscardJobRec disrec; XEvent event; if (XpCheckExtInit(dpy, XP_INITIAL_RELEASE) == -1) return; /* NoSuchExtension */ LockDisplay (dpy); GetReq(PrintEndJob,req); req->reqType = info->codes->major_opcode; req->printReqType = X_PrintEndJob; req->cancel = True; UnlockDisplay (dpy); SyncHandle (); if (discard) { /* * get context and effectively do a sync of events. */ disrec.event_base_return = info->codes->first_event; disrec.context = XpGetContext(dpy); /* * discard job, and also doc and page XPPrintNotify events. */ while (XCheckIfEvent(dpy, &event, _XpDiscardJob, (XPointer) &disrec)) { /*EMPTY*/ } } }
void XpStartJob ( Display *dpy, XPSaveData save_data ) { xPrintStartJobReq *req; XExtDisplayInfo *info = (XExtDisplayInfo *) xp_find_display (dpy); XPContext context; /**************************************************************** * * PRIOR TO XPSTARTJOB, set the job attribute "job-owner" * which will be used by the X-Server when it spools the * output. When XpStartJob completes, the job attribute * pool is frozen, disallowing "job-owner" to be modified. */ { char *joa; /* job owner attribute */ char *PwName; #ifndef WIN32 #ifdef X_NEEDS_PWPARAMS _Xgetpwparams pwparams; #endif struct passwd *pw; pw = _XGetpwuid(getuid(),pwparams); if (pw && (PwName = pw->pw_name)) { #else if ((PwName = getenv("USERNAME"))) { #endif joa = (char *) Xmalloc( strlen( PwName ) + 20 ); sprintf( joa, "*job-owner: %s", PwName ); context = XpGetContext( dpy ); XpSetAttributes( dpy, context, XPJobAttr, joa, XPAttrMerge ); Xfree( joa ); } } if (XpCheckExtInit(dpy, XP_INITIAL_RELEASE) == -1) return; /* NoSuchExtension */ LockDisplay (dpy); GetReq(PrintStartJob,req); req->reqType = info->codes->major_opcode; req->printReqType = X_PrintStartJob; req->saveData = (CARD8) save_data; UnlockDisplay (dpy); SyncHandle (); } void XpEndJob ( Display *dpy ) { xPrintEndJobReq *req; XExtDisplayInfo *info = (XExtDisplayInfo *) xp_find_display (dpy); if (XpCheckExtInit(dpy, XP_INITIAL_RELEASE) == -1) return; /* NoSuchExtension */ LockDisplay (dpy); GetReq(PrintEndJob,req); req->reqType = info->codes->major_opcode; req->printReqType = X_PrintEndJob; req->cancel = False; UnlockDisplay (dpy); SyncHandle (); }
XtEnum XmPrintPopupPDM(Widget print_shell, Widget transient_for_video_shell) { Atom pdm_selection; Atom type; unsigned char * value; int length; int format; Atom PDM_START ; Display * display_used ; PDMSelectData * pdm_select_data ; Widget widget_for_selection ; XtAppContext app; unsigned long old_timeout; /* get parameter for PDM_START from libXp ask conversion using XtSetSelectionParameters, and then call XtGetSelectionValue, which registers a XtSelectionCallbackProc that will wait for failure (no pdm owner, or timeout) or success. Phase 2 of the pdm (clientmessage) will be handled by a event handler set up from the selection callback on success */ if (!XpGetPdmStartParams (XtDisplay(print_shell), XtWindow(print_shell), XpGetContext(XtDisplay(print_shell)), XtDisplay(transient_for_video_shell), XtWindow(transient_for_video_shell), &display_used, &pdm_selection, &type, &format, &value, &length)) return XmPDM_NOTIFY_FAIL; /* only support XPDMDISPLAY = "print" or "video" */ if (display_used == XtDisplay(print_shell)) widget_for_selection = print_shell ; else if (display_used == XtDisplay(transient_for_video_shell)) widget_for_selection = transient_for_video_shell ; else return XmPDM_NOTIFY_FAIL ; XtSetSelectionParameters(widget_for_selection, pdm_selection, type, (XtPointer)value, length, format); XFree(value); pdm_select_data = (PDMSelectData *) XtMalloc(sizeof(PDMSelectData)); pdm_select_data->pdm_selection = pdm_selection ; pdm_select_data->transient_for_video_shell = transient_for_video_shell ; pdm_select_data->print_shell = (XmPrintShellWidget) print_shell ; /* need this one in all cases */ PDM_START = XInternAtom(XtDisplay(widget_for_selection), XmIPDM_START, False); app = XtWidgetToApplicationContext(widget_for_selection); /* twenty minutes */ #define REALLY_LONG_TIMEOUT (2 * 60 * 1000) _XmAppLock(app); old_timeout = XtAppGetSelectionTimeout(app); XtAppSetSelectionTimeout(app, REALLY_LONG_TIMEOUT); XtGetSelectionValue(widget_for_selection, pdm_selection, PDM_START, PDMSelectionProc, (XtPointer)pdm_select_data, XtLastTimestampProcessed( XtDisplay(widget_for_selection))); XtAppSetSelectionTimeout(app, old_timeout); _XmAppUnlock(app); /* put up a InputOnly window on top of the dialog, so that the end-user cannot muck around with the print setup dialog hile the PDM is trying to come up. This is removed in PDMSelectionProc */ pdm_select_data->transient_for_input_only_window = XCreateWindow(XtDisplay(transient_for_video_shell), XtWindow(transient_for_video_shell), 0, 0, XtWidth(transient_for_video_shell), XtHeight(transient_for_video_shell), 0, CopyFromParent, InputOnly, CopyFromParent, 0, NULL); XMapRaised(XtDisplay(transient_for_video_shell), pdm_select_data->transient_for_input_only_window); return XmPDM_NOTIFY_SUCCESS ; }
/************************************************************************ * * Initialize * ************************************************************************/ static void Initialize( Widget req_widget, Widget new_widget, ArgList args, Cardinal *num_args ) { int event_base_return, error_base_return ; XmPrintShellWidget print_shell = (XmPrintShellWidget) new_widget ; XPContext pcontext ; Screen * pscreen ; _XmProcessLock(); /* mark the screen of this print shell in this context */ XSaveContext(XtDisplay(new_widget), (XID)XtScreen(new_widget), _XmPrintScreenToShellContext, (XPointer) new_widget); /* also maintain a counter of all shell */ _XmPrintShellCounter ++ ; _XmProcessUnlock(); print_shell->print.xp_connected = False ; print_shell->print.print_resolution = 100 ; /*** first check if the Print extension is present at all */ if (!XpQueryExtension (XtDisplay(new_widget), &event_base_return, &error_base_return)) { return ; } /* need to check that the print context is set for the screen of this print shell (i.e. it's a print screen, not just a screen on a display that support printing and for which a context was establish on a different screen - which can be common in preview case */ pcontext = XpGetContext(XtDisplay(new_widget)); if (!pcontext || XpGetScreenOfContext(XtDisplay(new_widget),pcontext) != XtScreen(new_widget)) { return ; } print_shell->print.xp_connected = True ; /*** add an element to a widget/XPContext table, used in the event dispatch mechanism */ AddToTable(pcontext, new_widget); /*** add extension event Handler for Start/End Job/Page Notify */ XtInsertEventTypeHandler(new_widget, event_base_return + XPPrintNotify, (XtPointer)XPPrintMask, PrintNotifyHandler, NULL, XtListTail); /*** also add extension event Handler for tracking attributes change */ XtInsertEventTypeHandler(new_widget, event_base_return + XPAttributeNotify, (XtPointer)XPAttributeMask, AttributesNotifyHandler, NULL, XtListTail); /* always register the extension selector, and the event dispatcher, it will override itself accordingly and works ok for different display connection */ XtRegisterExtensionSelector(XtDisplay(new_widget), event_base_return + XPPrintNotify, event_base_return + XPAttributeNotify, SelectXpEvents, NULL); (void) XtSetEventDispatcher(XtDisplay(new_widget), event_base_return + XPPrintNotify, PrintDispatchEvent); (void) XtSetEventDispatcher(XtDisplay(new_widget), event_base_return + XPAttributeNotify, PrintDispatchEvent); /* go and get resolution and initial sizes */ ResourcesUpdate(new_widget, pcontext, &(new_widget->core.width), &(new_widget->core.height)); }