#define NULLSTR(x) (((x)!=NULL)?(x):(""))
#define Error(x) { printf x ; exit(EXIT_FAILURE); }
#define Assertion(expr, msg) { if (!(expr)) { Error msg } }
#define Log(x) { if(True) printf x; }
#ifdef XEDIT
#include "xedit.h"
#endif
#include "print.h"
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/AsciiText.h>
#include <stdio.h>
#include <stdlib.h>
static Widget
CreatePrintShell(Widget videoshell,
Screen *pscreen,
Visual *pvisual,
String printshell_name,
ArgList args,
Cardinal numargs)
{
String videoname,
videoclass;
Widget pappshell,
printshell;
Display *pdpy = XDisplayOfScreen(pscreen);
int dummyc = 0;
String dummys = "";
Cardinal shell_n;
Arg shell_args[5];
XtGetApplicationNameAndClass(XtDisplay(videoshell),
&videoname, &videoclass);
XtDisplayInitialize(XtWidgetToApplicationContext(videoshell), pdpy,
videoname, videoclass,
NULL, 0,
&dummyc, &dummys);
shell_n = 0;
XtSetArg(shell_args[shell_n], XtNscreen, pscreen); shell_n++;
if (pvisual) {
XtSetArg(shell_args[shell_n], XtNvisual, pvisual); shell_n++;
}
pappshell = XtAppCreateShell(videoname, videoclass,
applicationShellWidgetClass,
pdpy,
shell_args, shell_n);
printshell = XtCreatePopupShell(printshell_name,
xawPrintShellWidgetClass,
pappshell, args, numargs);
XtSetMappedWhenManaged(printshell, False);
return printshell;
}
typedef struct
{
const char *programname;
Widget toplevel;
Bool isPrinting;
Widget printshell;
struct
{
Widget form;
Widget pageheaderlabel;
Widget text;
} content;
int numpages;
Display *pdpy;
Screen *pscreen;
XPContext pcontext;
XtCallbackProc pdpyDestroyCallback;
void *printtofile_handle;
const char *jobtitle;
} AppPrintData;
static AppPrintData apdx;
static AppPrintData *apd = &apdx;
static
long CountPages(Widget textWidget)
{
long numpages = 0;
XawTextPosition prevpagepos = -1,
currpos = 0;
XtCallActionProc(textWidget, "beginning-of-file", NULL, NULL, 0);
do
{
prevpagepos = XawTextTopPosition(textWidget);
XtCallActionProc(textWidget, "next-page", NULL, NULL, 0);
currpos = XawTextTopPosition(textWidget);
numpages++;
} while(prevpagepos != currpos);
XtCallActionProc(textWidget, "beginning-of-file", NULL, NULL, 0);
Log(("CountPages() found %ld pages.\n", numpages))
return numpages;
}
static void
PageSetupCB(Widget widget, XtPointer client_data, XtPointer call_data)
{
Widget pshell = widget;
XawPrintShellCallbackStruct *psp = (XawPrintShellCallbackStruct *)call_data;
AppPrintData *p = (AppPrintData *)client_data;
Log(("--> PageSetupCB\n"));
if (!psp->last_page_in_job) {
int currpage;
char buffer[256];
XtVaGetValues(pshell, XawNcurrPageNumInJob, &currpage, NULL);
sprintf(buffer, "Title: %s / Page: %d/%d", p->jobtitle, currpage, p->numpages);
XtVaSetValues(apd->content.pageheaderlabel, XtNlabel, buffer, NULL);
if (currpage > 1) {
Log(("pagedown %d\n", currpage));
XtCallActionProc(p->content.text, "next-page", NULL, NULL, 0);
}
else
{
Log(("first page\n"));
}
if (currpage >= p->numpages) {
psp->last_page_in_job = True;
}
}
}
static
void FinishPrinting(AppPrintData *p)
{
char *scr;
if (p->printtofile_handle) {
if (XpuWaitForPrintFileChild(p->printtofile_handle) != XPGetDocFinished) {
PrintMsg(("Error while printing to file.\n"));
}
p->printtofile_handle = NULL;
}
scr = XpGetOneAttribute(p->pdpy, p->pcontext, XPJobAttr, "xp-spooler-command-results");
if( scr )
{
if( strlen(scr) > 0 )
{
const char *msg = XpuCompoundTextToXmb(p->pdpy, scr);
if( msg )
{
PrintMsg(("Spooler command returned:\n%s", msg));
XpuFreeXmbString(msg);
}
else
{
PrintMsg(("Spooler command returned (unconverted):\n%s", scr));
}
}
XFree((void *)scr);
}
if (p->printshell) {
XtDestroyWidget(p->printshell);
p->printshell = NULL;
}
(*apd->pdpyDestroyCallback)(NULL, NULL, NULL);
if (p->pcontext != None) {
XpDestroyContext(p->pdpy, p->pcontext);
}
XtCloseDisplay(p->pdpy);
p->toplevel = NULL;
p->isPrinting = False;
p->pdpy = NULL;
p->pscreen = NULL;
p->pcontext = None;
}
static
void PrintEndJobCB(Widget pshell, XtPointer client_data, XtPointer call_data)
{
AppPrintData *p = (AppPrintData *)client_data;
Log(("--> PrintEndJobCB\n"));
FinishPrinting(p);
}
static
XFontSet GetPrintTextFontSet(const char *appname, Display *pdpy, long dpi_x, long dpi_y)
{
XFontSet fontset;
char fontname[1024];
char **missing_charset_list_return;
int missing_charset_count_return;
char *def_string_return;
int i;
sprintf(fontname,
"-dt-interface user-medium-r-normal-s*-*-120-%ld-%ld-*-*,"
"-adobe-courier-medium-r-normal--*-120-%ld-%ld-*-*,"
"-watanabe-mincho-medium-r-normal--*-120-%ld-%ld-*-*,"
"-wadalab-gothic-medium-r-normal--*-120-%ld-%ld-*-*,"
"-*-*-*-*-*--*-120-%ld-%ld-*-*",
dpi_x, dpi_y,
dpi_x, dpi_y,
dpi_x, dpi_y,
dpi_x, dpi_y,
dpi_x, dpi_y);
fontset = XCreateFontSet(pdpy, fontname,
&missing_charset_list_return,
&missing_charset_count_return,
&def_string_return);
for( i=0 ; i < missing_charset_count_return ; i++ ) {
fprintf(stderr, "%s: warning: font for charset %s is lacking.\n",
appname, missing_charset_list_return[i]);
}
if (!fontset)
Error(("GetPrintTextFontSet: XCreateFontSet() failure.\n"));
return fontset;
}
void DoPrintTextSource(const char *programname,
Widget textsource, Widget toplevel,
Display *pdpy, XPContext pcontext,
XpuColorspaceRec *colorspace,
XtCallbackProc pdpyDestroyCB,
const char *jobtitle, const char *toFile)
{
long dpi_x = 0L,
dpi_y = 0L;
int n;
Arg args[20];
XFontSet textfontset = NULL;
XFontSetExtents *font_extents;
apd->programname = programname;
apd->pdpyDestroyCallback = pdpyDestroyCB;
if (apd->isPrinting) {
PrintMsg(("Already busy with printing.\n"));
return;
}
XpuSetJobTitle(pdpy, pcontext, jobtitle);
XpSetContext(pdpy, pcontext);
if (XpuGetResolution(pdpy, pcontext, &dpi_x, &dpi_y) != 1) {
PrintMsg(("No default resolution for printer.\n"));
XpuClosePrinterDisplay(pdpy, pcontext);
return;
}
apd->toplevel = toplevel;
apd->pdpy = pdpy;
apd->pcontext = pcontext;
apd->pscreen = XpGetScreenOfContext(pdpy, pcontext);
apd->jobtitle = jobtitle;
n = 0;
XtSetArg(args[n], XtNgeometry, "+0+0"); n++;
XtSetArg(args[n], XawNlayoutMode, XawPrintLAYOUTMODE_DRAWABLEAREA); n++;
if (colorspace) {
printf("Setting visual to id=0x%lx.\n", colorspace->visualinfo.visualid);
}
apd->printshell = CreatePrintShell(toplevel, apd->pscreen,
(colorspace?(colorspace->visualinfo.visual):(NULL)),
"printshell", args, n);
n = 0;
XtSetArg(args[n], XtNresizable, True); n++;
XtSetArg(args[n], XtNright, XtChainRight); n++;
apd->content.form = XtCreateManagedWidget("form", formWidgetClass, apd->printshell, args, n);
textfontset = GetPrintTextFontSet(apd->programname, pdpy, dpi_x, dpi_y);
n = 0;
XtSetArg(args[n], XtNinternational, True); n++;
XtSetArg(args[n], XtNfromHoriz, NULL); n++;
XtSetArg(args[n], XtNfromVert, NULL); n++;
XtSetArg(args[n], XtNtop, XtChainTop); n++;
XtSetArg(args[n], XtNright, XtChainRight); n++;
XtSetArg(args[n], XtNresizable, True); n++;
XtSetArg(args[n], XtNfontSet, textfontset); n++;
XtSetArg(args[n], XtNlabel, "Page: n/n"); n++;
XtSetArg(args[n], XtNjustify, XtJustifyRight); n++;
apd->content.pageheaderlabel = XtCreateManagedWidget("pageinfo", labelWidgetClass, apd->content.form, args, n);
font_extents = XExtentsOfFontSet(textfontset);
n = 0;
XtSetArg(args[n], XtNinternational, True); n++;
XtSetArg(args[n], XtNtextSource, textsource); n++;
XtSetArg(args[n], XtNscrollHorizontal, XawtextScrollNever); n++;
XtSetArg(args[n], XtNscrollVertical, XawtextScrollNever); n++;
#define WORKAROUND_FOR_SOMETHING_IS_WRONG 1
#ifdef WORKAROUND_FOR_SOMETHING_IS_WRONG
XtSetArg(args[n], XtNtop, XtChainTop); n++;
XtSetArg(args[n], XtNright, XtChainRight); n++;
XtSetArg(args[n], XtNvertDistance, (font_extents->max_logical_extent.height+2)*2); n++;
#else
XtSetArg(args[n], XtNfromHoriz, NULL); n++;
XtSetArg(args[n], XtNfromVert, apd->content.pageheaderlabel); n++;
#endif
XtSetArg(args[n], XtNfontSet, textfontset); n++;
apd->content.text = XtCreateManagedWidget("text", asciiTextWidgetClass, apd->content.form, args, n);
XawTextDisplayCaret(apd->content.text, False);
XtAddCallback(apd->printshell, XawNpageSetupCallback, PageSetupCB, (XtPointer)apd);
XtAddCallback(apd->printshell, XawNendJobCallback, PrintEndJobCB, (XtPointer)apd);
XtRealizeWidget(apd->printshell);
apd->numpages = CountPages(apd->content.text);
if (XpGetScreenOfContext(XtDisplay(apd->printshell), apd->pcontext) != XtScreen(apd->printshell))
Error(("Widget's screen != print screen. BAD.\n"));
apd->isPrinting = True;
if (toFile) {
PrintMsg(("Printing to file '%s'...\n", toFile));
apd->printtofile_handle = XpuStartJobToFile(pdpy, pcontext, toFile);
if (!apd->printtofile_handle) {
perror("XpuStartJobToFile failure");
PrintMsg(("Printing failed: XpuStartJobToFile\n"));
apd->isPrinting = False;
return;
}
}
else
{
PrintMsg(("Printing to printer...\n"));
XpuStartJobToSpooler(pdpy);
}
}