diff options
Diffstat (limited to 'xpsimplehelloworld/xpsimplehelloworld.c')
-rw-r--r-- | xpsimplehelloworld/xpsimplehelloworld.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/xpsimplehelloworld/xpsimplehelloworld.c b/xpsimplehelloworld/xpsimplehelloworld.c new file mode 100644 index 0000000..064894c --- /dev/null +++ b/xpsimplehelloworld/xpsimplehelloworld.c @@ -0,0 +1,374 @@ +/* + * $Xorg: xphelloworld.c,v 1.2 2002/05/10 06:54:^1 gisburn Exp $ + * + * xphelloworld - Xprint version of hello world + * + * +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 <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/XprintUtil/xprintutil.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +/* Turn a NULL pointer string into an empty string */ +#define NULLSTR(x) (((x)!=NULL)?(x):("")) + +#define Log(x) { if(verbose) printf x; } + +static const char *ProgramName; /* program name (from argv[0]) */ +static Bool verbose = False; /* verbose output what the program is doing */ + +static +void usage(void) +{ + fprintf (stderr, "usage: %s [options]\n", ProgramName); + fprintf (stderr, "-printer printernname\tprinter to use\n"); + fprintf (stderr, "-printfile file\tprint to file instead of printer\n"); + fprintf (stderr, "-embedpsl2data string\tPostScript level 2 fragment to embed\n" + "\t\t(use 'xppsembeddemo1' to embed demo data)\n"); + fprintf (stderr, "-v\tverbose output\n"); + fprintf (stderr, "\n"); + exit(EXIT_FAILURE); +} + +/* strstr(), case-insensitive */ +static +char *str_case_str(const char *s, const char *find) +{ + size_t len; + char c, + sc; + + if ((c = tolower(*find++)) != '\0') + { + len = strlen(find); + do + { + do + { + if ((sc = tolower(*s++)) == '\0') + return NULL; + } while (sc != c); + } while (strncasecmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} + +static +int do_hello_world(const char *printername, const char *printerfile, const char *psembeddata ) +{ + Display *pdpy; /* X connection */ + XPContext pcontext; /* Xprint context */ + void *printtofile_handle; /* "context" when printing to file */ + int xp_event_base, /* XpExtension even base */ + xp_error_base; /* XpExtension error base */ + long dpi; + Screen *pscreen; + int pscreennumber; + Window pwin; + XGCValues gcvalues; + XEvent ev; + GC pgc; + unsigned short dummy; + XRectangle winrect; + char fontname[256]; /* BUG: is this really big enougth ? */ + XFontStruct *font; + + if( XpuGetPrinter(printername, &pdpy, &pcontext) != 1 ) + { + fprintf(stderr, "Cannot open printer '%s'\n", printername); + return(EXIT_FAILURE); + } + + if( XpQueryExtension(pdpy, &xp_event_base, &xp_error_base) == False ) + { + fprintf(stderr, "XpQueryExtension() failed.\n"); + XpuClosePrinterDisplay(pdpy, pcontext); + return(EXIT_FAILURE); + } + + /* Listen to XP(Start|End)(Job|Doc|Page)Notify events). + * This is mantatory as Xp(Start|End)(Job|Doc|Page) functions are _not_ + * syncronous !! + * Not waiting for such events may cause that subsequent data may be + * destroyed/corrupted!! + */ + XpSelectInput(pdpy, pcontext, XPPrintMask); + + /* Set job title */ + XpuSetJobTitle(pdpy, pcontext, "Hello world for Xprint"); + + /* Set print context + * Note that this modifies the available fonts, including builtin printer prints. + * All XListFonts()/XLoadFont() stuff should be done _after_ setting the print + * context to obtain the proper fonts. + */ + XpSetContext(pdpy, pcontext); + + /* Get default printer reolution */ + if( XpuGetResolution(pdpy, pcontext, &dpi) != 1 ) + { + fprintf(stderr, "No default resolution for printer '%s'.\n", printername); + XpuClosePrinterDisplay(pdpy, pcontext); + return(EXIT_FAILURE); + } + + if( printerfile ) + { + Log(("starting job (to file '%s').\n", printerfile)); + printtofile_handle = XpuStartJobToFile(pdpy, pcontext, printerfile); + if( !printtofile_handle ) + { + fprintf(stderr, "%s: Error: %s while trying to print to file.\n", + ProgramName, strerror(errno)); + XpuClosePrinterDisplay(pdpy, pcontext); + return(EXIT_FAILURE); + } + + XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartJobNotify); + } + else + { + Log(("starting job.\n")); + XpuStartJobToSpooler(pdpy); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartJobNotify); + } + +#ifdef MULTIPLE_DOCUMENTS_IN_ONE_JOB + /* Start document (one job can contain any number of "documents") + * XpStartDoc() isn't mandatory if job only contains one document - first + * XpStartPage() will generate a "synthetic" XpStartDoc() if one had not + * already been done. + */ + XpStartDoc(pdpy, XPDocNormal); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartDocNotify); +#endif /* MULTIPLE_DOCUMENTS_IN_ONE_JOB */ + + pscreen = XpGetScreenOfContext(pdpy, pcontext); + pscreennumber = XScreenNumberOfScreen(pscreen); + + /* Obtain some info about page geometry */ + XpGetPageDimensions(pdpy, pcontext, &dummy, &dummy, &winrect); + + pwin = XCreateSimpleWindow(pdpy, XRootWindowOfScreen(pscreen), + winrect.x, winrect.y, winrect.width, winrect.height, + 10, + XBlackPixel(pdpy, pscreennumber), + XWhitePixel(pdpy, pscreennumber)); + + gcvalues.background = XWhitePixel(pdpy, pscreennumber); + gcvalues.foreground = XBlackPixel(pdpy, pscreennumber); + + pgc = XCreateGC(pdpy, pwin, GCBackground|GCForeground, &gcvalues); + + Log(("start page.\n")); + XpStartPage(pdpy, pwin); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartPageNotify); + + /* Mapping the window inside XpStartPage()/XpEndPage() + * Set XCreateWindow/border_width to 0 or move XMapWindow in front of + * XpStartPage() to get rid of the surrounding black border lines. + * (This is usually done before XpStartPage() in real applications) + */ + XMapWindow(pdpy, pwin); + + /* usual rendering stuff..... */ + + sprintf(fontname, "-*-*-*-*-*-*-*-180-%ld-%ld-*-*-iso8859-1", dpi, dpi); + font = XLoadQueryFont(pdpy, fontname); + XSetFont(pdpy, pgc, font->fid); + XDrawString(pdpy, pwin, pgc, 100, 100, "hello world from X11 print system", 33); + +#define DO_EMBED_TEST 1 + +#ifdef DO_EMBED_TEST + if( psembeddata ) + { + char *embedded_formats_supported; + + embedded_formats_supported = XpGetOneAttribute(pdpy, pcontext, XPPrinterAttr, "xp-embedded-formats-supported"); + + Log(("psembed: xp-embedded-formats-supported='%s'\n", NULLSTR(embedded_formats_supported))); + + /* MAX(XExtendedMaxRequestSize(pdpy), XMaxRequestSize(pdpy)) defines the + * maximum length of emebdded PostScript data which can be send in one + * step using XpPutDocumentData() */ + Log(("psembed: XExtendedMaxRequestSize=%ld\n", (long)XExtendedMaxRequestSize(pdpy))); + Log(("psembed: XMaxRequestSize=%ld\n", (long)XMaxRequestSize(pdpy))); + + /* Should we embed the demo ? */ + if( !strcmp(psembeddata, "xppsembeddemo1") ) + { + Log(("psembed: Using PS embedding demo 1\n")); + psembeddata = "newpath\n270 360 moveto\n 0 72 rlineto\n" + "72 0 rlineto\n 0 -72 rlineto\n closepath\n fill\n"; + } + else + { + Log(("psembed: Using user PS embedding data = '%s'\n", psembeddata)); + } + + /* Check whether "PostScript Level 2" is supported as embedding format + * (The content of the "xp-embedded-formats-supported" attribute needs + * to be searched in a case-insensitive way since the model-configs + * may use the same word with multiple variants of case + * (e.g. "PostScript" vs. "Postscript" or "PCL" vs. "Pcl" etc.") + * To avoid problems we simply use |str_case_str()| (case-insensitive + * strstr()) instead of |strstr()| here...) + */ + if( embedded_formats_supported && + (str_case_str(embedded_formats_supported, "PostScript 2") != NULL) ) + { + /* Note that the emebdded PostScript code uses the same resolution and + * coordinate space as currently be used by the DDX (if you don not + * want that simply reset it yourself :) */ + char *test = (char *)psembeddata; + int test_len = strlen(test); + char *type = "PostScript 2"; /* Format of embedded data + * (older PS DDX may be picky, fixed via + * http://xprint.mozdev.org/bugs/show_bug.cgi?id=4023) + */ + char *option = ""; /* PostScript DDX does not support any options yet + * (in general |BadValue| will be returned for not + * supported options/option values) */ + XpPutDocumentData(pdpy, pwin, test, test_len, type, option); + } + else + { + Log(("psembed: error: cannot embed data, 'PostScript 2' not supported as embedded data format for this printer\n")); + } + } +#endif /* DO_EMBED_TEST */ + + XpEndPage(pdpy); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndPageNotify); + Log(("end page.\n")); + +#ifdef DO_SOME_MORE_RENDERING + XpStartPage(pdpy); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartPageNotify); + + /* some more rendering..... */ + + XpEndPage(pdpy); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndPageNotify); +#endif /* DO_SOME_MORE_RENDERING */ + +#ifdef MULTIPLE_DOCUMENTS_IN_ONE_JOB + /* End document. Do _not_ use it if you did not explicitly used + * XpStartDoc() above (e.g. if XpStartDoc() was triggered by first + * XpStartPage() - see comment about XpStartDoc() above... + */ + XpEndDoc(pdpy); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndDocNotify); +#endif /* MULTIPLE_DOCUMENTS_IN_ONE_JOB */ + + /* End the print job - the final results are sent by the X print + * server to the spooler sub system. + */ + XpEndJob(pdpy); + XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndJobNotify); + Log(("end job.\n")); + + if( printerfile ) + { + if( XpuWaitForPrintFileChild(printtofile_handle) != XPGetDocFinished ) + { + fprintf(stderr, "%s: Error while printing to file.\n", ProgramName); + XpuClosePrinterDisplay(pdpy, pcontext); + return(EXIT_FAILURE); + } + } + + XpuClosePrinterDisplay(pdpy, pcontext); + return(EXIT_SUCCESS); +} + +int main (int argc, char *argv[]) +{ + const char *printername = NULL; /* printer to query */ + const char *toFile = NULL; /* output file (instead of printer) */ + const char *embedpsl2data = NULL; /* PS Level 2 code fragment for embedding in output */ + XPPrinterList plist; /* list of printers */ + int plist_count; /* number of entries in |plist|-array */ + int i; + int retval; + + ProgramName = argv[0]; + + for (i = 1; i < argc; i++) + { + char *arg = argv[i]; + int len = strlen(arg); + + if (!strncmp("-printer", arg, len)) + { + if (++i >= argc) + usage(); + printername = argv[i]; + } + else if (!strncmp("-printfile", arg, len)) + { + if (++i >= argc) + usage(); + toFile = argv[i]; + } + else if (!strncmp("-embedpsl2data", arg, len)) + { + if (++i >= argc) + usage(); + embedpsl2data = argv[i]; + } + else if (!strncmp("-v", arg, len)) + { + verbose = True; + } + else + { + usage(); + } + } + + plist = XpuGetPrinterList(printername, &plist_count); + + if (!plist) { + fprintf(stderr, "%s: no printers found for printer spec \"%s\".\n", + ProgramName, NULLSTR(printername)); + exit(EXIT_FAILURE); + } + + Log(("Using printer '%s'\n", plist[0].name)); + + retval = do_hello_world(plist[0].name, toFile, embedpsl2data); + + XpuFreePrinterList(plist); + + return(retval); +} + + |